Tell the app pod mutator which app it is mutating - #595
Merged
Conversation
The deploy-path mutator seam of ADR-0061 is a func(*corev1.PodSpec). It reaches every pod this adapter authors for an app -- the Deployment's pod template and the one-off run Job -- and it is told nothing about any of them, so the only policy it can carry is policy that is true of every app on the cluster. For a toleration on a tainted pool that is usually right. For a runtime class it is not: an operator running one app's image under a sandboxed runtime and another's under the default has no way to say so. The ways around it are the ones ADR-0073 §2 already rejected for the platform split -- key off a container image or a label and reconstruct a classification the engine had in hand -- and a wrong branch there applies the wrong policy to the wrong workload. Adapter.WithAppPodMutator takes func(PodIdentity, *corev1.PodSpec). PodIdentity carries the app, the namespace the object is being written into, and which of the two app-image pods it is. All three are already in scope at both call sites; no new plumbing stands behind them. It says namespace rather than environment on purpose. Neither WorkloadSpec nor RunSpec carries an environment name, an environment-scoped view is a copy of the adapter with a different namespace (ADR-0035 phase 2), and the namespace is what the pod is actually written into. An embedder that keys its own policy on something else maps the namespace onto it on their side, so the seam does not learn how anyone stores their policy. WithPodMutator is retained, unchanged and working, for an embedder already compiled against it: it wires the same single field through a closure that discards the identity, so the two spellings do not stack and the last one wired runs. Its nil case still clears the hook rather than wrapping nil in a closure that would panic on the first deploy. WithPlatformPodMutator is untouched. Its pods run Burrow's own images and none of them belongs to an app, so the identity has nothing to say there; ADR-0077 §2 states its signature and reach stay as they are. The compile-time pin on both ADR-0073 hook signatures in placement_test.go is unchanged and still passes. The authored-pod-path guard learns the new helper name alongside the field it already recognised, so a call site that applies the hook inline is still visible to the scan. Signed-off-by: Nicholas Phillips <nsphilli@gmail.com>
incognick
marked this pull request as draft
August 20, 2026 22:46
incognick
marked this pull request as ready for review
August 21, 2026 00:59
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
The app-path pod mutator seam of ADR-0061 is a
func(*corev1.PodSpec). It reaches every pod the adapter authors for an app — the Deployment's pod template and the one-off run Job — and is told nothing about any of them, so the only policy it can carry is policy true of every app on the cluster. A toleration for a tainted pool usually is. A runtime class is not.Adapter.WithAppPodMutator(func(kube.PodIdentity, *corev1.PodSpec)) *Adapter.PodIdentitycarries the app, the namespace the object is being written into, and which of the two app-image pods it is. All three are already in scope at both call sites; nothing new is threaded through the engine to supply them.What is deliberately not changed
WithPodMutatorkeeps working, unchanged. It is a public seam an embedder may already be compiled against. It now wires the same single field through a closure that discards the identity, so the two spellings do not stack and the last one wired runs.WithPodMutator(nil)still clears the hook rather than wrapping nil in a closure that would panic on the first deploy.WithPlatformPodMutatoris untouched. Its pods run Burrow's own images — add-on instances, collectors, the backup and restore Jobs — and none of them belongs to an app, so the identity has nothing to say there. ADR-0077 §2 states its signature and reach stay as they are.placement_test.go) is unedited and still passes. The new method carries a pin of its own in the same shape.Why namespace and not environment
Neither
controlplane.WorkloadSpecnorcontrolplane.RunSpeccarries an environment name; an environment-scoped view is a copy of the adapter with a different namespace (ADR-0035 phase 2); and the namespace is what the pod is actually written into. An embedder that keys its own policy on something else maps the namespace onto it on their side, so the seam does not learn how anyone stores their policy.The two app-image paths also do not share a request type, so there is no existing value that could be handed over on both. Synthesising one for the path that lacks it is the move ADR-0077 §2 rejects at the controller seam. The three fields of
PodIdentityare ones both paths genuinely have.Tests
controlplane/kube/app_pod_identity_test.gopins the identity on the deploy path and the run path, that it reports the environment's namespace throughWithNamespace, that one wired hook applies different policy to two apps, thatWithPodMutatorstill runs and does not stack with the new spelling, and that its nil case clears the hook.The authored-pod-path guard learns the new helper name alongside the field it already recognised, so a call site applying the hook inline is still visible to the scan.
This is not ready to merge
There is no accepted record for widening this seam yet. The record is being written; this PR should wait for it, and its shape may change if the record decides differently. Opening it now so the code is reviewable alongside the record rather than after it.