Skip to content

Commit

Permalink
Add missing reserved annotation support to play
Browse files Browse the repository at this point in the history
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 <[email protected]>
  • Loading branch information
jakecorrenti committed Jul 17, 2023
1 parent 52af8a2 commit d7e25e1
Show file tree
Hide file tree
Showing 4 changed files with 300 additions and 1 deletion.
3 changes: 3 additions & 0 deletions libpod/container_inspect.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
53 changes: 53 additions & 0 deletions pkg/specgen/generate/kube/kube.go
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
242 changes: 242 additions & 0 deletions test/e2e/play_kube_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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"))
})
})
3 changes: 2 additions & 1 deletion test/e2e/run_networking_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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))
Expand All @@ -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() {
Expand Down

0 comments on commit d7e25e1

Please sign in to comment.