Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

separate webhooks from the api types package #672

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
82 changes: 0 additions & 82 deletions api/v1beta1/domachinetemplate_webhook.go

This file was deleted.

2 changes: 1 addition & 1 deletion api/v1beta1/zz_generated.deepcopy.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Original file line number Diff line number Diff line change
Expand Up @@ -14,15 +14,18 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1beta1
// Package webhooks contains implementations of validating and mutating webhooks for infrastructure.cluster.x-k8s.io resources.
package webhooks

import (
"context"
"fmt"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"

"sigs.k8s.io/cluster-api-provider-digitalocean/api/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand All @@ -35,46 +38,58 @@ var _ = logf.Log.WithName("docluster-resource")
// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-docluster,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=doclusters,versions=v1beta1,name=validation.docluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-docluster,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=doclusters,versions=v1beta1,name=default.docluster.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1

// DOClusterWebhook is a collection of webhooks for DOCluster objects.
type DOClusterWebhook struct{}

var (
_ webhook.Defaulter = &DOCluster{}
_ webhook.Validator = &DOCluster{}
_ webhook.CustomDefaulter = &DOClusterWebhook{}
_ webhook.CustomValidator = &DOClusterWebhook{}
)

func (r *DOCluster) SetupWebhookWithManager(mgr ctrl.Manager) error {
func (w *DOClusterWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
For(&v1beta1.DOCluster{}).
WithDefaulter(&DOClusterWebhook{}).
WithValidator(&DOClusterWebhook{}).
Complete()
}

// Default implements webhook.Defaulter so a webhook will be registered for the type.
func (r *DOCluster) Default() {}
// Default implements webhook.CustomDefaulter so a webhook will be registered for the type.
func (w *DOClusterWebhook) Default(context.Context, runtime.Object) error {
return nil
}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
func (r *DOCluster) ValidateCreate() (admission.Warnings, error) {
// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOClusterWebhook) ValidateCreate(context.Context, runtime.Object) (admission.Warnings, error) {
return nil, nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
func (r *DOCluster) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOClusterWebhook) ValidateUpdate(_ context.Context, objOld, objNew runtime.Object) (admission.Warnings, error) {
var allErrs field.ErrorList

oldDOCluster, ok := old.(*DOCluster)
oldDOCluster, ok := objOld.(*v1beta1.DOCluster)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOCluster old object but got a %T", objOld))
}

newDOCluster, ok := objNew.(*v1beta1.DOCluster)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOCluster but got a %T", old))
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOCluster new object but got a %T", objNew))
}

if r.Spec.Region != oldDOCluster.Spec.Region {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "region"), r.Spec.Region, "field is immutable"))
if newDOCluster.Spec.Region != oldDOCluster.Spec.Region {
allErrs = append(allErrs, field.Invalid(field.NewPath("spec", "region"), newDOCluster.Spec.Region, "field is immutable"))
}

if len(allErrs) == 0 {
return nil, nil
}

return nil, apierrors.NewInvalid(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
return nil, apierrors.NewInvalid(newDOCluster.GroupVersionKind().GroupKind(), newDOCluster.Name, allErrs)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
func (r *DOCluster) ValidateDelete() (admission.Warnings, error) {
// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOClusterWebhook) ValidateDelete(context.Context, runtime.Object) (admission.Warnings, error) {
return nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,63 +14,73 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1beta1
package webhooks

import (
"context"
"fmt"
"reflect"

apierrors "k8s.io/apimachinery/pkg/api/errors"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/cluster-api-provider-digitalocean/api/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

// log is for logging in this package.
var doclustertemplatelog = logf.Log.WithName("doclustertemplate-resource")
var _ = logf.Log.WithName("doclustertemplate-resource")

func (r *DOClusterTemplate) SetupWebhookWithManager(mgr ctrl.Manager) error {
func (w *DOClusterTemplateWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
For(&v1beta1.DOClusterTemplate{}).
WithDefaulter(&DOClusterTemplateWebhook{}).
WithValidator(&DOClusterTemplateWebhook{}).
Complete()
}

//+kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-doclustertemplate,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=doclustertemplates,versions=v1beta1,name=default.doclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
//+kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-doclustertemplate,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=doclustertemplates,versions=v1beta1,name=validation.doclustertemplate.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1

var _ webhook.Defaulter = &DOClusterTemplate{}
// DOClusterTemplateWebhook is a collection of webhooks for DOClusterTemplate objects.
type DOClusterTemplateWebhook struct{}

// Default implements webhook.Defaulter so a webhook will be registered for the type.
func (r *DOClusterTemplate) Default() {
doclustertemplatelog.Info("default", "name", r.Name)
}

var _ webhook.Validator = &DOClusterTemplate{}
var (
_ webhook.CustomDefaulter = &DOClusterTemplateWebhook{}
_ webhook.CustomValidator = &DOClusterTemplateWebhook{}
)

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
func (r *DOClusterTemplate) ValidateCreate() (admission.Warnings, error) {
doclustertemplatelog.Info("validate create", "name", r.Name)
// Default implements webhook.CustomDefaulter so a webhook will be registered for the type.
func (w *DOClusterTemplateWebhook) Default(context.Context, runtime.Object) error {
return nil
}

// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOClusterTemplateWebhook) ValidateCreate(context.Context, runtime.Object) (admission.Warnings, error) {
return nil, nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
func (r *DOClusterTemplate) ValidateUpdate(oldRaw runtime.Object) (admission.Warnings, error) {
old, ok := oldRaw.(*DOClusterTemplate)
// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOClusterTemplateWebhook) ValidateUpdate(_ context.Context, objOld, objNew runtime.Object) (admission.Warnings, error) {
oldTemplate, ok := objOld.(*v1beta1.DOClusterTemplate)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOClusterTemplate old object but got a %T", objOld))
}

newTemplate, ok := objNew.(*v1beta1.DOClusterTemplate)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOClusterTemplate but got a %T", oldRaw))
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOClusterTemplate new object but got a %T", objNew))
}

if !reflect.DeepEqual(r.Spec, old.Spec) {
if !reflect.DeepEqual(newTemplate.Spec, oldTemplate.Spec) {
return nil, apierrors.NewBadRequest("DOClusterTemplate.Spec is immutable")
}
return nil, nil
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
func (r *DOClusterTemplate) ValidateDelete() (admission.Warnings, error) {
doclustertemplatelog.Info("validate delete", "name", r.Name)
// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOClusterTemplateWebhook) ValidateDelete(context.Context, runtime.Object) (admission.Warnings, error) {
return nil, nil
}
Original file line number Diff line number Diff line change
Expand Up @@ -14,9 +14,11 @@ See the License for the specific language governing permissions and
limitations under the License.
*/

package v1beta1
package webhooks

import (
"context"
"fmt"
"reflect"

"github.com/pkg/errors"
Expand All @@ -25,6 +27,7 @@ import (
runtime "k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/util/validation/field"

"sigs.k8s.io/cluster-api-provider-digitalocean/api/v1beta1"
ctrl "sigs.k8s.io/controller-runtime"
logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook"
Expand All @@ -37,41 +40,53 @@ var _ = logf.Log.WithName("domachine-resource")
// +kubebuilder:webhook:verbs=create;update,path=/validate-infrastructure-cluster-x-k8s-io-v1beta1-domachine,mutating=false,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=domachines,versions=v1beta1,name=validation.domachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1
// +kubebuilder:webhook:verbs=create;update,path=/mutate-infrastructure-cluster-x-k8s-io-v1beta1-domachine,mutating=true,failurePolicy=fail,matchPolicy=Equivalent,groups=infrastructure.cluster.x-k8s.io,resources=domachines,versions=v1beta1,name=default.domachine.infrastructure.cluster.x-k8s.io,sideEffects=None,admissionReviewVersions=v1beta1

// DOMachineWebhook is a collection of webhooks for DOMachine objects.
type DOMachineWebhook struct{}

var (
_ webhook.Defaulter = &DOMachine{}
_ webhook.Validator = &DOMachine{}
_ webhook.CustomDefaulter = &DOMachineWebhook{}
_ webhook.CustomValidator = &DOMachineWebhook{}
)

func (r *DOMachine) SetupWebhookWithManager(mgr ctrl.Manager) error {
func (w *DOMachineWebhook) SetupWebhookWithManager(mgr ctrl.Manager) error {
return ctrl.NewWebhookManagedBy(mgr).
For(r).
For(&v1beta1.DOMachine{}).
WithDefaulter(&DOMachineWebhook{}).
WithValidator(&DOMachineWebhook{}).
Complete()
}

// Default implements webhook.Defaulter so a webhook will be registered for the type.
func (r *DOMachine) Default() {}
// Default implements webhook.CustomDefaulter so a webhook will be registered for the type.
func (w *DOMachineWebhook) Default(context.Context, runtime.Object) error {
return nil
}

// ValidateCreate implements webhook.Validator so a webhook will be registered for the type.
func (r *DOMachine) ValidateCreate() (admission.Warnings, error) {
// ValidateCreate implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOMachineWebhook) ValidateCreate(context.Context, runtime.Object) (admission.Warnings, error) {
return nil, nil
}

// ValidateUpdate implements webhook.Validator so a webhook will be registered for the type.
func (r *DOMachine) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
// ValidateUpdate implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOMachineWebhook) ValidateUpdate(_ context.Context, objOld, objNew runtime.Object) (admission.Warnings, error) {
var allErrs field.ErrorList

newDOMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(r)
newDOMachine, ok := objNew.(*v1beta1.DOMachine)
if !ok {
return nil, apierrors.NewBadRequest(fmt.Sprintf("expected an DOMachine new object but got a %T", objNew))
}

newDOMachineUnstr, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objNew)
if err != nil {
return nil, apierrors.NewInternalError(errors.Wrap(err, "failed to convert new DOMachine to unstructured object"))
}

oldDOMachine, err := runtime.DefaultUnstructuredConverter.ToUnstructured(old)
oldDOMachineUnstr, err := runtime.DefaultUnstructuredConverter.ToUnstructured(objOld)
if err != nil {
return nil, apierrors.NewInternalError(errors.Wrap(err, "failed to convert old DOMachine to unstructured object"))
}

newDOMachineSpec := newDOMachine["spec"].(map[string]interface{})
oldDOMachineSpec := oldDOMachine["spec"].(map[string]interface{})
newDOMachineSpec := newDOMachineUnstr["spec"].(map[string]interface{})
oldDOMachineSpec := oldDOMachineUnstr["spec"].(map[string]interface{})

// allow changes to providerID
delete(oldDOMachineSpec, "providerID")
Expand All @@ -89,10 +104,10 @@ func (r *DOMachine) ValidateUpdate(old runtime.Object) (admission.Warnings, erro
return nil, nil
}

return nil, apierrors.NewInvalid(r.GroupVersionKind().GroupKind(), r.Name, allErrs)
return nil, apierrors.NewInvalid(newDOMachine.GroupVersionKind().GroupKind(), newDOMachine.Name, allErrs)
}

// ValidateDelete implements webhook.Validator so a webhook will be registered for the type.
func (r *DOMachine) ValidateDelete() (admission.Warnings, error) {
// ValidateDelete implements webhook.CustomValidator so a webhook will be registered for the type.
func (w *DOMachineWebhook) ValidateDelete(context.Context, runtime.Object) (admission.Warnings, error) {
return nil, nil
}
Loading