Documentation
¶
Overview ¶
Package config provides configuration loading and validation.
Package config provides data models for the controller configuration.
These models represent the structure of the configuration YAML loaded from the Kubernetes ConfigMap and credentials from the Secret.
Index ¶
- Constants
- func ParseSecretData(dataRaw map[string]interface{}) (map[string][]byte, error)
- func SetDefaults(cfg *Config)
- func ValidateCredentials(creds *Credentials) error
- func ValidateExtraContext(ctx map[string]interface{}) error
- func ValidateStructure(cfg *Config) error
- type CRTListFile
- type Config
- type ControllerConfig
- type Credentials
- type DataplaneConfig
- type GeneralFile
- type HAProxyConfig
- type HTTPResourceFixture
- type LeaderElectionConfig
- type LoggingConfig
- type MapFile
- type PodSelector
- type PostProcessorConfig
- type SSLCertificate
- type TemplateSnippet
- type TemplatingSettings
- type ValidationAssertion
- type ValidationTest
- type WatchedResource
Constants ¶
const ( // DefaultLevel is the default log level. // Empty string means use LOG_LEVEL env var or default to INFO. DefaultLevel = "" // DefaultDataplanePort is the default Dataplane API port for production HAProxy pods. DefaultDataplanePort = 5555 // DefaultEnableValidationWebhook is the default webhook setting for resources. DefaultEnableValidationWebhook = false // DefaultMinDeploymentInterval is the default minimum time between consecutive deployments. DefaultMinDeploymentInterval = 2 * time.Second // DefaultDriftPreventionInterval is the default interval for periodic drift prevention deployments. DefaultDriftPreventionInterval = 60 * time.Second // DefaultDataplaneMapsDir is the default directory for HAProxy map files. DefaultDataplaneMapsDir = "/etc/haproxy/maps" // DefaultDataplaneSSLCertsDir is the default directory for SSL certificates. // This matches the values.yaml default and HAProxy container directory structure. DefaultDataplaneSSLCertsDir = "/etc/haproxy/certs" // DefaultDataplaneGeneralStorageDir is the default directory for general files. DefaultDataplaneGeneralStorageDir = "/etc/haproxy/general" // DefaultDataplaneConfigFile is the default path to the main HAProxy config file. DefaultDataplaneConfigFile = "/etc/haproxy/haproxy.cfg" // DefaultLeaderElectionEnabled is the default leader election enabled setting. DefaultLeaderElectionEnabled = true // DefaultLeaderElectionLeaseName is the default name for the leader election lease. DefaultLeaderElectionLeaseName = "haptic-leader" // DefaultLeaderElectionLeaseDuration is the default lease duration. DefaultLeaderElectionLeaseDuration = 15 * time.Second // DefaultLeaderElectionRenewDeadline is the default renew deadline. DefaultLeaderElectionRenewDeadline = 10 * time.Second // DefaultLeaderElectionRetryPeriod is the default retry period. DefaultLeaderElectionRetryPeriod = 2 * time.Second )
Default values for configuration fields.
Variables ¶
This section is empty.
Functions ¶
func ParseSecretData ¶
ParseSecretData extracts and base64-decodes Secret data from an unstructured map.
Kubernetes Secrets store data as base64-encoded strings in the API. When accessed through unstructured.Unstructured, the values remain base64-encoded and must be decoded before use.
Parameters:
- dataRaw: The raw Secret data map from unstructured.NestedMap(resource.Object, "data")
Returns:
- map[string][]byte: Decoded secret data ready for use
- error: If any value is not a string or fails base64 decoding
func SetDefaults ¶
func SetDefaults(cfg *Config)
SetDefaults applies default values to unset configuration fields. This modifies the config in-place and should be called after parsing the configuration and before validation.
Port Handling Strategy:
- A value of 0 for production ports (healthz, metrics, dataplane) means "uninitialized" and will be replaced with the default value
- Debug ports may intentionally be 0 to indicate "disabled" (see cmd/controller/main.go)
- After defaults are applied, production ports MUST NOT be 0 (validation will catch this)
Most callers should use LoadConfig() instead. This function is primarily useful for testing default application independently from YAML parsing.
func ValidateCredentials ¶
func ValidateCredentials(creds *Credentials) error
ValidateCredentials ensures all required credential fields are present and non-empty.
func ValidateExtraContext ¶
ValidateExtraContext validates that ExtraContext contains only JSON-compatible types.
This validation catches type issues at config load time rather than at template render time. YAML unmarshaling can produce unexpected types (e.g., integers unmarshal as float64), and this validation ensures all values are representable in JSON.
Supported types:
- nil (null)
- bool
- float64 (all YAML numbers become float64)
- string
- []interface{} (arrays)
- map[string]interface{} (objects)
func ValidateStructure ¶
ValidateStructure performs basic structural validation on the configuration. Validates required fields, value ranges, and non-empty slices. Does NOT validate template syntax or JSONPath expressions.
Types ¶
type CRTListFile ¶
type CRTListFile struct {
// Template is the template content that generates the crt-list file.
Template string `yaml:"template"`
// PostProcessing defines optional post-processors to apply after rendering.
// Post-processors are applied in order to transform the rendered output.
PostProcessing []PostProcessorConfig `yaml:"post_processing,omitempty"`
}
CRTListFile is a crt-list file template.
CRT-list files contain entries that map SSL certificates to specific SNI patterns with per-certificate options. This enables advanced SSL certificate management with features like SNI routing, OCSP stapling, and per-certificate TLS settings.
type Config ¶
type Config struct {
// PodSelector identifies HAProxy pods to configure.
PodSelector PodSelector `yaml:"pod_selector"`
// Controller contains controller-level settings (ports, etc.).
Controller ControllerConfig `yaml:"controller"`
// Logging configures logging behavior.
Logging LoggingConfig `yaml:"logging"`
// Dataplane configures the Dataplane API for production HAProxy instances.
Dataplane DataplaneConfig `yaml:"dataplane"`
// TemplatingSettings configures template rendering behavior and custom variables.
TemplatingSettings TemplatingSettings `yaml:"templating_settings" json:"templatingSettings"`
// WatchedResourcesIgnoreFields specifies JSONPath expressions for fields
// to remove from all watched resources to reduce memory usage.
//
// Example: ["metadata.managedFields"]
WatchedResourcesIgnoreFields []string `yaml:"watched_resources_ignore_fields"`
// WatchedResources maps resource type names to their watch configuration.
//
// Example:
// ingresses:
// api_version: networking.k8s.io/v1
// kind: Ingress
// index_by: ["metadata.namespace", "metadata.name"]
WatchedResources map[string]WatchedResource `yaml:"watched_resources"`
// TemplateSnippets maps snippet names to reusable template fragments.
//
// Snippets can be included in other templates using {% include "name" %}.
TemplateSnippets map[string]TemplateSnippet `yaml:"template_snippets"`
// Maps maps map file names to their template definitions.
//
// These generate HAProxy map files for backend routing and other features.
Maps map[string]MapFile `yaml:"maps"`
// Files maps file names to their template definitions.
//
// These generate auxiliary files like custom error pages.
Files map[string]GeneralFile `yaml:"files"`
// SSLCertificates maps certificate names to their template definitions.
//
// These generate SSL certificate files for HAProxy.
SSLCertificates map[string]SSLCertificate `yaml:"ssl_certificates"`
// CRTLists maps crt-list file names to their template definitions.
//
// These generate crt-list files for SSL certificate lists with per-certificate options.
CRTLists map[string]CRTListFile `yaml:"crt_lists"`
// HAProxyConfig contains the main HAProxy configuration template.
HAProxyConfig HAProxyConfig `yaml:"haproxy_config"`
// ValidationTests contains embedded tests for validating template rendering.
// These tests are used both in CLI validation and webhook admission validation.
// The map key is the test name, which must be unique.
ValidationTests map[string]ValidationTest `yaml:"validation_tests"`
}
Config is the root configuration structure loaded from the ConfigMap.
func LoadConfig ¶
LoadConfig parses YAML configuration and applies default values. This is the recommended function for loading configuration.
It performs two operations atomically:
- Parses YAML into Config struct
- Applies default values to unset fields
Example:
cfg, err := config.LoadConfig(yamlString)
if err != nil {
return err
}
// cfg now has defaults applied and is ready for validation
type ControllerConfig ¶
type ControllerConfig struct {
// LeaderElection configures leader election for high availability.
LeaderElection LeaderElectionConfig `yaml:"leader_election"`
}
ControllerConfig contains controller-level configuration.
type Credentials ¶
type Credentials struct {
// DataplaneUsername is the username for production HAProxy instances.
DataplaneUsername string
// DataplanePassword is the password for production HAProxy instances.
DataplanePassword string
}
Credentials contains HAProxy Dataplane API credentials.
This is loaded from the Kubernetes Secret, not the ConfigMap.
func LoadCredentials ¶
func LoadCredentials(secretData map[string][]byte) (*Credentials, error)
LoadCredentials parses Secret data into a Credentials struct. This is a pure function that extracts credentials from Secret data. It does not load from Kubernetes or perform validation.
Expected Secret keys: dataplane_username, dataplane_password.
type DataplaneConfig ¶
type DataplaneConfig struct {
// Port is the Dataplane API port for production HAProxy pods.
// A value of 0 means "uninitialized" and will be replaced with the default.
// This is a production port and MUST NOT remain 0 after defaults are applied.
// Default: 5555
Port int `yaml:"port"`
// MinDeploymentInterval enforces minimum time between consecutive deployments.
// This prevents rapid-fire deployments from hammering HAProxy instances.
// Format: Go duration string (e.g., "2s", "500ms")
// Default: 2s
MinDeploymentInterval string `yaml:"min_deployment_interval"`
// DriftPreventionInterval triggers periodic deployments to prevent configuration drift.
// A deployment is automatically triggered if no deployment has occurred within this interval.
// This detects and corrects drift caused by external Dataplane API clients.
// Format: Go duration string (e.g., "60s", "5m")
// Default: 60s
DriftPreventionInterval string `yaml:"drift_prevention_interval"`
// MapsDir is the directory for HAProxy map files.
// Used for both validation and deployment.
// Default: /etc/haproxy/maps
MapsDir string `yaml:"maps_dir"`
// SSLCertsDir is the directory for SSL certificates.
// Used for both validation and deployment.
// Default: /etc/haproxy/ssl
SSLCertsDir string `yaml:"ssl_certs_dir"`
// GeneralStorageDir is the directory for general files (error pages, etc.).
// Used for both validation and deployment.
// Default: /etc/haproxy/general
GeneralStorageDir string `yaml:"general_storage_dir"`
// ConfigFile is the path to the main HAProxy configuration file.
// Used for validation.
// Default: /etc/haproxy/haproxy.cfg
ConfigFile string `yaml:"config_file"`
}
DataplaneConfig configures the Dataplane API for production HAProxy instances.
func (*DataplaneConfig) GetDriftPreventionInterval ¶
func (d *DataplaneConfig) GetDriftPreventionInterval() time.Duration
GetDriftPreventionInterval returns the configured drift prevention interval or the default if not specified or invalid.
func (*DataplaneConfig) GetMinDeploymentInterval ¶
func (d *DataplaneConfig) GetMinDeploymentInterval() time.Duration
GetMinDeploymentInterval returns the configured minimum deployment interval or the default if not specified or invalid.
type GeneralFile ¶
type GeneralFile struct {
// Template is the template content that generates the file.
Template string `yaml:"template"`
// PostProcessing defines optional post-processors to apply after rendering.
// Post-processors are applied in order to transform the rendered output.
PostProcessing []PostProcessorConfig `yaml:"post_processing,omitempty"`
}
GeneralFile is a general-purpose auxiliary file template.
type HAProxyConfig ¶
type HAProxyConfig struct {
// Template is the template content that generates haproxy.cfg.
Template string `yaml:"template"`
// PostProcessing defines optional post-processors to apply after rendering.
// Post-processors are applied in order to transform the rendered output.
// Common use case: indentation normalization with regex_replace.
//
// Example:
// post_processing:
// - type: regex_replace
// params:
// pattern: "^[ ]+"
// replace: " "
PostProcessing []PostProcessorConfig `yaml:"post_processing,omitempty"`
}
HAProxyConfig is the main HAProxy configuration template.
type HTTPResourceFixture ¶
type HTTPResourceFixture struct {
// URL is the HTTP URL that will be matched.
// When a template calls http.Fetch() with this URL, the fixture content is returned.
URL string `yaml:"url" json:"url"`
// Content is the response body to return when this URL is fetched.
Content string `yaml:"content" json:"content"`
}
HTTPResourceFixture defines mock HTTP content for validation tests.
This allows templates that use http.Fetch() to receive pre-defined content during validation tests without making actual HTTP requests.
type LeaderElectionConfig ¶
type LeaderElectionConfig struct {
// Enabled determines whether leader election is active.
// If false, the controller assumes it is the sole instance (single-replica mode).
// Default: true
Enabled bool `yaml:"enabled"`
// LeaseName is the name of the Lease resource used for coordination.
// Default: haptic-leader
LeaseName string `yaml:"lease_name"`
// LeaseDuration is the duration that non-leader candidates will wait
// to force acquire leadership (measured against time of last observed ack).
// Format: Go duration string (e.g., "60s", "1m")
// Default: 60s
// Minimum: 15s
LeaseDuration string `yaml:"lease_duration"`
// RenewDeadline is the duration that the acting leader will retry
// refreshing leadership before giving up.
// Format: Go duration string (e.g., "15s")
// Default: 15s
// Must be less than LeaseDuration
RenewDeadline string `yaml:"renew_deadline"`
// RetryPeriod is the duration the LeaderElector clients should wait
// between tries of actions.
// Format: Go duration string (e.g., "5s")
// Default: 5s
// Must be less than RenewDeadline
RetryPeriod string `yaml:"retry_period"`
}
LeaderElectionConfig configures leader election for running multiple replicas.
func (*LeaderElectionConfig) GetLeaseDuration ¶
func (le *LeaderElectionConfig) GetLeaseDuration() time.Duration
GetLeaseDuration returns the configured lease duration or the default if not specified or invalid.
func (*LeaderElectionConfig) GetRenewDeadline ¶
func (le *LeaderElectionConfig) GetRenewDeadline() time.Duration
GetRenewDeadline returns the configured renew deadline or the default if not specified or invalid.
func (*LeaderElectionConfig) GetRetryPeriod ¶
func (le *LeaderElectionConfig) GetRetryPeriod() time.Duration
GetRetryPeriod returns the configured retry period or the default if not specified or invalid.
type LoggingConfig ¶
type LoggingConfig struct {
// Level controls the log level: TRACE, DEBUG, INFO, WARN, ERROR (case-insensitive)
// Empty string means use LOG_LEVEL env var or default (INFO)
Level string `yaml:"level"`
}
LoggingConfig configures logging behavior.
type MapFile ¶
type MapFile struct {
// Template is the template content that generates the map file.
Template string `yaml:"template"`
// PostProcessing defines optional post-processors to apply after rendering.
// Post-processors are applied in order to transform the rendered output.
PostProcessing []PostProcessorConfig `yaml:"post_processing,omitempty"`
}
MapFile is an HAProxy map file template.
type PodSelector ¶
type PodSelector struct {
// MatchLabels are the labels to match HAProxy pods.
//
// Example:
// app: haproxy
// component: loadbalancer
MatchLabels map[string]string `yaml:"match_labels"`
}
PodSelector identifies which HAProxy pods to configure.
type PostProcessorConfig ¶
type PostProcessorConfig struct {
// Type specifies the post-processor type.
// Supported values: "regex_replace"
Type string `yaml:"type"`
// Params contains type-specific configuration parameters.
// For regex_replace:
// - pattern: Regular expression pattern to match (required)
// - replace: Replacement string (required)
Params map[string]string `yaml:"params"`
}
PostProcessorConfig defines a post-processor to apply to rendered template output.
type SSLCertificate ¶
type SSLCertificate struct {
// Template is the template content that generates the certificate file.
Template string `yaml:"template"`
// PostProcessing defines optional post-processors to apply after rendering.
// Post-processors are applied in order to transform the rendered output.
PostProcessing []PostProcessorConfig `yaml:"post_processing,omitempty"`
}
SSLCertificate is an SSL certificate file template.
type TemplateSnippet ¶
type TemplateSnippet struct {
// Name is the snippet identifier for {% include "name" %}.
// This is derived from the map key in the configuration.
Name string
// Template is the template content.
Template string `yaml:"template"`
}
TemplateSnippet is a reusable template fragment.
type TemplatingSettings ¶
type TemplatingSettings struct {
// Engine specifies which template engine to use for rendering.
// Valid values: "scriggo" (default and only supported engine)
Engine string `yaml:"engine" json:"engine"`
// ExtraContext provides custom variables that are passed to all templates.
//
// This allows users to add arbitrary data to the template context without
// modifying controller code. Values can be any valid JSON type (string, number,
// boolean, object, array).
//
// Example in YAML:
// extra_context:
// debug:
// enabled: true
// environment: production
// custom_value: 42
//
// Templates can then reference these variables directly: {{ debug.enabled }}, {{ environment }}, etc.
ExtraContext map[string]interface{} `yaml:"extra_context" json:"extraContext"`
}
TemplatingSettings configures template rendering behavior and custom variables.
type ValidationAssertion ¶
type ValidationAssertion struct {
// Type is the assertion type: "haproxy_valid", "contains", "not_contains", "match_count", "equals", "jsonpath", "match_order".
Type string `yaml:"type"`
// Description explains what this assertion validates.
Description string `yaml:"description"`
// Target specifies what to validate: "haproxy.cfg", "map:<name>", "file:<name>", "cert:<name>".
// Only used for non-haproxy_valid assertions.
Target string `yaml:"target"`
// Pattern is the regex pattern to match (for "contains" and "not_contains").
Pattern string `yaml:"pattern"`
// Expected is the expected value (for "equals" and "jsonpath").
Expected string `yaml:"expected"`
// JSONPath is the JSONPath expression to query (for "jsonpath").
JSONPath string `yaml:"jsonpath"`
// Patterns is a list of regex patterns that must appear in the specified order (for "match_order").
Patterns []string `yaml:"patterns"`
}
ValidationAssertion defines a single validation check.
type ValidationTest ¶
type ValidationTest struct {
// Description explains what this test validates.
Description string `yaml:"description"`
// Fixtures contains mock Kubernetes resources for this test.
// The map key is the resource type name (e.g., "services", "ingresses").
// The map value is a list of resources in unstructured format.
Fixtures map[string][]interface{} `yaml:"fixtures"`
// HTTPFixtures contains mock HTTP responses for this test.
// When templates call http.Fetch() for a URL that matches a fixture,
// the fixture content is returned instead of making an actual HTTP request.
HTTPFixtures []HTTPResourceFixture `yaml:"httpResources,omitempty"`
// Assertions contains validation checks to run against the rendered config.
Assertions []ValidationAssertion `yaml:"assertions"`
}
ValidationTest defines a single validation test with fixtures and assertions.
The test name is provided by the map key in ValidationTests.
type WatchedResource ¶
type WatchedResource struct {
// APIVersion is the Kubernetes API version (e.g., "networking.k8s.io/v1").
APIVersion string `yaml:"api_version"`
// Resources is the plural form of the Kubernetes resource type (e.g., "ingresses", "services").
// This is the name used in RBAC rules and API paths.
Resources string `yaml:"resources"`
// EnableValidationWebhook enables admission webhook validation for this resource.
// Default: false
EnableValidationWebhook bool `yaml:"enable_validation_webhook"`
// IndexBy specifies JSONPath expressions for extracting index keys.
//
// Resources are indexed by these values for O(1) lookup.
//
// Examples:
// ["metadata.namespace", "metadata.name"]
// ["metadata.labels['kubernetes.io/service-name']"]
IndexBy []string `yaml:"index_by"`
// LabelSelector filters resources by labels (server-side filtering).
//
// Example:
// app: haproxy
// component: loadbalancer
LabelSelector map[string]string `yaml:"label_selector,omitempty"`
// Store specifies the storage backend: "full" (MemoryStore) or "on-demand" (CachedStore).
// Default: "full"
//
// Use "on-demand" for large resources that are accessed infrequently (e.g., Secrets).
// Use "full" for frequently accessed resources (e.g., Ingress, Service, EndpointSlice).
Store string `yaml:"store"`
}
WatchedResource configures watching for a specific Kubernetes resource type.