Background
crossplane-diff runs a server-side apply (SSA) dry-run against the apiserver to render the "would-be" form of each resource being diffed. This picks up apiserver-side mutations that don't come from the render pipeline:
- CRD
default: field values
- Mutating admission webhook output (sidecar injectors, label/annotation injectors, etc.)
- Validating admission webhooks (invalid references, quota, policy)
Currently, the dry-run is only performed when the target resource already exists in the cluster. See cmd/diff/diffprocessor/diff_calculator.go — the applyClient.DryRunApply call is gated on current != nil. For brand-new resources (additions), the diff emits desired straight from the render pipeline.
This is an intentional choice: it avoids requiring create RBAC on every GVK that might be diffed, which is otherwise unnecessary because we never persist anything.
The asymmetry
~~~ modification diffs reflect defaulted + webhooked state
+++ addition diffs do not
For most Crossplane managed resources the gap is small — providers typically don't chain heavy mutating webhooks at the apiserver level, and most reconciliation happens later in the provider controller. But the gap is nonzero, and it conflicts with the project's "accuracy above all else" principle.
Proposal
Add an opt-in flag (e.g. --ssa-additions or --strict-additions) that, when set, also performs the dry-run SSA for resources that don't yet exist in the cluster. Default off, so existing deployments don't get a surprise RBAC requirement.
When enabled, document that:
- The role needs
create on every GVK that may appear as an addition
- Validating webhooks may reject resources that
crossplane render produced; this turns what was a clean +++ diff into a diff-time error (arguably more accurate, but a behavior change)
Priority
Low. No reported cases of additions diverging from reality in practice. File this so we don't lose the idea.
References
- Discussion in [today's session]
cmd/diff/diffprocessor/diff_calculator.go (the current != nil gate around DryRunApply)
cmd/diff/client/kubernetes/apply_client.go (the SSA implementation)
Background
crossplane-diffruns a server-side apply (SSA) dry-run against the apiserver to render the "would-be" form of each resource being diffed. This picks up apiserver-side mutations that don't come from the render pipeline:default:field valuesCurrently, the dry-run is only performed when the target resource already exists in the cluster. See
cmd/diff/diffprocessor/diff_calculator.go— theapplyClient.DryRunApplycall is gated oncurrent != nil. For brand-new resources (additions), the diff emitsdesiredstraight from the render pipeline.This is an intentional choice: it avoids requiring
createRBAC on every GVK that might be diffed, which is otherwise unnecessary because we never persist anything.The asymmetry
~~~modification diffs reflect defaulted + webhooked state+++addition diffs do notFor most Crossplane managed resources the gap is small — providers typically don't chain heavy mutating webhooks at the apiserver level, and most reconciliation happens later in the provider controller. But the gap is nonzero, and it conflicts with the project's "accuracy above all else" principle.
Proposal
Add an opt-in flag (e.g.
--ssa-additionsor--strict-additions) that, when set, also performs the dry-run SSA for resources that don't yet exist in the cluster. Default off, so existing deployments don't get a surprise RBAC requirement.When enabled, document that:
createon every GVK that may appear as an additioncrossplane renderproduced; this turns what was a clean+++diff into a diff-time error (arguably more accurate, but a behavior change)Priority
Low. No reported cases of additions diverging from reality in practice. File this so we don't lose the idea.
References
cmd/diff/diffprocessor/diff_calculator.go(thecurrent != nilgate aroundDryRunApply)cmd/diff/client/kubernetes/apply_client.go(the SSA implementation)