conversion

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: 8 Imported by: 0

README

pkg/controller/conversion

Converts the HAProxyTemplateConfig CRD (Kubernetes API surface) into the internal *config.Config (controller-internal) the rest of the controller works with.

Overview

Two entry points:

Function Input Output
ParseCRD(resource) *unstructured.Unstructured from a watcher (*config.Config, *v1alpha1.HAProxyTemplateConfig, error) — both the converted internal config and the typed CRD wrapper for k8s metadata
ConvertSpec(spec) typed *v1alpha1.HAProxyTemplateConfigSpec (*config.Config, error) — useful when callers already have the typed object

ParseCRD is the production path; the controller's CRD watcher hands raw unstructured bytes to it, then publishes the resulting *config.Config plus the CRD wrapper as a ConfigParsedEvent. The wrapper is kept around so downstream components (status updater, config publisher) have access to metadata.name / metadata.namespace / metadata.uid for owner references and status patches.

Quick Start

import "gitlab.com/haproxy-haptic/haptic/pkg/controller/conversion"

cfg, crd, err := conversion.ParseCRD(unstructuredResource)
if err != nil {
    // type mismatch, missing fields, or invalid YAML inside spec
    return err
}
// cfg  → *config.Config (templates, watched resources, dataplane settings, etc.)
// crd  → *v1alpha1.HAProxyTemplateConfig (typed CRD with metadata)

Design

The conversion is intentionally a one-way street: CRD types live in pkg/apis/haproxytemplate/v1alpha1 and are generated from kubebuilder annotations; internal *config.Config lives in pkg/core/config and is plain Go. Keeping them separate lets the internal type evolve independently of the CRD schema (and lets tests construct configs without going through YAML).

Validation of field-level constraints (template syntax, JSONPath expressions, port ranges) does not happen here — pkg/controller/configchange.ConfigChangeHandler runs the scatter-gather validation against the converted *config.Config. This package is just the structural conversion.

See Also

License

Apache-2.0 — see root LICENSE.

Documentation

Index

Constants

This section is empty.

Variables

This section is empty.

Functions

func ConvertSpec

func ConvertSpec(spec *v1alpha1.HAProxyTemplateConfigSpec) (*config.Config, error)

ConvertSpec converts a HAProxyTemplateConfig CRD Spec to internal config.Config format.

This is a comprehensive converter that handles ALL fields from the CRD spec including:

  • Production fields: PodSelector, Controller, Logging, Dataplane
  • Template fields: HAProxyConfig, TemplateSnippets, Maps, Files, SSLCertificates
  • Resource fields: WatchedResources, WatchedResourcesIgnoreFields
  • Configuration fields: TemplatingSettings
  • Test fields: ValidationTests (includes fixtures and assertions)

The CRD spec field CredentialsSecretRef is intentionally excluded as it's handled separately by the credentials loader component.

IMPORTANT: When adding or modifying fields in the CRD types (pkg/apis/haproxytemplate/v1alpha1/types.go), you MUST update this function to copy those fields. The CRD types have documentation comments pointing to this file as a reminder.

Common mistake: Adding a field to the CRD but forgetting to copy it here, resulting in the field being silently ignored by the controller.

func ParseCRD

ParseCRD converts an unstructured HAProxyTemplateConfig CRD to typed structs.

This function validates the resource type, converts the unstructured resource to a typed HAProxyTemplateConfig CRD, and then converts the CRD Spec to a config.Config for validation and rendering.

Returns:

  • *config.Config: Parsed configuration for validation and rendering
  • *v1alpha1.HAProxyTemplateConfig: Original CRD for Kubernetes metadata (name, namespace, UID)
  • error: Validation or conversion failure

Types

type SpecResolution

type SpecResolution struct {
	// StrippedTests maps each stripped validation-test name to a
	// human-readable reason ("requires unavailable resource X" vs
	// "field X absent from resolved schema").
	StrippedTests map[string]string
}

SpecResolution reports what ResolveEffectiveSpec stripped, so the validate CLI can list the stripped tests (the degraded-profile harness asserts the exact set).

func ResolveEffectiveSpec

func ResolveEffectiveSpec(
	spec *v1alpha1.HAProxyTemplateConfigSpec,
	served func(apiVersion, resources string) bool,
	fieldServed func(apiVersion, resources, fieldPath string) (bool, error),
	logger *slog.Logger,
) (*SpecResolution, error)

ResolveEffectiveSpec mirrors the controller's effective-config resolution (pkg/core/config.ResolveEffective) for the offline validate path, operating in place on the CRD spec form the validate CLI's helpers consume. Semantics:

  • each watched resource resolves to the first apiVersions candidate the `served` callback reports as available (in the CLI: a CRD manifest in --schema-dir listing the version as served);
  • an OPTIONAL resource with no served candidate is dropped together with every templateSnippet / validationTest whose requires names it — this is what makes degraded cluster profiles testable offline;
  • a validationTest whose requiresFields names a field the `fieldServed` callback reports absent from the resolved schema is dropped too — the field-level analogue for schema generations that serve the resource at the same version string but without individual fields. fieldServed may be nil (no --schema-dir): field checks are then skipped entirely, the same leniency the untyped path has always had. A fieldServed error fails the resolution (never silently strips);
  • unlike the live controller, a REQUIRED resource with no served candidate falls back to its first candidate instead of failing: offline validation has no cluster to interrogate, and a schema-dir that simply doesn't bundle some watched resource must keep validating through the untyped path exactly as it always has (same leniency as the GVK-resolution skip in the offline type bootstrap). The same fallback applies to every resource when `served` is nil (no --schema-dir at all).

Jump to

Keyboard shortcuts

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