Skip to content

Commit

Permalink
Allow to wire an object mutation handler
Browse files Browse the repository at this point in the history
  • Loading branch information
alculquicondor committed Aug 23, 2024
1 parent e6c3d13 commit 922ee77
Show file tree
Hide file tree
Showing 2 changed files with 51 additions and 25 deletions.
39 changes: 23 additions & 16 deletions pkg/builder/webhook.go
Original file line number Diff line number Diff line change
Expand Up @@ -37,6 +37,7 @@ import (
// WebhookBuilder builds a Webhook.
type WebhookBuilder struct {
apiType runtime.Object
mutationHandler admission.ObjectHandler
customDefaulter admission.CustomDefaulter
customValidator admission.CustomValidator
gvk schema.GroupVersionKind
Expand Down Expand Up @@ -65,6 +66,12 @@ func (blder *WebhookBuilder) For(apiType runtime.Object) *WebhookBuilder {
return blder
}

// WithMutationHandler takes an admission.ObjectHandler interface, a MutatingWebhook will be wired for this type.
func (blder *WebhookBuilder) WithMutationHandler(handler admission.ObjectHandler) *WebhookBuilder {
blder.mutationHandler = handler
return blder
}

// WithDefaulter takes an admission.CustomDefaulter interface, a MutatingWebhook will be wired for this type.
func (blder *WebhookBuilder) WithDefaulter(defaulter admission.CustomDefaulter) *WebhookBuilder {
blder.customDefaulter = defaulter
Expand Down Expand Up @@ -169,24 +176,24 @@ func (blder *WebhookBuilder) registerDefaultingWebhook() {
}

func (blder *WebhookBuilder) getDefaultingWebhook() *admission.Webhook {
if defaulter := blder.customDefaulter; defaulter != nil {
w := admission.WithCustomDefaulter(blder.mgr.GetScheme(), blder.apiType, defaulter)
if blder.recoverPanic != nil {
w = w.WithRecoverPanic(*blder.recoverPanic)
}
return w
var w *admission.Webhook
if handler := blder.mutationHandler; handler != nil {
w = admission.WithObjectHandler(blder.mgr.GetScheme(), blder.apiType, handler)
} else if defaulter := blder.customDefaulter; defaulter != nil {
w = admission.WithCustomDefaulter(blder.mgr.GetScheme(), blder.apiType, defaulter)
} else if defaulter, ok := blder.apiType.(admission.Defaulter); ok {
w = admission.DefaultingWebhookFor(blder.mgr.GetScheme(), defaulter)
}
if defaulter, ok := blder.apiType.(admission.Defaulter); ok {
w := admission.DefaultingWebhookFor(blder.mgr.GetScheme(), defaulter)
if blder.recoverPanic != nil {
w = w.WithRecoverPanic(*blder.recoverPanic)
}
return w
if w == nil {
log.Info(
"Skip registering a mutating webhook, object does not implement admission.Defaulter or WithDefaulter wasn't called",
"GVK", blder.gvk)
return nil
}
log.Info(
"skip registering a mutating webhook, object does not implement admission.Defaulter or WithDefaulter wasn't called",
"GVK", blder.gvk)
return nil
if blder.recoverPanic != nil {
w = w.WithRecoverPanic(*blder.recoverPanic)
}
return w
}

// registerValidatingWebhook registers a validating webhook if necessary.
Expand Down
37 changes: 28 additions & 9 deletions pkg/webhook/admission/defaulter_custom.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,18 @@ import (
"k8s.io/apimachinery/pkg/runtime"
)

// ObjectHandler defines functions for handling objects on webhooks.
type ObjectHandler interface {
Handle(ctx context.Context, raw []byte, obj runtime.Object) Response
}

// WithObjectHandler creates a new Webhook for an ObjectHandler interface.
func WithObjectHandler(scheme *runtime.Scheme, obj runtime.Object, handler ObjectHandler) *Webhook {
return &Webhook{
Handler: &handlerForType{object: obj, handler: handler, decoder: NewDecoder(scheme)},
}
}

// CustomDefaulter defines functions for setting defaults on resources.
type CustomDefaulter interface {
Default(ctx context.Context, obj runtime.Object) error
Expand All @@ -36,22 +48,22 @@ type CustomDefaulter interface {
// WithCustomDefaulter creates a new Webhook for a CustomDefaulter interface.
func WithCustomDefaulter(scheme *runtime.Scheme, obj runtime.Object, defaulter CustomDefaulter) *Webhook {
return &Webhook{
Handler: &defaulterForType{object: obj, defaulter: defaulter, decoder: NewDecoder(scheme)},
Handler: &handlerForType{object: obj, handler: &handlerForDefaulter{defaulter: defaulter}, decoder: NewDecoder(scheme)},
}
}

type defaulterForType struct {
defaulter CustomDefaulter
object runtime.Object
decoder Decoder
type handlerForType struct {
handler ObjectHandler
object runtime.Object
decoder Decoder
}

// Handle handles admission requests.
func (h *defaulterForType) Handle(ctx context.Context, req Request) Response {
func (h *handlerForType) Handle(ctx context.Context, req Request) Response {
if h.decoder == nil {
panic("decoder should never be nil")
}
if h.defaulter == nil {
if h.handler == nil {
panic("defaulter should never be nil")
}
if h.object == nil {
Expand All @@ -76,7 +88,14 @@ func (h *defaulterForType) Handle(ctx context.Context, req Request) Response {
return Errored(http.StatusBadRequest, err)
}

// Default the object
return h.handler.Handle(ctx, req.Object.Raw, obj)
}

type handlerForDefaulter struct {
defaulter CustomDefaulter
}

func (h *handlerForDefaulter) Handle(ctx context.Context, raw []byte, obj runtime.Object) Response {
if err := h.defaulter.Default(ctx, obj); err != nil {
var apiStatus apierrors.APIStatus
if errors.As(err, &apiStatus) {
Expand All @@ -90,5 +109,5 @@ func (h *defaulterForType) Handle(ctx context.Context, req Request) Response {
if err != nil {
return Errored(http.StatusInternalServerError, err)
}
return PatchResponseFromRaw(req.Object.Raw, marshalled)
return PatchResponseFromRaw(raw, marshalled)
}

0 comments on commit 922ee77

Please sign in to comment.