renderer

package
v0.1.0-alpha.12 Latest Latest
Warning

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

Go to latest
Published: Feb 27, 2026 License: Apache-2.0 Imports: 25 Imported by: 0

README

pkg/controller/renderer

Renderer component - template rendering for HAProxy configuration.

Overview

Event-driven component that renders HAProxy configuration from templates using current resource state.

Quick Start

renderer := renderer.NewRendererComponent(bus, engine, logger)
go renderer.Start(ctx)

Events

  • Subscribes: ReconciliationTriggeredEvent
  • Publishes: TemplateRenderedEvent, TemplateRenderFailedEvent

Template Context

The renderer builds a context with all watched Kubernetes resources:

{
  "resources": {
    "ingresses": StoreWrapper,    // Provides List() and Get()
    "services": StoreWrapper,
    "endpoints": StoreWrapper,
    // ... other watched resources
  }
}
StoreWrapper Performance

StoreWrapper unwraps unstructured.Unstructured objects to plain maps for template access:

  • List(): Lazy-cached - unwraps all resources on first call, caches for subsequent calls within the same reconciliation
  • Get(keys...): On-demand - unwraps matched resources each call (typically small result sets)

This ensures templates pay the unwrapping cost only once per reconciliation, regardless of how many times List() is called.

License

See main repository for license information.

Documentation

Overview

Package renderer implements the Renderer component that renders HAProxy configuration and auxiliary files from templates.

The Renderer is a Stage 5 component that subscribes to reconciliation trigger events, builds rendering context from resource stores, and publishes rendered output events for the next phase (validation/deployment).

Index

Constants

View Source
const (
	// ComponentName is the unique identifier for this component.
	ComponentName = "renderer"
)

Variables

This section is empty.

Functions

This section is empty.

Types

type Component

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

Component implements the renderer component.

It subscribes to ReconciliationTriggeredEvent, renders all templates using the template engine and resource stores, and publishes the results via TemplateRenderedEvent or TemplateRenderFailedEvent.

The component renders configurations twice per reconciliation: 1. Production version with absolute paths for HAProxy pods (/etc/haproxy/*) 2. Validation version with temp directory paths for controller validation

This is a leader-only component that starts when leadership is acquired. The Reconciler triggers a fresh reconciliation on BecameLeaderEvent to provide current state.

CRT-list Fallback: The component determines CRT-list storage capability from the local HAProxy version (passed at construction time). When CRT-list storage is not supported (HAProxy < 3.2), CRT-list file paths are resolved to the general files directory instead of the SSL directory, ensuring the generated configuration matches where files are actually stored.

func New

func New(
	eventBus *busevents.EventBus,
	cfg *config.Config,
	storeMap map[string]stores.Store,
	haproxyPodStore stores.Store,
	currentConfigStore *currentconfigstore.Store,
	capabilities dataplane.Capabilities,
	logger *slog.Logger,
) (*Component, error)

New creates a new Renderer component.

The component pre-compiles all templates during initialization for optimal runtime performance.

Parameters:

  • eventBus: The EventBus for subscribing to events and publishing results
  • config: Controller configuration containing templates
  • stores: Map of resource type names to their stores (e.g., "ingresses" -> Store)
  • haproxyPodStore: Store containing HAProxy controller pods for pod-maxconn calculations
  • currentConfigStore: Store containing the current deployed HAProxy config (for slot preservation)
  • capabilities: HAProxy capabilities determined from local version
  • logger: Structured logger for component logging

Returns:

  • A new Component instance ready to be started
  • Error if template compilation fails

func (*Component) HealthCheck

func (c *Component) HealthCheck() error

HealthCheck implements the lifecycle.HealthChecker interface. Returns an error if the component appears to be stalled (processing for > timeout). Returns nil when idle (not processing) - idle is always healthy for event-driven components.

func (*Component) Name

func (c *Component) Name() string

Name returns the unique identifier for this component. Implements the lifecycle.Component interface.

func (*Component) SetHTTPStoreComponent

func (c *Component) SetHTTPStoreComponent(httpStoreComponent *httpstore.Component)

SetHTTPStoreComponent sets the HTTP store component for dynamic HTTP resource fetching. This must be called before Start() to enable http.Fetch() in templates.

func (*Component) Start

func (c *Component) Start(ctx context.Context) error

Start begins the renderer's event loop.

This method blocks until the context is cancelled or an error occurs. As a leader-only component, it subscribes to events when started (after leadership is acquired).

The component runs until the context is cancelled, at which point it performs cleanup and returns.

Parameters:

  • ctx: Context for cancellation and lifecycle management

Returns:

  • nil when context is cancelled (graceful shutdown)
  • Error only in exceptional circumstances

func (*Component) SubscriptionReady

func (c *Component) SubscriptionReady() <-chan struct{}

SubscriptionReady returns a channel that is closed when the component has completed its event subscription. This implements lifecycle.SubscriptionReadySignaler.

For leader-only components like the Renderer, subscription happens in Start() rather than in the constructor. This method allows the lifecycle registry to wait for subscription before signaling that the component is ready.

type RenderResult

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

	// AuxiliaryFiles contains all rendered auxiliary files (maps, certs, general).
	AuxiliaryFiles *dataplane.AuxiliaryFiles

	// DurationMs is the total render duration in milliseconds.
	DurationMs int64

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

RenderResult contains the output of a render operation.

type RenderService

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

RenderService is a pure service that transforms stores into HAProxy configuration.

This service uses absolute paths from the config's Dataplane settings to ensure rendered configs reference files at the correct locations where DataPlane API stores auxiliary files.

Resources in stores are already converted (floats to ints) at storage time, so the service simply passes through store data without additional processing.

func NewRenderService

func NewRenderService(cfg *RenderServiceConfig) *RenderService

NewRenderService creates a new RenderService.

The service uses relative paths derived from the config's Dataplane settings. The directory names are extracted using filepath.Base() to get just the final directory component (e.g., /etc/haproxy/maps → maps).

These relative paths are resolved by HAProxy using the `default-path origin <baseDir>` directive in the global section, which makes HAProxy resolve paths from the specified base directory regardless of where the config file is located. This works for:

  • Local validation: ValidationService replaces baseDir with temp directory
  • DataPlane API deployment: baseDir points to where files are stored (e.g., /etc/haproxy)

func (*RenderService) ClearVMPool

func (s *RenderService) ClearVMPool()

ClearVMPool releases pooled template engine VMs. Call after rendering completes to reduce memory from parallel rendering spikes.

func (*RenderService) Render

func (s *RenderService) Render(ctx context.Context, provider stores.StoreProvider) (*RenderResult, error)

Render transforms the stores into HAProxy configuration.

The render mode (production vs validation) is determined automatically:

  • If provider is *OverlayStoreProvider with HTTP overlay: validation mode
  • Otherwise: production mode

Parameters:

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

Returns:

  • RenderResult containing the rendered configuration and auxiliary files
  • Error if rendering fails

type RenderServiceConfig

type RenderServiceConfig struct {
	// Engine is the template engine to use for rendering.
	Engine templating.Engine

	// Config is the controller configuration.
	Config *config.Config

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

	// Capabilities defines HAProxy version capabilities.
	Capabilities dataplane.Capabilities

	// HAProxyPodStore is the store containing HAProxy pods (optional).
	HAProxyPodStore stores.Store

	// HTTPStoreComponent is the HTTP store for dynamic content (optional).
	HTTPStoreComponent *httpstore.Component

	// CurrentConfigStore is the store for current deployed config (optional).
	CurrentConfigStore *currentconfigstore.Store
}

RenderServiceConfig contains configuration for creating a RenderService.

Jump to

Keyboard shortcuts

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