Skip to content

feat(component): add OrphanWhen to release a resource without deleting it#145

Merged
sourcehawk merged 5 commits into
mainfrom
feature/orphan-when
Jun 2, 2026
Merged

feat(component): add OrphanWhen to release a resource without deleting it#145
sourcehawk merged 5 commits into
mainfrom
feature/orphan-when

Conversation

@sourcehawk
Copy link
Copy Markdown
Owner

Description

Adds a component.OrphanWhen(cond) resource option that releases a managed resource instead of deleting it: when the condition is true, the component removes the controller owner reference it set and stops managing the resource, leaving the object in the cluster. The motivating use is migrating a resource to a new owner without deleting it, since removing the owner reference both stops garbage-collection with the old owner and unblocks adoption by a new one.

Changes

  • Add component.OrphanWhen(condition bool) ResourceOption (additive, OR semantics). It is a build-time configuration error to combine it with Delete, DeleteWhen, GatedBy, or ReadOnly.
  • Add a release reconcile pass (orphanResources): for each orphaned resource it fetches the live object and removes only this owner's controller owner reference (matched by UID) via a fetch-and-update, preserving all other fields. It never applies desired state, never deletes, contributes no health, and is idempotent (a missing object or already-absent reference is a no-op; conflicts are retried).
  • Orphaned resources are partitioned into a separate set excluded from allManagedResources(), so a disabled component feature gate never deletes an orphan-marked resource. The pass runs in all three reconcile paths (normal, suspended, feature-gate-disabled).

Challenges

Ownership is removed with a fetch-and-update of the live object rather than a Server-Side Apply. Because the component applies with forced ownership, an SSA of a stripped-down object would drop the spec fields its field manager owns and revert the resource's content; editing only metadata.ownerReferences on the fetched object preserves everything else.

Related

Documentation (the component.md resource-options table and the IncludeWhen-vs-GatedBy guidance) is updated separately on the docs site branch.

Testing

Unit tests cover option resolution and the four exclusivity errors; fake-client tests cover the pass (owner reference removed, object survives, idempotent, only this owner's reference removed, not-found no-op) and the wired Reconcile path. A new E2E test on a real kind cluster proves the payoff end to end: it garbage-collects a control resource after the owner is deleted (confirming GC is active) and asserts the orphaned resource survives owner deletion with its owner reference gone. make all passes; make e2e-component passes (13/13).

Copilot AI review requested due to automatic review settings June 2, 2026 02:48
Copy link
Copy Markdown

Copilot AI left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Adds a new component.OrphanWhen(cond) resource option that releases a managed resource by removing the component's controller owner reference from the live object, leaving the object in the cluster. This supports migrating resources to a new owner without triggering garbage collection. The change introduces a separate orphanResources slice on the Component, a dedicated reconcile pass (orphanResources) that fetch-and-updates only metadata.ownerReferences, and runs the pass in all three reconcile paths (normal, suspended, feature-gate-disabled).

Changes:

  • New OrphanWhen resource option with OR-semantics and exclusivity validation against Delete/DeleteWhen/GatedBy/ReadOnly.
  • New orphanResources reconcile pass using fetch-and-update + retry-on-conflict, idempotent and not-found tolerant.
  • Builder partitions orphan-marked resources into their own slice (excluded from allManagedResources()), and Reconcile invokes the pass in normal, suspended, and feature-gate-disabled paths.

Reviewed changes

Copilot reviewed 8 out of 8 changed files in this pull request and generated no comments.

Show a summary per file
File Description
pkg/component/resource_options.go Adds OrphanWhen, Orphan resolved option, and exclusivity validation.
pkg/component/resource_options_test.go Unit tests for orphan resolution and exclusivity errors.
pkg/component/orphan.go New orphanResources pass: fetch live object, strip owner UID from refs, update, retry on conflict.
pkg/component/orphan_test.go Fake-client tests covering removal, idempotency, not-found, and selective UID removal.
pkg/component/orphan_integration_test.go Builder-level partition test and end-to-end Reconcile path test.
pkg/component/component.go Adds orphanResources field and invokes the pass in all three reconcile paths.
pkg/component/builder.go Routes orphan-marked resources to the new slice via a switch on resolved options.
e2e/component/orphan_test.go Kind-cluster E2E proving the orphaned object survives owner GC while a control object does not.

@sourcehawk sourcehawk merged commit 1196e4b into main Jun 2, 2026
4 checks passed
@sourcehawk sourcehawk deleted the feature/orphan-when branch June 2, 2026 02:52
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants