Skip to content

Commit 068f86f

Browse files
committed
✨ Fix up the webhook to only touch what it actually cares about.
This specifically means it won't try to erase fields it thinks shouldn't be there.
1 parent 0c3bd39 commit 068f86f

File tree

3 files changed

+92
-18
lines changed

3 files changed

+92
-18
lines changed

.github/workflows/main.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,7 @@ jobs:
3838
run: |
3939
os=$(go env GOOS)
4040
arch=$(go env GOARCH)
41-
version=1.24.2
41+
version=1.29.3
4242
curl -L https://storage.googleapis.com/kubebuilder-tools/kubebuilder-tools-${version}-${os}-${arch}.tar.gz | tar -xz -C /tmp/
4343
sudo mv /tmp/kubebuilder /usr/local/kubebuilder
4444
- run: make test

webhook/webhook.go

Lines changed: 32 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -18,14 +18,13 @@ package webhook
1818

1919
import (
2020
"context"
21-
"encoding/json"
2221
"fmt"
2322
"net/http"
2423
"os"
2524

2625
"github.com/pkg/errors"
26+
jsonpatch "gomodules.xyz/jsonpatch/v2"
2727
corev1 "k8s.io/api/core/v1"
28-
"k8s.io/apimachinery/pkg/api/resource"
2928
ctrl "sigs.k8s.io/controller-runtime"
3029
"sigs.k8s.io/controller-runtime/pkg/client"
3130
"sigs.k8s.io/controller-runtime/pkg/webhook"
@@ -90,6 +89,23 @@ func (hook *initInjector) handleInner(ctx context.Context, req admission.Request
9089
}
9190
}
9291

92+
if len(migrators) == 0 {
93+
// Nothing to do.
94+
resp := admission.Allowed("no migrators")
95+
return &resp, nil
96+
}
97+
98+
patches := []jsonpatch.JsonPatchOperation{}
99+
// Check that initContainers exists at all.
100+
if len(pod.Spec.InitContainers) == 0 {
101+
patch := jsonpatch.JsonPatchOperation{
102+
Operation: "add",
103+
Path: "/spec/initContainers",
104+
Value: []interface{}{},
105+
}
106+
patches = append(patches, patch)
107+
}
108+
93109
// For each migrator, inject an initContainer.
94110
for _, m := range migrators {
95111
// Look for the container named in the migrator and pull the image from that. If no container
@@ -100,27 +116,26 @@ func (hook *initInjector) handleInner(ctx context.Context, req admission.Request
100116
podIdx = i
101117
}
102118
}
103-
initContainer := corev1.Container{
104-
Name: fmt.Sprintf("migrate-wait-%s", m.Name),
105-
Image: os.Getenv("WAITER_IMAGE"),
106-
Command: []string{"/waiter", pod.Spec.Containers[podIdx].Image, m.Namespace, m.Name, os.Getenv("API_HOSTNAME")},
107-
Resources: corev1.ResourceRequirements{
108-
Requests: corev1.ResourceList{
109-
corev1.ResourceMemory: resource.MustParse("16M"),
110-
corev1.ResourceCPU: resource.MustParse("10m"),
119+
patch := jsonpatch.JsonPatchOperation{
120+
Operation: "add",
121+
Path: "/spec/initContainers/-",
122+
Value: map[string]interface{}{
123+
"name": fmt.Sprintf("migrate-wait-%s", m.Name),
124+
"image": os.Getenv("WAITER_IMAGE"),
125+
"command": []string{"/waiter", pod.Spec.Containers[podIdx].Image, m.Namespace, m.Name, os.Getenv("API_HOSTNAME")},
126+
"resources": map[string]interface{}{
127+
"requests": map[string]string{
128+
"memory": "16M",
129+
"cpu": "10m",
130+
},
111131
},
112132
},
113133
}
114134
log.Info("Injecting init container", "pod", fmt.Sprintf("%s/%s", req.Namespace, req.Name), "migrator", fmt.Sprintf("%s/%s", m.Namespace, m.Name))
115-
pod.Spec.InitContainers = append(pod.Spec.InitContainers, initContainer)
116-
}
117-
118-
marshaledPod, err := json.Marshal(pod)
119-
if err != nil {
120-
return nil, errors.Wrap(err, "error encoding response object")
135+
patches = append(patches, patch)
121136
}
122137

123-
resp := admission.PatchResponseFromRaw(req.Object.Raw, marshaledPod)
138+
resp := admission.Patched("injecting init containers", patches...)
124139
return &resp, nil
125140
}
126141

webhook/webhook_test.go

Lines changed: 59 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,8 @@ import (
2525
. "github.com/onsi/gomega"
2626
corev1 "k8s.io/api/core/v1"
2727
metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
28+
"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
29+
"k8s.io/apimachinery/pkg/runtime/schema"
2830

2931
migrationsv1beta1 "github.com/coderanger/migrations-operator/api/v1beta1"
3032
)
@@ -63,6 +65,32 @@ var _ = Describe("InitInjector", func() {
6365
Expect(pod.Spec.InitContainers).To(BeEmpty())
6466
})
6567

68+
It("doesn't touch existing init containers with no migrators", func() {
69+
c := helper.TestClient
70+
71+
pod := &corev1.Pod{
72+
ObjectMeta: metav1.ObjectMeta{Name: "testing", Labels: map[string]string{"app": "testing"}},
73+
Spec: corev1.PodSpec{
74+
Containers: []corev1.Container{
75+
{
76+
Name: "main",
77+
Image: "fake",
78+
},
79+
},
80+
InitContainers: []corev1.Container{
81+
{
82+
Name: "init",
83+
Image: "fake",
84+
},
85+
},
86+
},
87+
}
88+
c.Create(pod)
89+
90+
c.EventuallyGetName("testing", pod)
91+
Expect(pod.Spec.InitContainers[0].Name).To(Equal("init"))
92+
})
93+
6694
It("injects with a matching migrator", func() {
6795
c := helper.TestClient
6896

@@ -252,4 +280,35 @@ var _ = Describe("InitInjector", func() {
252280
err := c.Create(context.Background(), pod)
253281
Expect(err).To(MatchError(ContainSubstring("no migrators found matching pod")))
254282
})
283+
284+
It("doesn't remove restartPolicy from init containers", func() {
285+
c := helper.TestClient
286+
287+
pod := &unstructured.Unstructured{}
288+
pod.SetGroupVersionKind(schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"})
289+
pod.SetName("testing")
290+
pod.UnstructuredContent()["spec"] = map[string][]map[string]string{
291+
"containers": {
292+
{
293+
"name": "main",
294+
"image": "fake",
295+
},
296+
},
297+
"initContainers": {
298+
{
299+
"name": "sidecar",
300+
"image": "fake",
301+
"restartPolicy": "Always",
302+
},
303+
},
304+
}
305+
c.Create(pod)
306+
307+
c.EventuallyGetName("testing", pod)
308+
spec := pod.UnstructuredContent()["spec"].(map[string]interface{})
309+
println(spec)
310+
initContainers := spec["initContainers"].([]interface{})
311+
sidecar := initContainers[0].(map[string]interface{})
312+
Expect(sidecar["restartPolicy"]).To(Equal("Always"))
313+
})
255314
})

0 commit comments

Comments
 (0)