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

⚠️ feat: new features about support warning with webhook #2014

Merged
merged 13 commits into from Apr 19, 2023
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.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
17 changes: 9 additions & 8 deletions examples/builtins/validatingwebhook.go
Expand Up @@ -24,6 +24,7 @@ import (
"k8s.io/apimachinery/pkg/runtime"

logf "sigs.k8s.io/controller-runtime/pkg/log"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

// +kubebuilder:webhook:path=/validate-v1-pod,mutating=false,failurePolicy=fail,groups="",resources=pods,verbs=create;update,versions=v1,name=vpod.kb.io
Expand All @@ -32,34 +33,34 @@ import (
type podValidator struct{}

// validate admits a pod if a specific annotation exists.
func (v *podValidator) validate(ctx context.Context, obj runtime.Object) error {
func (v *podValidator) validate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
log := logf.FromContext(ctx)
pod, ok := obj.(*corev1.Pod)
if !ok {
return fmt.Errorf("expected a Pod but got a %T", obj)
return nil, fmt.Errorf("expected a Pod but got a %T", obj)
}

log.Info("Validating Pod")
key := "example-mutating-admission-webhook"
anno, found := pod.Annotations[key]
if !found {
return fmt.Errorf("missing annotation %s", key)
return nil, fmt.Errorf("missing annotation %s", key)
}
if anno != "foo" {
return fmt.Errorf("annotation %s did not have value %q", key, "foo")
return nil, fmt.Errorf("annotation %s did not have value %q", key, "foo")
}

return nil
return nil, nil
}

func (v *podValidator) ValidateCreate(ctx context.Context, obj runtime.Object) error {
func (v *podValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
return v.validate(ctx, obj)
}

func (v *podValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error {
func (v *podValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
return v.validate(ctx, newObj)
}

func (v *podValidator) ValidateDelete(ctx context.Context, obj runtime.Object) error {
func (v *podValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
return v.validate(ctx, obj)
}
23 changes: 12 additions & 11 deletions examples/crd/pkg/resource.go
Expand Up @@ -24,6 +24,7 @@ import (
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
"k8s.io/apimachinery/pkg/runtime"
"sigs.k8s.io/controller-runtime/pkg/webhook"
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
)

// ChaosPodSpec defines the desired state of ChaosPod
Expand Down Expand Up @@ -66,41 +67,41 @@ type ChaosPodList struct {
var _ webhook.Validator = &ChaosPod{}

// ValidateCreate implements webhookutil.validator so a webhook will be registered for the type
func (c *ChaosPod) ValidateCreate() error {
func (c *ChaosPod) ValidateCreate() (admission.Warnings, error) {
log.Info("validate create", "name", c.Name)

if c.Spec.NextStop.Before(&metav1.Time{Time: time.Now()}) {
return fmt.Errorf(".spec.nextStop must be later than current time")
return nil, fmt.Errorf(".spec.nextStop must be later than current time")
}
return nil
return nil, nil
}

// ValidateUpdate implements webhookutil.validator so a webhook will be registered for the type
func (c *ChaosPod) ValidateUpdate(old runtime.Object) error {
func (c *ChaosPod) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
log.Info("validate update", "name", c.Name)

if c.Spec.NextStop.Before(&metav1.Time{Time: time.Now()}) {
return fmt.Errorf(".spec.nextStop must be later than current time")
return nil, fmt.Errorf(".spec.nextStop must be later than current time")
}

oldC, ok := old.(*ChaosPod)
if !ok {
return fmt.Errorf("expect old object to be a %T instead of %T", oldC, old)
return nil, fmt.Errorf("expect old object to be a %T instead of %T", oldC, old)
}
if c.Spec.NextStop.After(oldC.Spec.NextStop.Add(time.Hour)) {
return fmt.Errorf("it is not allowed to delay.spec.nextStop for more than 1 hour")
return nil, fmt.Errorf("it is not allowed to delay.spec.nextStop for more than 1 hour")
}
return nil
return nil, nil
}

// ValidateDelete implements webhookutil.validator so a webhook will be registered for the type
func (c *ChaosPod) ValidateDelete() error {
func (c *ChaosPod) ValidateDelete() (admission.Warnings, error) {
log.Info("validate delete", "name", c.Name)

if c.Spec.NextStop.Before(&metav1.Time{Time: time.Now()}) {
return fmt.Errorf(".spec.nextStop must be later than current time")
return nil, fmt.Errorf(".spec.nextStop must be later than current time")
}
return nil
return nil, nil
}

// +kubebuilder:webhook:path=/mutate-chaosapps-metamagical-io-v1-chaospod,mutating=true,failurePolicy=fail,groups=chaosapps.metamagical.io,resources=chaospods,verbs=create;update,versions=v1,name=mchaospod.kb.io
Expand Down
72 changes: 36 additions & 36 deletions pkg/builder/webhook_test.go
Expand Up @@ -749,39 +749,39 @@ func (*TestValidatorList) DeepCopyObject() runtime.Object { return nil }

var _ admission.Validator = &TestValidator{}

func (v *TestValidator) ValidateCreate() error {
func (v *TestValidator) ValidateCreate() (admission.Warnings, error) {
if v.Panic {
panic("fake panic test")
}
if v.Replica < 0 {
return errors.New("number of replica should be greater than or equal to 0")
return nil, errors.New("number of replica should be greater than or equal to 0")
}
return nil
return nil, nil
}

func (v *TestValidator) ValidateUpdate(old runtime.Object) error {
func (v *TestValidator) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
if v.Panic {
panic("fake panic test")
}
if v.Replica < 0 {
return errors.New("number of replica should be greater than or equal to 0")
return nil, errors.New("number of replica should be greater than or equal to 0")
}
if oldObj, ok := old.(*TestValidator); !ok {
return fmt.Errorf("the old object is expected to be %T", oldObj)
return nil, fmt.Errorf("the old object is expected to be %T", oldObj)
} else if v.Replica < oldObj.Replica {
return fmt.Errorf("new replica %v should not be fewer than old replica %v", v.Replica, oldObj.Replica)
return nil, fmt.Errorf("new replica %v should not be fewer than old replica %v", v.Replica, oldObj.Replica)
}
return nil
return nil, nil
}

func (v *TestValidator) ValidateDelete() error {
func (v *TestValidator) ValidateDelete() (admission.Warnings, error) {
if v.Panic {
panic("fake panic test")
}
if v.Replica > 0 {
return errors.New("number of replica should be less than or equal to 0 to delete")
return nil, errors.New("number of replica should be less than or equal to 0 to delete")
}
return nil
return nil, nil
}

// TestDefaultValidator.
Expand Down Expand Up @@ -824,25 +824,25 @@ func (dv *TestDefaultValidator) Default() {

var _ admission.Validator = &TestDefaultValidator{}

func (dv *TestDefaultValidator) ValidateCreate() error {
func (dv *TestDefaultValidator) ValidateCreate() (admission.Warnings, error) {
if dv.Replica < 0 {
return errors.New("number of replica should be greater than or equal to 0")
return nil, errors.New("number of replica should be greater than or equal to 0")
}
return nil
return nil, nil
}

func (dv *TestDefaultValidator) ValidateUpdate(old runtime.Object) error {
func (dv *TestDefaultValidator) ValidateUpdate(old runtime.Object) (admission.Warnings, error) {
if dv.Replica < 0 {
return errors.New("number of replica should be greater than or equal to 0")
return nil, errors.New("number of replica should be greater than or equal to 0")
}
return nil
return nil, nil
}

func (dv *TestDefaultValidator) ValidateDelete() error {
func (dv *TestDefaultValidator) ValidateDelete() (admission.Warnings, error) {
if dv.Replica > 0 {
return errors.New("number of replica should be less than or equal to 0 to delete")
return nil, errors.New("number of replica should be less than or equal to 0 to delete")
}
return nil
return nil, nil
}

// TestCustomDefaulter.
Expand Down Expand Up @@ -872,59 +872,59 @@ var _ admission.CustomDefaulter = &TestCustomDefaulter{}

type TestCustomValidator struct{}

func (*TestCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) error {
func (*TestCustomValidator) ValidateCreate(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
logf.FromContext(ctx).Info("Validating object")
req, err := admission.RequestFromContext(ctx)
if err != nil {
return fmt.Errorf("expected admission.Request in ctx: %w", err)
return nil, fmt.Errorf("expected admission.Request in ctx: %w", err)
}
if req.Kind.Kind != testValidatorKind {
return fmt.Errorf("expected Kind TestValidator got %q", req.Kind.Kind)
return nil, fmt.Errorf("expected Kind TestValidator got %q", req.Kind.Kind)
}

v := obj.(*TestValidator) //nolint:ifshort
if v.Replica < 0 {
return errors.New("number of replica should be greater than or equal to 0")
return nil, errors.New("number of replica should be greater than or equal to 0")
}
return nil
return nil, nil
}

func (*TestCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error {
func (*TestCustomValidator) ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) (admission.Warnings, error) {
logf.FromContext(ctx).Info("Validating object")
req, err := admission.RequestFromContext(ctx)
if err != nil {
return fmt.Errorf("expected admission.Request in ctx: %w", err)
return nil, fmt.Errorf("expected admission.Request in ctx: %w", err)
}
if req.Kind.Kind != testValidatorKind {
return fmt.Errorf("expected Kind TestValidator got %q", req.Kind.Kind)
return nil, fmt.Errorf("expected Kind TestValidator got %q", req.Kind.Kind)
}

v := newObj.(*TestValidator)
old := oldObj.(*TestValidator)
if v.Replica < 0 {
return errors.New("number of replica should be greater than or equal to 0")
return nil, errors.New("number of replica should be greater than or equal to 0")
}
if v.Replica < old.Replica {
return fmt.Errorf("new replica %v should not be fewer than old replica %v", v.Replica, old.Replica)
return nil, fmt.Errorf("new replica %v should not be fewer than old replica %v", v.Replica, old.Replica)
}
return nil
return nil, nil
}

func (*TestCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) error {
func (*TestCustomValidator) ValidateDelete(ctx context.Context, obj runtime.Object) (admission.Warnings, error) {
logf.FromContext(ctx).Info("Validating object")
req, err := admission.RequestFromContext(ctx)
if err != nil {
return fmt.Errorf("expected admission.Request in ctx: %w", err)
return nil, fmt.Errorf("expected admission.Request in ctx: %w", err)
}
if req.Kind.Kind != testValidatorKind {
return fmt.Errorf("expected Kind TestValidator got %q", req.Kind.Kind)
return nil, fmt.Errorf("expected Kind TestValidator got %q", req.Kind.Kind)
}

v := obj.(*TestValidator) //nolint:ifshort
if v.Replica > 0 {
return errors.New("number of replica should be less than or equal to 0 to delete")
return nil, errors.New("number of replica should be less than or equal to 0 to delete")
}
return nil
return nil, nil
}

var _ admission.CustomValidator = &TestCustomValidator{}
18 changes: 0 additions & 18 deletions pkg/webhook/admission/admissiontest/doc.go

This file was deleted.

66 changes: 0 additions & 66 deletions pkg/webhook/admission/admissiontest/util.go

This file was deleted.