Skip to content

OCPBUGS-58422: Handle disabled Ingress capability in HyperShift#1182

Open
stefanonardo wants to merge 1 commit into
openshift:mainfrom
stefanonardo:OCPBUGS-58422
Open

OCPBUGS-58422: Handle disabled Ingress capability in HyperShift#1182
stefanonardo wants to merge 1 commit into
openshift:mainfrom
stefanonardo:OCPBUGS-58422

Conversation

@stefanonardo

@stefanonardo stefanonardo commented Jul 6, 2026

Copy link
Copy Markdown

Summary

When Ingress capability is disabled in HyperShift, the console operator crashes repeatedly because it expects IngressController CRDs and Routes that don't exist. This PR makes the operator handle the ingress-disabled case gracefully.

Changes

  • starter.go: Detect ingress-disabled at startup via direct API calls to Infrastructure and ClusterVersion resources. Skip creating route and health check controllers, which prevents the IngressController informer from being created and eliminates reflector errors.
  • route/controller.go: Reorder sync to check IsExternalControlPlaneWithIngressDisabled() before fetching IngressController (defensive).
  • oauthclients.go: Add infrastructure and clusterVersion listers. Early-return when ingress is disabled and no ConsoleURL is configured.
  • clidownloads/controller.go: Add infrastructure and clusterVersion listers (from existing configInformer factory). Early-return when ingress is disabled and no ClientDownloadsURL is configured.
  • sync_v400.go: Early-return when ingress is disabled and no ConsoleURL is configured.
  • manifests: Gate openshift-ingress-operator namespace Role and RoleBinding with Console+Ingress capability annotation so CVO skips them when the Ingress capability is disabled (the namespace does not exist in that case).

Related

Test plan

  • make test-unit passes
  • Verified on a HyperShift hosted cluster on AWS with --disable-cluster-capabilities Ingress (using fix: OCPBUGS-58422: Allow disabling Ingress without Console in HyperShift hypershift#8933 to remove the Ingress/Console coupling validation):
    • Before the fix: console operator logs show continuous route "console" not found, IngressController not found, and FailedRouteGet errors; ClusterOperator reports Degraded=True
    • After deploying the fix: console operator pod runs stable with 0 restarts, startup log confirms Ingress capability is disabled in external control plane topology, skipping route and health check controllers, zero route/IngressController errors in the logs, and OAuthClientsControllerDegraded condition is cleared from the ClusterOperator status

Summary by CodeRabbit

  • New Features
    • Improved handling of external control plane setups when ingress is disabled by cleanly skipping console/route and download URL resolution.
  • Bug Fixes
    • OAuth client, CLI download, and console sync now exit early with progressing/degraded status when ingress is unavailable, avoiding route/ingress lookups.
    • Prevented unnecessary failures by only initializing route and route health-check controllers when ingress is enabled.
  • Chores
    • Updated RBAC capability annotations to associate the console operator role and binding with “Console+Ingress”.

@openshift-ci-robot openshift-ci-robot added jira/valid-reference Indicates that this PR references a valid Jira ticket of any type. jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 6, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@stefanonardo: This pull request references Jira Issue OCPBUGS-58422, which is invalid:

  • expected the bug to target the "5.0.0" version, but no target version was set

Comment /jira refresh to re-evaluate validity if changes to the Jira bug are made, or edit the title of this pull request to link to a different bug.

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

Details

In response to this:

Summary

When Ingress capability is disabled in HyperShift, the console operator crashes repeatedly because it expects IngressController CRDs and Routes that don't exist. This PR makes the operator handle the ingress-disabled case gracefully.

Changes

  • starter.go: Detect ingress-disabled at startup via direct API calls to Infrastructure and ClusterVersion resources. Skip creating route and health check controllers, which prevents the IngressController informer from being created and eliminates reflector errors.
  • route/controller.go: Reorder sync to check IsExternalControlPlaneWithIngressDisabled() before fetching IngressController (defensive).
  • oauthclients.go: Add infrastructure and clusterVersion listers. Early-return when ingress is disabled and no ConsoleURL is configured.
  • clidownloads/controller.go: Add infrastructure and clusterVersion listers (from existing configInformer factory). Early-return when ingress is disabled and no ClientDownloadsURL is configured.
  • sync_v400.go: Early-return when ingress is disabled and no ConsoleURL is configured.
  • manifests: Gate openshift-ingress-operator namespace Role and RoleBinding with Console+Ingress capability annotation so CVO skips them when the Ingress capability is disabled (the namespace does not exist in that case).

Test plan

  • make test-unit passes
  • Verified on a HyperShift hosted cluster on AWS with --disable-cluster-capabilities Ingress:
  • Before the fix: console operator logs show continuous route "console" not found, IngressController not found, and FailedRouteGet errors; ClusterOperator reports Degraded=True
  • After deploying the fix: console operator pod runs stable with 0 restarts, startup log confirms Ingress capability is disabled in external control plane topology, skipping route and health check controllers, zero route/IngressController errors in the logs, and OAuthClientsControllerDegraded condition is cleared from the ClusterOperator status

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 requested review from TheRealJon and jhadvig July 6, 2026 11:09
@openshift-ci

openshift-ci Bot commented Jul 6, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

This pull-request has been approved by: stefanonardo
Once this PR has been reviewed and has the lgtm label, please assign therealjon 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 commented Jul 6, 2026

Copy link
Copy Markdown

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: c73c411d-81c7-4a45-b7ff-31141d734304

📥 Commits

Reviewing files that changed from the base of the PR and between 5fd368d and 302c519.

📒 Files selected for processing (7)
  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/operator/sync_v400.go
  • pkg/console/starter/starter.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift/console (manual)
🚧 Files skipped from review as they are similar to previous changes (7)
  • pkg/console/operator/sync_v400.go
  • manifests/04-rbac-rolebinding.yaml
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/controllers/route/controller.go
  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/starter/starter.go

Walkthrough

This PR updates ingress capability annotations, adds ingress-disabled early returns in controller sync paths, and changes operator startup wiring to skip route-related controllers when ingress is disabled.

Changes

Ingress-disabled controller gating

Layer / File(s) Summary
RBAC annotations
manifests/03-rbac-role-ns-openshift-ingress-operator.yaml, manifests/04-rbac-rolebinding.yaml
Updates capability.openshift.io/name from Console to Console+Ingress.
Controller sync guards
pkg/console/controllers/clidownloads/controller.go, pkg/console/controllers/oauthclients/oauthclients.go, pkg/console/controllers/route/controller.go, pkg/console/operator/sync_v400.go
Adds infrastructure and cluster-version lookups, reorders route sync checks, and adds early-return paths when external control plane ingress is disabled.
Startup controller wiring
pkg/console/starter/starter.go
Loads infrastructure and cluster version data, derives ingressDisabled, rewires OAuth client informers, conditionally creates route/health-check controllers, and runs the final controller list.

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

🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Description check ⚠️ Warning The description covers summary, changes, and tests, but misses required template sections like root cause, setup, conformance, and reviewers. Add the missing template sections: analysis/root cause, solution details, test setup, test cases, browser conformance, additional info, and reviewers.
✅ Passed checks (14 passed)
Check name Status Explanation
Title check ✅ Passed The title matches the main change: handling disabled Ingress capability in HyperShift.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.
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 No test files or Ginkgo title changes are present; the diff only touches manifests and production code.
Test Structure And Quality ✅ Passed No Ginkgo test files or test blocks were changed in this PR; only manifests and production code were modified, so the test-quality check is not applicable.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added in this PR; the diff only changes controllers/manifests, so MicroShift test compatibility is not implicated.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the diff only touches controllers/manifests, so SNO test compatibility is not applicable.
Topology-Aware Scheduling Compatibility ✅ Passed No nodeSelector, affinity, topology-spread, replica, or PDB scheduling changes were added; the PR only gates route controllers and RBAC capability annotations for HyperShift.
Ote Binary Stdout Contract ✅ Passed No modified process-level code writes to stdout; added startup logic uses klog only, and controllercmd calls logs.InitLogs() to route logs to stderr.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the PR touches only operator/manifests code, and no test files or IPv4/network assumptions were found.
No-Weak-Crypto ✅ Passed PASS: touched files contain no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB or ConstantTimeCompare usage; changes are RBAC annotations and early-return logic only.
Container-Privileges ✅ Passed PASS: The PR only changes RBAC annotations and controller logic; no touched files add privileged/hostPID/hostNetwork/hostIPC/SYS_ADMIN or allowPrivilegeEscalation settings.
No-Sensitive-Data-In-Logs ✅ Passed PASS: The only new log is a static startup message; the new early-return paths and manifest changes add no logs or sensitive-value formatting.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

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

@stefanonardo

Copy link
Copy Markdown
Author

/cherry-pick release-4.22

@openshift-cherrypick-robot

Copy link
Copy Markdown

@stefanonardo: once the present PR merges, I will cherry-pick it on top of release-4.22 in a new PR and assign it to you.

Details

In response to this:

/cherry-pick release-4.22

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.

@openshift-ci-robot openshift-ci-robot added jira/valid-bug Indicates that a referenced Jira bug is valid for the branch this PR is targeting. and removed jira/invalid-bug Indicates that a referenced Jira bug is invalid for the branch this PR is targeting. labels Jul 6, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@stefanonardo: This pull request references Jira Issue OCPBUGS-58422, 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)

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

Details

In response to this:

Summary

When Ingress capability is disabled in HyperShift, the console operator crashes repeatedly because it expects IngressController CRDs and Routes that don't exist. This PR makes the operator handle the ingress-disabled case gracefully.

Changes

  • starter.go: Detect ingress-disabled at startup via direct API calls to Infrastructure and ClusterVersion resources. Skip creating route and health check controllers, which prevents the IngressController informer from being created and eliminates reflector errors.
  • route/controller.go: Reorder sync to check IsExternalControlPlaneWithIngressDisabled() before fetching IngressController (defensive).
  • oauthclients.go: Add infrastructure and clusterVersion listers. Early-return when ingress is disabled and no ConsoleURL is configured.
  • clidownloads/controller.go: Add infrastructure and clusterVersion listers (from existing configInformer factory). Early-return when ingress is disabled and no ClientDownloadsURL is configured.
  • sync_v400.go: Early-return when ingress is disabled and no ConsoleURL is configured.
  • manifests: Gate openshift-ingress-operator namespace Role and RoleBinding with Console+Ingress capability annotation so CVO skips them when the Ingress capability is disabled (the namespace does not exist in that case).

Related

Test plan

  • make test-unit passes
  • Verified on a HyperShift hosted cluster on AWS with --disable-cluster-capabilities Ingress (using fix: OCPBUGS-58422: Allow disabling Ingress without Console in HyperShift hypershift#8933 to remove the Ingress/Console coupling validation):
  • Before the fix: console operator logs show continuous route "console" not found, IngressController not found, and FailedRouteGet errors; ClusterOperator reports Degraded=True
  • After deploying the fix: console operator pod runs stable with 0 restarts, startup log confirms Ingress capability is disabled in external control plane topology, skipping route and health check controllers, zero route/IngressController errors in the logs, and OAuthClientsControllerDegraded condition is cleared from the ClusterOperator status

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.

stefanonardo added a commit to stefanonardo/hypershift that referenced this pull request Jul 6, 2026
Remove the validation that requires Console to be disabled when Ingress
is disabled. The console-operator now handles ingress-disabled gracefully
(openshift/console-operator#1182).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>

@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: 3

🧹 Nitpick comments (2)
pkg/console/controllers/clidownloads/controller.go (1)

128-135: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Inconsistent use of the resource-name constant.

Line 128 uses api.ConfigResourceName for the Infrastructure Get, but Line 132 hardcodes "version" for the ClusterVersion Get right next to it. The same literal is repeated in oauthclients.go, sync_v400.go, and starter.go. A shared named constant (e.g. alongside api.ConfigResourceName) would improve consistency and avoid a typo causing a silent lookup failure.

🤖 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/console/controllers/clidownloads/controller.go` around lines 128 - 135,
The ClusterVersion lookup in the controller is hardcoding "version" instead of
using a shared resource-name constant, which makes the code inconsistent and
typo-prone. Update `clidownloads/controller.go` so
`c.clusterVersionLister.Get(...)` uses a named constant like the existing
`api.ConfigResourceName`, and extract that resource name into a shared constant
that can also be reused by `oauthclients.go`, `sync_v400.go`, and `starter.go`
to keep all lookups consistent.
pkg/console/controllers/oauthclients/oauthclients.go (1)

146-159: 📐 Maintainability & Code Quality | 🔵 Trivial | ⚡ Quick win

Duplicate "fetch infra+clusterVersion, check ingress-disabled" boilerplate across controllers.

This exact pattern (Get InfrastructureConfig, Get ClusterVersion by the hardcoded "version" name, call util.IsExternalControlPlaneWithIngressDisabled, early-return) is repeated near-verbatim in pkg/console/operator/sync_v400.go (lines 64-70) and pkg/console/controllers/route/controller.go (lines 174-189). Consider extracting a small shared helper in pkg/console/controllers/util (e.g. IsIngressDisabled(infraLister, cvLister) (bool, error)) to avoid drift between the three call sites, and to centralize the magic "version" resource name (also hardcoded in pkg/console/starter/starter.go line 253) behind a named constant.

🤖 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/console/controllers/oauthclients/oauthclients.go` around lines 146 - 159,
The ingress-disabled check is duplicated across controllers, including the OAuth
client sync path and other call sites, which risks drift and repeated hardcoded
resource lookup details. Extract the shared “fetch InfrastructureConfig and
ClusterVersion, then call util.IsExternalControlPlaneWithIngressDisabled” flow
into a helper under pkg/console/controllers/util, and have oauthclients.go and
the other controllers call it instead of inlining the lookup/early-return logic.
While doing that, centralize the hardcoded "version" ClusterVersion name behind
a named constant so all callers use the same symbol.
🤖 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/console/controllers/clidownloads/controller.go`:
- Around line 128-139: In clidownloads controller logic, the early return in the
`Get`/`IsExternalControlPlaneWithIngressDisabled` branch can leave
`OCDownloadsSyncDegraded` latched from a prior run. Update the condition state
in this path before returning by clearing the `OCDownloadsSyncDegraded`
zero-value condition in the same controller flow that handles
`infrastructureConfig`, `clusterVersionConfig`, and
`statusHandler.FlushAndReturn`, so the ClusterOperator does not remain Degraded
when ingress is disabled.

In `@pkg/console/controllers/oauthclients/oauthclients.go`:
- Around line 60-61: The OAuthClients controller is using Infrastructure and
ClusterVersion listers in sync() without registering their informers with the
factory. Update the controller setup to pass infrastructureConfigInformer and
clusterVersionInformer into WithInformers(...) alongside the existing informers
so cache synchronization waits on both resources and the controller resyncs when
either changes.

In `@pkg/console/starter/starter.go`:
- Around line 249-261: The ingressDisabled check in starter.go is acting as a
one-time startup gate, so if Infrastructure or ClusterVersions are not ready yet
the route and health-check controllers may never start for this pod. Update the
startup flow around util.IsExternalControlPlaneWithIngressDisabled and the
controller setup in the starter logic so this condition is re-evaluated when the
relevant config becomes available, or make it explicit that a restart is
required for capability changes to take effect. Preserve the klog.Info path for
the disabled case, but do not let a transient startup state permanently block
controller startup.

---

Nitpick comments:
In `@pkg/console/controllers/clidownloads/controller.go`:
- Around line 128-135: The ClusterVersion lookup in the controller is hardcoding
"version" instead of using a shared resource-name constant, which makes the code
inconsistent and typo-prone. Update `clidownloads/controller.go` so
`c.clusterVersionLister.Get(...)` uses a named constant like the existing
`api.ConfigResourceName`, and extract that resource name into a shared constant
that can also be reused by `oauthclients.go`, `sync_v400.go`, and `starter.go`
to keep all lookups consistent.

In `@pkg/console/controllers/oauthclients/oauthclients.go`:
- Around line 146-159: The ingress-disabled check is duplicated across
controllers, including the OAuth client sync path and other call sites, which
risks drift and repeated hardcoded resource lookup details. Extract the shared
“fetch InfrastructureConfig and ClusterVersion, then call
util.IsExternalControlPlaneWithIngressDisabled” flow into a helper under
pkg/console/controllers/util, and have oauthclients.go and the other controllers
call it instead of inlining the lookup/early-return logic. While doing that,
centralize the hardcoded "version" ClusterVersion name behind a named constant
so all callers use the same symbol.
🪄 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: bf8e3405-e144-4ab0-877e-4e5a944d5f36

📥 Commits

Reviewing files that changed from the base of the PR and between 4d4fe9d and 942cc71.

📒 Files selected for processing (7)
  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/operator/sync_v400.go
  • pkg/console/starter/starter.go
🔗 Linked repositories identified

CodeRabbit considers these linked repositories for cross-repo context during reviews:

  • openshift/console (manual)
📜 Review details
🧰 Additional context used
📓 Path-based instructions (15)
**/*.{yaml,yml,json}

📄 CodeRabbit inference engine (Custom checks)

**/*.{yaml,yml,json}: Flag privileged: true, hostPID, hostNetwork, hostIPC, SYS_ADMIN capability, running as root without justification, and allowPrivilegeEscalation: true in container/Kubernetes manifests
When deployment manifests, operator code, or controllers are added/modified, ensure they do not introduce scheduling constraints assuming standard HA topology (3+ control-plane nodes, dedicated workers). Flag: required pod anti-affinity with maxUnavailable: 0 (deadlocks on SNO/TNF/TNA), pod topology spread with DoNotSchedule and hostname key (breaks on SNO), replica counts derived from node count without topology awareness, nodeSelector/node affinity targeting control-plane nodes (fails on HyperShift), scheduling to all control-plane nodes equally without excluding arbiter nodes (TNA), assuming dedicated worker nodes exist (SNO/TNF), or PodDisruptionBudgets designed for 3+ nodes (TNF/TNA). Do not flag if change checks ControlPlaneTopology, node counts, or topology labels before applying constraints.

Files:

  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
{manifests,bindata/assets,quickstarts,examples,profile-patches}/**/*.{yaml,yml}

📄 CodeRabbit inference engine (.claude/skills/manifest-review.md)

{manifests,bindata/assets,quickstarts,examples,profile-patches}/**/*.{yaml,yml}: Kubernetes manifests under manifests/, bindata/assets/, quickstarts/, examples/, and profile-patches/ must include the appropriate cluster profile annotations when they are CVO-deployed resources (for example include.release.openshift.io/hypershift, include.release.openshift.io/ibm-cloud-managed, include.release.openshift.io/self-managed-high-availability, and include.release.openshift.io/single-node-developer).
Console resources in the manifest trees must include the capability annotation capability.openshift.io/name: Console.
RBAC manifests must follow least-privilege design: grant only the permissions needed, avoid wildcards unless truly justified, use verbs that match the actual operation set, and set correct apiGroups ("" for core APIs and specific groups for CRDs).
Resources must use the correct namespace for their role: openshift-console for console workload resources and openshift-console-operator for operator resources; any cross-namespace reference must be explicit and intentional.
YAML manifests should use 2-space indentation, keep fields in a consistent order, and include --- separators between multiple resources in the same file.
When binding roles to service accounts, use console-operator in the openshift-console-operator namespace for operator cross-namespace access, and use console in the openshift-console namespace for console workload-scoped access.

Files:

  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
**

⚙️ CodeRabbit configuration file

**: # OpenShift Console Operator - AI Context Hub

This file serves as the central AI documentation hub for the OpenShift Console Operator project. AI assistants (Claude, Cursor, Copilot, CodeRabbit, etc.) use this and the linked documents to understand project context.

Go Version and Dependencies

Go Version and Dependencies

  • Go version: 1.24.0 (toolchain: go1.24.4)
  • Dependency management: Uses go.mod with vendoring
  • Build flags: Use GOFLAGS="-mod=vendor" for builds and tests to ensure vendored dependencies are used
  • Key dependencies: openshift/api, openshift/library-go, k8s.io client libraries
  • Go version: 1.24.0 (toolchain: go1.24.4)
  • Dependency management: Uses go.mod with vendoring
  • Build flags: Use GOFLAGS="-mod=vendor" for builds and tests to ensure vendored dependencies are used
  • Key dependencies: openshift/api, openshift/library-go, k8s.io client libraries

Quick Reference

This Repository

Document Purpose
ARCHITECTURE.md System architecture, components, repository structure
CONVENTIONS.md Go coding standards, patterns, import organization
TESTING.md Testing patterns, commands, debugging
README.md Project README with setup instructions

Console Repository (openshift/console)

For frontend-related guidelines, see the openshift/console repository:

Document Purpose
STYLEGUIDE.md Frontend code style guidelines
INTERNATIONALIZATION.md i18n patterns and translation guidelines
CONTRIBUTING.md Contribution guidelines for the console project

Project Summary

The **console-operator...

Files:

  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
  • pkg/console/operator/sync_v400.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/starter/starter.go
**/*.yaml

⚙️ CodeRabbit configuration file

**/*.yaml: Review YAML manifests based on content and kind.

Refer to /manifest-review when YAML contains:

  • kind: Role or kind: ClusterRole (RBAC review)
  • kind: RoleBinding or kind: ClusterRoleBinding
  • annotations: section (check for cluster profiles)
  • verbs: ["*"] or wildcard permissions
  • apiGroups: ["*"] or overly broad permissions
  • ServiceAccount references in subjects

Check for required annotations in manifests/:

  • include.release.openshift.io/hypershift
  • include.release.openshift.io/ibm-cloud-managed
  • include.release.openshift.io/self-managed-high-availability
  • include.release.openshift.io/single-node-developer
  • capability.openshift.io/name: Console

For quickstarts/, additionally check:

  • QuickStart spec structure
  • Task descriptions and prerequisites
  • See quickstarts/README.md for guidelines

Files:

  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
**/*.{yaml,yml}

⚙️ CodeRabbit configuration file

**/*.{yaml,yml}: If this is a Kubernetes/OpenShift manifest or Helm template:

  • securityContext: runAsNonRoot, readOnlyRootFilesystem,
    allowPrivilegeEscalation: false
  • Drop ALL capabilities, add only what is required
  • Resource limits (cpu, memory) on every container
  • No hostPID, hostNetwork, hostIPC, privileged: true
  • NetworkPolicy defined for the namespace
  • OpenShift: SCC must be restricted or custom-scoped
  • Liveness + readiness probes defined
  • automountServiceAccountToken: false unless needed
  • RBAC: least privilege; no cluster-admin for workloads
  • Helm: no .Values interpolation in shell commands

Files:

  • manifests/03-rbac-role-ns-openshift-ingress-operator.yaml
  • manifests/04-rbac-rolebinding.yaml
**/*.go

📄 CodeRabbit inference engine (AGENTS.md)

**/*.go: Follow Go coding standards and patterns documented in CONVENTIONS.md
Organize imports according to conventions documented in CONVENTIONS.md
Use gofmt to format Go code with standard formatting
Run go vet checks on all Go packages

Follow Go coding standards and patterns as documented in CONVENTIONS.md, including proper import organization

Organize Go code following the repository structure: main entry point in cmd/console/main.go, API constants in pkg/api/, operator command setup in pkg/cmd/operator/, and version command in pkg/cmd/version/

**/*.go: Use gofmt for formatting Go code
Follow standard Go naming conventions
Group imports in order: standard lib, 3rd party, kube/openshift, internal (marked with comments)
Use meaningful error messages with context in Go code
Set status conditions using status.Handle* functions with type prefixes (*Degraded, *Progressing, *Available, *Upgradeable)
Use typed errors and wrap errors to preserve stack context

Flag MD5, SHA1, DES, RC4, 3DES, Blowfish, and ECB mode cryptographic usage. Also flag custom crypto implementations and non-constant-time comparison of secrets or tokens.

**/*.go: Do not use deprecated Go APIs such as ioutil.ReadFile, ioutil.WriteFile, ioutil.ReadAll, or net.Dial in Dial callbacks; use os.ReadFile, os.WriteFile, io.ReadAll, and DialContext instead.
When returning errors in Go, wrap them with %w and include meaningful context instead of returning the raw error or using %v.
Use specific error checks such as apierrors.IsNotFound(err) instead of matching error strings with strings.Contains(err.Error(), ...).
Propagate the caller’s context.Context through operations and avoid replacing it with context.Background() inside request/controller code.
Use defer to release acquired resources so cleanup happens on all return paths.
Avoid god functions: keep Go functions to roughly under 100 lines and split code with too many responsibilities into smaller...

Files:

  • pkg/console/operator/sync_v400.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/starter/starter.go

⚙️ CodeRabbit configuration file

**/*.go: Review Go code following OpenShift operator patterns.
See CONVENTIONS.md for coding standards and patterns.

Refer to the following skills based on CODE PATTERNS, not just file paths:

Refer to /controller-review when code contains:

  • Controller struct types (e.g., type *Controller struct)
  • func New*Controller( factory functions
  • factory.New().WithFilteredEventsInformers( pattern
  • .ToController( method calls
  • Sync(ctx context.Context, controllerContext factory.SyncContext) methods
  • operatorConfig.Spec.ManagementState checks
  • status.NewStatusHandler or status.Handle* functions

Refer to /sync-handler-review when code contains:

  • Main operator sync functions (e.g., sync_v400.go content)
  • Sequential resource syncing with early returns
  • Incremental reconciliation loops
  • Multiple resourceapply.Apply*() calls in sequence
  • Dependency ordering of ConfigMaps → Secrets → Service Accounts → RBAC → Services → Deployments → Routes
  • Feature gate conditional logic

Refer to /go-quality-review for all Go code to check:

  • Deprecated imports: ioutil.ReadFile, ioutil.WriteFile, ioutil.ReadAll
  • Deprecated patterns: Dial without DialContext
  • Error handling: missing %w in fmt.Errorf
  • Code smells: deep nesting (4+ levels), functions >100 lines
  • Magic values: unexplained numbers/strings
  • Context propagation: context.Background() instead of passed ctx
  • Missing godoc on exported functions

Files:

  • pkg/console/operator/sync_v400.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/starter/starter.go
{pkg,cmd}/**/*.go

📄 CodeRabbit inference engine (CLAUDE.md)

Use gofmt for code formatting on pkg and cmd directories

{pkg,cmd}/**/*.go: Format code using gofmt -w ./pkg ./cmd
Run go vet checks on all Go packages in ./pkg and ./cmd

Files:

  • pkg/console/operator/sync_v400.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/starter/starter.go
**/*sync*.go

📄 CodeRabbit inference engine (CONVENTIONS.md)

Implement sync loops (sync_v400) incrementally: start from zero, create/update missing requirements, and return to continue on next loop

Files:

  • pkg/console/operator/sync_v400.go
**/operator/**/*.go

📄 CodeRabbit inference engine (Custom checks)

When deployment manifests, operator code, or controllers are added/modified, ensure they do not introduce scheduling constraints assuming standard HA topology. Check ControlPlaneTopology for SingleReplica/DualReplica/HighlyAvailableArbiter/External modes before applying constraints. Use required anti-affinity with maxUnavailable >= 1 (not maxUnavailable: 0). Cap replica counts to schedulable nodes. Exclude arbiter nodes on TNA. Avoid master nodeSelectors on HyperShift. Use library-go DeploymentController hooks (WithTopologyAwareReplicasHook, WithTopologyAwareSchedulingHook, WithControlPlaneNodeSelectorHook).

Files:

  • pkg/console/operator/sync_v400.go
**/sync_v400.go

📄 CodeRabbit inference engine (.claude/skills/sync-handler-review.md)

Incremental sync pattern: each sync loop should stop on the first error and resume from the next step on the next reconciliation instead of collecting and joining all errors.

Files:

  • pkg/console/operator/sync_v400.go
**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}

⚙️ CodeRabbit configuration file

**/*.{py,js,ts,go,rs,java,rb,php,kt,swift,cs}: Injection prevention (prodsec-skills):

  • SQL: parameterized queries only; no string concatenation
  • Command: no shell=True, os.system, or backtick exec with user input
  • LDAP/XPath: escape special characters in filters
  • Path traversal: canonicalize paths, reject ../
  • Deserialization: no pickle/yaml.load()/eval on untrusted data
  • Prototype pollution: no recursive merge of untrusted objects
  • Validate at trust boundaries with allow-lists, not deny-lists
  • Normalize Unicode and anchor regexes (^$); watch for ReDoS

Files:

  • pkg/console/operator/sync_v400.go
  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/clidownloads/controller.go
  • pkg/console/starter/starter.go
pkg/console/controllers/**/*.go

📄 CodeRabbit inference engine (ARCHITECTURE.md)

Place all controller implementations in pkg/console/controllers/ subdirectory, with each controller in its own package (e.g., clidownloads/, oauthclients/, route/, service/)

Files:

  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/oauthclients/oauthclients.go
  • pkg/console/controllers/clidownloads/controller.go
**/*controller*.go

📄 CodeRabbit inference engine (CONVENTIONS.md)

Use the OpenShift library-go factory pattern for controllers

**/*controller*.go: Use the controller factory pattern with factory.New().WithFilteredEventsInformers(), util.IncludeNamesFilter() for informer filtering, and a descriptive ToController() call with a recorder.
In controller sync logic, handle all operatorConfig.Spec.ManagementState values: Managed, Unmanaged, Removed, and return an error for unknown states.
Create and use status.NewStatusHandler(c.operatorClient), set the appropriate status condition helpers (HandleProgressingOrDegraded(), HandleDegraded(), HandleProgressing(), HandleAvailable()), and always call FlushAndReturn() at the end of sync.
Group imports with commented sections for standard library, third-party, kube, openshift, and operator/internal packages.
Wrap errors with context using fmt.Errorf("failed to X: %w", err), handle apierrors.IsNotFound() appropriately for delete operations, optional resources, and get-before-create flows, and return meaningful error messages.
Use resourceapply.Apply*() functions from library-go, pass the controller recorder for events, and handle returned errors properly.
Set owner references with util.OwnerRefFrom(cr) from pkg/console/subresource/util, ensure only one owner reference has controller=true, and clean up owner references when replacing existing resources.

Files:

  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/clidownloads/controller.go
**/*controller.go

📄 CodeRabbit inference engine (.claude/skills/sync-handler-review.md)

**/*controller.go: Controller Sync methods must reconcile dependent resources in dependency order: ConfigMaps and Secrets first, then Service Accounts, RBAC (Roles and RoleBindings), Services, Deployments, and finally Routes.
Status updates must track reconciliation progress accurately by adding progressing/degraded conditions on failures and marking the resource available only after reconciliation completes successfully.
Return immediately on reconciliation errors instead of logging and continuing, to preserve incremental reconciliation behavior.
Use resourceapply.Apply*() helpers for resource creation and updates instead of writing separate create/update logic.
When a resource is removed from the desired config, the controller must delete the corresponding cluster object and treat NotFound as a successful no-op.
Check feature gates before syncing gated resources, and only reconcile the gated resources when the feature is enabled.
Respect ManagementState, including missing cleanup logic for Removed state.
Do not mutate live Kubernetes objects directly; build desired state and apply it through reconciliation helpers.
Always update status conditions during reconciliation; missing status condition updates is an anti-pattern.

Files:

  • pkg/console/controllers/route/controller.go
  • pkg/console/controllers/clidownloads/controller.go
pkg/console/starter/**/*.go

📄 CodeRabbit inference engine (ARCHITECTURE.md)

Access feature gates via featuregates.FeatureGateAccess in starter.go for features like ExternalOIDC and ConsolePluginContentSecurityPolicy

Files:

  • pkg/console/starter/starter.go
🔇 Additional comments (7)
manifests/03-rbac-role-ns-openshift-ingress-operator.yaml (1)

11-11: LGTM!

manifests/04-rbac-rolebinding.yaml (1)

90-90: LGTM!

pkg/console/controllers/clidownloads/controller.go (2)

50-56: LGTM!

Also applies to: 76-82


87-98: 🩺 Stability & Availability

Confirm the controller start order against the shared config informer factory — if that factory is already running before this controller starts, the missing informer may be a watch gap rather than a startup hazard.

pkg/console/controllers/route/controller.go (1)

174-195: LGTM!

pkg/console/starter/starter.go (1)

305-317: LGTM!

Also applies to: 442-504, 697-730

pkg/console/operator/sync_v400.go (1)

63-71: 🎯 Functional Correctness

ClusterVersion informer is already registered with the config informers, so this race concern doesn't apply.

			> Likely an incorrect or invalid review comment.

Comment thread pkg/console/controllers/clidownloads/controller.go
Comment thread pkg/console/controllers/oauthclients/oauthclients.go
Comment thread pkg/console/starter/starter.go
stefanonardo added a commit to stefanonardo/hypershift that referenced this pull request Jul 6, 2026
Remove the validation that requires Console to be disabled when Ingress
is disabled. The console-operator now handles ingress-disabled gracefully
(openshift/console-operator#1182).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@stefanonardo

Copy link
Copy Markdown
Author

/retest

Skip route and health check controllers when Ingress is disabled.
Add ingress-disabled checks to OAuth, CLI downloads, and main sync.
Gate ingress-operator RBAC manifests with Console+Ingress capability.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
@stefanonardo

Copy link
Copy Markdown
Author

/retest

@openshift-ci

openshift-ci Bot commented Jul 7, 2026

Copy link
Copy Markdown
Contributor

@stefanonardo: 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-aws-console 302c519 link true /test e2e-aws-console
ci/prow/e2e-gcp-ovn 302c519 link true /test e2e-gcp-ovn

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