Skip to content

fix: use ownership instead of revision to guard teardown deletion#542

Open
erdii wants to merge 3 commits into
package-operator:mainfrom
erdii:drop-revision-comparison-on-teardown-orphan
Open

fix: use ownership instead of revision to guard teardown deletion#542
erdii wants to merge 3 commits into
package-operator:mainfrom
erdii:drop-revision-comparison-on-teardown-orphan

Conversation

@erdii

@erdii erdii commented Jun 5, 2026

Copy link
Copy Markdown
Member

When an Owner is provided, check whether we are the controller via
detectOwner rather than comparing revision annotations. Owner refs
are the authoritative signal for ownership and correctly handle
orphaning deletions where the revision annotation may have been
updated by a different reconciliation pass. Callers without an
Owner fall back to the existing revision comparison.

Summary

Change Type

Check List Before Merging

  • This PR passes all pre-commit hook validations.
  • This PR is fully tested and regression tests are included.
  • Relevant documentation has been updated.

Additional Information

@erdii erdii requested a review from a team as a code owner June 5, 2026 11:23
@coderabbitai

coderabbitai Bot commented Jun 5, 2026

Copy link
Copy Markdown
Contributor

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: a0d8cd1d-4cf6-435a-9e40-ed34597cc713

📥 Commits

Reviewing files that changed from the base of the PR and between 6dd5ae6 and b4f4349.

📒 Files selected for processing (1)
  • machinery/objects_test.go
💤 Files with no reviewable changes (1)
  • machinery/objects_test.go

Walkthrough

Teardown now branches on options.Owner to either use owner/controller checks or fall back to revision matching. The tests were updated for the new mode-aware teardown behavior and a new integration case covers adoption and owner-reference removal.

Changes

Owner-aware object teardown flow

Layer / File(s) Summary
Teardown branching
machinery/objects.go
Teardown branches on options.Owner, patches non-controller owner references, and skips deletion on revision mismatch when no owner is provided.
Teardown unit scenarios
machinery/objects_test.go
TestObjectEngine_Teardown updates its mode-aware setup, adjusts revision-mismatch expectations, adds new owner-state cases, and asserts the teardown mocks after execution.
Integration teardown path
test/objects_test.go
TestObjectEngine_TeardownNotControllerRevisionMatch creates two owners, simulates adoption, verifies owner-reference removal for the non-controller, and verifies controller teardown deletes on the second call.

🎯 3 (Moderate) | ⏱️ ~25 minutes

🚥 Pre-merge checks | ✅ 5
✅ Passed checks (5 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: teardown now uses ownership instead of revision when deciding whether to delete.
Description check ✅ Passed The description captures the ownership-vs-revision behavior and includes a completed checklist; the template is mostly followed.
Docstring Coverage ✅ Passed Docstring coverage is 100.00% which is sufficient. The required threshold is 80.00%.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Comment @coderabbitai help to get the list of available commands.

@erdii erdii force-pushed the drop-revision-comparison-on-teardown-orphan branch from 43dae05 to f3558d8 Compare June 5, 2026 11:25
@codecov

codecov Bot commented Jun 5, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 71.42857% with 2 lines in your changes missing coverage. Please review.
✅ Project coverage is 82.70%. Comparing base (42e572f) to head (b4f4349).
⚠️ Report is 7 commits behind head on main.

Files with missing lines Patch % Lines
machinery/objects.go 71.42% 1 Missing and 1 partial ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main     #542      +/-   ##
==========================================
+ Coverage   82.68%   82.70%   +0.01%     
==========================================
  Files          32       32              
  Lines        2737     2740       +3     
==========================================
+ Hits         2263     2266       +3     
  Misses        346      346              
  Partials      128      128              

☔ View full report in Codecov by Harness.
📢 Have feedback on the report? Share it here.

🚀 New features to boost your workflow:
  • ❄️ Test Analytics: Detect flaky tests, report on failures, and find test suite problems.

When an Owner is provided, check whether we are the controller via
detectOwner rather than comparing revision annotations. Owner refs
are the authoritative signal for ownership and correctly handle
orphaning deletions where the revision annotation may have been
updated by a different reconciliation pass. Callers without an
Owner fall back to the existing revision comparison.
@erdii erdii force-pushed the drop-revision-comparison-on-teardown-orphan branch from f3558d8 to 90da9d2 Compare June 8, 2026 09:23
Comment thread machinery/objects.go
@@ -173,6 +164,16 @@ func (e *ObjectEngine) Teardown(
// TODO should we check if the patch differs from actualObject before firing the request?
return true, e.writer.Patch(ctx, patch, client.MergeFrom(actualObject))

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

i think using a merge patch here is dangerous and could result in accidentally overwriting the object.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Maybe sending an empty SSA intent with resourceVersion set to the observer version from actualObject instead is safe?

This would:

  • give us 100% certainty that we know what we're overwriting because of optimistic locking
  • remove all field values that we still own from the object including the owner reference

There's a pitfall though: Other actors in the system would have to deliberately own all fields that they want to keep when we tear down the object.

@erdii erdii Jun 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Do we actually have to remove the owner ref at all?

Asumme:

  • we have owner-old and owner-new.
  • owner-new takes the controlling owner reference and demotes our owner reference to non controlling. (It actually doesn't matter if the owner ref is demoted or not.)
  • teardown of the owner-old is triggered

then:

  1. we skip deletion of the managed object during teardown
  2. we remove the owner-old
  3. the owner ref to owner-old starts dangling
  4. the kubernetes garbage collector removes the danling owner ref
  5. the managed object still exists.

@erdii erdii Jun 19, 2026

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

So the case where ownership is transfered to a new owner is handled.

I think the only dangerous case is where our owner ref is demoted from controller: true to controller: false without adding a new owner.
If that's the case and we don't remove our owner ref then the garbage collector would still remove the managed object after the owner is deleted.

@pbabic-redhat pbabic-redhat left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Couple of small testing comments.

Comment thread machinery/objects_test.go Outdated
Comment on lines +1411 to +1414
afterAssert: func(t *testing.T, writer *testutil.CtrlClient) {
t.Helper()
writer.AssertNotCalled(t, "Delete")
},

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Won't the call to "Delete" fail if the mock was not setup with it (i.e., not called w.On("Delete",...)) anyway? If so, afterAssert might be unnecessary.

Comment thread machinery/objects_test.go Outdated
Comment on lines +1494 to +1496
if tc.afterAssert != nil {
tc.afterAssert(t, writer)
}

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

I would instead call AssertExpectations with all the mocks. I've seen so many tests that still don't have it. It can cause weird silent failures.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

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

Nice observation! Totally agree that AssertExpectations should be used everywhere. I've pushed a commit that addresses your concerns atleast for the teardown tests.

Let me know what you think and if you like it I'll squash the commits together.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In `@machinery/objects_test.go`:
- Around line 1254-1255: Remove the stale commented-out mock expectations for
the writer.On Delete method calls that are triggering dupword lint failures.
Delete the entire commented blocks containing writer.On("Delete", mock.Anything,
mock.Anything, mock.Anything) and its associated Panic statement at both
locations mentioned (lines 1254-1255 and lines 1285-1286) as these expectations
are no longer needed and cause CI failures.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Enterprise

Run ID: a1d991d3-a3c8-444f-bab5-b6bfbf9bc494

📥 Commits

Reviewing files that changed from the base of the PR and between 90da9d2 and 6dd5ae6.

📒 Files selected for processing (1)
  • machinery/objects_test.go

Comment thread machinery/objects_test.go Outdated
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