From d4693e2cd7e355a834d0896dad31030cfcf97c22 Mon Sep 17 00:00:00 2001 From: Solly Ross Date: Wed, 13 Feb 2019 22:04:21 -0800 Subject: [PATCH] fixup! Extract out multi-handler support, remove builder --- pkg/webhook/admission/webhook.go | 51 +++++++++++++++++++++++++------- 1 file changed, 41 insertions(+), 10 deletions(-) diff --git a/pkg/webhook/admission/webhook.go b/pkg/webhook/admission/webhook.go index 8a610d3597..1036ef11f3 100644 --- a/pkg/webhook/admission/webhook.go +++ b/pkg/webhook/admission/webhook.go @@ -19,11 +19,17 @@ package admission import ( "context" "net/http" + "errors" metav1 "k8s.io/apimachinery/pkg/apis/meta/v1" "sigs.k8s.io/controller-runtime/pkg/runtime/inject" "github.com/appscode/jsonpatch" admissionv1beta1 "k8s.io/api/admission/v1beta1" + "k8s.io/apimachinery/pkg/util/json" +) + +var ( + unableToEncodeResponse = errors.New("unable to encode response") ) // Request defines the input for an admission handler. @@ -43,12 +49,44 @@ type Response struct { // Patches are the JSON patches for mutating webhooks. // Using this instead of setting Response.Patch to minimize // overhead of serialization and deserialization. + // Patches set here will override any patches in the response, + // so leave this empty if you want to set the patch response directly. Patches []jsonpatch.JsonPatchOperation // AdmissionResponse is the raw admission response. // The Patch field in it will be overwritten by the listed patches. admissionv1beta1.AdmissionResponse } +// Complete populates any fields that are yet to be set in +// the underlying AdmissionResponse, It mutates the response. +func (r *Response) Complete(req Request) error { + r.UID = req.UID + + // ensure that we have a valid status code + if r.Result == nil { + r.Result = &metav1.Status{} + } + if r.Result.Code == 0 { + r.Result.Code = http.StatusOK + } + // TODO(directxman12): do we need to populate this further, and/or + // is code actually necessary (the same webhook doesn't use it) + + if len(r.Patches) == 0 { + return nil + } + + var err error + r.Patch, err = json.Marshal(r.Patches) + if err != nil { + return err + } + patchType := admissionv1beta1.PatchTypeJSONPatch + r.PatchType = &patchType + + return nil +} + // Handler can handle an AdmissionRequest. type Handler interface { Handle(context.Context, Request) Response @@ -77,17 +115,10 @@ type Webhook struct { // deny the request if anyone denies. func (w *Webhook) Handle(ctx context.Context, req Request) Response { resp := w.Handler.Handle(ctx, req) - resp.UID = req.UID - - // ensure that we have a valid status code - if resp.Result == nil { - resp.Result = &metav1.Status{} - } - if resp.Result.Code == 0 { - resp.Result.Code = http.StatusOK + if err := resp.Complete(req); err != nil { + log.Error(err, "unable to encode response") + return ErrorResponse(http.StatusInternalServerError, unableToEncodeResponse) } - // TODO(directxman12): do we need to populate this further, and/or - // is code actually necessary (the same webhook doesn't use it) return resp }