Skip to content

Commit a375c55

Browse files
Simplify design and error on multiple mutation mechanisms
1 parent ea977b9 commit a375c55

File tree

3 files changed

+50
-31
lines changed

3 files changed

+50
-31
lines changed

pkg/builder/webhook.go

Lines changed: 25 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -37,7 +37,7 @@ import (
3737
// WebhookBuilder builds a Webhook.
3838
type WebhookBuilder struct {
3939
apiType runtime.Object
40-
mutatorFactory admission.HandlerFactory
40+
mutationHandler admission.Handler
4141
customDefaulter admission.CustomDefaulter
4242
customValidator admission.CustomValidator
4343
gvk schema.GroupVersionKind
@@ -66,9 +66,9 @@ func (blder *WebhookBuilder) For(apiType runtime.Object) *WebhookBuilder {
6666
return blder
6767
}
6868

69-
// WithMutatorFactory takes an admission.HandlerFactory, a MutatingWebhook will be wired for the handler that this factory creates.
70-
func (blder *WebhookBuilder) WithMutatorFactory(factory admission.HandlerFactory) *WebhookBuilder {
71-
blder.mutatorFactory = factory
69+
// WithMutationHandler takes an admission.Handler, a MutatingWebhook will be wired for it.
70+
func (blder *WebhookBuilder) WithMutationHandler(h admission.Handler) *WebhookBuilder {
71+
blder.mutationHandler = h
7272
return blder
7373
}
7474

@@ -147,7 +147,9 @@ func (blder *WebhookBuilder) registerWebhooks() error {
147147
}
148148

149149
// Register webhook(s) for type
150-
blder.registerDefaultingWebhook()
150+
if err := blder.registerDefaultingWebhook(); err != nil {
151+
return err
152+
}
151153
blder.registerValidatingWebhook()
152154

153155
err = blder.registerConversionWebhook()
@@ -158,8 +160,11 @@ func (blder *WebhookBuilder) registerWebhooks() error {
158160
}
159161

160162
// registerDefaultingWebhook registers a defaulting webhook if necessary.
161-
func (blder *WebhookBuilder) registerDefaultingWebhook() {
162-
mwh := blder.getDefaultingWebhook()
163+
func (blder *WebhookBuilder) registerDefaultingWebhook() error {
164+
mwh, err := blder.getDefaultingWebhook()
165+
if err != nil {
166+
return err
167+
}
163168
if mwh != nil {
164169
mwh.LogConstructor = blder.logConstructor
165170
path := generateMutatePath(blder.gvk)
@@ -173,21 +178,27 @@ func (blder *WebhookBuilder) registerDefaultingWebhook() {
173178
blder.mgr.GetWebhookServer().Register(path, mwh)
174179
}
175180
}
181+
return nil
176182
}
177183

178-
func (blder *WebhookBuilder) getDefaultingWebhook() *admission.Webhook {
184+
func (blder *WebhookBuilder) getDefaultingWebhook() (*admission.Webhook, error) {
179185
var w *admission.Webhook
180-
if factory := blder.mutatorFactory; factory != nil {
181-
w = admission.WithHandlerFactory(blder.mgr.GetScheme(), blder.apiType, factory)
182-
} else if defaulter := blder.customDefaulter; defaulter != nil {
186+
if handler := blder.mutationHandler; handler != nil {
187+
w = &admission.Webhook{Handler: handler}
188+
}
189+
if defaulter := blder.customDefaulter; defaulter != nil {
190+
if w != nil {
191+
return nil, errors.New("a WebhookBuilder can only define a MutationHandler or a Defaulter, but not both")
192+
}
183193
w = admission.WithCustomDefaulter(blder.mgr.GetScheme(), blder.apiType, defaulter)
184-
} else {
185-
return nil
194+
}
195+
if w == nil {
196+
return nil, nil
186197
}
187198
if blder.recoverPanic != nil {
188199
w = w.WithRecoverPanic(*blder.recoverPanic)
189200
}
190-
return w
201+
return w, nil
191202
}
192203

193204
// registerValidatingWebhook registers a validating webhook if necessary.

pkg/builder/webhook_test.go

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,12 @@ import (
3030
. "github.com/onsi/ginkgo/v2"
3131
. "github.com/onsi/gomega"
3232
"github.com/onsi/gomega/gbytes"
33+
"gomodules.xyz/jsonpatch/v2"
34+
admissionv1 "k8s.io/api/admission/v1"
3335
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
3436
"k8s.io/apimachinery/pkg/runtime"
3537
"k8s.io/apimachinery/pkg/runtime/schema"
38+
"k8s.io/utils/ptr"
3639

3740
logf "sigs.k8s.io/controller-runtime/pkg/log"
3841
"sigs.k8s.io/controller-runtime/pkg/log/zap"
@@ -229,8 +232,8 @@ func runTests(admissionReviewVersion string) {
229232
ExpectWithOffset(1, err).NotTo(HaveOccurred())
230233

231234
err = WebhookManagedBy(m).
232-
WithMutatorFactory(mutatorFactoryForTestDefaulter(m.GetScheme())).
233235
For(&TestDefaulter{}).
236+
WithMutationHandler(&TestMutationHandler{}).
234237
WithLogConstructor(func(base logr.Logger, req *admission.Request) logr.Logger {
235238
return admission.DefaultLogConstructor(testingLogger, req)
236239
}).
@@ -280,7 +283,7 @@ func runTests(admissionReviewVersion string) {
280283
ExpectWithOffset(1, w.Body).To(ContainSubstring(`"allowed":true`))
281284
ExpectWithOffset(1, w.Body).To(ContainSubstring(`"patch":`))
282285
ExpectWithOffset(1, w.Body).To(ContainSubstring(`"code":200`))
283-
EventuallyWithOffset(1, logBuffer).Should(gbytes.Say(`"msg":"Defaulting object","object":{"name":"foo","namespace":"default"},"namespace":"default","name":"foo","resource":{"group":"foo.test.org","version":"v1","resource":"testdefaulter"},"user":"","requestID":"07e52e8d-4513-11e9-a716-42010a800270"`))
286+
EventuallyWithOffset(1, logBuffer).Should(gbytes.Say(`"msg":"Mutating object","object":{"name":"foo","namespace":"default"},"namespace":"default","name":"foo","resource":{"group":"foo.test.org","version":"v1","resource":"testdefaulter"},"user":"","requestID":"07e52e8d-4513-11e9-a716-42010a800270"`))
284287

285288
By("sending a request to a validating webhook path that doesn't exist")
286289
path = generateValidatePath(testDefaulterGVK)
@@ -646,7 +649,8 @@ func (*TestDefaultValidatorList) DeepCopyObject() runtime.Object { return nil
646649
type TestCustomDefaulter struct{}
647650

648651
func (*TestCustomDefaulter) Default(ctx context.Context, obj runtime.Object) error {
649-
logf.FromContext(ctx).Info("Defaulting object")
652+
log := logf.FromContext(ctx)
653+
log.Info("Defaulting object")
650654
req, err := admission.RequestFromContext(ctx)
651655
if err != nil {
652656
return fmt.Errorf("expected admission.Request in ctx: %w", err)
@@ -668,12 +672,27 @@ func (*TestCustomDefaulter) Default(ctx context.Context, obj runtime.Object) err
668672

669673
var _ admission.CustomDefaulter = &TestCustomDefaulter{}
670674

671-
func mutatorFactoryForTestDefaulter(scheme *runtime.Scheme) admission.HandlerFactory {
672-
return func(obj runtime.Object, _ admission.Decoder) admission.Handler {
673-
return admission.WithCustomDefaulter(scheme, obj, &TestCustomDefaulter{}).Handler
675+
// TestMutationHandler
676+
type TestMutationHandler struct{}
677+
678+
func (*TestMutationHandler) Handle(ctx context.Context, req admission.Request) admission.Response {
679+
log := logf.FromContext(ctx)
680+
log.Info("Mutating object")
681+
return admission.Response{
682+
AdmissionResponse: admissionv1.AdmissionResponse{
683+
Allowed: true,
684+
PatchType: ptr.To(admissionv1.PatchTypeJSONPatch),
685+
},
686+
Patches: []jsonpatch.Operation{{
687+
Operation: "replace",
688+
Path: "/replica",
689+
Value: "2",
690+
}},
674691
}
675692
}
676693

694+
var _ admission.Handler = &TestMutationHandler{}
695+
677696
// TestCustomValidator.
678697

679698
type TestCustomValidator struct{}

pkg/webhook/admission/webhook.go

Lines changed: 0 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,6 @@ import (
2727
"gomodules.xyz/jsonpatch/v2"
2828
admissionv1 "k8s.io/api/admission/v1"
2929
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
30-
"k8s.io/apimachinery/pkg/runtime"
3130
"k8s.io/apimachinery/pkg/util/json"
3231
utilruntime "k8s.io/apimachinery/pkg/util/runtime"
3332
"k8s.io/klog/v2"
@@ -96,9 +95,6 @@ func (r *Response) Complete(req Request) error {
9695
return nil
9796
}
9897

99-
// HandlerFactory can create a Handler for the given type.
100-
type HandlerFactory func(obj runtime.Object, decoder Decoder) Handler
101-
10298
// Handler can handle an AdmissionRequest.
10399
type Handler interface {
104100
// Handle yields a response to an AdmissionRequest.
@@ -118,13 +114,6 @@ func (f HandlerFunc) Handle(ctx context.Context, req Request) Response {
118114
return f(ctx, req)
119115
}
120116

121-
// WithHandlerFactory creates a new Webhook for a handler factory.
122-
func WithHandlerFactory(scheme *runtime.Scheme, obj runtime.Object, factory HandlerFactory) *Webhook {
123-
return &Webhook{
124-
Handler: factory(obj, NewDecoder(scheme)),
125-
}
126-
}
127-
128117
// Webhook represents each individual webhook.
129118
//
130119
// It must be registered with a webhook.Server or

0 commit comments

Comments
 (0)