Browse Source

feat: add selectable fields to the CRDs (#5226)

* feat: add selectable fields to the CRDs

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

On-behalf-of: Gergely Brautigam <gergely.brautigam@sap.com>

* upgrade the test cluster version

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

On-behalf-of: Gergely Brautigam <gergely.brautigam@sap.com>

* bump kind version to run the latest cluster

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>

---------

Signed-off-by: Gergely Brautigam <182850+Skarlso@users.noreply.github.com>
Gergely Brautigam 7 months ago
parent
commit
9e57660ed5

+ 2 - 2
.github/workflows/e2e.yml

@@ -13,8 +13,8 @@ env:
   GO_VERSION: '1.24'
   GINKGO_VERSION: 'v2.8.0'
   DOCKER_BUILDX_VERSION: 'v0.4.2'
-  KIND_VERSION: 'v0.17.0'
-  KIND_IMAGE: 'kindest/node:v1.26.0'
+  KIND_VERSION: 'v0.30.0'
+  KIND_IMAGE: 'kindest/node:v1.33.4'
 
   # Common users. We can't run a step 'if secrets.GHCR_USERNAME != ""' but we can run
   # a step 'if env.GHCR_USERNAME' != ""', so we copy these to succinctly test whether

+ 4 - 0
apis/externalsecrets/v1/externalsecret_types.go

@@ -560,6 +560,10 @@ type ExternalSecretStatus struct {
 // +kubebuilder:printcolumn:name="Refresh Interval",type=string,JSONPath=`.spec.refreshInterval`
 // +kubebuilder:printcolumn:name="Status",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].reason`
 // +kubebuilder:printcolumn:name="Ready",type=string,JSONPath=`.status.conditions[?(@.type=="Ready")].status`
+// +kubebuilder:selectablefield:JSONPath=`.spec.secretStoreRef.name`
+// +kubebuilder:selectablefield:JSONPath=`.spec.secretStoreRef.kind`
+// +kubebuilder:selectablefield:JSONPath=`.spec.target.name`
+// +kubebuilder:selectablefield:JSONPath=`.spec.refreshInterval`
 type ExternalSecret struct {
 	metav1.TypeMeta   `json:",inline"`
 	metav1.ObjectMeta `json:"metadata,omitempty"`

+ 5 - 0
config/crds/bases/external-secrets.io_externalsecrets.yaml

@@ -665,6 +665,11 @@ spec:
                 type: string
             type: object
         type: object
+    selectableFields:
+    - jsonPath: .spec.secretStoreRef.name
+    - jsonPath: .spec.secretStoreRef.kind
+    - jsonPath: .spec.target.name
+    - jsonPath: .spec.refreshInterval
     served: true
     storage: true
     subresources:

+ 14 - 0
deploy/charts/external-secrets/tests/__snapshot__/crds_test.yaml.snap

@@ -1655,6 +1655,8 @@ should match snapshot of default values:
                                   - value
                                 type: object
                               type: array
+                            validationResult:
+                              type: integer
                           required:
                             - data
                           type: object
@@ -4417,6 +4419,18 @@ should match snapshot of default values:
                                 - name
                                 - type
                               type: object
+                            checkAndSet:
+                              description: |-
+                                CheckAndSet defines the Check-And-Set (CAS) settings for PushSecret operations.
+                                Only applies to Vault KV v2 stores. When enabled, write operations must include
+                                the current version of the secret to prevent unintentional overwrites.
+                              properties:
+                                required:
+                                  description: |-
+                                    Required when true, all write operations must include a check-and-set parameter.
+                                    This helps prevent unintentional overwrites of secrets.
+                                  type: boolean
+                              type: object
                             forwardInconsistent:
                               description: |-
                                 ForwardInconsistent tells Vault to forward read-after-write requests to the Vault

+ 5 - 0
deploy/crds/bundle.yaml

@@ -11742,6 +11742,11 @@ spec:
                   type: string
               type: object
           type: object
+      selectableFields:
+        - jsonPath: .spec.secretStoreRef.name
+        - jsonPath: .spec.secretStoreRef.kind
+        - jsonPath: .spec.target.name
+        - jsonPath: .spec.refreshInterval
       served: true
       storage: true
       subresources:

+ 76 - 0
docs/api/selectable-fields.md

@@ -0,0 +1,76 @@
+# ExternalSecret Selectable Fields
+
+As of Kubernetes 1.30, External Secrets Operator supports selectable fields for querying ExternalSecret resources based on spec field values. This feature enables efficient server-side filtering of ExternalSecret resources.
+
+## Overview
+
+Selectable fields allow you to use `kubectl` field selectors and Kubernetes API field selectors to filter ExternalSecret resources based on specific spec field values rather than just metadata fields like `metadata.name` and `metadata.namespace`.
+
+## Supported Selectable Fields
+
+The following spec fields are available for field selectors in ExternalSecret resources:
+
+- `spec.secretStoreRef.name` - Name of the SecretStore or ClusterSecretStore
+- `spec.secretStoreRef.kind` - Type of store (SecretStore or ClusterSecretStore)
+- `spec.target.name` - Name of the target Kubernetes Secret
+- `spec.refreshInterval` - Refresh interval for the external secret
+
+## Usage Examples
+
+### Using kubectl with field selectors
+
+Query all ExternalSecrets that use a specific SecretStore:
+```bash
+kubectl get externalsecrets --field-selector spec.secretStoreRef.name=my-vault-store
+```
+
+Find all ExternalSecrets that use ClusterSecretStores:
+```bash
+kubectl get externalsecrets --field-selector spec.secretStoreRef.kind=ClusterSecretStore
+```
+
+Find ExternalSecrets with a specific refresh interval:
+```bash
+kubectl get externalsecrets --field-selector spec.refreshInterval=15m
+```
+
+Find ExternalSecrets that create a specific target secret:
+```bash
+kubectl get externalsecrets --field-selector spec.target.name=database-credentials
+```
+
+You can also combine multiple field selectors:
+```bash
+kubectl get externalsecrets --field-selector spec.secretStoreRef.kind=SecretStore,spec.refreshInterval=1h
+```
+
+### Using the Kubernetes API
+
+When using the Kubernetes client libraries, you can use field selectors programmatically:
+
+```go
+import (
+    metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
+    "sigs.k8s.io/controller-runtime/pkg/client"
+)
+
+// List ExternalSecrets using a specific SecretStore
+fieldSelector := fields.OneTermEqualSelector("spec.secretStoreRef.name", "my-vault-store")
+listOptions := &client.ListOptions{
+    FieldSelector: fieldSelector,
+}
+
+var externalSecrets esv1.ExternalSecretList
+err := kubeClient.List(ctx, &externalSecrets, listOptions)
+```
+
+### Advanced Filtering
+
+You can combine field selectors with label selectors for more complex queries:
+
+```bash
+# Find ExternalSecrets with specific store AND specific label
+kubectl get externalsecrets \
+  --field-selector spec.secretStoreRef.kind=ClusterSecretStore \
+  --selector environment=production
+```

+ 1 - 1
e2e/Makefile

@@ -2,7 +2,7 @@ MAKEFLAGS   += --warn-undefined-variables
 SHELL       := /bin/bash
 .SHELLFLAGS := -euo pipefail -c
 
-KIND_IMG       = "kindest/node:v1.24.2@sha256:1f0cee2282f43150b52dc7933183ed96abdcfc8d293f30ec07082495874876f1"
+KIND_IMG       = "kindest/node:v1.33.4@sha256:25a6018e48dfcaee478f4a59af81157a437f15e6e140bf103f85a2e7cd0cbbf2"
 DOCKER_BUILD_ARGS     ?=
 
 export E2E_IMAGE_NAME ?= ghcr.io/external-secrets/external-secrets-e2e

+ 1 - 0
hack/api-docs/mkdocs.yml

@@ -87,6 +87,7 @@ nav:
           - API specification: api/spec.md
           - Controller Options: api/controller-options.md
           - Metrics: api/metrics.md
+          - Selectable Fields: api/selectable-fields.md
   - Guides:
       - Introduction: guides/introduction.md
       - External Secrets: