Skip to content

Commit e6f429a

Browse files
author
Mengqi Yu
committed
inject client and decoder for webhook
1 parent 7ee3ea2 commit e6f429a

File tree

17 files changed

+171
-83
lines changed

17 files changed

+171
-83
lines changed

example/main.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -81,7 +81,8 @@ func main() {
8181
Operations(admissionregistrationv1beta1.Create, admissionregistrationv1beta1.Update).
8282
WithManager(mgr).
8383
ForType(&corev1.Pod{}).
84-
Build(&podAnnotator{client: mgr.GetClient(), decoder: mgr.GetAdmissionDecoder()})
84+
Handlers(&podAnnotator{}).
85+
Build()
8586
if err != nil {
8687
entryLog.Error(err, "unable to setup mutating webhook")
8788
os.Exit(1)
@@ -94,7 +95,8 @@ func main() {
9495
Operations(admissionregistrationv1beta1.Create, admissionregistrationv1beta1.Update).
9596
WithManager(mgr).
9697
ForType(&corev1.Pod{}).
97-
Build(&podValidator{client: mgr.GetClient(), decoder: mgr.GetAdmissionDecoder()})
98+
Handlers(&podValidator{}).
99+
Build()
98100
if err != nil {
99101
entryLog.Error(err, "unable to setup validating webhook")
100102
os.Exit(1)

example/mutatingwebhook.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@ import (
2424
corev1 "k8s.io/api/core/v1"
2525
"sigs.k8s.io/controller-runtime/pkg/client"
2626
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
27+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
2728
)
2829

2930
// podAnnotator annotates Pods
3031
type podAnnotator struct {
3132
client client.Client
32-
decoder admission.Decoder
33+
decoder types.Decoder
3334
}
3435

3536
// Implement admission.Handler so the controller can handle admission request.
3637
var _ admission.Handler = &podAnnotator{}
3738

3839
// podAnnotator adds an annotation to every incoming pods.
39-
func (a *podAnnotator) Handle(ctx context.Context, req admission.Request) admission.Response {
40+
func (a *podAnnotator) Handle(ctx context.Context, req types.Request) types.Response {
4041
pod := &corev1.Pod{}
4142

4243
err := a.decoder.Decode(req, pod)

example/validatingwebhook.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,19 +24,20 @@ import (
2424
corev1 "k8s.io/api/core/v1"
2525
"sigs.k8s.io/controller-runtime/pkg/client"
2626
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
27+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
2728
)
2829

2930
// podValidator validates Pods
3031
type podValidator struct {
3132
client client.Client
32-
decoder admission.Decoder
33+
decoder types.Decoder
3334
}
3435

3536
// Implement admission.Handler so the controller can handle admission request.
3637
var _ admission.Handler = &podValidator{}
3738

3839
// podValidator admits a pod iff a specific annotation exists.
39-
func (v *podValidator) Handle(ctx context.Context, req admission.Request) admission.Response {
40+
func (v *podValidator) Handle(ctx context.Context, req types.Request) types.Response {
4041
pod := &corev1.Pod{}
4142

4243
err := v.decoder.Decode(req, pod)

pkg/manager/internal.go

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,7 +28,7 @@ import (
2828
"sigs.k8s.io/controller-runtime/pkg/recorder"
2929
"sigs.k8s.io/controller-runtime/pkg/runtime/inject"
3030
logf "sigs.k8s.io/controller-runtime/pkg/runtime/log"
31-
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
31+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
3232
)
3333

3434
var log = logf.KBLog.WithName("manager")
@@ -41,7 +41,7 @@ type controllerManager struct {
4141
// to scheme.scheme.
4242
scheme *runtime.Scheme
4343
// admissionDecoder is used to decode an admission.Request.
44-
admissionDecoder admission.Decoder
44+
admissionDecoder types.Decoder
4545

4646
// runnables is the set of Controllers that the controllerManager injects deps into and Starts.
4747
runnables []Runnable
@@ -112,6 +112,9 @@ func (cm *controllerManager) SetFields(i interface{}) error {
112112
if _, err := inject.StopChannelInto(cm.stop, i); err != nil {
113113
return err
114114
}
115+
if _, err := inject.DecoderInto(cm.admissionDecoder, i); err != nil {
116+
return err
117+
}
115118
return nil
116119
}
117120

@@ -127,7 +130,7 @@ func (cm *controllerManager) GetScheme() *runtime.Scheme {
127130
return cm.scheme
128131
}
129132

130-
func (cm *controllerManager) GetAdmissionDecoder() admission.Decoder {
133+
func (cm *controllerManager) GetAdmissionDecoder() types.Decoder {
131134
return cm.admissionDecoder
132135
}
133136

pkg/manager/manager.go

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"time"
2222

2323
"github.com/go-logr/logr"
24+
2425
"k8s.io/apimachinery/pkg/api/meta"
2526
"k8s.io/apimachinery/pkg/runtime"
2627
"k8s.io/client-go/kubernetes/scheme"
@@ -32,6 +33,7 @@ import (
3233
internalrecorder "sigs.k8s.io/controller-runtime/pkg/internal/recorder"
3334
"sigs.k8s.io/controller-runtime/pkg/recorder"
3435
"sigs.k8s.io/controller-runtime/pkg/webhook/admission"
36+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
3537
)
3638

3739
// Manager initializes shared dependencies such as Caches and Clients, and provides them to Runnables.
@@ -57,7 +59,7 @@ type Manager interface {
5759
GetScheme() *runtime.Scheme
5860

5961
// GetAdmissionDecoder returns the runtime.Decoder based on the scheme.
60-
GetAdmissionDecoder() admission.Decoder
62+
GetAdmissionDecoder() types.Decoder
6163

6264
// GetClient returns a client configured with the Config
6365
GetClient() client.Client
@@ -94,7 +96,7 @@ type Options struct {
9496
newCache func(config *rest.Config, opts cache.Options) (cache.Cache, error)
9597
newClient func(config *rest.Config, options client.Options) (client.Client, error)
9698
newRecorderProvider func(config *rest.Config, scheme *runtime.Scheme, logger logr.Logger) (recorder.Provider, error)
97-
newAdmissionDecoder func(scheme *runtime.Scheme) (admission.Decoder, error)
99+
newAdmissionDecoder func(scheme *runtime.Scheme) (types.Decoder, error)
98100
}
99101

100102
// Runnable allows a component to be started.

pkg/runtime/inject/inject.go

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"k8s.io/client-go/rest"
2222
"sigs.k8s.io/controller-runtime/pkg/cache"
2323
"sigs.k8s.io/controller-runtime/pkg/client"
24+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
2425
)
2526

2627
// Cache is used by the ControllerManager to inject Cache into Sources, EventHandlers, Predicates, and
@@ -59,15 +60,29 @@ type Client interface {
5960
InjectClient(client.Client) error
6061
}
6162

62-
// ClientInto will set client on i and return the result if it implements client. Returns
63-
//// false if i does not implement client.
63+
// ClientInto will set client on i and return the result if it implements Client. Returns
64+
// false if i does not implement Client.
6465
func ClientInto(client client.Client, i interface{}) (bool, error) {
6566
if s, ok := i.(Client); ok {
6667
return true, s.InjectClient(client)
6768
}
6869
return false, nil
6970
}
7071

72+
// Decoder is used by the ControllerManager to inject decoder into webhook handlers.
73+
type Decoder interface {
74+
InjectDecoder(types.Decoder) error
75+
}
76+
77+
// DecoderInto will set decoder on i and return the result if it implements Decoder. Returns
78+
// false if i does not implement Decoder.
79+
func DecoderInto(decoder types.Decoder, i interface{}) (bool, error) {
80+
if s, ok := i.(Decoder); ok {
81+
return true, s.InjectDecoder(decoder)
82+
}
83+
return false, nil
84+
}
85+
7186
// Scheme is used by the ControllerManager to inject Scheme into Sources, EventHandlers, Predicates, and
7287
// Reconciles
7388
type Scheme interface {

pkg/webhook/admission/builder/builder.go

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -31,14 +31,17 @@ import (
3131

3232
// WebhookBuilder builds a webhook based on the provided options.
3333
type WebhookBuilder struct {
34-
// Name specifies the Name of the webhook. It must be unique in the http
34+
// name specifies the Name of the webhook. It must be unique in the http
3535
// server that serves all the webhooks.
3636
name string
3737

38-
// Path is the URL Path to register this webhook. e.g. "/feature-foo-mutating-pods".
38+
// path is the URL Path to register this webhook. e.g. "/feature-foo-mutating-pods".
3939
path string
4040

41-
// Type specifies the type of the webhook
41+
// handlers are handlers for handling admission request.
42+
handlers []admission.Handler
43+
44+
// t specifies the type of the webhook
4245
t *types.WebhookType
4346
// only one of operations and Rules can be set.
4447
operations []admissionregistrationv1beta1.OperationType
@@ -128,6 +131,12 @@ func (b *WebhookBuilder) WithManager(mgr manager.Manager) *WebhookBuilder {
128131
return b
129132
}
130133

134+
// Handlers sets the handlers of the webhook.
135+
func (b *WebhookBuilder) Handlers(handlers ...admission.Handler) *WebhookBuilder {
136+
b.handlers = handlers
137+
return b
138+
}
139+
131140
func (b *WebhookBuilder) validate() error {
132141
if b.t == nil {
133142
return errors.New("webhook type cannot be nil")
@@ -142,7 +151,7 @@ func (b *WebhookBuilder) validate() error {
142151
}
143152

144153
// Build creates the Webhook based on the options provided.
145-
func (b *WebhookBuilder) Build(handlers ...admission.Handler) (*admission.Webhook, error) {
154+
func (b *WebhookBuilder) Build() (*admission.Webhook, error) {
146155
err := b.validate()
147156
if err != nil {
148157
return nil, err
@@ -153,7 +162,7 @@ func (b *WebhookBuilder) Build(handlers ...admission.Handler) (*admission.Webhoo
153162
Type: *b.t,
154163
FailurePolicy: b.failurePolicy,
155164
NamespaceSelector: b.namespaceSelector,
156-
Handlers: handlers,
165+
Handlers: b.handlers,
157166
}
158167

159168
if len(b.path) == 0 {

pkg/webhook/admission/decode.go

Lines changed: 6 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -19,21 +19,16 @@ package admission
1919
import (
2020
"k8s.io/apimachinery/pkg/runtime"
2121
"k8s.io/apimachinery/pkg/runtime/serializer"
22+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
2223
)
2324

24-
// Decoder is used to decode AdmissionRequest.
25-
type Decoder interface {
26-
// Decode decodes the raw byte object from the AdmissionRequest to the passed-in runtime.Object.
27-
Decode(Request, runtime.Object) error
28-
}
29-
3025
// DecodeFunc is a function that implements the Decoder interface.
31-
type DecodeFunc func(Request, runtime.Object) error
26+
type DecodeFunc func(types.Request, runtime.Object) error
3227

33-
var _ Decoder = DecodeFunc(nil)
28+
var _ types.Decoder = DecodeFunc(nil)
3429

3530
// Decode implements the Decoder interface.
36-
func (f DecodeFunc) Decode(req Request, obj runtime.Object) error {
31+
func (f DecodeFunc) Decode(req types.Request, obj runtime.Object) error {
3732
return f(req, obj)
3833
}
3934

@@ -42,12 +37,12 @@ type decoder struct {
4237
}
4338

4439
// NewDecoder creates a Decoder given the runtime.Scheme
45-
func NewDecoder(scheme *runtime.Scheme) (Decoder, error) {
40+
func NewDecoder(scheme *runtime.Scheme) (types.Decoder, error) {
4641
return decoder{codecs: serializer.NewCodecFactory(scheme)}, nil
4742
}
4843

4944
// Decode decodes the inlined object in the AdmissionRequest into the passed-in runtime.Object.
50-
func (d decoder) Decode(req Request, into runtime.Object) error {
45+
func (d decoder) Decode(req types.Request, into runtime.Object) error {
5146
deserializer := d.codecs.UniversalDeserializer()
5247
return runtime.DecodeInto(deserializer, req.AdmissionRequest.Object.Raw, into)
5348
}

pkg/webhook/admission/decode_test.go

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -24,10 +24,11 @@ import (
2424
corev1 "k8s.io/api/core/v1"
2525
"k8s.io/apimachinery/pkg/runtime"
2626
"k8s.io/client-go/kubernetes/scheme"
27+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
2728
)
2829

2930
var _ = Describe("admission webhook decoder", func() {
30-
var decoder Decoder
31+
var decoder types.Decoder
3132
BeforeEach(func(done Done) {
3233
var err error
3334
decoder, err = NewDecoder(scheme.Scheme)
@@ -45,7 +46,7 @@ var _ = Describe("admission webhook decoder", func() {
4546
})
4647

4748
Describe("Decode", func() {
48-
req := Request{
49+
req := types.Request{
4950
AdmissionRequest: &admissionv1beta1.AdmissionRequest{
5051
Object: runtime.RawExtension{
5152
Raw: []byte(`{

pkg/webhook/admission/http.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import (
2929
admissionv1beta1 "k8s.io/api/admission/v1beta1"
3030
"k8s.io/apimachinery/pkg/runtime"
3131
"k8s.io/apimachinery/pkg/runtime/serializer"
32+
"sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
3233
)
3334

3435
var admissionv1beta1scheme = runtime.NewScheme()
@@ -57,7 +58,7 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
5758
var body []byte
5859
var err error
5960

60-
var reviewResponse Response
61+
var reviewResponse types.Response
6162
if r.Body != nil {
6263
if body, err = ioutil.ReadAll(r.Body); err != nil {
6364
log.Error(err, "unable to read the body from the incoming request")
@@ -96,11 +97,11 @@ func (wh *Webhook) ServeHTTP(w http.ResponseWriter, r *http.Request) {
9697
for k := range wh.KVMap {
9798
ctx = context.WithValue(ctx, ContextKey(k), wh.KVMap[k])
9899
}
99-
reviewResponse = wh.Handle(ctx, Request{AdmissionRequest: ar.Request})
100+
reviewResponse = wh.Handle(ctx, types.Request{AdmissionRequest: ar.Request})
100101
writeResponse(w, reviewResponse)
101102
}
102103

103-
func writeResponse(w io.Writer, response Response) {
104+
func writeResponse(w io.Writer, response types.Response) {
104105
encoder := json.NewEncoder(w)
105106
responseAdmissionReview := v1beta1.AdmissionReview{
106107
Response: response.Response,

pkg/webhook/admission/http_test.go

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ import (
2727
. "github.com/onsi/gomega"
2828

2929
admissionv1beta1 "k8s.io/api/admission/v1beta1"
30+
atypes "sigs.k8s.io/controller-runtime/pkg/webhook/admission/types"
3031
"sigs.k8s.io/controller-runtime/pkg/webhook/types"
3132
)
3233

@@ -154,10 +155,10 @@ func (nopCloser) Close() error { return nil }
154155
type fakeHandler struct {
155156
invoked bool
156157
valueFromContext string
157-
fn func(context.Context, Request) Response
158+
fn func(context.Context, atypes.Request) atypes.Response
158159
}
159160

160-
func (h *fakeHandler) Handle(ctx context.Context, req Request) Response {
161+
func (h *fakeHandler) Handle(ctx context.Context, req atypes.Request) atypes.Response {
161162
v := ctx.Value(ContextKey("foo"))
162163
if v != nil {
163164
typed, ok := v.(string)
@@ -169,7 +170,7 @@ func (h *fakeHandler) Handle(ctx context.Context, req Request) Response {
169170
if h.fn != nil {
170171
return h.fn(ctx, req)
171172
}
172-
return Response{Response: &admissionv1beta1.AdmissionResponse{
173+
return atypes.Response{Response: &admissionv1beta1.AdmissionResponse{
173174
Allowed: true,
174175
}}
175176
}

0 commit comments

Comments
 (0)