Documentation
¶
Overview ¶
Package blueprint provides blueprint loading, facet processing, composition, and writing for the Windsor CLI.
The config_block_order file orders config blocks for evaluation by their inter-block reference dependencies. The order built up by mergeFacetScopeIntoGlobal reflects facet processing order, which does not necessarily match evaluation order: a block that references another block must be evaluated after the block it references, regardless of which facet wrote which first. Topological sort of the block dependency graph produces an order where every block evaluates after the blocks it depends on.
The expr_helpers file provides shared expression AST utilities for the blueprint package. It provides parsing and walking of expr-lang expressions (${...}), dotted path extraction, and detection of derived-from-block references used for config merge semantics.
The ExplainResolver provides blueprint value provenance resolution for the windsor explain command. It resolves a dotted path against the composed blueprint and produces a trace showing the value and which facets contributed to it, enabling users to understand where values originate and how composition affected them.
The YAMLNodeResolver provides YAML AST utilities for resolving line numbers from facet files. It navigates goccy/go-yaml parsed trees to locate specific nodes by structural path (map key, named sequence item, sequence index, or entry value match), enabling precise provenance line number resolution during blueprint composition and explain.
Index ¶
- Variables
- func EvaluateWithOrigins(eval evaluator.ExpressionEvaluator, keyPath string, value any, ...) (any, error)
- func IsDowngrade(previousURL, targetURL string) bool
- func MergeScopeMaps(globalScope map[string]any, overlay map[string]any) map[string]any
- func OrdinalFromBasename(basename string) int
- func OrdinalFromFacetPath(path string) int
- func RenderForDisplay(resource any, raw bool, deferredPaths map[string]bool) any
- func ValidateComposedBlueprint(blueprint *blueprintv1alpha1.Blueprint) error
- type BaseBlueprintComposer
- func (c *BaseBlueprintComposer) Compose(loaders []BlueprintLoader, initLoaderNames []string, userBlueprintPath string, ...) (*blueprintv1alpha1.Blueprint, error)
- func (c *BaseBlueprintComposer) SetCommonSubstitutions(substitutions map[string]string)
- func (c *BaseBlueprintComposer) SetExcludedFacets(excluded []ExcludedFacet)
- type BaseBlueprintHandler
- func (h *BaseBlueprintHandler) Explain(pathStr string) (*ExplainTrace, error)
- func (h *BaseBlueprintHandler) Generate() *blueprintv1alpha1.Blueprint
- func (h *BaseBlueprintHandler) GenerateResolved() (*blueprintv1alpha1.Blueprint, error)
- func (h *BaseBlueprintHandler) GetDeclaredSources() ([]blueprintv1alpha1.Source, error)
- func (h *BaseBlueprintHandler) GetDeferredPaths() map[string]bool
- func (h *BaseBlueprintHandler) GetLocalTemplateData() (map[string][]byte, error)
- func (h *BaseBlueprintHandler) GetTerraformComponents() []blueprintv1alpha1.TerraformComponent
- func (h *BaseBlueprintHandler) LoadBlueprint(blueprintURL ...string) error
- func (h *BaseBlueprintHandler) RetargetSource(name, url string) (string, error)
- func (h *BaseBlueprintHandler) SetSkipValidation(skip bool)
- func (h *BaseBlueprintHandler) SetTraceCollector(tc TraceCollector)
- func (h *BaseBlueprintHandler) UpgradeSourcesToLatest() ([]SourceUpgrade, error)
- func (h *BaseBlueprintHandler) Write(overwrite ...bool) error
- type BaseBlueprintLoader
- func (l *BaseBlueprintLoader) GetBlueprint() *blueprintv1alpha1.Blueprint
- func (l *BaseBlueprintLoader) GetBlueprintPath() string
- func (l *BaseBlueprintLoader) GetFacets() []blueprintv1alpha1.Facet
- func (l *BaseBlueprintLoader) GetSourceName() string
- func (l *BaseBlueprintLoader) GetTemplateData() map[string][]byte
- func (l *BaseBlueprintLoader) Load(sourceName, sourceURL string) error
- type BaseBlueprintProcessor
- func (p *BaseBlueprintProcessor) GetDeferredPaths() map[string]bool
- func (p *BaseBlueprintProcessor) GetExcludedFacets() []ExcludedFacet
- func (p *BaseBlueprintProcessor) ProcessFacets(target *blueprintv1alpha1.Blueprint, facets []blueprintv1alpha1.Facet, ...) (map[string]any, error)
- func (p *BaseBlueprintProcessor) ProcessGlobally(sources []SourceFacetSet) (map[string]any, error)
- func (p *BaseBlueprintProcessor) ResetExcludedFacets()
- func (p *BaseBlueprintProcessor) SetExtraScope(scope map[string]any)
- func (p *BaseBlueprintProcessor) SetTraceCollector(tc TraceCollector)
- type BaseBlueprintWriter
- type BlueprintComposer
- type BlueprintHandler
- type BlueprintLoader
- type BlueprintProcessor
- type BlueprintWriter
- type ConfigBlockRecord
- type CrdInstallLayer
- type DefaultTraceCollector
- func (c *DefaultTraceCollector) Finalize(bp *blueprintv1alpha1.Blueprint, scope map[string]any, templateRoot string)
- func (c *DefaultTraceCollector) GetTrace(pathStr string) (*ExplainTrace, error)
- func (c *DefaultTraceCollector) RecordConfigBlock(configPath string, record ConfigBlockRecord)
- func (c *DefaultTraceCollector) RecordContribution(composedPath string, tc TraceContribution)
- type ExcludedFacet
- type ExplainContribution
- type ExplainPath
- type ExplainPathKind
- type ExplainScopeRef
- type ExplainTrace
- type MockBlueprintHandler
- func (m *MockBlueprintHandler) Explain(path string) (*ExplainTrace, error)
- func (m *MockBlueprintHandler) Generate() *blueprintv1alpha1.Blueprint
- func (m *MockBlueprintHandler) GenerateResolved() (*blueprintv1alpha1.Blueprint, error)
- func (m *MockBlueprintHandler) GetDeclaredSources() ([]blueprintv1alpha1.Source, error)
- func (m *MockBlueprintHandler) GetDeferredPaths() map[string]bool
- func (m *MockBlueprintHandler) GetLocalTemplateData() (map[string][]byte, error)
- func (m *MockBlueprintHandler) GetTerraformComponents() []blueprintv1alpha1.TerraformComponent
- func (m *MockBlueprintHandler) LoadBlueprint(blueprintURL ...string) error
- func (m *MockBlueprintHandler) RetargetSource(name, url string) (string, error)
- func (m *MockBlueprintHandler) SetSkipValidation(skip bool)
- func (m *MockBlueprintHandler) SkipValidation() bool
- func (m *MockBlueprintHandler) UpgradeSourcesToLatest() ([]SourceUpgrade, error)
- func (m *MockBlueprintHandler) Write(overwrite ...bool) error
- type RequirementsError
- type Shims
- type SourceFacetSet
- type SourceUpgrade
- type TraceCollector
- type TraceContribution
Constants ¶
This section is empty.
Variables ¶
var DefaultBlueprint = blueprintv1alpha1.Blueprint{ Kind: "Blueprint", ApiVersion: "blueprints.windsorcli.dev/v1alpha1", Metadata: blueprintv1alpha1.Metadata{ Name: "default", Description: "A default blueprint", }, Sources: []blueprintv1alpha1.Source{}, TerraformComponents: []blueprintv1alpha1.TerraformComponent{}, Kustomizations: []blueprintv1alpha1.Kustomization{}, }
DefaultBlueprint provides the base blueprint structure used when no blueprint exists.
var ErrBlueprintInvalid = errors.New("invalid blueprint")
ErrBlueprintInvalid is the sentinel returned by blueprint validation when the composed blueprint violates a structural invariant. Callers use errors.Is to detect this class of failure and present the wrapped message to the operator without scary "Error:" framing — the run is rejected, but the cause is a blueprint authoring mistake the operator can fix, not an internal exception.
Functions ¶
func EvaluateWithOrigins ¶ added in v0.9.0
func EvaluateWithOrigins(eval evaluator.ExpressionEvaluator, keyPath string, value any, origins map[string]string, scope map[string]any, evaluateDeferred bool) (any, error)
EvaluateWithOrigins evaluates a single input value using per-sub-key origin paths stored in origins (dot-separated keys such as "config.db.host"). When a direct origin exists for keyPath the entire value is evaluated against that path. When sub-key origins exist the value is walked recursively so each leaf resolves against its originating facet.
func IsDowngrade ¶ added in v0.9.0
IsDowngrade reports whether targetURL pins an older stable semver than previousURL for the same OCI repository. It returns false when either URL is not a parseable OCI reference, when the two reference different repositories (a re-source is not an ordered version change), or when either tag is not a semver (a branch, mutable tag, or commit is not ordered) — in those cases a regression cannot be asserted, so the caller must not treat the change as a downgrade.
func MergeScopeMaps ¶ added in v0.9.0
MergeScopeMaps deep-merges two scope maps (e.g. from multiple loaders or scope plus context values). When the same block name exists in both, block bodies are deep-merged recursively (maps by key, lists/scalars replaced at that path). Returns a new map; does not mutate inputs.
func OrdinalFromBasename ¶ added in v0.9.0
OrdinalFromBasename returns the default ordinal for a facet file given only its basename (e.g. "config-cluster.yaml", "provider-base.yaml"). Used by OrdinalFromFacetPath and by tests.
func OrdinalFromFacetPath ¶ added in v0.9.0
OrdinalFromFacetPath returns the default ordinal for a facet based on its file path. The basename of the path is used to match prefix rules. When the facet does not set ordinal explicitly, the loader uses this to assign a default so that facet processing order is deterministic (config first, then provider/platform base, then provider/platform, then options, then addons). Higher ordinal means higher precedence when merging. Rules: config-* 100; provider-* or platform-* with "-base" in name 199; provider-* or platform-* 200; option-* or options-* 300; addon-* or addons-* 400; no match 0.
func RenderForDisplay ¶ added in v0.9.0
RenderForDisplay returns a copy of resource ready for CLI output: composed-blueprint fields not meant for display (Messages, resolved separately by GenerateResolved for bootstrap/up to print) are cleared, and unless raw is true, deferred values named in deferredPaths are rewritten to a placeholder. Unsupported resource types pass through unchanged.
func ValidateComposedBlueprint ¶ added in v0.9.0
func ValidateComposedBlueprint(blueprint *blueprintv1alpha1.Blueprint) error
ValidateComposedBlueprint rejects composed blueprints whose Backend field names a component that does not exist. Nil and empty-Backend blueprints are accepted. Failures wrap ErrBlueprintInvalid.
Types ¶
type BaseBlueprintComposer ¶ added in v0.9.0
type BaseBlueprintComposer struct {
// contains filtered or unexported fields
}
BaseBlueprintComposer provides the default implementation of the BlueprintComposer interface.
func NewBlueprintComposer ¶ added in v0.9.0
func NewBlueprintComposer(rt *runtime.Runtime) *BaseBlueprintComposer
NewBlueprintComposer creates a new BlueprintComposer that merges multiple blueprints into one. The runtime provides access to configuration and context. Optional overrides allow setting common substitutions that will be applied to all kustomizations in the composed blueprint.
func (*BaseBlueprintComposer) Compose ¶ added in v0.9.0
func (c *BaseBlueprintComposer) Compose(loaders []BlueprintLoader, initLoaderNames []string, userBlueprintPath string, configScope map[string]any) (*blueprintv1alpha1.Blueprint, error)
Compose merges blueprints from multiple loaders into a single unified blueprint. Blueprints are merged in order: sources (in the order they appear in the user's Sources array, filtered by install:true) → user blueprint as final overlay. The actual merging of individual components and kustomizations is delegated to Blueprint.StrategicMerge. After merging, Compose ensures all source loaders' source names are present in the result's Sources array so components can resolve references (e.g. source: "core"). The "template" source is only included when the local template directory exists. Missing sources are added from the loader's blueprint or as minimal entries; for OCI loaders without a matching source entry, URL and Ref are taken from any OCI source in the loader's blueprint. When configScope is non-nil, it is used when evaluating user blueprint terraform inputs so config-block refs resolve.
func (*BaseBlueprintComposer) SetCommonSubstitutions ¶ added in v0.9.0
func (c *BaseBlueprintComposer) SetCommonSubstitutions(substitutions map[string]string)
SetCommonSubstitutions configures substitution values that will be added to all kustomizations during composition. These typically include context-wide values like cluster name, domain, or environment that should be available to every kustomization's postBuild substitution.
func (*BaseBlueprintComposer) SetExcludedFacets ¶ added in v0.9.0
func (c *BaseBlueprintComposer) SetExcludedFacets(excluded []ExcludedFacet)
SetExcludedFacets provides the facets dropped by a false when: during facet processing, so validateDependencies can attribute a dangling dependency to the excluded facet that would have provided it and name the condition that excluded it.
type BaseBlueprintHandler ¶
type BaseBlueprintHandler struct {
// contains filtered or unexported fields
}
BaseBlueprintHandler provides the default implementation of the BlueprintHandler interface. It orchestrates the pipeline: Load → Process → Compose → Write.
func NewBlueprintHandler ¶
func NewBlueprintHandler(rt *runtime.Runtime, artifactBuilder artifact.Artifact, opts ...*BaseBlueprintHandler) *BaseBlueprintHandler
NewBlueprintHandler creates a new BlueprintHandler with the provided runtime and artifact builder. It initializes the internal processor, composer, and writer components with sensible defaults. Optional overrides can be passed to replace any of the internal components for testing or custom behavior. Panics if runtime or artifactBuilder are nil.
func (*BaseBlueprintHandler) Explain ¶ added in v0.9.0
func (h *BaseBlueprintHandler) Explain(pathStr string) (*ExplainTrace, error)
Explain delegates to the trace collector if set, otherwise returns an error. The handler method exists only to satisfy the BlueprintHandler interface.
func (*BaseBlueprintHandler) Generate ¶
func (h *BaseBlueprintHandler) Generate() *blueprintv1alpha1.Blueprint
Generate returns the fully composed blueprint after all sources and user blueprint have been merged. This is a simple accessor method that returns the composedBlueprint field. The blueprint is already fully processed and composed by LoadBlueprint(). Input expressions and substitutions remain in their raw form and are evaluated later by their respective consumers.
func (*BaseBlueprintHandler) GenerateResolved ¶ added in v0.9.0
func (h *BaseBlueprintHandler) GenerateResolved() (*blueprintv1alpha1.Blueprint, error)
GenerateResolved returns a deep copy of the composed blueprint with deferred substitutions resolved. This is the JIT entry point for consumers that need fully evaluated values (e.g. the provisioner writing ConfigMaps to the cluster). The copy ensures the base composedBlueprint is never mutated, so subsequent Generate() or GenerateResolved() calls start from the original deferred expressions. Callers that only display the blueprint (e.g. windsor show) should use Generate() instead to preserve deferred placeholders.
Returns an error when a deferred substitution cannot be resolved (e.g. terraform_output() references a missing key, or terraform itself errors during the lookup), named by the offending substitution path (e.g. "kustomize.dns.substitutions.external_dns_tenant_id") so operators see the failure at blueprint-resolution time rather than via a downstream pod crashloop. An unresolved expression must never reach a ConfigMap: raw `${...}` source text left in place would be treated as a literal config value by downstream Helm renders.
func (*BaseBlueprintHandler) GetDeclaredSources ¶ added in v0.9.0
func (h *BaseBlueprintHandler) GetDeclaredSources() ([]blueprintv1alpha1.Source, error)
GetDeclaredSources loads only the context's blueprint.yaml (the user blueprint) and returns its declared sources, without loading remote source content or composing. It is the cheap pre-flight read upgrade uses to evaluate a --source change before pulling or composing anything, so a refused downgrade never triggers a registry round-trip. Returns an empty slice when no blueprint.yaml or no sources are declared.
func (*BaseBlueprintHandler) GetDeferredPaths ¶ added in v0.9.0
func (h *BaseBlueprintHandler) GetDeferredPaths() map[string]bool
GetDeferredPaths returns composed paths whose values were deferred during expression evaluation.
func (*BaseBlueprintHandler) GetLocalTemplateData ¶
func (h *BaseBlueprintHandler) GetLocalTemplateData() (map[string][]byte, error)
GetLocalTemplateData returns all files collected from the template blueprint's directory. This includes blueprint.yaml, schema.yaml, features, and any other template files. The data is used by the artifact builder when pushing local templates to an OCI registry. Returns nil if no template loader exists (e.g., when loading from OCI without a local _template).
func (*BaseBlueprintHandler) GetTerraformComponents ¶
func (h *BaseBlueprintHandler) GetTerraformComponents() []blueprintv1alpha1.TerraformComponent
GetTerraformComponents returns a copy of the composed blueprint's terraform components with Source and FullPath resolved for each component. Source names are expanded to full OCI or Git URLs based on the Sources array. Components with a Name or Source are placed in the Windsor scratch path (contexts/<context>/terraform/), while local components without a source are placed in the project's terraform directory.
func (*BaseBlueprintHandler) LoadBlueprint ¶
func (h *BaseBlueprintHandler) LoadBlueprint(blueprintURL ...string) error
LoadBlueprint orchestrates the complete blueprint loading pipeline. It loads the user blueprint first, then loads all sources from the user's sources array (including "name: template" for local _template). Sources are loaded recursively to discover nested sources. Finally, it processes facets for all source blueprints and composes them into a single unified blueprint, applying the user blueprint as the final override layer. The blueprintURL parameter stores URLs that should be added to sources during initialization. These URLs are loaded first so their metadata names can be used.
func (*BaseBlueprintHandler) RetargetSource ¶ added in v0.9.0
func (h *BaseBlueprintHandler) RetargetSource(name, url string) (string, error)
RetargetSource repoints an already-declared source to a new tagged OCI URL and returns the source's previous URL for diff reporting. The new URL must include a version tag, validated via OCI parsing; the tag is carried in the URL (the canonical source form), so any prior ref fields are cleared. It errors when the source name is not declared, since adding or removing a source is a structural edit to blueprint.yaml rather than a retarget. RetargetSource mutates the composed blueprint in memory only; call Write to persist.
func (*BaseBlueprintHandler) SetSkipValidation ¶ added in v0.9.0
func (h *BaseBlueprintHandler) SetSkipValidation(skip bool)
SetSkipValidation toggles structural-invariant validation in LoadBlueprint. Default is false (validate). Teardown commands (destroy, down, env) call this with true so an operator with a deployed-but-misordered blueprint can still tear down or inspect — without this escape hatch, the validator would block the only commands that could resolve the situation. Write/deploy commands (init, bootstrap, up, apply, plan) leave it false so structural mistakes surface at the moment they are introduced. (show tolerates validation failure via a separate mechanism in getBlueprint that captures the error and continues, rather than skipping validation outright.) Provisioner's destroy paths iterate components independent of blueprint position (Blueprint.BackendComponentID + symmetric-destroy), so skipping validation does not produce a wrong destroy order.
func (*BaseBlueprintHandler) SetTraceCollector ¶ added in v0.9.0
func (h *BaseBlueprintHandler) SetTraceCollector(tc TraceCollector)
SetTraceCollector enables opt-in trace collection for the explain command. When set, the collector is propagated to the processor at the start of composition so expression scope references and nested paths are recorded during facet processing. Pass nil to disable.
func (*BaseBlueprintHandler) UpgradeSourcesToLatest ¶ added in v0.9.0
func (h *BaseBlueprintHandler) UpgradeSourcesToLatest() ([]SourceUpgrade, error)
UpgradeSourcesToLatest moves each remote OCI source pinned to a semver to the highest stable tag this CLI is compatible with (see artifact.ResolveCompatibleTag), mutating the composed blueprint in memory (call Write to persist) and returning the changes for reporting. Sources that are not OCI, not semver-pinned, or already at the latest compatible tag are left untouched. All tags are resolved before any source is mutated, so a registry failure mid-resolution leaves the in-memory blueprint untouched.
func (*BaseBlueprintHandler) Write ¶
func (h *BaseBlueprintHandler) Write(overwrite ...bool) error
Write persists the blueprint to blueprint.yaml in the config root directory. It always writes the referential form (metadata, repository, sources only). If overwrite is true, an existing file is replaced; if false or omitted, the file is only written if it does not already exist, preserving user modifications.
type BaseBlueprintLoader ¶ added in v0.9.0
type BaseBlueprintLoader struct {
// contains filtered or unexported fields
}
BaseBlueprintLoader provides the default implementation of the BlueprintLoader interface.
func NewBlueprintLoader ¶ added in v0.9.0
func NewBlueprintLoader(rt *runtime.Runtime, artifactBuilder artifact.Artifact) *BaseBlueprintLoader
NewBlueprintLoader creates a new BlueprintLoader. The sourceName and sourceURL are provided when calling Load(), not during construction. The artifactBuilder is required for OCI sources but may be nil for local sources.
func (*BaseBlueprintLoader) GetBlueprint ¶ added in v0.9.0
func (l *BaseBlueprintLoader) GetBlueprint() *blueprintv1alpha1.Blueprint
GetBlueprint returns the loaded blueprint, which may be nil if loading failed or the source does not contain a blueprint. The blueprint is modified during facet processing as components from evaluated facets are appended to it.
func (*BaseBlueprintLoader) GetBlueprintPath ¶ added in v0.9.0
func (l *BaseBlueprintLoader) GetBlueprintPath() string
GetBlueprintPath returns the absolute path to the main blueprint file (e.g. blueprint.yaml) for this source. For the user blueprint this is the config root blueprint; for template/OCI sources it is empty. Used when resolving relative paths in expressions (e.g. yaml(), file()).
func (*BaseBlueprintLoader) GetFacets ¶ added in v0.9.0
func (l *BaseBlueprintLoader) GetFacets() []blueprintv1alpha1.Facet
GetFacets returns all Facet definitions loaded from this source's facets directory. Facets are YAML files in the facets/ subdirectory that define conditional terraform components and kustomizations. Returns an empty slice if no facets were found.
func (*BaseBlueprintLoader) GetSourceName ¶ added in v0.9.0
func (l *BaseBlueprintLoader) GetSourceName() string
GetSourceName returns the identifier for this loader, used in error messages and to track which source a blueprint came from during composition. Common values are "primary", "user", or the name specified in a blueprint's sources array.
func (*BaseBlueprintLoader) GetTemplateData ¶ added in v0.9.0
func (l *BaseBlueprintLoader) GetTemplateData() map[string][]byte
GetTemplateData returns a map of relative file paths to their contents for all files collected from this source. This data is used when building OCI artifacts from local templates, allowing the complete template to be pushed to a registry.
func (*BaseBlueprintLoader) Load ¶ added in v0.9.0
func (l *BaseBlueprintLoader) Load(sourceName, sourceURL string) error
Load loads the blueprint from the specified source. The sourceName identifies this loader (e.g., "user", "template", or a source name from the sources array). The sourceURL specifies an OCI artifact URL to pull; if empty, the loader will use local filesystem paths based on sourceName. For "user", it loads from config root. For other names, it loads from _template.
type BaseBlueprintProcessor ¶ added in v0.9.0
type BaseBlueprintProcessor struct {
// contains filtered or unexported fields
}
BaseBlueprintProcessor provides the default implementation of the BlueprintProcessor interface.
func NewBlueprintProcessor ¶ added in v0.9.0
func NewBlueprintProcessor(rt *runtime.Runtime) *BaseBlueprintProcessor
NewBlueprintProcessor creates a new BlueprintProcessor using the runtime's expression evaluator. The evaluator is used to evaluate 'when' conditions on facets and components. Optional overrides allow replacing the evaluator for testing. The processor is stateless and can be shared across multiple concurrent facet processing operations. The evaluator must be provided either via the runtime or as an override.
func (*BaseBlueprintProcessor) GetDeferredPaths ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) GetDeferredPaths() map[string]bool
GetDeferredPaths returns a copy of deferred composed paths discovered during the last ProcessFacets call.
func (*BaseBlueprintProcessor) GetExcludedFacets ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) GetExcludedFacets() []ExcludedFacet
GetExcludedFacets returns a copy of the facets excluded by a false when: across every ProcessFacets call since the last reset. Read after the per-source passes complete so the set is stable.
func (*BaseBlueprintProcessor) ProcessFacets ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) ProcessFacets(target *blueprintv1alpha1.Blueprint, facets []blueprintv1alpha1.Facet, sourceName ...string) (map[string]any, error)
ProcessFacets iterates facets, evaluating each facet's 'when' against config data. Facets with true (or unset) conditions contribute their terraform components, kustomizations, and config blocks to target. Components in facets may have 'when' for granular control. Facets are sorted by ordinal (asc), then by metadata.name (tiebreak). Higher ordinal means higher precedence when merging. Config blocks, terraform components, and kustomizations are merged by ordinal (higher wins), then by strategy precedence (remove > replace > merge) when ordinals match. Config block expressions are evaluated once per round after all same-name blocks are merged, so expressions see the final merged value for each block. If sourceName is set, it updates Source on components lacking it. The target blueprint is modified in place. Returns: evaluated config scope and block order for the loader. Runtime ConfigHandler context values are merged over facet-derived scope so 'when' or component expressions use the actual config. An active facet contributes its config blocks (not its components) even while its requires are unmet, so facets with mutually dependent config and requires resolve across rounds; a facet still unsatisfied when the loop settles fails composition, so a permanently-blocked facet never leaks config into a successful blueprint.
func (*BaseBlueprintProcessor) ProcessGlobally ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) ProcessGlobally(sources []SourceFacetSet) (map[string]any, error)
ProcessGlobally resolves config and facet inclusion once across every source's facets, then emits each source's included components into its own target blueprint. Facets are ranked by a depth-adjusted ordinal so a deeper source's config wins over a shallower one's for the same key, while derivations resolve against the final merged scope and an upstream facet's when: sees a downstream source's config. Returns the resolved global scope.
func (*BaseBlueprintProcessor) ResetExcludedFacets ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) ResetExcludedFacets()
ResetExcludedFacets clears the accumulated excluded-facet record. Callers invoke it once before a composition's per-source ProcessFacets pass, so the set reflects only that composition. ProcessFacets appends across sources rather than resetting, letting a multi-source compose accumulate one set.
func (*BaseBlueprintProcessor) SetExtraScope ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) SetExtraScope(scope map[string]any)
SetExtraScope sets additional scope values that are merged over context values during facet processing.
func (*BaseBlueprintProcessor) SetTraceCollector ¶ added in v0.9.0
func (p *BaseBlueprintProcessor) SetTraceCollector(tc TraceCollector)
SetTraceCollector sets the trace collector for recording per-key contributions and config blocks during composition. When non-nil, all contributions are recorded into the collector. Set to nil to disable trace collection.
type BaseBlueprintWriter ¶ added in v0.9.0
type BaseBlueprintWriter struct {
// contains filtered or unexported fields
}
BaseBlueprintWriter provides the default implementation of the BlueprintWriter interface.
func NewBlueprintWriter ¶ added in v0.9.0
func NewBlueprintWriter(rt *runtime.Runtime) *BaseBlueprintWriter
NewBlueprintWriter creates a new BlueprintWriter that persists blueprints to the filesystem. The runtime provides the config root path where blueprint.yaml will be written. Optional overrides allow replacing the shims for testing file system operations.
func (*BaseBlueprintWriter) Write ¶ added in v0.9.0
func (w *BaseBlueprintWriter) Write(blueprint *blueprintv1alpha1.Blueprint, overwrite bool, initBlueprintURLs ...string) error
Write serializes the blueprint to YAML and saves it to blueprint.yaml in the config root. It always writes the referential form: metadata, repository, and sources only (no terraform/kustomize expansion). Components come from referenced blueprint sources; run "windsor show blueprint" to see the fully rendered blueprint. If overwrite is false and the file exists, the write is skipped to preserve user modifications. The initBlueprintURLs parameter contains blueprint URLs to add as sources when initializing.
type BlueprintComposer ¶ added in v0.9.0
type BlueprintComposer interface {
Compose(loaders []BlueprintLoader, initLoaderNames []string, userBlueprintPath string, configScope map[string]any) (*blueprintv1alpha1.Blueprint, error)
}
BlueprintComposer combines processed blueprints from multiple loaders into a final composed blueprint. It applies the composition algorithm: Sources (in order) → Template (if not in sources) → User overlay.
type BlueprintHandler ¶
type BlueprintHandler interface {
LoadBlueprint(blueprintURL ...string) error
SetSkipValidation(skip bool)
Write(overwrite ...bool) error
RetargetSource(name, url string) (string, error)
UpgradeSourcesToLatest() ([]SourceUpgrade, error)
GetDeclaredSources() ([]blueprintv1alpha1.Source, error)
GetTerraformComponents() []blueprintv1alpha1.TerraformComponent
GetLocalTemplateData() (map[string][]byte, error)
Generate() *blueprintv1alpha1.Blueprint
GenerateResolved() (*blueprintv1alpha1.Blueprint, error)
Explain(path string) (*ExplainTrace, error)
GetDeferredPaths() map[string]bool
}
BlueprintHandler manages the lifecycle of infrastructure blueprints. It orchestrates loading, processing, composing, and writing blueprints.
type BlueprintLoader ¶ added in v0.9.0
type BlueprintLoader interface {
Load(sourceName, sourceURL string) error
GetBlueprint() *blueprintv1alpha1.Blueprint
GetFacets() []blueprintv1alpha1.Facet
GetTemplateData() map[string][]byte
GetSourceName() string
}
BlueprintLoader holds individual blueprint state in-memory through the processing lifecycle. One BlueprintLoader is created per blueprint source (primary, each OCI source, user).
type BlueprintProcessor ¶ added in v0.9.0
type BlueprintProcessor interface {
ProcessFacets(target *blueprintv1alpha1.Blueprint, facets []blueprintv1alpha1.Facet, sourceName ...string) (scope map[string]any, err error)
ProcessGlobally(sources []SourceFacetSet) (map[string]any, error)
}
BlueprintProcessor evaluates when: conditions on facets, terraform components, and kustomizations. It determines inclusion/exclusion based on boolean condition results. The processor is stateless and shared across all loaders. ProcessFacets returns the evaluated config scope for the loader so callers can merge scopes from multiple loaders (e.g. for user overlay and final terraform input evaluation).
type BlueprintWriter ¶ added in v0.9.0
type BlueprintWriter interface {
Write(blueprint *blueprintv1alpha1.Blueprint, overwrite bool, initBlueprintURLs ...string) error
}
BlueprintWriter writes the final composed blueprint to contexts/<context>/blueprint.yaml.
type ConfigBlockRecord ¶ added in v0.9.0
type ConfigBlockRecord struct {
FacetPath string
Line int
RawValue any
ScopeRefs []string
NestedPaths []string
NestedRefs map[string][]string
}
ConfigBlockRecord records a config block value for scope reference resolution. ScopeRefs and NestedPaths are pre-extracted during recording so query-time AST parsing is not needed. NestedRefs maps each nested expression path to its pre-extracted scope variable references.
type CrdInstallLayer ¶ added in v0.9.0
CrdInstallLayer is a CRD kustomization the provisioner will synthesize: a source (empty for the default/project source) and the references it owns. Derived from the composed blueprint by CrdLayers.
func CrdLayers ¶ added in v0.9.0
func CrdLayers(bp *blueprintv1alpha1.Blueprint) []CrdInstallLayer
CrdLayers returns the CRD kustomization layers a composed blueprint implies: the default/project layer (empty source) from bp.Crds, then one per install source that vendors CRDs, alphabetically by name. The composer wires the stack to these names and the provisioner materializes them, so both must agree on the set — they share this single derivation.
type DefaultTraceCollector ¶ added in v0.9.0
type DefaultTraceCollector struct {
// contains filtered or unexported fields
}
DefaultTraceCollector is the standard TraceCollector implementation backed by in-memory maps. Contributions and config blocks are recorded during composition (Phase 1). After composition, Finalize stores the composed blueprint, scope, and template root. GetTrace performs lazy resolution on demand.
func NewTraceCollector ¶ added in v0.9.0
func NewTraceCollector() *DefaultTraceCollector
NewTraceCollector creates a new DefaultTraceCollector with initialized storage.
func (*DefaultTraceCollector) Finalize ¶ added in v0.9.0
func (c *DefaultTraceCollector) Finalize(bp *blueprintv1alpha1.Blueprint, scope map[string]any, templateRoot string)
Finalize stores the composed blueprint, scope, and template root for lazy trace resolution. Called once after all facet processing and scope merging completes.
func (*DefaultTraceCollector) GetTrace ¶ added in v0.9.0
func (c *DefaultTraceCollector) GetTrace(pathStr string) (*ExplainTrace, error)
GetTrace resolves a dotted blueprint path and returns a trace with the composed value, contributions sorted by ordinal, effective marking, and scope reference resolution.
func (*DefaultTraceCollector) RecordConfigBlock ¶ added in v0.9.0
func (c *DefaultTraceCollector) RecordConfigBlock(configPath string, record ConfigBlockRecord)
RecordConfigBlock stores a config block value and pre-extracts scope references, nested expression paths, and per-path refs from the raw value. No child entries are created; getConfigBlockWithRecord's fallback logic resolves lines via YAML AST. Thread-safe.
func (*DefaultTraceCollector) RecordContribution ¶ added in v0.9.0
func (c *DefaultTraceCollector) RecordContribution(composedPath string, tc TraceContribution)
RecordContribution stores a per-key contribution from a facet and pre-extracts scope references from the raw value expression. Called from the processor during composition for each terraform input, kustomize substitution, and kustomize components list. Thread-safe.
type ExcludedFacet ¶ added in v0.9.0
type ExcludedFacet struct {
Name string // facet metadata name
When string // the when: expression that evaluated false
Provides []string // terraform component IDs and kustomization names (including flux tiers) it declares
}
ExcludedFacet records a facet dropped from composition by a false when: condition, along with the component and kustomization names it would have contributed. Dependency validation joins a dangling dependency name against these so it can name the excluded facet and the condition that excluded it, rather than only reporting the unresolvable edge.
type ExplainContribution ¶ added in v0.9.0
type ExplainContribution struct {
SourceName string
FacetPath string
AbsFacetPath string
Line int
Ordinal int
Strategy string
Expression string
HasValue bool
Effective bool
ScopeRefs []ExplainScopeRef
RawComponents []string
// contains filtered or unexported fields
}
ExplainContribution describes one source that contributed to the value (facet file, source name, etc.). AbsFacetPath is the absolute filesystem path for clickable terminal references; FacetPath is the shortened display form. Line is the 1-based line number of the specific key (or the component definition if the key is not locatable). Effective is true when this contribution produced the final composed value; false means it was overridden by a higher-ordinal facet.
type ExplainPath ¶ added in v0.9.0
type ExplainPath struct {
Kind ExplainPathKind
Segment string
Key string
}
ExplainPath is a parsed explain path identifying a single value in the composed blueprint.
func ParseExplainPath ¶ added in v0.9.0
func ParseExplainPath(path string) (ExplainPath, error)
ParseExplainPath parses a path string into an ExplainPath. Supported forms:
- terraform.<componentID>.inputs.<key>
- kustomize.<name>.substitutions.<key>
- configMaps.<name>.<key>
Returns an error if the path is malformed or empty.
func (ExplainPath) String ¶ added in v0.9.0
func (p ExplainPath) String() string
String returns the canonical path string (e.g. terraform.cluster.inputs.domain_name).
type ExplainPathKind ¶ added in v0.9.0
type ExplainPathKind int
ExplainPathKind identifies the type of blueprint path being explained.
const ( ExplainPathKindTerraformInput ExplainPathKind = iota ExplainPathKindKustomizeSubstitution ExplainPathKindKustomizeComponents ExplainPathKindConfigMap ExplainPathKindSubstitution )
type ExplainScopeRef ¶ added in v0.9.0
type ExplainScopeRef struct {
Name string
Status string
Source string
Line int
Nested []ExplainScopeRef
}
ExplainScopeRef describes a scope variable referenced in an expression, its resolution status, and the source location of the config block that defines it (if applicable). Nested holds refs for expressions or map keys that contain expressions, recursively until origins.
type ExplainTrace ¶ added in v0.9.0
type ExplainTrace struct {
Path string
Value string
Contributions []ExplainContribution
}
ExplainTrace holds the result of explaining a path: the value and its contributions.
type MockBlueprintHandler ¶
type MockBlueprintHandler struct {
LoadBlueprintFunc func(...string) error
SetSkipValidationFunc func(skip bool)
WriteFunc func(overwrite ...bool) error
RetargetSourceFunc func(name, url string) (string, error)
UpgradeSourcesToLatestFunc func() ([]SourceUpgrade, error)
GetDeclaredSourcesFunc func() ([]blueprintv1alpha1.Source, error)
GetTerraformComponentsFunc func() []blueprintv1alpha1.TerraformComponent
GetLocalTemplateDataFunc func() (map[string][]byte, error)
GenerateFunc func() *blueprintv1alpha1.Blueprint
GenerateResolvedFunc func() (*blueprintv1alpha1.Blueprint, error)
ExplainFunc func(string) (*ExplainTrace, error)
GetDeferredPathsFunc func() map[string]bool
// contains filtered or unexported fields
}
MockBlueprintHandler is a mock implementation of BlueprintHandler interface for testing.
func NewMockBlueprintHandler ¶
func NewMockBlueprintHandler() *MockBlueprintHandler
NewMockBlueprintHandler creates a new instance of MockBlueprintHandler.
func (*MockBlueprintHandler) Explain ¶ added in v0.9.0
func (m *MockBlueprintHandler) Explain(path string) (*ExplainTrace, error)
Explain calls the mock ExplainFunc if set, otherwise returns nil.
func (*MockBlueprintHandler) Generate ¶
func (m *MockBlueprintHandler) Generate() *blueprintv1alpha1.Blueprint
Generate calls the mock GenerateFunc if set, otherwise returns nil.
func (*MockBlueprintHandler) GenerateResolved ¶ added in v0.9.0
func (m *MockBlueprintHandler) GenerateResolved() (*blueprintv1alpha1.Blueprint, error)
GenerateResolved calls the mock GenerateResolvedFunc if set, otherwise falls back to Generate.
func (*MockBlueprintHandler) GetDeclaredSources ¶ added in v0.9.0
func (m *MockBlueprintHandler) GetDeclaredSources() ([]blueprintv1alpha1.Source, error)
GetDeclaredSources calls the mock GetDeclaredSourcesFunc if set, otherwise returns nil.
func (*MockBlueprintHandler) GetDeferredPaths ¶ added in v0.9.0
func (m *MockBlueprintHandler) GetDeferredPaths() map[string]bool
GetDeferredPaths calls the mock GetDeferredPathsFunc if set, otherwise returns nil.
func (*MockBlueprintHandler) GetLocalTemplateData ¶
func (m *MockBlueprintHandler) GetLocalTemplateData() (map[string][]byte, error)
GetLocalTemplateData calls the mock GetLocalTemplateDataFunc if set, otherwise returns empty map.
func (*MockBlueprintHandler) GetTerraformComponents ¶
func (m *MockBlueprintHandler) GetTerraformComponents() []blueprintv1alpha1.TerraformComponent
GetTerraformComponents calls the mock GetTerraformComponentsFunc if set, otherwise returns empty slice.
func (*MockBlueprintHandler) LoadBlueprint ¶
func (m *MockBlueprintHandler) LoadBlueprint(blueprintURL ...string) error
LoadBlueprint calls the mock LoadBlueprintFunc if set, otherwise returns nil.
func (*MockBlueprintHandler) RetargetSource ¶ added in v0.9.0
func (m *MockBlueprintHandler) RetargetSource(name, url string) (string, error)
RetargetSource calls the mock RetargetSourceFunc if set, otherwise returns an empty previous URL.
func (*MockBlueprintHandler) SetSkipValidation ¶ added in v0.9.0
func (m *MockBlueprintHandler) SetSkipValidation(skip bool)
SetSkipValidation calls the mock SetSkipValidationFunc if set, otherwise records the flag on the mock so tests can assert prepareProject toggled it.
func (*MockBlueprintHandler) SkipValidation ¶ added in v0.9.0
func (m *MockBlueprintHandler) SkipValidation() bool
SkipValidation reports the recorded skip flag (only meaningful when SetSkipValidationFunc is not set). Test-only accessor.
func (*MockBlueprintHandler) UpgradeSourcesToLatest ¶ added in v0.9.0
func (m *MockBlueprintHandler) UpgradeSourcesToLatest() ([]SourceUpgrade, error)
UpgradeSourcesToLatest calls the mock UpgradeSourcesToLatestFunc if set, otherwise returns nil.
func (*MockBlueprintHandler) Write ¶
func (m *MockBlueprintHandler) Write(overwrite ...bool) error
Write calls the mock WriteFunc if set, otherwise returns nil.
type RequirementsError ¶ added in v0.9.0
type RequirementsError struct {
Message string
}
RequirementsError signals that one or more required facet inputs are not set. It carries the formatted operator-facing message produced by formatRequirementsError. Pipeline callers that would otherwise wrap blueprint errors with internal context (project's "failed to load blueprint data", handler's "failed to compose blueprint" and "failed to process facets for 'X'") detect this type via errors.As and pass it through unwrapped, so the operator sees the prose alone instead of a chain of internal frame names.
func (*RequirementsError) Error ¶ added in v0.9.0
func (e *RequirementsError) Error() string
type Shims ¶
type Shims struct {
Stat func(string) (os.FileInfo, error)
ReadFile func(string) ([]byte, error)
ReadDir func(string) ([]os.DirEntry, error)
WriteFile func(string, []byte, os.FileMode) error
MkdirAll func(string, os.FileMode) error
Walk func(string, filepath.WalkFunc) error
YamlMarshal func(any) ([]byte, error)
YamlUnmarshal func([]byte, any) error
FilepathBase func(string) string
}
Shims provides testable wrappers around external dependencies for the blueprint package. This enables dependency injection and mocking in unit tests while maintaining clean separation between business logic and external system interactions.
type SourceFacetSet ¶ added in v0.9.0
type SourceFacetSet struct {
Name string
Depth int
Target *blueprintv1alpha1.Blueprint
Facets []blueprintv1alpha1.Facet
}
SourceFacetSet is one source's contribution to global composition: its name, its dependency depth (deeper/referencing sources override shallower ones), the blueprint to emit its components into, and its facets.
type SourceUpgrade ¶ added in v0.9.0
SourceUpgrade records one source moved to a newer version by UpgradeSourcesToLatest.
type TraceCollector ¶ added in v0.9.0
type TraceCollector interface {
RecordContribution(composedPath string, tc TraceContribution)
RecordConfigBlock(configPath string, record ConfigBlockRecord)
Finalize(bp *blueprintv1alpha1.Blueprint, scope map[string]any, templateRoot string)
GetTrace(pathStr string) (*ExplainTrace, error)
}
TraceCollector records per-key contributions and config blocks during blueprint composition, then provides trace queries after finalization. Implementations are set on the processor before composition begins and are only active when the explain command is running.
type TraceContribution ¶ added in v0.9.0
type TraceContribution struct {
FacetPath string
SourceName string
Ordinal int
Strategy string
Line int
RawValue any
RawComponents []string
ScopeRefs []string
}
TraceContribution records a single per-key contribution from a facet during composition. Recorded at the per-key level (e.g. "terraform.networking.inputs.domain_name") with all metadata resolved at record time so no retroactive YAML reparsing is needed. ScopeRefs are pre-extracted from expressions during recording.