Help us shape the future of Go! Take the 2026 Go Developer Survey

pipeline

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Oct 30, 2026 License: Apache-2.0 Imports: 18 Imported by: 0

README

pkg/controller/pipeline

Synchronous rendering, validation, and external-input acceptance. The pipeline has no event-bus dependency; callers provide a resource store and render mode.

Validation ownership

Caller Synchronous checks HAProxy render gate
Admission and HTTP-store proposals HAProxy and configured output validators Not needed for the proposal verdict
Leader reconciliation Configured output validators; full validation before accepting new HTTP inputs Checks the deployed plan asynchronously
Follower warmer Full validation before accepting new HTTP inputs The leader owns deployment checks

PipelineConfig.Validator enables synchronous HAProxy checks. OutputValidator checks auxiliary formats. CommitValidator gates the acceptance of new external inputs when the normal synchronous validator is absent. Only Renderer is required; New panics if it's nil.

Usage

Given configured rendering and validation services:

import (
    "github.com/haproxy-haptic/HAPTIC/pkg/controller/pipeline"
    "github.com/haproxy-haptic/HAPTIC/pkg/controller/rendercontext"
)

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

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

ExecuteWithResult also returns the validation result, including phase details and warnings on failure. Render mode is an explicit argument; an overlay store doesn't choose it for the caller.

Results and errors

PipelineResult carries authenticated snapshots of the configuration, plan, auxiliary files, status patches, Events, and owned resources, together with PlanID, ContentChecksum, and phase timings. Mutable compatibility fields stay nil in production; use the Materialize* methods for detached copies.

Failures return *PipelineError with Phase (render or validation) and a validation subphase when applicable. Use errors.As to inspect it. Cancellation is checked between phases and before success and preserves its cause.

Checks invoked by this pipeline run synchronously. The separate render gate tracks HAProxy verdicts by plan identity; see ADR-0022.

Documentation

Overview

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

Index

Constants

This section is empty.

Variables

View Source
var ErrOutputRefusedByGate = errors.New("HAProxy refused this exact render before; " +
	"its new HTTP content stays pending until the content or the cluster changes")

ErrOutputRefusedByGate stops an acceptance whose render HAProxy already refused.

View Source
var ErrRenderHeld = errors.New("rendering is paused until the critical http.Fetch source answers")

ErrRenderHeld marks a reconcile that did not render because it would only repeat the previous render's failure on unavailable critical content.

Functions

func CriticalContentUnavailable

func CriticalContentUnavailable(err error) bool

CriticalContentUnavailable reports a failed fetch required by the rendered configuration.

func InputsMoved

func InputsMoved(err error) bool

InputsMoved reports a render that lost the commit race to another commit.

func RenderHeld

func RenderHeld(err error) bool

RenderHeld reports a reconcile that skipped its render; its error repeats the failure of the render that started the hold.

func WaitsForCriticalContent

func WaitsForCriticalContent(err error) bool

WaitsForCriticalContent reports a deploying render that stopped because a critical source has no accepted content yet; the acceptance attempt it requested is what lets the next render deploy.

func WithPendingContentWithheld

func WithPendingContentWithheld(ctx context.Context) context.Context

WithPendingContentWithheld leaves new HTTP content to an independent acceptance attempt.

func WithRefusedOutputs

func WithRefusedOutputs(ctx context.Context, refused func(contentChecksum string) bool) context.Context

WithRefusedOutputs gives an acceptance attempt the outputs the render gate refused: accepting content into one of them again would only be revoked again.

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 is nil. This is intentional: it is a required dependency, 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, mode rendercontext.RenderMode, extraOpts ...rendercontext.Option) (*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

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 or authority failed)
  • ValidationResult with validation details (nil if render or authority failed)
  • Error if rendering fails or context authority expires; ordinary validation failures return a non-nil ValidationResult

func (*Pipeline) HeldRender

func (p *Pipeline) HeldRender(mode rendercontext.RenderMode) error

HeldRender returns the error Execute would return in mode without rendering any input set, or nil when Execute would render.

type PipelineConfig

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

	// Validator is the validation service for checking configuration. Nil
	// makes the pipeline render-only: the reconcile instance leaves HAProxy's
	// verdict to the asynchronous render gate (ADR-0022), while the proposal
	// instance keeps the synchronous check admission answers with.
	Validator *validation.ValidationService

	// OutputValidator optionally validates rendered auxiliary formats.
	OutputValidator RenderedOutputValidator

	// CommitValidator gates accepting external content no previous render
	// used. The reconcile pipeline has no Validator, but a render that pulls in
	// new HTTP-store content is the moment that content becomes the store's
	// accepted version — so it takes the full synchronous check before the
	// commit, not the gate's later verdict. Renders that accept nothing new
	// never reach it, which is every render in a steady state.
	CommitValidator *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] 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 {
	// HTTPObservations can confirm only the accepted versions read by this execution.
	HTTPObservations []httpstore.ObservationToken

	// CycleSnapshot binds the output and every effect from this render.
	CycleSnapshot *rendercycle.Snapshot

	// OutputSnapshot binds the exact config, plan, and auxiliary artifacts.
	OutputSnapshot *renderoutput.Snapshot

	// HAProxyConfig is the rendered HAProxy configuration.
	HAProxyConfig string

	// AuxiliaryFiles contains all rendered auxiliary files.
	// Production results leave it nil and use AuxiliaryFileSnapshot.
	AuxiliaryFiles *dataplane.AuxiliaryFiles

	// AuxiliaryFileSnapshot is the authenticated immutable production representation.
	AuxiliaryFileSnapshot *renderartifact.Snapshot

	// Plan is the structure this render declared: its sections, backends, map
	// entries and file set. Nil when the renderer produced none.
	Plan *renderplan.Plan

	// PlanID is the digest identifying Plan.
	PlanID string

	// StatusPatches is the detached compatibility representation.
	// Production renders leave it nil and use StatusPatchSnapshot.
	StatusPatches []templating.StatusPatch

	// StatusPatchSnapshot is the authenticated immutable production representation.
	StatusPatchSnapshot *templating.StatusPatchSnapshot

	// Events contains Kubernetes Events templates asked to emit via recordEvent()
	// (e.g. a RouteConflict Warning on an Ingress). Forwarded to the EventEmitter.
	// Production renders leave it nil and use EventSnapshot.
	Events []templating.RenderedEvent

	// EventSnapshot is the authenticated immutable production representation.
	EventSnapshot *templating.RenderedEventSnapshot

	// 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).
	// Production renders leave it nil and use RenderedResourceSnapshot.
	RenderedResources []templating.RenderedResource

	// RenderedResourceSnapshot is the authenticated immutable production representation.
	RenderedResourceSnapshot *templating.RenderedResourceSnapshot

	// 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

	// CacheState is "warm" when the render had a graph to build on, "cold" when it
	// re-evaluated everything, and "replay" when it reused the previous output.
	CacheState string

	// CacheBuildMs is what the most recent completed cache build cost, 0 while none
	// has completed.
	CacheBuildMs 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

	// ValidationWarnings contains non-fatal diagnostics produced after render.
	ValidationWarnings []string
}

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

func (*PipelineResult) MaterializeAuxiliaryFiles

func (r *PipelineResult) MaterializeAuxiliaryFiles() (*dataplane.AuxiliaryFiles, error)

MaterializeAuxiliaryFiles returns a caller-isolated compatibility view.

func (*PipelineResult) MaterializeEvents

func (r *PipelineResult) MaterializeEvents() ([]templating.RenderedEvent, error)

MaterializeEvents returns a caller-isolated compatibility view.

func (*PipelineResult) MaterializeRenderedResources

func (r *PipelineResult) MaterializeRenderedResources() ([]templating.RenderedResource, error)

MaterializeRenderedResources returns a caller-isolated compatibility view.

func (*PipelineResult) MaterializeStatusPatches

func (r *PipelineResult) MaterializeStatusPatches() ([]templating.StatusPatch, error)

MaterializeStatusPatches returns a caller-isolated compatibility view.

type RenderedOutputValidator

type RenderedOutputValidator interface {
	ValidateRenderedOutput(ctx context.Context, result *PipelineResult) (warnings []string, err error)
}

RenderedOutputValidator validates the complete rendered file set.

Jump to

Keyboard shortcuts

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