...
1
16
17 package admission
18
19 import (
20 "context"
21 "encoding/json"
22 "errors"
23 "net/http"
24
25 admissionv1 "k8s.io/api/admission/v1"
26 apierrors "k8s.io/apimachinery/pkg/api/errors"
27 metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28 "k8s.io/apimachinery/pkg/runtime"
29 )
30
31
32 type CustomDefaulter interface {
33 Default(ctx context.Context, obj runtime.Object) error
34 }
35
36
37 func WithCustomDefaulter(scheme *runtime.Scheme, obj runtime.Object, defaulter CustomDefaulter) *Webhook {
38 return &Webhook{
39 Handler: &defaulterForType{object: obj, defaulter: defaulter, decoder: NewDecoder(scheme)},
40 }
41 }
42
43 type defaulterForType struct {
44 defaulter CustomDefaulter
45 object runtime.Object
46 decoder Decoder
47 }
48
49
50 func (h *defaulterForType) Handle(ctx context.Context, req Request) Response {
51 if h.decoder == nil {
52 panic("decoder should never be nil")
53 }
54 if h.defaulter == nil {
55 panic("defaulter should never be nil")
56 }
57 if h.object == nil {
58 panic("object should never be nil")
59 }
60
61
62 if req.Operation == admissionv1.Delete {
63 return Response{AdmissionResponse: admissionv1.AdmissionResponse{
64 Allowed: true,
65 Result: &metav1.Status{
66 Code: http.StatusOK,
67 },
68 }}
69 }
70
71 ctx = NewContextWithRequest(ctx, req)
72
73
74 obj := h.object.DeepCopyObject()
75 if err := h.decoder.Decode(req, obj); err != nil {
76 return Errored(http.StatusBadRequest, err)
77 }
78
79
80 if err := h.defaulter.Default(ctx, obj); err != nil {
81 var apiStatus apierrors.APIStatus
82 if errors.As(err, &apiStatus) {
83 return validationResponseFromStatus(false, apiStatus.Status())
84 }
85 return Denied(err.Error())
86 }
87
88
89 marshalled, err := json.Marshal(obj)
90 if err != nil {
91 return Errored(http.StatusInternalServerError, err)
92 }
93 return PatchResponseFromRaw(req.Object.Raw, marshalled)
94 }
95
View as plain text