@@ -19,11 +19,17 @@ package admission
1919import (
2020 "context"
2121 "net/http"
22+ "errors"
2223
2324 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
2425 "sigs.k8s.io/controller-runtime/pkg/runtime/inject"
2526 "github.com/appscode/jsonpatch"
2627 admissionv1beta1 "k8s.io/api/admission/v1beta1"
28+ "k8s.io/apimachinery/pkg/util/json"
29+ )
30+
31+ var (
32+ unableToEncodeResponse = errors .New ("unable to encode response" )
2733)
2834
2935// Request defines the input for an admission handler.
@@ -43,12 +49,44 @@ type Response struct {
4349 // Patches are the JSON patches for mutating webhooks.
4450 // Using this instead of setting Response.Patch to minimize
4551 // overhead of serialization and deserialization.
52+ // Patches set here will override any patches in the response,
53+ // so leave this empty if you want to set the patch response directly.
4654 Patches []jsonpatch.JsonPatchOperation
4755 // AdmissionResponse is the raw admission response.
4856 // The Patch field in it will be overwritten by the listed patches.
4957 admissionv1beta1.AdmissionResponse
5058}
5159
60+ // Complete populates any fields that are yet to be set in
61+ // the underlying AdmissionResponse, It mutates the response.
62+ func (r * Response ) Complete (req Request ) error {
63+ r .UID = req .UID
64+
65+ // ensure that we have a valid status code
66+ if r .Result == nil {
67+ r .Result = & metav1.Status {}
68+ }
69+ if r .Result .Code == 0 {
70+ r .Result .Code = http .StatusOK
71+ }
72+ // TODO(directxman12): do we need to populate this further, and/or
73+ // is code actually necessary (the same webhook doesn't use it)
74+
75+ if len (r .Patches ) == 0 {
76+ return nil
77+ }
78+
79+ var err error
80+ r .Patch , err = json .Marshal (r .Patches )
81+ if err != nil {
82+ return err
83+ }
84+ patchType := admissionv1beta1 .PatchTypeJSONPatch
85+ r .PatchType = & patchType
86+
87+ return nil
88+ }
89+
5290// Handler can handle an AdmissionRequest.
5391type Handler interface {
5492 Handle (context.Context , Request ) Response
@@ -77,17 +115,10 @@ type Webhook struct {
77115// deny the request if anyone denies.
78116func (w * Webhook ) Handle (ctx context.Context , req Request ) Response {
79117 resp := w .Handler .Handle (ctx , req )
80- resp .UID = req .UID
81-
82- // ensure that we have a valid status code
83- if resp .Result == nil {
84- resp .Result = & metav1.Status {}
85- }
86- if resp .Result .Code == 0 {
87- resp .Result .Code = http .StatusOK
118+ if err := resp .Complete (req ); err != nil {
119+ log .Error (err , "unable to encode response" )
120+ return ErrorResponse (http .StatusInternalServerError , unableToEncodeResponse )
88121 }
89- // TODO(directxman12): do we need to populate this further, and/or
90- // is code actually necessary (the same webhook doesn't use it)
91122
92123 return resp
93124}
0 commit comments