Skip to content

Conversation

@bharath-b-rh
Copy link
Contributor

No description provided.

@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 24, 2025
@openshift-ci-robot
Copy link

openshift-ci-robot commented Dec 24, 2025

@bharath-b-rh: This pull request references ESO-289 which is a valid jira issue.

Warning: The referenced jira issue has an invalid target version for the target branch this PR targets: expected the story to target the "4.22.0" version, but no target version was set.

Details

In response to this:

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
Copy link

coderabbitai bot commented Dec 24, 2025

Warning

.coderabbit.yaml has a parsing error

The CodeRabbit configuration file in this repository has a parsing error and default settings were used instead. Please fix the error(s) in the configuration file. You can initialize chat with CodeRabbit to get help with the configuration file.

💥 Parsing errors (1)
end of the stream or a document separator is expected in ".coderabbit.yaml" (1:1)

 1 | @coderabbitai When a comment "@c ...
-----^
⚙️ Configuration instructions
  • Please see the configuration documentation for more information.
  • You can also validate your configuration using the online YAML validator.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Walkthrough

This PR refactors multiple Kubernetes CRD API types to use optional pointer fields instead of concrete types, improving optionality semantics. It includes corresponding nil-safe accessor patterns, deep copy implementations, updated test configurations, and configuration file adjustments to align with the new pointer-based type signatures.

Changes

Cohort / File(s) Summary
CRD API Type Definitions
api/v1alpha1/external_secrets_config_types.go, api/v1alpha1/external_secrets_manager_types.go, api/v1alpha1/meta.go
Convert concrete struct fields to optional pointers (e.g., ApplicationConfig, ControllerConfig, Mode, Labels, Tolerations, NodeSelector). Update field tags with +optional, +required, omitempty. Adjust optionality markers for nested config types and collections.
DeepCopy Implementations
api/v1alpha1/zz_generated.deepcopy.go
Add nil-guarded allocations and deep-copy invocations for pointer fields. Handle conditional population of pointer-based containers (slices, maps). Replace direct assignments with per-element DeepCopyInto calls for nested structures.
CRD Schema & Metadata
config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml, api/v1alpha1/groupversion_info.go
Normalize YAML description text capitalization (lowercase starting words). Add trailing periods to public comments. No structural schema or validation changes.
Controller Nil-Safe Accessors
pkg/controller/external_secrets/deployments.go, pkg/controller/external_secrets/utils.go, pkg/controller/external_secrets/certificate.go, pkg/controller/external_secrets/install_external_secrets.go, pkg/controller/external_secrets/networkpolicy.go
Introduce explicit nil checks for optional config fields (ControllerConfig, ApplicationConfig, CertProvider). Use ptr.Deref for safe dereference of optional values. Replace manual map copies with maps.Copy. Update proxy and container handling for pointer-based fields.
Controller Implementation Updates
pkg/controller/external_secrets_manager/controller.go, pkg/controller/external_secrets/configmap.go, pkg/controller/crd_annotator/controller.go
Add pointer dereferencing for status fields (Name, Type). Replace fmt.Sprintf with fmt.Appendf for patch construction. Add ctx field to Reconciler struct. Minor formatting adjustments.
Common Utilities
pkg/controller/common/errors.go, pkg/controller/common/utils.go, pkg/controller/common/validation_helpers_duplication.go
Simplify error extraction in IsIrrecoverableError using errors.As. Add maps.Copy for label copying. Introduce atomic.Uint32 done field for reset capability. Add nil guards for optional config fields. Update comment punctuation.
Controller Tests
pkg/controller/external_secrets/*_test.go, pkg/controller/external_secrets_manager/*_test.go, pkg/controller/crd_annotator/*_test.go
Update test struct initializations to use pointer-wrapped config types (\*ControllerConfig, \*ApplicationConfig, \*PluginsConfig). Replace bare enum values with ptr.To(...) wrappers. Add import of k8s.io/utils/ptr. Adjust nested field access patterns for pointer types.
Test Utilities & E2E Tests
test/apis/generator.go, test/apis/vars.go, test/e2e/e2e_test.go
Replace interface{} with any type alias. Update JSON schema patch construction to use fmt.Appendf. Adjust CRD validation patch generation. Remove cert-controller pod readiness check from E2E verification.
Configuration
.coderabbit.yaml
Add directive to consolidate unresolved nitpick suggestions into a single git-diff formatted comment on PR command @coderabbitai /nitpicks.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

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

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.5.0)

Error: build linters: unable to load custom analyzer "kubeapilinter": bin/kube-api-linter.so, plugin: not implemented
The command is terminated due to an error: build linters: unable to load custom analyzer "kubeapilinter": bin/kube-api-linter.so, plugin: not implemented


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

@openshift-ci openshift-ci bot requested review from TrilokGeer and swghosh December 24, 2025 12:53
@openshift-ci
Copy link

openshift-ci bot commented Dec 24, 2025

[APPROVALNOTIFIER] This PR is APPROVED

This pull-request has been approved by: bharath-b-rh

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

The pull request process is described here

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

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

@openshift-ci openshift-ci bot added the approved Indicates a PR has been approved by an approver from all required OWNERS files. label Dec 24, 2025
@bharath-b-rh
Copy link
Contributor Author

@coderabbitai /nitpicks

@coderabbitai
Copy link

coderabbitai bot commented Dec 24, 2025

@bharath-b-rh: I'll review the PR with a focus on nitpicks, style issues, and minor improvements. Since this PR addresses linter-suggested fixes, I'll pay special attention to code quality, consistency, and best practices.

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

Copy link

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

Caution

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

⚠️ Outside diff range comments (4)
pkg/controller/common/utils.go (2)

244-266: Critical: InitContainers are not compared.

The function checks the length of InitContainers (lines 244-247) and adds them to fetchedContainers (lines 252-254), but the comparison loop (lines 255-264) only iterates over desired.Spec.Template.Spec.Containers. This means modifications to InitContainers (e.g., image, args, env changes) will not be detected, preventing updates from being applied.

🔎 Proposed fix to include InitContainers in the comparison
 	for i := range desired.Spec.Template.Spec.Containers {
 		desiredContainer := &desired.Spec.Template.Spec.Containers[i]
 		fetchedContainer, exists := fetchedContainers[desiredContainer.Name]
 		if !exists {
 			return true
 		}
 		if containerSpecModified(desiredContainer, fetchedContainer) {
 			return true
 		}
 	}
+	for i := range desired.Spec.Template.Spec.InitContainers {
+		desiredContainer := &desired.Spec.Template.Spec.InitContainers[i]
+		fetchedContainer, exists := fetchedContainers[desiredContainer.Name]
+		if !exists {
+			return true
+		}
+		if containerSpecModified(desiredContainer, fetchedContainer) {
+			return true
+		}
+	}
 
 	return false

555-566: Critical: Missing double-check pattern creates race condition.

The function has two issues:

  1. Line 558 loads done but doesn't use the result (dead code).
  2. The implementation lacks a double-check after acquiring the lock, allowing f() to be called multiple times if multiple goroutines check done == 0 before any of them sets it to 1.
🔎 Proposed fix with double-check pattern
-// Do is same as sync.Once.Do, which calls the passed func f() only once
-// until Now is reset.
+// Do calls f() only once until Reset is called, similar to sync.Once.Do.
 func (n *Now) Do(f func()) {
-	n.done.Load()
 	if n.done.Load() == 0 {
 		n.Lock()
 		defer n.Unlock()
-
-		defer n.done.Store(1)
-		f()
+		if n.done.Load() == 0 {
+			defer n.done.Store(1)
+			f()
+		}
 	}
 }
pkg/controller/external_secrets/test_utils.go (1)

37-49: Minor typo in comments.

The comments at lines 37 and 44 have trailing ,. instead of just .

🔎 Proposed fix
-// testService returns a Service object decoded from the specified asset file,.
+// testService returns a Service object decoded from the specified asset file.
 func testService(assetName string) *corev1.Service {
-// testServiceAccount returns a ServiceAccount object decoded from the specified asset file,.
+// testServiceAccount returns a ServiceAccount object decoded from the specified asset file.
 func testServiceAccount(assetName string) *corev1.ServiceAccount {
pkg/controller/external_secrets_manager/controller_test.go (1)

295-307: Pointer comparison may not work as intended.

At Line 297, c1.Name != c2.Name compares pointer addresses rather than the string values they point to. Since c1.Name comes from the reconciled object and c2.Name from the expected test data, they will have different memory addresses even if the string values are identical, causing the comparison to always evaluate to true (not equal).

This could lead to test logic bypassing the condition comparison. Consider using value comparison:

🔎 Proposed fix
 			for _, c1 := range esm.Status.ControllerStatuses {
 				for _, c2 := range tt.expectedStatusCondition {
-					if c1.Name != c2.Name {
+					if ptr.Deref(c1.Name, "") != ptr.Deref(c2.Name, "") {
 						continue
 					}
📜 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 d29a39d and 41730e0.

📒 Files selected for processing (38)
  • .coderabbit.yaml
  • api/v1alpha1/external_secrets_config_types.go
  • api/v1alpha1/external_secrets_manager_types.go
  • api/v1alpha1/groupversion_info.go
  • api/v1alpha1/meta.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
  • pkg/controller/common/errors.go
  • pkg/controller/common/utils.go
  • pkg/controller/common/validation_helpers_duplication.go
  • pkg/controller/crd_annotator/controller.go
  • pkg/controller/crd_annotator/controller_test.go
  • pkg/controller/external_secrets/certificate.go
  • pkg/controller/external_secrets/certificate_test.go
  • pkg/controller/external_secrets/configmap.go
  • pkg/controller/external_secrets/constants.go
  • pkg/controller/external_secrets/controller.go
  • pkg/controller/external_secrets/deployments.go
  • pkg/controller/external_secrets/deployments_test.go
  • pkg/controller/external_secrets/install_external_secrets.go
  • pkg/controller/external_secrets/install_external_secrets_test.go
  • pkg/controller/external_secrets/networkpolicy.go
  • pkg/controller/external_secrets/networkpolicy_test.go
  • pkg/controller/external_secrets/rbacs.go
  • pkg/controller/external_secrets/rbacs_test.go
  • pkg/controller/external_secrets/secret.go
  • pkg/controller/external_secrets/secret_test.go
  • pkg/controller/external_secrets/service_test.go
  • pkg/controller/external_secrets/serviceaccounts_test.go
  • pkg/controller/external_secrets/test_utils.go
  • pkg/controller/external_secrets/utils.go
  • pkg/controller/external_secrets/validatingwebhook.go
  • pkg/controller/external_secrets/validatingwebhook_test.go
  • pkg/controller/external_secrets_manager/controller.go
  • pkg/controller/external_secrets_manager/controller_test.go
  • test/apis/generator.go
  • test/apis/vars.go
  • test/e2e/e2e_test.go
💤 Files with no reviewable changes (4)
  • pkg/controller/external_secrets/secret.go
  • pkg/controller/external_secrets/rbacs.go
  • pkg/controller/external_secrets/validatingwebhook.go
  • test/e2e/e2e_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:

  • pkg/controller/external_secrets/test_utils.go
  • pkg/controller/external_secrets/configmap.go
  • pkg/controller/common/validation_helpers_duplication.go
  • api/v1alpha1/groupversion_info.go
  • pkg/controller/external_secrets/constants.go
  • pkg/controller/external_secrets/rbacs_test.go
  • api/v1alpha1/zz_generated.deepcopy.go
  • config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
  • pkg/controller/external_secrets/networkpolicy.go
  • pkg/controller/external_secrets/install_external_secrets.go
  • test/apis/generator.go
  • pkg/controller/external_secrets/networkpolicy_test.go
  • pkg/controller/external_secrets/serviceaccounts_test.go
  • pkg/controller/external_secrets/validatingwebhook_test.go
  • test/apis/vars.go
  • pkg/controller/external_secrets/install_external_secrets_test.go
  • pkg/controller/common/utils.go
  • pkg/controller/external_secrets/deployments.go
  • pkg/controller/external_secrets/controller.go
  • pkg/controller/external_secrets_manager/controller_test.go
  • pkg/controller/external_secrets/service_test.go
  • pkg/controller/external_secrets/certificate_test.go
  • pkg/controller/external_secrets/certificate.go
  • pkg/controller/crd_annotator/controller.go
  • pkg/controller/crd_annotator/controller_test.go
  • api/v1alpha1/external_secrets_manager_types.go
  • pkg/controller/external_secrets/secret_test.go
  • pkg/controller/common/errors.go
  • pkg/controller/external_secrets_manager/controller.go
  • api/v1alpha1/meta.go
  • api/v1alpha1/external_secrets_config_types.go
  • pkg/controller/external_secrets/deployments_test.go
  • pkg/controller/external_secrets/utils.go
🧬 Code graph analysis (19)
pkg/controller/external_secrets/test_utils.go (2)
pkg/controller/common/utils.go (1)
  • DecodeServiceObjBytes (130-136)
pkg/operator/assets/bindata.go (1)
  • MustAsset (1787-1794)
pkg/controller/external_secrets/rbacs_test.go (1)
api/v1alpha1/external_secrets_config_types.go (1)
  • ControllerConfig (108-138)
pkg/controller/external_secrets/networkpolicy.go (1)
api/v1alpha1/external_secrets_config_types.go (1)
  • ControllerConfig (108-138)
pkg/controller/external_secrets/install_external_secrets.go (4)
pkg/controller/common/utils.go (2)
  • IsESMSpecEmpty (494-496)
  • ObjectMetadataModified (195-197)
api/v1alpha1/external_secrets_manager_types.go (1)
  • GlobalConfig (66-76)
api/v1alpha1/external_secrets_config_types.go (1)
  • ControllerConfig (108-138)
pkg/controller/common/errors.go (1)
  • FromClientError (61-71)
pkg/controller/external_secrets/serviceaccounts_test.go (2)
api/v1alpha1/external_secrets_config_types.go (3)
  • PluginsConfig (207-211)
  • BitwardenSecretManagerProvider (141-155)
  • ControllerConfig (108-138)
api/v1alpha1/meta.go (2)
  • Mode (117-117)
  • Enabled (121-121)
pkg/controller/external_secrets/validatingwebhook_test.go (1)
api/v1alpha1/external_secrets_config_types.go (3)
  • ControllerConfig (108-138)
  • CertProvidersConfig (214-218)
  • CertManagerConfig (168-204)
pkg/controller/external_secrets/install_external_secrets_test.go (3)
pkg/controller/client/fakes/fake_ctrl_client.go (1)
  • FakeCtrlClient (12-135)
pkg/controller/commontest/utils.go (3)
  • TestExternalSecretsNamespace (22-22)
  • TestClientError (30-30)
  • TestExternalSecretsConfig (34-40)
pkg/controller/client/client.go (1)
  • CtrlClient (20-30)
pkg/controller/common/utils.go (1)
api/v1alpha1/external_secrets_config_types.go (1)
  • ControllerConfig (108-138)
pkg/controller/external_secrets/controller.go (1)
pkg/controller/client/client.go (1)
  • CtrlClient (20-30)
pkg/controller/external_secrets_manager/controller_test.go (2)
api/v1alpha1/external_secrets_manager_types.go (1)
  • Condition (113-123)
api/v1alpha1/conditions.go (2)
  • Ready (20-20)
  • Degraded (10-10)
pkg/controller/external_secrets/service_test.go (2)
api/v1alpha1/external_secrets_config_types.go (2)
  • PluginsConfig (207-211)
  • BitwardenSecretManagerProvider (141-155)
api/v1alpha1/meta.go (2)
  • Mode (117-117)
  • Enabled (121-121)
pkg/controller/external_secrets/certificate_test.go (2)
api/v1alpha1/external_secrets_config_types.go (6)
  • ApplicationConfig (91-105)
  • ControllerConfig (108-138)
  • CertProvidersConfig (214-218)
  • CertManagerConfig (168-204)
  • PluginsConfig (207-211)
  • BitwardenSecretManagerProvider (141-155)
api/v1alpha1/meta.go (3)
  • Mode (117-117)
  • Enabled (121-121)
  • ObjectReference (20-38)
pkg/controller/external_secrets/certificate.go (1)
api/v1alpha1/external_secrets_config_types.go (1)
  • ControllerConfig (108-138)
pkg/controller/crd_annotator/controller_test.go (1)
api/v1alpha1/external_secrets_config_types.go (3)
  • ControllerConfig (108-138)
  • CertProvidersConfig (214-218)
  • CertManagerConfig (168-204)
pkg/controller/external_secrets/secret_test.go (2)
api/v1alpha1/external_secrets_config_types.go (3)
  • ApplicationConfig (91-105)
  • ControllerConfig (108-138)
  • CertProvidersConfig (214-218)
api/v1alpha1/meta.go (2)
  • Mode (117-117)
  • Disabled (124-124)
pkg/controller/external_secrets_manager/controller.go (1)
api/v1alpha1/external_secrets_manager_types.go (1)
  • ControllerStatus (96-111)
api/v1alpha1/external_secrets_config_types.go (1)
api/v1alpha1/meta.go (3)
  • Mode (117-117)
  • SecretReference (41-47)
  • ObjectReference (20-38)
pkg/controller/external_secrets/deployments_test.go (2)
api/v1alpha1/external_secrets_config_types.go (4)
  • ApplicationConfig (91-105)
  • BitwardenSecretManagerProvider (141-155)
  • PluginsConfig (207-211)
  • CertManagerConfig (168-204)
api/v1alpha1/meta.go (5)
  • CommonConfigs (50-90)
  • Mode (117-117)
  • Enabled (121-121)
  • SecretReference (41-47)
  • ProxyConfig (93-114)
pkg/controller/external_secrets/utils.go (3)
api/v1alpha1/external_secrets_config_types.go (2)
  • BitwardenSecretManagerProvider (141-155)
  • ApplicationConfig (91-105)
pkg/controller/common/utils.go (1)
  • EvalMode (489-491)
api/v1alpha1/meta.go (2)
  • Mode (117-117)
  • Disabled (124-124)
🪛 YAMLlint (1.37.1)
.coderabbit.yaml

[error] 1-1: syntax error: found character '@' that cannot start any token

(syntax)

🔇 Additional comments (46)
pkg/controller/common/validation_helpers_duplication.go (1)

18-18: Comment punctuation improvements align with Go conventions.

The changes add terminal periods to comment headers, making them grammatically complete sentences per Go style guidelines. All utility functions remain correctly implemented with no behavioral changes.

Also applies to: 37-37, 53-53, 72-72, 91-91, 100-100, 117-117

pkg/controller/common/utils.go (5)

6-6: LGTM!

Good use of the standard maps package for the maps.Copy operation below.


33-39: LGTM!

Explicitly declaring the done field as atomic.Uint32 is a good practice that improves code clarity.


65-72: LGTM!

Using maps.Copy is more idiomatic and clearer than a manual loop.


499-504: LGTM!

The nil-safe checks are correctly implemented to handle the pointer-based fields in the updated type signature.


568-574: LGTM!

The Reset implementation is correct, allowing Do to call f() again after reset.

api/v1alpha1/groupversion_info.go (1)

28-32: LGTM!

Comment punctuation updates align with Go documentation standards.

pkg/controller/common/errors.go (1)

48-54: LGTM!

The refactored IsIrrecoverableError uses idiomatic errors.As pattern for error unwrapping. This is cleaner than manual type assertions and correctly handles wrapped errors.

pkg/controller/external_secrets/install_external_secrets.go (1)

34-52: LGTM!

The nil-safe pointer dereference pattern and maps.Copy usage are clean improvements that align with the pointer-based API field changes.

pkg/controller/external_secrets/configmap.go (1)

84-89: LGTM!

Clean refactor using maps.Copy from the standard library instead of manual iteration.

pkg/controller/external_secrets/controller.go (1)

84-95: LGTM!

Comment punctuation and formatting improvements.

pkg/controller/external_secrets/certificate.go (1)

101-128: LGTM!

The nil-safe access pattern for nested configuration and ptr.Deref usage for optional IssuerRef fields are well-implemented. The fallback logic correctly applies defaults when values are nil or empty.

pkg/controller/external_secrets/constants.go (1)

55-78: LGTM!

The comment punctuation improvements enhance documentation consistency without affecting functionality.

pkg/controller/crd_annotator/controller.go (1)

249-250: LGTM!

The change from fmt.Sprintf with a pre-sized buffer to fmt.Appendf with a nil buffer is functionally equivalent and aligns with Go idioms for string formatting.

pkg/controller/external_secrets/networkpolicy.go (1)

80-92: LGTM!

The nil guards and pointer dereference correctly implement nil-safe access for the pointer-based NetworkPolicies field, aligning with the API's pointer-based optionality pattern.

test/apis/vars.go (1)

142-142: LGTM!

The change from *interface{} to *any is a stylistic improvement using the Go 1.18+ type alias, with no functional impact.

config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml (1)

1166-1167: LGTM!

The description text changes improve consistency by using lowercase for field descriptions in the CRD schema. No functional changes to the CRD structure.

Also applies to: 1214-1226, 1541-1547, 1570-1571

pkg/controller/external_secrets/validatingwebhook_test.go (1)

10-10: LGTM!

The test correctly updates to use pointer-based fields (ControllerConfig as *ControllerConfig and InjectAnnotations as *string) with proper use of ptr.To helper, aligning with the API's pointer-based optionality pattern.

Also applies to: 123-129

pkg/controller/external_secrets/secret_test.go (1)

40-43: LGTM!

The test updates correctly reflect the pointer-based API changes for ApplicationConfig and ControllerConfig fields in ExternalSecretsConfigSpec.

Also applies to: 51-54, 62-67, 214-222

pkg/controller/external_secrets/service_test.go (1)

9-9: LGTM!

The test correctly updates to use pointer-based fields (Plugins as *PluginsConfig and Mode as *Mode) with proper use of ptr.To helper, aligning with the API's pointer-based optionality pattern.

Also applies to: 62-67

pkg/controller/external_secrets/rbacs_test.go (1)

34-42: LGTM!

The test updates correctly adapt to the pointer-based ControllerConfig field change in the API. The use of &operatorv1alpha1.ControllerConfig{} properly initializes the pointer field.

Also applies to: 268-278, 282-293

pkg/controller/external_secrets_manager/controller.go (2)

184-196: LGTM!

The pointer handling for ControllerStatus.Name is correct. Using ptr.Deref for nil-safe comparison and storing &controllerName properly handles the pointer-based API. Since controllerName is a function parameter (passed by value), taking its address and appending the struct to the slice is safe.


198-227: LGTM!

The updateStatusCondition function correctly handles pointer-based Condition.Type field. The use of ptr.Deref(c.Type, "") provides nil-safe comparison, and &updCondition.Type correctly stores the type as a pointer.

pkg/controller/external_secrets/utils.go (3)

91-101: LGTM!

The nil-safety checks are properly ordered from outer to inner structures. The use of ptr.Deref with operatorv1alpha1.Disabled as default in isBitwardenConfigEnabled correctly handles the optional Mode field.


103-124: LGTM!

The getLogLevel and getOperatingNamespace functions properly handle the pointer-based configuration fields with appropriate nil checks before dereferencing.


131-159: LGTM!

The proxy configuration handling correctly implements the precedence order (ESC > ESM > OLM env vars) with proper nil checks. The pointer assignments for OLM environment variable fallback are correct.

test/apis/generator.go (1)

160-187: LGTM!

The changes appropriately modernize the codebase:

  • []interface{}[]any aligns with Go 1.18+ type alias
  • fmt.Appendf(nil, ...) is more efficient than []byte(fmt.Sprintf(...)) as it avoids intermediate string allocation

Also applies to: 219-344

api/v1alpha1/zz_generated.deepcopy.go (1)

1-668: LGTM!

This is auto-generated code by controller-gen. The deepcopy implementations correctly handle the new pointer-based fields with appropriate nil checks and proper deep copy patterns for nested structures.

pkg/controller/crd_annotator/controller_test.go (2)

32-43: LGTM!

The test helper correctly adapts to the pointer-based ControllerConfig field and uses ptr.To("true") for the InjectAnnotations string pointer field.


420-435: LGTM!

Using r.Get instead of r.CtrlClient.Get is appropriate since the Reconciler struct embeds CtrlClient, making Get directly accessible on the reconciler.

pkg/controller/external_secrets/deployments_test.go (4)

140-213: LGTM!

The test correctly adapts to the pointer-based ApplicationConfig field. The nested pointer fields (Tolerations as *[]corev1.Toleration, NodeSelector as *map[string]string) are properly initialized.


356-391: LGTM!

The test cases for invalid configurations correctly use the pointer-based struct initialization pattern with &v1alpha1.ApplicationConfig{} and properly initialize the embedded CommonConfigs with pointer-to-slice/map fields.


516-536: LGTM!

The Bitwarden configuration test correctly handles the conditional nil-safe initialization of Plugins and ControllerConfig with proper pointer assignments. Using ptr.To(v1alpha1.Enabled) for the Mode field aligns with the API change to *Mode.


660-728: LGTM!

The proxy configuration tests correctly use ptr.To() for string pointer fields (HTTPProxy, HTTPSProxy, NoProxy) in the ProxyConfig struct, properly testing the precedence logic.

pkg/controller/external_secrets/deployments.go (3)

1-159: LGTM on nil-safety patterns and maps.Copy usage.

The nil-safe checks for ApplicationConfig and nested fields are correctly implemented, and using maps.Copy is idiomatic Go 1.21+ for efficiently copying map entries.


181-273: Nil-safety patterns for resource configuration look correct.

The pointer dereference patterns for NodeSelector and Tolerations (lines 214, 216, 258, 260) correctly handle the new *map[string]string and *[]corev1.Toleration types.


482-518: Proxy configuration nil-safety is well implemented.

The guard clause at line 483 correctly short-circuits when proxyConfig is nil or when all proxy fields are nil. The ptr.Deref usage provides safe dereferencing with empty string defaults.

pkg/controller/external_secrets/networkpolicy_test.go (2)

82-90: Test configuration correctly uses pointer types.

The test properly initializes Plugins as a pointer and uses ptr.To(operatorv1alpha1.Enabled) for the Mode field, aligning with the API type changes.


243-262: Network policy test configuration is properly updated.

The NetworkPolicies field is correctly initialized as *[]operatorv1alpha1.NetworkPolicy, and intstr.FromInt32(443) is the appropriate function for explicit int32 port values.

pkg/controller/external_secrets/serviceaccounts_test.go (1)

75-108: LGTM on service account test updates.

Test configurations properly use pointer types for Plugins and ControllerConfig, consistent with the API type changes.

pkg/controller/external_secrets/install_external_secrets_test.go (1)

16-254: Comprehensive test coverage for namespace handling.

The test suite thoroughly covers namespace creation, update scenarios (label changes, label preservation, label override), and error paths. The use of wantCreate and wantUpdate flags with call count verification is a good pattern.

pkg/controller/external_secrets/certificate_test.go (1)

470-488: Test helper properly constructs pointer-based configuration.

The testExternalSecretsConfigForCertificate helper correctly initializes all pointer fields (ControllerConfig, ApplicationConfig, Plugins) and uses ptr.To for the OperatingNamespace string pointer.

api/v1alpha1/external_secrets_config_types.go (2)

64-74: LGTM on pointer-based optional fields.

The conversion of ApplicationConfig, Plugins, and ControllerConfig to pointer types with +optional annotations correctly implements optional semantics for the CRD spec.


251-255: Verify: +required with omitempty on Egress slice.

The Egress field is marked +required but has omitempty. For slices, this may be intentional if an empty slice [] is considered valid for "required". However, verify this aligns with the intended validation behavior—omitempty will omit the field entirely when empty rather than serializing as [].

api/v1alpha1/meta.go (2)

50-90: LGTM on CommonConfigs pointer-based fields.

The conversion to pointer types for optional configuration fields (LogLevel, Tolerations, NodeSelector) properly enables distinguishing between "not set" (nil) and "set to zero/empty value".


92-114: ProxyConfig pointer fields are correctly implemented.

Converting HTTPProxy, HTTPSProxy, and NoProxy to *string with +optional allows proper nil-checking in the controller code (as seen in deployments.go).

@@ -0,0 +1 @@
@coderabbitai When a comment "@coderabbitai /nitpicks" is added on PR, please consolidate all your unresolved nitpick suggestions from this PR into a single comment which is in git diff format, which author can easily apply using `git apply` command in the same PR or in a follow up PR.
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

Invalid YAML syntax - file will not be parsed.

The content is plain text starting with @, which is not valid YAML. YAML configuration files must be structured documents. This directive will be ignored by CodeRabbit.

If you want to add custom instructions, use the proper YAML structure:

🔎 Example valid .coderabbit.yaml structure
# Example: To customize review behavior
reviews:
  profile: "chill"
  path_instructions:
    - path: "**"
      instructions: "Focus on major issues impacting performance, readability, maintainability and security."

If this directive is meant as a one-time comment instruction rather than a permanent configuration, consider removing this file and using a PR comment instead.

🧰 Tools
🪛 YAMLlint (1.37.1)

[error] 1-1: syntax error: found character '@' that cannot start any token

(syntax)

🤖 Prompt for AI Agents
.coderabbit.yaml around lines 1 to 1: the file currently contains a plain text
directive starting with "@" which is invalid YAML and will cause the config to
be ignored; replace this line with a valid YAML mapping (or remove the file if
you only intended a one‑time PR comment). To fix, convert the directive into a
proper YAML structure such as a top‑level "reviews:" mapping with keys like
"profile" and "path_instructions" or move the instruction into a PR comment;
ensure strings are quoted where needed and the file is syntactically valid YAML
so the tool can parse it.

Comment on lines 236 to +244
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +kubebuilder:validation:Required
Name string `json:"name"`
// +required
Name string `json:"name,omitempty"`

// componentName specifies which external-secrets component this network policy applies to.
// +kubebuilder:validation:Enum:=ExternalSecretsCoreController;BitwardenSDKServer
// +kubebuilder:validation:Required
ComponentName ComponentName `json:"componentName"`
// +required
ComponentName ComponentName `json:"componentName,omitempty"`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent annotation: +required with omitempty on NetworkPolicy fields.

Both Name (line 239) and ComponentName (line 244) are marked +required but have json:"...,omitempty" tags. For truly required fields, the omitempty tag should be removed to ensure the fields are always serialized and validated as present.

🔎 Suggested fix
 	// +kubebuilder:validation:MaxLength:=253
 	// +required
-	Name string `json:"name,omitempty"`
+	Name string `json:"name"`

 	// componentName specifies which external-secrets component this network policy applies to.
 	// +kubebuilder:validation:Enum:=ExternalSecretsCoreController;BitwardenSDKServer
 	// +required
-	ComponentName ComponentName `json:"componentName,omitempty"`
+	ComponentName ComponentName `json:"componentName"`
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +kubebuilder:validation:Required
Name string `json:"name"`
// +required
Name string `json:"name,omitempty"`
// componentName specifies which external-secrets component this network policy applies to.
// +kubebuilder:validation:Enum:=ExternalSecretsCoreController;BitwardenSDKServer
// +kubebuilder:validation:Required
ComponentName ComponentName `json:"componentName"`
// +required
ComponentName ComponentName `json:"componentName,omitempty"`
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +required
Name string `json:"name"`
// componentName specifies which external-secrets component this network policy applies to.
// +kubebuilder:validation:Enum:=ExternalSecretsCoreController;BitwardenSDKServer
// +required
ComponentName ComponentName `json:"componentName"`
🤖 Prompt for AI Agents
In api/v1alpha1/external_secrets_config_types.go around lines 236 to 244, the
struct fields Name and ComponentName are annotated with +required but their json
tags include ,omitempty which prevents required fields from being
serialized/validated; to fix, remove the ,omitempty from the json struct tags
for both Name and ComponentName so they become json:"name" and
json:"componentName" (or equivalent without omitempty), keeping the kubebuilder
validation tags intact so the fields are always present and validated.

Comment on lines 96 to +99
type ControllerStatus struct {
// name of the controller for which the observed condition is recorded.
// +kubebuilder:validation:Required
Name string `json:"name"`
// +required
Name *string `json:"name,omitempty"`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Inconsistent annotation: +required with pointer and omitempty.

The Name field is marked +required but uses a pointer type with omitempty. This is semantically contradictory—a required field should not be nullable/omittable. Consider either:

  • Keep +required and change to Name string (non-pointer, no omitempty)
  • Keep the pointer with omitempty and change to +optional
🤖 Prompt for AI Agents
In api/v1alpha1/external_secrets_manager_types.go around lines 96 to 99, the
ControllerStatus.Name field is annotated `+required` but declared as a pointer
with `json:"name,omitempty"`, which is contradictory; change the declaration to
a non-pointer string and remove `omitempty` (e.g., Name string `json:"name"`) so
the field is truly required, and keep the `+required` annotation; alternatively,
if you intend the field to be optional, change the annotation to `+optional` and
keep the pointer+omitempty — pick one and make that consistent.

Comment on lines 113 to +116
type Condition struct {
// type of the condition
// +kubebuilder:validation:Required
Type string `json:"type"`
// +required
Type *string `json:"type,omitempty"`
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same inconsistency: +required with pointer and omitempty on Type field.

The Type field has the same conflicting pattern as Name. A +required field should not use a pointer type with omitempty tag.

🤖 Prompt for AI Agents
In api/v1alpha1/external_secrets_manager_types.go around lines 113 to 116, the
Condition.Type field is marked `+required` but is defined as a pointer with
`omitempty`, which is inconsistent; change the field to a non-pointer string and
remove `omitempty` from the JSON tag (e.g., Type string `json:"type"`), ensuring
the required field is a plain string and the tag reflects it.

Comment on lines 19 to 38
// ObjectReference is a reference to an object with a given name, kind and group.
type ObjectReference struct {
// Name of the resource being referred to.
// name of the resource being referred to.
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +kubebuilder:validation:Required
Name string `json:"name"`
// +required
Name string `json:"name,omitempty"`

// Kind of the resource being referred to.
// kind of the resource being referred to.
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +kubebuilder:validation:Optional
Kind string `json:"kind,omitempty"`
// +optional
Kind *string `json:"kind,omitempty"`

// Group of the resource being referred to.
// group of the resource being referred to.
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +kubebuilder:validation:Optional
Group string `json:"group,omitempty"`
// +optional
Group *string `json:"group,omitempty"`
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

ObjectReference field changes look correct except for Name annotation.

The conversion of Kind and Group to pointer types with +optional is correct. However, Name (line 25) has +required with omitempty, which is inconsistent—a required field should typically not have omitempty.

🤖 Prompt for AI Agents
In api/v1alpha1/meta.go around lines 19 to 38, the Name field is marked
+required but its struct tag uses `json:"name,omitempty"`, which is
inconsistent; remove the `omitempty` (or alternatively mark Name as +optional)
so the JSON tag matches the kubebuilder requirement—update the Name tag to
`json:"name"` and keep the existing validation annotations to enforce presence
and length.

Comment on lines 40 to 47
// SecretReference is a reference to the secret with the given name, which should exist in the same namespace where it will be utilized.
type SecretReference struct {
// Name of the secret resource being referred to.
// name of the secret resource being referred to.
// +kubebuilder:validation:MinLength:=1
// +kubebuilder:validation:MaxLength:=253
// +kubebuilder:validation:Required
Name string `json:"name"`
// +required
Name string `json:"name,omitempty"`
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟡 Minor

Same pattern issue on SecretReference.Name.

The Name field has +required but uses omitempty tag. For consistency, consider removing omitempty from required fields.

🤖 Prompt for AI Agents
In api/v1alpha1/meta.go around lines 40 to 47, the SecretReference.Name field is
marked with +required but its struct tag uses `json:"name,omitempty"`, which
contradicts the required annotation; update the struct tag to remove `omitempty`
so the JSON tag is `json:"name"` (keeping validation kubebuilder comments
intact) to ensure required fields are not omitted during marshaling/validation.

Comment on lines +67 to 68

ctx context.Context
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

cat -n pkg/controller/crd_annotator/controller.go | sed -n '50,120p'

Repository: openshift/external-secrets-operator

Length of output: 3002


🏁 Script executed:

# Check how context is used in other reconciler implementations
rg -n -C3 'func \(r \*Reconciler\) Reconcile\(ctx context\.Context' --type=go

Repository: openshift/external-secrets-operator

Length of output: 2186


🏁 Script executed:

# Also check the specific file for the context field definition and usage
rg -n 'ctx.*context\.' pkg/controller/crd_annotator/controller.go | head -20

Repository: openshift/external-secrets-operator

Length of output: 430


🏁 Script executed:

cat -n pkg/controller/crd_annotator/controller.go | sed -n '189,220p'

Repository: openshift/external-secrets-operator

Length of output: 1695


🏁 Script executed:

cat -n pkg/controller/crd_annotator/controller.go | sed -n '240,280p'

Repository: openshift/external-secrets-operator

Length of output: 1735


🏁 Script executed:

cat -n pkg/controller/crd_annotator/controller.go | sed -n '298,320p'

Repository: openshift/external-secrets-operator

Length of output: 1254


Fix context propagation in reconciliation methods.

The struct-level ctx initialized with context.Background() (line 85) is used in updateAnnotationsInAllCRDs (line 264) and updateAnnotations (line 252) instead of the per-request context. Additionally, updateStatus is called with r.ctx at line 298. This bypasses the per-request context's timeout and cancellation semantics, preventing proper request scoping.

The Reconcile method receives the per-request context but processReconcileRequest (line 215) has no parameter to accept and propagate it. Pass the per-request context through the call chain: modify processReconcileRequest to accept ctx context.Context as a parameter, update all callers to pass it, and use it in updateAnnotationsInAllCRDs and updateAnnotations instead of the struct-level background context.

Comment on lines +131 to 145
if exist {
// Merge labels: preserve existing, overlay with desired resourceLabels
desired.Labels = make(map[string]string)
maps.Copy(desired.Labels, fetched.Labels)
maps.Copy(desired.Labels, resourceLabels)

if common.ObjectMetadataModified(desired, fetched) {
if err := r.UpdateWithRetry(r.ctx, desired); err != nil {
return common.FromClientError(err, "failed to update namespace %s", namespace)
}
}
} else {
if err := r.Create(r.ctx, desired); err != nil {
return common.FromClientError(err, "failed to create namespace %s", namespace)
}
Copy link

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Missing ResourceVersion will cause update failures.

When updating an existing namespace, desired lacks the ResourceVersion from fetched. Kubernetes API requires ResourceVersion for updates to handle optimistic concurrency.

🔎 Proposed fix
 	if exist {
 		// Merge labels: preserve existing, overlay with desired resourceLabels
 		desired.Labels = make(map[string]string)
 		maps.Copy(desired.Labels, fetched.Labels)
 		maps.Copy(desired.Labels, resourceLabels)
+		desired.ResourceVersion = fetched.ResourceVersion
 
 		if common.ObjectMetadataModified(desired, fetched) {
 			if err := r.UpdateWithRetry(r.ctx, desired); err != nil {
 				return common.FromClientError(err, "failed to update namespace %s", namespace)
 			}
 		}

Alternatively, update fetched.Labels directly and pass fetched to UpdateWithRetry:

 	if exist {
-		// Merge labels: preserve existing, overlay with desired resourceLabels
-		desired.Labels = make(map[string]string)
-		maps.Copy(desired.Labels, fetched.Labels)
-		maps.Copy(desired.Labels, resourceLabels)
-
-		if common.ObjectMetadataModified(desired, fetched) {
-			if err := r.UpdateWithRetry(r.ctx, desired); err != nil {
+		// Merge resourceLabels into fetched labels
+		if fetched.Labels == nil {
+			fetched.Labels = make(map[string]string)
+		}
+		maps.Copy(fetched.Labels, resourceLabels)
+
+		if common.ObjectMetadataModified(desired, fetched) {
+			if err := r.UpdateWithRetry(r.ctx, fetched); err != nil {
 				return common.FromClientError(err, "failed to update namespace %s", namespace)
 			}
 		}
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
if exist {
// Merge labels: preserve existing, overlay with desired resourceLabels
desired.Labels = make(map[string]string)
maps.Copy(desired.Labels, fetched.Labels)
maps.Copy(desired.Labels, resourceLabels)
if common.ObjectMetadataModified(desired, fetched) {
if err := r.UpdateWithRetry(r.ctx, desired); err != nil {
return common.FromClientError(err, "failed to update namespace %s", namespace)
}
}
} else {
if err := r.Create(r.ctx, desired); err != nil {
return common.FromClientError(err, "failed to create namespace %s", namespace)
}
if exist {
// Merge labels: preserve existing, overlay with desired resourceLabels
desired.Labels = make(map[string]string)
maps.Copy(desired.Labels, fetched.Labels)
maps.Copy(desired.Labels, resourceLabels)
desired.ResourceVersion = fetched.ResourceVersion
if common.ObjectMetadataModified(desired, fetched) {
if err := r.UpdateWithRetry(r.ctx, desired); err != nil {
return common.FromClientError(err, "failed to update namespace %s", namespace)
}
}
} else {
if err := r.Create(r.ctx, desired); err != nil {
return common.FromClientError(err, "failed to create namespace %s", namespace)
}
🤖 Prompt for AI Agents
In pkg/controller/external_secrets/install_external_secrets.go around lines 131
to 145, the code copies fetched.Labels into a new desired object but does not
preserve fetched.ResourceVersion, causing Kubernetes update calls to fail; fix
by preserving the ResourceVersion before calling UpdateWithRetry (e.g., set
desired.ResourceVersion = fetched.ResourceVersion) or instead modify
fetched.Labels in-place (merge resourceLabels into fetched.Labels) and call
UpdateWithRetry with fetched so the ResourceVersion is retained.

@openshift-ci
Copy link

openshift-ci bot commented Dec 24, 2025

@bharath-b-rh: The following test failed, say /retest to rerun all failed tests or /retest-required to rerun all mandatory failed tests:

Test name Commit Details Required Rerun command
ci/prow/e2e-operator 41730e0 link true /test e2e-operator

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

approved Indicates a PR has been approved by an approver from all required OWNERS files. 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.

2 participants