From fb60a14eccf7004177e2080bd0987412037d491b Mon Sep 17 00:00:00 2001 From: Sanket Sudake Date: Thu, 23 Jan 2025 15:36:07 +0530 Subject: [PATCH] Adopt custom defaulter and validator interface for webhooks intead of deprecated default (#3152) * Move webhooks to webhooks package Signed-off-by: Sanket Sudake * change interface Signed-off-by: Sanket Sudake * Change interface methods Signed-off-by: Sanket Sudake * comment debug logs for now Signed-off-by: Sanket Sudake * rename files Signed-off-by: Sanket Sudake * Fix webhook warnings Signed-off-by: Sanket Sudake * Update makefile Signed-off-by: Sanket Sudake * lint fixes Signed-off-by: Sanket Sudake --------- Signed-off-by: Sanket Sudake --- Makefile | 2 +- pkg/apis/core/v1/environment_webhook.go | 73 ----------- pkg/apis/core/v1/function_webhook.go | 105 --------------- pkg/apis/core/v1/httptrigger_webhook.go | 80 ------------ .../core/v1/kuberneteswatchtrigger_webhook.go | 73 ----------- pkg/apis/core/v1/package_webhook.go | 108 ---------------- pkg/apis/core/v1/timetrigger_webhook.go | 92 ------------- .../canaryconfig.go} | 39 +++--- pkg/webhook/environment.go | 92 +++++++++++++ pkg/webhook/function.go | 104 +++++++++++++++ pkg/webhook/httptrigger.go | 91 +++++++++++++ pkg/webhook/kuberneteswatchtrigger.go | 91 +++++++++++++ .../messagequeuetrigger.go} | 65 ++++++---- pkg/webhook/package.go | 121 ++++++++++++++++++ .../{admission-webhook.go => service.go} | 17 ++- pkg/webhook/timetrigger.go | 92 +++++++++++++ 16 files changed, 658 insertions(+), 587 deletions(-) delete mode 100644 pkg/apis/core/v1/environment_webhook.go delete mode 100644 pkg/apis/core/v1/function_webhook.go delete mode 100644 pkg/apis/core/v1/httptrigger_webhook.go delete mode 100644 pkg/apis/core/v1/kuberneteswatchtrigger_webhook.go delete mode 100644 pkg/apis/core/v1/package_webhook.go delete mode 100644 pkg/apis/core/v1/timetrigger_webhook.go rename pkg/{apis/core/v1/canaryconfig_webhook .go => webhook/canaryconfig.go} (58%) create mode 100644 pkg/webhook/environment.go create mode 100644 pkg/webhook/function.go create mode 100644 pkg/webhook/httptrigger.go create mode 100644 pkg/webhook/kuberneteswatchtrigger.go rename pkg/{apis/core/v1/messagequeuetrigger_webhook.go => webhook/messagequeuetrigger.go} (51%) create mode 100644 pkg/webhook/package.go rename pkg/webhook/{admission-webhook.go => service.go} (91%) create mode 100644 pkg/webhook/timetrigger.go diff --git a/Makefile b/Makefile index 5dd4ad52..132891c4 100644 --- a/Makefile +++ b/Makefile @@ -72,7 +72,7 @@ generate-crds: ### Webhook generation: it generates webhook configs with help of kubebuilder:webhook tag generate-webhooks: go run sigs.k8s.io/controller-tools/cmd/controller-gen webhook \ - paths=./pkg/apis/core/v1 \ + paths=./pkg/webhook \ output:dir=charts/fission-all/templates/webhook-server diff --git a/pkg/apis/core/v1/environment_webhook.go b/pkg/apis/core/v1/environment_webhook.go deleted file mode 100644 index bc263ee6..00000000 --- a/pkg/apis/core/v1/environment_webhook.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1 - -import ( - "go.uber.org/zap" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - - "github.com/fission/fission/pkg/utils/loggerfactory" -) - -// log is for logging in this package. -var environmentlog = loggerfactory.GetLogger().Named("environment-resource") - -func (r *Environment) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-environment,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=environments,verbs=create;update,versions=v1,name=menvironment.fission.io,admissionReviewVersions=v1 - -var _ webhook.Defaulter = &Environment{} - -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *Environment) Default() { - environmentlog.Debug("default", zap.String("name", r.Name)) -} - -// user: change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-fission-io-v1-environment,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=environments,verbs=create,versions=v1,name=venvironment.fission.io,admissionReviewVersions=v1 - -var _ webhook.Validator = &Environment{} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *Environment) ValidateCreate() (admission.Warnings, error) { - environmentlog.Debug("validate create", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("Environment", err) - return nil, err - } - return nil, nil -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *Environment) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - environmentlog.Debug("validate update", zap.String("name", r.Name)) - return nil, nil -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *Environment) ValidateDelete() (admission.Warnings, error) { - environmentlog.Debug("validate delete", zap.String("name", r.Name)) - return nil, nil -} diff --git a/pkg/apis/core/v1/function_webhook.go b/pkg/apis/core/v1/function_webhook.go deleted file mode 100644 index 2a946a38..00000000 --- a/pkg/apis/core/v1/function_webhook.go +++ /dev/null @@ -1,105 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1 - -import ( - "fmt" - - "go.uber.org/zap" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - - "github.com/fission/fission/pkg/utils/loggerfactory" -) - -// log is for logging in this package. -var functionlog = loggerfactory.GetLogger().Named("function-resource") - -func (r *Function) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-function,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=functions,verbs=create;update,versions=v1,name=mfunction.fission.io,admissionReviewVersions=v1 - -var _ webhook.Defaulter = &Function{} - -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *Function) Default() { -} - -// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-fission-io-v1-function,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=functions,verbs=create;update,versions=v1,name=vfunction.fission.io,admissionReviewVersions=v1 - -var _ webhook.Validator = &Function{} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *Function) ValidateCreate() (admission.Warnings, error) { - functionlog.Debug("validate create", zap.String("name", r.Name)) - - for _, cnfMap := range r.Spec.ConfigMaps { - if cnfMap.Namespace != r.ObjectMeta.Namespace { - err := fmt.Errorf("ConfigMap's [%s] and function's Namespace [%s] are different. ConfigMap needs to be present in the same namespace as function", cnfMap.Namespace, r.ObjectMeta.Namespace) - return nil, AggregateValidationErrors("Function", err) - } - } - for _, secret := range r.Spec.Secrets { - if secret.Namespace != r.ObjectMeta.Namespace { - err := fmt.Errorf("secret [%s] and function's Namespace [%s] are different. Secret needs to be present in the same namespace as function", secret.Namespace, r.ObjectMeta.Namespace) - return nil, AggregateValidationErrors("Function", err) - } - } - - err := r.Validate() - if err != nil { - return nil, AggregateValidationErrors("Function", err) - } - return nil, nil -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *Function) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - functionlog.Debug("validate update", zap.String("name", r.Name)) - - for _, cnfMap := range r.Spec.ConfigMaps { - if cnfMap.Namespace != r.ObjectMeta.Namespace { - err := fmt.Errorf("ConfigMap's [%s] and function's Namespace [%s] are different. ConfigMap needs to be present in the same namespace as function", cnfMap.Namespace, r.ObjectMeta.Namespace) - return nil, AggregateValidationErrors("Function", err) - } - } - for _, secret := range r.Spec.Secrets { - if secret.Namespace != r.ObjectMeta.Namespace { - err := fmt.Errorf("secret [%s] and function's Namespace [%s] are different. Secret needs to be present in the same namespace as function", secret.Namespace, r.ObjectMeta.Namespace) - return nil, AggregateValidationErrors("Function", err) - } - } - - err := r.Validate() - if err != nil { - return nil, AggregateValidationErrors("Function", err) - } - return nil, nil -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *Function) ValidateDelete() (admission.Warnings, error) { - functionlog.Debug("validate delete", zap.String("name", r.Name)) - return nil, nil -} diff --git a/pkg/apis/core/v1/httptrigger_webhook.go b/pkg/apis/core/v1/httptrigger_webhook.go deleted file mode 100644 index 8d4200b3..00000000 --- a/pkg/apis/core/v1/httptrigger_webhook.go +++ /dev/null @@ -1,80 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1 - -import ( - "go.uber.org/zap" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - - "github.com/fission/fission/pkg/utils/loggerfactory" -) - -// log is for logging in this package. -var httptriggerlog = loggerfactory.GetLogger().Named("httptrigger-resource") - -func (r *HTTPTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-httptrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=httptriggers,verbs=create;update,versions=v1,name=mhttptrigger.fission.io,admissionReviewVersions=v1 - -var _ webhook.Defaulter = &HTTPTrigger{} - -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *HTTPTrigger) Default() { - httptriggerlog.Debug("default", zap.String("name", r.Name)) -} - -// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-fission-io-v1-httptrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=httptriggers,verbs=create;update,versions=v1,name=vhttptrigger.fission.io,admissionReviewVersions=v1 - -var _ webhook.Validator = &HTTPTrigger{} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (t *HTTPTrigger) ValidateCreate() (admission.Warnings, error) { - httptriggerlog.Debug("validate create", zap.String("name", t.Name)) - err := t.Validate() - if err != nil { - err = AggregateValidationErrors("HTTPTrigger", err) - return nil, err - } - return nil, nil -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *HTTPTrigger) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - httptriggerlog.Debug("validate update", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("HTTPTrigger", err) - return nil, err - } - - return nil, nil -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *HTTPTrigger) ValidateDelete() (admission.Warnings, error) { - httptriggerlog.Debug("validate delete", zap.String("name", r.Name)) - - return nil, nil -} diff --git a/pkg/apis/core/v1/kuberneteswatchtrigger_webhook.go b/pkg/apis/core/v1/kuberneteswatchtrigger_webhook.go deleted file mode 100644 index d455ea72..00000000 --- a/pkg/apis/core/v1/kuberneteswatchtrigger_webhook.go +++ /dev/null @@ -1,73 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1 - -import ( - "go.uber.org/zap" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - - "github.com/fission/fission/pkg/utils/loggerfactory" -) - -// log is for logging in this package. -var kuberneteswatchtriggerlog = loggerfactory.GetLogger().Named("kuberneteswatchtrigger-resource") - -func (r *KubernetesWatchTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-kuberneteswatchtrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=kuberneteswatchtriggers,verbs=create;update,versions=v1,name=mkuberneteswatchtrigger.fission.io,admissionReviewVersions=v1 - -var _ webhook.Defaulter = &KubernetesWatchTrigger{} - -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *KubernetesWatchTrigger) Default() { - kuberneteswatchtriggerlog.Debug("default", zap.String("name", r.Name)) -} - -// user: change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-fission-io-v1-kuberneteswatchtrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=kuberneteswatchtriggers,verbs=create,versions=v1,name=vkuberneteswatchtrigger.fission.io,admissionReviewVersions=v1 - -var _ webhook.Validator = &KubernetesWatchTrigger{} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *KubernetesWatchTrigger) ValidateCreate() (admission.Warnings, error) { - kuberneteswatchtriggerlog.Debug("validate create", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("Watch", err) - return nil, err - } - return nil, nil -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *KubernetesWatchTrigger) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - // WATCH UPDATE NOT IMPLEMENTED - return nil, nil -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *KubernetesWatchTrigger) ValidateDelete() (admission.Warnings, error) { - kuberneteswatchtriggerlog.Debug("validate delete", zap.String("name", r.Name)) - return nil, nil -} diff --git a/pkg/apis/core/v1/package_webhook.go b/pkg/apis/core/v1/package_webhook.go deleted file mode 100644 index 372697f9..00000000 --- a/pkg/apis/core/v1/package_webhook.go +++ /dev/null @@ -1,108 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1 - -import ( - "fmt" - - "github.com/dustin/go-humanize" - "go.uber.org/zap" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - - ferror "github.com/fission/fission/pkg/error" - "github.com/fission/fission/pkg/utils/loggerfactory" -) - -// log is for logging in this package. -var packagelog = loggerfactory.GetLogger().Named("package-resource") - -func (r *Package) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -//+kubebuilder:webhook:path=/mutate-fission-io-v1-package,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=packages,verbs=create;update,versions=v1,name=mpackage.fission.io,admissionReviewVersions=v1 - -var _ webhook.Defaulter = &Package{} - -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *Package) Default() { - packagelog.Debug("default", zap.String("name", r.Name)) - if r.Status.BuildStatus == "" { - if !r.Spec.Deployment.IsEmpty() { - // deployment package exists - r.Status.BuildStatus = BuildStatusNone - } else if !r.Spec.Source.IsEmpty() { - // source package with no deployment is a pending build - r.Status.BuildStatus = BuildStatusPending - } else { - r.Status.BuildStatus = BuildStatusFailed // empty package - r.Status.BuildLog = "Both source and deployment are empty" - } - } -} - -// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-fission-io-v1-package,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=packages,verbs=create;update,versions=v1,name=vpackage.fission.io,admissionReviewVersions=v1 - -var _ webhook.Validator = &Package{} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *Package) ValidateCreate() (admission.Warnings, error) { - packagelog.Debug("validate create", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("Package", err) - return nil, err - } - - // Ensure size limits - if len(r.Spec.Source.Literal) > int(ArchiveLiteralSizeLimit) { - err := ferror.MakeError(ferror.ErrorInvalidArgument, - fmt.Sprintf("Package literal larger than %s", humanize.Bytes(uint64(ArchiveLiteralSizeLimit)))) - return nil, err - } - if len(r.Spec.Deployment.Literal) > int(ArchiveLiteralSizeLimit) { - err := ferror.MakeError(ferror.ErrorInvalidArgument, - fmt.Sprintf("Package literal larger than %s", humanize.Bytes(uint64(ArchiveLiteralSizeLimit)))) - return nil, err - } - return nil, nil -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *Package) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - packagelog.Debug("validate update", zap.String("name", r.Name)) - err := r.Validate() - - if err != nil { - err = AggregateValidationErrors("Package", err) - return nil, err - } - - return nil, nil -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *Package) ValidateDelete() (admission.Warnings, error) { - packagelog.Debug("validate delete", zap.String("name", r.Name)) - return nil, nil -} diff --git a/pkg/apis/core/v1/timetrigger_webhook.go b/pkg/apis/core/v1/timetrigger_webhook.go deleted file mode 100644 index f260386b..00000000 --- a/pkg/apis/core/v1/timetrigger_webhook.go +++ /dev/null @@ -1,92 +0,0 @@ -/* -Copyright 2022. - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - -Unless required by applicable law or agreed to in writing, software -distributed under the License is distributed on an "AS IS" BASIS, -WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -See the License for the specific language governing permissions and -limitations under the License. -*/ - -package v1 - -import ( - "go.uber.org/zap" - "k8s.io/apimachinery/pkg/runtime" - ctrl "sigs.k8s.io/controller-runtime" - "sigs.k8s.io/controller-runtime/pkg/webhook" - "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - - ferror "github.com/fission/fission/pkg/error" - "github.com/fission/fission/pkg/utils/loggerfactory" -) - -// log is for logging in this package. -var timetriggerlog = loggerfactory.GetLogger().Named("timetrigger-resource") - -func (r *TimeTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { - return ctrl.NewWebhookManagedBy(mgr). - For(r). - Complete() -} - -// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-timetrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=timetriggers,verbs=create;update,versions=v1,name=mtimetrigger.fission.io,admissionReviewVersions=v1 - -var _ webhook.Defaulter = &TimeTrigger{} - -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *TimeTrigger) Default() { - timetriggerlog.Debug("default", zap.String("name", r.Name)) -} - -// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. -//+kubebuilder:webhook:path=/validate-fission-io-v1-timetrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=timetriggers,verbs=create;update,versions=v1,name=vtimetrigger.fission.io,admissionReviewVersions=v1 - -var _ webhook.Validator = &TimeTrigger{} - -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *TimeTrigger) ValidateCreate() (admission.Warnings, error) { - timetriggerlog.Debug("validate create", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("TimeTrigger", err) - return nil, err - } - - err = IsValidCronSpec(r.Spec.Cron) - if err != nil { - err = ferror.MakeError(ferror.ErrorInvalidArgument, "TimeTrigger cron spec is not valid") - return nil, err - } - return nil, nil -} - -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *TimeTrigger) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - timetriggerlog.Debug("validate update", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("TimeTrigger", err) - return nil, err - } - - err = IsValidCronSpec(r.Spec.Cron) - if err != nil { - err = ferror.MakeError(ferror.ErrorInvalidArgument, "TimeTrigger cron spec is not valid") - return nil, err - } - - return nil, nil -} - -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *TimeTrigger) ValidateDelete() (admission.Warnings, error) { - timetriggerlog.Debug("validate delete", zap.String("name", r.Name)) - return nil, nil -} diff --git a/pkg/apis/core/v1/canaryconfig_webhook .go b/pkg/webhook/canaryconfig.go similarity index 58% rename from pkg/apis/core/v1/canaryconfig_webhook .go rename to pkg/webhook/canaryconfig.go index cf785126..672fa252 100644 --- a/pkg/apis/core/v1/canaryconfig_webhook .go +++ b/pkg/webhook/canaryconfig.go @@ -14,56 +14,55 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1 +package webhook import ( - "go.uber.org/zap" + "context" + "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" - "github.com/fission/fission/pkg/utils/loggerfactory" + v1 "github.com/fission/fission/pkg/apis/core/v1" ) -// log is for logging in this package. -var canaryconfiglog = loggerfactory.GetLogger().Named("canaryconfig-resource") +type CanaryConfig struct{} func (r *CanaryConfig) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). - For(r). + For(&v1.CanaryConfig{}). + WithDefaulter(r). + WithValidator(r). Complete() } // Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-canaryconfig,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=canaryconfigs,verbs=create;update,versions=v1,name=mcanaryconfig.fission.io,admissionReviewVersions=v1 // Refer Makefile -> generate-webhooks to generate config for manifests -var _ webhook.Defaulter = &CanaryConfig{} +var _ webhook.CustomDefaulter = &CanaryConfig{} -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *CanaryConfig) Default() { - canaryconfiglog.Debug("default", zap.String("name", r.Name)) +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *CanaryConfig) Default(_ context.Context, obj runtime.Object) error { + return nil } // user can change verbs to "verbs=create;update;delete" if you want to enable deletion validation. // Validation webhooks can be added by adding tag: kubebuilder:webhook:path=/validate-fission-io-v1-canaryconfig,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=canaryconfigs,verbs=create;update,versions=v1,name=vcanaryconfig.fission.io,admissionReviewVersions=v1 -var _ webhook.Validator = &CanaryConfig{} +var _ webhook.CustomValidator = &CanaryConfig{} -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *CanaryConfig) ValidateCreate() (admission.Warnings, error) { - canaryconfiglog.Debug("validate create", zap.String("name", r.Name)) +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *CanaryConfig) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { return nil, nil } -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *CanaryConfig) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - canaryconfiglog.Debug("validate update", zap.String("name", r.Name)) +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *CanaryConfig) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { return nil, nil } -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *CanaryConfig) ValidateDelete() (admission.Warnings, error) { - canaryconfiglog.Debug("validate delete", zap.String("name", r.Name)) +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *CanaryConfig) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { return nil, nil } diff --git a/pkg/webhook/environment.go b/pkg/webhook/environment.go new file mode 100644 index 00000000..9931dea6 --- /dev/null +++ b/pkg/webhook/environment.go @@ -0,0 +1,92 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + v1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/utils/loggerfactory" +) + +type Environment struct{} + +// log is for logging in this package. +var environmentlog = loggerfactory.GetLogger().Named("environment-resource") + +func (r *Environment) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&v1.Environment{}). + WithDefaulter(r). + WithValidator(r). + Complete() +} + +// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-environment,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=environments,verbs=create;update,versions=v1,name=menvironment.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &Environment{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *Environment) Default(_ context.Context, obj runtime.Object) error { + return nil +} + +// user: change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-fission-io-v1-environment,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=environments,verbs=create,versions=v1,name=venvironment.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &Environment{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Environment) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.Environment) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Environment but got a %T", obj)) + } + environmentlog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Environment) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.Environment) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Environment but got a %T", newObj)) + } + environmentlog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Environment) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +func (r *Environment) validate(_ *v1.Environment, new *v1.Environment) error { + if err := new.Validate(); err != nil { + err = v1.AggregateValidationErrors("Environment", err) + return err + } + return nil +} diff --git a/pkg/webhook/function.go b/pkg/webhook/function.go new file mode 100644 index 00000000..691c7642 --- /dev/null +++ b/pkg/webhook/function.go @@ -0,0 +1,104 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + v1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/utils/loggerfactory" +) + +type Function struct{} + +// log is for logging in this package. +var functionlog = loggerfactory.GetLogger().Named("function-resource") + +func (r *Function) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&v1.Function{}). + WithDefaulter(r). + WithValidator(r). + Complete() +} + +// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-function,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=functions,verbs=create;update,versions=v1,name=mfunction.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &Function{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *Function) Default(_ context.Context, obj runtime.Object) error { + return nil +} + +// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-fission-io-v1-function,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=functions,verbs=create;update,versions=v1,name=vfunction.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &Function{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Function) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.Function) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Function but got a %T", obj)) + } + functionlog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Function) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.Function) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Function but got a %T", newObj)) + } + functionlog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Function) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +func (r *Function) validate(_ *v1.Function, new *v1.Function) error { + for _, cnfMap := range new.Spec.ConfigMaps { + if cnfMap.Namespace != new.Namespace { + err := fmt.Errorf("ConfigMap's [%s] and function's Namespace [%s] are different. ConfigMap needs to be present in the same namespace as function", cnfMap.Namespace, new.Namespace) + return v1.AggregateValidationErrors("Function", err) + } + } + for _, secret := range new.Spec.Secrets { + if secret.Namespace != new.Namespace { + err := fmt.Errorf("secret [%s] and function's Namespace [%s] are different. Secret needs to be present in the same namespace as function", secret.Namespace, new.Namespace) + return v1.AggregateValidationErrors("Function", err) + } + } + + if err := new.Validate(); err != nil { + return v1.AggregateValidationErrors("Function", err) + } + return nil +} diff --git a/pkg/webhook/httptrigger.go b/pkg/webhook/httptrigger.go new file mode 100644 index 00000000..70d55446 --- /dev/null +++ b/pkg/webhook/httptrigger.go @@ -0,0 +1,91 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + v1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/utils/loggerfactory" +) + +type HTTPTrigger struct{} + +// log is for logging in this package. +var httptriggerlog = loggerfactory.GetLogger().Named("httptrigger-resource") + +func (r *HTTPTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&v1.HTTPTrigger{}). + WithDefaulter(r). + WithValidator(r). + Complete() +} + +// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-httptrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=httptriggers,verbs=create;update,versions=v1,name=mhttptrigger.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &HTTPTrigger{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *HTTPTrigger) Default(_ context.Context, obj runtime.Object) error { + return nil +} + +// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-fission-io-v1-httptrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=httptriggers,verbs=create;update,versions=v1,name=vhttptrigger.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &HTTPTrigger{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *HTTPTrigger) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.HTTPTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a HTTPTrigger but got a %T", obj)) + } + httptriggerlog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *HTTPTrigger) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.HTTPTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a HTTPTrigger but got a %T", newObj)) + } + httptriggerlog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *HTTPTrigger) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +func (r *HTTPTrigger) validate(_ *v1.HTTPTrigger, new *v1.HTTPTrigger) error { + if err := new.Validate(); err != nil { + return v1.AggregateValidationErrors("HTTPTrigger", err) + } + return nil +} diff --git a/pkg/webhook/kuberneteswatchtrigger.go b/pkg/webhook/kuberneteswatchtrigger.go new file mode 100644 index 00000000..a4351c3f --- /dev/null +++ b/pkg/webhook/kuberneteswatchtrigger.go @@ -0,0 +1,91 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + v1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/utils/loggerfactory" +) + +type KubernetesWatchTrigger struct{} + +// log is for logging in this package. +var kuberneteswatchtriggerlog = loggerfactory.GetLogger().Named("kuberneteswatchtrigger-resource") + +func (r *KubernetesWatchTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&v1.KubernetesWatchTrigger{}). + WithDefaulter(r). + WithValidator(r). + Complete() +} + +// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-kuberneteswatchtrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=kuberneteswatchtriggers,verbs=create;update,versions=v1,name=mkuberneteswatchtrigger.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &KubernetesWatchTrigger{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *KubernetesWatchTrigger) Default(_ context.Context, obj runtime.Object) error { + return nil +} + +// user: change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-fission-io-v1-kuberneteswatchtrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=kuberneteswatchtriggers,verbs=create,versions=v1,name=vkuberneteswatchtrigger.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &KubernetesWatchTrigger{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *KubernetesWatchTrigger) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.KubernetesWatchTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a KubernetesWatchTrigger but got a %T", obj)) + } + kuberneteswatchtriggerlog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *KubernetesWatchTrigger) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.KubernetesWatchTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a KubernetesWatchTrigger but got a %T", newObj)) + } + kuberneteswatchtriggerlog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *KubernetesWatchTrigger) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +func (r *KubernetesWatchTrigger) validate(_ *v1.KubernetesWatchTrigger, new *v1.KubernetesWatchTrigger) error { + if err := new.Validate(); err != nil { + return v1.AggregateValidationErrors("Watch", err) + } + return nil +} diff --git a/pkg/apis/core/v1/messagequeuetrigger_webhook.go b/pkg/webhook/messagequeuetrigger.go similarity index 51% rename from pkg/apis/core/v1/messagequeuetrigger_webhook.go rename to pkg/webhook/messagequeuetrigger.go index 9a14ca8a..ac172695 100644 --- a/pkg/apis/core/v1/messagequeuetrigger_webhook.go +++ b/pkg/webhook/messagequeuetrigger.go @@ -14,65 +14,78 @@ See the License for the specific language governing permissions and limitations under the License. */ -package v1 +package webhook import ( + "context" + "fmt" + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" "k8s.io/apimachinery/pkg/runtime" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/utils/loggerfactory" ) +type MessageQueueTrigger struct{} + // log is for logging in this package. var messagequeuetriggerlog = loggerfactory.GetLogger().Named("messagequeuetrigger-resource") func (r *MessageQueueTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { return ctrl.NewWebhookManagedBy(mgr). - For(r). + For(&v1.MessageQueueTrigger{}). + WithDefaulter(r). + WithValidator(r). Complete() } // Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-messagequeuetrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=messagequeuetriggers,verbs=create;update,versions=v1,name=mmessagequeuetrigger.fission.io,admissionReviewVersions=v1 -var _ webhook.Defaulter = &MessageQueueTrigger{} +var _ webhook.CustomDefaulter = &MessageQueueTrigger{} -// Default implements webhook.Defaulter so a webhook will be registered for the type -func (r *MessageQueueTrigger) Default() { - messagequeuetriggerlog.Debug("default", zap.String("name", r.Name)) +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *MessageQueueTrigger) Default(_ context.Context, obj runtime.Object) error { + return nil } // user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. //+kubebuilder:webhook:path=/validate-fission-io-v1-messagequeuetrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=messagequeuetriggers,verbs=create;update,versions=v1,name=vmessagequeuetrigger.fission.io,admissionReviewVersions=v1 -var _ webhook.Validator = &MessageQueueTrigger{} +var _ webhook.CustomValidator = &MessageQueueTrigger{} -// ValidateCreate implements webhook.Validator so a webhook will be registered for the type -func (r *MessageQueueTrigger) ValidateCreate() (admission.Warnings, error) { - messagequeuetriggerlog.Debug("validate create", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("MessageQueueTrigger", err) - return nil, err +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *MessageQueueTrigger) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.MessageQueueTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MessageQueueTrigger but got a %T", obj)) } - return nil, nil + messagequeuetriggerlog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) } -// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type -func (r *MessageQueueTrigger) ValidateUpdate(old runtime.Object) (admission.Warnings, error) { - messagequeuetriggerlog.Debug("validate update", zap.String("name", r.Name)) - err := r.Validate() - if err != nil { - err = AggregateValidationErrors("MessageQueueTrigger", err) - return nil, err +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *MessageQueueTrigger) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.MessageQueueTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a MessageQueueTrigger but got a %T", newObj)) } + messagequeuetriggerlog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *MessageQueueTrigger) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { return nil, nil } -// ValidateDelete implements webhook.Validator so a webhook will be registered for the type -func (r *MessageQueueTrigger) ValidateDelete() (admission.Warnings, error) { - messagequeuetriggerlog.Debug("validate delete", zap.String("name", r.Name)) - return nil, nil +func (r *MessageQueueTrigger) validate(_ *v1.MessageQueueTrigger, new *v1.MessageQueueTrigger) error { + if err := new.Validate(); err != nil { + return v1.AggregateValidationErrors("MessageQueueTrigger", err) + } + return nil } diff --git a/pkg/webhook/package.go b/pkg/webhook/package.go new file mode 100644 index 00000000..777ccd47 --- /dev/null +++ b/pkg/webhook/package.go @@ -0,0 +1,121 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + "github.com/dustin/go-humanize" + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + v1 "github.com/fission/fission/pkg/apis/core/v1" + ferror "github.com/fission/fission/pkg/error" + "github.com/fission/fission/pkg/utils/loggerfactory" +) + +type Package struct{} + +// log is for logging in this package. +var packagelog = loggerfactory.GetLogger().Named("package-resource") + +func (r *Package) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&v1.Package{}). + WithDefaulter(r). + WithValidator(r). + Complete() +} + +//+kubebuilder:webhook:path=/mutate-fission-io-v1-package,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=packages,verbs=create;update,versions=v1,name=mpackage.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &Package{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *Package) Default(_ context.Context, obj runtime.Object) error { + new, ok := obj.(*v1.Package) + if !ok { + return apierrors.NewBadRequest(fmt.Sprintf("expected a Package but got a %T", obj)) + } + packagelog.Debug("default", zap.String("name", new.Name)) + if new.Status.BuildStatus == "" { + if !new.Spec.Deployment.IsEmpty() { + // deployment package exists + new.Status.BuildStatus = v1.BuildStatusNone + } else if !new.Spec.Source.IsEmpty() { + // source package with no deployment is a pending build + new.Status.BuildStatus = v1.BuildStatusPending + } else { + new.Status.BuildStatus = v1.BuildStatusFailed // empty package + new.Status.BuildLog = "Both source and deployment are empty" + } + } + return nil +} + +// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-fission-io-v1-package,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=packages,verbs=create;update,versions=v1,name=vpackage.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &Package{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Package) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.Package) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Package but got a %T", obj)) + } + packagelog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Package) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.Package) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a Package but got a %T", newObj)) + } + packagelog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *Package) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +func (r *Package) validate(_ *v1.Package, new *v1.Package) error { + err := new.Validate() + if err != nil { + return v1.AggregateValidationErrors("Package", err) + } + + // Ensure size limits + if len(new.Spec.Source.Literal) > int(v1.ArchiveLiteralSizeLimit) { + return ferror.MakeError(ferror.ErrorInvalidArgument, + fmt.Sprintf("Package literal larger than %s", humanize.Bytes(uint64(v1.ArchiveLiteralSizeLimit)))) + } + if len(new.Spec.Deployment.Literal) > int(v1.ArchiveLiteralSizeLimit) { + return ferror.MakeError(ferror.ErrorInvalidArgument, + fmt.Sprintf("Package literal larger than %s", humanize.Bytes(uint64(v1.ArchiveLiteralSizeLimit)))) + } + return nil +} diff --git a/pkg/webhook/admission-webhook.go b/pkg/webhook/service.go similarity index 91% rename from pkg/webhook/admission-webhook.go rename to pkg/webhook/service.go index 3f956190..bb57a255 100644 --- a/pkg/webhook/admission-webhook.go +++ b/pkg/webhook/service.go @@ -33,7 +33,6 @@ import ( metricsserver "sigs.k8s.io/controller-runtime/pkg/metrics/server" "sigs.k8s.io/controller-runtime/pkg/webhook" - v1 "github.com/fission/fission/pkg/apis/core/v1" "github.com/fission/fission/pkg/crd" "github.com/fission/fission/pkg/generated/clientset/versioned/scheme" //+kubebuilder:scaffold:imports @@ -78,14 +77,14 @@ func Start(ctx context.Context, clientGen crd.ClientGeneratorInterface, logger * // Setup webhooks webhookInjectors := []WebhookInjector{ - &v1.CanaryConfig{}, - &v1.Environment{}, - &v1.Package{}, - &v1.Function{}, - &v1.HTTPTrigger{}, - &v1.MessageQueueTrigger{}, - &v1.TimeTrigger{}, - &v1.KubernetesWatchTrigger{}, + &CanaryConfig{}, + &Environment{}, + &Package{}, + &Function{}, + &HTTPTrigger{}, + &MessageQueueTrigger{}, + &TimeTrigger{}, + &KubernetesWatchTrigger{}, } for _, injector := range webhookInjectors { diff --git a/pkg/webhook/timetrigger.go b/pkg/webhook/timetrigger.go new file mode 100644 index 00000000..8cfdf55f --- /dev/null +++ b/pkg/webhook/timetrigger.go @@ -0,0 +1,92 @@ +/* +Copyright 2022. + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. +*/ + +package webhook + +import ( + "context" + "fmt" + + "go.uber.org/zap" + apierrors "k8s.io/apimachinery/pkg/api/errors" + "k8s.io/apimachinery/pkg/runtime" + ctrl "sigs.k8s.io/controller-runtime" + "sigs.k8s.io/controller-runtime/pkg/webhook" + "sigs.k8s.io/controller-runtime/pkg/webhook/admission" + + v1 "github.com/fission/fission/pkg/apis/core/v1" + "github.com/fission/fission/pkg/utils/loggerfactory" +) + +type TimeTrigger struct{} + +// log is for logging in this package. +var timetriggerlog = loggerfactory.GetLogger().Named("timetrigger-resource") + +func (r *TimeTrigger) SetupWebhookWithManager(mgr ctrl.Manager) error { + return ctrl.NewWebhookManagedBy(mgr). + For(&v1.TimeTrigger{}). + WithDefaulter(r). + WithValidator(r). + Complete() +} + +// Admission webhooks can be added by adding tag: kubebuilder:webhook:path=/mutate-fission-io-v1-timetrigger,mutating=true,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=timetriggers,verbs=create;update,versions=v1,name=mtimetrigger.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomDefaulter = &TimeTrigger{} + +// Default implements webhook.CustomDefaulter so a webhook will be registered for the type +func (r *TimeTrigger) Default(_ context.Context, obj runtime.Object) error { + return nil +} + +// user change verbs to "verbs=create;update;delete" if you want to enable deletion validation. +//+kubebuilder:webhook:path=/validate-fission-io-v1-timetrigger,mutating=false,failurePolicy=fail,sideEffects=None,groups=fission.io,resources=timetriggers,verbs=create;update,versions=v1,name=vtimetrigger.fission.io,admissionReviewVersions=v1 + +var _ webhook.CustomValidator = &TimeTrigger{} + +// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *TimeTrigger) ValidateCreate(_ context.Context, obj runtime.Object) (admission.Warnings, error) { + new, ok := obj.(*v1.TimeTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a TimeTrigger but got a %T", obj)) + } + timetriggerlog.Debug("validate create", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type +func (r *TimeTrigger) ValidateUpdate(_ context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) { + new, ok := newObj.(*v1.TimeTrigger) + if !ok { + return nil, apierrors.NewBadRequest(fmt.Sprintf("expected a TimeTrigger but got a %T", newObj)) + } + timetriggerlog.Debug("validate update", zap.String("name", new.Name)) + return nil, r.validate(nil, new) +} + +// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type +func (r *TimeTrigger) ValidateDelete(_ context.Context, _ runtime.Object) (admission.Warnings, error) { + return nil, nil +} + +func (r *TimeTrigger) validate(_ *v1.TimeTrigger, new *v1.TimeTrigger) error { + if err := new.Validate(); err != nil { + return v1.AggregateValidationErrors("TimeTrigger", err) + } + + return nil +}