@@ -37,7 +37,6 @@ import (
3737 logf "sigs.k8s.io/controller-runtime/pkg/log"
3838 "sigs.k8s.io/controller-runtime/pkg/webhook"
3939 "sigs.k8s.io/controller-runtime/pkg/webhook/admission"
40-
4140 common_webhook "github.com/openstack-k8s-operators/lib-common/modules/common/webhook"
4241)
4342
@@ -149,6 +148,8 @@ func (r *Cinder) ValidateCreate() (admission.Warnings, error) {
149148 cinderlog .Info ("validate create" , "name" , r .Name )
150149
151150 var allErrs field.ErrorList
151+ var allWarns admission.Warnings
152+
152153 basePath := field .NewPath ("spec" )
153154
154155 // Validate cinderVolume name is valid
@@ -168,8 +169,9 @@ func (r *Cinder) ValidateCreate() (admission.Warnings, error) {
168169 GetCrMaxLengthCorrection (r .Name )) // omit issue with statefulset pod label "controller-revision-hash": "<statefulset_name>-<hash>"
169170 allErrs = append (allErrs , err ... )
170171
171- if err := r .Spec .ValidateCreate (basePath , r .Namespace ); err != nil {
172- allErrs = append (allErrs , err ... )
172+ if warn , errs := r .Spec .ValidateCreate (basePath , r .Namespace ); err != nil {
173+ allErrs = append (allErrs , errs ... )
174+ allWarns = append (allWarns , warn ... )
173175 }
174176
175177 if len (allErrs ) != 0 {
@@ -183,28 +185,51 @@ func (r *Cinder) ValidateCreate() (admission.Warnings, error) {
183185
184186// ValidateCreate - Exported function wrapping non-exported validate functions,
185187// this function can be called externally to validate an cinder spec.
186- func (spec * CinderSpec ) ValidateCreate (basePath * field.Path , namespace string ) field.ErrorList {
188+ func (spec * CinderSpec ) ValidateCreate (
189+ basePath * field.Path ,
190+ namespace string ,
191+ ) ([]string , field.ErrorList ) {
187192 var allErrs field.ErrorList
193+ var allWarns admission.Warnings
188194
189195 // validate the service override key is valid
190196 allErrs = append (allErrs , service .ValidateRoutedOverrides (
191197 basePath .Child ("cinderAPI" ).Child ("override" ).Child ("service" ),
192198 spec .CinderAPI .Override .Service )... )
193199
200+ // Cinder Backup validation: it returns errors in case both CinderBackup
201+ // and CinderBackups are used, and it throws a warning by default when the
202+ // deprecated parameter is used (it is a non blocking issue though)
194203 allErrs = append (allErrs , spec .ValidateCinderTopology (basePath , namespace )... )
195- return allErrs
204+ bkpWarns , bkpErrs := spec .ValidateCinderBackup (basePath )
205+ allErrs = append (allErrs , bkpErrs ... )
206+ allWarns = append (allWarns , bkpWarns ... )
207+
208+ return allWarns , allErrs
196209}
197210
198- func (spec * CinderSpecCore ) ValidateCreate (basePath * field.Path , namespace string ) field.ErrorList {
211+ func (spec * CinderSpecCore ) ValidateCreate (
212+ basePath * field.Path ,
213+ namespace string ,
214+ ) ([]string , field.ErrorList ){
199215 var allErrs field.ErrorList
216+ var allWarns admission.Warnings
200217
201218 // validate the service override key is valid
202219 allErrs = append (allErrs , service .ValidateRoutedOverrides (
203220 basePath .Child ("cinderAPI" ).Child ("override" ).Child ("service" ),
204221 spec .CinderAPI .Override .Service )... )
205222
206223 allErrs = append (allErrs , spec .ValidateCinderTopology (basePath , namespace )... )
207- return allErrs
224+
225+ // Cinder Backup validation: it returns errors in case both CinderBackup
226+ // and CinderBackups are used, and it throws a warning by default when the
227+ // deprecated parameter is used (it is a non blocking issue though)
228+ bkpWarns , bkpErrs := spec .ValidateCinderBackup (basePath )
229+ allErrs = append (allErrs , bkpErrs ... )
230+ allWarns = append (allWarns , bkpWarns ... )
231+
232+ return allWarns , allErrs
208233}
209234
210235// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type
@@ -217,6 +242,8 @@ func (r *Cinder) ValidateUpdate(old runtime.Object) (admission.Warnings, error)
217242 }
218243
219244 var allErrs field.ErrorList
245+ var allWarns admission.Warnings
246+
220247 basePath := field .NewPath ("spec" )
221248
222249 // Validate cinderVolume name is valid
@@ -236,8 +263,9 @@ func (r *Cinder) ValidateUpdate(old runtime.Object) (admission.Warnings, error)
236263 GetCrMaxLengthCorrection (r .Name )) // omit issue with statefulset pod label "controller-revision-hash": "<statefulset_name>-<hash>"
237264 allErrs = append (allErrs , err ... )
238265
239- if err := r .Spec .ValidateUpdate (oldCinder .Spec , basePath , r .Namespace ); err != nil {
266+ if warns , err := r .Spec .ValidateUpdate (oldCinder .Spec , basePath , r .Namespace ); err != nil {
240267 allErrs = append (allErrs , err ... )
268+ allWarns = append (allWarns , warns ... )
241269 }
242270
243271 if len (allErrs ) != 0 {
@@ -246,33 +274,61 @@ func (r *Cinder) ValidateUpdate(old runtime.Object) (admission.Warnings, error)
246274 r .Name , allErrs )
247275 }
248276
249- return nil , nil
277+ return allWarns , nil
250278}
251279
252280// ValidateUpdate - Exported function wrapping non-exported validate functions,
253281// this function can be called externally to validate an cinder spec.
254- func (spec * CinderSpec ) ValidateUpdate (old CinderSpec , basePath * field.Path , namespace string ) field.ErrorList {
282+ func (spec * CinderSpec ) ValidateUpdate (
283+ old CinderSpec ,
284+ basePath * field.Path ,
285+ namespace string ,
286+ ) ([]string , field.ErrorList ) {
287+
255288 var allErrs field.ErrorList
289+ var allWarns []string
256290
257291 // validate the service override key is valid
258292 allErrs = append (allErrs , service .ValidateRoutedOverrides (
259293 basePath .Child ("cinderAPI" ).Child ("override" ).Child ("service" ),
260294 spec .CinderAPI .Override .Service )... )
261295
262296 allErrs = append (allErrs , spec .ValidateCinderTopology (basePath , namespace )... )
263- return allErrs
297+
298+ // Cinder Backup validation: it returns errors in case both CinderBackup
299+ // and CinderBackups are used, and it throws a warning by default when the
300+ // deprecated parameter is used (it is a non blocking issue though)
301+ bkpWarns , bkpErrs := spec .ValidateCinderBackup (basePath )
302+ allErrs = append (allErrs , bkpErrs ... )
303+ allWarns = append (allWarns , bkpWarns ... )
304+
305+ return allWarns , allErrs
264306}
265307
266- func (spec * CinderSpecCore ) ValidateUpdate (old CinderSpecCore , basePath * field.Path , namespace string ) field.ErrorList {
308+ func (spec * CinderSpecCore ) ValidateUpdate (
309+ old CinderSpecCore ,
310+ basePath * field.Path ,
311+ namespace string ,
312+ ) ([]string , field.ErrorList ) {
313+
267314 var allErrs field.ErrorList
315+ var allWarns []string
268316
269317 // validate the service override key is valid
270318 allErrs = append (allErrs , service .ValidateRoutedOverrides (
271319 basePath .Child ("cinderAPI" ).Child ("override" ).Child ("service" ),
272320 spec .CinderAPI .Override .Service )... )
273321
274322 allErrs = append (allErrs , spec .ValidateCinderTopology (basePath , namespace )... )
275- return allErrs
323+
324+ // Cinder Backup validation: it returns errors in case both CinderBackup
325+ // and CinderBackups are used, and it throws a warning by default when the
326+ // deprecated parameter is used (it is a non blocking issue though)
327+ bkpWarns , bkpErrs := spec .ValidateCinderBackup (basePath )
328+ allErrs = append (allErrs , bkpErrs ... )
329+ allWarns = append (allWarns , bkpWarns ... )
330+
331+ return allWarns , allErrs
276332}
277333
278334// ValidateDelete implements webhook.Validator so a webhook will be registered for the type
@@ -349,7 +405,7 @@ func (spec *CinderSpecCore) ValidateCinderTopology(basePath *field.Path, namespa
349405 bkPath := basePath .Child ("cinderBackup" )
350406 allErrs = append (allErrs ,
351407 spec .CinderBackup .ValidateTopology (bkPath , namespace )... )
352-
408+
353409 // When a TopologyRef CR is referenced with an override to an instance of
354410 // CinderBackups, fail if a different Namespace is referenced because not
355411 // supported
@@ -418,3 +474,50 @@ func (spec *CinderSpec) ValidateCinderTopology(basePath *field.Path, namespace s
418474 }
419475 return allErrs
420476}
477+
478+ // TODO: Remove this function when refactoring CinderSpec to include CinderSpecCore
479+ func (spec * CinderSpec ) ValidateCinderBackup (basePath * field.Path ) ([]string , field.ErrorList ) {
480+ var allErrs field.ErrorList
481+ var allWarns []string
482+
483+ // Check if the deprecated field is configured
484+ isDeprecatedUsed := spec .CinderBackup .Replicas != nil && * spec .CinderBackup .Replicas > 0
485+ // Check if CinderBackup list is configured
486+ isCinderBackupListUsed := spec .CinderBackups != nil && len (* spec .CinderBackups ) > 0
487+
488+ // Fail if both cinderBackup (the deprecated field) and cinderBackups (the new list)
489+ // are used together
490+ if isDeprecatedUsed && isCinderBackupListUsed {
491+ errMsg := "Usage of the deprecated 'cinderBackup' is forbidden when 'cinderBackups' is defined."
492+ allErrs = append (allErrs , field .Invalid (basePath , "cinderBackup" , errMsg ))
493+ }
494+ // Append a warning depending on the cinderBackup field usage
495+ if isDeprecatedUsed {
496+ warningMsg := "The 'cinderBackup' field is deprecated and will be removed in a future release. Please migrate to 'cinderBackups'."
497+ allWarns = append (allWarns , warningMsg )
498+ }
499+ return allWarns , allErrs
500+ }
501+
502+ func (spec * CinderSpecCore ) ValidateCinderBackup (basePath * field.Path )([]string , field.ErrorList ) {
503+ var allErrs field.ErrorList
504+ var allWarns []string
505+
506+ // Check if the deprecated field is configured
507+ isDeprecatedUsed := spec .CinderBackup .Replicas != nil && * spec .CinderBackup .Replicas > 0
508+ // Check if CinderBackup list is configured
509+ isCinderBackupListUsed := spec .CinderBackups != nil && len (* spec .CinderBackups ) > 0
510+
511+ // Fail if both cinderBackup (the deprecated field) and cinderBackups (the new list)
512+ // are used together
513+ if isDeprecatedUsed && isCinderBackupListUsed {
514+ errMsg := "Usage of the deprecated 'cinderBackup' is forbidden when the new 'cinderBackups' API is used."
515+ allErrs = append (allErrs , field .Invalid (basePath , "cinderBackup" , errMsg ))
516+ }
517+ // Append a warning depending on the cinderBackup field usage
518+ if isDeprecatedUsed {
519+ warningMsg := "The 'cinderBackup' field is deprecated and will be removed in a future release. Please migrate to 'cinderBackups'."
520+ allWarns = append (allWarns , warningMsg )
521+ }
522+ return allWarns , allErrs
523+ }
0 commit comments