Skip to content

Commit 43e4a85

Browse files
author
Mengqi Yu
committed
update godoc for webhook
1 parent 79f0601 commit 43e4a85

File tree

4 files changed

+216
-27
lines changed

4 files changed

+216
-27
lines changed

pkg/doc.go

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,19 @@ system must be read for each Reconciler.
4949
5050
* Controller require Watches to be configured to enqueue reconcile.Requests in response to events.
5151
52+
Webhook
53+
54+
Admission Webhooks are a mechanism for extending kubernetes APIs. Webhooks can be configured with target
55+
event type (object Create, Update, Delete), the API server will send AdmissionRequests to them
56+
when certain events happen. The webhooks may mutate and (or) validate the object embedded in
57+
the AdmissionReview requests and send back the response to the API server.
58+
59+
There are 2 types of admission webhook: mutating and validating admission webhook.
60+
Mutating webhook is used to mutate a core API object or a CRD instance before the API server admits it.
61+
Validating webhook is used to validate if an object meets certain requirements.
62+
63+
* Admission Webhooks require Handler(s) to be provided to process the received AdmissionReview requests.
64+
5265
Reconciler
5366
5467
Reconciler is a function provided to a Controller that may be called at anytime with the Name and Namespace of an object.

pkg/webhook/admission/builder/doc.go

Lines changed: 107 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,107 @@
1+
/*
2+
Copyright 2018 The Kubernetes Authors.
3+
4+
Licensed under the Apache License, Version 2.0 (the "License");
5+
you may not use this file except in compliance with the License.
6+
You may obtain a copy of the License at
7+
8+
http://www.apache.org/licenses/LICENSE-2.0
9+
10+
Unless required by applicable law or agreed to in writing, software
11+
distributed under the License is distributed on an "AS IS" BASIS,
12+
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
See the License for the specific language governing permissions and
14+
limitations under the License.
15+
*/
16+
17+
/*
18+
Package builder provides methods to build admission webhooks.
19+
20+
The following are 2 examples for building mutating webhook and validating webhook.
21+
22+
webhook1, err := NewWebhookBuilder().
23+
Mutating().
24+
Operations(admissionregistrationv1beta1.Create).
25+
ForType(&corev1.Pod{}).
26+
WithManager(mgr).
27+
Handlers(mutatingHandler11, mutatingHandler12).
28+
Build()
29+
if err != nil {
30+
// handle error
31+
}
32+
33+
webhook2, err := NewWebhookBuilder().
34+
Validating().
35+
Operations(admissionregistrationv1beta1.Create, admissionregistrationv1beta1.Update).
36+
ForType(&appsv1.Deployment{}).
37+
WithManager(mgr).
38+
Handlers(validatingHandler21).
39+
Build()
40+
if err != nil {
41+
// handle error
42+
}
43+
44+
Note: To build a webhook for a CRD, you need to ensure the manager uses the scheme that understands your CRD.
45+
This is necessary, because if the scheme doesn't understand your CRD types, the decoder won't be able to decode
46+
the CR object from the admission review request.
47+
48+
The following snippet shows how to register CRD types with manager's scheme.
49+
50+
mgr, err := manager.New(cfg, manager.Options{})
51+
if err != nil {
52+
// handle error
53+
}
54+
// SchemeGroupVersion is group version used to register these objects
55+
SchemeGroupVersion = schema.GroupVersion{Group: "crew.k8s.io", Version: "v1"}
56+
// SchemeBuilder is used to add go types to the GroupVersionKind scheme
57+
SchemeBuilder = &scheme.Builder{GroupVersion: SchemeGroupVersion}
58+
// Register your CRD types.
59+
SchemeBuilder.Register(&Kraken{}, &KrakenList{})
60+
// Register your CRD types with the manager's scheme.
61+
err = SchemeBuilder.AddToScheme(mgr.GetScheme())
62+
if err != nil {
63+
// handle error
64+
}
65+
66+
There are more options for configuring a webhook. e.g. Name, Path, FailurePolicy, NamespaceSelector.
67+
Here is another example:
68+
69+
webhook3, err := NewWebhookBuilder().
70+
Name("foo.example.com").
71+
Path("/mutatepods").
72+
Mutating().
73+
Operations(admissionregistrationv1beta1.Create).
74+
ForType(&corev1.Pod{}).
75+
FailurePolicy(admissionregistrationv1beta1.Fail).
76+
WithManager(mgr).
77+
Handlers(mutatingHandler31, mutatingHandler32).
78+
Build()
79+
if err != nil {
80+
// handle error
81+
}
82+
83+
For most users, we recommend to use Operations and ForType instead of Rules to construct a webhook,
84+
since it is more intuitive and easier to pass the target operations to Operations method and
85+
a empty target object to ForType method than passing a complex RuleWithOperations struct to Rules method.
86+
87+
Rules may be useful for some more advanced use cases like subresources, wildcard resources etc.
88+
Here is an example:
89+
90+
webhook4, err := NewWebhookBuilder().
91+
Validating().
92+
Rules(admissionregistrationv1beta1.RuleWithOperations{
93+
Operations: []admissionregistrationv1beta1.OperationType{admissionregistrationv1beta1.Create},
94+
Rule: admissionregistrationv1beta1.Rule{
95+
APIGroups: []string{"apps", "batch"},
96+
APIVersions: []string{"v1"},
97+
Resources: []string{"*"},
98+
},
99+
}).
100+
WithManager(mgr).
101+
Handlers(validatingHandler41).
102+
Build()
103+
if err != nil {
104+
// handle error
105+
}
106+
*/
107+
package builder

pkg/webhook/admission/doc.go

Lines changed: 75 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -15,30 +15,81 @@ limitations under the License.
1515
*/
1616

1717
/*
18-
Package admission provides functions to build and bootstrap an admission webhook server for a k8s cluster.
19-
20-
Build webhooks
21-
22-
webhook1, err := NewWebhookBuilder().
23-
Name("foo.k8s.io").
24-
Mutating().
25-
Operations(admissionregistrationv1beta1.Create).
26-
ForType(&corev1.Pod{}).
27-
WithManager(mgr).
28-
Build(mutatingHandler1, mutatingHandler2)
29-
if err != nil {
30-
// handle error
31-
}
32-
33-
webhook2, err := NewWebhookBuilder().
34-
Name("bar.k8s.io").
35-
Validating().
36-
Operations(admissionregistrationv1beta1.Create, admissionregistrationv1beta1.Update).
37-
ForType(&appsv1.Deployment{}).
38-
WithManager(mgr).
39-
Build(validatingHandler1)
40-
if err != nil {
41-
// handle error
18+
Package admission provides implementation for admission webhook and methods to implement admission webhook handlers.
19+
20+
The following snippet is an example implementation of mutating handler.
21+
22+
type Mutator struct {
23+
client client.Client
24+
decoder types.Decoder
25+
}
26+
27+
func (m *Mutator) mutatePodsFn(ctx context.Context, pod *corev1.Pod) error {
28+
// your logic to mutate the passed-in pod.
29+
}
30+
31+
func (m *Mutator) Handle(ctx context.Context, req types.Request) types.Response {
32+
pod := &corev1.Pod{}
33+
err := m.decoder.Decode(req, pod)
34+
if err != nil {
35+
return admission.ErrorResponse(http.StatusBadRequest, err)
36+
}
37+
// Do deepcopy before actually mutate the object.
38+
copy := pod.DeepCopy()
39+
err = m.mutatePodsFn(ctx, copy)
40+
if err != nil {
41+
return admission.ErrorResponse(http.StatusInternalServerError, err)
42+
}
43+
return admission.PatchResponse(pod, copy)
44+
}
45+
46+
// InjectClient is called by the Manager and provides a client.Client to the Mutator instance.
47+
func (m *Mutator) InjectClient(c client.Client) error {
48+
h.client = c
49+
return nil
50+
}
51+
52+
// InjectDecoder is called by the Manager and provides a types.Decoder to the Mutator instance.
53+
func (m *Mutator) InjectDecoder(d types.Decoder) error {
54+
h.decoder = d
55+
return nil
56+
}
57+
58+
The following snippet is an example implementation of validating handler.
59+
60+
type Handler struct {
61+
client client.Client
62+
decoder types.Decoder
63+
}
64+
65+
func (v *Validator) validatePodsFn(ctx context.Context, pod *corev1.Pod) (bool, string, error) {
66+
// your business logic
67+
}
68+
69+
func (v *Validator) Handle(ctx context.Context, req types.Request) types.Response {
70+
pod := &corev1.Pod{}
71+
err := h.decoder.Decode(req, pod)
72+
if err != nil {
73+
return admission.ErrorResponse(http.StatusBadRequest, err)
74+
}
75+
76+
allowed, reason, err := h.validatePodsFn(ctx, pod)
77+
if err != nil {
78+
return admission.ErrorResponse(http.StatusInternalServerError, err)
79+
}
80+
return admission.ValidationResponse(allowed, reason)
81+
}
82+
83+
// InjectClient is called by the Manager and provides a client.Client to the Validator instance.
84+
func (v *Validator) InjectClient(c client.Client) error {
85+
h.client = c
86+
return nil
87+
}
88+
89+
// InjectDecoder is called by the Manager and provides a types.Decoder to the Validator instance.
90+
func (v *Validator) InjectDecoder(d types.Decoder) error {
91+
h.decoder = d
92+
return nil
4293
}
4394
*/
4495
package admission

pkg/webhook/doc.go

Lines changed: 21 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@ limitations under the License.
1515
*/
1616

1717
/*
18-
Package webhook provides functions to build and bootstrap an admission webhook server for a k8s cluster.
18+
Package webhook provides methods to build and bootstrap a webhook server.
19+
20+
Currently, it only supports admission webhooks. It will support CRD conversion webhooks in the near future.
1921
2022
Build webhooks
2123
@@ -46,9 +48,25 @@ Build webhooks
4648
// handle error
4749
}
4850
49-
Create a server for webhooks.
51+
Create a webhook server.
5052
51-
as, err := NewServer("baz-admission-server", mrg, ServerOptions{})
53+
as, err := NewServer("baz-admission-server", mgr, ServerOptions{
54+
CertDir: "/tmp/cert",
55+
BootstrapOptions: &BootstrapOptions{
56+
Secret: &apitypes.NamespacedName{
57+
Namespace: "default",
58+
Name: "foo-admission-server-secret",
59+
},
60+
Service: &Service{
61+
Namespace: "default",
62+
Name: "foo-admission-server-service",
63+
// Selectors should select the pods that runs this webhook server.
64+
Selectors: map[string]string{
65+
"app": "foo-admission-server",
66+
},
67+
},
68+
},
69+
})
5270
if err != nil {
5371
// handle error
5472
}

0 commit comments

Comments
 (0)