Skip to content

OCPBUGS-98213: fix router component ordering to prevent missing HAProxy backends#8971

Open
hypershift-jira-solve-ci[bot] wants to merge 2 commits into
openshift:mainfrom
hypershift-community:fix-OCPBUGS-98213
Open

OCPBUGS-98213: fix router component ordering to prevent missing HAProxy backends#8971
hypershift-jira-solve-ci[bot] wants to merge 2 commits into
openshift:mainfrom
hypershift-community:fix-OCPBUGS-98213

Conversation

@hypershift-jira-solve-ci

@hypershift-jira-solve-ci hypershift-jira-solve-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

OCPBUGS-98213: fix router component ordering to prevent missing HAProxy backends

What this PR does / why we need it:

The router's adaptConfig function lists existing Route objects to generate the HAProxy ConfigMap. When the router was registered early in the component list (position #8), components that create Routes — ignition-server (#35) and metrics-proxy (#38) — had not yet run during the first reconcile pass. This caused the initial HAProxy config to miss ignition and metrics-proxy backends, routing ignition requests to the KAS default backend and failing NodePool ignition.

This PR:

  • Moves the router component to after metricsproxyv2 (the last route-creating component) so that all Routes exist when the router config is generated.
  • Declares ignition-server and metrics-proxy as explicit WithDependencies on the router component, blocking its reconciliation until both dependencies are Available and RolloutComplete. This provides a stronger guarantee than positional ordering alone, though the informer cache update from watch events is still async.
  • Adds TestRouterComponentComesAfterRouteCreatingComponents to verify the router is always registered after ignition-server and metrics-proxy, preventing future regressions from component reordering.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98213

Special notes for your reviewer:

The fix uses two complementary mechanisms: positional ordering in registerComponents (belt) and WithDependencies via the component framework (suspenders). WithDependencies ensures the router's reconciliation is skipped until ignition-server and metrics-proxy report Available + RolloutComplete, giving the informer cache time to reflect their routes.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin


Note: This PR was auto-generated by the jira-agent periodic CI job in response to OCPBUGS-98213. See the full report for token usage, cost breakdown, and detailed phase output.

Summary by CodeRabbit

  • Bug Fixes
    • Ensured the router component initializes after components that create prerequisite Routes.
    • Made router reconciliation explicitly honor required dependencies; on ARO hosted control planes, it now waits for required Routes to exist and be ready before proceeding.
  • Tests
    • Added and expanded unit tests to verify router component registration order, ARO Route requirements, readiness checks, and router predicate behavior.

@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

@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 9, 2026
@openshift-ci-robot

Copy link
Copy Markdown

@hypershift-jira-solve-ci[bot]: This pull request references Jira Issue OCPBUGS-98213, 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)

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

Details

In response to this:

What this PR does / why we need it:

The router's adaptConfig function lists existing Route objects to generate the HAProxy ConfigMap. When the router was registered early in the component list (position #8), components that create Routes — ignition-server (#35) and metrics-proxy (#38) — had not yet run during the first reconcile pass. This caused the initial HAProxy config to miss ignition and metrics-proxy backends, routing ignition requests to the KAS default backend and failing NodePool ignition.

This PR:

  • Moves the router component to after metricsproxyv2 (the last route-creating component) so that all Routes exist when the router config is generated, eliminating the race window.
  • Adds TestRouterComponentComesAfterRouteCreatingComponents to verify the router is always registered after ignition-server and metrics-proxy, preventing future regressions from component reordering.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98213

Special notes for your reviewer:

The fix is a component ordering change only — no behavioral changes to the router or route-creating components themselves. The test locks down the ordering constraint so it cannot silently regress.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin

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-ci-robot

Copy link
Copy Markdown

@hypershift-jira-solve-ci[bot]: This pull request references Jira Issue OCPBUGS-98213, 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)
Details

In response to this:

What this PR does / why we need it:

The router's adaptConfig function lists existing Route objects to generate the HAProxy ConfigMap. When the router was registered early in the component list (position #8), components that create Routes — ignition-server (#35) and metrics-proxy (#38) — had not yet run during the first reconcile pass. This caused the initial HAProxy config to miss ignition and metrics-proxy backends, routing ignition requests to the KAS default backend and failing NodePool ignition.

This PR:

  • Moves the router component to after metricsproxyv2 (the last route-creating component) so that all Routes exist when the router config is generated, eliminating the race window.
  • Adds TestRouterComponentComesAfterRouteCreatingComponents to verify the router is always registered after ignition-server and metrics-proxy, preventing future regressions from component reordering.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98213

Special notes for your reviewer:

The fix is a component ordering change only — no behavioral changes to the router or route-creating components themselves. The test locks down the ordering constraint so it cannot silently regress.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin


Note: This PR was auto-generated by the jira-agent periodic CI job in response to OCPBUGS-98213. See the full report for token usage, cost breakdown, and detailed phase output.

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.

@coderabbitai

coderabbitai Bot commented Jul 9, 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
📝 Walkthrough

Walkthrough

routerv2 now declares dependencies on ignitionserverv2 and metricsproxyv2, and its predicate checks that the required Routes exist and are ready in ARO HCP mode. HostedControlPlaneReconciler.registerComponents now adds routerv2 later in the component list. A new test asserts that router registration occurs after the ignition server and metrics proxy components.

Sequence Diagram(s)

sequenceDiagram
  participant Reconciler as HostedControlPlaneReconciler
  participant Router as routerv2 component
  participant API as Kubernetes Route API
  participant HCP as HostedControlPlane
  Reconciler->>Router: register component with dependencies
  Router->>HCP: inspect HCP router mode and platform
  Router->>API: list Routes in HCP namespace
  API-->>Router: return Route objects
  Router->>Router: check expected names and spec.host readiness
  Router-->>Reconciler: permit or block reconciliation
Loading
🚥 Pre-merge checks | ✅ 10 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Test Structure And Quality ⚠️ Warning Two fake-client router tests discard routev1.Install errors, so setup can proceed with an invalid scheme and yield misleading results. Handle scheme registration failures in both tests with t.Fatalf if routev1.Install(scheme) returns an error.
✅ Passed checks (10 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly matches the main change: reordering the router component to prevent missing HAProxy backends.
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.
Stable And Deterministic Test Names ✅ Passed Added test and subtest names are static, descriptive strings; no timestamps, random IDs, node/namespace names, or other run-to-run variable data appear in the new titles.
Topology-Aware Scheduling Compatibility ✅ Passed No topology-sensitive scheduling changes were introduced; the patch only reorders router registration and adds route/dependency tests, with no affinity, nodeSelector, spread, or replica logic.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the new tests are plain Go unit tests using fake clients and no IPv4 hardcodes or external connectivity.
No-Weak-Crypto ✅ Passed PR only reorders router components and adds route-readiness tests; no weak crypto, custom crypto, or non-constant-time secret comparisons were added.
Container-Privileges ✅ Passed The PR only reorders router registration and updates tests/fixture statuses; no touched manifest adds privileged, hostPID/Network/IPC, SYS_ADMIN, or allowPrivilegeEscalation.
No-Sensitive-Data-In-Logs ✅ Passed No new runtime logging was added; the PR only reorders components and adds tests, and the new errors/messages expose only route names, not secrets or PII.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@openshift-ci openshift-ci Bot requested review from Nirshal and clebs July 9, 2026 14:45
@openshift-ci openshift-ci Bot added area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release and removed do-not-merge/needs-area labels Jul 9, 2026

@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.

🧹 Nitpick comments (1)
control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go (1)

279-285: 🎯 Functional Correctness | 🔵 Trivial | ⚡ Quick win

Consider WithDependencies instead of positional ordering.

Comment-guarded slice ordering is fragile: any future insertion/reordering in registerComponents, or a move away from strictly sequential reconciliation of r.components, silently reintroduces this bug. This framework already has an explicit ordering primitive for exactly this case — WithDependencies(...), which blocks a component's reconciliation until its declared dependencies are ready — used elsewhere (e.g. clusterpolicy, dnsoperator, konnectivity_agent all call WithDependencies(oapiv2.ComponentName)/kasv2.ComponentName). Declaring routerv2.NewComponent().WithDependencies(ignitionserverv2.ComponentName, metricsproxyv2.ComponentName) (if the framework's builder API supports appending dependencies) would make the ordering contract explicit and self-enforcing rather than implicit in registration order.

🤖 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
`@control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go`
around lines 279 - 285, The router registration in registerComponents is relying
on fragile slice order to wait for ignition-server and metrics-proxy, which can
be broken by future reordering. Update routerv2.NewComponent to declare an
explicit dependency on the components that create Route objects using the
framework’s WithDependencies API, so router reconciliation is blocked until
those dependencies are ready. Use the existing component names in this
controller (for example ignitionserverv2.ComponentName and
metricsproxyv2.ComponentName) to make the ordering contract explicit and
self-enforcing.
🤖 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.

Nitpick comments:
In
`@control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go`:
- Around line 279-285: The router registration in registerComponents is relying
on fragile slice order to wait for ignition-server and metrics-proxy, which can
be broken by future reordering. Update routerv2.NewComponent to declare an
explicit dependency on the components that create Route objects using the
framework’s WithDependencies API, so router reconciliation is blocked until
those dependencies are ready. Use the existing component names in this
controller (for example ignitionserverv2.ComponentName and
metricsproxyv2.ComponentName) to make the ordering contract explicit and
self-enforcing.

ℹ️ Review info
⚙️ Run configuration

Configuration used: Repository YAML (base), Central YAML (inherited)

Review profile: CHILL

Plan: Enterprise

Run ID: 8b89eabd-9f22-4e18-a641-6d02aef5df25

📥 Commits

Reviewing files that changed from the base of the PR and between 433a404 and b092cf4.

📒 Files selected for processing (2)
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go

@codecov

codecov Bot commented Jul 9, 2026

Copy link
Copy Markdown

Codecov Report

❌ Patch coverage is 84.61538% with 8 lines in your changes missing coverage. Please review.
✅ Project coverage is 43.74%. Comparing base (1f2811f) to head (c995ad0).
⚠️ Report is 28 commits behind head on main.

Files with missing lines Patch % Lines
...trollers/hostedcontrolplane/v2/router/component.go 84.31% 6 Missing and 2 partials ⚠️
Additional details and impacted files
@@            Coverage Diff             @@
##             main    #8971      +/-   ##
==========================================
+ Coverage   43.53%   43.74%   +0.20%     
==========================================
  Files         771      772       +1     
  Lines       95798    95991     +193     
==========================================
+ Hits        41707    41987     +280     
+ Misses      51192    51090     -102     
- Partials     2899     2914      +15     
Files with missing lines Coverage Δ
...ostedcontrolplane/hostedcontrolplane_controller.go 45.73% <100.00%> (ø)
...trollers/hostedcontrolplane/v2/router/component.go 62.31% <84.31%> (+62.31%) ⬆️

... and 16 files with indirect coverage changes

Flag Coverage Δ
cmd-support 37.22% <ø> (ø)
cpo-hostedcontrolplane 46.01% <84.61%> (+0.49%) ⬆️
cpo-other 45.11% <ø> (+0.01%) ⬆️
hypershift-operator 54.03% <ø> (+0.38%) ⬆️
other 32.08% <ø> (ø)

Flags with carried forward coverage won't be shown. Click here to find out more.

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

@bryan-cox bryan-cox left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Review

How Reconciliation Actually Works

  1. reconcileInfrastructure() runs first (line 1084) — creates KAS routes, konnectivity routes, and OAuth routes via infra/infra.go
  2. AdmitHCPManagedRoutes() runs next (line 1201) — sets host/status on HCP-managed routes
  3. for _, c := range r.components (line 1263) — iterates sequentially, calling each component's Reconcile(), which calls update(), which applies manifests via server-side apply

Does component order matter?

Partially. The router's adaptConfig (v2/router/config.go:43) does:

cpContext.Client.List(cpContext, routeList, client.InNamespace(cpContext.HCP.Namespace))

cpContext.Client is r.Client (line 1247) — the controller-runtime cached client backed by informer caches. When ignition-server's Reconcile() creates a Route via server-side apply, the Route hits etcd, but the informer cache update from the watch event is async. So ordering the router after route-creating components gives the informer more time to process the watch event, making it more likely the routes are visible — but it's not a hard guarantee.

What routes does the router care about?

The router's adaptConfig handles: KAS (3 routes), ignition, konnectivity, OAuth (3 routes), metrics_forwarder, and metrics_proxy.

  • KAS, konnectivity, OAuth routes are created in reconcileInfrastructure(), which runs before the component loop. These are not affected by component ordering at all.
  • Only ignition-server and metrics-proxy create routes via the component framework (v2/assets/ignition-server/route.yaml and v2/assets/metrics-proxy/route.yaml). These are the ones affected by this PR.

The route-creating component list is complete

The PR correctly identifies ignition-server and metrics-proxy as the only two route-creating components in the framework. Confirmed by:

  • Only two route.yaml assets exist under v2/assets/
  • No other components reference routev1.Route outside of router itself

Test quality

The test is well-structured:

  • Uses exported ComponentName constants
  • Properly sets up the reconciler with required mocks
  • Verifies position ordering in the actual component slice
  • Only tests AWS platform, but the route-creating components aren't platform-conditional so this is fine

Issues

  1. The PR description overstates the fix. It says this "eliminates the race window" — it doesn't. It reduces the window by giving the informer cache more time to sync, but the cache update is still async. A fully robust fix would use WithDependencies() on the router component (the framework supports this — see metricsproxyv2 which already uses WithDependencies(endpointresolverv2.ComponentName)), or use an uncached read in adaptConfig.

  2. The 6-line inline comment is verbose. 2 lines would suffice:

    // Router must come after route-creating components (ignition-server, metrics-proxy)
    // so their routes exist in the cache when adaptConfig generates the HAProxy config.
  3. Not a blocker, but worth noting: the router already handles missing routes gracefully — if a route doesn't exist, it just doesn't get a backend entry. The next reconcile pass will pick it up. So this is a first-reconcile latency optimization, not a hard correctness bug.

Verdict

Conditional ACK — the ordering change is a reasonable improvement and the test is good. But the PR description should be corrected to not claim it "eliminates" the race, and the comment should be shortened.

@bryan-cox

Copy link
Copy Markdown
Member

/test address-review-comments

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Review agent triggered. View job

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Done. Addressed both items:

  1. Comment shortened to 2 lines as suggested.
  2. Commit message corrected — "eliminates the race window" → "reduces the race window" with a note that the informer cache update is still async.

Good point on #3 — the router does handle missing routes gracefully via subsequent reconcile passes, so this is indeed a first-reconcile latency optimization rather than a hard correctness fix.


AI-assisted response via Claude Code

@openshift-ci-robot

Copy link
Copy Markdown

@hypershift-jira-solve-ci[bot]: This pull request references Jira Issue OCPBUGS-98213, 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 ASSIGNED, which is one of the valid states (NEW, ASSIGNED, POST)
Details

In response to this:

What this PR does / why we need it:

The router's adaptConfig function lists existing Route objects to generate the HAProxy ConfigMap. When the router was registered early in the component list (position #8), components that create Routes — ignition-server (#35) and metrics-proxy (#38) — had not yet run during the first reconcile pass. This caused the initial HAProxy config to miss ignition and metrics-proxy backends, routing ignition requests to the KAS default backend and failing NodePool ignition.

This PR:

  • Moves the router component to after metricsproxyv2 (the last route-creating component) so that all Routes exist when the router config is generated, eliminating the race window.
  • Adds TestRouterComponentComesAfterRouteCreatingComponents to verify the router is always registered after ignition-server and metrics-proxy, preventing future regressions from component reordering.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98213

Special notes for your reviewer:

The fix is a component ordering change only — no behavioral changes to the router or route-creating components themselves. The test locks down the ordering constraint so it cannot silently regress.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin


Note: This PR was auto-generated by the jira-agent periodic CI job in response to OCPBUGS-98213. See the full report for token usage, cost breakdown, and detailed phase output.

Summary by CodeRabbit

  • Bug Fixes
  • Improved startup/registration sequencing so routing configuration happens after related route components are initialized, reducing the risk of initial requests being routed to the wrong backend.
  • Tests
  • Added a unit test to confirm the routing component is registered after key components that create routes, preventing regressions in routing order.

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.

@bryan-cox

Copy link
Copy Markdown
Member

Was https://redhat.atlassian.net/browse/OCPBUGS-98213?focusedCommentId=17546910 taken into account when generating this PR?

@bryan-cox

Copy link
Copy Markdown
Member

/test address-review-comments

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Review agent triggered. View job

@openshift-ci-robot

Copy link
Copy Markdown

@hypershift-jira-solve-ci[bot]: This pull request references Jira Issue OCPBUGS-98213, 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)
Details

In response to this:

OCPBUGS-98213: fix router component ordering to prevent missing HAProxy backends

What this PR does / why we need it:

The router's adaptConfig function lists existing Route objects to generate the HAProxy ConfigMap. When the router was registered early in the component list (position #8), components that create Routes — ignition-server (#35) and metrics-proxy (#38) — had not yet run during the first reconcile pass. This caused the initial HAProxy config to miss ignition and metrics-proxy backends, routing ignition requests to the KAS default backend and failing NodePool ignition.

This PR:

  • Moves the router component to after metricsproxyv2 (the last route-creating component) so that all Routes exist when the router config is generated.
  • Declares ignition-server and metrics-proxy as explicit WithDependencies on the router component, blocking its reconciliation until both dependencies are Available and RolloutComplete. This provides a stronger guarantee than positional ordering alone, though the informer cache update from watch events is still async.
  • Adds TestRouterComponentComesAfterRouteCreatingComponents to verify the router is always registered after ignition-server and metrics-proxy, preventing future regressions from component reordering.

Which issue(s) this PR fixes:

Fixes https://redhat.atlassian.net/browse/OCPBUGS-98213

Special notes for your reviewer:

The fix uses two complementary mechanisms: positional ordering in registerComponents (belt) and WithDependencies via the component framework (suspenders). WithDependencies ensures the router's reconciliation is skipped until ignition-server and metrics-proxy report Available + RolloutComplete, giving the informer cache time to reflect their routes.

Checklist:

  • Subject and description added to both, commit and PR.
  • Relevant issues have been referenced.
  • This change includes docs.
  • This change includes unit tests.

Always review AI generated responses prior to use.
Generated with Claude Code via openshift-developer plugin


Note: This PR was auto-generated by the jira-agent periodic CI job in response to OCPBUGS-98213. See the full report for token usage, cost breakdown, and detailed phase output.

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.

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Addressed review feedback:

  1. WithDependencies instead of positional ordering — Added WithDependencies(ignitionserverv2.ComponentName, metricsproxyv2.ComponentName) to the router component in router/component.go. This uses the framework's dependency mechanism to block the router's reconciliation until both route-creating components are Available and RolloutComplete, providing a stronger guarantee than positional ordering alone. The comment-guarded ordering has been removed.

  2. PR description updated — Removed the "eliminating the race window" claim. The description now accurately states that WithDependencies provides a stronger guarantee but the informer cache update is still async.

  3. Test fixtures updated — The router's ControlPlaneComponent status now shows WaitingForDependencies: ignition-server, metrics-proxy instead of WaitingForRolloutComplete since the dependency check runs before reconciliation.

The positional ordering test is preserved as a secondary safety net — WithDependencies is the primary mechanism.


AI-assisted response via Claude Code

@bryan-cox

Copy link
Copy Markdown
Member

/restructure-commits

@github-actions

github-actions Bot commented Jul 9, 2026

Copy link
Copy Markdown

🤖 Restructuring commits: workflow run

@bryan-cox bryan-cox left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

/approve

@openshift-ci

openshift-ci Bot commented Jul 9, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bryan-cox, hypershift-jira-solve-ci[bot]

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

The pull request process is described 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

@openshift-ci openshift-ci Bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Jul 9, 2026
@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

9 similar comments
@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

e2e-aks

1 similar comment
@cwbotbot

Copy link
Copy Markdown

Test Results

e2e-aws

e2e-aks

@bryan-cox

Copy link
Copy Markdown
Member

/retest

"pdb.yaml",
component.AdaptPodDisruptionBudget(),
).
WithDependencies(ignitionserverv2.ComponentName, metricsproxyv2.ComponentName).

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Pleas let's Drop the dependency on metrics-proxy which is not guaranteed to exist, the predicate should take care of it already

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Removed metricsproxyv2.ComponentName from WithDependencies — the router now only depends on ignition-server. The predicate's ensureHCPRouterRoutesExist already gates on metrics-proxy route readiness when applicable, so the hard dependency was redundant and caused deadlocks on platforms where metrics-proxy is never created.


AI-assisted response via Claude Code

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Addressed by removing the hard dependency — the CI failure analysis confirmed the deadlock. The router predicate is sufficient to handle this.


AI-assisted response via Claude Code

@enxebre

enxebre commented Jul 10, 2026

Copy link
Copy Markdown
Member

/test address-review-comments

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Review agent triggered. View job

@openshift-ci openshift-ci Bot removed the lgtm Indicates that a PR is ready to be merged. label Jul 10, 2026
message: 'Waiting for deployment router rollout to finish: 0 out of 3 new replicas
have been updated'
reason: WaitingForRolloutComplete
message: 'Waiting for Dependencies: ignition-server, metrics-proxy'

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

fix the unit tests this needs to be regenerated #8971 (comment)

Copy link
Copy Markdown
Contributor Author

Choose a reason for hiding this comment

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

Done. Updated all 5 router fixture YAML files to reflect the actual declared dependency (ignition-server only, no metrics-proxy).


AI-assisted response via Claude Code

@enxebre

enxebre commented Jul 10, 2026

Copy link
Copy Markdown
Member

/test address-review-comments

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Review agent triggered. View job

…dencies

The metrics-proxy component is conditional (only created when
MetricsForwarding.Mode=Forward), so declaring it as a hard dependency
causes a deadlock on platforms where it is never instantiated (e.g. GKE).
The router predicate already ensures metrics-proxy routes exist before
reconciling, making the explicit dependency unnecessary.

Update all 5 router fixture YAML files to match the actual declared
dependency (ignition-server only).

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@enxebre

enxebre commented Jul 10, 2026

Copy link
Copy Markdown
Member

/lgtm

@openshift-ci openshift-ci Bot added the lgtm Indicates that a PR is ready to be merged. label Jul 10, 2026
@openshift-merge-bot

Copy link
Copy Markdown
Contributor

Scheduling tests matching the pipeline_run_if_changed or not excluded by pipeline_skip_if_only_changed parameters:
/test e2e-aks
/test e2e-aws
/test e2e-aws-upgrade-hypershift-operator
/test e2e-azure-v2-self-managed
/test e2e-kubevirt-aws-ovn-reduced
/test e2e-v2-aws
/test e2e-v2-gke

@enxebre enxebre added tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges. and removed lgtm Indicates that a PR is ready to be merged. labels Jul 10, 2026
@bryan-cox

Copy link
Copy Markdown
Member

/test e2e-kubevirt-aws-ovn-reduced

@openshift-ci

openshift-ci Bot commented Jul 11, 2026

Copy link
Copy Markdown
Contributor

@hypershift-jira-solve-ci[bot]: The following test 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-kubevirt-aws-ovn-reduced c995ad0 link true /test e2e-kubevirt-aws-ovn-reduced

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.

@hypershift-jira-solve-ci

Copy link
Copy Markdown
Contributor Author

Now I have all the evidence I need. Let me compile the final report:

Test Failure Analysis Complete

Job Information

Test Failure Analysis

Error

Error: set memory limit 324000 too low; should be at least 524288 bytes

Summary

The job failed in the pre phase because the cp-entrypoint-wrapper init container — injected by CI infrastructure into every test step pod — was configured with a memory limit of 324,000 bytes (~316 KB), which is below the container runtime's minimum of 524,288 bytes (512 KB). This caused the init container to fail to start 258 consecutive times over ~55 minutes, blocking all subsequent containers (sidecar, test) from ever running. The pod was killed after a 1-hour timeout. This is a CI infrastructure issue unrelated to PR #8971.

Root Cause

The root cause is a CI infrastructure memory limit misconfiguration in the cp-entrypoint-wrapper init container, not a bug in the HyperShift code under test.

What happened step-by-step:

  1. The management cluster installed successfully — all 12 pre-install steps (ipi-conf, ipi-conf-aws, ovn-conf, ipi-install-install, etc.) completed without error.
  2. After install, the openshift-tests-extension-admission-crd-install step (still in the pre phase) attempted to start.
  3. The CI infrastructure injected a cp-entrypoint-wrapper init container using image quay-proxy.ci.openshift.org/openshift/ci:ci_entrypoint-wrapper_latest with a memory limit of 324,000 bytes (316 KB).
  4. The container runtime (cri-o/containerd) rejected this because its minimum memory limit is 524,288 bytes (512 KB).
  5. The kubelet retried creating this container 258 times over ~55 minutes, failing every time with: Error: set memory limit 324000 too low; should be at least 524288 bytes.
  6. After 1 hour, ci-operator killed the pod for exceeding the pending timeout.
  7. This cascaded: subsequent post-phase pods (dump, gather-aws-console) hit the same init container failure (255–277 retries each), though gather-must-gather, gather-extra, and gather-audit-logs succeeded (they may have been scheduled on nodes with a different runtime configuration or the limit was applied differently).

Why this is NOT related to PR #8971:

  • The PR modifies HyperShift router component ordering — it has no influence on CI infrastructure container resource limits.
  • The cp-entrypoint-wrapper container and its memory limit (324,000 bytes) are injected by ci-operator, not by the test or HyperShift code.
  • The failing step (openshift-tests-extension-admission-crd-install) is a CI registry step that installs a CRD — it is not HyperShift-specific code.
  • The same failure pattern affected 3 out of ~6 post-install/post-phase pods, indicating a systemic CI infrastructure issue.
Recommendations
  1. Retry the job — This is a transient CI infrastructure issue. The cp-entrypoint-wrapper memory limit misconfiguration may have been fixed or may not reproduce on a different build cluster node.
  2. If retries continue to fail, file a bug against the OpenShift CI infrastructure team (openshift/ci-tools or openshift/release) regarding the ci_entrypoint-wrapper_latest image having a memory limit of 324,000 bytes, which is below the container runtime minimum of 524,288 bytes.
  3. No code changes needed in PR OCPBUGS-98213: fix router component ordering to prevent missing HAProxy backends #8971 — This failure is entirely a CI infrastructure issue.
Evidence
Evidence Detail
Failing step openshift-tests-extension-admission-crd-install (pre phase)
Failing container cp-entrypoint-wrapper (init container injected by ci-operator)
Container image quay-proxy.ci.openshift.org/openshift/ci:ci_entrypoint-wrapper_latest
Memory limit set 324,000 bytes (~316 KB)
Minimum required 524,288 bytes (512 KB)
Error message Error: set memory limit 324000 too low; should be at least 524288 bytes
Retry count 258 attempts in ~55 minutes (for the primary failing pod)
Pods affected 3 of ~6 post-install pods (admission-crd-install, dump, gather-aws-console)
Pods unaffected gather-must-gather, gather-extra, gather-audit-logs, gather-core-dump succeeded
Cluster install ✅ Succeeded (45m34s) — all IPI install steps passed
Phase failed Pre phase (after install but before tests ran)
Job reason executing_multi_stage_test:pod_pending
Relationship to PR None — PR #8971 modifies router component ordering, not CI container resources

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

Labels

approved Indicates a PR has been approved by an approver from all required OWNERS files. area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release 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. tide/merge-method-squash Denotes a PR that should be squashed by tide when it merges.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

5 participants