Integrate collection policies across layered assembly

This commit is contained in:
2026-10-23 19:49:12 +00:00
parent 89a9684f0d
commit acd9e9a9fa
15 changed files with 269 additions and 93 deletions

View File

@@ -92,7 +92,7 @@ func loadGroupedWithSecretLookup[T any](request loadRequest[T], secrets SecretBi
}
func assembleLayeredInput[T any](request loadRequest[T], input assembledInput, accounting *importAccounting) (assembledInput, []Diagnostic) {
groups := make([]*composedDocument, 0, len(request.underlays))
var assembly *assemblyAccumulator
for index, group := range request.underlays {
acquired, diagnostics := acquireUnderlayGroupScopes(group, index+1, request.protectionVersion(), accounting, input.versionState, request.sequencePolicy)
mergeResourceContexts(&input.contexts, acquired.contexts)
@@ -100,35 +100,71 @@ func assembleLayeredInput[T any](request loadRequest[T], input assembledInput, a
input.sources = append(input.sources, acquired.sources...)
return input, diagnostics
}
composition, diagnostics := composeUnderlayGroup(acquired, request.protectionVersion(), request.sequencePolicy, collectionPolicyScope{})
var lower collectionPolicyScope
if assembly != nil && assembly.current != nil {
lower = assembly.current.collectionPolicies
}
composition, diagnostics := composeUnderlayGroup(acquired, request.protectionVersion(), request.sequencePolicy, lower)
input.sources = append(input.sources, acquired.sources...)
if len(diagnostics) != 0 {
return input, diagnostics
}
if composition != nil {
groups = append(groups, composition)
if assembly == nil {
assembly = newAssemblyAccumulator(composition)
} else {
var declarations []sequenceDeclarationSpec
for _, scope := range composition.acquisition {
declarations = append(declarations, acquiredSequenceDeclarations(scope)...)
}
if diagnostics := assembly.applyOverlayWithCollectionPolicy(
composition.root, composition.origins, composition.applications, LayerUnderlay,
request.sequencePolicy, declarations,
); len(diagnostics) != 0 {
return input, diagnostics
}
}
}
}
var assembly *assemblyAccumulator
for _, group := range groups {
if assembly == nil {
assembly = newAssemblyAccumulator(group)
continue
mainPresent := input.document != nil || input.composition != nil || len(input.acquisition) != 0
var mainComposition *composedDocument
if mainPresent {
var lower collectionPolicyScope
if assembly != nil && assembly.current != nil {
lower = assembly.current.collectionPolicies
}
if diagnostics := assembly.applyOverlay(group.root, group.origins, group.applications, LayerUnderlay); len(diagnostics) != 0 {
return input, diagnostics
}
}
if input.document != nil {
mainComposition, diagnostics := compositionForInputWithPolicy(input, request.sequencePolicy)
var diagnostics []Diagnostic
mainComposition, diagnostics = compositionForInputWithPolicies(input, lower, request.sequencePolicy)
if len(diagnostics) != 0 {
return input, diagnostics
}
}
if request.sourceVersionMode == sourceVersionModeDefault {
var mainRoot *document.Node
if mainComposition != nil {
mainRoot = mainComposition.root
} else if input.document != nil {
mainRoot = input.document
}
if diagnostics := checkVersion(request.definition.Version, mainRoot); hasErrors(diagnostics) {
return input, diagnostics
}
}
if mainComposition != nil {
if assembly == nil {
assembly = newAssemblyAccumulator(mainComposition)
} else if diagnostics := assembly.applyOverlay(mainComposition.root, mainComposition.origins, mainComposition.applications, LayerBase); len(diagnostics) != 0 {
return input, diagnostics
} else {
var declarations []sequenceDeclarationSpec
for _, scope := range mainComposition.acquisition {
declarations = append(declarations, acquiredSequenceDeclarations(scope)...)
}
if diagnostics := assembly.applyOverlayWithCollectionPolicy(
mainComposition.root, mainComposition.origins, mainComposition.applications, LayerBase,
request.sequencePolicy, declarations,
); len(diagnostics) != 0 {
return input, diagnostics
}
}
}
if assembly == nil && (activeOverlay(request.overlay) || len(request.overrides) != 0) {
@@ -146,10 +182,7 @@ func assembleLayeredInput[T any](request loadRequest[T], input assembledInput, a
selection := Source{kind: sourceBytes}
selected := parsedSource{document: &document.Node{Kind: document.Mapping}, source: &SourceInfo{}}
var diagnostics []Diagnostic
var overlayPolicy []sequencePolicy
if request.ordinary {
overlayPolicy = []sequencePolicy{request.sequencePolicy}
}
overlayPolicy := []sequencePolicy{request.sequencePolicy}
input.sources, diagnostics = loadSelectedOverlayIntoWithVersion(selection, request.overlayFilesystem, selected, assembly, input.sources, request.overlay, request.protectionVersion(), defaultImportLimits(), input.versionState, overlayPolicy...)
if len(diagnostics) != 0 {
return input, diagnostics
@@ -172,23 +205,6 @@ func assembleLayeredInput[T any](request loadRequest[T], input assembledInput, a
return input, nil
}
func acquireUnderlayGroup(group loadGroup, index int, rule *VersionRule, accounting *importAccounting) (*composedDocument, []SourceInfo, map[string]ResourceContext, []Diagnostic) {
return acquireUnderlayGroupWithVersion(group, index, rule, accounting, nil)
}
func acquireUnderlayGroupWithVersion(group loadGroup, index int, rule *VersionRule, accounting *importAccounting, versionState *sourceVersionState) (*composedDocument, []SourceInfo, map[string]ResourceContext, []Diagnostic) {
return acquireUnderlayGroupWithPolicyVersion(group, index, rule, accounting, versionState, sequencePolicy{})
}
func acquireUnderlayGroupWithPolicyVersion(group loadGroup, index int, rule *VersionRule, accounting *importAccounting, versionState *sourceVersionState, policy sequencePolicy) (*composedDocument, []SourceInfo, map[string]ResourceContext, []Diagnostic) {
acquired, diagnostics := acquireUnderlayGroupScopes(group, index, rule, accounting, versionState, policy)
if len(diagnostics) != 0 {
return nil, acquired.sources, acquired.contexts, diagnostics
}
composition, diagnostics := composeUnderlayGroup(acquired, rule, policy, collectionPolicyScope{})
return composition, acquired.sources, acquired.contexts, diagnostics
}
func acquireUnderlayGroupScopes(group loadGroup, index int, rule *VersionRule, accounting *importAccounting, versionState *sourceVersionState, policy sequencePolicy) (*acquiredUnderlayGroup, []Diagnostic) {
initialBytes, initialNodes := accounting.bytes, accounting.nodes
visited := make(map[resourceIdentity]importRoute)
@@ -208,6 +224,7 @@ func acquireUnderlayGroupScopes(group loadGroup, index int, rule *VersionRule, a
Imports: contribution.imports, Filesystem: contribution.filesystem,
Definition: Definition[struct{}]{Version: rule}, destination: contribution.destination.clone(),
placementMode: contribution.placementMode, sequencePolicy: policy, deferAssembly: true,
directiveContext: rootDirectiveContextLayered,
importDefaults: func() importDefaults {
if versionState == nil {
return importDefaults{}