status: sort isUpgrading messages to prevent ClusterOperator write loop#481
status: sort isUpgrading messages to prevent ClusterOperator write loop#481sdodson wants to merge 2 commits into
Conversation
isUpgrading() iterates over a map[string]string to build upgrade status messages. Go map iteration order is randomized, so when multiple operands are upgrading simultaneously (e.g. coredns and kube-rbac-proxy), the returned messages slice has a non-deterministic order on each call. This non-determinism caused a self-sustaining write loop during upgrades: 1. isUpgrading() produces messages in order [A, B] 2. operatorStatusesEqual() returns false (Message differs from stored) 3. ClusterOperator is written 4. The CO watch fires, triggering another reconcile 5. isUpgrading() produces messages in order [B, A] 6. operatorStatusesEqual() returns false again 7. ClusterOperator is written again -> goto 4 The result was the ClusterOperator being updated many times per second for the entire duration of an upgrade, as observed via 'oc get co -w'. Fix by sorting the messages slice before returning from isUpgrading(), making the output deterministic and breaking the loop. Adds a unit test that calls isUpgrading() 100 times with multiple upgrading components and asserts stable message ordering. rh-pre-commit.version: 2.4.0 rh-pre-commit.check-secrets: ENABLED
|
Skipping CI for Draft Pull Request. |
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Repository: openshift/coderabbit/.coderabbit.yaml Review profile: CHILL Plan: Enterprise Run ID: 📒 Files selected for processing (1)
🚧 Files skipped from review as they are similar to previous changes (1)
Walkthrough
ChangesDeterministic upgrade message ordering
Estimated code review effort🎯 1 (Trivial) | ⏱️ ~3 minutes 🚥 Pre-merge checks | ✅ 14 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (14 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
|
[APPROVALNOTIFIER] This PR is NOT APPROVED This pull-request has been approved by: The full list of commands accepted by this bot can be found here. DetailsNeeds approval from an approver in each of these files:Approvers can indicate their approval by writing |
There was a problem hiding this comment.
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 `@pkg/operator/controller/status/controller_test.go`:
- Around line 833-845: The test around isUpgrading only compares each result to
the first observed slice, which doesn’t assert the intended sorting contract.
Update the assertion in controller_test.go to compare messages directly against
the explicit expected sorted slice returned by isUpgrading, using the
isUpgrading symbol and the current/old/new version inputs to keep the test
deterministic.
🪄 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: Repository: openshift/coderabbit/.coderabbit.yaml
Review profile: CHILL
Plan: Enterprise
Run ID: ef0d9424-261b-4195-a5c0-36e47b155d27
📒 Files selected for processing (2)
pkg/operator/controller/status/controller.gopkg/operator/controller/status/controller_test.go
The previous assertion compared each isUpgrading() result against the first observed slice. If the first call happened to return messages in a non-sorted order (e.g. after a future regression), subsequent calls matching that same bad order would still pass the test. Replace the first-observed baseline with an explicit, hardcoded expected slice in lexicographic order. This directly asserts the sorting contract rather than merely checking consistency across calls. rh-pre-commit.version: 2.4.0 rh-pre-commit.check-secrets: ENABLED
Problem
During a cluster upgrade,
oc get co -wshows thednsClusterOperator being updated many times per second, even when the pod counts in the Progressing message haven't changed.Root Cause
isUpgrading()iterates over amap[string]stringto build upgrade status messages. Go map iteration order is randomized, so when multiple operands are upgrading simultaneously (e.g.corednsandkube-rbac-proxy), the returnedmessagesslice has a non-deterministic order on each call.This caused a self-sustaining write loop:
isUpgrading()produces messages in order[A, B]operatorStatusesEqual()returns false (Message differs from stored)isUpgrading()produces messages in order[B, A]operatorStatusesEqual()returns false againFix
Sort the
messagesslice before returning fromisUpgrading(), making the output deterministic and breaking the loop.Testing
Added a unit test that calls
isUpgrading()100 times with multiple upgrading components and asserts the messages are always returned in the same sorted order.Summary by CodeRabbit