Skip to content

OCPBUGS-85677, OCPBUGS-90541: Don't set Progressing=False until all pods available - #3095

Open
jluhrsen wants to merge 2 commits into
openshift:masterfrom
jluhrsen:fix-progressing-false-timing
Open

OCPBUGS-85677, OCPBUGS-90541: Don't set Progressing=False until all pods available#3095
jluhrsen wants to merge 2 commits into
openshift:masterfrom
jluhrsen:fix-progressing-false-timing

Conversation

@jluhrsen

Copy link
Copy Markdown
Contributor

No description provided.

We don't want the ClusterOperator to report Progressing=True whenever a
Node reboots. However, we also don't want to report Progressing=False
during a CNI rollout until all pods are available. This change ensures
both are covered.
@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. labels Jul 29, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@jluhrsen: This pull request references Jira Issue OCPBUGS-85677, which is valid.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state POST, which is one of the valid states (NEW, ASSIGNED, POST)

The bug has been updated to refer to the pull request using the external bug tracker.

This pull request references Jira Issue OCPBUGS-90541, which is valid. The bug has been moved to the POST state.

3 validation(s) were run on this bug
  • bug is open, matching expected state (open)
  • bug target version (5.0.0) matches configured target version for branch (5.0.0)
  • bug is in the state New, which is one of the valid states (NEW, ASSIGNED, POST)

No GitHub users were found matching the public email listed for the QA contact in Jira (core-networking-bot@redhat.com), skipping review request.

The bug has been updated to refer to the pull request using the external bug tracker.

Details

In response to this:

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the openshift-eng/jira-lifecycle-plugin repository.

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Pipeline controller notification
This repo is configured to use the pipeline controller. Second-stage tests will be triggered either automatically or after lgtm label is added, depending on the repository configuration. The pipeline controller will automatically detect which contexts are required and will utilize /test Prow commands to trigger the second stage.

For optional jobs, comment /test ? to see a list of all defined jobs. To trigger manually all jobs from second stage use /pipeline required command.

This repository is configured in: LGTM mode

@coderabbitai

coderabbitai Bot commented Jul 29, 2026

Copy link
Copy Markdown

Summary by CodeRabbit

  • Bug Fixes
    • Improved rollout status tracking for DaemonSets, Deployments, and StatefulSets.
    • More accurately identifies resources that have completed a stable rollout.
    • Prevents premature or lingering “Progressing” states during rollouts and availability delays.
    • Preserves rollout state across restarts and upgrades.
  • Chores
    • Added automatic migration of existing resources to the updated rollout-tracking behavior.

Walkthrough

Rollout tracking now uses an observed stable generation annotation for DaemonSets, StatefulSets, and Deployments. Stable objects receive the annotation, progression checks use it as the gating signal, timestamps use the injected clock, and tests cover updated rollout and restart behavior.

Changes

Stable generation rollout tracking

Layer / File(s) Summary
Stable generation contract and migration
pkg/names/names.go, pkg/controller/statusmanager/status_manager.go, pkg/controller/statusmanager/pod_status.go
Adds the annotation constant, one-time migration state, generation comparison helper, and migration seeding logic.
Workload progression and annotation updates
pkg/controller/statusmanager/pod_status.go
Updates DaemonSet, StatefulSet, and Deployment progression decisions, records stable generations after availability, and uses status.clock.Now() for change timestamps.
Progression and state restoration validation
pkg/controller/statusmanager/status_manager_test.go
Updates test helpers and rollout expectations, adds table-driven coverage, uses deterministic fake-clock timing, and adjusts restart and crash-loop scenarios.

Estimated code review effort: 4 (Complex) | ~45 minutes

Sequence Diagram(s)

sequenceDiagram
  participant SetFromPods
  participant WorkloadStatus
  participant ObjectAnnotations
  SetFromPods->>WorkloadStatus: read generation and availability status
  WorkloadStatus-->>SetFromPods: report stable or progressing state
  SetFromPods->>ObjectAnnotations: write observed-stable-generation
Loading

Suggested reviewers: taanyas, jcaamano


Caution

Pre-merge checks failed

Please resolve all errors before merging. Addressing warnings is optional.

  • Ignore

❌ Failed checks (6 errors, 2 warnings, 1 inconclusive)

Check name Status Explanation Resolution
Title check ❌ Error The title is related, but it exceeds 72 characters and lacks the required component prefix. Use an imperative title under 72 characters and add the scoped component prefix, e.g. 'statusmanager: Fix Progressing timing'.
Pr Quality ❌ Error Scope is fine, but the PR text lacks the required Why/What/Testing sections and CI lane details. Add PR body sections for Why, What, and Testing/How to verify (CI jobs/platforms), plus root-cause, user impact, and rollback notes.
Commit Message Quality ❌ Error Both PR commits have clear bodies, but neither subject is prefixed with the affected component, violating the commit-message format guidance. Rewrite each subject with the relevant component prefix (e.g. statusmanager:, names:) and keep the existing bodies focused on intent.
E2e Tests For Feature Changes ❌ Error Status-manager rollout behavior changed in pkg/, but no test/e2e/ files changed and no PR Testing/How to verify it section is present/verified. Add e2e coverage under test/e2e/, or document why it’s infeasible in the PR under “How to verify it” with CI lanes/platforms/results, then use @coderabbitai ignore pre-merge checks.
Stale Project Docs And Config ❌ Error docs/architecture.md and docs/operands.md still describe status tracking for only DaemonSets/Deployments, but the PR adds StatefulSet rollout handling. Update the affected docs/config in this PR to mention StatefulSets and the observed-stable-generation behavior, or explain any intentional omission in a PR comment and override with @coderabbitai ignore pre-merge checks.
Ai-Generated Code Smell ❌ Error New test includes a stale comment that restates the assertion and no longer matches the table-driven cases. Remove the redundant comment or rewrite it to describe the test intent without echoing the code.
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Go And Test Code Quality ⚠️ Warning New code in pkg/controller/statusmanager/pod_status.go adds multiple log.Printf calls; this repo requires klog-only logging in production code. Replace the added log.Printf calls with klog (e.g. klog.Errorf/V) or propagate wrapped errors instead of logging directly.
Description check ❓ Inconclusive No description was provided, so the pull request context is too sparse to assess beyond the code changes. Add a brief description of the rollout-status behavior change and the affected statusmanager tests.
✅ Passed checks (15 passed)
Check name Status Explanation
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.
Unit Tests For Go Changes ✅ Passed Production Go files changed, and pkg/controller/statusmanager/status_manager_test.go was modified in the same PR.
Rbac Least Privilege ✅ Passed No YAML files under bindata/ or manifests/ changed in the PR diff, so no RBAC rules were added or modified.
Docs For Feature And Behavior Changes ✅ Passed PASS: This is a bug fix for Progressing timing/internal status tracking; no docs/ files were changed, and existing docs already cover the general status behavior.
Stable And Deterministic Test Names ✅ Passed Added test titles are static t.Run strings; no generated pod/namespace/IP/timestamp values appear in names.
Test Structure And Quality ✅ Passed Tests use fake clients/clocks, avoid Ginkgo wait patterns, and include clear failure messages; no cleanup or timeout issues were introduced.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the changes are plain unit tests in pkg/controller/statusmanager with no MicroShift-skipped markers or unsupported OpenShift API usage.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo/e2e tests were added; status_manager_test.go uses testing.T unit tests and has no SNO-relevant multi-node assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed Changed files are status-manager logic/tests only; no nodeSelector/affinity/spread/PDB/replica-count scheduling code or topology labels were added.
Ote Binary Stdout Contract ✅ Passed No stdout writes were added in main/init/TestMain/suite setup; the new logs are runtime/test-local and use stderr by default.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the touched tests are standard unit tests and show no IPv4-only or external connectivity assumptions.
No-Weak-Crypto ✅ Passed The touched files only add generation-annotation logic and tests; no MD5/SHA1/DES/RC4/3DES/Blowfish, crypto APIs, or secret comparisons appear.
Container-Privileges ✅ Passed PASS: Changes are Go-only; no container/K8s manifests were modified, and no privileged/hostPID/hostNetwork/hostIPC/SYS_ADMIN/allowPrivilegeEscalation settings were found.
No-Sensitive-Data-In-Logs ✅ Passed New logs only report workload kind/name/namespace on annotation update failures; no passwords, tokens, PII, hostnames, or customer data are logged.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@jluhrsen

Copy link
Copy Markdown
Contributor Author

/payload-aggregate periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-ovn-upgrade-ipsec 10

/pipeline required

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e-aws-ovn-upgrade-ipsec
/test e2e-gcp-ovn-techpreview

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aws-ovn-fdp-qe
/test e2e-aws-ovn-hypershift-conformance
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-upgrade
/test e2e-aws-ovn-windows
/test e2e-azure-ovn-upgrade
/test e2e-gcp-ovn
/test e2e-gcp-ovn-upgrade
/test e2e-metal-ipi-ovn-dualstack-bgp
/test e2e-metal-ipi-ovn-dualstack-bgp-local-gw
/test e2e-metal-ipi-ovn-ipv6
/test e2e-metal-ipi-ovn-ipv6-ipsec
/test e2e-ovn-ipsec-step-registry
/test hypershift-e2e-aks

@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@jluhrsen: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-ovn-upgrade-ipsec

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/954d4ec0-8b67-11f1-9f2c-80a779d0e75b-0

@openshift-ci
openshift-ci Bot requested review from jcaamano and taanyas July 29, 2026 16:11
@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: jluhrsen
Once this PR has been reviewed and has the lgtm label, please assign danwinship for approval. For more information see the Code Review Process.

The full list of commands accepted by this bot can be found here.

Details Needs approval from an approver in each of these files:

Approvers can indicate their approval by writing /approve in a comment
Approvers can cancel approval by writing /approve cancel in a comment

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

🧹 Nitpick comments (1)
pkg/controller/statusmanager/pod_status.go (1)

73-283: 📐 Maintainability & Code Quality | 🔵 Trivial

Verify e2e coverage for this user-facing Progressing behavior change.

SetFromPods now changes when the ClusterOperator's Progressing condition flips to False during node reboots/CNI rollouts (the stated goal of OCPBUGS-85677/90541). Only unit tests were included in this review; no test/e2e/ changes were provided.

Can you confirm whether corresponding test/e2e/ coverage and a PR "Testing"/"How to verify it" section (CI lanes, platform coverage, results) exist for this change?

As per path instructions, "For new or modified Go code under pkg/ that changes user-facing behavior or fixes a bug, add or modify corresponding files under test/e2e/, and include a PR Testing or How to verify it section describing CI lanes, platform coverage, and test results."

🤖 Prompt for 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.

In `@pkg/controller/statusmanager/pod_status.go` around lines 73 - 283, Add or
update test/e2e coverage for the user-facing Progressing condition behavior
changed in SetFromPods, specifically during node reboots and CNI rollouts,
covering the OCPBUGS-85677/90541 scenarios. Ensure the pull request includes a
Testing or How to verify it section documenting CI lanes, platform coverage, and
test results.

Source: Path instructions

🤖 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/controller/statusmanager/status_manager_test.go`:
- Around line 89-120: Fix the annotation merge in set() so it preserves both
annotations already persisted on current and new annotations on obj. Start with
a separate copy of current.GetAnnotations(), then copy obj.GetAnnotations() into
it before calling obj.SetAnnotations(merged); retain the existing
resource-version update and create/update behavior.

---

Nitpick comments:
In `@pkg/controller/statusmanager/pod_status.go`:
- Around line 73-283: Add or update test/e2e coverage for the user-facing
Progressing condition behavior changed in SetFromPods, specifically during node
reboots and CNI rollouts, covering the OCPBUGS-85677/90541 scenarios. Ensure the
pull request includes a Testing or How to verify it section documenting CI
lanes, platform coverage, and test results.
🪄 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 YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 5b1343dd-4349-429c-b49e-01a0b46739b5

📥 Commits

Reviewing files that changed from the base of the PR and between 00e6cc5 and 61d6f6c.

📒 Files selected for processing (3)
  • pkg/controller/statusmanager/pod_status.go
  • pkg/controller/statusmanager/status_manager_test.go
  • pkg/names/names.go

Comment thread pkg/controller/statusmanager/status_manager_test.go
Adds a networkoperator.openshift.io/observed-stable-generation
annotation to CNO operands when they are observed stable. Unlike the
copy of the object's status temporarily stored in a ClusterOperator
annotation during a rollout, this is persistent state.

With this change, an operand is rolling out if:
* Its observed generation does not match its generation
* It is not currently available and it has never been observed stable at
  this generation

That is, a rollout completes once we have observed a stable rollout at a
particular generation at least once. Therefore:
* We only go Progressing=False once all pods are available
* We do not subsequently go Progressing=False unless the operand's
  generation changes, i.e. a for a spec change
@openshift-pr-manager

Copy link
Copy Markdown

/test 5.0-upgrade-from-stable-4.22-e2e-aws-ovn-upgrade

👻🚫 retest requested by jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test 5.0-upgrade-from-stable-4.22-e2e-gcp-ovn-upgrade

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-aws-ovn-fdp-qe

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-aws-ovn-hypershift-conformance

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-aws-ovn-upgrade

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-aws-ovn-upgrade-ipsec

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-gcp-ovn

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-gcp-ovn-techpreview

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-metal-ipi-ovn-dualstack-bgp-local-gw

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-metal-ipi-ovn-ipv6-ipsec

👻🚫 auto-retest triggered for jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/payload-job periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-ovn-upgrade-ipsec

👻🚫 retest requested by jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test e2e-ovn-ipsec-step-registry

👻🚫 retest requested by jluhrsen@redhat.com via Flake Buster

@openshift-pr-manager

Copy link
Copy Markdown

/test hypershift-e2e-aks

👻🚫 retest requested by jluhrsen@redhat.com via Flake Buster

@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@openshift-pr-manager[bot]: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-ovn-upgrade-ipsec

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/c59c8530-8ba5-11f1-8d0d-1cc3603e6024-0

@jluhrsen

Copy link
Copy Markdown
Contributor Author

/payload-aggregate periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-ovn-upgrade-ipsec 10

@jluhrsen
jluhrsen force-pushed the fix-progressing-false-timing branch from 61d6f6c to 256039d Compare July 29, 2026 23:48
@openshift-ci

openshift-ci Bot commented Jul 29, 2026

Copy link
Copy Markdown
Contributor

@jluhrsen: trigger 1 job(s) for the /payload-(with-prs|job|aggregate|job-with-prs|aggregate-with-prs) command

  • periodic-ci-openshift-release-main-nightly-4.22-e2e-aws-ovn-upgrade-ipsec

See details on https://pr-payload-tests.ci.openshift.org/runs/ci/f70d9da0-8ba7-11f1-8261-77f45802b631-0

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 4

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
pkg/controller/statusmanager/status_manager_test.go (1)

2562-2563: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Both restart tests still justify Progressing=False via the old "UpdatedReplicas >= Replicas" rule. The gate is now observed-stable-generation alignment — which is precisely why observed-stable-generation: "1" was added to both fixtures; the comments will mislead the next reader debugging these expectations.

  • pkg/controller/statusmanager/status_manager_test.go#L2562-L2563: reword to state that beta was already observed stable at generation 1, so post-rollout unavailability is treated as reboot churn.
  • pkg/controller/statusmanager/status_manager_test.go#L2636-L2637: same rewording for the StatefulSet's unready replica.
🤖 Prompt for 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.

In `@pkg/controller/statusmanager/status_manager_test.go` around lines 2562 -
2563, The comments in both restart test fixtures still describe the obsolete
UpdatedReplicas >= Replicas completion rule. Reword the comments at
pkg/controller/statusmanager/status_manager_test.go lines 2562-2563 and
2636-2637 to state that beta was already observed stable at generation 1, so
post-rollout unavailability is treated as reboot churn; update comments only,
leaving the test behavior unchanged.

Source: Coding guidelines

🧹 Nitpick comments (2)
pkg/controller/statusmanager/status_manager_test.go (2)

120-134: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

setStatus clobbers caller-set annotations instead of merging.

Unlike set() (which now merges correctly), setStatus overwrites obj's annotations with the server copy, mutating the caller's object. No current test depends on it, but it's the same latent trap set() just fixed, and it silently drops locally-added annotations. Also, the status subresource update doesn't need annotations at all.

♻️ Mirror set()'s merge semantics
 	obj.SetResourceVersion(current.GetResourceVersion())
-	obj.SetAnnotations(current.GetAnnotations())
+	merged := make(map[string]string)
+	maps.Copy(merged, current.GetAnnotations())
+	maps.Copy(merged, obj.GetAnnotations())
+	obj.SetAnnotations(merged)
🤖 Prompt for 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.

In `@pkg/controller/statusmanager/status_manager_test.go` around lines 120 - 134,
Update setStatus to preserve caller-set annotations by merging the current
server annotations with obj’s existing annotations, matching set()’s merge
semantics, rather than replacing them. Since the status subresource update does
not require annotations, avoid mutating obj’s annotations when refreshing the
resource version before Status().Update.

1846-1857: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Cases with observedStableGeneration == 0 write "...observed-stable-generation": "0" rather than leaving it absent.

The "New " cases are meant to exercise the never-annotated path, but the helper unconditionally stamps the annotation. isObservedStable still returns false for "0" vs generation 1, so expectations hold, yet the genuinely un-annotated path — the one the one-time migration in SetFromPods keys off (annotations[...] == "") — is never covered here.

♻️ Only set the annotation when the case specifies one
-		annotations := tt.object.GetAnnotations()
-		if annotations == nil {
-			annotations = make(map[string]string, 1)
-		}
-		annotations[names.ObservedStableGenerationAnnotation] = strconv.FormatInt(tt.observedStableGeneration, 10)
-		tt.object.SetAnnotations(annotations)
+		if tt.observedStableGeneration != 0 {
+			annotations := tt.object.GetAnnotations()
+			if annotations == nil {
+				annotations = make(map[string]string, 1)
+			}
+			annotations[names.ObservedStableGenerationAnnotation] = strconv.FormatInt(tt.observedStableGeneration, 10)
+			tt.object.SetAnnotations(annotations)
+		}
🤖 Prompt for 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.

In `@pkg/controller/statusmanager/status_manager_test.go` around lines 1846 -
1857, Update the test setup around observedStableGeneration so it only adds
ObservedStableGenerationAnnotation when the case specifies a nonzero value;
leave annotations absent for zero-valued “New <workload>” cases. Preserve the
existing annotation formatting and object setup for explicitly configured
generations.
🤖 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/controller/statusmanager/pod_status.go`:
- Line 170: The timeout checks in the DaemonSet, StatefulSet, and Deployment
status paths must use the injected clock consistently. In
pkg/controller/statusmanager/pod_status.go at lines 170-170, 234-234, and
297-297, update each time.Since-based comparison to calculate elapsed time from
status.clock.Now(), matching the LastChangeTime assignments and preserving the
existing hung-rollout thresholds.
- Around line 105-106: Replace the status-manager migration failure logging
around setAnnotation in status.Update with the appropriate klog call, preserving
the existing message, namespace/name context, and error value. Also update the
other log.Printf usages in pod_status.go to klog so all status-manager failures
follow the production logging policy.

In `@pkg/controller/statusmanager/status_manager_test.go`:
- Around line 1872-1873: Remove the stale “both DSes” comment above the
table-driven assertion, or replace it with a concise description of the
single-object parameterized expectation covered by each case. Keep the assertion
and test behavior unchanged.

In `@pkg/controller/statusmanager/status_manager.go`:
- Around line 114-117: Persist or recover annotationMigrationDone in
status_manager.go so migration completion survives CNO restarts and is not rerun
when installComplete is restored; in pod_status.go, update the DaemonSet,
Deployment, and StatefulSet stable checks to require each resource’s full
availability/readiness predicates in addition to ObservedGeneration >=
Generation, preventing unavailable active rollouts from being classified as
stable. Affected sites: pkg/controller/statusmanager/status_manager.go lines
114-117; pkg/controller/statusmanager/pod_status.go lines 102-103, 111-112, and
120-121.

---

Outside diff comments:
In `@pkg/controller/statusmanager/status_manager_test.go`:
- Around line 2562-2563: The comments in both restart test fixtures still
describe the obsolete UpdatedReplicas >= Replicas completion rule. Reword the
comments at pkg/controller/statusmanager/status_manager_test.go lines 2562-2563
and 2636-2637 to state that beta was already observed stable at generation 1, so
post-rollout unavailability is treated as reboot churn; update comments only,
leaving the test behavior unchanged.

---

Nitpick comments:
In `@pkg/controller/statusmanager/status_manager_test.go`:
- Around line 120-134: Update setStatus to preserve caller-set annotations by
merging the current server annotations with obj’s existing annotations, matching
set()’s merge semantics, rather than replacing them. Since the status
subresource update does not require annotations, avoid mutating obj’s
annotations when refreshing the resource version before Status().Update.
- Around line 1846-1857: Update the test setup around observedStableGeneration
so it only adds ObservedStableGenerationAnnotation when the case specifies a
nonzero value; leave annotations absent for zero-valued “New <workload>” cases.
Preserve the existing annotation formatting and object setup for explicitly
configured generations.
🪄 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 YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: ffac25e0-051e-45a9-9587-7e84c83d5d84

📥 Commits

Reviewing files that changed from the base of the PR and between 61d6f6c and 256039d.

📒 Files selected for processing (4)
  • pkg/controller/statusmanager/pod_status.go
  • pkg/controller/statusmanager/status_manager.go
  • pkg/controller/statusmanager/status_manager_test.go
  • pkg/names/names.go

Comment on lines +105 to +106
if err := status.setAnnotation(context.TODO(), ds, names.ObservedStableGenerationAnnotation, &gen); err != nil {
log.Printf("Error migrating DaemonSet %s/%s annotation: %v", ds.Namespace, ds.Name, err)

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="pkg/controller/statusmanager/pod_status.go"

echo "== file size =="
wc -l "$file"

echo
echo "== imports and relevant symbols =="
ast-grep outline "$file" --view expanded || true

echo
echo "== relevant lines 80-140 =="
sed -n '80,140p' "$file" | cat -n

echo
echo "== search for log.Printf / klog in file =="
rg -n 'log\.Printf|klog\.' "$file" || true

Repository: openshift/cluster-network-operator

Length of output: 6059


Use klog instead of log.Printf here. This file still uses log.Printf in the migration path and elsewhere; switch these status-manager failures to klog to match the production logging policy.

🤖 Prompt for 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.

In `@pkg/controller/statusmanager/pod_status.go` around lines 105 - 106, Replace
the status-manager migration failure logging around setAnnotation in
status.Update with the appropriate klog call, preserving the existing message,
namespace/name context, and error value. Also update the other log.Printf usages
in pod_status.go to klog so all status-manager failures follow the production
logging policy.

Source: Coding guidelines


if !hadState || !reflect.DeepEqual(dsState.LastSeenStatus, ds.Status) {
dsState.LastChangeTime = time.Now()
dsState.LastChangeTime = status.clock.Now()

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🩺 Stability & Availability | 🟡 Minor | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -euo pipefail

file="pkg/controller/statusmanager/pod_status.go"

echo "== file outline / line count =="
wc -l "$file"

echo "== search for time.Since and clock usage =="
rg -n "time\.Since|status\.clock|LastChangeTime" "$file"

echo "== relevant excerpts =="
sed -n '150,190p;220,250p;280,315p' "$file"

Repository: openshift/cluster-network-operator

Length of output: 5281


🏁 Script executed:

#!/bin/bash
set -euo pipefail
sed -n '160,185p;228,245p;290,308p' pkg/controller/statusmanager/pod_status.go

Repository: openshift/cluster-network-operator

Length of output: 2280


Use the injected clock for the timeout checks. The DaemonSet, StatefulSet, and Deployment paths set LastChangeTime from status.clock, but time.Since still uses wall time, so fake or non-wall clocks can make hung-rollout detection fire too early or never. Compare against status.clock.Now() in each path.

📍 Affects 1 file
  • pkg/controller/statusmanager/pod_status.go#L170-L170 (this comment)
  • pkg/controller/statusmanager/pod_status.go#L234-L234
  • pkg/controller/statusmanager/pod_status.go#L297-L297
🤖 Prompt for 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.

In `@pkg/controller/statusmanager/pod_status.go` at line 170, The timeout checks
in the DaemonSet, StatefulSet, and Deployment status paths must use the injected
clock consistently. In pkg/controller/statusmanager/pod_status.go at lines
170-170, 234-234, and 297-297, update each time.Since-based comparison to
calculate elapsed time from status.clock.Now(), matching the LastChangeTime
assignments and preserving the existing hung-rollout thresholds.

Comment on lines +1872 to +1873
// Both DSes have unavailable pods and neither has been observed stable
// at its current generation, so Progressing must be True.

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

Stale copy-pasted comment. This table-driven assertion covers a single object per case (DS/Deployment/StatefulSet); there are no "both DSes". Drop or replace with a description of the parameterized expectation.

As per coding guidelines: "Flag obvious comment slop... Fail unless comments add genuine value."

🤖 Prompt for 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.

In `@pkg/controller/statusmanager/status_manager_test.go` around lines 1872 -
1873, Remove the stale “both DSes” comment above the table-driven assertion, or
replace it with a concise description of the single-object parameterized
expectation covered by each case. Keep the assertion and test behavior
unchanged.

Source: Coding guidelines

Comment on lines +114 to +117
// annotationMigrationDone is set after the first SetFromPods call where
// installComplete is true. It prevents the one-time migration from running
// again on subsequent calls.
annotationMigrationDone bool

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🎯 Functional Correctness | 🟠 Major | 🏗️ Heavy lift

Persist and tighten the migration boundary.

annotationMigrationDone resets on every CNO restart, but installComplete is restored. The migration therefore reclassifies post-install workloads; ObservedGeneration >= Generation does not establish availability, so an unavailable active rollout can be annotated as stable and stop reporting Progressing.

  • pkg/controller/statusmanager/status_manager.go#L114-L117: persist or recover migration completion across restarts.
  • pkg/controller/statusmanager/pod_status.go#L102-L103: require the DaemonSet’s full stable predicates, not only observed generation.
  • pkg/controller/statusmanager/pod_status.go#L111-L112: require the Deployment’s full stable predicates, not only observed generation.
  • pkg/controller/statusmanager/pod_status.go#L120-L121: require the StatefulSet’s full stable predicates, not only observed generation.
📍 Affects 2 files
  • pkg/controller/statusmanager/status_manager.go#L114-L117 (this comment)
  • pkg/controller/statusmanager/pod_status.go#L102-L103
  • pkg/controller/statusmanager/pod_status.go#L111-L112
  • pkg/controller/statusmanager/pod_status.go#L120-L121
🤖 Prompt for 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.

In `@pkg/controller/statusmanager/status_manager.go` around lines 114 - 117,
Persist or recover annotationMigrationDone in status_manager.go so migration
completion survives CNO restarts and is not rerun when installComplete is
restored; in pod_status.go, update the DaemonSet, Deployment, and StatefulSet
stable checks to require each resource’s full availability/readiness predicates
in addition to ObservedGeneration >= Generation, preventing unavailable active
rollouts from being classified as stable. Affected sites:
pkg/controller/statusmanager/status_manager.go lines 114-117;
pkg/controller/statusmanager/pod_status.go lines 102-103, 111-112, and 120-121.

@jluhrsen

Copy link
Copy Markdown
Contributor Author

/pipeline required
/retest

@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling required tests:
/test e2e-aws-ovn-upgrade-ipsec
/test e2e-gcp-ovn-techpreview

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aws-ovn-fdp-qe
/test e2e-aws-ovn-hypershift-conformance
/test e2e-aws-ovn-serial-1of2
/test e2e-aws-ovn-serial-2of2
/test e2e-aws-ovn-upgrade
/test e2e-aws-ovn-windows
/test e2e-azure-ovn-upgrade
/test e2e-gcp-ovn
/test e2e-gcp-ovn-upgrade
/test e2e-metal-ipi-ovn-dualstack-bgp
/test e2e-metal-ipi-ovn-dualstack-bgp-local-gw
/test e2e-metal-ipi-ovn-ipv6
/test e2e-metal-ipi-ovn-ipv6-ipsec
/test e2e-ovn-ipsec-step-registry
/test hypershift-e2e-aks

@openshift-ci

openshift-ci Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

@jluhrsen: The following tests failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-ovn-ipsec-step-registry 256039d link true /test e2e-ovn-ipsec-step-registry
ci/prow/e2e-aws-ovn-upgrade-ipsec 256039d link true /test e2e-aws-ovn-upgrade-ipsec
ci/prow/e2e-aws-ovn-fdp-qe 256039d link true /test e2e-aws-ovn-fdp-qe
ci/prow/hypershift-e2e-aks 256039d link true /test hypershift-e2e-aks
ci/prow/e2e-metal-ipi-ovn-dualstack-bgp-local-gw 256039d link true /test e2e-metal-ipi-ovn-dualstack-bgp-local-gw
ci/prow/e2e-gcp-ovn-upgrade 256039d link true /test e2e-gcp-ovn-upgrade
ci/prow/e2e-metal-ipi-ovn-ipv6-ipsec 256039d link true /test e2e-metal-ipi-ovn-ipv6-ipsec

Full PR test history. Your PR dashboard.

Details

Instructions for interacting with me using PR comments are available here. If you have questions or suggestions related to my behavior, please file an issue against the kubernetes-sigs/prow repository. I understand the commands that are listed here.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. jira/valid-reference Indicates that this PR references a valid Jira ticket of any type.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants