diff --git a/kubernetes/admissioncontrollers/introduction/README.md b/kubernetes/admissioncontrollers/introduction/README.md
index 4bae035..5249a22 100644
--- a/kubernetes/admissioncontrollers/introduction/README.md
+++ b/kubernetes/admissioncontrollers/introduction/README.md
@@ -37,14 +37,21 @@ After the above, we should have:
We always start with a `dockerfile` since we need a Go dev environment.
+```
+FROM golang:1.15-alpine as dev-env
+
+WORKDIR /app
+
+```
+
Build and run the controller
```
# get dev environment: webhook
cd sourcecode
-docker build --target dev-env . -t webhook
-docker run -it --rm -p 80:80 --entrypoint bash -v ${HOME}/.kube/:/root/.kube/ -v ${PWD}:/app webhook
+docker build . -t webhook
+docker run -it --rm -p 80:80 -v ${PWD}:/app webhook sh
```
@@ -54,8 +61,8 @@ Let's define our basic main module and a web server
```
go mod init example-webhook
```
-Source code:
+New file : `main.go`
```
package main
@@ -95,7 +102,7 @@ NOTE: In Windows, container networking is not fully supported. Our container exp
Let's exit the container and start with `--net host` so our container can access our kubernetes `kind` cluster
```
-docker run -it --rm --net host --entrypoint bash -v ${HOME}/.kube/:/root/.kube/ -v ${PWD}:/app webhook
+docker run -it --rm --net host -v ${HOME}/.kube/:/root/.kube/ -v ${PWD}:/app webhook sh
```
We can also test our access to our kubernetes cluster with the config that is mounted in:
@@ -293,10 +300,7 @@ var parameters ServerParameters
# start our web server exposing TLS endpoint
- err = http.ListenAndServeTLS(":" + strconv.Itoa(parameters.port), parameters.certFile, parameters.keyFile, nil)
- if err != nil {
- panic(err.Error())
- }
+ log.Fatal(http.ListenAndServeTLS(":" + strconv.Itoa(parameters.port), parameters.certFile, parameters.keyFile, nil))
```
@@ -318,9 +322,37 @@ if err != nil {
Let's built what we have and deploy it to our kubernetes cluster
+We will firstly need to add a build step to our `dockerfile` to build the code
+And we'll also need to create a smaller runtime layer in our `dockerfile`
+
+Full `dockerfile` :
```
-docker build ./sourcecode -f ./sourcecode/dockerfile -t aimvector/example-webhook:v1
+FROM golang:1.15-alpine as dev-env
+
+WORKDIR /app
+
+FROM dev-env as build-env
+COPY go.mod /go.sum /app/
+RUN go mod download
+
+COPY . /app/
+
+RUN CGO_ENABLED=0 go build -o /webhook
+
+FROM alpine:3.10 as runtime
+
+COPY --from=build-env /webhook /usr/local/bin/webhook
+RUN chmod +x /usr/local/bin/webhook
+
+ENTRYPOINT ["webhook"]
+
+```
+
+Let's build the container and push it to a registry:
+
+```
+docker build . -t aimvector/example-webhook:v1
docker push aimvector/example-webhook:v1
```
@@ -359,14 +391,30 @@ kubectl cp example-webhook-756bcb566b-9kxjp:/tmp/request ./mock-request.json
So lets grab the info from the admission request, so we can do something with it
-```
-# HandleMutate()
-fmt.Printf("Type: %v \t Event: %v \t Name: %v \n",
- admissionReviewReq.Request.Kind,
- admissionReviewReq.Request.Operation,
- admissionReviewReq.Request.Name,
-)
+```
+ //dependencies
+ "k8s.io/api/admission/v1beta1"
+ "errors"
+
+ //HandleMutate()
+
+ var admissionReviewReq v1beta1.AdmissionReview
+
+ if _, _, err := universalDeserializer.Decode(body, nil, &admissionReviewReq); err != nil {
+ w.WriteHeader(http.StatusBadRequest)
+ fmt.Errorf("could not deserialize request: %v", err)
+ } else if admissionReviewReq.Request == nil {
+ w.WriteHeader(http.StatusBadRequest)
+ errors.New("malformed admission review: request is nil")
+ }
+
+ fmt.Printf("Type: %v \t Event: %v \t Name: %v \n",
+ admissionReviewReq.Request.Kind,
+ admissionReviewReq.Request.Operation,
+ admissionReviewReq.Request.Name,
+ )
+
```
# Mutation
@@ -385,12 +433,14 @@ err = json.Unmarshal(admissionReviewReq.Request.Object.Raw, &pod)
if err != nil {
fmt.Errorf("could not unmarshal pod on admission request: %v", err)
}
+
```
To perform a simple mutation on the object before the Kubernetes API sees the object, we can apply a patch to the operation.
```
-//main()
+//global
+
type patchOperation struct {
Op string `json:"op"`
Path string `json:"path"`
@@ -432,17 +482,34 @@ Once you have completed all your patching, convert the patches to byte slice:
Add it to the admission response
```
-admissionReviewResponse.Response.Patch = patchBytes
+ admissionReviewResponse := v1beta1.AdmissionReview{
+ Response: &v1beta1.AdmissionResponse{
+ UID: admissionReviewReq.Request.UID,
+ Allowed: true,
+ },
+ }
+
+ admissionReviewResponse.Response.Patch = patchBytes
+
+ bytes, err := json.Marshal(&admissionReviewResponse)
+ if err != nil {
+ fmt.Errorf("marshaling response: %v", err)
+ }
+
+ w.Write(bytes)
+
+ //dependencies
+ "encoding/json"
```
# Build and push the updates
```
-docker build ./sourcecode -f ./sourcecode/dockerfile -t aimvector/example-webhook:v1
+docker build . -t aimvector/example-webhook:v1
docker push aimvector/example-webhook:v1
```
-# Delete all pods
+# Delete all pods to get latest image
```
kubectl delete pods --all
@@ -457,5 +524,5 @@ kubectl -n default apply -f ./demo-pod.yaml
See the injected label
```
-kubectl get pods demo-pod -o yaml
+kubectl get pods --show-labels
```
\ No newline at end of file
diff --git a/kubernetes/admissioncontrollers/introduction/mock-request.json b/kubernetes/admissioncontrollers/introduction/mock-request.json
new file mode 100644
index 0000000..8c32958
--- /dev/null
+++ b/kubernetes/admissioncontrollers/introduction/mock-request.json
@@ -0,0 +1,150 @@
+{
+ "kind": "AdmissionReview",
+ "apiVersion": "admission.k8s.io/v1beta1",
+ "request": {
+ "uid": "dffc1f0f-0c0b-4d15-892f-71524ecfd06c",
+ "kind": {
+ "group": "",
+ "version": "v1",
+ "kind": "Pod"
+ },
+ "resource": {
+ "group": "",
+ "version": "v1",
+ "resource": "pods"
+ },
+ "requestKind": {
+ "group": "",
+ "version": "v1",
+ "kind": "Pod"
+ },
+ "requestResource": {
+ "group": "",
+ "version": "v1",
+ "resource": "pods"
+ },
+ "name": "demo-pod",
+ "namespace": "default",
+ "operation": "CREATE",
+ "userInfo": {
+ "username": "kubernetes-admin",
+ "groups": [
+ "system:masters",
+ "system:authenticated"
+ ]
+ },
+ "object": {
+ "kind": "Pod",
+ "apiVersion": "v1",
+ "metadata": {
+ "name": "demo-pod",
+ "namespace": "default",
+ "creationTimestamp": null,
+ "labels": {
+ "example-webhook-enabled": "true"
+ },
+ "annotations": {
+ "kubectl.kubernetes.io/last-applied-configuration": "{\"apiVersion\":\"v1\",\"kind\":\"Pod\",\"metadata\":{\"annotations\":{},\"labels\":{\"example-webhook-enabled\":\"true\"},\"name\":\"demo-pod\",\"namespace\":\"default\"},\"spec\":{\"containers\":[{\"image\":\"nginx\",\"name\":\"nginx\"}]}}\n"
+ },
+ "managedFields": [
+ {
+ "manager": "kubectl.exe",
+ "operation": "Update",
+ "apiVersion": "v1",
+ "time": "2021-04-14T07:47:56Z",
+ "fieldsType": "FieldsV1",
+ "fieldsV1": {
+ "f:metadata": {
+ "f:annotations": {
+ ".": {},
+ "f:kubectl.kubernetes.io/last-applied-configuration": {}
+ },
+ "f:labels": {
+ ".": {},
+ "f:example-webhook-enabled": {}
+ }
+ },
+ "f:spec": {
+ "f:containers": {
+ "k:{\"name\":\"nginx\"}": {
+ ".": {},
+ "f:image": {},
+ "f:imagePullPolicy": {},
+ "f:name": {},
+ "f:resources": {},
+ "f:terminationMessagePath": {},
+ "f:terminationMessagePolicy": {}
+ }
+ },
+ "f:dnsPolicy": {},
+ "f:enableServiceLinks": {},
+ "f:restartPolicy": {},
+ "f:schedulerName": {},
+ "f:securityContext": {},
+ "f:terminationGracePeriodSeconds": {}
+ }
+ }
+ }
+ ]
+ },
+ "spec": {
+ "volumes": [
+ {
+ "name": "default-token-4fzpv",
+ "secret": {
+ "secretName": "default-token-4fzpv"
+ }
+ }
+ ],
+ "containers": [
+ {
+ "name": "nginx",
+ "image": "nginx",
+ "resources": {},
+ "volumeMounts": [
+ {
+ "name": "default-token-4fzpv",
+ "readOnly": true,
+ "mountPath": "/var/run/secrets/kubernetes.io/serviceaccount"
+ }
+ ],
+ "terminationMessagePath": "/dev/termination-log",
+ "terminationMessagePolicy": "File",
+ "imagePullPolicy": "Always"
+ }
+ ],
+ "restartPolicy": "Always",
+ "terminationGracePeriodSeconds": 30,
+ "dnsPolicy": "ClusterFirst",
+ "serviceAccountName": "default",
+ "serviceAccount": "default",
+ "securityContext": {},
+ "schedulerName": "default-scheduler",
+ "tolerations": [
+ {
+ "key": "node.kubernetes.io/not-ready",
+ "operator": "Exists",
+ "effect": "NoExecute",
+ "tolerationSeconds": 300
+ },
+ {
+ "key": "node.kubernetes.io/unreachable",
+ "operator": "Exists",
+ "effect": "NoExecute",
+ "tolerationSeconds": 300
+ }
+ ],
+ "priority": 0,
+ "enableServiceLinks": true,
+ "preemptionPolicy": "PreemptLowerPriority"
+ },
+ "status": {}
+ },
+ "oldObject": null,
+ "dryRun": false,
+ "options": {
+ "kind": "CreateOptions",
+ "apiVersion": "meta.k8s.io/v1"
+ }
+ }
+}
\ No newline at end of file
diff --git a/kubernetes/admissioncontrollers/introduction/sourcecode/dockerfile b/kubernetes/admissioncontrollers/introduction/sourcecode/dockerfile
index e1c753b..1ae30b0 100644
--- a/kubernetes/admissioncontrollers/introduction/sourcecode/dockerfile
+++ b/kubernetes/admissioncontrollers/introduction/sourcecode/dockerfile
@@ -1,8 +1,5 @@
FROM golang:1.15-alpine as dev-env
-RUN apk update && apk upgrade && \
- apk add --no-cache bash
-
WORKDIR /app
FROM dev-env as build-env
diff --git a/kubernetes/admissioncontrollers/introduction/sourcecode/go.mod b/kubernetes/admissioncontrollers/introduction/sourcecode/go.mod
index dba3851..8171aed 100644
--- a/kubernetes/admissioncontrollers/introduction/sourcecode/go.mod
+++ b/kubernetes/admissioncontrollers/introduction/sourcecode/go.mod
@@ -3,7 +3,6 @@ module example-webhook
go 1.15
require (
- k8s.io/api v0.21.0
k8s.io/apimachinery v0.21.0
k8s.io/client-go v0.21.0
)
diff --git a/kubernetes/admissioncontrollers/introduction/sourcecode/go.sum b/kubernetes/admissioncontrollers/introduction/sourcecode/go.sum
index 9537a5d..ec17b47 100644
--- a/kubernetes/admissioncontrollers/introduction/sourcecode/go.sum
+++ b/kubernetes/admissioncontrollers/introduction/sourcecode/go.sum
@@ -404,8 +404,6 @@ k8s.io/apimachinery v0.21.0 h1:3Fx+41if+IRavNcKOz09FwEXDBG6ORh6iMsTSelhkMA=
k8s.io/apimachinery v0.21.0/go.mod h1:jbreFvJo3ov9rj7eWT7+sYiRx+qZuCYXwWT1bcDswPY=
k8s.io/client-go v0.21.0 h1:n0zzzJsAQmJngpC0IhgFcApZyoGXPrDIAD601HD09ag=
k8s.io/client-go v0.21.0/go.mod h1:nNBytTF9qPFDEhoqgEPaarobC8QPae13bElIVHzIglA=
-k8s.io/client-go v1.5.2 h1:JOxmv4FxrCIOS54kAABbN8/hA9jqGpns+Zc6soNgd8U=
-k8s.io/client-go v1.5.2/go.mod h1:OmM68YRko3DQ0sjlnWxzjQF9lcSLHJXuGMTo23rc7wI=
k8s.io/gengo v0.0.0-20200413195148-3a45101e95ac/go.mod h1:ezvh/TsK7cY6rbqRK0oQQ8IAqLxYwwyPxAX1Pzy0ii0=
k8s.io/klog/v2 v2.0.0/go.mod h1:PBfzABfn139FHAV07az/IF9Wp1bkk3vpT2XSJ76fSDE=
k8s.io/klog/v2 v2.8.0 h1:Q3gmuM9hKEjefWFFYF0Mat+YyFJvsUyYuwyNNJ5C9Ts=
diff --git a/kubernetes/admissioncontrollers/introduction/sourcecode/main.go b/kubernetes/admissioncontrollers/introduction/sourcecode/main.go
index 959ee38..647b376 100644
--- a/kubernetes/admissioncontrollers/introduction/sourcecode/main.go
+++ b/kubernetes/admissioncontrollers/introduction/sourcecode/main.go
@@ -2,29 +2,43 @@ package main
import (
"net/http"
+ "log"
"k8s.io/apimachinery/pkg/runtime"
"k8s.io/apimachinery/pkg/runtime/serializer"
- "flag"
- "strconv"
+
"os"
"fmt"
"path/filepath"
- "io/ioutil"
"k8s.io/client-go/kubernetes"
rest "k8s.io/client-go/rest"
"k8s.io/client-go/tools/clientcmd"
"k8s.io/client-go/util/homedir"
- apiv1 "k8s.io/api/core/v1"
+ "flag"
+ "strconv"
+ "io/ioutil"
"k8s.io/api/admission/v1beta1"
- "encoding/json"
"errors"
+
+ apiv1 "k8s.io/api/core/v1"
+ "encoding/json"
)
var (
universalDeserializer = serializer.NewCodecFactory(runtime.NewScheme()).UniversalDeserializer()
)
+var parameters ServerParameters
+
+type ServerParameters struct {
+ port int // webhook server port
+ certFile string // path to the x509 certificate for https
+ keyFile string // path to the x509 private key matching `CertFile`
+}
+
+var config *rest.Config
+var clientSet *kubernetes.Clientset
+
type patchOperation struct {
Op string `json:"op"`
Path string `json:"path"`
@@ -32,20 +46,10 @@ type patchOperation struct {
}
-type ServerParameters struct {
- port int // webhook server port
- certFile string // path to the x509 certificate for https
- keyFile string // path to the x509 private key matching `CertFile`
-}
-
-var parameters ServerParameters
-var config *rest.Config
-var clientSet *kubernetes.Clientset
-
func main() {
useKubeConfig := os.Getenv("USE_KUBECONFIG")
- kubeConfigFilePath := os.Getenv("KUBECONFIG")
+ kubeConfigFilePath := os.Getenv("KUBECONFIG")
flag.IntVar(¶meters.port, "port", 8443, "Webhook server port.")
flag.StringVar(¶meters.certFile, "tlsCertFile", "/etc/webhook/certs/tls.crt", "File containing the x509 Certificate for HTTPS.")
@@ -89,11 +93,8 @@ func main() {
test()
http.HandleFunc("/", HandleRoot)
http.HandleFunc("/mutate", HandleMutate)
-
- err = http.ListenAndServeTLS(":" + strconv.Itoa(parameters.port), parameters.certFile, parameters.keyFile, nil)
- if err != nil {
- panic(err.Error())
- }
+
+ log.Fatal(http.ListenAndServeTLS(":" + strconv.Itoa(parameters.port), parameters.certFile, parameters.keyFile, nil))
}
func HandleRoot(w http.ResponseWriter, r *http.Request){
@@ -101,9 +102,9 @@ func HandleRoot(w http.ResponseWriter, r *http.Request){
}
func HandleMutate(w http.ResponseWriter, r *http.Request){
-
- body, err := ioutil.ReadAll(r.Body)
- err = ioutil.WriteFile("/tmp/request", body, 0644)
+
+ body, err := ioutil.ReadAll(r.Body)
+ // err = ioutil.WriteFile("/tmp/request", body, 0644)
if err != nil {
panic(err.Error())
}
@@ -125,21 +126,23 @@ func HandleMutate(w http.ResponseWriter, r *http.Request){
)
var pod apiv1.Pod
- err = json.Unmarshal(admissionReviewReq.Request.Object.Raw, &pod)
+
+ err = json.Unmarshal(admissionReviewReq.Request.Object.Raw, &pod)
if err != nil {
fmt.Errorf("could not unmarshal pod on admission request: %v", err)
}
var patches []patchOperation
+
labels := pod.ObjectMeta.Labels
labels["example-webhook"] = "it-worked"
patches = append(patches, patchOperation{
- Op: "add",
- Path: "/metadata/labels",
- Value: labels,
- })
+ Op: "add",
+ Path: "/metadata/labels",
+ Value: labels,
+ })
patchBytes, err := json.Marshal(patches)
if err != nil {
@@ -161,5 +164,4 @@ func HandleMutate(w http.ResponseWriter, r *http.Request){
}
w.Write(bytes)
-
}
\ No newline at end of file
diff --git a/kubernetes/admissioncontrollers/introduction/sourcecode/test.go b/kubernetes/admissioncontrollers/introduction/sourcecode/test.go
index d5dbf47..fabfedb 100644
--- a/kubernetes/admissioncontrollers/introduction/sourcecode/test.go
+++ b/kubernetes/admissioncontrollers/introduction/sourcecode/test.go
@@ -15,5 +15,4 @@ func test(){
}
fmt.Printf("There are %d pods in the cluster\n", len(pods.Items))
-
}
\ No newline at end of file
diff --git a/kubernetes/admissioncontrollers/introduction/tls/example-webhook-tls.yaml b/kubernetes/admissioncontrollers/introduction/tls/example-webhook-tls.yaml
index e6c8a5f..5ce9544 100644
--- a/kubernetes/admissioncontrollers/introduction/tls/example-webhook-tls.yaml
+++ b/kubernetes/admissioncontrollers/introduction/tls/example-webhook-tls.yaml
@@ -4,5 +4,5 @@ metadata:
name: example-webhook-tls
type: Opaque
data:
- tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVLRENDQXhDZ0F3SUJBZ0lVZjNkS1BVY1FUTWNKc2lWRXpjUWo2dnFSVjc4d0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRVlV4RURBT0JnTlZCQWdUQjBWNFlXMXdiR1V4RWpBUUJnTlZCQWNUQ1UxbApiR0p2ZFhKdVpURVFNQTRHQTFVRUNoTUhSWGhoYlhCc1pURUxNQWtHQTFVRUN4TUNRMEV3SGhjTk1qRXdOREE1Ck1ETXdNVEF3V2hjTk5ERXdOREEwTURNd01UQXdXakJTTVFzd0NRWURWUVFHRXdKQlZURVFNQTRHQTFVRUNCTUgKUlhoaGJYQnNaVEVTTUJBR0ExVUVCeE1KVFdWc1ltOTFjbTVsTVJBd0RnWURWUVFLRXdkRmVHRnRjR3hsTVFzdwpDUVlEVlFRTEV3SkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMWEpSaXlWClVkTkVnREtzK1lTNjFsRnpkQm1QU2FXQ2hpSUxhNXZWUjlsTDBXMjRVTCtyNWliUnUraDJqTjJ6TVdMTmZPVDIKTWJwU05KY3dRUFpqVisyZTlKRUdhYThBWHdkQk1adkxiU1VvWUpQR1NKMWxVSmoyeXZ2dk42ZmY0ZU56OWljegp2RVdlSzNVMUFGdzk4TnZzb3pKcTBtbEl5MTVRU1o0NGJNSHJ6OTRYQTBCRGhZVWVmNUVSb2hSQ2Z4VndESmk1CnVDRDBEK0JLSFpRNlc0b2hNQ3kzeVR4QWk5dWNZc3haNTR0alZ3a0ZwSG1lREpTdDlFZWNWNkxzMTVidVlTcEEKZ1VYSVEvdkdzcG1pQUp4MnVteDFuc091bEtNUDkwQUdzOWNpcUdvZDUxSldtRG43b2JvdmJuNHVhbE05S2RtRgpnRXhPdnZuRWJjYXhFUFVDQXdFQUFhT0I5VENCOGpBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGxCQll3CkZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0hRWURWUjBPQkJZRUZCc0cKcUFVTzAyUFBhelQwQzg2S1J2YVpGZjNGTUI4R0ExVWRJd1FZTUJhQUZKZFhWUEZGM0pxcXdhYVNIZEZxaXBGKwpMU2wxTUhNR0ExVWRFUVJzTUdxQ0QyVjRZVzF3YkdVdGQyVmlhRzl2YTRJcFpYaGhiWEJzWlMxM1pXSm9iMjlyCkxtUmxabUYxYkhRdWMzWmpMbU5zZFhOMFpYSXViRzlqWVd5Q0cyVjRZVzF3YkdVdGQyVmlhRzl2YXk1a1pXWmgKZFd4MExuTjJZNElKYkc5allXeG9iM04waHdSL0FBQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNtUjdBdQozSHEwVGhrYWtHUEg3YkkwcmhpUTE5TStCMkdHT3VkbjVCNDdKWCs0VjA1bCsxUUd5NGR5eUpFZnp2VWZDMHRRCnUyTWs5amt0OTloRDlWb3NHanBSaGRFQ2ZhTVdoQVhoclZkQi9wcXdnOTh4amlrb1c4bXZFOGJlT3pIU1IxYVYKWnBuM01acGdlR1lkNkxxejdlb0JrNmp4djZVVk1DUGpETkVLN3dQNm40VlRtSFJNQmhHeFNxQ28rQWRDa1hRVgpRZUtQWm9yUlhlbEI4eW5LNVpLR01TU1JqL0h2cExUUUZTTnB3MzBTV0EvRjZJYmRtSEphUmp2M21lNUswbmU1Cjg1bE5vTFd4SUtJNGFOSUVkMitrUzcyaWV6bnRIOTBWZHhJTjBzOTgyZnFYa2diRm5ITCtiYk5MNlF3WDZHSFkKRWxReXl1WGdCOGVZY3dtRQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
- tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFcEFJQkFBS0NBUUVBdGNsR0xKVlIwMFNBTXF6NWhMcldVWE4wR1k5SnBZS0dJZ3RybTlWSDJVdlJiYmhRCnY2dm1KdEc3NkhhTTNiTXhZczE4NVBZeHVsSTBsekJBOW1OWDdaNzBrUVpwcndCZkIwRXhtOHR0SlNoZ2s4WkkKbldWUW1QYksrKzgzcDkvaDQzUDJKek84Ulo0cmRUVUFYRDN3Mit5ak1tclNhVWpMWGxCSm5qaHN3ZXZQM2hjRApRRU9GaFI1L2tSR2lGRUovRlhBTW1MbTRJUFFQNEVvZGxEcGJpaUV3TExmSlBFQ0wyNXhpekZubmkyTlhDUVdrCmVaNE1sSzMwUjV4WG91elhsdTVoS2tDQlJjaEQrOGF5bWFJQW5IYTZiSFdldzY2VW93LzNRQWF6MXlLb2FoM24KVWxhWU9mdWh1aTl1Zmk1cVV6MHAyWVdBVEU2KytjUnR4ckVROVFJREFRQUJBb0lCQVFDVGcySFRlZFB0YVcvUwpMM1ZIRk1vblRGWFJDK3BLU1hHSkhOVlVuaXp3a3NxK2kwdlRUYTIwb0lzb0oxTkY4RXhLRGMra2lIZHY1NWRQCmZGT3EzSkNVZldHZWNhSys1TUU0Uk5uNXY0aXhGMlBQWnA2MFFtdTF4TWFReTl6UStDYjRpTGdkdGFpNG9aSkkKU1JzaXZ3eTltZmdRU0lpMzhOOCtpRTVFK3lxZDdOdkdwZWhObWVMSVZyQ0t5QjU3NzRQaUxHcUFLcTk0Zk1BMQplZVFwSHVDaHZHSDJDZUk0L0ZpeEROT2FwZm13Z3RtSUZVM0Z2TkNYaTBKb20zN0lWYUFNZ3VJc1ZvUHpRNlVyCkhOa3UyaGo4YWFmandCSjhGZDdFMWhjY0J3UFdKQ3VqYUN6aGNxUmR0YURFbDAxdHROcERsRi9nUXpJMW1MMDEKQjdJL1Myb2hBb0dCQU00Z1N0TTM3cDhwUVBEelY0dVVwamVuZ1dNZ2R1UW42aVFUQk5SSldKYW1VMi9yWnU2WQpVUDJtRVNXWkJuNFd4dldTSjl0dnhrKytsRHY2Z3VNWitGdnVIWGxGWGRzQmU5NW1xU3gzTG5HTCtmdGwxQjc2Cm94MkU5Rit6NURQVENDT2IyeGNhd1B0eEZ6Q2lIVXFJYTdsQ3Yybm81WHRnenA5VTNVNnlUUlo5QW9HQkFPSEYKVm1QK21PcVFvdVcydmFPZmRvcEQyQjdxNmYzMUhvb3p0TzJ6aEtodXpqTTcvTjRJNGRWRFUvYmw4U2dvMDA0dQpScHI2OUs1ZWlZc21HbzBGK2Nwdmo4Yis4RmtZQk1rUFRYb2o0VFpHODZkcTFZUHhreWtwRE5RVzRFU3lDTENRCmthSGVDcFppdE1PY09pbHhYSjc5MUgzSUVhTEljNnFrYkFJb245WFpBb0dBSEIvUDFjMzE0d1dQOU5CZkM0NTIKdDNWRmRDOER5ZEdnWXRldGV3R2U4cjh5OXp4WlNRakRWRGlLY21UVXUvT0RwaElSR2lIQUh6VlRxSE5mMUhqQQpxRnB1N3hNRjRWSHNnc1hqSTB3SHJEcDdHMUFqaHk2UGZ3R2JEa3ZQUVRyMEMxZkNwdjVoZ20xRnlyN3ozQzJNCjlUUWtSZUVmSHB4dzFOQ1JlYUZlWDBrQ2dZRUFnQ3BhaEtGL2hZbGVNREd4TGpYVVFXR0tTdUxvdXJad0E5eWUKbFdJWHFOWmVVRTk1bVVKSmtadUxDdG8yTUtvY2FvRnlxNEJUYnJsVU01NEo3SXk3NU9PNEp5dUtuY2s0empyVgpyTVM1a09wdVgxZ1NwYmg1NWgvYm5IcndEWTlUeDRnS1pHMThiU3JUbTBnUTdIM2lLby9HRlRHQ2NYcUJ6eGxRCkIxbXdndUVDZ1lCbGF5TGh1eVdmWUZCcEh6RGdxdGtSSFFCamd4RU1qbEUvVU5KQTBZaW9WanZRaHUzWEUybDgKNGpmenVBQXJvenlxMnFrd21ORWd2dWI5Qm8yMjAvNXppOXRLdmNSSU1wbXhsWTd1MUx3TnNtRzU5UmZ2K05iTgpqYnB1L2p6aEN4SlZ4SGxpRkhRWitncFgzbmtCazQ2bFVuVmRzbmRHaTJKOHllSmVlRmhEVkE9PQotLS0tLUVORCBSU0EgUFJJVkFURSBLRVktLS0tLQo=
+ tls.crt: LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUVLRENDQXhDZ0F3SUJBZ0lVZVM1ZWRPRHlWdWhhTVZHcStodGtQWXJrL0E0d0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRVlV4RURBT0JnTlZCQWdUQjBWNFlXMXdiR1V4RWpBUUJnTlZCQWNUQ1UxbApiR0p2ZFhKdVpURVFNQTRHQTFVRUNoTUhSWGhoYlhCc1pURUxNQWtHQTFVRUN4TUNRMEV3SGhjTk1qRXdOREUwCk1EUTBPVEF3V2hjTk5ERXdOREE1TURRME9UQXdXakJTTVFzd0NRWURWUVFHRXdKQlZURVFNQTRHQTFVRUNCTUgKUlhoaGJYQnNaVEVTTUJBR0ExVUVCeE1KVFdWc1ltOTFjbTVsTVJBd0RnWURWUVFLRXdkRmVHRnRjR3hsTVFzdwpDUVlEVlFRTEV3SkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMVDB6NGE3Ckk5b1RVd2RhaWZmeGlLSkFCOHhoUklRNG16NHVSQTdSUk5DZFVOZTBsNEhSN1RUeUlGWnhHeFpUempVeVhGSWgKbklvamNkdEFXeEFwdVJCWGsvNlJub3ZiVG42UHVWbWJGa1lvblg2blErenNNSG5Tcm5jNFFMVERXbEc3MjdIMwo1ekZsUVRRS3RCZUoybmpWUnorOS9aWTBRL2QxWFZnb1VKcDV6RGZKTFJDVkoxZFVMM3FsWlYyeERvM2NkL2hBCjQyTEt3OTFNNTJTRE16aEJtczg1UXhqbnFNZHB0WWt2NVBSei9OWkN5TDlhSlV5SG5rcjhscENKeit6aUdHdEoKd2NSbGZWdWpQK0xGQ1RUS2ZGYi9ORnhpWWtZc2RJV0xlc0lXRytncnNQT2JWOEQwYUhKYXhtY1RXWUlZYWQ5QwpTQUJqcm9nNUM5NXAvZWNDQXdFQUFhT0I5VENCOGpBT0JnTlZIUThCQWY4RUJBTUNCYUF3SFFZRFZSMGxCQll3CkZBWUlLd1lCQlFVSEF3RUdDQ3NHQVFVRkJ3TUNNQXdHQTFVZEV3RUIvd1FDTUFBd0hRWURWUjBPQkJZRUZHY3IKam5jTUR1S0wwKzdvTTlHUDNRUkh2TWd1TUI4R0ExVWRJd1FZTUJhQUZJSnh4VXIyUzlhd0ptM1Nqd3QvRCt1cApJWlFzTUhNR0ExVWRFUVJzTUdxQ0QyVjRZVzF3YkdVdGQyVmlhRzl2YTRJcFpYaGhiWEJzWlMxM1pXSm9iMjlyCkxtUmxabUYxYkhRdWMzWmpMbU5zZFhOMFpYSXViRzlqWVd5Q0cyVjRZVzF3YkdVdGQyVmlhRzl2YXk1a1pXWmgKZFd4MExuTjJZNElKYkc5allXeG9iM04waHdSL0FBQUJNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUEwcmd0YQp6SDVXU2JKZXlCY1RkdkRyR25VN3hVZ3lxZlh2aWkzV25ZRTQ0MkdqR2tzY0wxM0lUUFFoM3k0VDJVTTZxbTh2CldlbXYvTmYvcm1UeVRlSU4rUWtneHlBd2cvOThSMTcvNUs3YTVzamRiQ2Z5elFYNFMrUkxyQW9pT1pxUDZrelUKblRlV01kZGlPV0YwSEhJT2tKdnliTVhFSDVja3N5Y0NhSk5mRU4vdnhoL3FFZXc1N0R0aFl6ZFQ5cHovMHVrNQpDSkpIenMyWDFtMlJoa2hGM0hGR3FMdDhhVVJ4T0JoNEZ2WmxlUjZYbXNIM2pRa3pBT28yOXRtK3JoZEkxaXRzClY0Q1NDWjB1clJETjRrTWFZT2M5VS9pcU9WbmQyMzVEMC9GVHRZS1VaRWVDZXVNQThLTkZuUXFJMkYxTWNwUnAKWVhURUpzSXhKUThOUnZWKwotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==
+ tls.key: LS0tLS1CRUdJTiBSU0EgUFJJVkFURSBLRVktLS0tLQpNSUlFb3dJQkFBS0NBUUVBdFBUUGhyc2oyaE5UQjFxSjkvR0lva0FIekdGRWhEaWJQaTVFRHRGRTBKMVExN1NYCmdkSHROUElnVm5FYkZsUE9OVEpjVWlHY2lpTngyMEJiRUNtNUVGZVQvcEdlaTl0T2ZvKzVXWnNXUmlpZGZxZEQKN093d2VkS3VkemhBdE1OYVVidmJzZmZuTVdWQk5BcTBGNG5hZU5WSFA3MzlsalJEOTNWZFdDaFFtbm5NTjhrdApFSlVuVjFRdmVxVmxYYkVPamR4MytFRGpZc3JEM1V6blpJTXpPRUdhenpsREdPZW94Mm0xaVMvazlIUDgxa0xJCnYxb2xUSWVlU3Z5V2tJblA3T0lZYTBuQnhHVjlXNk0vNHNVSk5NcDhWdjgwWEdKaVJpeDBoWXQ2d2hZYjZDdXcKODV0WHdQUm9jbHJHWnhOWmdoaHAzMEpJQUdPdWlEa0wzbW45NXdJREFRQUJBb0lCQURJcFZzbTdZS0hZRDRFUApXUVdSUDlYeU4vY3cwMlJ2cUtFaEJCNnpaZ2NLUk5tMnB2VUdzMkdrNk0vdGhKdTQyWVdua3kzMVFVYU5zc2NiClhPTHJIZkRveGc2Z1lUblZyam1wTDdFbUs1T0JPTDllTUpjaGxnSi9JM3ZLN1N6dXBqL1grbnVvQTcrT21QZUwKTEFjR1lMaDBMczc5cEtrWmplbXY4Qk03QWJVQUxQM3pnakJRdi9DOXBrdTJ1cUE1RytOM0F0R0pOcm0xTHRRNApLaGwxL0g4RGNPSUduNzZwUms1WUxtL2RFV3ZGb1VQcGRXakpyWFhZNXRvTERMelF5YS9PTGNzZkR6R0ZKQnljCk9RMEI0OG9ZUHJYN0J3WnBka2FjMFVTSWJtN0l0T1BsOTBIdjdPdDl0cVZYVERGMmNnQUs3UmtvU1htV2tYUDIKaURSU0gra0NnWUVBM0tBT29CWHBoSUVmWDU2SVk1aDV5Z3Nmb3dCd1l4azVxRjBjRWpjbVFmaGU1RDVQRDliMQpERkhiQVlFZW52dEVCWXhUK216ejhtTU84QVJDSnNtTmp2M0M4bzNXTE5rRVVuV3hXazJiRlQ3NDBQUUJpNFdFCndSTWNWL1NrT0F6NnlhdW9oMVBLMGFiWHAyR1JJM1NpOSs1aTExL0NyNWtyRE0wMUpoSGlidTBDZ1lFQTBmaDUKU29NYTVocENoYjloWTFyRnhmSnRtd2U4eFBUT3puVDVXWjAvakZPTFNvR0lyU0YrcHg0a0hrdDF2ZG9XTk1wZAoxQWFEN2F4U3gyYjA5aThMSjhXOG85YTBLSmNOS01tNm9vRURqbms4V0VJQm9oeUtrSldsU1NXRU1xc1Y4V0NJClAxY3kwL3JSL3pWUVJlc2QwNlFEbjMwOUJLdDYwYUpUd0hIS01hTUNnWUJIbTIrRHgvamw5OTdOOHkrRFc5N1QKays2dHdodTRIbHpYWjNrUDlIUm5Yd3kxZWYvQlBWeUZwaCsyQ2tsOUFrS2VwbUF2WEtPRTNWL2d5UkVMYzhtTgpTcEcybGhDWXQ4c3VWR0srMDRkdFN1WUpNOWs0aHBxQzdBZjhDRHd3c1EzSTNQMHpCeUJDRWF2VytOVFp0Q2FjCjMvT1d3YzczblhnYWpKUWVpaGw3TlFLQmdRQ1NJWGJ3dDd3Qnh1YmpSS1dYeXpYM3BOaEpYQ0l4aFJ0bExwM1gKazR3RnNxTXZrR1U1OFNTL1ZFZlkyYld4RXRYL21aT2htNE0zNTRXWkIzdVcxbmpTRGxsU1FYd1MvOFdGekpmYQp2eVZsZzlUT3ErbU5GSVlQU0ViSFdKZmYxNWdtN0lNR2FqNlNyMjUxU25wNm5yNmNhL3FsaGpqd1JoUHRVQ2N2CnVVSDZOd0tCZ0R0cE54ZlV1QlhvVkswczJkeGVIODBmVXNQWm1yMDM1ZUFJeWJyazJRZjN1cXRtWDEwU2V0blgKeUw2UlluNHBCOU52U2NRR0VxK2M1MW5CdHpQV2IvSHlxWmRLVWtGUEFvaDc1b3hKS0YrUlErT1B0eXp0MkEyWApsTHJjYkRxN0J5SkF5Nml4S3ZwU0tJcUtlZjdvempHQ2pHTDF0RlNOZmd6NTA4VjRBK2NjCi0tLS0tRU5EIFJTQSBQUklWQVRFIEtFWS0tLS0tCg==
diff --git a/kubernetes/admissioncontrollers/introduction/webhook-template.yaml b/kubernetes/admissioncontrollers/introduction/webhook-template.yaml
index d6d5c4f..1477f66 100644
--- a/kubernetes/admissioncontrollers/introduction/webhook-template.yaml
+++ b/kubernetes/admissioncontrollers/introduction/webhook-template.yaml
@@ -5,7 +5,7 @@ metadata:
webhooks:
- name: example-webhook.default.svc.cluster.local
admissionReviewVersions:
- - "v1beta"
+ - "v1beta1"
sideEffects: "None"
timeoutSeconds: 30
objectSelector:
diff --git a/kubernetes/admissioncontrollers/introduction/webhook.yaml b/kubernetes/admissioncontrollers/introduction/webhook.yaml
index f549119..83d9798 100644
--- a/kubernetes/admissioncontrollers/introduction/webhook.yaml
+++ b/kubernetes/admissioncontrollers/introduction/webhook.yaml
@@ -16,7 +16,7 @@ webhooks:
name: example-webhook
namespace: default
path: "/mutate"
- caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURtRENDQW9DZ0F3SUJBZ0lVWGJCWkhMaXFrL0VtcUo0MTBNZjFTNDBNUXVnd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRVlV4RURBT0JnTlZCQWdUQjBWNFlXMXdiR1V4RWpBUUJnTlZCQWNUQ1UxbApiR0p2ZFhKdVpURVFNQTRHQTFVRUNoTUhSWGhoYlhCc1pURUxNQWtHQTFVRUN4TUNRMEV3SGhjTk1qRXdOREE1Ck1ETXdNREF3V2hjTk1qWXdOREE0TURNd01EQXdXakJTTVFzd0NRWURWUVFHRXdKQlZURVFNQTRHQTFVRUNCTUgKUlhoaGJYQnNaVEVTTUJBR0ExVUVCeE1KVFdWc1ltOTFjbTVsTVJBd0RnWURWUVFLRXdkRmVHRnRjR3hsTVFzdwpDUVlEVlFRTEV3SkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFQVmp2dDlmClJqWU9jRzlJNzBCZzFQcDBCMG0vTWxoREpsbmUxdnJUelJBTEpQK3ZIK0h0RzBIV0VBY3JhVU81MFB1Z3RHekcKekdGa3IzNDZYK2pRbmtWRmQvSnZHTG5WN1hzWFRJblVkNUJ4UnQrbWVjaVE5Y2t6SWl0bVQ5UElvMElTVlVaRgp4SWtpYXJES0dpK3FjQlg0NUNvaWNwQUVOLzNNOXBJanJOdTVBVDI1dUkrbHJUNXdvT1g1QmFVRWpqaCtHdlZtCmNlNzJEMkJhU2lPUDYwZTJlY3ZtU2FQdEZ2bjk3WDI5RkpYTkhoUElNUFlQR1ZUZ0hQSjdXdHBISjdzWGZhUHMKNW9pZzJPUXFLeEFaaXBRYnRob1orb0pVQk51aDBTMXZFUnlPRnV3L2VOSnpuNERRcWxBSmNCbmJlUDA4S2dQUwo4VGxIa0ZXdjFXMVdPdzhDQXdFQUFhTm1NR1F3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJCk1BWUJBZjhDQVFJd0hRWURWUjBPQkJZRUZKZFhWUEZGM0pxcXdhYVNIZEZxaXBGK0xTbDFNQjhHQTFVZEl3UVkKTUJhQUZKZFhWUEZGM0pxcXdhYVNIZEZxaXBGK0xTbDFNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUURjRnVPOApLajJYSWJLdnFPeFdUNWQ1V2FRa21TTVV4VlgrT3FEYmY3MWNqNGhYeTNpQzQ3UW80UTlQR2JnSVV3RjlxSzhVCmRHdXhpYzRnWHJXY0dFSzZzNlVLVU5xWUIySTFXV0VZdW5jekw1WnZrUnpOWmlQUEVneTJkTmxRQ3FkZlF4SVIKWThKUExlTkF6MmZteDZHNTFab0RVSzhHSmtLVnlOYnlsTndSL0JxMHJVU1NYbHhvVE5WWGFDVk93UE9RMGxjRgp2TDdidWVWVzd3RW9RbEhFU1k3Q0NHQkl6bEhlcVNtZzdVNGd0Nk5tWE9yS2dELzhzalk1SUR5L2UyeDR5MFR2CjduSXF4UUNWb0NZQmRrNWNOU2IvZWJVUEdBcHFVS3R1WEJzMlpjRklob0ZOd09sem1hYmF2cVEvNFpEVVNGS3AKZ1dQZGhXWVByS04vamZtbgotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
+ caBundle: "LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSURtRENDQW9DZ0F3SUJBZ0lVUmE5YzR5NXVmUXNEWHFrZFo1cFhmOEFGcjNBd0RRWUpLb1pJaHZjTkFRRUwKQlFBd1VqRUxNQWtHQTFVRUJoTUNRVlV4RURBT0JnTlZCQWdUQjBWNFlXMXdiR1V4RWpBUUJnTlZCQWNUQ1UxbApiR0p2ZFhKdVpURVFNQTRHQTFVRUNoTUhSWGhoYlhCc1pURUxNQWtHQTFVRUN4TUNRMEV3SGhjTk1qRXdOREUwCk1EUTBOekF3V2hjTk1qWXdOREV6TURRME56QXdXakJTTVFzd0NRWURWUVFHRXdKQlZURVFNQTRHQTFVRUNCTUgKUlhoaGJYQnNaVEVTTUJBR0ExVUVCeE1KVFdWc1ltOTFjbTVsTVJBd0RnWURWUVFLRXdkRmVHRnRjR3hsTVFzdwpDUVlEVlFRTEV3SkRRVENDQVNJd0RRWUpLb1pJaHZjTkFRRUJCUUFEZ2dFUEFEQ0NBUW9DZ2dFQkFMR1Q2NW9SClVWcTdDM2RKNkZYSXQwOVdFVkN0MUZuWDRZL3Vtc0wySGpudkdNdGdsU096a0p5cjVTYk5uRytZVzQ4UmhzVEQKZEMxTzFmbWFTWmpRYUNjQ2ZJRFZSTDFyVDFxNis0Smo1QTJnN1VPOS9NbThySnlFeFFMaXVJTVJoc1lUaFR6OQpmTDZucXBKWDZaelpPRFhIcUR0SU1wM2tkdGJ1dGhZRW01WW5RQjd3dTRPUnZJbmtkQk0wNWVHZGw3MFkwVHF1CmlZY3ZBL0MzRndUZjErOTBvTHdIdDcyakw3THBBL0pZSGwvWHNuMVhMd1dic3J0ZUZEVUtsWFl2c1lhKytrSVQKbnloeTF3MkZTeWNtSUdDU2hPdjJsVm1sbVVOUWI4b1lZaDNzTUtEZnhZMmwwak5mVnRibituZ0p6bzFqcklYSAptcTJkdzRiWC9WV3F1ZnNDQXdFQUFhTm1NR1F3RGdZRFZSMFBBUUgvQkFRREFnRUdNQklHQTFVZEV3RUIvd1FJCk1BWUJBZjhDQVFJd0hRWURWUjBPQkJZRUZJSnh4VXIyUzlhd0ptM1Nqd3QvRCt1cElaUXNNQjhHQTFVZEl3UVkKTUJhQUZJSnh4VXIyUzlhd0ptM1Nqd3QvRCt1cElaUXNNQTBHQ1NxR1NJYjNEUUVCQ3dVQUE0SUJBUUNWdDFaOQo4aWMzNVloL3JITktiMGtOZmFPTUNWaWQzamZoNUR0V2tIVG0rVlRkMk1oUDRHb1lGNXNYSmhMN280dzRFTXV2ClNJTGlPMDJjRnVON0NLVno2NUNLQXQwNkI5ekxOb1NUWVlzbWVGUERnME0xUWMreW1FeGlWYU5CelZtRUdHbHMKNXdyUHhXMzE1L1h4VWRnc25kcWRQUmFQM0NBZGM5dEl0Q1BSL0ZoRys0ZHlvd0NiYmZ3NGhiekhDRmRyenJ1cwpLc1Z6NFFWekZkeWhiUFlFQ0hlYVp0UUxzalNQVng4U1kwZWtPcWZyTkZxcHMwRzNEL3pMSmFGVE8xRTVwUkkvClAwTk9JKzRCcnVoQXRZY2d0djhVWTNHc3VQNzE2QmxwY2taZ3FMTm5Zci8vTllZY0NGcEs1enhmaXdYc3VXNDEKWHhuY1VJUG9BSXlXY1cyWQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg=="
rules:
- operations: [ "CREATE" ]
apiGroups: [""]