From 5e44be1d24a7c42283278edecc62100ed8941041 Mon Sep 17 00:00:00 2001 From: Gabriel Mendoza Date: Thu, 16 Apr 2026 14:27:38 -0400 Subject: [PATCH] Fix CEL validation error when provider field is missing in VolumeSpec ## Problem After upgrading to v3.1.0, customers encountered validation errors when updating existing Standalone CRs that were created with previous versions: ``` The Standalone "standalone" is invalid: status.smartstore.volumes[0]: Invalid value: "object": no such key: provider evaluating rule: region is required when provider is aws ``` This error occurred because the CEL validation rule added in #1740 attempted to access `self.provider` without first checking if the field exists. In upgrade scenarios, status fields populated by older operator versions may not include the `provider` field, causing the validation to fail with "no such key: provider". ## Root Cause The original CEL validation rule was: ``` self.provider != 'aws' || size(self.region) > 0 ``` This rule evaluates `self.provider` even when the field doesn't exist, violating CEL's requirement to check field existence with `has()` before accessing optional fields. ## Solution Updated the CEL validation rule to: ``` !has(self.provider) || self.provider != 'aws' || (has(self.region) && size(self.region) > 0) ``` This change: 1. First checks if `provider` field exists with `!has(self.provider)` 2. If it doesn't exist, validation passes (allows backward compatibility) 3. Only validates the AWS region requirement when provider is explicitly set to 'aws' 4. Also checks `has(self.region)` before accessing the region field ## Testing Reproduced the issue by: 1. Creating a Standalone CR with the v3.1.0 CRDs 2. Patching the status to remove the provider field (simulating upgrade scenario) 3. Confirmed the error: "no such key: provider evaluating rule" 4. Applied the fix and verified the same operation succeeds ## Impact - Fixes upgrade path from pre-3.1.0 versions where status fields were populated without the provider field - Maintains the validation requirement that AWS volumes must have a region - No impact on new deployments as they will include the provider field Co-Authored-By: Claude Opus 4.6 --- api/v4/common_types.go | 2 +- ...enterprise.splunk.com_clustermanagers.yaml | 12 ++++++---- .../enterprise.splunk.com_clustermasters.yaml | 12 ++++++---- ...nterprise.splunk.com_ingestorclusters.yaml | 6 +++-- ...enterprise.splunk.com_licensemanagers.yaml | 6 +++-- .../enterprise.splunk.com_licensemasters.yaml | 6 +++-- ...erprise.splunk.com_monitoringconsoles.yaml | 12 ++++++---- ...erprise.splunk.com_searchheadclusters.yaml | 12 ++++++---- .../enterprise.splunk.com_standalones.yaml | 24 ++++++++++++------- 9 files changed, 61 insertions(+), 31 deletions(-) diff --git a/api/v4/common_types.go b/api/v4/common_types.go index e53317075..9bfcb17cf 100644 --- a/api/v4/common_types.go +++ b/api/v4/common_types.go @@ -327,7 +327,7 @@ type IndexConfDefaultsSpec struct { } // VolumeSpec defines remote volume config -// +kubebuilder:validation:XValidation:rule="self.provider != 'aws' || size(self.region) > 0",message="region is required when provider is aws" +// +kubebuilder:validation:XValidation:rule="!has(self.provider) || self.provider != 'aws' || (has(self.region) && size(self.region) > 0)",message="region is required when provider is aws" type VolumeSpec struct { // Remote volume name // +kubebuilder:validation:Required diff --git a/config/crd/bases/enterprise.splunk.com_clustermanagers.yaml b/config/crd/bases/enterprise.splunk.com_clustermanagers.yaml index a19a639ae..a44a2b11b 100644 --- a/config/crd/bases/enterprise.splunk.com_clustermanagers.yaml +++ b/config/crd/bases/enterprise.splunk.com_clustermanagers.yaml @@ -1164,7 +1164,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -2375,7 +2376,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name @@ -4626,7 +4628,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: @@ -4919,7 +4922,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name diff --git a/config/crd/bases/enterprise.splunk.com_clustermasters.yaml b/config/crd/bases/enterprise.splunk.com_clustermasters.yaml index 77b835376..c46a2c1e6 100644 --- a/config/crd/bases/enterprise.splunk.com_clustermasters.yaml +++ b/config/crd/bases/enterprise.splunk.com_clustermasters.yaml @@ -1160,7 +1160,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -2371,7 +2372,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name @@ -4622,7 +4624,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: @@ -4912,7 +4915,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name diff --git a/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml b/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml index 44238ca7a..c2d80fb44 100644 --- a/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml +++ b/config/crd/bases/enterprise.splunk.com_ingestorclusters.yaml @@ -1160,7 +1160,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -4579,7 +4580,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: diff --git a/config/crd/bases/enterprise.splunk.com_licensemanagers.yaml b/config/crd/bases/enterprise.splunk.com_licensemanagers.yaml index b65b6beaf..bd5d6153e 100644 --- a/config/crd/bases/enterprise.splunk.com_licensemanagers.yaml +++ b/config/crd/bases/enterprise.splunk.com_licensemanagers.yaml @@ -1154,7 +1154,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -4473,7 +4474,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: diff --git a/config/crd/bases/enterprise.splunk.com_licensemasters.yaml b/config/crd/bases/enterprise.splunk.com_licensemasters.yaml index c2a96b9e7..70b638e5d 100644 --- a/config/crd/bases/enterprise.splunk.com_licensemasters.yaml +++ b/config/crd/bases/enterprise.splunk.com_licensemasters.yaml @@ -1149,7 +1149,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -4468,7 +4469,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: diff --git a/config/crd/bases/enterprise.splunk.com_monitoringconsoles.yaml b/config/crd/bases/enterprise.splunk.com_monitoringconsoles.yaml index f5142a14f..d9fd2d451 100644 --- a/config/crd/bases/enterprise.splunk.com_monitoringconsoles.yaml +++ b/config/crd/bases/enterprise.splunk.com_monitoringconsoles.yaml @@ -1156,7 +1156,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -4474,7 +4475,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: @@ -5776,7 +5778,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -9094,7 +9097,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: diff --git a/config/crd/bases/enterprise.splunk.com_searchheadclusters.yaml b/config/crd/bases/enterprise.splunk.com_searchheadclusters.yaml index 4f4674b32..4faa49ccf 100644 --- a/config/crd/bases/enterprise.splunk.com_searchheadclusters.yaml +++ b/config/crd/bases/enterprise.splunk.com_searchheadclusters.yaml @@ -1162,7 +1162,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -4497,7 +4498,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: @@ -5869,7 +5871,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -9462,7 +9465,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: diff --git a/config/crd/bases/enterprise.splunk.com_standalones.yaml b/config/crd/bases/enterprise.splunk.com_standalones.yaml index 8c8c5035c..fcb3ad911 100644 --- a/config/crd/bases/enterprise.splunk.com_standalones.yaml +++ b/config/crd/bases/enterprise.splunk.com_standalones.yaml @@ -1157,7 +1157,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -2372,7 +2373,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name @@ -4624,7 +4626,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: @@ -4911,7 +4914,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name @@ -6075,7 +6079,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array type: object clusterManagerRef: @@ -7291,7 +7296,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name @@ -9543,7 +9549,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' + || (has(self.region) && size(self.region) > 0)' type: array type: object appSrcDeployStatus: @@ -9833,7 +9840,8 @@ spec: type: object x-kubernetes-validations: - message: region is required when provider is aws - rule: self.provider != 'aws' || size(self.region) > 0 + rule: '!has(self.provider) || self.provider != ''aws'' || + (has(self.region) && size(self.region) > 0)' type: array x-kubernetes-list-map-keys: - name