Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 25 additions & 0 deletions api/v1alpha1/external_secrets_config_types.go
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ import (
corev1 "k8s.io/api/core/v1"
networkingv1 "k8s.io/api/networking/v1"
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
)

func init() {
Expand Down Expand Up @@ -151,6 +152,20 @@ type ControllerConfig struct {
// +listMapKey=componentName
NetworkPolicies []NetworkPolicy `json:"networkPolicies,omitempty"`

// concurrent sets the core controller --concurrent flag (max concurrent reconciles).
// When omitted, defaults to 1 for backward compatibility.
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=100
// +optional
Concurrent *int32 `json:"concurrent,omitempty"`

// replicas sets the desired replica count for the external-secrets core controller Deployment.
// When omitted, defaults to 1. When greater than 1, leader election keeps a single active reconciler.
// +kubebuilder:validation:Minimum=1
// +kubebuilder:validation:Maximum=10
// +optional
Replicas *int32 `json:"replicas,omitempty"`
Comment on lines +155 to +167

Copy link
Copy Markdown

Choose a reason for hiding this comment

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

🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash
set -u

# Locate Go files that consume ControllerConfig or construct controller arguments.
fd -e go . | while IFS= read -r file; do
  if rg -q '\bControllerConfig\b|\.Concurrent\b|\.Replicas\b|--concurrent' "$file"; then
    ast-grep outline "$file" --items all
    rg -n -C 5 '\bControllerConfig\b|\.Concurrent\b|\.Replicas\b|--concurrent|replicas:' "$file"
  fi
done

Repository: openshift/external-secrets-operator

Length of output: 50392


🏁 Script executed:

#!/bin/bash
set -u

# Restrict the search to tracked, non-vendored source and test files.
git ls-files '*.go' ':!:vendor/**' \
  | xargs -r rg -n -C 6 'ControllerConfig|\.Concurrent|\.Replicas|--concurrent|ExternalSecretsConfig' \
  | head -n 1200

Repository: openshift/external-secrets-operator

Length of output: 50391


🏁 Script executed:

#!/bin/bash
set -u

# Find the renderer and its focused tests without generated assets or vendor code.
for file in $(git ls-files '*.go' ':!:vendor/**' ':!:pkg/operator/assets/**'); do
  if rg -q 'ControllerConfig|\.Concurrent|\.Replicas|--concurrent' "$file"; then
    echo "===== $file ====="
    rg -n -C 12 'ControllerConfig|\.Concurrent|\.Replicas|--concurrent' "$file"
  fi
done

Repository: openshift/external-secrets-operator

Length of output: 50392


🏁 Script executed:

#!/bin/bash
set -u

echo '===== pkg/controller/external_secrets/deployments.go: deployment construction ====='
sed -n '1,430p' pkg/controller/external_secrets/deployments.go

echo '===== replica and concurrency assignments in source/tests ====='
rg -n -C 8 'Spec\.Replicas|Replicas:|--concurrent|updateContainerSpec|createOrApplyDeployment|CreateOrApplyDeployment' \
  pkg/controller/external_secrets api pkg/operator \
  -g '*.go' -g '!assets/**' | head -n 1200

Repository: openshift/external-secrets-operator

Length of output: 38149


🏁 Script executed:

#!/bin/bash
set -u

# Check the embedded core-controller Deployment template for its baseline replica count.
rg -n -C 12 'name: external-secrets$|kind: Deployment|replicas:' \
  pkg/operator/assets/bindata.go | head -n 500

Repository: openshift/external-secrets-operator

Length of output: 18410


Wire ControllerConfig.Replicas and ControllerConfig.Concurrent into the core controller Deployment. The renderer hard-codes --concurrent=1 and the embedded Deployment has replicas: 1, so configured values are ignored. Retain 1 when either field is omitted.

🤖 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 `@api/v1alpha1/external_secrets_config_types.go` around lines 155 - 167, Update
the core controller Deployment rendering to use ControllerConfig.Replicas for
the Deployment replica count and ControllerConfig.Concurrent for the
--concurrent argument, falling back to 1 when either pointer is nil. Replace the
hard-coded values in the renderer and embedded Deployment while preserving the
existing configuration flow.


// componentConfigs allows specifying deployment-level configuration overrides for individual external-secrets components. This field enables fine-grained control over deployment settings for each component independently.
// Each component can only have one configuration entry.
// +kubebuilder:validation:MinItems:=0
Expand Down Expand Up @@ -191,6 +206,16 @@ type ComponentConfig struct {
// +listMapKey=name
// +optional
OverrideEnv []corev1.EnvVar `json:"overrideEnv,omitempty"`

// experimentalOverrides is an escape hatch: a strategic merge patch applied to this
// component's Deployment.spec after first-class fields are rendered. Intended for scheduling
// fields (affinity, tolerations, nodeSelector, topologySpreadConstraints). Patches that touch
// operator-owned nested lists — containers, initContainers, ephemeralContainers, volumes, or
// volumeMounts/volumeDevices — are rejected and cause Degraded. Invalid or unusable patch data
// also causes Degraded. Prefer first-class fields (concurrent, replicas, revisionHistoryLimit,
// overrideEnv, trustedCABundle) when available.
// +optional
ExperimentalOverrides *runtime.RawExtension `json:"experimentalOverrides,omitempty"`
}

// DeploymentConfig defines configuration overrides for a Kubernetes Deployment resource.
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1385,6 +1385,126 @@ tests:
overrideEnv:
- name: SHARED_VAR
value: "webhook-value"
- name: Should allow concurrent and replicas within valid bounds
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 20
replicas: 2
expected: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 20
replicas: 2
- name: Should allow concurrent at maximum of 100
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 100
expected: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 100
- name: Should allow replicas at maximum of 10
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
replicas: 10
expected: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
replicas: 10
- name: Should fail with concurrent less than 1
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 0
expectedError: "ExternalSecretsConfig.operator.openshift.io \"cluster\" is invalid: spec.controllerConfig.concurrent: Invalid value: 0: spec.controllerConfig.concurrent in body should be greater than or equal to 1"
- name: Should fail with concurrent exceeding maximum of 100
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 101
expectedError: "ExternalSecretsConfig.operator.openshift.io \"cluster\" is invalid: spec.controllerConfig.concurrent: Invalid value: 101: spec.controllerConfig.concurrent in body should be less than or equal to 100"
- name: Should fail with replicas less than 1
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
replicas: 0
expectedError: "ExternalSecretsConfig.operator.openshift.io \"cluster\" is invalid: spec.controllerConfig.replicas: Invalid value: 0: spec.controllerConfig.replicas in body should be greater than or equal to 1"
- name: Should fail with replicas exceeding maximum of 10
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
replicas: 11
expectedError: "ExternalSecretsConfig.operator.openshift.io \"cluster\" is invalid: spec.controllerConfig.replicas: Invalid value: 11: spec.controllerConfig.replicas in body should be less than or equal to 10"
- name: Should allow experimentalOverrides on a componentConfig
resourceName: cluster
initial: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 20
replicas: 2
componentConfigs:
- componentName: ExternalSecretsCoreController
experimentalOverrides:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: external-secrets
topologyKey: kubernetes.io/hostname
expected: |
apiVersion: operator.openshift.io/v1alpha1
kind: ExternalSecretsConfig
spec:
controllerConfig:
concurrent: 20
replicas: 2
componentConfigs:
- componentName: ExternalSecretsCoreController
experimentalOverrides:
template:
spec:
affinity:
podAntiAffinity:
requiredDuringSchedulingIgnoredDuringExecution:
- labelSelector:
matchLabels:
app.kubernetes.io/name: external-secrets
topologyKey: kubernetes.io/hostname
- name: Should allow networkPolicy with valid componentName ExternalSecretsCoreController
resourceName: cluster
initial: |
Expand Down
17 changes: 16 additions & 1 deletion api/v1alpha1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

27 changes: 27 additions & 0 deletions bundle/manifests/operator.openshift.io_externalsecretsconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,17 @@ spec:
minimum: 1
type: integer
type: object
experimentalOverrides:
description: |-
experimentalOverrides is an escape hatch: a strategic merge patch applied to this
component's Deployment.spec after first-class fields are rendered. Intended for scheduling
fields (affinity, tolerations, nodeSelector, topologySpreadConstraints). Patches that touch
operator-owned nested lists — containers, initContainers, ephemeralContainers, volumes, or
volumeMounts/volumeDevices — are rejected and cause Degraded. Invalid or unusable patch data
also causes Degraded. Prefer first-class fields (concurrent, replicas, revisionHistoryLimit,
overrideEnv, trustedCABundle) when available.
type: object
x-kubernetes-preserve-unknown-fields: true
overrideEnv:
description: |-
overrideEnv specifies custom environment variables for this component's container. These are merged with operator-managed environment variables, with user-defined values taking precedence.
Expand Down Expand Up @@ -1511,6 +1522,14 @@ spec:
x-kubernetes-list-map-keys:
- componentName
x-kubernetes-list-type: map
concurrent:
description: |-
concurrent sets the core controller --concurrent flag (max concurrent reconciles).
When omitted, defaults to 1 for backward compatibility.
format: int32
maximum: 100
minimum: 1
type: integer
labels:
additionalProperties:
type: string
Expand Down Expand Up @@ -1768,6 +1787,14 @@ spec:
immutable
rule: oldSelf.all(op, self.exists(p, p.name == op.name && p.componentName
== op.componentName))
replicas:
description: |-
replicas sets the desired replica count for the external-secrets core controller Deployment.
When omitted, defaults to 1. When greater than 1, leader election keeps a single active reconciler.
format: int32
maximum: 10
minimum: 1
type: integer
trustedCABundle:
description: |-
trustedCABundle references a ConfigMap containing PEM-encoded CA certificates for the external-secrets core controller to trust when making outbound TLS connections.
Expand Down
27 changes: 27 additions & 0 deletions config/crd/bases/operator.openshift.io_externalsecretsconfigs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -1330,6 +1330,17 @@ spec:
minimum: 1
type: integer
type: object
experimentalOverrides:
description: |-
experimentalOverrides is an escape hatch: a strategic merge patch applied to this
component's Deployment.spec after first-class fields are rendered. Intended for scheduling
fields (affinity, tolerations, nodeSelector, topologySpreadConstraints). Patches that touch
operator-owned nested lists — containers, initContainers, ephemeralContainers, volumes, or
volumeMounts/volumeDevices — are rejected and cause Degraded. Invalid or unusable patch data
also causes Degraded. Prefer first-class fields (concurrent, replicas, revisionHistoryLimit,
overrideEnv, trustedCABundle) when available.
type: object
x-kubernetes-preserve-unknown-fields: true
overrideEnv:
description: |-
overrideEnv specifies custom environment variables for this component's container. These are merged with operator-managed environment variables, with user-defined values taking precedence.
Expand Down Expand Up @@ -1511,6 +1522,14 @@ spec:
x-kubernetes-list-map-keys:
- componentName
x-kubernetes-list-type: map
concurrent:
description: |-
concurrent sets the core controller --concurrent flag (max concurrent reconciles).
When omitted, defaults to 1 for backward compatibility.
format: int32
maximum: 100
minimum: 1
type: integer
labels:
additionalProperties:
type: string
Expand Down Expand Up @@ -1768,6 +1787,14 @@ spec:
immutable
rule: oldSelf.all(op, self.exists(p, p.name == op.name && p.componentName
== op.componentName))
replicas:
description: |-
replicas sets the desired replica count for the external-secrets core controller Deployment.
When omitted, defaults to 1. When greater than 1, leader election keeps a single active reconciler.
format: int32
maximum: 10
minimum: 1
type: integer
trustedCABundle:
description: |-
trustedCABundle references a ConfigMap containing PEM-encoded CA certificates for the external-secrets core controller to trust when making outbound TLS connections.
Expand Down
3 changes: 3 additions & 0 deletions docs/api_reference.md
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ _Appears in:_
| `componentName` _[ComponentName](#componentname)_ | componentName identifies which external-secrets component this configuration applies to.<br />Valid component names: ExternalSecretsCoreController, Webhook, CertController, BitwardenSDKServer. | | Enum: [ExternalSecretsCoreController Webhook CertController BitwardenSDKServer] <br /> |
| `deploymentConfigs` _[DeploymentConfig](#deploymentconfig)_ | deploymentConfigs specifies overrides for the Kubernetes Deployment resource of this component. | | |
| `overrideEnv` _[EnvVar](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#envvar-v1-core) array_ | overrideEnv specifies custom environment variables for this component's container. These are merged with operator-managed environment variables, with user-defined values taking precedence.<br />Names starting with 'KUBERNETES_' or 'EXTERNAL_SECRETS_' are reserved prefixes and will be rejected.<br />The exact names 'HOSTNAME', 'SSL_CERT_DIR', and 'SSL_CERT_FILE' are also reserved. | | MaxItems: 50 <br /> |
| `experimentalOverrides` _[RawExtension](https://kubernetes.io/docs/reference/generated/kubernetes-api/v1.32/#rawextension-runtime-pkg)_ | experimentalOverrides is an escape hatch: a strategic merge patch applied to this<br />component's Deployment.spec after first-class fields are rendered. Intended for scheduling<br />fields (affinity, tolerations, nodeSelector, topologySpreadConstraints). Patches that touch<br />operator-owned nested lists — containers, initContainers, ephemeralContainers, volumes, or<br />volumeMounts/volumeDevices — are rejected and cause Degraded. Invalid or unusable patch data<br />also causes Degraded. Prefer first-class fields (concurrent, replicas, revisionHistoryLimit,<br />overrideEnv, trustedCABundle) when available. | | |


#### ComponentName
Expand Down Expand Up @@ -220,6 +221,8 @@ _Appears in:_
| `labels` _object (keys:string, values:string)_ | labels to apply to all resources created for the external-secrets operand deployment.<br />This field can have a maximum of 20 entries. | | MaxProperties: 20 <br />MinProperties: 0 <br /> |
| `annotations` _object (keys:string, values:string)_ | annotations are for adding custom annotations to all the resources created for external-secrets deployment.<br />The annotations are merged with any default annotations set by the operator. User-specified annotations take precedence over defaults in case of conflicts.<br />Annotation keys containing domains `kubernetes.io/`, `openshift.io/`, `cert-manager.io/` or `k8s.io/` (including subdomains like `*.kubernetes.io/`) are not allowed. | | MaxProperties: 20 <br />MinProperties: 0 <br /> |
| `networkPolicies` _[NetworkPolicy](#networkpolicy) array_ | networkPolicies specifies the list of network policy configurations<br />to be applied to external-secrets pods.<br />Each entry allows specifying a name for the generated NetworkPolicy object,<br />along with its full Kubernetes NetworkPolicy definition.<br />The operator prepends "eso-user-" to the provided name when creating the Kubernetes object.<br />If this field is not provided, external-secrets components will be isolated<br />with deny-all network policies, which will prevent proper operation. | | MaxItems: 50 <br />MinItems: 0 <br /> |
| `concurrent` _integer_ | concurrent sets the core controller --concurrent flag (max concurrent reconciles).<br />When omitted, defaults to 1 for backward compatibility. | | Maximum: 100 <br />Minimum: 1 <br /> |
| `replicas` _integer_ | replicas sets the desired replica count for the external-secrets core controller Deployment.<br />When omitted, defaults to 1. When greater than 1, leader election keeps a single active reconciler. | | Maximum: 10 <br />Minimum: 1 <br /> |
| `componentConfigs` _[ComponentConfig](#componentconfig) array_ | componentConfigs allows specifying deployment-level configuration overrides for individual external-secrets components. This field enables fine-grained control over deployment settings for each component independently.<br />Each component can only have one configuration entry. | | MaxItems: 4 <br />MinItems: 0 <br /> |
| `trustedCABundle` _[ConfigMapKeyReference](#configmapkeyreference)_ | trustedCABundle references a ConfigMap containing PEM-encoded CA certificates for the external-secrets core controller to trust when making outbound TLS connections.<br />If specified, this bundle is used for all outbound TLS traffic, including connections to external secret management systems and configured proxies.<br />The ConfigMap must exist in the external-secrets operand namespace and must not carry the CNO inject-trusted-cabundle label when proxy is configured.<br />When omitted, external providers use standard system certificates. When proxy is configured, proxy TLS connections use the operator-managed<br />OpenShift trusted CA bundle injected by the Cluster Network Operator. | | |

Expand Down