Skip to content

Commit 9205bab

Browse files
committed
refactor(defaulting webhook): breaking the original interface instead of introducing new interface
Signed-off-by: STRRL <[email protected]>
1 parent 7d1e860 commit 9205bab

File tree

7 files changed

+195
-619
lines changed

7 files changed

+195
-619
lines changed

pkg/webhook/admission/admissiontest/util.go

Lines changed: 10 additions & 54 deletions
Original file line numberDiff line numberDiff line change
@@ -25,86 +25,42 @@ import (
2525
// It implements the admission.Validator interface and
2626
// rejects all requests with the same configured error
2727
// or passes if ErrorToReturn is nil.
28+
// And it would always return configured warning messages WarningsToReturn.
2829
type FakeValidator struct {
2930
// ErrorToReturn is the error for which the FakeValidator rejects all requests
3031
ErrorToReturn error `json:"errorToReturn,omitempty"`
3132
// GVKToReturn is the GroupVersionKind that the webhook operates on
3233
GVKToReturn schema.GroupVersionKind
33-
}
34-
35-
// ValidateCreate implements admission.Validator.
36-
func (v *FakeValidator) ValidateCreate() error {
37-
return v.ErrorToReturn
38-
}
39-
40-
// ValidateUpdate implements admission.Validator.
41-
func (v *FakeValidator) ValidateUpdate(old runtime.Object) error {
42-
return v.ErrorToReturn
43-
}
44-
45-
// ValidateDelete implements admission.Validator.
46-
func (v *FakeValidator) ValidateDelete() error {
47-
return v.ErrorToReturn
48-
}
49-
50-
// GetObjectKind implements admission.Validator.
51-
func (v *FakeValidator) GetObjectKind() schema.ObjectKind { return v }
52-
53-
// DeepCopyObject implements admission.Validator.
54-
func (v *FakeValidator) DeepCopyObject() runtime.Object {
55-
return &FakeValidator{ErrorToReturn: v.ErrorToReturn, GVKToReturn: v.GVKToReturn}
56-
}
57-
58-
// GroupVersionKind implements admission.Validator.
59-
func (v *FakeValidator) GroupVersionKind() schema.GroupVersionKind {
60-
return v.GVKToReturn
61-
}
62-
63-
// SetGroupVersionKind implements admission.Validator.
64-
func (v *FakeValidator) SetGroupVersionKind(gvk schema.GroupVersionKind) {
65-
v.GVKToReturn = gvk
66-
}
67-
68-
// FakeValidatorWarn provides fake validating webhook functionality for testing
69-
// It implements the admission.ValidatorWarn interface and
70-
// rejects all requests with the same configured error
71-
// or passes if ErrorToReturn is nil.
72-
// And it would always return configured warning messages WarningsToReturn.
73-
type FakeValidatorWarn struct {
74-
// ErrorToReturn is the error for which the FakeValidatorWarn rejects all requests
75-
ErrorToReturn error `json:"ErrorToReturn,omitempty"`
76-
// GVKToReturn is the GroupVersionKind that the webhook operates on
77-
GVKToReturn schema.GroupVersionKind
78-
// WarningsToReturn is the warnings for FakeValidatorWarn returns to all requests
34+
// WarningsToReturn is the warnings for FakeValidator returns to all requests
7935
WarningsToReturn []string
8036
}
8137

82-
func (v *FakeValidatorWarn) ValidateCreate() (warnings []string, err error) {
38+
func (v *FakeValidator) ValidateCreate() (warnings []string, err error) {
8339
return v.WarningsToReturn, v.ErrorToReturn
8440
}
8541

86-
func (v *FakeValidatorWarn) ValidateUpdate(old runtime.Object) (warnings []string, err error) {
42+
func (v *FakeValidator) ValidateUpdate(old runtime.Object) (warnings []string, err error) {
8743
return v.WarningsToReturn, v.ErrorToReturn
8844
}
8945

90-
func (v *FakeValidatorWarn) ValidateDelete() (warnings []string, err error) {
46+
func (v *FakeValidator) ValidateDelete() (warnings []string, err error) {
9147
return v.WarningsToReturn, v.ErrorToReturn
9248
}
9349

94-
func (v *FakeValidatorWarn) SetGroupVersionKind(kind schema.GroupVersionKind) {
50+
func (v *FakeValidator) SetGroupVersionKind(kind schema.GroupVersionKind) {
9551
v.GVKToReturn = kind
9652
}
9753

98-
func (v *FakeValidatorWarn) GroupVersionKind() schema.GroupVersionKind {
54+
func (v *FakeValidator) GroupVersionKind() schema.GroupVersionKind {
9955
return v.GVKToReturn
10056
}
10157

102-
func (v *FakeValidatorWarn) GetObjectKind() schema.ObjectKind {
58+
func (v *FakeValidator) GetObjectKind() schema.ObjectKind {
10359
return v
10460
}
10561

106-
func (v *FakeValidatorWarn) DeepCopyObject() runtime.Object {
107-
return &FakeValidatorWarn{ErrorToReturn: v.ErrorToReturn,
62+
func (v *FakeValidator) DeepCopyObject() runtime.Object {
63+
return &FakeValidator{ErrorToReturn: v.ErrorToReturn,
10864
GVKToReturn: v.GVKToReturn,
10965
WarningsToReturn: v.WarningsToReturn,
11066
}

pkg/webhook/admission/validator.go

Lines changed: 30 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@ package admission
1919
import (
2020
"context"
2121
"errors"
22+
"fmt"
2223
"net/http"
2324

2425
v1 "k8s.io/api/admission/v1"
@@ -29,9 +30,9 @@ import (
2930
// Validator defines functions for validating an operation.
3031
type Validator interface {
3132
runtime.Object
32-
ValidateCreate() error
33-
ValidateUpdate(old runtime.Object) error
34-
ValidateDelete() error
33+
ValidateCreate() ([]string, error)
34+
ValidateUpdate(old runtime.Object) ([]string, error)
35+
ValidateDelete() ([]string, error)
3536
}
3637

3738
// ValidatingWebhookFor creates a new Webhook for validating the provided type.
@@ -55,28 +56,26 @@ func (h *validatingHandler) Handle(ctx context.Context, req Request) Response {
5556
panic("validator should never be nil")
5657
}
5758

59+
ctx = NewContextWithRequest(ctx, req)
60+
5861
// Get the object in the request
5962
obj := h.validator.DeepCopyObject().(Validator)
60-
if req.Operation == v1.Create {
61-
err := h.decoder.Decode(req, obj)
62-
if err != nil {
63-
return Errored(http.StatusBadRequest, err)
64-
}
6563

66-
err = obj.ValidateCreate()
64+
var err error
65+
var warnings []string
66+
67+
switch req.Operation {
68+
case v1.Create:
69+
err = h.decoder.Decode(req, obj)
6770
if err != nil {
68-
var apiStatus apierrors.APIStatus
69-
if errors.As(err, &apiStatus) {
70-
return validationResponseFromStatus(false, apiStatus.Status())
71-
}
72-
return Denied(err.Error())
71+
return Errored(http.StatusBadRequest, err)
7372
}
74-
}
7573

76-
if req.Operation == v1.Update {
74+
warnings, err = obj.ValidateCreate()
75+
case v1.Update:
7776
oldObj := obj.DeepCopyObject()
7877

79-
err := h.decoder.DecodeRaw(req.Object, obj)
78+
err = h.decoder.DecodeRaw(req.Object, obj)
8079
if err != nil {
8180
return Errored(http.StatusBadRequest, err)
8281
}
@@ -85,33 +84,26 @@ func (h *validatingHandler) Handle(ctx context.Context, req Request) Response {
8584
return Errored(http.StatusBadRequest, err)
8685
}
8786

88-
err = obj.ValidateUpdate(oldObj)
89-
if err != nil {
90-
var apiStatus apierrors.APIStatus
91-
if errors.As(err, &apiStatus) {
92-
return validationResponseFromStatus(false, apiStatus.Status())
93-
}
94-
return Denied(err.Error())
95-
}
96-
}
97-
98-
if req.Operation == v1.Delete {
87+
warnings, err = obj.ValidateUpdate(oldObj)
88+
case v1.Delete:
9989
// In reference to PR: https://github.com/kubernetes/kubernetes/pull/76346
10090
// OldObject contains the object being deleted
101-
err := h.decoder.DecodeRaw(req.OldObject, obj)
91+
err = h.decoder.DecodeRaw(req.OldObject, obj)
10292
if err != nil {
10393
return Errored(http.StatusBadRequest, err)
10494
}
10595

106-
err = obj.ValidateDelete()
107-
if err != nil {
108-
var apiStatus apierrors.APIStatus
109-
if errors.As(err, &apiStatus) {
110-
return validationResponseFromStatus(false, apiStatus.Status())
111-
}
112-
return Denied(err.Error())
113-
}
96+
warnings, err = obj.ValidateDelete()
97+
default:
98+
return Errored(http.StatusBadRequest, fmt.Errorf("unknown operation request %q", req.Operation))
11499
}
115100

116-
return Allowed("")
101+
if err != nil {
102+
var apiStatus apierrors.APIStatus
103+
if errors.As(err, &apiStatus) {
104+
return validationResponseFromStatus(false, apiStatus.Status())
105+
}
106+
return Denied(err.Error()).WithWarnings(warnings...)
107+
}
108+
return Allowed("").WithWarnings(warnings...)
117109
}

pkg/webhook/admission/validator_custom.go

Lines changed: 10 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,9 @@ import (
2929

3030
// CustomValidator defines functions for validating an operation.
3131
type CustomValidator interface {
32-
ValidateCreate(ctx context.Context, obj runtime.Object) error
33-
ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) error
34-
ValidateDelete(ctx context.Context, obj runtime.Object) error
32+
ValidateCreate(ctx context.Context, obj runtime.Object) ([]string, error)
33+
ValidateUpdate(ctx context.Context, oldObj, newObj runtime.Object) ([]string, error)
34+
ValidateDelete(ctx context.Context, obj runtime.Object) ([]string, error)
3535
}
3636

3737
// WithCustomValidator creates a new Webhook for validating the provided type.
@@ -65,6 +65,8 @@ func (h *validatorForType) Handle(ctx context.Context, req Request) Response {
6565
obj := h.object.DeepCopyObject()
6666

6767
var err error
68+
var warnings []string
69+
6870
switch req.Operation {
6971
case v1.Connect:
7072
// No validation for connect requests.
@@ -74,7 +76,7 @@ func (h *validatorForType) Handle(ctx context.Context, req Request) Response {
7476
return Errored(http.StatusBadRequest, err)
7577
}
7678

77-
err = h.validator.ValidateCreate(ctx, obj)
79+
warnings, err = h.validator.ValidateCreate(ctx, obj)
7880
case v1.Update:
7981
oldObj := obj.DeepCopyObject()
8082
if err := h.decoder.DecodeRaw(req.Object, obj); err != nil {
@@ -84,15 +86,15 @@ func (h *validatorForType) Handle(ctx context.Context, req Request) Response {
8486
return Errored(http.StatusBadRequest, err)
8587
}
8688

87-
err = h.validator.ValidateUpdate(ctx, oldObj, obj)
89+
warnings, err = h.validator.ValidateUpdate(ctx, oldObj, obj)
8890
case v1.Delete:
8991
// In reference to PR: https://github.com/kubernetes/kubernetes/pull/76346
9092
// OldObject contains the object being deleted
9193
if err := h.decoder.DecodeRaw(req.OldObject, obj); err != nil {
9294
return Errored(http.StatusBadRequest, err)
9395
}
9496

95-
err = h.validator.ValidateDelete(ctx, obj)
97+
warnings, err = h.validator.ValidateDelete(ctx, obj)
9698
default:
9799
return Errored(http.StatusBadRequest, fmt.Errorf("unknown operation request %q", req.Operation))
98100
}
@@ -103,9 +105,9 @@ func (h *validatorForType) Handle(ctx context.Context, req Request) Response {
103105
if errors.As(err, &apiStatus) {
104106
return validationResponseFromStatus(false, apiStatus.Status())
105107
}
106-
return Denied(err.Error())
108+
return Denied(err.Error()).WithWarnings(warnings...)
107109
}
108110

109111
// Return allowed if everything succeeded.
110-
return Allowed("")
112+
return Allowed("").WithWarnings(warnings...)
111113
}

0 commit comments

Comments
 (0)