Repository navigation
Replies: 2 comments
TriageVerdict: a reproducible bug in the Databases walkthrough's Is this a misuse of humus?No. The behaviour is the walkthrough's own code: its
Is it a feature request?No. Three promises cover it:
A fix changes the walkthrough's Is it reproducible?Yes. At 02f0286, with Go 1.27.0, client-go v0.37.1,
In both unit tests, all three Deleted while the next reconcile waits to provision: the Secret comes back with the old password. The
All four runs showed the same order. Deleted once the reconciles have settled: the password rotates. The same scenario, with the delete 9s after The report is right about the mechanism, and its reproduction is the first unit scenario. Three things it didn't say:
WhyThe Secret is the password's source of truth, and
In CI, the cases run in parallel under #1251 is filed to fix it:
|
|
Fixed by #1251, in #1252 (merged as 51986b1). The Reconciler's apply of the Secret now names the UID of the Secret it read. The API server creates a Secret an apply names that doesn't exist, but not one whose UID it names. So once that Secret is deleted, the apply fails with a conflict instead of bringing it back with the old password. On that conflict the reconcile rotates there and then: a new password, set on the role, then a new Secret. The deletion's own reconcile then keeps the new password. The triage's unit and k3s reproductions are in |
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
What happens
The shared
Rotationcase of the Databases walkthrough fails intermittently, onmain, in the merge queue and on PRs. It fails under both Databases walkthrough (testcontainers) and Databases walkthrough (kind), e.g. run 39619448817 onmain:It has failed this way 10 times since 2026-10-20, out of about 200 CI runs, about 1 in 20:
mainmainmainmainThe case deletes the
Database's Secret and waits for a Secret with a new UID. One comes, but it has the old password, socases.go:102fails. The rotation is lost for good: every later reconcile finds the new Secret and keeps the password in it.The Rotation section says deleting the Secret rotates the password.
Why
This hasn't been triaged. What follows comes from the code and a reproduction.
Reconcilereads the password from the Secret with aGet, provisions the role with it, then applies the Secret with server-side apply. If the Secret is deleted after theGetand before the apply, the apply creates a new Secret, with a new UID, holding the password theGetread. The deletion's reconcile then finds that Secret and keeps its password.A reconcile is likely in flight when the case deletes the Secret: the Controller owns Secrets, so the first reconcile's own Secret apply and status update each queue another reconcile of the
Database, and under CI's load, with the eight cases in parallel under-race, one of them can still be running.Reproduction. This test, added to
example/databases/controllerat 02f0286, has the delete land right after the reconcile'sGet. It fails every time (-count=3), with the Secret holding the old password:Expected
Deleting a
Database's Secret always rotates its password, whenever the delete lands. TheRotationcase passes whenever the controller works.References
Reconciler.passwordandapplySecretRotationcaseAll reactions