What problem are you facing?
When adopting an existing Kubernetes resource into Crossplane, we run the Object in Observe-only mode first, to prove the import is a no-op before granting the provider write access. The goal is a "zero-diff import": Crossplane should not want to change anything about the resource (beyond, in the AWS-provider analogy, tags) before we consider it safe to manage.
Today an observe-only Object gives us no visibility into what Crossplane would change if we switched it to update mode. spec.forProvider vs status.atProvider comparison is manual and, in observe mode, the provider owns no fields so there is nothing meaningful to compare. To actually flush out would-be changes we currently have to perform a convoluted state-machine step: flip the management policy from observe to update while simultaneously swapping the ProviderConfig to a permissions-restricted (e.g. tag-only) role, so that any attempted change beyond the allowed set is rejected with a 403, and then trace the 403 back to the offending field. That is slow, error-prone, and requires a credential-rotation dance.
We would like a first-class signal, available while the resource is still observe-only and untouched, that answers: "when I switch this Object to update mode, what actually changes on the live resource?"
How could Crossplane help solve your problem?
crossplane-runtime is adding an UpToDate status condition to the managed reconciler (see crossplane/crossplane-runtime#945, tracking crossplane/crossplane-runtime#939). It reflects the Observe result as a condition with reasons ObserveMatched (True), and UpdateRestricted / UpdateRequested / UpdateFailed (False), plus ReconcilePaused (Unknown), and carries a diff message on the False states.
provider-kubernetes can implement this so that, for an Object:
- In sync (an update would change nothing) →
UpToDate: True / ObserveMatched.
- Would change (an update would modify the live resource) →
UpToDate: False / UpdateRestricted, with a field-level diff in the condition message describing exactly what would change — and, in observe mode, without mutating the resource.
The important property for the import use case is that the diff answers "what would update mode change?" independent of current field ownership. Concretely, the provider (on the server-side-apply path) can dry-run applying the manifest as the provider field owner with ForceOwnership — exactly what an update would do — and diff the result against the live object. This shows precisely the fields the manifest would change, even for a resource currently owned entirely by another actor (the import scenario), while leaving fields the manifest does not mention untouched.
This collapses the observe → tag-only-ProviderConfig → 403-hunting detour into simply reading the UpToDate condition on an observe-only Object.
Notes / scope
- Depends on the crossplane-runtime UpToDate work (crossplane/crossplane-runtime#945); provider-kubernetes needs to populate
ExternalObservation.Diff and derive up-to-date-ness meaningfully in observe mode.
- Applies to both the cluster-scoped (
v1alpha2) and namespaced (v1alpha1) Object controllers.
- Open design questions worth discussing on the PR: whether connection details should be published for observe-only resources, diff-message truncation for large diffs, and human-friendly rendering of the diff.
What problem are you facing?
When adopting an existing Kubernetes resource into Crossplane, we run the
ObjectinObserve-only mode first, to prove the import is a no-op before granting the provider write access. The goal is a "zero-diff import": Crossplane should not want to change anything about the resource (beyond, in the AWS-provider analogy, tags) before we consider it safe to manage.Today an observe-only
Objectgives us no visibility into what Crossplane would change if we switched it to update mode.spec.forProvidervsstatus.atProvidercomparison is manual and, in observe mode, the provider owns no fields so there is nothing meaningful to compare. To actually flush out would-be changes we currently have to perform a convoluted state-machine step: flip the management policy from observe to update while simultaneously swapping the ProviderConfig to a permissions-restricted (e.g. tag-only) role, so that any attempted change beyond the allowed set is rejected with a 403, and then trace the 403 back to the offending field. That is slow, error-prone, and requires a credential-rotation dance.We would like a first-class signal, available while the resource is still observe-only and untouched, that answers: "when I switch this Object to update mode, what actually changes on the live resource?"
How could Crossplane help solve your problem?
crossplane-runtime is adding an
UpToDatestatus condition to the managed reconciler (see crossplane/crossplane-runtime#945, tracking crossplane/crossplane-runtime#939). It reflects theObserveresult as a condition with reasonsObserveMatched(True), andUpdateRestricted/UpdateRequested/UpdateFailed(False), plusReconcilePaused(Unknown), and carries a diff message on the False states.provider-kubernetes can implement this so that, for an
Object:UpToDate: True/ObserveMatched.UpToDate: False/UpdateRestricted, with a field-level diff in the condition message describing exactly what would change — and, in observe mode, without mutating the resource.The important property for the import use case is that the diff answers "what would update mode change?" independent of current field ownership. Concretely, the provider (on the server-side-apply path) can dry-run applying the manifest as the provider field owner with
ForceOwnership— exactly what an update would do — and diff the result against the live object. This shows precisely the fields the manifest would change, even for a resource currently owned entirely by another actor (the import scenario), while leaving fields the manifest does not mention untouched.This collapses the observe → tag-only-ProviderConfig → 403-hunting detour into simply reading the
UpToDatecondition on an observe-onlyObject.Notes / scope
ExternalObservation.Diffand derive up-to-date-ness meaningfully in observe mode.v1alpha2) and namespaced (v1alpha1)Objectcontrollers.