package webhook import ( "context" "net/http" admissionv1 "k8s.io/api/admission/v1" ctrl "sigs.k8s.io/controller-runtime" "sigs.k8s.io/controller-runtime/pkg/webhook/admission" ) var validatingHandlerLog = ctrl.Log.WithName("validating_handler") var _ admission.DecoderInjector = &validatingHandler{} var _ admission.Handler = &validatingHandler{} type validatingHandler struct { validator Validator decoder *admission.Decoder } // InjectDecoder injects the decoder into a mutatingHandler. func (h *validatingHandler) InjectDecoder(d *admission.Decoder) error { h.decoder = d return nil } // Handle handles admission requests. func (h *validatingHandler) Handle(ctx context.Context, req admission.Request) admission.Response { validatingHandlerLog.V(1).Info("validating webhook request", "request", req) var resp admission.Response switch req.Operation { case admissionv1.Create: resp = h.handleCreate(ctx, req) case admissionv1.Update: resp = h.handleUpdate(ctx, req) case admissionv1.Delete: resp = h.handleDelete(ctx, req) default: resp = admission.Allowed("") } validatingHandlerLog.V(1).Info("validating webhook response", "response", resp) return resp } func (h *validatingHandler) handleCreate(ctx context.Context, req admission.Request) admission.Response { prototype, err := h.validator.Prototype(req) if err != nil { return admission.Errored(http.StatusBadRequest, err) } obj := prototype.DeepCopyObject() if err := h.decoder.DecodeRaw(req.Object, obj); err != nil { return admission.Errored(http.StatusBadRequest, err) } if err := h.validator.ValidateCreate(ContextWithAdmissionRequest(ctx, req), obj); err != nil { return admission.Denied(err.Error()) } return admission.Allowed("") } func (h *validatingHandler) handleUpdate(ctx context.Context, req admission.Request) admission.Response { prototype, err := h.validator.Prototype(req) if err != nil { return admission.Errored(http.StatusBadRequest, err) } obj := prototype.DeepCopyObject() oldObj := prototype.DeepCopyObject() if err := h.decoder.DecodeRaw(req.Object, obj); err != nil { return admission.Errored(http.StatusBadRequest, err) } if err := h.decoder.DecodeRaw(req.OldObject, oldObj); err != nil { return admission.Errored(http.StatusBadRequest, err) } if err := h.validator.ValidateUpdate(ContextWithAdmissionRequest(ctx, req), obj, oldObj); err != nil { return admission.Denied(err.Error()) } return admission.Allowed("") } func (h *validatingHandler) handleDelete(ctx context.Context, req admission.Request) admission.Response { prototype, err := h.validator.Prototype(req) if err != nil { return admission.Errored(http.StatusBadRequest, err) } obj := prototype.DeepCopyObject() if err := h.decoder.DecodeRaw(req.OldObject, obj); err != nil { return admission.Errored(http.StatusBadRequest, err) } if err := h.validator.ValidateDelete(ContextWithAdmissionRequest(ctx, req), obj); err != nil { return admission.Denied(err.Error()) } return admission.Allowed("") }