From faf3a2c7217ae4297adceaeddeb0dcd152b182a6 Mon Sep 17 00:00:00 2001 From: Andrea Panattoni Date: Fri, 30 Jun 2023 11:01:10 +0200 Subject: [PATCH] Support pods without volumes When a pod has `.spec.automountServiceAccountToken=false`, it has no volumes nor containers[*].volumeMounts, and the mutating webhook must produce a patch to create those arrays. Signed-off-by: Andrea Panattoni --- pkg/webhook/webhook.go | 22 +++++++++++++++++++--- test/e2e/resourcename_test.go | 33 +++++++++++++++++++++++++++++++++ 2 files changed, 52 insertions(+), 3 deletions(-) diff --git a/pkg/webhook/webhook.go b/pkg/webhook/webhook.go index 6a007b76..d19c666d 100644 --- a/pkg/webhook/webhook.go +++ b/pkg/webhook/webhook.go @@ -434,6 +434,15 @@ func patchEmptyResources(patch []types.JsonPatchOperation, containerIndex uint, } func addVolDownwardAPI(patch []types.JsonPatchOperation, hugepageResourceList []hugepageResourceData, pod *corev1.Pod) []types.JsonPatchOperation { + + if len(pod.Spec.Volumes) == 0 { + patch = append(patch, types.JsonPatchOperation{ + Operation: "add", + Path: "/spec/volumes", + Value: []corev1.Volume{}, + }) + } + dAPIItems := []corev1.DownwardAPIVolumeFile{} if pod.Labels != nil && len(pod.Labels) > 0 { @@ -491,14 +500,21 @@ func addVolDownwardAPI(patch []types.JsonPatchOperation, hugepageResourceList [] return patch } -func addVolumeMount(patch []types.JsonPatchOperation, containersLen int) []types.JsonPatchOperation { +func addVolumeMount(patch []types.JsonPatchOperation, containers []corev1.Container) []types.JsonPatchOperation { vm := corev1.VolumeMount{ Name: "podnetinfo", ReadOnly: true, MountPath: types.DownwardAPIMountPath, } - for containerIndex := 0; containerIndex < containersLen; containerIndex++ { + for containerIndex, container := range containers { + if len(container.VolumeMounts) == 0 { + patch = append(patch, types.JsonPatchOperation{ + Operation: "add", + Path: "/spec/containers/" + strconv.Itoa(containerIndex) + "/volumeMounts", + Value: []corev1.VolumeMount{}, + }) + } patch = append(patch, types.JsonPatchOperation{ Operation: "add", Path: "/spec/containers/" + strconv.Itoa(containerIndex) + "/volumeMounts/-", @@ -510,7 +526,7 @@ func addVolumeMount(patch []types.JsonPatchOperation, containersLen int) []types } func createVolPatch(patch []types.JsonPatchOperation, hugepageResourceList []hugepageResourceData, pod *corev1.Pod) []types.JsonPatchOperation { - patch = addVolumeMount(patch, len(pod.Spec.Containers)) + patch = addVolumeMount(patch, pod.Spec.Containers) patch = addVolDownwardAPI(patch, hugepageResourceList, pod) return patch } diff --git a/test/e2e/resourcename_test.go b/test/e2e/resourcename_test.go index 47d30f30..6df82b35 100644 --- a/test/e2e/resourcename_test.go +++ b/test/e2e/resourcename_test.go @@ -7,6 +7,7 @@ import ( cniv1 "github.com/k8snetworkplumbingwg/network-attachment-definition-client/pkg/apis/k8s.cni.cncf.io/v1" corev1 "k8s.io/api/core/v1" + "k8s.io/utils/pointer" ) var _ = Describe("Verify that resource and POD which consumes resource cannot be in different namespaces", func() { @@ -154,4 +155,36 @@ var _ = Describe("Network injection testing", func() { Expect(limNo.String()).Should(Equal("1")) }) }) + + Context("one network request and automountServiceAccountToken=false", func() { + BeforeEach(func() { + nad = util.GetResourceSelectorOnly(testNetworkName, *testNs, testNetworkResName) + Expect(util.ApplyNetworkAttachmentDefinition(networkClient.K8sCniCncfIoV1Interface, nad, timeout)).Should(BeNil()) + + pod = util.GetOneNetwork(testNetworkName, *testNs, defaultPodName) + pod.Spec.AutomountServiceAccountToken = pointer.Bool(false) + + Expect(util.CreateRunningPod(cs.CoreV1Interface, pod, timeout, interval)).Should(BeNil()) + Expect(pod.Name).ShouldNot(BeNil()) + pod, err = util.UpdatePodInfo(cs.CoreV1Interface, pod, timeout) + Expect(err).Should(BeNil()) + }) + + AfterEach(func() { + _ = util.DeletePod(cs.CoreV1Interface, pod, timeout) + Expect(util.DeleteNetworkAttachmentDefinition(networkClient.K8sCniCncfIoV1Interface, testNetworkName, nad, timeout)).Should(BeNil()) + }) + + It("should have one limit injected", func() { + limNo, ok := pod.Spec.Containers[0].Resources.Limits[testNetworkResName] + Expect(ok).Should(BeTrue()) + Expect(limNo.String()).Should(Equal("1")) + }) + + It("should have one request injected", func() { + limNo, ok := pod.Spec.Containers[0].Resources.Requests[testNetworkResName] + Expect(ok).Should(BeTrue()) + Expect(limNo.String()).Should(Equal("1")) + }) + }) })