You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Successor to #293, which proposed replacing the placement path template with a spec.layout
discriminated union and was reversed. The template stays; the two things it genuinely cannot express
become additive fields. Design: docs/layout/model.md, sequenced as PR 4 of docs/layout/implementation-plan.md (both land
with #318).
The fields
serializeNamespace: Auto | Always | Never — whether a written document carries metadata.namespace.
Auto (default): omit it when the governing kustomization already sets this resource's namespace.
Today's inferred behavior, now named.
Always: always write it. The only safe choice when nothing downstream supplies it.
Never: never write it, and prove something else does.
The name deliberately avoids writeNamespace: "write" is the most loaded word in this API (the
write boundary, the write jail, WriteBoundaryRefused), and writeNamespace: Never invites the
reading "never write to this namespace", which is a permission — precisely what the neighbouring sourceNamespace fields are.
kustomizeRoot: Adopt | Create | Require — what the target does about the folder's root.
Adopt (default): use the one that is there; do nothing if there is none.
Create: write a kustomization.yaml the user did not author, which is what bootstraps an empty
repository and what makes serializeNamespace: Never provable there — the operator owns the file
the omission depends on.
Require: refuse to write when no root governs the path, instead of committing documents that
land in whatever namespace the applier defaults to.
CreatePerDirectory is deliberately deferred, with its trigger written down in model.md.
Why this is not breaking
Both defaults equal today's behavior, so this ships in any release without a coordinated consumer
bump. That is the largest consequence of the reversal: the whole placement story (PRs 1–4) is
additive, and #294's wave lost its largest member.
What has to ship with it
A post-scan validation pass, in PR 3, because these two fields make promises no CEL rule can
check — the precondition is a property of the observed folder, not of the spec:
Rule
Precondition
serializeNamespace: Never requires a namespace supplier
a kustomization with namespace: governs the path
kustomizeRoot: Require needs a root
one governs the path
a declared single-root assertion
the folder has exactly one root
Done when
The six scenarios in docs/layout/examples/ run
unskipped. PR 1 builds them as an executable corpus with every case that needs these fields skipped
and naming this work in its skip message, so this is finished when the last skip is gone — which
is the definition of done the plan is built to produce.
Open questions carried from the design
Does serializeNamespace: Never need to name its supplier (KustomizeRoot, FluxTargetNamespace, Asserted) so the post-scan pass checks the guarantee rather than infers
which one was meant?
Is Require the right default for a folder that already contains a kustomization when the target
is created?
Successor to #293, which proposed replacing the placement path template with a
spec.layoutdiscriminated union and was reversed. The template stays; the two things it genuinely cannot express
become additive fields. Design:
docs/layout/model.md, sequenced as PR 4 ofdocs/layout/implementation-plan.md(both landwith #318).
The fields
serializeNamespace: Auto | Always | Never— whether a written document carriesmetadata.namespace.Auto(default): omit it when the governing kustomization already sets this resource's namespace.Today's inferred behavior, now named.
Always: always write it. The only safe choice when nothing downstream supplies it.Never: never write it, and prove something else does.The name deliberately avoids
writeNamespace: "write" is the most loaded word in this API (thewrite boundary, the write jail,
WriteBoundaryRefused), andwriteNamespace: Neverinvites thereading "never write to this namespace", which is a permission — precisely what the neighbouring
sourceNamespacefields are.kustomizeRoot: Adopt | Create | Require— what the target does about the folder's root.Adopt(default): use the one that is there; do nothing if there is none.Create: write akustomization.yamlthe user did not author, which is what bootstraps an emptyrepository and what makes
serializeNamespace: Neverprovable there — the operator owns the filethe omission depends on.
Require: refuse to write when no root governs the path, instead of committing documents thatland in whatever namespace the applier defaults to.
CreatePerDirectoryis deliberately deferred, with its trigger written down inmodel.md.Why this is not breaking
Both defaults equal today's behavior, so this ships in any release without a coordinated consumer
bump. That is the largest consequence of the reversal: the whole placement story (PRs 1–4) is
additive, and #294's wave lost its largest member.
What has to ship with it
A post-scan validation pass, in PR 3, because these two fields make promises no CEL rule can
check — the precondition is a property of the observed folder, not of the spec:
serializeNamespace: Neverrequires a namespace suppliernamespace:governs the pathkustomizeRoot: Requireneeds a rootDone when
The six scenarios in
docs/layout/examples/rununskipped. PR 1 builds them as an executable corpus with every case that needs these fields skipped
and naming this work in its skip message, so this is finished when the last skip is gone — which
is the definition of done the plan is built to produce.
Open questions carried from the design
serializeNamespace: Neverneed to name its supplier (KustomizeRoot,FluxTargetNamespace,Asserted) so the post-scan pass checks the guarantee rather than inferswhich one was meant?
Requirethe right default for a folder that already contains a kustomization when the targetis created?
placement.defaultgain a CRD default now that the shipped ancestor walk (fix(placement): register a new file with its nearest ancestor kustomization #319) registersa defaulted path with the kustomization that governs it? The remaining objection is legibility,
not correctness.