Skip to content

Conversation

@celebdor
Copy link
Collaborator

What this PR does / why we need it:

Fix regression where HCP router LoadBalancer service was created unexpectedly for configurations using Route hostnames under the management cluster's apps domain.

After upgrading HCP clusters, a router service of type LoadBalancer is created unexpectedly. On platforms with limited LoadBalancer IPs (e.g., BareMetal with exhausted MetalLB IPAddressPool), the service stays in <pending> state and blocks the upgrade.

The fix for OCPBUGS-56914 (PR #6780) changed the condition for creating the public router service from checking only if KAS uses Route to checking if ANY service uses Route with hostname. This caused the router service to be created for configurations that previously didn't need it.

This PR adds IsPublicWithExternalDNS() function that checks if any service uses a Route with a hostname that is external to the management cluster's default ingress domain. When hostnames are subdomains of the apps domain (e.g., oauth.apps.mgmt-cluster.example.com), the management cluster's default router can serve them via wildcard DNS, so no dedicated HCP router LoadBalancer service is needed.

This preserves the OCPBUGS-56914 fix for external DNS users while preventing unnecessary router service creation for apps-domain routes.

Which issue(s) this PR fixes:
Fixes OCPBUGS-70152

Checklist

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

🤖 Generated with Claude Code via /jira:solve OCPBUGS-70152 celebdor

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Dec 23, 2025

Skipping CI for Draft Pull Request.
If you want CI signal for your change, please convert it to an actual PR.
You can still manually trigger a test run with /test all

@openshift-ci openshift-ci bot added the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 23, 2025
@coderabbitai
Copy link
Contributor

coderabbitai bot commented Dec 23, 2025

Walkthrough

This PR introduces domain-aware routing for Hosted Control Plane by adding a DefaultIngressDomain parameter to router enablement logic. The change refactors router decision-making from internal context checks to explicit domain-based checks, adding new helper functions for DNS subdomain validation and propagating the domain through the control plane reconciliation context.

Changes

Cohort / File(s) Summary
Core Router Logic Updates
control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
Replaced useHCPRouter() with domain-aware routerv2.UseHCPRouter(hcp, defaultIngressDomain). Updated public DNS checks to IsPublicWithExternalDNS(hcp, defaultIngressDomain). Added DefaultIngressDomain to cpContext propagated to all components.
Router Component Refactoring
control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go
Introduced public UseHCPRouter(hcp *hyperv1.HostedControlPlane, defaultIngressDomain string) bool. Replaced internal useHCPRouter(cpContext) with new signature. Updated routing logic to use IsPublicWithExternalDNS(hcp, defaultIngressDomain).
Control Plane Context Extensions
support/controlplane-component/controlplane-component.go
Added DefaultIngressDomain string field to both ControlPlaneContext and WorkloadContext structs. Propagated domain value in workloadContext() initialization.
DNS Helper Functions
support/util/expose.go
Added IsSubdomain(hostname, domain string) bool for DNS label-based subdomain checks. Added UseDedicatedDNSWithExternalDomain(hcp, svcType, defaultIngressDomain) bool to determine if service requires dedicated router with external domain.
Visibility Helper
support/util/visibility.go
Added IsPublicWithExternalDNS(hcp *hyperv1.HostedControlPlane, defaultIngressDomain string) bool to check if HCP is public and requires external DNS routing.
Test Suite Updates
control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
Removed TestUseHCPRouter() test function and testify/assert import.
New Router Component Tests
control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go
Added comprehensive test coverage for UseHCPRouter() across AWS, GCP, IBM Cloud platforms with various endpoint access modes and shared ingress scenarios.
DNS Helper Function Tests
support/util/expose_test.go
Added TestIsSubdomain() with edge cases and boundary conditions. Added TestUseDedicatedDNSWithExternalDomain() validating external DNS routing decisions.
Visibility Function Tests
support/util/visibility_test.go
Added TestIsPublicWithExternalDNS() covering external DNS hostnames, apps domain, and private platform scenarios.

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~22 minutes

✨ Finishing touches
  • 📝 Generate docstrings
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment

📜 Recent review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 351f6ae and 58c8de3.

📒 Files selected for processing (9)
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go
  • support/controlplane-component/controlplane-component.go
  • support/util/expose.go
  • support/util/expose_test.go
  • support/util/visibility.go
  • support/util/visibility_test.go
💤 Files with no reviewable changes (1)
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • support/util/expose.go
  • support/util/expose_test.go
  • support/controlplane-component/controlplane-component.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go
  • support/util/visibility_test.go
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
  • support/util/visibility.go
🧬 Code graph analysis (5)
support/util/expose.go (2)
api/hypershift/v1beta1/hostedcluster_types.go (2)
  • ServiceType (930-930)
  • Route (921-921)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • Hostname (384-390)
control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go (5)
support/controlplane-component/generic-adapter.go (1)
  • WithPredicate (32-36)
support/controlplane-component/controlplane-component.go (1)
  • WorkloadContext (74-93)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • UseSharedIngress (379-382)
api/hypershift/v1beta1/hostedcluster_types.go (1)
  • IBMCloudPlatform (1217-1217)
support/util/visibility.go (2)
  • IsPrivateHCP (9-20)
  • IsPublicWithExternalDNS (69-74)
support/util/visibility_test.go (2)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • Hostname (384-390)
support/util/visibility.go (1)
  • IsPublicWithExternalDNS (69-74)
control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go (4)
control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go (1)
  • UseHCPRouter (63-71)
support/util/visibility.go (1)
  • IsPublicWithExternalDNS (69-74)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • UseSharedIngress (379-382)
api/hypershift/v1beta1/hostedcluster_types.go (1)
  • IBMCloudPlatform (1217-1217)
support/util/visibility.go (2)
support/util/expose.go (1)
  • UseDedicatedDNSWithExternalDomain (119-126)
api/hypershift/v1beta1/hostedcluster_types.go (4)
  • APIServer (934-934)
  • OAuthServer (940-940)
  • Konnectivity (937-937)
  • Ignition (943-943)
🪛 golangci-lint (2.5.0)
support/util/expose_test.go

[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn

(typecheck)

control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go

[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn

(typecheck)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Red Hat Konflux / control-plane-operator-main-on-pull-request
  • GitHub Check: Red Hat Konflux / hypershift-release-mce-211-on-pull-request
  • GitHub Check: Red Hat Konflux / hypershift-cli-mce-211-on-pull-request
  • GitHub Check: Red Hat Konflux / hypershift-operator-main-on-pull-request
🔇 Additional comments (9)
support/util/visibility.go (1)

65-74: LGTM! Domain-aware routing logic is well-structured.

The function correctly checks for external DNS requirements by verifying if any service uses a Route hostname outside the management cluster's default ingress domain. This enables the fix for the regression where router LoadBalancer services were created unnecessarily for apps-domain routes.

support/util/expose.go (2)

87-113: LGTM! DNS subdomain logic is correctly implemented.

The function properly performs DNS label-based subdomain matching:

  • Handles edge cases (empty inputs, exact matches, partial label matches)
  • Uses case-insensitive comparison as required for DNS
  • Correctly validates label boundaries to avoid false positives like "oauthapps.example.com" matching "apps.example.com"

115-126: Review the tested behavior when DefaultIngressDomain is empty.

The concern is valid: DefaultIngressDomain can be empty when the environment variable is unset or when the ingress capability is missing (hostedcluster_controller.go:4390). When empty, this function returns true, treating all hostnames as external.

However, this behavior is intentional and explicitly tested (expose_test.go:259-278). The conservative approach—assuming external DNS is needed when the default ingress domain is unknown—is reasonable for determining LoadBalancer service requirements.

Ensure callers (like IsPublicWithExternalDNS used at hostedcontrolplane_controller.go:1409) handle the case where DefaultIngressDomain is empty. Defensive checks already exist (v2/controlplaneoperator/deployment.go:159), but document this expected behavior if not already clear.

support/util/visibility_test.go (1)

233-382: LGTM! Comprehensive test coverage for external DNS logic.

The test cases thoroughly validate the domain-aware routing behavior across multiple scenarios including external DNS, apps domain routes, mixed configurations, and edge cases. This provides strong confidence in the correctness of the new IsPublicWithExternalDNS function.

support/util/expose_test.go (1)

94-298: LGTM! Excellent test coverage for DNS helpers.

Both test functions provide comprehensive coverage:

  • TestIsSubdomain validates all edge cases including case-insensitivity, label boundaries, and empty inputs
  • TestUseDedicatedDNSWithExternalDomain verifies the external domain detection logic across various service configurations

The empty default ingress domain test case (lines 259-278) explicitly validates that all hostnames are treated as external when no domain is specified, documenting this important behavior.

support/controlplane-component/controlplane-component.go (1)

62-63: LGTM! Proper context propagation for default ingress domain.

The DefaultIngressDomain field is correctly added to both context types and properly propagated from ControlPlaneContext to WorkloadContext, following the established pattern for other context fields.

Also applies to: 89-89, 109-109

control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go (1)

52-71: LGTM! Router routing logic correctly implements domain-aware behavior.

The UseHCPRouter function properly determines when a dedicated HCP router is needed:

  1. Skips router for shared ingress and IBMCloud (platform constraints)
  2. Requires router for private HCPs (always need dedicated routing)
  3. Requires router only for public HCPs with external DNS hostnames (fixes the regression)

The refactoring from an internal predicate to a public function with explicit parameters improves testability and clarity.

control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go (1)

10-255: LGTM! Comprehensive test coverage for router routing decisions.

The test suite thoroughly validates UseHCPRouter behavior across:

  • Multiple platforms (AWS, GCP, IBMCloud) with various endpoint access configurations
  • External DNS vs. apps domain hostname scenarios
  • Shared ingress mode
  • Dynamic test generation for public platforms

This provides strong confidence that the domain-aware routing logic works correctly across all supported configurations.

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

1052-1052: LGTM! Consistent integration of domain-aware routing.

The DefaultIngressDomain is properly propagated through the reconciliation flow:

  • Added to the control plane context (line 1105)
  • Used in router predicate checks (lines 1052, 1380)
  • Used in external DNS checks (lines 1409, 1520)

The changes maintain consistency with the new domain-aware routing model introduced by this PR.

Also applies to: 1105-1105, 1380-1380, 1409-1409, 1520-1520


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

@openshift-ci-robot openshift-ci-robot added the jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. label Dec 23, 2025
@openshift-ci-robot openshift-ci-robot added the jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. label Dec 23, 2025
@openshift-ci-robot
Copy link

@celebdor: This pull request references Jira Issue OCPBUGS-70152, 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 (4.22.0) matches configured target version for branch (4.22.0)
  • bug is in the state ASSIGNED, 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 (heli@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:

What this PR does / why we need it:

Fix regression where HCP router LoadBalancer service was created unexpectedly for configurations using Route hostnames under the management cluster's apps domain.

After upgrading HCP clusters, a router service of type LoadBalancer is created unexpectedly. On platforms with limited LoadBalancer IPs (e.g., BareMetal with exhausted MetalLB IPAddressPool), the service stays in <pending> state and blocks the upgrade.

The fix for OCPBUGS-56914 (PR #6780) changed the condition for creating the public router service from checking only if KAS uses Route to checking if ANY service uses Route with hostname. This caused the router service to be created for configurations that previously didn't need it.

This PR adds IsPublicWithExternalDNS() function that checks if any service uses a Route with a hostname that is external to the management cluster's default ingress domain. When hostnames are subdomains of the apps domain (e.g., oauth.apps.mgmt-cluster.example.com), the management cluster's default router can serve them via wildcard DNS, so no dedicated HCP router LoadBalancer service is needed.

This preserves the OCPBUGS-56914 fix for external DNS users while preventing unnecessary router service creation for apps-domain routes.

Which issue(s) this PR fixes:
Fixes OCPBUGS-70152

Checklist

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

🤖 Generated with Claude Code via /jira:solve OCPBUGS-70152 celebdor

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 openshift-ci bot added area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside an OCP release and removed do-not-merge/needs-area labels Dec 23, 2025
@openshift-ci
Copy link
Contributor

openshift-ci bot commented Dec 23, 2025

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: celebdor
Once this PR has been reviewed and has the lgtm label, please assign bryan-cox 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

@celebdor celebdor marked this pull request as ready for review December 23, 2025 04:13
@openshift-ci openshift-ci bot removed the do-not-merge/work-in-progress Indicates that a PR should not merge because it is a work in progress. label Dec 23, 2025
@openshift-ci openshift-ci bot requested review from bryan-cox and jparrill December 23, 2025 04:14
When a HostedControlPlane uses Route publishing strategy with hostnames
that are subdomains of the management cluster's default ingress domain
(e.g., oauth.apps.example.com under apps.example.com), the HCP router
LoadBalancer service should not be created. The management cluster's
ingress controller can directly handle these routes.

This fix introduces DNS label-based subdomain checking via IsSubdomain()
to properly detect when route hostnames fall within the apps domain.
The UseHCPRouter() function is now exported from the router component
and checks:
1. Shared ingress mode (always skip router)
2. IBMCloud platform (always skip router)
3. Private/PublicAndPrivate HCPs (need router for internal routes)
4. Public HCPs with external DNS hostnames (need router)
5. Public HCPs with apps domain hostnames (skip router)

The fix also adds DefaultIngressDomain to ControlPlaneContext and
WorkloadContext structs to make the domain available to component
predicates.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 0

Caution

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

⚠️ Outside diff range comments (1)
control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go (1)

174-174: Ensure DefaultIngressDomain environment variable is configured or add validation.

DefaultIngressDomain is initialized from the config.DefaultIngressDomainEnvVar environment variable in main.go:451 with no validation. When this environment variable is empty and no explicit hostname is provided, ShortenRouteHostnameIfNeeded (support/util/route.go:23-31) returns an empty string, leaving route hostnames unset. This affects the three route reconciliation functions at lines 1270, 1308, and 1322.

Ensure the environment variable is always configured in deployment, or add validation/logging to catch when it's missing.

📜 Review details

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Cache: Disabled due to data retention organization setting

Knowledge base: Disabled due to Reviews -> Disable Knowledge Base setting

📥 Commits

Reviewing files that changed from the base of the PR and between 351f6ae and 58c8de3.

📒 Files selected for processing (9)
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go
  • support/controlplane-component/controlplane-component.go
  • support/util/expose.go
  • support/util/expose_test.go
  • support/util/visibility.go
  • support/util/visibility_test.go
💤 Files with no reviewable changes (1)
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller_test.go
🧰 Additional context used
📓 Path-based instructions (1)
**

⚙️ CodeRabbit configuration file

-Focus on major issues impacting performance, readability, maintainability and security. Avoid nitpicks and avoid verbosity.

Files:

  • support/util/expose.go
  • support/util/expose_test.go
  • support/controlplane-component/controlplane-component.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go
  • control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go
  • support/util/visibility_test.go
  • control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go
  • support/util/visibility.go
🧬 Code graph analysis (5)
support/util/expose.go (2)
api/hypershift/v1beta1/hostedcluster_types.go (2)
  • ServiceType (930-930)
  • Route (921-921)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • Hostname (384-390)
control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go (5)
support/controlplane-component/generic-adapter.go (1)
  • WithPredicate (32-36)
support/controlplane-component/controlplane-component.go (1)
  • WorkloadContext (74-93)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • UseSharedIngress (379-382)
api/hypershift/v1beta1/hostedcluster_types.go (1)
  • IBMCloudPlatform (1217-1217)
support/util/visibility.go (2)
  • IsPrivateHCP (9-20)
  • IsPublicWithExternalDNS (69-74)
support/util/visibility_test.go (2)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • Hostname (384-390)
support/util/visibility.go (1)
  • IsPublicWithExternalDNS (69-74)
control-plane-operator/controllers/hostedcontrolplane/hostedcontrolplane_controller.go (4)
control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go (1)
  • UseHCPRouter (63-71)
support/util/visibility.go (1)
  • IsPublicWithExternalDNS (69-74)
hypershift-operator/controllers/sharedingress/sharedingress_controller.go (1)
  • UseSharedIngress (379-382)
api/hypershift/v1beta1/hostedcluster_types.go (1)
  • IBMCloudPlatform (1217-1217)
support/util/visibility.go (2)
support/util/expose.go (1)
  • UseDedicatedDNSWithExternalDomain (119-126)
api/hypershift/v1beta1/hostedcluster_types.go (4)
  • APIServer (934-934)
  • OAuthServer (940-940)
  • Konnectivity (937-937)
  • Ignition (943-943)
🪛 golangci-lint (2.5.0)
support/util/expose_test.go

[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn

(typecheck)

control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go

[error] 228-228: : # github.com/openshift/hypershift/sync-global-pullsecret [github.com/openshift/hypershift/sync-global-pullsecret.test]
sync-global-pullsecret/sync-global-pullsecret_test.go:228:23: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:234:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:247:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:257:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:270:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:283:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:296:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:309:26: undefined: MockdbusConn
sync-global-pullsecret/sync-global-pullsecret_test.go:327:12: undefined: NewMockdbusConn

(typecheck)

⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (4)
  • GitHub Check: Red Hat Konflux / control-plane-operator-main-on-pull-request
  • GitHub Check: Red Hat Konflux / hypershift-release-mce-211-on-pull-request
  • GitHub Check: Red Hat Konflux / hypershift-cli-mce-211-on-pull-request
  • GitHub Check: Red Hat Konflux / hypershift-operator-main-on-pull-request
🔇 Additional comments (9)
support/util/visibility.go (1)

65-74: LGTM! Domain-aware routing logic is well-structured.

The function correctly checks for external DNS requirements by verifying if any service uses a Route hostname outside the management cluster's default ingress domain. This enables the fix for the regression where router LoadBalancer services were created unnecessarily for apps-domain routes.

support/util/expose.go (2)

87-113: LGTM! DNS subdomain logic is correctly implemented.

The function properly performs DNS label-based subdomain matching:

  • Handles edge cases (empty inputs, exact matches, partial label matches)
  • Uses case-insensitive comparison as required for DNS
  • Correctly validates label boundaries to avoid false positives like "oauthapps.example.com" matching "apps.example.com"

115-126: Review the tested behavior when DefaultIngressDomain is empty.

The concern is valid: DefaultIngressDomain can be empty when the environment variable is unset or when the ingress capability is missing (hostedcluster_controller.go:4390). When empty, this function returns true, treating all hostnames as external.

However, this behavior is intentional and explicitly tested (expose_test.go:259-278). The conservative approach—assuming external DNS is needed when the default ingress domain is unknown—is reasonable for determining LoadBalancer service requirements.

Ensure callers (like IsPublicWithExternalDNS used at hostedcontrolplane_controller.go:1409) handle the case where DefaultIngressDomain is empty. Defensive checks already exist (v2/controlplaneoperator/deployment.go:159), but document this expected behavior if not already clear.

support/util/visibility_test.go (1)

233-382: LGTM! Comprehensive test coverage for external DNS logic.

The test cases thoroughly validate the domain-aware routing behavior across multiple scenarios including external DNS, apps domain routes, mixed configurations, and edge cases. This provides strong confidence in the correctness of the new IsPublicWithExternalDNS function.

support/util/expose_test.go (1)

94-298: LGTM! Excellent test coverage for DNS helpers.

Both test functions provide comprehensive coverage:

  • TestIsSubdomain validates all edge cases including case-insensitivity, label boundaries, and empty inputs
  • TestUseDedicatedDNSWithExternalDomain verifies the external domain detection logic across various service configurations

The empty default ingress domain test case (lines 259-278) explicitly validates that all hostnames are treated as external when no domain is specified, documenting this important behavior.

support/controlplane-component/controlplane-component.go (1)

62-63: LGTM! Proper context propagation for default ingress domain.

The DefaultIngressDomain field is correctly added to both context types and properly propagated from ControlPlaneContext to WorkloadContext, following the established pattern for other context fields.

Also applies to: 89-89, 109-109

control-plane-operator/controllers/hostedcontrolplane/v2/router/component.go (1)

52-71: LGTM! Router routing logic correctly implements domain-aware behavior.

The UseHCPRouter function properly determines when a dedicated HCP router is needed:

  1. Skips router for shared ingress and IBMCloud (platform constraints)
  2. Requires router for private HCPs (always need dedicated routing)
  3. Requires router only for public HCPs with external DNS hostnames (fixes the regression)

The refactoring from an internal predicate to a public function with explicit parameters improves testability and clarity.

control-plane-operator/controllers/hostedcontrolplane/v2/router/component_test.go (1)

10-255: LGTM! Comprehensive test coverage for router routing decisions.

The test suite thoroughly validates UseHCPRouter behavior across:

  • Multiple platforms (AWS, GCP, IBMCloud) with various endpoint access configurations
  • External DNS vs. apps domain hostname scenarios
  • Shared ingress mode
  • Dynamic test generation for public platforms

This provides strong confidence that the domain-aware routing logic works correctly across all supported configurations.

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

1052-1052: LGTM! Consistent integration of domain-aware routing.

The DefaultIngressDomain is properly propagated through the reconciliation flow:

  • Added to the control plane context (line 1105)
  • Used in router predicate checks (lines 1052, 1380)
  • Used in external DNS checks (lines 1409, 1520)

The changes maintain consistency with the new domain-aware routing model introduced by this PR.

Also applies to: 1105-1105, 1380-1380, 1409-1409, 1520-1520

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Dec 23, 2025

@celebdor: 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/okd-scos-images 58c8de3 link true /test okd-scos-images

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.

Copy link
Member

@bryan-cox bryan-cox left a comment

Choose a reason for hiding this comment

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

@celebdor this looks good to me. One nit on test names not using the when/it should format:

  Current:
  "AWS private - needs router"
  "proper subdomain"

  Should be:
  "When AWS HCP is private, it should need router"
  "When hostname is proper subdomain, it should return true"

@devguyio
Copy link
Contributor

devguyio commented Jan 5, 2026

/test hypershift-operator-main-push

@openshift-ci
Copy link
Contributor

openshift-ci bot commented Jan 5, 2026

@devguyio: The specified target(s) for /test were not found.
The following commands are available to trigger required jobs:

/test e2e-aks
/test e2e-aks-4-21
/test e2e-aks-override
/test e2e-aws
/test e2e-aws-4-21
/test e2e-aws-override
/test e2e-aws-upgrade-hypershift-operator
/test e2e-kubevirt-aws-ovn-reduced
/test images
/test okd-scos-images
/test security
/test unit
/test verify
/test verify-deps

The following commands are available to trigger optional jobs:

/test e2e-aws-autonode
/test e2e-aws-metrics
/test e2e-aws-minimal
/test e2e-aws-techpreview
/test e2e-azure-aks-ovn-conformance
/test e2e-conformance
/test e2e-kubevirt-aws-ovn
/test e2e-kubevirt-azure-ovn
/test e2e-kubevirt-metal-conformance
/test e2e-openstack-aws
/test e2e-openstack-aws-conformance
/test e2e-openstack-aws-csi-cinder
/test e2e-openstack-aws-csi-manila
/test e2e-openstack-aws-nfv
/test okd-scos-e2e-aws-ovn
/test reqserving-e2e-aws

Use /test all to run the following jobs that were automatically triggered:

pull-ci-openshift-hypershift-main-e2e-aks
pull-ci-openshift-hypershift-main-e2e-aks-4-21
pull-ci-openshift-hypershift-main-e2e-aws
pull-ci-openshift-hypershift-main-e2e-aws-upgrade-hypershift-operator
pull-ci-openshift-hypershift-main-e2e-kubevirt-aws-ovn-reduced
pull-ci-openshift-hypershift-main-images
pull-ci-openshift-hypershift-main-okd-scos-images
pull-ci-openshift-hypershift-main-security
pull-ci-openshift-hypershift-main-unit
pull-ci-openshift-hypershift-main-verify
Details

In response to this:

/test hypershift-operator-main-push

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.

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

Labels

area/control-plane-operator Indicates the PR includes changes for the control plane operator - in an OCP release area/hypershift-operator Indicates the PR includes changes for the hypershift operator and API - outside 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.

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants