Repository navigation
Conversation
DefaultStrategy never touched metadata.generation, and neither does the upstream machinery around it: BeforeCreate sets no generation at all, and BeforeUpdate only copies the stored value forward so clients cannot forge it. Upstream leaves the increment to each resource's own strategy, so a resource served through this kit stayed at generation 0 for its whole life. That is quietly destructive for controllers, because it makes every `status.observedGeneration == metadata.generation` comparison trivially true: an idempotence short-circuit written against it latches after the first reconcile and the resource is never reconciled for a spec edit again. It is also invisible to envtest, which serves real CRDs through the real apiserver and does increment generation, so the behaviour only diverges once a resource is served from an aggregated server built with this kit. A resource opts in by implementing GenerationTracker, which answers the one question a generic strategy cannot: whether its spec changed. Implementations compare their own typed spec, so there is no reflection and no guessing at which field is the "spec". Opt-in rather than automatic because turning it on changes what every controller watching a resource observes. Only a spec change increments: metadata-only edits must not make controllers re-reconcile. Status updates never reach this path, because the status subresource installs a strategy that calls only its own override.
|
Understand this PR’s impact Explore downstream dependencies and potential security impact with Blast Radius. Important
This repository does not receive automatic reviews because it has fewer than 10 stars. ⚙️ Run configuration
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info
📝 Walkthrough
🚥 Pre-merge checks | ✅ 5
✨ Finishing Touches
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
Coverage Report for CI Build 38731468667Coverage increased (+1.3%) to 39.419%Details
Uncovered ChangesNo uncovered changes found. Coverage RegressionsNo coverage regressions found. Coverage Stats
💛 - Coveralls |
What
DefaultStrategy never touched metadata.generation, and neither does the upstream machinery around it: BeforeCreate sets no generation at all, and BeforeUpdate only copies the stored value forward so clients cannot forge it. Upstream leaves the increment to each resource's own strategy, so a resource served through this kit stayed at generation 0 for its whole life.
That is quietly destructive for controllers, because it makes every
status.observedGeneration == metadata.generationcomparison trivially true: an idempotence short-circuit written against it latches after the first reconcile and the resource is never reconciled for a spec edit again. It is also invisible to envtest, which serves real CRDs through the real apiserver and does increment generation, so the behaviour only diverges once a resource is served from an aggregated server built with this kit.A resource opts in by implementing GenerationTracker, which answers the one question a generic strategy cannot: whether its spec changed. Implementations compare their own typed spec, so there is no reflection and no guessing at which field is the "spec". Opt-in rather than automatic because turning it on changes what every controller watching a resource observes.
Only a spec change increments: metadata-only edits must not make controllers re-reconcile. Status updates never reach this path, because the status subresource installs a strategy that calls only its own override.
Why
Handling generations is a hassle, this PR eases this somewhat. :)
Testing
Unit tests
Notes for reviewers
No breaking changes, purely opt-in!
Checklist
Summary by CodeRabbit