v1alpha1

package
v0.9.0 Latest Latest
Warning

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

Go to latest
Published: Aug 4, 2026 License: MPL-2.0 Imports: 25 Imported by: 0

Documentation

Overview

Package v1alpha1 contains types for the v1alpha1 API group +groupName=blueprints.windsorcli.dev

Package v1alpha1 contains types for the v1alpha1 API group +groupName=blueprints.windsorcli.dev

Package v1alpha1 contains types for the v1alpha1 API group +groupName=blueprints.windsorcli.dev

Index

Constants

View Source
const CrdLayerName = "crds"

CrdLayerName is the base name of the synthesized kustomizations that install the vendored CRD layer. One CRD kustomization is materialized per source that carries CRDs: the layer for the default/project source takes this name verbatim, and a layer for a named source takes "crds-<source>" (see CrdKustomizationName). The stack depends on these layers by name, and ToFluxKustomization keys its PostBuild skip on them (see IsCrdLayerName) — so the "crds" name and the "crds-" namespace are reserved: the composer rejects user-authored kustomizations that claim them.

Variables

This section is empty.

Functions

func CrdKustomizationName added in v0.9.0

func CrdKustomizationName(source string) string

CrdKustomizationName returns the name of the kustomization the provisioner synthesizes for a CRD source: "crds" for the default/project source (empty name) and "crds-<source>" for a named source. The barrier makes every root kustomization depend on this name so the stack waits on the CRDs.

func DeepMergeMaps added in v0.9.0

func DeepMergeMaps(base, overlay map[string]any) map[string]any

DeepMergeMaps returns a new map from a deep merge of base and overlay maps. Overlay values take precedence; nested maps merge recursively. Non-map overlay values replace base values. Empty overlay values—including empty string "", empty slice, and empty map—never overwrite an existing non-empty base value, so populated Inputs (or other merged maps) are preserved when overlay has empty values. Map-like overlay values are normalized to map[string]any. Package-level so callers without a Blueprint can merge scope maps (e.g. context over facet scope) without losing nested facet-derived keys.

func HasRemoteTemplateSource added in v0.9.0

func HasRemoteTemplateSource(sources []Source) bool

HasRemoteTemplateSource returns true when sources include a template source with a non-empty URL.

func IsCrdLayerName added in v0.9.0

func IsCrdLayerName(name string) bool

IsCrdLayerName reports whether name belongs to the synthesized CRD layer namespace: the base "crds" name or any per-source "crds-<source>" name.

func IsLocalTemplateSource added in v0.9.0

func IsLocalTemplateSource(source Source) bool

IsLocalTemplateSource returns true when the source is the template source with no URL (local context template).

func ToMapStringAny added in v0.9.0

func ToMapStringAny(v any) map[string]any

ToMapStringAny converts a map-like value to map[string]any recursively (e.g. map[interface{}]interface{} from YAML or expr). Returns nil if v is not a map. Ensures blueprint Inputs are always map[string]any so YAML marshaling produces nested YAML rather than Go's %v string format.

func ToSliceAny added in v0.9.0

func ToSliceAny(v any) []any

ToSliceAny converts a slice-like value to []any recursively (e.g. []interface{} from YAML or expr). Returns nil if v is not a slice.

Types

type Blueprint

type Blueprint struct {
	// Kind is the blueprint type, following Kubernetes conventions.
	Kind string `yaml:"kind"`

	// ApiVersion is the API schema version of the blueprint.
	ApiVersion string `yaml:"apiVersion"`

	// Metadata includes the blueprint's name and description.
	Metadata Metadata `yaml:"metadata"`

	// Backend names the terraform component that terminates the backend tier.
	Backend string `yaml:"backend,omitempty"`

	// Repository details the source repository of the blueprint.
	Repository Repository `yaml:"repository,omitempty"`

	// Sources are external resources referenced by the blueprint.
	Sources []Source `yaml:"sources,omitempty"`

	// TerraformComponents are Terraform modules in the blueprint.
	TerraformComponents []TerraformComponent `yaml:"terraform,omitempty"`

	// Crds is the flat list of vendored CRD references the blueprint installs from the default/project
	// source (e.g. "cert-manager-1.16.2"). It is authored and asserted as a bare scalar list, the same
	// form facets use. CRDs carried by an OCI source are not listed here — they ride with that Source
	// (see Source.Crds) and install in the background when the source is install:true. The provisioner
	// materializes these into the "crds" kustomization, bound to the default source, ahead of the stack.
	Crds []string `yaml:"crds,omitempty"`

	// Kustomizations are plain Flux Kustomization configs (the kustomize: passthrough).
	Kustomizations []Kustomization `yaml:"kustomize,omitempty"`

	// FluxSystems are system entries (the flux: collection): each compiles to an install plus
	// resources-variant Kustomizations. Distinct from Kustomizations, which are 1:1 passthroughs.
	FluxSystems []FluxSystem `yaml:"flux,omitempty"`

	// Substitutions are top-level key/value pairs evaluated with facet scope and injected into
	// values-common, making them available to all kustomizations via PostBuild substitution.
	// Values may use expression syntax (e.g. "${dns.domain}") resolved against facet config blocks.
	Substitutions map[string]string `yaml:"substitutions,omitempty"`

	// ConfigMaps are standalone ConfigMaps to be created, not tied to specific kustomizations.
	// These ConfigMaps are referenced by all kustomizations in PostBuild substitution.
	ConfigMaps map[string]map[string]string `yaml:"configMaps,omitempty"`

	// Messages are operator-facing post-run notes contributed by active facets. They carry raw
	// text/when templates through composition; GenerateResolved evaluates each against composed
	// scope, keeping only the when-true entries with interpolated text for the command to print.
	Messages []Message `yaml:"messages,omitempty"`
}

Blueprint is a configuration blueprint for initializing a project.

func (*Blueprint) AllKustomizations added in v0.9.0

func (b *Blueprint) AllKustomizations() []Kustomization

AllKustomizations returns a flat list of every compiled Kustomization — plain kustomize: entries first, then the install and resources tiers compiled from each FluxSystem. Expressions on stored FluxSystems are already evaluated; this method only performs name/path/dependency assembly.

func (*Blueprint) BackendComponentID added in v0.9.0

func (b *Blueprint) BackendComponentID() string

BackendComponentID returns Blueprint.Backend, or "" when no backend tier is declared.

func (*Blueprint) BackendTier added in v0.9.0

func (b *Blueprint) BackendTier() []*TerraformComponent

BackendTier returns the named backend component plus every component declared before it in TerraformComponents, in declaration order. Returns nil when Backend is unset or names a component not present (validation catches the latter at load).

func (*Blueprint) DeepCopy

func (b *Blueprint) DeepCopy() *Blueprint

DeepCopy creates a deep copy of the Blueprint object.

func (*Blueprint) IsBackendTierMember added in v0.9.0

func (b *Blueprint) IsBackendTierMember(id string) bool

IsBackendTierMember reports whether the component ID appears in BackendTier.

func (*Blueprint) RemoveFluxSystem added in v0.9.0

func (b *Blueprint) RemoveFluxSystem(removal FluxSystem) error

RemoveFluxSystem removes specified non-index fields from an existing FluxSystem. It finds a system matching the same Name, then subtracts dependsOn entries and any install fields named in removal.Install (reusing subtractKustomizationFields, since Install is itself a Kustomization carrying no Name until tier compilation, so it cannot go through RemoveKustomization's by-Name lookup), and drops any resources variant whose Name is named in removal.Resources (empty Name matches the unnamed variant). A resources variant has no kustomize: analog — it compiles to its own distinct Kustomization — so naming it is itself the field-level operation, not a whole-system deletion. The index field (Name) is not affected. If no matching system exists, no action is taken.

func (*Blueprint) RemoveKustomization added in v0.9.0

func (b *Blueprint) RemoveKustomization(removal Kustomization) error

RemoveKustomization removes specified non-index fields from an existing Kustomization. It finds a kustomization matching the same Name, then removes patches, components, dependencies, cleanup items, and substitutions that are specified in the removal kustomization. The index field (Name) is not affected. If no matching kustomization exists, no action is taken.

func (*Blueprint) RemoveTerraformComponent added in v0.9.0

func (b *Blueprint) RemoveTerraformComponent(removal TerraformComponent) error

RemoveTerraformComponent removes specified non-index fields from an existing TerraformComponent. Components are matched by component ID (name if provided, otherwise Path). It removes inputs, dependencies, and other fields that are specified in the removal component. Index fields (Name, Path, Source) are not affected. If no matching component exists, no action is taken.

func (*Blueprint) ReplaceKustomization added in v0.8.0

func (b *Blueprint) ReplaceKustomization(kustomization Kustomization) error

ReplaceKustomization replaces an existing Kustomization with the provided kustomization. If a kustomization with the same Name exists, it is completely replaced. Otherwise, the kustomization is appended. Returns an error if a dependency cycle is detected during sorting.

func (*Blueprint) ReplaceTerraformComponent added in v0.8.0

func (b *Blueprint) ReplaceTerraformComponent(component TerraformComponent) error

ReplaceTerraformComponent replaces an existing TerraformComponent with the provided component. Components are matched by component ID (name if provided, otherwise Path). If a matching component exists, it is completely replaced. Otherwise, the component is appended. Returns an error if a dependency cycle is detected during sorting or if component IDs are not unique.

func (*Blueprint) StrategicMerge added in v0.8.0

func (b *Blueprint) StrategicMerge(overlays ...*Blueprint) error

StrategicMerge performs a strategic merge of the provided overlay Blueprints into the receiver Blueprint. This method appends to array fields, deep merges map fields, and updates scalar fields if present in the overlays. It is designed for feature composition, enabling the combination of multiple features into a single blueprint.

func (*Blueprint) UpsertFluxSystem added in v0.9.0

func (b *Blueprint) UpsertFluxSystem(sys FluxSystem) error

UpsertFluxSystem merges sys into the FluxSystem with the same Name if one exists in b.FluxSystems, or appends it when none does. On a match, DependsOn accumulates (union), Install/Resources deep-merge via MergeFluxInstall/MergeFluxVariants, and Secrets union per data key — the same field-level semantics strategicMergeKustomization already gives same-name plain kustomize: entries — rather than sys wholesale-replacing what is already there. This is the path StrategicMerge uses to combine FluxSystems across sources (each source's facets already merged among themselves before reaching here), so a same-name collision here must not silently drop one side's install/resources tiers or Secrets the way a blind replace would.

type BlueprintPatch added in v0.8.0

type BlueprintPatch struct {
	// Path to the patch file relative to the kustomization (blueprint format).
	Path string `yaml:"path,omitempty"`

	// Patch content as YAML string (Flux format).
	Patch string `yaml:"patch,omitempty"`

	// Target selector for the patch (Flux format).
	Target *kustomize.Selector `yaml:"target,omitempty"`
}

BlueprintPatch represents a patch in the blueprint format. This is converted to kustomize.Patch during processing. Supports both blueprint format (Path) and Flux format (Patch + Target).

type BoolExpression added in v0.9.0

type BoolExpression struct {
	Value  *bool
	Expr   string
	IsExpr bool
}

BoolExpression represents a boolean value that can be unmarshaled from a boolean or a string expression. String expressions are preserved for later evaluation during facet processing.

func (*BoolExpression) DeepCopy added in v0.9.0

func (b *BoolExpression) DeepCopy() *BoolExpression

DeepCopy creates a deep copy of the BoolExpression.

func (*BoolExpression) IsEnabled added in v0.9.0

func (b *BoolExpression) IsEnabled() bool

IsEnabled returns true if the BoolExpression is nil (default) or if its value is true. Returns false only if the value is explicitly set to false. This is used for fields like Enabled that default to true.

func (*BoolExpression) IsInstalled added in v0.9.0

func (b *BoolExpression) IsInstalled() bool

IsInstalled returns true only if the BoolExpression is explicitly set to true. Returns false if nil (default), if it's an expression, or if explicitly false. This is used for fields like Install that default to false.

func (*BoolExpression) MarshalYAML added in v0.9.0

func (b *BoolExpression) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler to write boolean as a bool or expression string.

func (*BoolExpression) ToBool added in v0.9.0

func (b *BoolExpression) ToBool() *bool

ToBool returns the boolean value, or nil if it's an expression.

func (*BoolExpression) UnmarshalYAML added in v0.9.0

func (b *BoolExpression) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml.Unmarshaler to read boolean from a bool or string expression.

type ConditionalKustomization added in v0.8.0

type ConditionalKustomization struct {
	Kustomization `yaml:",inline"`

	// When is an expression that determines if this kustomization should be applied.
	// If empty, the kustomization is always applied when the parent facet matches.
	When string `yaml:"when,omitempty"`

	// Strategy determines how this kustomization is merged into the blueprint.
	// Valid values are "merge" (default), "replace", and "remove".
	// If empty or "merge", the kustomization is merged with existing kustomizations matching the same Name.
	// If "replace", the kustomization completely replaces any existing kustomization with the same Name.
	// If "remove", the kustomization's non-index fields (everything except Name) are removed from the
	// matching existing kustomization. Remove operations are always applied last after all merge/replace operations.
	Strategy string `yaml:"strategy,omitempty"`

	// Ordinal overrides the facet ordinal for this kustomization's merge precedence. When nil, the facet's ordinal is used.
	// Higher ordinal means higher precedence when merging (processed later, wins on conflict).
	Ordinal *int `yaml:"ordinal,omitempty"`

	// Requires lists requirement blocks scoped to this kustomization. Evaluated only when the parent
	// facet is active and this kustomization's When holds; missing paths are aggregated under the
	// effective condition (facet.When && kustomization.When && block.When).
	Requires []RequirementBlock `yaml:"requires,omitempty"`
}

ConditionalKustomization extends Kustomization with conditional logic support.

func (*ConditionalKustomization) DeepCopy added in v0.8.0

DeepCopy creates a deep copy of the ConditionalKustomization object.

type ConditionalTerraformComponent added in v0.8.0

type ConditionalTerraformComponent struct {
	TerraformComponent `yaml:",inline"`

	// When is an expression (expr-lang/expr) that determines if this terraform
	// component should be applied. If empty, the component is always applied
	// when the parent facet matches.
	When string `yaml:"when,omitempty"`

	// Strategy determines how this component is merged into the blueprint.
	// Valid values are "merge" (default), "replace", and "remove".
	// If empty or "merge", the component is merged with existing components matching the same Path and Source.
	// If "replace", the component completely replaces any existing component with the same Path and Source.
	// If "remove", the component's non-index fields (everything except Path and Source) are removed from the
	// matching existing component. Remove operations are always applied last after all merge/replace operations.
	Strategy string `yaml:"strategy,omitempty"`

	// Ordinal overrides the facet ordinal for this component's merge precedence. When nil, the facet's ordinal is used.
	// Higher ordinal means higher precedence when merging (processed later, wins on conflict).
	Ordinal *int `yaml:"ordinal,omitempty"`

	// Requires lists requirement blocks scoped to this terraform component. Evaluated only when the
	// parent facet is active and this component's When holds; missing paths are aggregated under the
	// effective condition (facet.When && component.When && block.When).
	Requires []RequirementBlock `yaml:"requires,omitempty"`
}

ConditionalTerraformComponent extends TerraformComponent with conditional logic support.

func (*ConditionalTerraformComponent) DeepCopy added in v0.8.0

DeepCopy creates a deep copy of the ConditionalTerraformComponent object.

type Config

type Config struct {
	Version      string               `yaml:"version"`
	ToolsManager string               `yaml:"toolsManager,omitempty"`
	Terraform    *RootTerraformConfig `yaml:"terraform,omitempty"`
	Contexts     map[string]*Context  `yaml:"contexts"`
}

Config represents the entire configuration

type ConfigBlock added in v0.9.0

type ConfigBlock struct {
	// Name identifies the block; exposed at scope root.
	Name string `yaml:"name"`
	// When is an expression that determines if this config block is evaluated; if empty, always evaluated when facet is active.
	When string `yaml:"when,omitempty"`
	// Strategy determines how this block is merged with blocks of the same name from other facets.
	// Valid values are "merge" (default), "replace", and "remove". If "merge", the block is deep-merged.
	// If "replace", the block replaces any existing block with the same name. If "remove", the block is removed from scope.
	Strategy string `yaml:"strategy,omitempty"`
	// Ordinal overrides the facet ordinal for this block's merge precedence. When nil, the facet's ordinal is used.
	// Higher ordinal means higher precedence when merging (wins on conflict).
	Ordinal *int `yaml:"ordinal,omitempty"`
	// Requires lists requirement blocks scoped to this config block. When the parent facet is active and this
	// block's optional When holds, every block in Requires is evaluated under the AND of facet.When,
	// block.When, and each Requires entry's own When. Missing paths are aggregated alongside facet- and
	// component-level misses in the user-facing error.
	Requires []RequirementBlock `yaml:"requires,omitempty"`
	// Body holds the canonical content as map[string]any{"value": <content>} for merge and evaluation. Not YAML-marshaled directly.
	Body map[string]any `yaml:"-"`
}

ConfigBlock represents a named, optionally conditional configuration block in a facet. Only name, when, value, strategy, and ordinal are allowed; value is required and may be a scalar, list, or map. The block is exposed at scope root: expressions use <name> for scalar/list values, or <name>.<key> when value is a map. References from terraform.inputs and kustomize.substitutions use the block name (e.g. talos, platform).

func (*ConfigBlock) DeepCopy added in v0.9.0

func (c *ConfigBlock) DeepCopy() *ConfigBlock

DeepCopy creates a deep copy of the ConfigBlock object.

func (*ConfigBlock) MarshalYAML added in v0.9.0

func (c *ConfigBlock) MarshalYAML() (any, error)

MarshalYAML implements custom marshaling. Only name, when, value, strategy, and ordinal are written.

func (*ConfigBlock) UnmarshalYAML added in v0.9.0

func (c *ConfigBlock) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements custom unmarshaling. Only name, when, value, strategy, and ordinal are read; value is required. Body is set to {"value": raw["value"]} for merge and evaluation.

type Context

type Context struct {
	ID          *string                    `yaml:"id,omitempty"`
	Platform    *string                    `yaml:"platform,omitempty"`
	Provider    *string                    `yaml:"provider,omitempty"`
	Environment map[string]string          `yaml:"environment,omitempty"`
	Secrets     *secrets.SecretsConfig     `yaml:"secrets,omitempty"`
	AWS         *aws.AWSConfig             `yaml:"aws,omitempty"`
	Azure       *azure.AzureConfig         `yaml:"azure,omitempty"`
	GCP         *gcp.GCPConfig             `yaml:"gcp,omitempty"`
	VSphere     *vsphere.VSphereConfig     `yaml:"vsphere,omitempty"`
	Docker      *docker.DockerConfig       `yaml:"docker,omitempty"`
	Git         *git.GitConfig             `yaml:"git,omitempty"`
	Terraform   *terraform.TerraformConfig `yaml:"terraform,omitempty"`
	VM          *vm.VMConfig               `yaml:"vm,omitempty"`
	Cluster     *cluster.ClusterConfig     `yaml:"cluster,omitempty"`
	Network     *network.NetworkConfig     `yaml:"network,omitempty"`
	DNS         *dns.DNSConfig             `yaml:"dns,omitempty"`
}

Context represents the context configuration.

func (*Context) DeepCopy

func (c *Context) DeepCopy() *Context

DeepCopy creates a deep copy of the Context object

func (*Context) Merge

func (base *Context) Merge(overlay *Context)

Merge performs a deep merge of the current Context with another Context.

type Decryption added in v0.9.0

type Decryption struct {
	// Provider is the decryption backend, e.g. "sops".
	Provider string `yaml:"provider,omitempty"`

	// SecretRef names the in-cluster Secret holding the decryption key.
	SecretRef *DecryptionSecretRef `yaml:"secretRef,omitempty"`
}

Decryption configures in-cluster decryption of a Kustomization's manifests, mapping to Flux's spec.decryption. When set, kustomize-controller decrypts encrypted files in the source with the referenced key Secret during reconciliation; leaving it nil keeps Flux's default of no decryption.

func (*Decryption) DeepCopy added in v0.9.0

func (d *Decryption) DeepCopy() *Decryption

DeepCopy returns a deep copy of the Decryption, sharing no pointer with the original.

type DecryptionSecretRef added in v0.9.0

type DecryptionSecretRef struct {
	// Name is the Secret's name.
	Name string `yaml:"name,omitempty"`
}

DecryptionSecretRef names the Secret that holds the decryption key material, resolved in the Kustomization's own namespace.

type DurationString added in v0.9.0

type DurationString struct {
	Duration time.Duration
}

DurationString represents a duration that marshals/unmarshals as a string (e.g., "5m"). It can be converted to metav1.Duration for use with Kubernetes APIs.

func FromMetaV1Duration added in v0.9.0

func FromMetaV1Duration(d *metav1.Duration) *DurationString

FromMetaV1Duration creates a DurationString from *metav1.Duration.

func (*DurationString) MarshalYAML added in v0.9.0

func (d *DurationString) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler to write duration as a string.

func (*DurationString) ToMetaV1Duration added in v0.9.0

func (d *DurationString) ToMetaV1Duration() *metav1.Duration

ToMetaV1Duration converts DurationString to *metav1.Duration.

func (*DurationString) UnmarshalYAML added in v0.9.0

func (d *DurationString) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml.Unmarshaler to read duration from a string or object.

type Facet added in v0.9.0

type Facet struct {
	// Kind is the facet type, following Kubernetes conventions.
	Kind string `yaml:"kind"`

	// ApiVersion is the API schema version of the facet.
	ApiVersion string `yaml:"apiVersion"`

	// Metadata includes the facet's name and description.
	Metadata Metadata `yaml:"metadata"`

	// Path is the file path where this facet was loaded from.
	// This is used for resolving relative paths in jsonnet() and file() functions.
	Path string `yaml:"-"`

	// Source names the blueprint source this facet came from. Set transiently during composition so a
	// globally-resolved facet can be emitted back into its own source's blueprint; never serialized.
	Source string `yaml:"-"`

	// Ordinal guides the order in which this facet is applied relative to others. Higher ordinal means higher precedence when merging.
	// When nil, the loader derives ordinal from the facet file basename (e.g. config-* 100, provider-base/platform-base 199, provider-/platform- 200, options- 300, addon-/addons- 400).
	Ordinal *int `yaml:"ordinal,omitempty"`

	// When is an expression that determines if this facet should be applied.
	// The expression is evaluated against user configuration values via the
	// expr-lang/expr library (NOT Google's CEL).
	// Examples: "platform == 'aws'", "observability.enabled == true && observability.backend == 'quickwit'"
	When string `yaml:"when,omitempty"`

	// Backend contributes Blueprint.Backend; the composer merges by ordinal precedence.
	Backend string `yaml:"backend,omitempty"`

	// Config is a list of named configuration blocks evaluated in blueprint context and exposed at scope root.
	// Terraform inputs and kustomize substitutions reference <name>.<key> (e.g. talos.controlplanes), like context (cluster.*, network.*).
	Config []ConfigBlock `yaml:"config,omitempty"`

	// Requires lists input requirement blocks. When the facet is active and a block's optional When holds,
	// every path must resolve to a present, non-empty value in the merged scope. Unsatisfied paths across
	// every active facet are aggregated into a single user-facing error.
	Requires []RequirementBlock `yaml:"requires,omitempty"`

	// TerraformComponents are Terraform modules in the facet.
	TerraformComponents []ConditionalTerraformComponent `yaml:"terraform,omitempty"`

	// Kustomizations are kustomization configs in the facet.
	Kustomizations []ConditionalKustomization `yaml:"kustomize,omitempty"`

	// FluxSystems are system entries (the flux: collection) contributed by this facet; each compiles
	// to an install plus resources-variant Kustomizations.
	FluxSystems []FluxSystem `yaml:"flux,omitempty"`

	// Crds lists references into the vendored CRD catalog (e.g. "cert-manager-1.16.2").
	// The composer emits one deduped kustomization per reference at kustomize/crds/<ref>
	// and makes every kustomization in this facet depend on it.
	Crds []string `yaml:"crds,omitempty"`

	// Substitutions are top-level key/value pairs evaluated with facet scope and injected into
	// values-common, making them available to all kustomizations via PostBuild substitution.
	// Values may use expression syntax (e.g. "${dns.domain}") resolved against facet config blocks.
	Substitutions map[string]string `yaml:"substitutions,omitempty"`

	// Messages are operator-facing notes rendered at the end of a bootstrap/apply run. Unlike a
	// requires: message (failure path, pre-flight, verbatim), a post-run message is on the success
	// path, rendered after apply, and interpolated against composed scope — so its text can carry
	// run values (e.g. terraform_output). Each entry's optional When gates it; text is the message.
	Messages []Message `yaml:"messages,omitempty"`
}

Facet represents a conditional blueprint fragment that can be merged into a base blueprint. Facets enable modular composition of blueprints based on user configuration values. Facets inherit Repository and Sources from the base blueprint they are merged into.

func (*Facet) DeepCopy added in v0.9.0

func (f *Facet) DeepCopy() *Facet

DeepCopy creates a deep copy of the Facet object.

type FluxSystem added in v0.9.0

type FluxSystem struct {
	// Name identifies the system; tiers compile to "<name>-install" / "<name>-resources[-<variant>]".
	Name string `yaml:"name"`

	// Path is the base; tiers reconcile from "<path>/install" and "<path>/resources". Defaults to Name.
	Path string `yaml:"path,omitempty"`

	// Source is the blueprint source that provides the tier bases.
	Source string `yaml:"source,omitempty"`

	// Enabled includes or excludes the whole system. Defaults to true.
	Enabled *BoolExpression `yaml:"enabled,omitempty"`

	// Destroy governs whether the system's kustomizations are removed on teardown. Defaults to true.
	Destroy *BoolExpression `yaml:"destroy,omitempty"`

	// When gates the system; combined (AND) with each resources variant's own condition.
	When string `yaml:"when,omitempty"`

	// DependsOn are cross-layer edges to other systems, attached to the install tier when present
	// (resources reach them transitively) or to each resources variant otherwise. It never names the
	// intra-system install edge — that edge is implicit.
	DependsOn []string `yaml:"dependsOn,omitempty"`

	// Strategy governs how a system with this Name merges across facets (merge | replace | remove).
	Strategy string `yaml:"strategy,omitempty"`

	// Ordinal overrides the facet's ordinal for this system's merge precedence.
	Ordinal *int `yaml:"ordinal,omitempty"`

	// GlobalDependency inverts the system's edges: when true, every kustomization and system outside
	// this system's own dependency closure is wired to depend on its terminal tier — its resources tier
	// if it has one, else its install tier. It lets a cluster-wide precondition (e.g. admission policies
	// that must be enforcing before any workload lands) be declared once here rather than repeated as a
	// dependsOn on every consumer. The closure exclusion keeps the system, and anything it depends on,
	// from ordering after itself.
	GlobalDependency bool `yaml:"globalDependency,omitempty"`

	// Install is the controller/operator tier (at most one). Its Components/Substitute and operational
	// fields flow to "<name>-install"; its Name/Path/DependsOn are derived by the composer.
	Install *Kustomization `yaml:"install,omitempty"`

	// Resources are the custom-resource tier variants, all sharing "<path>/resources".
	Resources []FluxVariant `yaml:"resources,omitempty"`

	// Secrets declares Kubernetes Secrets for this system, keyed by Secret name; each entry carries the
	// Secret's data (data key -> reference to a schema property marked `sensitive: true`) and, optionally,
	// the namespaces to place it into. Unlike Substitute (plaintext ConfigMap material), Secrets back real
	// Secrets placed into the system's namespace(s) and are resolved and materialized separately — their
	// values are never rendered or written in plaintext.
	Secrets map[string]SecretEntry `yaml:"secrets,omitempty"`
}

FluxSystem is a system entry under a blueprint or facet's `flux:` list — a functional layer that compiles to an install Kustomization plus zero or more resources-variant Kustomizations. The descriptor carries identity, lifecycle, and merge fields; the Install/Resources tiers reuse the Kustomization type and carry the Flux operational properties per tier. It holds no operational properties itself — those belong on the tiers that produce Kustomization objects.

func (*FluxSystem) DeepCopy added in v0.9.0

func (s *FluxSystem) DeepCopy() *FluxSystem

DeepCopy returns a deep copy of the FluxSystem, including its Install tier and Resources variants (each deep-copied via Kustomization.DeepCopy/FluxVariant.DeepCopy).

func (FluxSystem) TierNames added in v0.9.0

func (sys FluxSystem) TierNames() []string

TierNames returns the compiled Kustomization names this system produces (its install tier, if any, followed by each resources variant), in compiled order.

type FluxVariant added in v0.9.0

type FluxVariant struct {
	Kustomization `yaml:",inline"`

	// When gates this variant; combined (AND) with the system's own condition.
	When string `yaml:"when,omitempty"`
}

FluxVariant is one resources-tier Kustomization of a system. It reuses Kustomization for its components, substitutions, and operational properties; the authored `name` becomes the variant suffix ("<system>-resources-<name>") and `dependsOn` is appended to the implicit install edge.

func MergeFluxVariants added in v0.9.0

func MergeFluxVariants(existing, overlay []FluxVariant) []FluxVariant

MergeFluxVariants combines two resources-variant lists keyed by variant name. A variant from overlay deep-merges into the same-named variant in existing via MergeKustomizationFields (see MergeFluxInstall for why by-name Blueprint.Kustomizations matching isn't used instead), and the two When conditions combine with AND. A variant with a new name is appended in order. This keeps a cross-facet or cross-source merge from emitting two Kustomizations with the same "<system>-resources[-<name>]" identity.

func (*FluxVariant) DeepCopy added in v0.9.0

func (v *FluxVariant) DeepCopy() *FluxVariant

DeepCopy returns a deep copy of the FluxVariant, including its embedded Kustomization.

type IntExpression added in v0.9.0

type IntExpression struct {
	Value  *int
	Expr   string
	IsExpr bool
}

IntExpression represents an integer value that can be unmarshaled from an integer or a string expression. String expressions are preserved for later evaluation during facet processing.

func (*IntExpression) DeepCopy added in v0.9.0

func (i *IntExpression) DeepCopy() *IntExpression

DeepCopy creates a deep copy of the IntExpression.

func (*IntExpression) MarshalYAML added in v0.9.0

func (i *IntExpression) MarshalYAML() (any, error)

MarshalYAML implements yaml.Marshaler to write integer as an int or expression string.

func (*IntExpression) ToInt added in v0.9.0

func (i *IntExpression) ToInt() *int

ToInt returns the integer value, or nil if it's an expression.

func (*IntExpression) UnmarshalYAML added in v0.9.0

func (i *IntExpression) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML implements yaml.Unmarshaler to read integer from an int or string expression.

type Kustomization

type Kustomization struct {
	// Name of the kustomization. Omitted when empty so an unnamed inline flux resources variant
	// (a Kustomization embedded in FluxVariant) does not emit a blank name: into the composed output.
	Name string `yaml:"name,omitempty"`

	// Path of the kustomization. Defaults to Name.
	Path string `yaml:"path,omitempty"`

	// Source of the kustomization.
	Source string `yaml:"source,omitempty"`

	// Namespace overrides the namespace where the Flux Kustomization object itself lives.
	// When unset, the gitops namespace is used. DependsOn references always resolve in the
	// gitops namespace, so cross-namespace dependencies are not currently supported.
	Namespace string `yaml:"namespace,omitempty"`

	// TargetNamespace populates spec.targetNamespace, instructing Flux to override the
	// namespace of every resource reconciled by this kustomization.
	TargetNamespace string `yaml:"targetNamespace,omitempty"`

	// DependsOn lists dependencies of this kustomization.
	DependsOn []string `yaml:"dependsOn,omitempty"`

	// Interval for applying the kustomization.
	Interval *DurationString `yaml:"interval,omitempty"`

	// RetryInterval before retrying a failed kustomization.
	RetryInterval *DurationString `yaml:"retryInterval,omitempty"`

	// Timeout for the kustomization to complete.
	Timeout *DurationString `yaml:"timeout,omitempty"`

	// Patches to apply to the kustomization.
	Patches []BlueprintPatch `yaml:"patches,omitempty"`

	// Wait for the kustomization to be fully applied.
	Wait *bool `yaml:"wait,omitempty"`

	// Force apply the kustomization.
	Force *bool `yaml:"force,omitempty"`

	// Prune enables garbage collection of resources that are no longer present in the source.
	Prune *bool `yaml:"prune,omitempty"`

	// Components to include in the kustomization.
	Components []string `yaml:"components,omitempty"`

	// Destroy determines if the kustomization should be destroyed during down operations.
	// Defaults to true if not specified.
	// Supports expressions in facets: use "${cluster.destroy ?? true}" for dynamic values.
	Destroy *BoolExpression `yaml:"destroy,omitempty"`

	// DestroyOnly indicates that this kustomization should only run during destroy operations.
	// When true, the kustomization is skipped during apply/up operations and only executed during destroy.
	// Destroy-only kustomizations run before regular kustomizations during destroy, in normal dependency order.
	DestroyOnly *bool `yaml:"destroyOnly,omitempty"`

	// Enabled determines if the kustomization should be included in the final blueprint.
	// Defaults to true if not specified.
	// Supports expressions in facets: use "${some.condition ?? true}" for dynamic values.
	Enabled *BoolExpression `yaml:"enabled,omitempty"`

	// Substitutions contains values for post-build variable replacement,
	// collected and stored in ConfigMaps for use by Flux postBuild substitution.
	// All values are converted to strings as required by Flux variable substitution.
	// These are used for generating ConfigMaps and are not written to the final context blueprint.yaml.
	Substitutions map[string]string `yaml:"substitutions,omitempty"`

	// Substitute is the preferred spelling of Substitutions; both keys merge into Substitutions
	// during composition. It exists so `flux:` system tiers and `kustomize:` entries can spell
	// postBuild substitutions the same short way (matching Flux's `postBuild.substitute`).
	Substitute map[string]string `yaml:"substitute,omitempty"`

	// Secrets carries a flux system's Secrets onto its compiled namespace-owning tier so the imperative
	// placement step can find them after flattening: Secret name -> SecretEntry (target namespaces plus
	// data), resolved JIT at placement, never during composition. It is yaml:"-" so it is never
	// marshaled into show/apply output or the written blueprint, keeping secret material out of every
	// serialized surface by construction.
	Secrets map[string]SecretEntry `yaml:"-"`

	// Decryption configures in-cluster decryption for this kustomization's manifests, mapping to Flux's
	// spec.decryption. Nil leaves decryption unset (Flux default: no decryption).
	Decryption *Decryption `yaml:"decryption,omitempty"`
}

Kustomization represents a kustomization configuration.

func MergeFluxInstall added in v0.9.0

func MergeFluxInstall(existing, overlay *Kustomization) *Kustomization

MergeFluxInstall deep-merges overlay's Install tier into existing's via MergeKustomizationFields (Components/DependsOn accumulate, other fields are overridden by overlay when set) rather than via by-name Blueprint.Kustomizations matching, since Install carries no Name until tier compilation and that by-name path is a no-op on an unnamed Kustomization. Either side being nil just takes the other, matching how a facet or source with no Install opinion shouldn't erase one contributed elsewhere.

func MergeKustomizationFields added in v0.9.0

func MergeKustomizationFields(base, overlay Kustomization) Kustomization

MergeKustomizationFields deep-merges overlay onto base and returns the result without mutating either input: Components and DependsOn accumulate (deduplicated, Components sorted), Patches accumulate, Substitutions copy in, and every other field is overridden by overlay when overlay sets it. Callers that need by-name matching within a Blueprint's Kustomizations list use strategicMergeKustomization, which calls this once a match is found; callers merging two already-matched Kustomization values directly (e.g. FluxSystem tiers, which carry no Name until tier compilation) call this directly.

func (*Kustomization) DeepCopy added in v0.6.0

func (k *Kustomization) DeepCopy() *Kustomization

DeepCopy creates a deep copy of the Kustomization object.

func (*Kustomization) ToFluxKustomization added in v0.8.0

func (k *Kustomization) ToFluxKustomization(namespace string, defaultSourceName string, sources []Source, mode constants.GitopsMode, configMaps ...map[string]map[string]string) kustomizev1.Kustomization

ToFluxKustomization converts a blueprint Kustomization to a Flux Kustomization. It takes the default namespace for the kustomization (overridden per-kustomization by k.Namespace when set), the default source name to use if no source is specified, and the list of sources to determine the source kind (GitRepository or OCIRepository). A Path-less k defaults to k.Name, matching FluxSystem's own path-defaulting. k.TargetNamespace is passed through to spec.targetNamespace so Flux rewrites the namespace of every reconciled resource. DependsOn references are always resolved in the default namespace. The default Interval depends on whether k resolves to the blueprint's own repository or a named vendor source (see constants.FluxKustomizationInterval); mode is accepted for call-site stability but no longer affects it. A blueprint-level Interval override always wins. An optional configMaps argument (blueprint-level ConfigMaps such as values-common) is added to postBuild.substituteFrom so they are available to all kustomizations, matching what the provisioner applies. PostBuild is constructed from the kustomization's Substitutions field, except for the synthesized CRD layers (IsCrdLayerName(k.Name)), which skip PostBuild entirely: vendored CRDs need no substitution and their ${...} description text would otherwise fail envsubst (e.g. fluent-operator's ${record.to_json}).

type Message added in v0.9.0

type Message struct {
	// When is an optional expression gating whether this message renders. Empty means always.
	When string `yaml:"when,omitempty"`

	// Text is the message body. It is expression-evaluated against composed scope, so it may
	// reference config values and run outputs (e.g. "${terraform_output('dns-zone', 'nameservers')}").
	Text string `yaml:"text"`
}

Message is an operator-facing note a facet emits at the end of a run. When gates whether it renders; Text is the message body, evaluated against composed scope so it can interpolate run values.

type Metadata

type Metadata struct {
	// Name is the blueprint's unique identifier.
	Name string `yaml:"name"`

	// Description is a brief overview of the blueprint.
	Description string `yaml:"description,omitempty"`
}

Metadata describes a blueprint.

type PostBuild added in v0.4.0

type PostBuild struct {
	// Substitute is a map of resources to substitute from.
	Substitute map[string]string `yaml:"substitute,omitempty"`

	// SubstituteFrom is a list of resources to substitute from.
	SubstituteFrom []SubstituteReference `yaml:"substituteFrom,omitempty"`
}

PostBuild is a post-build step to run after the kustomization is applied.

type Reference

type Reference struct {
	// Branch to use.
	Branch string `yaml:"branch,omitempty"`

	// Tag to use.
	Tag string `yaml:"tag,omitempty"`

	// SemVer to use.
	SemVer string `yaml:"semver,omitempty"`

	// Name of the reference.
	Name string `yaml:"name,omitempty"`

	// Commit hash to use.
	Commit string `yaml:"commit,omitempty"`
}

Reference details a specific version or state of a repository or source.

type Repository

type Repository struct {
	// Url is the repository location.
	Url string `yaml:"url,omitempty"`

	// Ref details the branch, tag, or commit to use.
	Ref Reference `yaml:"ref,omitempty"`

	// SecretName is the secret for repository access.
	SecretName *string `yaml:"secretName,omitempty"`
}

Repository contains source code repository info.

type RequirementBlock added in v0.9.0

type RequirementBlock struct {
	// When is an expression gating this block. Empty means always required while the parent facet is active.
	When string `yaml:"when,omitempty"`

	// Paths are dotted scope keys whose values must be present and non-empty.
	Paths []string `yaml:"paths"`

	// Message is optional author-supplied context surfaced under this block's heading in the aggregated error.
	Message string `yaml:"message,omitempty"`
}

RequirementBlock declares a set of scope paths that must resolve to present, non-empty values for the parent facet's activation to be well-formed. When is optional and gates the block; if empty, the paths are required whenever the parent facet is active. Message is optional context surfaced in the aggregated error alongside the missing paths.

func (*RequirementBlock) DeepCopy added in v0.9.0

func (r *RequirementBlock) DeepCopy() *RequirementBlock

DeepCopy creates a deep copy of the RequirementBlock object.

func (*RequirementBlock) UnmarshalYAML added in v0.9.0

func (r *RequirementBlock) UnmarshalYAML(unmarshal func(any) error) error

UnmarshalYAML enforces that paths is present and non-empty. A block with no paths would silently disable requirement checking and defeat the feature's purpose, so the most likely cause (a typo like `pahts:`) is surfaced as a parse-time error instead of a downstream surprise.

type RootTerraformConfig added in v0.9.0

type RootTerraformConfig struct {
	Driver string `yaml:"driver,omitempty"`
}

RootTerraformConfig represents the root-level terraform configuration

type SecretEntry added in v0.9.0

type SecretEntry struct {
	// Namespaces are the namespaces to place this Secret into. Empty means auto-resolve the single
	// namespace the owning kustomization creates; each named namespace must be one that kustomization
	// provably created.
	Namespaces []string `yaml:"namespaces,omitempty"`

	// Data is the Secret's contents: data key -> reference to a schema property, resolved JIT at
	// placement and never rendered in plaintext. Materializes as an Opaque Secret by default; a
	// ".dockerconfigjson" key, or "docker-username" plus "docker-password" (optional
	// "docker-server", defaulting to "ghcr.io"), materializes as kubernetes.io/dockerconfigjson
	// instead, for use as an imagePullSecret — see ApplySecret/secretTypeAndData.
	Data map[string]string `yaml:"data,omitempty"`
}

SecretEntry is one `secrets:` entry on a flux system tier: the data that backs a Kubernetes Secret plus the namespaces it is placed into. Namespaces is optional — when omitted the target auto-resolves to the single namespace the owning kustomization creates (unchanged from the original behavior); when set it names the target(s) explicitly, so a system that owns more than one namespace (e.g. pki, which owns system-pki and system-pki-trust) can place a secret and a single entry can fan out to several namespaces. It is a plain struct decoded directly by the YAML decoder — data lives under `data:` so a data key can never collide with the `namespaces:` selector.

func (SecretEntry) DeepCopy added in v0.9.0

func (s SecretEntry) DeepCopy() SecretEntry

DeepCopy returns a deep copy of the SecretEntry, sharing no slice or map with the original.

type Source

type Source struct {
	// Name identifies the source.
	Name string `yaml:"name"`

	// Url is the source location.
	Url string `yaml:"url,omitempty"`

	// PathPrefix is a prefix to the source path.
	PathPrefix string `yaml:"pathPrefix,omitempty"`

	// Ref details the branch, tag, or commit to use.
	Ref Reference `yaml:"ref,omitempty"`

	// SecretName is the secret for source access.
	SecretName string `yaml:"secretName,omitempty"`

	// Install determines if the source should be merged (components merged into final blueprint).
	// Defaults to false if not specified.
	// Supports expressions in facets: use "${some.condition ?? true}" for dynamic values.
	Install *BoolExpression `yaml:"install,omitempty"`

	// Crds is the flat list of CRD references this source vendors at <source>/kustomize/crds/<ref>.
	// Populated by the composer from the source's included facets. When the source is install:true,
	// the provisioner materializes these into a background "crds-<name>" kustomization bound to this
	// source, so its CRDs install ahead of the stack without the blueprint author listing them.
	Crds []string `yaml:"crds,omitempty"`
}

Source is an external resource referenced by a blueprint.

type SubstituteReference added in v0.4.0

type SubstituteReference struct {
	// Kind of the resource to substitute from.
	Kind string `yaml:"kind"`

	// Name of the resource to substitute from.
	Name string `yaml:"name"`

	// Optional indicates if the resource is optional.
	Optional bool `yaml:"optional,omitempty"`
}

SubstituteReference is a reference to a resource to substitute from.

type TerraformComponent

type TerraformComponent struct {
	// Name of the terraform component. If provided, this becomes the unique identifier
	// instead of Path. Used for referencing in dependencies and context variables.
	Name string `yaml:"name,omitempty"`

	// Source of the Terraform module.
	Source string `yaml:"source,omitempty"`

	// Path of the Terraform module.
	Path string `yaml:"path"`

	// FullPath is the complete path, not serialized to YAML.
	FullPath string `yaml:"-"`

	// DependsOn lists dependencies of this terraform component.
	DependsOn []string `yaml:"dependsOn,omitempty"`

	// Inputs are configuration values for the module.
	// These values can be expressions using ${} syntax (e.g., "${cluster.name}") or literals.
	// Values with ${} are evaluated as expressions, plain values are passed through as literals.
	// These are used for generating tfvars files and are not written to the final context blueprint.yaml.
	Inputs map[string]any `yaml:"inputs,omitempty"`

	// Destroy determines if the component should be destroyed during down operations.
	// Defaults to true if not specified.
	// Supports expressions in facets: use "${cluster.destroy ?? true}" for dynamic values.
	Destroy *BoolExpression `yaml:"destroy,omitempty"`

	// Parallelism limits the number of concurrent operations as Terraform walks the graph.
	// This corresponds to the -parallelism flag in terraform apply/destroy commands.
	// Supports expressions in facets: use "${cluster.parallelism ?? 10}" for dynamic values.
	Parallelism *IntExpression `yaml:"parallelism,omitempty"`

	// Enabled determines if the component should be included in the final blueprint.
	// Defaults to true if not specified.
	// Supports expressions in facets: use "${some.condition ?? true}" for dynamic values.
	Enabled *BoolExpression `yaml:"enabled,omitempty"`

	// InputOrigins maps each input key to the facet file path that defined it.
	// Used internally for resolving relative paths in deferred expression evaluation.
	InputOrigins map[string]string `yaml:"-"`
}

TerraformComponent defines a Terraform module in a blueprint.

func (*TerraformComponent) DeepCopy added in v0.8.0

func (t *TerraformComponent) DeepCopy() *TerraformComponent

DeepCopy creates a deep copy of the TerraformComponent object.

func (*TerraformComponent) GetID added in v0.9.0

func (t *TerraformComponent) GetID() string

GetID returns the unique identifier for this terraform component. If Name is provided, it returns Name; otherwise, it returns Path.

type TestCase added in v0.9.0

type TestCase struct {
	// Name is the unique identifier for this test case.
	Name string `yaml:"name"`

	// Values are configuration values to apply before composing the blueprint.
	// These override any existing configuration for the test.
	Values map[string]any `yaml:"values,omitempty"`

	// Env provides environment variables visible to env() expressions during composition.
	// Resolution is hermetic: env() sees only these entries, never the host environment.
	Env map[string]string `yaml:"env,omitempty"`

	// TerraformOutputs provides mock terraform outputs for terraform_output() expressions.
	// Keys are component IDs, values are maps of output key-value pairs.
	// Example: {"network": {"vpc_id": "vpc-123", "subnet_ids": ["subnet-1", "subnet-2"]}}
	TerraformOutputs map[string]map[string]any `yaml:"terraformOutputs,omitempty"`

	// Expect defines components that must be present in the composed blueprint.
	// Uses partial matching: only specified fields are checked.
	// Kind, ApiVersion, and Metadata are ignored for matching purposes.
	Expect *Blueprint `yaml:"expect,omitempty"`

	// Exclude defines components that must NOT be present in the composed blueprint.
	// Uses partial matching: only specified fields are checked.
	// Kind, ApiVersion, and Metadata are ignored for matching purposes.
	Exclude *Blueprint `yaml:"exclude,omitempty"`

	// ExpectError indicates that blueprint composition is expected to fail with an error.
	// If true, the test passes when composition fails and fails when composition succeeds.
	// This is useful for testing invalid configurations that should be rejected by the framework.
	ExpectError bool `yaml:"expectError,omitempty"`

	// ApplySchemaDefaults composes this case with schema `default:` values materialized, as
	// production does. The test path otherwise skips schema defaults so a facet is exercised on
	// its own defaulting logic; set this to validate a facet that relies on a schema default
	// (e.g. a read of network.cidr_block with no `?? <fallback>`). Off by default; other cases
	// are unaffected.
	ApplySchemaDefaults bool `yaml:"applySchemaDefaults,omitempty"`
}

TestCase represents a single test case with input values and expected output. Each test case applies the specified values to configuration and validates the resulting composed blueprint against expectations.

type TestFile added in v0.9.0

type TestFile struct {
	// Cases is a list of test cases to execute.
	Cases []TestCase `yaml:"cases"`
}

TestFile represents a test file containing multiple test cases for blueprint composition validation. Test files are stored in contexts/_template/tests/*.test.yaml and define input values along with expected and excluded blueprint components.

Directories

Path Synopsis

Jump to

Keyboard shortcuts

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