Documentation
¶
Index ¶
- Constants
- func AllValidatorNames() []string
- func RunValidationTestsSync(ctx context.Context, cfg *coreconfig.Config, bootstrap TypeBootstrapper, ...) (configtest.Result, error)
- type BaseValidator
- type BasicValidator
- type JSONPathValidator
- type TemplateValidator
- type TypeBootstrapper
- type ValidationHandler
- type ValidationTestsValidator
Constants ¶
const ( // ValidatorNameBasic is the name for the basic structure validator. ValidatorNameBasic = "basic" // ValidatorNameTemplate is the name for the template syntax validator. ValidatorNameTemplate = "template" // ValidatorNameJSONPath is the name for the JSONPath expression validator. ValidatorNameJSONPath = "jsonpath" // ValidatorNameValidationTests is the name for the validator that runs the // config's embedded validationTests (the same suite the `controller validate` // CLI runs) before a config is accepted, so the daemon never loads a config // whose tests fail. ValidatorNameValidationTests = "validationtests" )
Validator names used in the scatter-gather validation pattern.
These constants ensure consistency between: - Validator responder names (in ConfigValidationResponse) - Expected responders list (in ConfigChangeHandler)
Using constants prevents typos and silent failures where the scatter-gather pattern would timeout waiting for a validator that uses a different name.
const EventBufferSize = busevents.LowVolumeSubscriberBuffer
EventBufferSize is the size of the event subscription buffer. Low-volume component (~1 validation request per reconciliation).
Variables ¶
This section is empty.
Functions ¶
func AllValidatorNames ¶
func AllValidatorNames() []string
AllValidatorNames returns a slice of all validator names. Use this when registering validators in the ConfigChangeHandler.
func RunValidationTestsSync ¶
func RunValidationTestsSync(ctx context.Context, cfg *coreconfig.Config, bootstrap TypeBootstrapper, runTimeout time.Duration, logger *slog.Logger) (configtest.Result, error)
RunValidationTestsSync resolves typed schemas, builds a throwaway engine, and runs the config's embedded validationTests via the shared configtest helper (the same one the admission webhook uses, so the gates can't drift). It is the shared core behind both the live scatter-gather gate (the validator's HandleRequest) and the startup load gate (controller.runIteration) — so a config's tests are bootstrapped, compiled, and executed identically whether they run on a live change or at controller load.
A config with no validationTests is a zero-cost pass. A runTimeout <= 0 uses the default suite budget (validationTestsRunTimeout). Any setup error is returned so the caller can fail validation with a clear reason rather than silently skipping the gate.
Types ¶
type BaseValidator ¶
BaseValidator wraps component.Base with validator-specific dispatch: it forwards only ConfigValidationRequest events to the handler, and on panic it publishes a failure ConfigValidationResponse so the scatter-gather coordinator does not time out.
func NewBaseValidator ¶
func NewBaseValidator( eventBus *busevents.EventBus, logger *slog.Logger, name string, handler ValidationHandler, ) *BaseValidator
NewBaseValidator creates a new base validator with the given configuration.
Parameters:
- eventBus: The EventBus to subscribe to and publish on
- logger: Structured logger for diagnostics
- name: Validator name (for error messages and responses)
- handler: ValidationHandler implementation for validator-specific logic
Returns:
- *BaseValidator ready to start
func (*BaseValidator) HandleEvent ¶
func (v *BaseValidator) HandleEvent(event busevents.Event)
HandleEvent implements component.EventHandler. We subscribed with a type filter so only ConfigValidationRequest events arrive, but the type assertion keeps things defensive in case the filter is widened later.
func (*BaseValidator) HandlePanic ¶
func (v *BaseValidator) HandlePanic(recovered any, event busevents.Event)
HandlePanic implements component.PanicHandler. Publishing a failure response on panic keeps the scatter-gather coordinator from waiting on a validator that has unwound. The outer recover in component.Base is still responsible for keeping the event loop alive.
type BasicValidator ¶
type BasicValidator struct {
*BaseValidator
// contains filtered or unexported fields
}
BasicValidator validates basic structural configuration requirements.
This component subscribes to ConfigValidationRequest events and validates basic structural requirements such as: - Required fields are present - Field types and values are correct - Port numbers are in valid ranges - Non-empty slices where required
This validator uses the existing config.ValidateStructure() function and does NOT validate template syntax or JSONPath expressions (handled by specialized validators).
This component is part of the scatter-gather validation pattern and publishes ConfigValidationResponse events with validation results.
func NewBasicValidator ¶
func NewBasicValidator(eventBus *busevents.EventBus, logger *slog.Logger) *BasicValidator
NewBasicValidator creates a new basic validator component.
Parameters:
- eventBus: The EventBus to subscribe to and publish on
- logger: Structured logger for diagnostics
Returns:
- *BasicValidator ready to start
func (*BasicValidator) HandleRequest ¶
func (v *BasicValidator) HandleRequest(req *events.ConfigValidationRequest)
HandleRequest processes a ConfigValidationRequest by validating basic structure. This implements the ValidationHandler interface.
type JSONPathValidator ¶
type JSONPathValidator struct {
*BaseValidator
// contains filtered or unexported fields
}
JSONPathValidator validates JSONPath expressions in configuration.
This component subscribes to ConfigValidationRequest events and validates all JSONPath expressions in the configuration using the k8s indexer package.
Validated fields: - WatchedResourcesIgnoreFields (all expressions) - WatchedResources[*].IndexBy (all expressions) - WatchedResources[*].FieldSelector (field.path=value format)
This component is part of the scatter-gather validation pattern and publishes ConfigValidationResponse events with validation results.
func NewJSONPathValidator ¶
func NewJSONPathValidator(eventBus *busevents.EventBus, logger *slog.Logger) *JSONPathValidator
NewJSONPathValidator creates a new JSONPath validator component.
Parameters:
- eventBus: The EventBus to subscribe to and publish on
- logger: Structured logger for diagnostics
Returns:
- *JSONPathValidator ready to start
func (*JSONPathValidator) HandleRequest ¶
func (v *JSONPathValidator) HandleRequest(req *events.ConfigValidationRequest)
HandleRequest processes a ConfigValidationRequest by validating all JSONPath expressions. This implements the ValidationHandler interface.
type TemplateValidator ¶
type TemplateValidator struct {
*BaseValidator
// contains filtered or unexported fields
}
TemplateValidator validates template syntax in configuration.
This component subscribes to ConfigValidationRequest events and validates all templates together as a complete set. It uses helpers.ExtractTemplatesFromConfig to ensure validation matches production behavior exactly (DRY principle).
Templates are validated together, not in isolation, so snippets that reference each other via render, import, or inherit_context work correctly.
This component is part of the scatter-gather validation pattern and publishes ConfigValidationResponse events with validation results.
func NewTemplateValidator ¶
func NewTemplateValidator(eventBus *busevents.EventBus, logger *slog.Logger, bootstrap TypeBootstrapper) *TemplateValidator
NewTemplateValidator creates a new template validator component.
Parameters:
- eventBus: the EventBus to subscribe to and publish on
- logger: structured logger for diagnostics
- bootstrap: resolver for typed reflect.Types per watched resource. MUST be non-nil — without real types the engine compile would degrade to envelope-only declarations and false-positively reject any chart that uses typed Spec / Status access. Tests pass a stub returning an in-memory Result; production passes a closure around controller.runTypeBootstrap.
func (*TemplateValidator) HandleRequest ¶
func (v *TemplateValidator) HandleRequest(req *events.ConfigValidationRequest)
HandleRequest processes a ConfigValidationRequest by validating all templates. This implements the ValidationHandler interface.
Templates are validated together as a complete set, matching production behavior. This ensures snippets that reference each other via render/import work correctly.
Schema acquisition for the request's watched resources happens synchronously here so the engine compile sees the same typed globals the Stage-5 production engine will see. A failure to resolve every declared resource's schema fails validation — template authors using typed access need the guarantee that every declared watched resource has its real schema (RBAC, CRD installation, apiserver health are all surfaced via this gate).
type TypeBootstrapper ¶
type TypeBootstrapper func(ctx context.Context, cfg *coreconfig.Config) (*typebootstrap.Result, error)
TypeBootstrapper runs the schema-acquisition pipeline for a candidate config and returns the resolved typed reflect.Types for each watched resource. Used by TemplateValidator so its engine compile sees the same typed globals the Stage-5 production engine will see — without this, a chart that uses typed Spec/Status access (e.g. `gw.Spec.Listeners`) would be false-positively rejected at Stage 1 against an envelope-only declaration set.
Production wiring binds this to controller.runTypeBootstrap with the iteration's K8s client captured in the closure; tests pass a stub that returns a Result built from in-memory schemas.
type ValidationHandler ¶
type ValidationHandler interface {
// HandleRequest processes a ConfigValidationRequest and publishes a response.
// The implementation should validate the config and publish a ConfigValidationResponse
// event to the bus.
HandleRequest(req *events.ConfigValidationRequest)
}
ValidationHandler defines the interface for validator-specific validation logic.
Each validator (basic, template, jsonpath) implements this interface to provide their specific validation logic while reusing the common event loop infrastructure.
type ValidationTestsValidator ¶
type ValidationTestsValidator struct {
*BaseValidator
// contains filtered or unexported fields
}
ValidationTestsValidator runs the config's embedded validationTests — the exact suite the `controller validate` CLI runs — as a scatter-gather validator. It guards live config changes: when a CRD update's tests fail the aggregation publishes ConfigInvalidEvent and the last-good config keeps serving.
The load path is guarded separately by the same suite: controller.runIteration calls RunValidationTestsSync on the initial config and crash-loops the pod if it fails (see that function and the startup gate in iteration.go). Both gates share RunValidationTestsSync so a config's tests behave identically whether they run on a live change or at load — the controller never serves a config whose own tests fail.
It builds a throwaway engine from the candidate config (using the same live-schema TypeBootstrapper the TemplateValidator uses, so typed access in tests compiles identically to production) plus a temporary HAProxy validation tree for `haproxy_valid` assertions, runs the suite, and reports the outcome. This runs only on config load/change — never on the resource reconciliation hot path.
func NewValidationTestsValidator ¶
func NewValidationTestsValidator(eventBus *busevents.EventBus, logger *slog.Logger, bootstrap TypeBootstrapper) *ValidationTestsValidator
NewValidationTestsValidator creates the validationTests validator.
bootstrap MUST be non-nil — without real typed reflect.Types the engine compile (and therefore any test exercising typed Spec/Status access) would false-positively fail. Production passes a closure around controller.runTypeBootstrap; tests pass a stub returning an in-memory Result.
func (*ValidationTestsValidator) HandleRequest ¶
func (v *ValidationTestsValidator) HandleRequest(req *events.ConfigValidationRequest)
HandleRequest runs the embedded validationTests for the candidate config and publishes a ConfigValidationResponse. A config with no validationTests is a no-op pass (the gate adds zero cost when the chart ships no tests).