diff --git a/CHANGELOG.md b/CHANGELOG.md index 07f37174302..fc430543beb 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -88,7 +88,7 @@ New deprecation(s): ### Other -- TODO ([#XXX](https://github.com/kedacore/keda/issues/XXX)) +- **General**: Replace deprecated webhook.Validator with webhook.CustomValidator ([#6660](https://github.com/kedacore/keda/issues/6660)) ## v2.17.0 diff --git a/apis/eventing/v1alpha1/cloudeventsource_webhook.go b/apis/eventing/v1alpha1/cloudeventsource_webhook.go index 2dc577665de..57a0506a77e 100644 --- a/apis/eventing/v1alpha1/cloudeventsource_webhook.go +++ b/apis/eventing/v1alpha1/cloudeventsource_webhook.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha1 import ( + "context" "encoding/json" "fmt" "slices" @@ -33,28 +34,61 @@ var cloudeventsourcelog = logf.Log.WithName("cloudeventsource-validation-webhook func (ces *CloudEventSource) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). + WithValidator(&CloudEventSourceCustomValidator{}). For(ces). Complete() } func (cces *ClusterCloudEventSource) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). + WithValidator(&ClusterCloudEventSourceCustomValidator{}). For(cces). Complete() } // +kubebuilder:webhook:path=/validate-eventing-keda-sh-v1alpha1-cloudeventsource,mutating=false,failurePolicy=ignore,sideEffects=None,groups=eventing.keda.sh,resources=cloudeventsources,verbs=create;update,versions=v1alpha1,name=vcloudeventsource.kb.io,admissionReviewVersions=v1 -var _ webhook.Validator = &CloudEventSource{} +// CloudEventSourceCustomValidator is a custom validator for CloudEventSource objects +type CloudEventSourceCustomValidator struct{} + +func (cescv CloudEventSourceCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + ces := obj.(*CloudEventSource) + return ces.ValidateCreate(request.DryRun) +} + +func (cescv CloudEventSourceCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + ces := newObj.(*CloudEventSource) + old := oldObj.(*CloudEventSource) + return ces.ValidateUpdate(old, request.DryRun) +} + +func (cescv CloudEventSourceCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + ces := obj.(*CloudEventSource) + return ces.ValidateDelete(request.DryRun) +} + +var _ webhook.CustomValidator = &CloudEventSourceCustomValidator{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (ces *CloudEventSource) ValidateCreate() (admission.Warnings, error) { +func (ces *CloudEventSource) ValidateCreate(_ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(ces, "", " ") cloudeventsourcelog.Info(fmt.Sprintf("validating cloudeventsource creation for %s", string(val))) return validateSpec(&ces.Spec) } -func (ces *CloudEventSource) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { +func (ces *CloudEventSource) ValidateUpdate(old runtime.Object, _ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(ces, "", " ") cloudeventsourcelog.V(1).Info(fmt.Sprintf("validating cloudeventsource update for %s", string(val))) @@ -66,22 +100,53 @@ func (ces *CloudEventSource) ValidateUpdate(old runtime.Object) (admission.Warni return validateSpec(&ces.Spec) } -func (ces *CloudEventSource) ValidateDelete() (admission.Warnings, error) { +func (ces *CloudEventSource) ValidateDelete(_ *bool) (admission.Warnings, error) { return nil, nil } // +kubebuilder:webhook:path=/validate-eventing-keda-sh-v1alpha1-clustercloudeventsource,mutating=false,failurePolicy=ignore,sideEffects=None,groups=eventing.keda.sh,resources=clustercloudeventsources,verbs=create;update,versions=v1alpha1,name=vclustercloudeventsource.kb.io,admissionReviewVersions=v1 -var _ webhook.Validator = &ClusterCloudEventSource{} +// ClusterCloudEventSourceCustomValidator is a custom validator for ClusterCloudEventSource objects +type ClusterCloudEventSourceCustomValidator struct{} + +func (ccescv ClusterCloudEventSourceCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + cces := obj.(*ClusterCloudEventSource) + return cces.ValidateCreate(request.DryRun) +} + +func (ccescv ClusterCloudEventSourceCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + cces := newObj.(*ClusterCloudEventSource) + old := oldObj.(*ClusterCloudEventSource) + return cces.ValidateUpdate(old, request.DryRun) +} + +func (ccescv ClusterCloudEventSourceCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + cces := obj.(*ClusterCloudEventSource) + return cces.ValidateDelete(request.DryRun) +} + +var _ webhook.CustomValidator = &ClusterCloudEventSourceCustomValidator{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (cces *ClusterCloudEventSource) ValidateCreate() (admission.Warnings, error) { +func (cces *ClusterCloudEventSource) ValidateCreate(_ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(cces, "", " ") cloudeventsourcelog.Info(fmt.Sprintf("validating clustercloudeventsource creation for %s", string(val))) return validateSpec(&cces.Spec) } -func (cces *ClusterCloudEventSource) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { +func (cces *ClusterCloudEventSource) ValidateUpdate(old runtime.Object, _ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(cces, "", " ") cloudeventsourcelog.V(1).Info(fmt.Sprintf("validating clustercloudeventsource update for %s", string(val))) @@ -93,7 +158,7 @@ func (cces *ClusterCloudEventSource) ValidateUpdate(old runtime.Object) (admissi return validateSpec(&cces.Spec) } -func (cces *ClusterCloudEventSource) ValidateDelete() (admission.Warnings, error) { +func (cces *ClusterCloudEventSource) ValidateDelete(_ *bool) (admission.Warnings, error) { return nil, nil } diff --git a/apis/keda/v1alpha1/scaledjob_webhook.go b/apis/keda/v1alpha1/scaledjob_webhook.go index 24eb03d3f24..0aec1164448 100644 --- a/apis/keda/v1alpha1/scaledjob_webhook.go +++ b/apis/keda/v1alpha1/scaledjob_webhook.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha1 import ( + "context" "encoding/json" "fmt" @@ -32,22 +33,54 @@ var scaledjoblog = logf.Log.WithName("scaledjob-validation-webhook") func (s *ScaledJob) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). + WithValidator(&ScaledJobCustomValidator{}). For(s). Complete() } // +kubebuilder:webhook:path=/validate-keda-sh-v1alpha1-scaledjob,mutating=false,failurePolicy=ignore,sideEffects=None,groups=keda.sh,resources=scaledjobs,verbs=create;update,versions=v1alpha1,name=vscaledjob.kb.io,admissionReviewVersions=v1 -var _ webhook.Validator = &ScaledJob{} +// ScaledJobCustomValidator is a custom validator for ScaledJob objects +type ScaledJobCustomValidator struct{} + +func (sjcv ScaledJobCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + sj := obj.(*ScaledJob) + return sj.ValidateCreate(request.DryRun) +} + +func (sjcv ScaledJobCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + sj := newObj.(*ScaledJob) + old := oldObj.(*ScaledJob) + return sj.ValidateUpdate(old, request.DryRun) +} + +func (sjcv ScaledJobCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + sj := obj.(*ScaledJob) + return sj.ValidateDelete(request.DryRun) +} + +var _ webhook.CustomValidator = &ScaledJobCustomValidator{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (s *ScaledJob) ValidateCreate() (admission.Warnings, error) { +func (s *ScaledJob) ValidateCreate(dryRun *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(s, "", " ") scaledjoblog.Info(fmt.Sprintf("validating scaledjob creation for %s", string(val))) - return nil, verifyTriggers(s, "create", false) + return nil, verifyTriggers(s, "create", *dryRun) } -func (s *ScaledJob) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { +func (s *ScaledJob) ValidateUpdate(old runtime.Object, dryRun *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(s, "", " ") scaledobjectlog.V(1).Info(fmt.Sprintf("validating scaledjob update for %s", string(val))) @@ -56,10 +89,10 @@ func (s *ScaledJob) ValidateUpdate(old runtime.Object) (admission.Warnings, erro scaledjoblog.V(1).Info("finalizer removal, skipping validation") return nil, nil } - return nil, verifyTriggers(s, "update", false) + return nil, verifyTriggers(s, "update", *dryRun) } -func (s *ScaledJob) ValidateDelete() (admission.Warnings, error) { +func (s *ScaledJob) ValidateDelete(_ *bool) (admission.Warnings, error) { return nil, nil } diff --git a/apis/keda/v1alpha1/scaledobject_webhook.go b/apis/keda/v1alpha1/scaledobject_webhook.go index 5c981bf3785..c6dca1eee17 100644 --- a/apis/keda/v1alpha1/scaledobject_webhook.go +++ b/apis/keda/v1alpha1/scaledobject_webhook.go @@ -53,6 +53,18 @@ var memoryString = "memory" var cpuString = "cpu" func (so *ScaledObject) SetupWebhookWithManager(mgr ctrl.Manager, cacheMissFallback bool) error { + err := setupKubernetesClients(mgr, cacheMissFallback) + if err != nil { + return fmt.Errorf("failed to setup kubernetes clients: %w", err) + } + + return ctrl.NewWebhookManagedBy(mgr). + WithValidator(&ScaledObjectCustomValidator{}). + For(so). + Complete() +} + +func setupKubernetesClients(mgr ctrl.Manager, cacheMissFallback bool) error { kc = mgr.GetClient() restMapper = mgr.GetRESTMapper() cacheMissToDirectClient = cacheMissFallback @@ -70,10 +82,8 @@ func (so *ScaledObject) SetupWebhookWithManager(mgr ctrl.Manager, cacheMissFallb return fmt.Errorf("failed to initialize direct client: %w", err) } } - return ctrl.NewWebhookManagedBy(mgr). - WithValidator(&ScaledObjectCustomValidator{}). - For(so). - Complete() + + return nil } // +kubebuilder:webhook:path=/validate-keda-sh-v1alpha1-scaledobject,mutating=false,failurePolicy=ignore,sideEffects=None,groups=keda.sh,resources=scaledobjects,verbs=create;update,versions=v1alpha1,name=vscaledobject.kb.io,admissionReviewVersions=v1 diff --git a/apis/keda/v1alpha1/triggerauthentication_webhook.go b/apis/keda/v1alpha1/triggerauthentication_webhook.go index 83fb6348e46..2e425ed7802 100644 --- a/apis/keda/v1alpha1/triggerauthentication_webhook.go +++ b/apis/keda/v1alpha1/triggerauthentication_webhook.go @@ -17,6 +17,7 @@ limitations under the License. package v1alpha1 import ( + "context" "encoding/json" "fmt" @@ -37,28 +38,61 @@ var triggerauthenticationlog = logf.Log.WithName("triggerauthentication-validati func (ta *TriggerAuthentication) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). + WithValidator(&TriggerAuthenticationCustomValidator{}). For(ta). Complete() } func (cta *ClusterTriggerAuthentication) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). + WithValidator(&ClusterTriggerAuthenticationCustomValidator{}). For(cta). Complete() } // +kubebuilder:webhook:path=/validate-keda-sh-v1alpha1-triggerauthentication,mutating=false,failurePolicy=ignore,sideEffects=None,groups=keda.sh,resources=triggerauthentications,verbs=create;update,versions=v1alpha1,name=vstriggerauthentication.kb.io,admissionReviewVersions=v1 -var _ webhook.Validator = &TriggerAuthentication{} +// TriggerAuthenticationCustomValidator is a custom validator for TriggerAuthentication objects +type TriggerAuthenticationCustomValidator struct{} + +func (tacv TriggerAuthenticationCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + ta := obj.(*TriggerAuthentication) + return ta.ValidateCreate(request.DryRun) +} + +func (tacv TriggerAuthenticationCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + ta := newObj.(*TriggerAuthentication) + old := oldObj.(*TriggerAuthentication) + return ta.ValidateUpdate(old, request.DryRun) +} + +func (tacv TriggerAuthenticationCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + ta := obj.(*TriggerAuthentication) + return ta.ValidateDelete(request.DryRun) +} + +var _ webhook.CustomValidator = &TriggerAuthenticationCustomValidator{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (ta *TriggerAuthentication) ValidateCreate() (admission.Warnings, error) { +func (ta *TriggerAuthentication) ValidateCreate(_ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(ta, "", " ") triggerauthenticationlog.Info(fmt.Sprintf("validating triggerauthentication creation for %s", string(val))) return validateSpec(&ta.Spec) } -func (ta *TriggerAuthentication) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { +func (ta *TriggerAuthentication) ValidateUpdate(old runtime.Object, _ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(ta, "", " ") scaledobjectlog.V(1).Info(fmt.Sprintf("validating triggerauthentication update for %s", string(val))) @@ -70,22 +104,53 @@ func (ta *TriggerAuthentication) ValidateUpdate(old runtime.Object) (admission.W return validateSpec(&ta.Spec) } -func (ta *TriggerAuthentication) ValidateDelete() (admission.Warnings, error) { +func (ta *TriggerAuthentication) ValidateDelete(_ *bool) (admission.Warnings, error) { return nil, nil } // +kubebuilder:webhook:path=/validate-keda-sh-v1alpha1-clustertriggerauthentication,mutating=false,failurePolicy=ignore,sideEffects=None,groups=keda.sh,resources=clustertriggerauthentications,verbs=create;update,versions=v1alpha1,name=vsclustertriggerauthentication.kb.io,admissionReviewVersions=v1 -var _ webhook.Validator = &ClusterTriggerAuthentication{} +// ClusterTriggerAuthenticationCustomValidator is a custom validator for ClusterTriggerAuthentication objects +type ClusterTriggerAuthenticationCustomValidator struct{} + +func (ctacv ClusterTriggerAuthenticationCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + cta := obj.(*ClusterTriggerAuthentication) + return cta.ValidateCreate(request.DryRun) +} + +func (ctacv ClusterTriggerAuthenticationCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + cta := newObj.(*ClusterTriggerAuthentication) + old := oldObj.(*ClusterTriggerAuthentication) + return cta.ValidateUpdate(old, request.DryRun) +} + +func (ctacv ClusterTriggerAuthenticationCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (warnings admission.Warnings, err error) { + request, err := admission.RequestFromContext(ctx) + if err != nil { + return nil, err + } + cta := obj.(*ClusterTriggerAuthentication) + return cta.ValidateDelete(request.DryRun) +} + +var _ webhook.CustomValidator = &ClusterTriggerAuthenticationCustomValidator{} // ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (cta *ClusterTriggerAuthentication) ValidateCreate() (admission.Warnings, error) { +func (cta *ClusterTriggerAuthentication) ValidateCreate(_ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(cta, "", " ") triggerauthenticationlog.Info(fmt.Sprintf("validating clustertriggerauthentication creation for %s", string(val))) return validateSpec(&cta.Spec) } -func (cta *ClusterTriggerAuthentication) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { +func (cta *ClusterTriggerAuthentication) ValidateUpdate(old runtime.Object, _ *bool) (admission.Warnings, error) { val, _ := json.MarshalIndent(cta, "", " ") scaledobjectlog.V(1).Info(fmt.Sprintf("validating clustertriggerauthentication update for %s", string(val))) @@ -98,7 +163,7 @@ func (cta *ClusterTriggerAuthentication) ValidateUpdate(old runtime.Object) (adm return validateSpec(&cta.Spec) } -func (cta *ClusterTriggerAuthentication) ValidateDelete() (admission.Warnings, error) { +func (cta *ClusterTriggerAuthentication) ValidateDelete(_ *bool) (admission.Warnings, error) { return nil, nil }