Skip to content

OCPBUGS-77042: use NewFromConfig instead of NewFromConfigOrDie in builder - #1426

Open
Cali0707 wants to merge 2 commits into
openshift:mainfrom
Cali0707:fix-missing-ca-panic
Open

OCPBUGS-77042: use NewFromConfig instead of NewFromConfigOrDie in builder#1426
Cali0707 wants to merge 2 commits into
openshift:mainfrom
Cali0707:fix-missing-ca-panic

Conversation

@Cali0707

@Cali0707 Cali0707 commented Jul 21, 2026

Copy link
Copy Markdown

This should fix the bug we are seeing with panics when there is a missing CA cert temporarily. By moving from NewFromConfigOrDie to NewFromConfig we remove the possibility for a panic and instead this will enter an exponential backoff retry before surfacing as a status error

Summary by CodeRabbit

  • Bug Fixes
    • Prevented abrupt termination during client setup by switching initialization to return errors instead of panicking.
    • Updated resource builder initialization and factory wiring to propagate client-creation failures to callers and reuse initialized clients safely across runs.
  • Tests
    • Adjusted test builder setup to use the updated error-returning initialization behavior.

@openshift-ci-robot openshift-ci-robot added jira/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. 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 21, 2026
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@Cali0707: This pull request references Jira Issue OCPBUGS-77042, 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:

This should fix the bug we are seeing with panics when there is a missing CA cert temporarily. By moving from NewFromConfigOrDie to NewFromConfig we remove the possibility for a panic and instead this will enter an exponential backoff retry before surfacing as a status error

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 21, 2026

Copy link
Copy Markdown

Warning

Review limit reached

@Cali0707, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 40 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

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

Review profile: CHILL

Plan: Pro Plus

Run ID: 2a28f538-ca72-47e8-9e2d-2e85920e11bb

📥 Commits

Reviewing files that changed from the base of the PR and between f184e09 and 6b0ac61.

📒 Files selected for processing (2)
  • hack/generate-lib-resources.py
  • lib/resourcebuilder/resourcebuilder.go

Walkthrough

Resource builder factories now return initialization errors. Typed clients use NewForConfig instead of NewForConfigOrDie, with errors propagated through runtime and generated builders, the cluster operator builder, and test factories. Generated imports are grouped, and typed-client sets are cached per configuration pointer.

Changes

Resource builder initialization

Layer / File(s) Summary
Error-returning constructor contract
lib/resourcebuilder/interface.go, pkg/cvo/sync_test.go
NewInterfaceFunc and New now return and propagate constructor errors, while the test factory returns a nil error on successful construction.
Cached typed-client initialization
lib/resourcebuilder/resourcebuilder.go, pkg/cvo/internal/operatorstatus.go
Typed clients use NewForConfig; client sets are synchronized and cached for up to two configurations, and initialization errors propagate through the builders.
Generated builder and import output
hack/generate-lib-resources.py
Generated resource builders include grouped imports, error-returning client creation, cached client sets, and error-returning builder factories.

Estimated code review effort: 3 (Moderate) | ~20 minutes

Sequence Diagram(s)

sequenceDiagram
  participant newBuilder
  participant getOrCreateClientSet
  participant newClientSet
  participant KubernetesTypedClients
  newBuilder->>getOrCreateClientSet: request clientSet for config
  getOrCreateClientSet->>newClientSet: create clientSet on cache miss
  newClientSet->>KubernetesTypedClients: call NewForConfig
  KubernetesTypedClients-->>newClientSet: typed clients or error
  newClientSet-->>getOrCreateClientSet: clientSet or error
  getOrCreateClientSet-->>newBuilder: cached clientSet or error
Loading
🚥 Pre-merge checks | ✅ 14 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 20.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (14 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: replacing the die-on-error client constructor with an error-returning builder path.
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 Ginkgo titles with dynamic data were added; the only test names in sync_test.go are static t.Run names.
Test Structure And Quality ✅ Passed No Ginkgo tests were changed in this commit; the touched files are non-test code, so the check is not applicable.
Microshift Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the only test file change is a helper signature update with no It/Describe/Context/When blocks.
Single Node Openshift (Sno) Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the touched tests are unit tests and introduce no multi-node or SNO assumptions.
Topology-Aware Scheduling Compatibility ✅ Passed No scheduling constraints, node selectors, affinities, replicas, or PDBs were added; the PR only changes client initialization and error propagation.
Ote Binary Stdout Contract ✅ Passed Touched init/setup code only registers schemes/flags; no new stdout writes or stdout logging calls were added in process-level code.
Ipv6 And Disconnected Network Test Compatibility ✅ Passed No new Ginkgo e2e tests were added; the only test change is a unit-test helper returning an error, with no IPv4 or external-network assumptions.
No-Weak-Crypto ✅ Passed Inspected all changed files and patch hunks; they only add error propagation/caching, with no MD5/SHA1/DES/RC4/3DES/Blowfish/ECB or secret comparisons.
Container-Privileges ✅ Passed PR only changes Go/Python builder code and tests; no manifests or securityContext/privilege settings were added.
No-Sensitive-Data-In-Logs ✅ Passed No new logging was added; touched files only change client construction/error propagation. Existing klog messages are unchanged and don’t emit secrets directly.
✨ Finishing Touches
🧪 Generate unit tests (beta)
  • Create PR with unit tests

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

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

@openshift-ci

openshift-ci Bot commented Jul 21, 2026

Copy link
Copy Markdown
Contributor

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

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

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

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

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🧹 Nitpick comments (1)
hack/generate-lib-resources.py (1)

172-177: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Fix unused loop control variable.

The loop variable data is not used in the loop body. Consider replacing it with _ to suppress static analysis warnings and clarify intent.

♻️ Proposed refactor
-    for prop_name, data in sorted(client_properties.items()):
+    for prop_name, _ in sorted(client_properties.items()):
         var_name = prop_name[0].lower() + prop_name[1:]
         lines.append('\t\t{:{width}} {},'.format(prop_name + ':', var_name, width=longest_property+1))
🤖 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 `@hack/generate-lib-resources.py` around lines 172 - 177, Replace the unused
data variable in the sorted client_properties loop with the conventional
underscore placeholder, while preserving prop_name and the generated output
unchanged.

Source: Linters/SAST tools

🤖 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 `@hack/generate-lib-resources.py`:
- Around line 172-177: Replace the unused data variable in the sorted
client_properties loop with the conventional underscore placeholder, while
preserving prop_name and the generated output unchanged.

ℹ️ Review info
⚙️ Run configuration

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

Review profile: CHILL

Plan: Enterprise

Run ID: db0b4910-c64f-4e74-bd27-615336b66875

📥 Commits

Reviewing files that changed from the base of the PR and between f232fe1 and 3c8efd2.

📒 Files selected for processing (5)
  • hack/generate-lib-resources.py
  • lib/resourcebuilder/interface.go
  • lib/resourcebuilder/resourcebuilder.go
  • pkg/cvo/internal/operatorstatus.go
  • pkg/cvo/sync_test.go

@Cali0707

Copy link
Copy Markdown
Author

/jira refresh

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

Copy link
Copy Markdown
Contributor

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

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

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

Details

In response to this:

/jira refresh

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.

Comment thread lib/resourcebuilder/resourcebuilder.go Outdated
if err != nil {
return nil, err
}
actual, _ := clientSetCache.LoadOrStore(config, cs)

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.

we'll want to clear the map here too, right? To avoid a slow memory leak as the REST config slowly rotates over time?

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

yes, just forgot about that initially - will add

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

Looking through this, we would not in practice get a memory leak here, as:

  1. cache is keyed by the pointer, not the value
  2. There are only two rest.Config pointers, which are only ever created at startup

So in practice this map will only ever have two entries

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.

  1. cache is keyed by the pointer, not the value
  2. There are only two rest.Config pointers, which are only ever created at startup

This makes me a bit nervous. Say the value changes (cred rotation, whatever) but the pointer does not. Will the old client automatically update to use the new creds? Or do we need to create a new client in that situation?

If we are confident we'll only ever have two entries, maybe we can simplify by dropping the map, and instead tracking the two clients with per-client properties? That way it's very clear that there are only two slots, and it will also be very clear if someone makes a future change that adds an additional slot.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

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

The two rest.Config pointers are created once at startup in pkg/start/start.go via cb.RestConfig(defaultQPS) and cb.RestConfig(highQPS). They are never recreated, the same two pointers are held by the resourceBuilder in pkg/cvo/cvo.go for the lifetime of the process..

Credential rotation is handled transparently by client-go, so we do not need to worry about recreating the rest.Config` or the clients built from it.

That said, I like your suggestion to replace the map with a fixed size array so that the two slot constraint is clear

@Cali0707
Cali0707 force-pushed the fix-missing-ca-panic branch from 11c826c to 0419cf7 Compare July 21, 2026 17:49
@openshift-ci-robot

Copy link
Copy Markdown
Contributor

@Cali0707: This pull request references Jira Issue OCPBUGS-77042, 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 (jiajliu@redhat.com), skipping review request.

Details

In response to this:

This should fix the bug we are seeing with panics when there is a missing CA cert temporarily. By moving from NewFromConfigOrDie to NewFromConfig we remove the possibility for a panic and instead this will enter an exponential backoff retry before surfacing as a status error

Summary by CodeRabbit

  • Bug Fixes
  • Improved client initialization to return errors instead of terminating the process on configuration failures.
  • Updated builder/client setup to consistently propagate initialization errors and reuse initialized typed clients.
  • Tests
  • Updated test builder wiring to align with the new error-returning initialization behavior.

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.

Comment thread lib/resourcebuilder/resourcebuilder.go

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Actionable comments posted: 1

Caution

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

⚠️ Outside diff range comments (1)
hack/generate-lib-resources.py (1)

164-199: 🩺 Stability & Availability | 🟠 Major | ⚡ Quick win

Codegen root cause for unbounded clientSetCache (see consolidated comment).

This template emits the unbounded, pointer-keyed clientSetCache with no eviction — same concern flagged on the generated lib/resourcebuilder/resourcebuilder.go. See consolidated comment for the shared fix.

🤖 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 `@hack/generate-lib-resources.py` around lines 164 - 199, Update the generation
template around getOrCreateClientSet and clientSetCache to stop emitting an
unbounded pointer-keyed sync.Map. Apply the same bounded cache strategy required
for the generated resourcebuilder client cache, including eviction and safe
reuse of client sets, while preserving newClientSet error handling and client
creation behavior.
🤖 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 `@lib/resourcebuilder/resourcebuilder.go`:
- Around line 135-147: Update getOrCreateClientSet and clientSetCache to prevent
unbounded retention of client sets when new *rest.Config instances replace older
ones. Implement bounded or insertion-order eviction while preserving
concurrently live distinct configurations; do not clear all entries on every
cache miss unless the surrounding usage guarantees only one live configuration
at a time.

---

Outside diff comments:
In `@hack/generate-lib-resources.py`:
- Around line 164-199: Update the generation template around
getOrCreateClientSet and clientSetCache to stop emitting an unbounded
pointer-keyed sync.Map. Apply the same bounded cache strategy required for the
generated resourcebuilder client cache, including eviction and safe reuse of
client sets, while preserving newClientSet error handling and client creation
behavior.
🪄 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: aa68bc00-8436-422c-89cf-2268e8fd0eae

📥 Commits

Reviewing files that changed from the base of the PR and between 3c8efd2 and 0419cf7.

📒 Files selected for processing (2)
  • hack/generate-lib-resources.py
  • lib/resourcebuilder/resourcebuilder.go

Comment thread lib/resourcebuilder/resourcebuilder.go Outdated
The generated newBuilder function previously used NewForConfigOrDie for
every typed client, which would panic if any client construction failed.
Switch to NewForConfig so errors propagate instead.

On failure, getOrCreateClientSet returns the error without caching, so
the next reconciliation attempt retries client creation from scratch.
The exponential backoff in Task.Run handles transient failures
automatically. If retries exhaust, the error surfaces as a sync failure
on the ClusterVersion status rather than crashing the process.

Signed-off-by: Calum Murray <cmurray@redhat.com>
@Cali0707
Cali0707 force-pushed the fix-missing-ca-panic branch from 0419cf7 to b7bc9ad Compare July 21, 2026 18:13
@Cali0707

Copy link
Copy Markdown
Author

/retest-required

@Cali0707

Copy link
Copy Markdown
Author

/retest

1 similar comment
@tmshort

tmshort commented Jul 28, 2026

Copy link
Copy Markdown

/retest

@Cali0707
Cali0707 force-pushed the fix-missing-ca-panic branch from b7bc9ad to f184e09 Compare July 30, 2026 20:08

@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

🤖 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 `@hack/generate-lib-resources.py`:
- Around line 202-221: Add an early nil-config guard to the generated
getOrCreateClientSet template in hack/generate-lib-resources.py, returning the
specified error before cache lookup; then regenerate
lib/resourcebuilder/resourcebuilder.go so its generated getOrCreateClientSet
implementation matches. Do not hand-edit lib/resourcebuilder/resourcebuilder.go;
the sibling site is corrected by regeneration.
- Around line 178-183: Update the loop over sorted client_properties in the
resource-generation code to use an intentionally ignored variable instead of the
unused data binding, while preserving prop_name, var_name, and the generated
output unchanged.
- Around line 223-236: Update the sorted client_properties loop in the
resource-generation code to avoid binding the unused data value, while
preserving prop_name iteration and generated builder field output.
🪄 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: Pro Plus

Run ID: 9c6c015b-505d-45e9-89e5-3884bf5dbf8c

📥 Commits

Reviewing files that changed from the base of the PR and between 0419cf7 and f184e09.

📒 Files selected for processing (5)
  • hack/generate-lib-resources.py
  • lib/resourcebuilder/interface.go
  • lib/resourcebuilder/resourcebuilder.go
  • pkg/cvo/internal/operatorstatus.go
  • pkg/cvo/sync_test.go

Comment thread hack/generate-lib-resources.py
Comment thread hack/generate-lib-resources.py
Comment thread hack/generate-lib-resources.py
The CVO creates exactly two rest.Config pointers at startup (default-QPS
and burst-QPS). Cache the client sets built from each using a fixed-size
[2]clientSetSlot array so the two-slot constraint is explicit in the type
system. A third config will produce a clear error rather than silently
growing.

Signed-off-by: Calum Murray <cmurray@redhat.com>
@Cali0707
Cali0707 force-pushed the fix-missing-ca-panic branch from f184e09 to 6b0ac61 Compare July 30, 2026 20:27
@openshift-ci

openshift-ci Bot commented Jul 31, 2026

Copy link
Copy Markdown
Contributor

@Cali0707: 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-agnostic-ovn-techpreview-serial-1of3 6b0ac61 link true /test e2e-agnostic-ovn-techpreview-serial-1of3
ci/prow/e2e-hypershift 6b0ac61 link true /test e2e-hypershift
ci/prow/e2e-hypershift-conformance 6b0ac61 link true /test e2e-hypershift-conformance

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/severity-important Referenced Jira bug's severity is important for the branch this PR is targeting. 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