Skip to content

✨ fix(boxcutter): cache Secrets only in olmv1-system namespace to ensure better performance#2609

Open
camilamacedo86 wants to merge 1 commit intooperator-framework:mainfrom
camilamacedo86:fix-ai-secret
Open

✨ fix(boxcutter): cache Secrets only in olmv1-system namespace to ensure better performance#2609
camilamacedo86 wants to merge 1 commit intooperator-framework:mainfrom
camilamacedo86:fix-ai-secret

Conversation

@camilamacedo86
Copy link
Copy Markdown
Contributor

@camilamacedo86 camilamacedo86 commented Mar 31, 2026

Configures the controller manager cache to watch Secrets only in the olmv1-system namespace, preventing a cluster-wide Secret informer while maintaining good performance for bundle Secret reads.

Motivation

Inspired by discussion in:
openshift/operator-framework-operator-controller#687 (comment)

Copilot AI review requested due to automatic review settings March 31, 2026 05:22
@openshift-ci openshift-ci bot requested review from joelanford and perdasilva March 31, 2026 05:22
@netlify
Copy link
Copy Markdown

netlify bot commented Mar 31, 2026

Deploy Preview for olmv1 ready!

Name Link
🔨 Latest commit d4523d9
🔍 Latest deploy log https://app.netlify.com/projects/olmv1/deploys/69cb76d0510a5c0008acdd35
😎 Deploy Preview https://deploy-preview-2609--olmv1.netlify.app
📱 Preview on mobile
Toggle QR Code...

QR Code

Use your smartphone camera to open QR code link.

To edit notification comments on pull requests, go to your Netlify project configuration.

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR switches ClusterObjectSet Secret lookups from the cached controller-runtime client to the uncached API reader to avoid creating a cluster-wide Secret informer (reducing memory/network/cache-sync overhead on large clusters).

Changes:

  • Add an APIReader field to ClusterObjectSetReconciler.
  • Update resolveObjectRef to read Secrets via APIReader.Get instead of Client.Get.
  • Wire mgr.GetAPIReader() in cmd/operator-controller/main.go and update unit tests accordingly.

Reviewed changes

Copilot reviewed 5 out of 5 changed files in this pull request and generated 2 comments.

Show a summary per file
File Description
internal/operator-controller/controllers/clusterobjectset_controller.go Introduces APIReader and uses it for Secret retrieval in resolveObjectRef.
cmd/operator-controller/main.go Wires APIReader from the manager into the reconciler.
internal/operator-controller/controllers/resolve_ref_test.go Updates tests to set APIReader on the reconciler.
internal/operator-controller/controllers/clusterobjectset_controller_test.go Updates controller tests to set APIReader.
internal/operator-controller/controllers/clusterobjectset_controller_internal_test.go Updates internal tests to set APIReader.

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Copy link
Copy Markdown
Contributor

@pedjak pedjak left a comment

Choose a reason for hiding this comment

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

Given that we have switched to secret-based approach for all bundles, this is going to add at least one more API call per reconcile round. If this is really needed, I would still suggest to use cache-based client, but either:

  • disable caching of secrets:
mgr, err := ctrl.NewManager(cfg, ctrl.Options{                                                                                                                             
      Client: client.Options{                                                                                                                                                
          Cache: &client.CacheOptions{                                                                                                                                       
              DisableFor: []client.Object{                                                                                                                                   
                  &corev1.Secret{},                                                                                                                                          
              },                                                                                                                                                             
          },                                                                                                                                                                 
      },                                                    
  })
  • or, restrict caching for only olmv1-system namespace

I would prefer the later because it does not add additional API calls for most of bundles.

@openshift-ci
Copy link
Copy Markdown

openshift-ci bot commented Mar 31, 2026

[APPROVALNOTIFIER] This PR is NOT APPROVED

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

@camilamacedo86 camilamacedo86 changed the title 🐛 fix: (boxcutter) use uncached reader for Secret lookups in ClusterObjectSet 🐛 fix(boxcutter): cache Secrets only in olmv1-system namespace Mar 31, 2026
@camilamacedo86 camilamacedo86 changed the title 🐛 fix(boxcutter): cache Secrets only in olmv1-system namespace ✨ fix(boxcutter): cache Secrets only in olmv1-system namespace to ensure better performance Mar 31, 2026
Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

Copilot reviewed 1 out of 1 changed files in this pull request and generated 3 comments.


💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Configure cache to watch Secrets exclusively in olmv1-system, avoiding a cluster-wide Secret informer while maintaining performance for bundle Secret lookups via the cached client
@codecov
Copy link
Copy Markdown

codecov bot commented Mar 31, 2026

Codecov Report

❌ Patch coverage is 0% with 6 lines in your changes missing coverage. Please review.
✅ Project coverage is 66.97%. Comparing base (43351b2) to head (d4523d9).
⚠️ Report is 2 commits behind head on main.

Files with missing lines Patch % Lines
cmd/operator-controller/main.go 0.00% 5 Missing and 1 partial ⚠️
Additional details and impacted files
@@             Coverage Diff             @@
##             main    #2609       +/-   ##
===========================================
+ Coverage   53.50%   66.97%   +13.47%     
===========================================
  Files         139      139               
  Lines        9872     9878        +6     
===========================================
+ Hits         5282     6616     +1334     
+ Misses       4210     2773     -1437     
- Partials      380      489      +109     
Flag Coverage Δ
e2e 10.73% <0.00%> (?)
experimental-e2e 52.54% <0.00%> (?)
unit 53.47% <0.00%> (-0.04%) ⬇️

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

☔ View full report in Codecov by Sentry.
📢 Have feedback on the report? Share it here.

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

Comment on lines +287 to +297
// Ensure bundle Secrets in the configured systemNamespace are cached without enabling a cluster-wide Secret informer.
// Bundle Secrets are created in cfg.systemNamespace by SecretPacker.
if secretCache, ok := cacheOptions.ByObject[&corev1.Secret{}]; ok {
if secretCache.Namespaces == nil {
secretCache.Namespaces = make(map[string]crcache.Config)
}
if _, exists := secretCache.Namespaces[cfg.systemNamespace]; !exists {
secretCache.Namespaces[cfg.systemNamespace] = crcache.Config{}
}
cacheOptions.ByObject[&corev1.Secret{}] = secretCache
}
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 already cache everything in the system namespace, don't we? See lines 259-261.

cfg.systemNamespace: {LabelSelector: k8slabels.Everything()},
},
DefaultLabelSelector: k8slabels.Nothing(),
// Memory optimization: strip managed fields and large annotations from cached objects
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.

Aside: I don't think we strip managed fields anymore do we? That would break our SSA clients (I think?)

Copy link
Copy Markdown
Contributor

@pedjak pedjak left a comment

Choose a reason for hiding this comment

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

Comment done by Claude:

A few observations on this change:

The map lookup is always false — this code is unreachable

cacheOptions.ByObject has type map[client.Object]cache.ByObject, where client.Object is an interface. Go compares interface map keys by (dynamic type, dynamic value). Since the dynamic type here is *corev1.Secret (a pointer), Go compares pointer addresses. The &corev1.Secret{} allocated on line 286 is a different pointer than the one used as key in SetupPullSecretCache (pullsecretcache.go:37), so the lookup never matches and ok is always false.

The entire block is dead code.

Even if it worked, it would be redundant

  1. DefaultNamespaces (lines 258-260) already includes cfg.systemNamespace with LabelSelector: labels.Everything(), so everything in that namespace (including Secrets) is already cached.
  2. SetupPullSecretCache already configures Secret caching scoped to saKey.Namespace, which is cfg.systemNamespace (the operator's own SA namespace).

There is no cluster-wide Secret informer to prevent — the existing configuration already scopes it.

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants