Add semantic configuration profile comparison
This commit is contained in:
@@ -46,7 +46,20 @@ type pipelineProfileDeclaration struct {
|
||||
overlay string
|
||||
}
|
||||
|
||||
func loadComposedPipeline(path string, opts PipelineLoadOptions) (*PipelineConfig, error) {
|
||||
// pipelineCompositionSources retains one validated root source set. Each
|
||||
// selected profile is resolved from a cloned base document so callers can
|
||||
// safely compare or otherwise resolve multiple profiles without rereading or
|
||||
// mutating the source set.
|
||||
type pipelineCompositionSources struct {
|
||||
rootPath string
|
||||
envelope pipelineCompositionEnvelope
|
||||
imports []loadedPipelineImport
|
||||
overlays []loadedPipelineProfileOverlay
|
||||
overlaysLoaded bool
|
||||
base *compositionDocument
|
||||
}
|
||||
|
||||
func loadPipelineCompositionSources(path string) (*pipelineCompositionSources, error) {
|
||||
rootPath, err := filepath.Abs(path)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("resolve root pipeline path %q: %w", path, err)
|
||||
@@ -72,14 +85,6 @@ func loadComposedPipeline(path string, opts PipelineLoadOptions) (*PipelineConfi
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
selection, err := selectPipelineProfile(envelope, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
overlays, err := loadPipelineProfileOverlays(rootPath, envelope.profiles, imports)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
documents := make([]*compositionDocument, 0, len(imports)+1)
|
||||
documents = append(documents, baseRoot)
|
||||
for _, imported := range imports {
|
||||
@@ -89,8 +94,47 @@ func loadComposedPipeline(path string, opts PipelineLoadOptions) (*PipelineConfi
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &pipelineCompositionSources{
|
||||
rootPath: rootPath,
|
||||
envelope: envelope,
|
||||
imports: imports,
|
||||
base: merged,
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (sources *pipelineCompositionSources) loadOverlays() error {
|
||||
if sources == nil {
|
||||
return fmt.Errorf("pipeline composition sources are required")
|
||||
}
|
||||
if sources.overlaysLoaded {
|
||||
return nil
|
||||
}
|
||||
overlays, err := loadPipelineProfileOverlays(sources.rootPath, sources.envelope.profiles, sources.imports)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
sources.overlays = overlays
|
||||
sources.overlaysLoaded = true
|
||||
return nil
|
||||
}
|
||||
|
||||
func (sources *pipelineCompositionSources) resolve(opts PipelineLoadOptions) (*PipelineConfig, error) {
|
||||
if sources == nil || sources.base == nil {
|
||||
return nil, fmt.Errorf("pipeline composition sources are required")
|
||||
}
|
||||
if !sources.overlaysLoaded {
|
||||
return nil, fmt.Errorf("pipeline profile overlays have not been loaded")
|
||||
}
|
||||
selection, err := selectPipelineProfile(sources.envelope, opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
merged := &compositionDocument{
|
||||
root: cloneCompositionNode(sources.base.root),
|
||||
sources: append([]string(nil), sources.base.sources...),
|
||||
}
|
||||
if selection != nil {
|
||||
overlay, ok := loadedProfileOverlay(overlays, selection.name)
|
||||
overlay, ok := loadedProfileOverlay(sources.overlays, selection.name)
|
||||
if !ok {
|
||||
return nil, fmt.Errorf("selected profile %q overlay was not loaded", selection.name)
|
||||
}
|
||||
@@ -106,7 +150,7 @@ func loadComposedPipeline(path string, opts PipelineLoadOptions) (*PipelineConfi
|
||||
return nil, err
|
||||
}
|
||||
var cfg PipelineConfig
|
||||
if err := decodeStrictYAMLFromReader("pipeline", rootPath, strings.NewReader(string(rendered)), &cfg); err != nil {
|
||||
if err := decodeStrictYAMLFromReader("pipeline", sources.rootPath, strings.NewReader(string(rendered)), &cfg); err != nil {
|
||||
return nil, fmt.Errorf("assembled pipeline sources %s: %w", formatCompositionSources(merged.sources), err)
|
||||
}
|
||||
records, err := merged.semanticRecords()
|
||||
@@ -114,11 +158,11 @@ func loadComposedPipeline(path string, opts PipelineLoadOptions) (*PipelineConfi
|
||||
return nil, err
|
||||
}
|
||||
metadata := &pipelineResolutionMetadata{
|
||||
rootPath: rootPath,
|
||||
rootPath: sources.rootPath,
|
||||
sources: append([]string(nil), merged.sources...),
|
||||
selectedProfile: selection,
|
||||
}
|
||||
for _, imported := range imports {
|
||||
for _, imported := range sources.imports {
|
||||
metadata.imports = append(metadata.imports, imported.path)
|
||||
}
|
||||
for _, record := range records {
|
||||
|
||||
Reference in New Issue
Block a user