From d7e25e14aa5a1186a715b7cf0a44412bc5fa5ca5 Mon Sep 17 00:00:00 2001 From: Jake Correnti Date: Wed, 12 Jul 2023 08:49:02 -0400 Subject: [PATCH] Add missing reserved annotation support to `play` Adds any required "wiring" to ensure the reserved annotations are supported by `podman kube play`. Addtionally fixes a bug where, when inspected, containers created using the `--publish-all` flag had a field `.HostConfig.PublishAllPorts` whose value was only evaluated as `false`. Signed-off-by: Jake Correnti --- libpod/container_inspect.go | 3 + pkg/specgen/generate/kube/kube.go | 53 +++++++ test/e2e/play_kube_test.go | 242 ++++++++++++++++++++++++++++++ test/e2e/run_networking_test.go | 3 +- 4 files changed, 300 insertions(+), 1 deletion(-) diff --git a/libpod/container_inspect.go b/libpod/container_inspect.go index 3e8cbf904b..19242632fc 100644 --- a/libpod/container_inspect.go +++ b/libpod/container_inspect.go @@ -507,6 +507,9 @@ func (c *Container) generateInspectContainerHostConfig(ctrSpec *spec.Spec, named if ctrSpec.Annotations[define.InspectAnnotationInit] == define.InspectResponseTrue { hostConfig.Init = true } + if ctrSpec.Annotations[define.InspectAnnotationPublishAll] == define.InspectResponseTrue { + hostConfig.PublishAllPorts = true + } } if err := c.platformInspectContainerHostConfig(ctrSpec, hostConfig); err != nil { diff --git a/pkg/specgen/generate/kube/kube.go b/pkg/specgen/generate/kube/kube.go index b2459c4f00..64f07186b3 100644 --- a/pkg/specgen/generate/kube/kube.go +++ b/pkg/specgen/generate/kube/kube.go @@ -361,6 +361,59 @@ func ToSpecGen(ctx context.Context, opts *CtrSpecGenOptions) (*specgen.SpecGener } s.Annotations = annotations + if containerCIDFile, ok := opts.Annotations[define.InspectAnnotationCIDFile+"/"+opts.Container.Name]; ok { + s.Annotations[define.InspectAnnotationCIDFile] = containerCIDFile + } + + if seccomp, ok := opts.Annotations[define.InspectAnnotationSeccomp+"/"+opts.Container.Name]; ok { + s.Annotations[define.InspectAnnotationSeccomp] = seccomp + } + + if apparmor, ok := opts.Annotations[define.InspectAnnotationApparmor+"/"+opts.Container.Name]; ok { + s.Annotations[define.InspectAnnotationApparmor] = apparmor + } + + if label, ok := opts.Annotations[define.InspectAnnotationLabel+"/"+opts.Container.Name]; ok { + if label == "nested" { + s.ContainerSecurityConfig.LabelNested = true + } + if !slices.Contains(s.ContainerSecurityConfig.SelinuxOpts, label) { + s.ContainerSecurityConfig.SelinuxOpts = append(s.ContainerSecurityConfig.SelinuxOpts, label) + } + s.Annotations[define.InspectAnnotationLabel] = strings.Join(s.ContainerSecurityConfig.SelinuxOpts, ",label=") + } + + if autoremove, ok := opts.Annotations[define.InspectAnnotationAutoremove+"/"+opts.Container.Name]; ok { + autoremoveAsBool, err := strconv.ParseBool(autoremove) + if err != nil { + return nil, err + } + s.Remove = autoremoveAsBool + s.Annotations[define.InspectAnnotationAutoremove] = autoremove + } + + if init, ok := opts.Annotations[define.InspectAnnotationInit+"/"+opts.Container.Name]; ok { + initAsBool, err := strconv.ParseBool(init) + if err != nil { + return nil, err + } + + s.Init = initAsBool + s.Annotations[define.InspectAnnotationInit] = init + } + + if publishAll, ok := opts.Annotations[define.InspectAnnotationPublishAll+"/"+opts.Container.Name]; ok { + if opts.IsInfra { + publishAllAsBool, err := strconv.ParseBool(publishAll) + if err != nil { + return nil, err + } + s.PublishExposedPorts = publishAllAsBool + } + + s.Annotations[define.InspectAnnotationPublishAll] = publishAll + } + // Environment Variables envs := map[string]string{} for _, env := range imageData.Config.Env { diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index 57ecd07c8b..886ab70eb5 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -5400,4 +5400,246 @@ spec: session.WaitWithDefaultTimeout() Expect(session).Should(Exit(125)) }) + + It("podman play kube test with reserved volumes-from annotation in yaml", func() { + ctr1 := "ctr1" + ctr2 := "ctr2" + ctrNameInKubePod := ctr2 + "-pod-" + ctr2 + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") + + err := os.MkdirAll(vol1, 0755) + Expect(err).ToNot(HaveOccurred()) + + session := podmanTest.Podman([]string{"create", "--name", ctr1, "-v", vol1, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + session = podmanTest.Podman([]string{"create", "--volumes-from", ctr1, "--name", ctr2, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr2}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + inspectCtr2 := podmanTest.Podman([]string{"inspect", "-f", "'{{ .HostConfig.Binds }}'", ctrNameInKubePod}) + inspectCtr2.WaitWithDefaultTimeout() + Expect(inspectCtr2).Should(Exit(0)) + Expect(inspectCtr2.OutputToString()).To(ContainSubstring(":" + vol1 + ":rw")) + + inspectCtr1 := podmanTest.Podman([]string{"inspect", "-f", "'{{ .HostConfig.Binds }}'", ctr1}) + inspectCtr1.WaitWithDefaultTimeout() + Expect(inspectCtr1).Should(Exit(0)) + + Expect(inspectCtr2.OutputToString()).To(Equal(inspectCtr1.OutputToString())) + }) + + It("podman kube play test with reserved autoremove annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--rm", "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.AutoRemove }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("true")) + }) + + It("podman kube play test with reserved privileged annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--privileged", "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.Privileged }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("true")) + }) + + It("podman kube play test with reserved init annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--init", "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .Path }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("/run/podman-init")) + }) + + It("podman kube play test with reserved CIDFile annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + cidFile := filepath.Join(podmanTest.TempDir, RandomString(10)+".txt") + + session := podmanTest.Podman([]string{"create", "--cidfile", cidFile, "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.ContainerIDFile }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal(cidFile)) + + }) + + It("podman kube play test with reserved Seccomp annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--security-opt", "seccomp=unconfined", "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.SecurityOpt }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("[seccomp=unconfined]")) + }) + + It("podman kube play test with reserved Apparmor annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--security-opt", "apparmor=unconfined", "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.SecurityOpt }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("[apparmor=unconfined]")) + }) + + It("podman kube play test with reserved Label annotation in yaml", func() { + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--security-opt", "label=level:s0", "--name", ctr, ALPINE}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.SecurityOpt }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("[label=level:s0]")) + }) + + It("podman kube play test with reserved PublishAll annotation in yaml", func() { + podmanTest.AddImageToRWStore(ALPINE) + dockerfile := fmt.Sprintf(`FROM %s +EXPOSE 2002 +EXPOSE 2001-2003 +EXPOSE 2004-2005/tcp`, ALPINE) + imageName := "testimg" + podmanTest.BuildImage(dockerfile, imageName, "false") + + // Verify that the buildah is just passing through the EXPOSE keys + inspect := podmanTest.Podman([]string{"inspect", imageName}) + inspect.WaitWithDefaultTimeout() + image := inspect.InspectImageJSON() + Expect(image).To(HaveLen(1)) + Expect(image[0].Config.ExposedPorts).To(HaveLen(3)) + Expect(image[0].Config.ExposedPorts).To(HaveKey("2002/tcp")) + Expect(image[0].Config.ExposedPorts).To(HaveKey("2001-2003/tcp")) + Expect(image[0].Config.ExposedPorts).To(HaveKey("2004-2005/tcp")) + + ctr := "ctr" + ctrNameInKubePod := ctr + "-pod-" + ctr + outputFile := filepath.Join(podmanTest.TempDir, "pod.yaml") + + session := podmanTest.Podman([]string{"create", "--publish-all", "--name", ctr, imageName, "true"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + + kube := podmanTest.Podman([]string{"kube", "generate", "--podman-only", "-f", outputFile, ctr}) + kube.WaitWithDefaultTimeout() + Expect(kube).Should(Exit(0)) + + play := podmanTest.Podman([]string{"kube", "play", outputFile}) + play.WaitWithDefaultTimeout() + Expect(play).Should(Exit(0)) + + session = podmanTest.Podman([]string{"inspect", "-f", "{{ .HostConfig.PublishAllPorts }}", ctrNameInKubePod}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(Equal("true")) + }) }) diff --git a/test/e2e/run_networking_test.go b/test/e2e/run_networking_test.go index fc185ca8b2..a0555d98b9 100644 --- a/test/e2e/run_networking_test.go +++ b/test/e2e/run_networking_test.go @@ -417,7 +417,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(image[0].Config.ExposedPorts).To(HaveKey("2004-2005/tcp")) containerName := "testcontainer" - session := podmanTest.Podman([]string{"create", "--name", containerName, imageName, "true"}) + session := podmanTest.Podman([]string{"create", "--publish-all", "--name", containerName, imageName, "true"}) session.WaitWithDefaultTimeout() inspectOut := podmanTest.InspectContainer(containerName) Expect(inspectOut).To(HaveLen(1)) @@ -430,6 +430,7 @@ EXPOSE 2004-2005/tcp`, ALPINE) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveKey("2003/tcp")) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveKey("2004/tcp")) Expect(inspectOut[0].NetworkSettings.Ports).To(HaveKey("2005/tcp")) + Expect(inspectOut[0].HostConfig.PublishAllPorts).To(BeTrue()) }) It("podman run -p 127.0.0.1::8980/udp", func() {