pipeline

package
v0.2.0-alpha.1 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jul 5, 2026 License: Apache-2.0 Imports: 10 Imported by: 0

README

pkg/controller/pipeline

Pure render-validate pipeline composing renderer.RenderService and validation.ValidationService into a single workflow.

Overview

The controller has two callers that need to render-then-validate a HAProxy configuration: the leader-side reconciliation (pkg/controller/reconciler.Coordinator) and the proposal validator that backs the admission webhook (pkg/controller/proposalvalidator). Both feed the same code path through this package, so admission decisions and reconciliation decisions can never diverge.

*Pipeline has no event-bus dependency — it's a synchronous service that takes a stores.StoreProvider, returns a *PipelineResult. Callers wrap it in their own event handling.

Quick Start

import (
    "gitlab.com/haproxy-haptic/haptic/pkg/controller/pipeline"
    "gitlab.com/haproxy-haptic/haptic/pkg/controller/renderer"
    "gitlab.com/haproxy-haptic/haptic/pkg/controller/validation"
)

renderSvc := renderer.NewRenderService(/* engine, config, paths, capabilities, ... */)
validateSvc := validation.NewValidationService(/* paths, capabilities, ... */)

pl := pipeline.New(&pipeline.PipelineConfig{
    Renderer:  renderSvc,
    Validator: validateSvc,
    Logger:    logger,
})

result, err := pl.Execute(ctx, storeProvider)

The *PipelineResult carries everything downstream consumers need without re-running render or validate:

  • HAProxyConfig (string), AuxiliaryFiles (*dataplane.AuxiliaryFiles)
  • StatusPatches []templating.StatusPatch — registered by templates during the render
  • AuxFileCount int — convenience aggregate
  • ContentChecksum string — pre-computed checksum of config + aux files (see below)
  • RenderDurationMs, ValidateDurationMs, TotalDurationMs — phase timings
  • ValidationPhase string — last completed validation phase (empty if all passed)
  • ParsedConfig *parser.StructuredConfig — see "Pre-Parsed Config Optimisation"

pipeline.New panics if Renderer or Validator is nil — these are required dependencies and a missing one is a configuration bug, not a runtime error to be surfaced later.

Entry Points
Method Use case
Execute(ctx, provider) (*PipelineResult, error) Standard reconciliation / proposal validation. Render + validate.
ExecuteWithResult(ctx, provider) (*PipelineResult, *validation.ValidationResult, error) Same render+validate flow but also returns the raw *validation.ValidationResult so callers can inspect warnings / phase details without parsing the wrapped error. Used by the proposal validator's webhook path.

What Execute Does

  1. Render — calls the render service with the supplied store provider. The render mode (production vs validation) is auto-detected: if the provider is an *OverlayStoreProvider with overlays, it's a validation render; otherwise it's a production render.
  2. Compute checksumdataplane.ComputeContentChecksum(config, auxFiles) runs once and is propagated through PipelineResult.ContentChecksum. Downstream consumers (publishing, deployment) reuse it instead of re-hashing.
  3. Validate — calls the three-phase validation service with the rendered config + aux files + pre-computed checksum (so the validation cache key is consistent across callers).
  4. Wrap errors — failures come back as *PipelineError with Phase (render / validation) and, for validation, ValidationPhase (syntax / schema / semantic). Use errors.As to pull the phase out instead of string-matching the message.

Pre-Parsed Config Optimisation

PipelineResult.ParsedConfig carries the *parser.StructuredConfig produced during syntax validation. Downstream sync operations (pkg/dataplane.Client.Sync) accept it as input to skip a redundant parse. When the validation cache hits, this field is nil — the cached entry doesn't carry the parsed structure.

See Also

License

Apache-2.0 — see root LICENSE.

Documentation

Overview

Package pipeline provides the render-validate pipeline for HAProxy configuration.

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

This section is empty.

Types

type Pipeline

type Pipeline struct {
	// contains filtered or unexported fields
}

Pipeline composes render and validate services into a single workflow.

The pipeline: 1. Renders HAProxy configuration from stores 2. Validates the rendered configuration 3. Returns combined result

This is a pure service with no event dependencies. It can be used by: - ReconciliationCoordinator for normal reconciliation flow - ProposalValidator for validation-only requests.

func New

func New(cfg *PipelineConfig) *Pipeline

New creates a new render-validate pipeline.

Panics if Renderer or Validator is nil. This is intentional: these are required dependencies, and failing at construction time is clearer than returning errors at execution time.

func (*Pipeline) Execute

func (p *Pipeline) Execute(ctx context.Context, provider stores.StoreProvider) (*PipelineResult, error)

Execute runs the render-validate pipeline.

The render mode (production vs validation) is determined automatically: - If provider is *OverlayStoreProvider with overlays: validation mode - Otherwise: production mode

Parameters:

  • ctx: Context for cancellation
  • provider: StoreProvider for accessing resource stores

Returns:

  • PipelineResult containing rendered config and validation status
  • Error if rendering or validation fails

func (*Pipeline) ExecuteWithResult

func (p *Pipeline) ExecuteWithResult(ctx context.Context, provider stores.StoreProvider) (*PipelineResult, *validation.ValidationResult, error)

ExecuteWithResult runs the pipeline and returns validation result even on failure. This is useful when you need details about why validation failed.

The render mode (production vs validation) is determined automatically: - If provider is *OverlayStoreProvider with overlays: validation mode - Otherwise: production mode

Parameters:

  • ctx: Context for cancellation
  • provider: StoreProvider for accessing resource stores

Returns:

  • PipelineResult with config and timing (nil if render failed)
  • ValidationResult with validation details (nil if render failed)
  • Error if rendering fails (validation failures return non-nil ValidationResult)

type PipelineConfig

type PipelineConfig struct {
	// Renderer is the render service for generating configuration.
	Renderer *renderer.RenderService

	// Validator is the validation service for checking configuration.
	Validator *validation.ValidationService

	// Logger is the structured logger for logging.
	Logger *slog.Logger
}

PipelineConfig contains configuration for creating a Pipeline.

type PipelineError

type PipelineError struct {
	// Phase identifies which pipeline phase failed.
	Phase PipelinePhase

	// ValidationPhase is set when Phase is PhaseValidation.
	// It contains the specific validation sub-phase (syntax, schema, semantic).
	ValidationPhase string

	// Cause is the underlying error.
	Cause error
}

PipelineError is a structured error that identifies which pipeline phase failed. Callers can use errors.AsType[*PipelineError] (or errors.As with a typed pointer target on Go < 1.26) to extract phase information instead of string parsing. The Coordinator does this in handlePipelineFailure to set the reconciliation-failed event's phase field.

func (*PipelineError) Error

func (e *PipelineError) Error() string

Error implements the error interface.

func (*PipelineError) Unwrap

func (e *PipelineError) Unwrap() error

Unwrap returns the underlying error for errors.Is/As compatibility.

type PipelinePhase

type PipelinePhase string

PipelinePhase identifies which phase of the pipeline failed.

const (
	// PhaseRender indicates the render phase.
	PhaseRender PipelinePhase = "render"
	// PhaseValidation indicates the validation phase.
	PhaseValidation PipelinePhase = "validation"
)

type PipelineResult

type PipelineResult struct {
	// HAProxyConfig is the rendered HAProxy configuration.
	HAProxyConfig string

	// AuxiliaryFiles contains all rendered auxiliary files.
	AuxiliaryFiles *dataplane.AuxiliaryFiles

	// StatusPatches contains status patches registered by templates during rendering.
	// Each patch targets a Kubernetes resource and contains outcome-keyed variants.
	StatusPatches []templating.StatusPatch

	// RenderedResources contains full Kubernetes resources the templates declared
	// the controller should own and reconcile (e.g. an auxiliary Service or other
	// object a template emits alongside the HAProxy config).
	RenderedResources []templating.RenderedResource

	// AuxFileCount is the total number of auxiliary files.
	AuxFileCount int

	// ContentChecksum is the pre-computed content checksum covering config + aux files.
	// Computed once in the pipeline and propagated through events to downstream consumers,
	// eliminating redundant hashing across validation, publishing, and deployment.
	ContentChecksum string

	// RenderDurationMs is the rendering duration in milliseconds.
	RenderDurationMs int64

	// ValidateDurationMs is the validation duration in milliseconds.
	ValidateDurationMs int64

	// TotalDurationMs is the total pipeline duration in milliseconds.
	TotalDurationMs int64

	// ValidationPhase indicates which validation phase completed last.
	// Empty string means all phases passed.
	ValidationPhase string

	// ParsedConfig is the pre-parsed desired configuration from syntax validation.
	// May be nil if validation cache was used.
	// When non-nil, can be passed to downstream sync operations to avoid re-parsing.
	ParsedConfig *parser.StructuredConfig
}

PipelineResult contains the output of a render-validate pipeline execution.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL