diff options
Diffstat (limited to 'test')
28 files changed, 869 insertions, 36 deletions
diff --git a/test/apiv2/01-basic.at b/test/apiv2/01-basic.at index b8a049cdf..0e94ddb7a 100644 --- a/test/apiv2/01-basic.at +++ b/test/apiv2/01-basic.at @@ -41,10 +41,16 @@ t GET libpod/containers/create 405 # # system info # +# Some day perhaps it will always be runc; for now, cgroupsv2 requires crun +# # FIXME: run 'podman info --format=json', and compare select fields -t GET info 200 \ - .OSType=linux \ - .DefaultRuntime=runc \ +runtime=runc +if have_cgroupsv2; then + runtime=crun +fi +t GET info 200 \ + .OSType=linux \ + .DefaultRuntime~.*$runtime \ .MemTotal~[0-9]\\+ # Timing: make sure server stays responsive diff --git a/test/apiv2/20-containers.at b/test/apiv2/20-containers.at index a69e8cc99..3a5d5a398 100644 --- a/test/apiv2/20-containers.at +++ b/test/apiv2/20-containers.at @@ -22,7 +22,7 @@ t GET libpod/containers/json?all=true 200 \ .[0].Id~[0-9a-f]\\{12\\} \ .[0].Image=$IMAGE \ .[0].Command[0]="true" \ - .[0].State=exited \ + .[0].State~\\\(exited\\\|stopped\\\) \ .[0].ExitCode=0 \ .[0].IsInfra=false diff --git a/test/apiv2/22-stop.at b/test/apiv2/22-stop.at new file mode 100644 index 000000000..11318ca81 --- /dev/null +++ b/test/apiv2/22-stop.at @@ -0,0 +1,24 @@ +# -*- sh -*- +# +# test 'stop' endpoints +# + +podman pull $IMAGE &>/dev/null + +# stop, by name +podman run -dt --name mytop $IMAGE top &>/dev/null + +t GET libpod/containers/mytop/json 200 .State.Status=running +t POST libpod/containers/mytop/stop "" 204 +t GET libpod/containers/mytop/json 200 .State.Status~\\\(exited\\\|stopped\\\) +t DELETE libpod/containers/mytop 204 + +# stop, by ID +# Remember that podman() hides all output; we need to get our CID via inspect +podman run -dt --name mytop $IMAGE top + +t GET libpod/containers/mytop/json 200 .State.Status=running +cid=$(jq -r .Id <<<"$output") +t POST libpod/containers/$cid/stop "" 204 +t GET libpod/containers/mytop/json 200 .State.Status~\\\(exited\\\|stopped\\\) +t DELETE libpod/containers/mytop 204 diff --git a/test/apiv2/40-pods.at b/test/apiv2/40-pods.at index 8b5651cff..70d9f8203 100644 --- a/test/apiv2/40-pods.at +++ b/test/apiv2/40-pods.at @@ -12,20 +12,21 @@ t GET libpod/pods/notfoo/exists 404 t GET libpod/pods/foo/json 200 \ .Config.name=foo \ .Config.id=$pod_id \ - .Containers=null + .Containers\|length=1 t GET libpod/pods/json 200 \ - .[0].Config.name=foo \ - .[0].Config.id=$pod_id \ - .[0].Containers=null + .[0].Name=foo \ + .[0].Id=$pod_id \ + .[0].Containers\|length=1 # Cannot create a dup pod with the same name t POST libpod/pods/create name=foo 409 .cause="pod already exists" #t POST libpod/pods/create a=b 400 .cause='bad parameter' # FIXME: unimplemented -if root; then - t POST libpod/pods/foo/pause '' 204 +if root || have_cgroupsv2; then + t POST libpod/pods/foo/pause '' 200 else + # Rootless cgroupsv1 : unsupported t POST libpod/pods/foo/pause '' 500 \ .cause="this container does not have a cgroup" \ .message~".*pause pods containing rootless containers with cgroup V1" @@ -33,7 +34,7 @@ fi t POST libpod/pods/foo/unpause '' 200 t POST libpod/pods/foo/unpause '' 200 # (2nd time) t POST libpod/pods/foo/stop '' 304 -t POST libpod/pods/foo/restart '' 500 .cause="no such container" +t POST libpod/pods/foo/restart '' 200 t POST libpod/pods/bar/restart '' 404 @@ -43,7 +44,7 @@ t POST libpod/pods/bar/restart '' 404 #t POST libpod/pods/prune 'a=b' 400 # FIXME: 2020-02-24 returns 200 # Clean up; and try twice, making sure that the second time fails -t DELETE libpod/pods/foo 204 +t DELETE libpod/pods/foo 200 t DELETE libpod/pods/foo 404 # vim: filetype=sh diff --git a/test/apiv2/test-apiv2 b/test/apiv2/test-apiv2 index bc2ed142c..f0fb4ae34 100755 --- a/test/apiv2/test-apiv2 +++ b/test/apiv2/test-apiv2 @@ -290,6 +290,12 @@ function rootless() { test "$ROOTLESS" = "true" } +# True if cgroups v2 are enabled +function have_cgroupsv2() { + cgroup_type=$(stat -f -c %T /sys/fs/cgroup) + test "$cgroup_type" = "cgroup2fs" +} + # END infrastructure code ############################################################################### # BEGIN sanity checks diff --git a/test/e2e/build_test.go b/test/e2e/build_test.go index b4e400549..8b03e9386 100644 --- a/test/e2e/build_test.go +++ b/test/e2e/build_test.go @@ -6,6 +6,7 @@ import ( "io/ioutil" "os" "path/filepath" + "runtime" "strings" . "github.com/containers/libpod/test/utils" @@ -43,6 +44,15 @@ var _ = Describe("Podman build", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + iid := session.OutputToStringArray()[len(session.OutputToStringArray())-1] + + // Verify that OS and Arch are being set + inspect := podmanTest.PodmanNoCache([]string{"inspect", iid}) + inspect.WaitWithDefaultTimeout() + data := inspect.InspectImageJSON() + Expect(data[0].Os).To(Equal(runtime.GOOS)) + Expect(data[0].Architecture).To(Equal(runtime.GOARCH)) + session = podmanTest.PodmanNoCache([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -142,4 +152,27 @@ var _ = Describe("Podman build", func() { Expect(strings.Fields(session.OutputToString())). To(ContainElement("scratch")) }) + + It("podman build basic alpine and print id to external file", func() { + + // Switch to temp dir and restore it afterwards + cwd, err := os.Getwd() + Expect(err).To(BeNil()) + Expect(os.Chdir(os.TempDir())).To(BeNil()) + defer Expect(os.Chdir(cwd)).To(BeNil()) + + targetPath := filepath.Join(os.TempDir(), "dir") + targetFile := filepath.Join(targetPath, "idFile") + + session := podmanTest.PodmanNoCache([]string{"build", "build/basicalpine", "--iidfile", targetFile}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + id, _ := ioutil.ReadFile(targetFile) + + // Verify that id is correct + inspect := podmanTest.PodmanNoCache([]string{"inspect", string(id)}) + inspect.WaitWithDefaultTimeout() + data := inspect.InspectImageJSON() + Expect(data[0].ID).To(Equal(string(id))) + }) }) diff --git a/test/e2e/commit_test.go b/test/e2e/commit_test.go index d4503d5a8..72387ed8c 100644 --- a/test/e2e/commit_test.go +++ b/test/e2e/commit_test.go @@ -1,7 +1,9 @@ package integration import ( + "io/ioutil" "os" + "path/filepath" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" @@ -234,4 +236,30 @@ var _ = Describe("Podman commit", func() { } Expect(envMap["TEST=1=1-01=9.01"]).To(BeTrue()) }) + + It("podman commit container and print id to external file", func() { + // Switch to temp dir and restore it afterwards + cwd, err := os.Getwd() + Expect(err).To(BeNil()) + Expect(os.Chdir(os.TempDir())).To(BeNil()) + targetPath := filepath.Join(os.TempDir(), "dir") + Expect(os.MkdirAll(targetPath, 0755)).To(BeNil()) + targetFile := filepath.Join(targetPath, "idFile") + defer Expect(os.RemoveAll(targetFile)).To(BeNil()) + defer Expect(os.Chdir(cwd)).To(BeNil()) + + _, ec, _ := podmanTest.RunLsContainer("test1") + Expect(ec).To(Equal(0)) + Expect(podmanTest.NumberOfContainers()).To(Equal(1)) + + session := podmanTest.Podman([]string{"commit", "test1", "foobar.com/test1-image:latest", "--iidfile", targetFile}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + id, _ := ioutil.ReadFile(targetFile) + check := podmanTest.Podman([]string{"inspect", "foobar.com/test1-image:latest"}) + check.WaitWithDefaultTimeout() + data := check.InspectImageJSON() + Expect(data[0].ID).To(Equal(string(id))) + }) }) diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go index 16b971e65..b10c3237d 100644 --- a/test/e2e/common_test.go +++ b/test/e2e/common_test.go @@ -15,6 +15,7 @@ import ( "time" "github.com/containers/libpod/libpod" + "github.com/containers/libpod/libpod/define" "github.com/containers/libpod/pkg/inspect" "github.com/containers/libpod/pkg/rootless" . "github.com/containers/libpod/test/utils" @@ -320,7 +321,7 @@ func (s *PodmanSessionIntegration) InspectImageJSON() []inspect.ImageData { } // InspectContainer returns a container's inspect data in JSON format -func (p *PodmanTestIntegration) InspectContainer(name string) []libpod.InspectContainerData { +func (p *PodmanTestIntegration) InspectContainer(name string) []define.InspectContainerData { cmd := []string{"inspect", name} session := p.Podman(cmd) session.WaitWithDefaultTimeout() @@ -492,8 +493,8 @@ func (p *PodmanTestIntegration) PullImage(image string) error { // InspectContainerToJSON takes the session output of an inspect // container and returns json -func (s *PodmanSessionIntegration) InspectContainerToJSON() []libpod.InspectContainerData { - var i []libpod.InspectContainerData +func (s *PodmanSessionIntegration) InspectContainerToJSON() []define.InspectContainerData { + var i []define.InspectContainerData err := json.Unmarshal(s.Out.Contents(), &i) Expect(err).To(BeNil()) return i @@ -519,6 +520,21 @@ func (p *PodmanTestIntegration) CreatePod(name string) (*PodmanSessionIntegratio return session, session.ExitCode(), session.OutputToString() } +// CreatePod creates a pod with no infra container and some labels. +// it optionally takes a pod name +func (p *PodmanTestIntegration) CreatePodWithLabels(name string, labels map[string]string) (*PodmanSessionIntegration, int, string) { + var podmanArgs = []string{"pod", "create", "--infra=false", "--share", ""} + if name != "" { + podmanArgs = append(podmanArgs, "--name", name) + } + for labelKey, labelValue := range labels { + podmanArgs = append(podmanArgs, "--label", fmt.Sprintf("%s=%s", labelKey, labelValue)) + } + session := p.Podman(podmanArgs) + session.WaitWithDefaultTimeout() + return session, session.ExitCode(), session.OutputToString() +} + func (p *PodmanTestIntegration) RunTopContainerInPod(name, pod string) *PodmanSessionIntegration { var podmanArgs = []string{"run", "--pod", pod} if name != "" { diff --git a/test/e2e/config.go b/test/e2e/config.go index 95b0481b3..49a47c7da 100644 --- a/test/e2e/config.go +++ b/test/e2e/config.go @@ -10,7 +10,7 @@ var ( ALPINEAMD64ID = "961769676411f082461f9ef46626dd7a2d1e2b2a38e6a44364bcbecf51e66dd4" ALPINEARM64DIGEST = "docker.io/library/alpine@sha256:db7f3dcef3d586f7dd123f107c93d7911515a5991c4b9e51fa2a43e46335a43e" ALPINEARM64ID = "915beeae46751fc564998c79e73a1026542e945ca4f73dc841d09ccc6c2c0672" - infra = "k8s.gcr.io/pause:3.1" + infra = "k8s.gcr.io/pause:3.2" BB = "docker.io/library/busybox:latest" healthcheck = "docker.io/libpod/alpine_healthcheck:latest" ImageCacheDir = "/tmp/podman/imagecachedir" diff --git a/test/e2e/config/containers-caps.conf b/test/e2e/config/containers-caps.conf new file mode 100644 index 000000000..7b964e4a7 --- /dev/null +++ b/test/e2e/config/containers-caps.conf @@ -0,0 +1,17 @@ +[containers] + +# List of default capabilities for containers. If it is empty or commented out, +# the default capabilities defined in the container engine will be added. +# +default_capabilities = [ + "CHOWN", + "DAC_OVERRIDE", + "FOWNER", + "FSETID", + "KILL", + "MKNOD", + "NET_BIND_SERVICE", + "SETGID", + "SETPCAP", + "SETUID", +] diff --git a/test/e2e/config/containers-ns.conf b/test/e2e/config/containers-ns.conf new file mode 100644 index 000000000..d2cf5b03f --- /dev/null +++ b/test/e2e/config/containers-ns.conf @@ -0,0 +1,24 @@ +[containers] + +pidns = "host" +netns = "host" +ipcns = "host" +utsns = "host" +userns = "host" +cgroupns = "host" + +# List of default capabilities for containers. If it is empty or commented out, +# the default capabilities defined in the container engine will be added. +# +default_capabilities = [ + "CHOWN", + "DAC_OVERRIDE", + "FOWNER", + "FSETID", + "KILL", + "MKNOD", + "NET_BIND_SERVICE", + "SETGID", + "SETPCAP", + "SETUID", +] diff --git a/test/e2e/config/containers.conf b/test/e2e/config/containers.conf new file mode 100644 index 000000000..55d18f5e8 --- /dev/null +++ b/test/e2e/config/containers.conf @@ -0,0 +1,50 @@ +[containers] + +# A list of ulimits to be set in containers by default, specified as +# "<ulimit name>=<soft limit>:<hard limit>", for example: +# "nofile=1024:2048" +# See setrlimit(2) for a list of resource names. +# Any limit not specified here will be inherited from the process launching the +# container engine. +# Ulimits has limits for non privileged container engines. +# +default_ulimits = [ + "nofile=500:500", +] + +# Environment variable list for the conmon process; used for passing necessary +# environment variables to conmon or the runtime. +# +env = [ + "PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin", + "foo=bar", +] + +# container engines use container separation using MAC(SELinux) labeling. +# Flag is ignored on label disabled systems. +# +label = true + +# Size of /dev/shm. Specified as <number><unit>. +# Unit is optional, values: +# b (bytes), k (kilobytes), m (megabytes), or g (gigabytes). +# If the unit is omitted, the system uses bytes. +# +shm_size = "201k" + +# List of devices. Specified as +# "<device-on-host>:<device-on-container>:<permissions>", for example: +# "/dev/sdc:/dev/xvdc:rwm". +# If it is empty or commented out, only the default devices will be used +# +devices = [ + "/dev/zero:/dev/notone,rwm", +] + +default_sysctls = [ + "net.ipv4.ping_group_range=0 1000", +] + +dns_searches=[ "foobar.com", ] +dns_servers=[ "1.2.3.4", ] +dns_options=[ "debug", ] diff --git a/test/e2e/containers_conf_test.go b/test/e2e/containers_conf_test.go new file mode 100644 index 000000000..a2ef7eb4a --- /dev/null +++ b/test/e2e/containers_conf_test.go @@ -0,0 +1,214 @@ +// +build !remoteclient + +package integration + +import ( + "fmt" + "io/ioutil" + "os" + "os/exec" + "path/filepath" + "strings" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman run", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() + podmanTest.SeedImages() + os.Setenv("CONTAINERS_CONF", "config/containers.conf") + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + processTestResult(f) + os.Unsetenv("CONTAINERS_CONF") + }) + + It("podman run limits test", func() { + SkipIfRootless() + //containers.conf is set to "nofile=500:500" + session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("500")) + + session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=2048:2048", fedoraMinimal, "ulimit", "-n"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("2048")) + }) + + It("podman run with containers.conf having additional env", func() { + //containers.conf default env includes foo + session := podmanTest.Podman([]string{"run", ALPINE, "printenv"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("foo=bar")) + }) + + It("podman run with additional devices", func() { + //containers.conf devices includes notone + session := podmanTest.Podman([]string{"run", "--device", "/dev/null:/dev/bar", ALPINE, "ls", "/dev"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("bar")) + Expect(session.OutputToString()).To(ContainSubstring("notone")) + }) + + It("podman run shm-size", func() { + //containers.conf default sets shm-size=201k, which ends up as 200k + session := podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("size=200k")) + }) + + It("podman Capabilities in containers.conf", func() { + SkipIfRootless() + os.Setenv("CONTAINERS_CONF", "config/containers.conf") + cap := podmanTest.Podman([]string{"run", ALPINE, "grep", "CapEff", "/proc/self/status"}) + cap.WaitWithDefaultTimeout() + Expect(cap.ExitCode()).To(Equal(0)) + + os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") + session := podmanTest.Podman([]string{"run", "busybox", "grep", "CapEff", "/proc/self/status"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).ToNot(Equal(cap.OutputToString())) + }) + + It("podman Regular capabilties", func() { + SkipIfRootless() + os.Setenv("CONTAINERS_CONF", "config/containers.conf") + setup := podmanTest.RunTopContainer("test1") + setup.WaitWithDefaultTimeout() + result := podmanTest.Podman([]string{"top", "test1", "capeff"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(result.OutputToString()).To(ContainSubstring("SYS_CHROOT")) + Expect(result.OutputToString()).To(ContainSubstring("NET_RAW")) + }) + + It("podman drop capabilties", func() { + os.Setenv("CONTAINERS_CONF", "config/containers-caps.conf") + setup := podmanTest.RunTopContainer("test1") + setup.WaitWithDefaultTimeout() + result := podmanTest.Podman([]string{"container", "top", "test1", "capeff"}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + Expect(result.OutputToString()).ToNot(ContainSubstring("SYS_CHROOT")) + Expect(result.OutputToString()).ToNot(ContainSubstring("NET_RAW")) + }) + + verifyNSHandling := func(nspath, option string) { + os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") + //containers.conf default ipcns to default to host + session := podmanTest.Podman([]string{"run", ALPINE, "ls", "-l", nspath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + fields := strings.Split(session.OutputToString(), " ") + ctrNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + + cmd := exec.Command("ls", "-l", nspath) + res, err := cmd.Output() + Expect(err).To(BeNil()) + fields = strings.Split(string(res), " ") + hostNS := strings.TrimSuffix(fields[len(fields)-1], "\n") + Expect(hostNS).To(Equal(ctrNS)) + + session = podmanTest.Podman([]string{"run", option, "private", ALPINE, "ls", "-l", nspath}) + fields = strings.Split(session.OutputToString(), " ") + ctrNS = fields[len(fields)-1] + Expect(hostNS).ToNot(Equal(ctrNS)) + } + + It("podman compare netns", func() { + verifyNSHandling("/proc/self/ns/net", "--network") + }) + + It("podman compare ipcns", func() { + verifyNSHandling("/proc/self/ns/ipc", "--ipc") + }) + + It("podman compare utsns", func() { + verifyNSHandling("/proc/self/ns/uts", "--uts") + }) + + It("podman compare pidns", func() { + verifyNSHandling("/proc/self/ns/pid", "--pid") + }) + + It("podman compare cgroupns", func() { + verifyNSHandling("/proc/self/ns/cgroup", "--cgroupns") + }) + + It("podman containers.conf additionalvolumes", func() { + conffile := filepath.Join(podmanTest.TempDir, "container.conf") + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + err := ioutil.WriteFile(conffile, []byte(fmt.Sprintf("[containers]\nvolumes=[\"%s:%s:Z\",]\n", tempdir, tempdir)), 0755) + if err != nil { + os.Exit(1) + } + + os.Setenv("CONTAINERS_CONF", conffile) + result := podmanTest.Podman([]string{"run", ALPINE, "ls", tempdir}) + result.WaitWithDefaultTimeout() + Expect(result.ExitCode()).To(Equal(0)) + }) + + It("podman run containers.conf sysctl test", func() { + SkipIfRootless() + //containers.conf is set to "net.ipv4.ping_group_range=0 1000" + session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "cat", "/proc/sys/net/ipv4/ping_group_range"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("1000")) + }) + + It("podman run containers.conf search domain", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session.LineInOuputStartsWith("search foobar.com") + }) + + It("podman run add dns server", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session.LineInOuputStartsWith("server 1.2.3.4") + }) + + It("podman run add dns option", func() { + session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session.LineInOuputStartsWith("options debug") + }) + + It("podman run containers.conf remove all search domain", func() { + session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.LineInOuputStartsWith("search")).To(BeFalse()) + }) +}) diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index ed4eb3335..ab806f683 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -1,6 +1,7 @@ package integration import ( + "fmt" "os" "strings" @@ -244,4 +245,27 @@ var _ = Describe("Podman exec", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman exec preserves --group-add groups", func() { + groupName := "group1" + gid := "4444" + ctrName1 := "ctr1" + ctr1 := podmanTest.Podman([]string{"run", "-ti", "--name", ctrName1, fedoraMinimal, "groupadd", "-g", gid, groupName}) + ctr1.WaitWithDefaultTimeout() + Expect(ctr1.ExitCode()).To(Equal(0)) + + imgName := "img1" + commit := podmanTest.Podman([]string{"commit", ctrName1, imgName}) + commit.WaitWithDefaultTimeout() + Expect(commit.ExitCode()).To(Equal(0)) + + ctrName2 := "ctr2" + ctr2 := podmanTest.Podman([]string{"run", "-d", "--name", ctrName2, "--group-add", groupName, imgName, "sleep", "300"}) + ctr2.WaitWithDefaultTimeout() + Expect(ctr2.ExitCode()).To(Equal(0)) + + exec := podmanTest.Podman([]string{"exec", "-ti", ctrName2, "id"}) + exec.WaitWithDefaultTimeout() + Expect(exec.ExitCode()).To(Equal(0)) + Expect(strings.Contains(exec.OutputToString(), fmt.Sprintf("%s(%s)", gid, groupName))).To(BeTrue()) + }) }) diff --git a/test/e2e/generate_kube_test.go b/test/e2e/generate_kube_test.go index 603edbe6b..389f2c822 100644 --- a/test/e2e/generate_kube_test.go +++ b/test/e2e/generate_kube_test.go @@ -10,7 +10,7 @@ import ( "github.com/ghodss/yaml" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "k8s.io/api/core/v1" + v1 "k8s.io/api/core/v1" ) var _ = Describe("Podman generate kube", func() { @@ -69,6 +69,51 @@ var _ = Describe("Podman generate kube", func() { Expect(numContainers).To(Equal(1)) }) + It("podman generate service kube on container with --security-opt level", func() { + session := podmanTest.Podman([]string{"create", "--name", "test", "--security-opt", "label=level:s0:c100,c200", "alpine"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", "test"}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + pod := new(v1.Pod) + err := yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + Expect(kube.OutputToString()).To(ContainSubstring("level: s0:c100,c200")) + }) + + It("podman generate service kube on container with --security-opt disable", func() { + session := podmanTest.Podman([]string{"create", "--name", "test-disable", "--security-opt", "label=disable", "alpine"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", "test-disable"}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + pod := new(v1.Pod) + err = yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + Expect(kube.OutputToString()).To(ContainSubstring("type: spc_t")) + }) + + It("podman generate service kube on container with --security-opt type", func() { + session := podmanTest.Podman([]string{"create", "--name", "test", "--security-opt", "label=type:foo_bar_t", "alpine"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + kube := podmanTest.Podman([]string{"generate", "kube", "test"}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + pod := new(v1.Pod) + err = yaml.Unmarshal(kube.Out.Contents(), pod) + Expect(err).To(BeNil()) + Expect(kube.OutputToString()).To(ContainSubstring("type: foo_bar_t")) + }) + It("podman generate service kube on container", func() { session := podmanTest.RunTopContainer("top") session.WaitWithDefaultTimeout() diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index d0dadd09d..e5ab0b854 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -191,7 +191,35 @@ var _ = Describe("Podman generate systemd", func() { found, _ := session.GrepString("# container-foo.service") Expect(found).To(BeTrue()) - found, _ = session.GrepString("stop --ignore --cidfile /%t/%n-cid -t 42") + found, _ = session.GrepString("stop --ignore --cidfile %t/%n-cid -t 42") + Expect(found).To(BeTrue()) + }) + + It("podman generate systemd --new without explicit detaching param", func() { + n := podmanTest.Podman([]string{"create", "--name", "foo", "alpine", "top"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "--new", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // Grepping the output (in addition to unit tests) + found, _ := session.GrepString("--cgroups=no-conmon -d") + Expect(found).To(BeTrue()) + }) + + It("podman generate systemd --new with explicit detaching param in middle", func() { + n := podmanTest.Podman([]string{"create", "--name", "foo", "-d", "alpine", "top"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "--new", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // Grepping the output (in addition to unit tests) + found, _ := session.GrepString("--name foo -d alpine top") Expect(found).To(BeTrue()) }) diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 43f08bf03..dc5e91c72 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -122,6 +122,8 @@ func populateCache(podman *PodmanTestIntegration) { for _, image := range CACHE_IMAGES { podman.RestoreArtifactToCache(image) } + // logformatter uses this to recognize the first test + fmt.Printf("-----------------------------\n") } func removeCache() { diff --git a/test/e2e/network_create_test.go b/test/e2e/network_create_test.go index b83757cc0..7eccaa9ab 100644 --- a/test/e2e/network_create_test.go +++ b/test/e2e/network_create_test.go @@ -58,7 +58,7 @@ func genericPluginsToPortMap(plugins interface{}, pluginType string) (network.Po } func (p *PodmanTestIntegration) removeCNINetwork(name string) { - session := p.Podman([]string{"network", "rm", name}) + session := p.Podman([]string{"network", "rm", "-f", name}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(BeZero()) } diff --git a/test/e2e/network_test.go b/test/e2e/network_test.go index 9aed5351a..440d307b5 100644 --- a/test/e2e/network_test.go +++ b/test/e2e/network_test.go @@ -4,13 +4,15 @@ package integration import ( "fmt" + "io/ioutil" + "os" + "path/filepath" + "strings" + . "github.com/containers/libpod/test/utils" "github.com/containers/storage/pkg/stringid" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "io/ioutil" - "os" - "path/filepath" ) func writeConf(conf []byte, confPath string) { @@ -155,4 +157,76 @@ var _ = Describe("Podman network", func() { Expect(session.IsJSONOutputValid()).To(BeTrue()) }) + It("podman inspect container single CNI network", func() { + SkipIfRootless() + netName := "testNetSingleCNI" + network := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.50.0/24", netName}) + network.WaitWithDefaultTimeout() + Expect(network.ExitCode()).To(BeZero()) + defer podmanTest.removeCNINetwork(netName) + + ctrName := "testCtr" + container := podmanTest.Podman([]string{"run", "-dt", "--network", netName, "--name", ctrName, ALPINE, "top"}) + container.WaitWithDefaultTimeout() + Expect(container.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", ctrName}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(BeZero()) + conData := inspect.InspectContainerToJSON() + Expect(len(conData)).To(Equal(1)) + Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(1)) + net, ok := conData[0].NetworkSettings.Networks[netName] + Expect(ok).To(BeTrue()) + Expect(net.NetworkID).To(Equal(netName)) + Expect(net.IPPrefixLen).To(Equal(24)) + Expect(strings.HasPrefix(net.IPAddress, "10.50.50.")).To(BeTrue()) + + // Necessary to ensure the CNI network is removed cleanly + rmAll := podmanTest.Podman([]string{"rm", "-f", ctrName}) + rmAll.WaitWithDefaultTimeout() + Expect(rmAll.ExitCode()).To(BeZero()) + }) + + It("podman inspect container two CNI networks", func() { + SkipIfRootless() + netName1 := "testNetTwoCNI1" + network1 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.0/25", netName1}) + network1.WaitWithDefaultTimeout() + Expect(network1.ExitCode()).To(BeZero()) + defer podmanTest.removeCNINetwork(netName1) + + netName2 := "testNetTwoCNI2" + network2 := podmanTest.Podman([]string{"network", "create", "--subnet", "10.50.51.128/26", netName2}) + network2.WaitWithDefaultTimeout() + Expect(network2.ExitCode()).To(BeZero()) + defer podmanTest.removeCNINetwork(netName2) + + ctrName := "testCtr" + container := podmanTest.Podman([]string{"run", "-dt", "--network", fmt.Sprintf("%s,%s", netName1, netName2), "--name", ctrName, ALPINE, "top"}) + container.WaitWithDefaultTimeout() + Expect(container.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", ctrName}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(BeZero()) + conData := inspect.InspectContainerToJSON() + Expect(len(conData)).To(Equal(1)) + Expect(len(conData[0].NetworkSettings.Networks)).To(Equal(2)) + net1, ok := conData[0].NetworkSettings.Networks[netName1] + Expect(ok).To(BeTrue()) + Expect(net1.NetworkID).To(Equal(netName1)) + Expect(net1.IPPrefixLen).To(Equal(25)) + Expect(strings.HasPrefix(net1.IPAddress, "10.50.51.")).To(BeTrue()) + net2, ok := conData[0].NetworkSettings.Networks[netName2] + Expect(ok).To(BeTrue()) + Expect(net2.NetworkID).To(Equal(netName2)) + Expect(net2.IPPrefixLen).To(Equal(26)) + Expect(strings.HasPrefix(net2.IPAddress, "10.50.51.")).To(BeTrue()) + + // Necessary to ensure the CNI network is removed cleanly + rmAll := podmanTest.Podman([]string{"rm", "-f", ctrName}) + rmAll.WaitWithDefaultTimeout() + Expect(rmAll.ExitCode()).To(BeZero()) + }) }) diff --git a/test/e2e/pod_ps_test.go b/test/e2e/pod_ps_test.go index aa07be55c..551ad3818 100644 --- a/test/e2e/pod_ps_test.go +++ b/test/e2e/pod_ps_test.go @@ -204,4 +204,27 @@ var _ = Describe("Podman ps", func() { Expect(session.ExitCode()).To(Equal(0)) Expect(session.OutputToString()).To(BeEmpty()) }) + + It("podman pod ps filter labels", func() { + _, ec, podid1 := podmanTest.CreatePod("") + Expect(ec).To(Equal(0)) + + _, ec, podid2 := podmanTest.CreatePodWithLabels("", map[string]string{ + "io.podman.test.label": "value1", + "io.podman.test.key": "irrelevant-value", + }) + Expect(ec).To(Equal(0)) + + _, ec, podid3 := podmanTest.CreatePodWithLabels("", map[string]string{ + "io.podman.test.label": "value2", + }) + Expect(ec).To(Equal(0)) + + session := podmanTest.Podman([]string{"pod", "ps", "--no-trunc", "--filter", "label=io.podman.test.key", "--filter", "label=io.podman.test.label=value1"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(Not(ContainSubstring(podid1))) + Expect(session.OutputToString()).To(ContainSubstring(podid2)) + Expect(session.OutputToString()).To(Not(ContainSubstring(podid3))) + }) }) diff --git a/test/e2e/prune_test.go b/test/e2e/prune_test.go index c9b01ad4a..672b0e103 100644 --- a/test/e2e/prune_test.go +++ b/test/e2e/prune_test.go @@ -59,6 +59,34 @@ var _ = Describe("Podman prune", func() { Expect(podmanTest.NumberOfContainers()).To(Equal(1)) }) + It("podman container prune after create containers", func() { + create := podmanTest.Podman([]string{"create", "--name", "test", BB}) + create.WaitWithDefaultTimeout() + Expect(create.ExitCode()).To(Equal(0)) + + prune := podmanTest.Podman([]string{"container", "prune", "-f"}) + prune.WaitWithDefaultTimeout() + Expect(prune.ExitCode()).To(Equal(0)) + + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + }) + + It("podman container prune after create & init containers", func() { + create := podmanTest.Podman([]string{"create", "--name", "test", BB}) + create.WaitWithDefaultTimeout() + Expect(create.ExitCode()).To(Equal(0)) + + init := podmanTest.Podman([]string{"init", "test"}) + init.WaitWithDefaultTimeout() + Expect(init.ExitCode()).To(Equal(0)) + + prune := podmanTest.Podman([]string{"container", "prune", "-f"}) + prune.WaitWithDefaultTimeout() + Expect(prune.ExitCode()).To(Equal(0)) + + Expect(podmanTest.NumberOfContainers()).To(Equal(0)) + }) + It("podman image prune none images", func() { SkipIfRemote() podmanTest.BuildImage(pruneImage, "alpine_bash:latest", "true") diff --git a/test/e2e/run_security_labels.go b/test/e2e/run_security_labels.go new file mode 100644 index 000000000..a04bdc739 --- /dev/null +++ b/test/e2e/run_security_labels.go @@ -0,0 +1,152 @@ +// +build !remoteclient + +package integration + +import ( + "os" + "strings" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman generate kube", func() { + var ( + tempdir string + err error + podmanTest *PodmanTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + podmanTest = PodmanTestCreate(tempdir) + podmanTest.Setup() + podmanTest.SeedImages() + + }) + + AfterEach(func() { + podmanTest.Cleanup() + f := CurrentGinkgoTestDescription() + processTestResult(f) + }) + + It("podman security labels", func() { + test1 := podmanTest.Podman([]string{"create", "--label", "io.containers.capabilities=setuid,setgid", "--name", "test1", "alpine", "echo", "test1"}) + test1.WaitWithDefaultTimeout() + Expect(test1.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Equal("CAP_SETUID,CAP_SETGID")) + }) + + It("podman bad security labels", func() { + test1 := podmanTest.Podman([]string{"create", "--label", "io.containers.capabilities=sys_admin", "--name", "test1", "alpine", "echo", "test1"}) + test1.WaitWithDefaultTimeout() + Expect(test1.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Not(Equal("CAP_SYS_ADMIN"))) + }) + + It("podman --cap-add sys_admin security labels", func() { + test1 := podmanTest.Podman([]string{"create", "--cap-add", "SYS_ADMIN", "--label", "io.containers.capabilities=sys_admin", "--name", "test1", "alpine", "echo", "test1"}) + test1.WaitWithDefaultTimeout() + Expect(test1.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Equal("CAP_SYS_ADMIN")) + }) + + It("podman --cap-drop all sys_admin security labels", func() { + test1 := podmanTest.Podman([]string{"create", "--cap-drop", "all", "--label", "io.containers.capabilities=sys_admin", "--name", "test1", "alpine", "echo", "test1"}) + test1.WaitWithDefaultTimeout() + Expect(test1.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Equal("")) + }) + + It("podman security labels from image", func() { + test1 := podmanTest.Podman([]string{"create", "--name", "test1", "alpine", "echo", "test1"}) + test1.WaitWithDefaultTimeout() + Expect(test1.ExitCode()).To(BeZero()) + + commit := podmanTest.Podman([]string{"commit", "-c", "label=io.containers.capabilities=sys_chroot,net_raw", "test1", "image1"}) + commit.WaitWithDefaultTimeout() + Expect(commit.ExitCode()).To(BeZero()) + + image1 := podmanTest.Podman([]string{"create", "--name", "test2", "image1", "echo", "test1"}) + image1.WaitWithDefaultTimeout() + Expect(image1.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test2"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Equal("CAP_SYS_CHROOT,CAP_NET_RAW")) + + }) + + It("podman --privileged security labels", func() { + pull := podmanTest.Podman([]string{"create", "--privileged", "--label", "io.containers.capabilities=setuid,setgid", "--name", "test1", "alpine", "echo", "test"}) + pull.WaitWithDefaultTimeout() + Expect(pull.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Not(Equal("CAP_SETUID,CAP_SETGID"))) + }) + + It("podman container runlabel (podman --version)", func() { + PodmanDockerfile := ` +FROM alpine:latest +LABEL io.containers.capabilities=chown,mknod` + + image := "podman-caps:podman" + podmanTest.BuildImage(PodmanDockerfile, image, "false") + + test1 := podmanTest.Podman([]string{"create", "--name", "test1", image, "echo", "test1"}) + test1.WaitWithDefaultTimeout() + Expect(test1.ExitCode()).To(BeZero()) + + inspect := podmanTest.Podman([]string{"inspect", "test1"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + + ctr := inspect.InspectContainerToJSON() + caps := strings.Join(ctr[0].EffectiveCaps, ",") + Expect(caps).To(Equal("CAP_CHOWN,CAP_MKNOD")) + }) + +}) diff --git a/test/e2e/search_test.go b/test/e2e/search_test.go index 6d762d338..9ba0241fe 100644 --- a/test/e2e/search_test.go +++ b/test/e2e/search_test.go @@ -5,13 +5,14 @@ package integration import ( "bytes" "fmt" - . "github.com/containers/libpod/test/utils" - . "github.com/onsi/ginkgo" - . "github.com/onsi/gomega" "io/ioutil" "os" "strconv" "text/template" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" ) type endpoint struct { diff --git a/test/e2e/volume_prune_test.go b/test/e2e/volume_prune_test.go index ba249278b..3049646b0 100644 --- a/test/e2e/volume_prune_test.go +++ b/test/e2e/volume_prune_test.go @@ -89,7 +89,7 @@ var _ = Describe("Podman volume prune", func() { session = podmanTest.Podman([]string{"volume", "ls"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) - Expect(len(session.OutputToStringArray())).To(Equal(2)) + Expect(len(session.OutputToStringArray())).To(Equal(0)) podmanTest.Cleanup() }) diff --git a/test/endpoint/endpoint.go b/test/endpoint/endpoint.go index f1634b6f0..5b5484865 100644 --- a/test/endpoint/endpoint.go +++ b/test/endpoint/endpoint.go @@ -26,7 +26,7 @@ var ( ImageCacheDir = "/tmp/podman/imagecachedir" VarlinkBinary = "/usr/bin/varlink" ALPINE = "docker.io/library/alpine:latest" - infra = "k8s.gcr.io/pause:3.1" + infra = "k8s.gcr.io/pause:3.2" BB = "docker.io/library/busybox:latest" redis = "docker.io/library/redis:alpine" fedoraMinimal = "quay.io/libpod/fedora-minimal:latest" diff --git a/test/system/010-images.bats b/test/system/010-images.bats index 3224c9b42..6957d4830 100644 --- a/test/system/010-images.bats +++ b/test/system/010-images.bats @@ -27,11 +27,11 @@ load helpers @test "podman images - json" { # 'created': podman includes fractional seconds, podman-remote does not tests=" -names[0] | $PODMAN_TEST_IMAGE_FQN -id | [0-9a-f]\\\{64\\\} -digest | sha256:[0-9a-f]\\\{64\\\} -created | [0-9-]\\\+T[0-9:.]\\\+Z -size | [0-9]\\\+ +Names[0] | $PODMAN_TEST_IMAGE_FQN +ID | [0-9a-f]\\\{64\\\} +Digest | sha256:[0-9a-f]\\\{64\\\} +CreatedAt | [0-9-]\\\+T[0-9:.]\\\+Z +Size | [0-9]\\\+ " run_podman images -a --format json diff --git a/test/system/030-run.bats b/test/system/030-run.bats index f1e9776c1..98c65f788 100644 --- a/test/system/030-run.bats +++ b/test/system/030-run.bats @@ -136,4 +136,26 @@ echo $rand | 0 | $rand run_podman rmi busybox } +# 'run --rmi' deletes the image in the end unless it's used by another container +@test "podman run --rmi" { + skip_if_remote + + # Name of a nonlocal image. It should be pulled in by the first 'run' + NONLOCAL_IMAGE=busybox + run_podman 1 image exists $NONLOCAL_IMAGE + + # Run a container, without --rm; this should block subsequent --rmi + run_podman run --name keepme $NONLOCAL_IMAGE /bin/true + run_podman image exists $NONLOCAL_IMAGE + + # Now try running with --rmi : it should succeed, but not remove the image + run_podman run --rmi --rm $NONLOCAL_IMAGE /bin/true + run_podman image exists $NONLOCAL_IMAGE + + # Remove the stray container, and run one more time with --rmi. + run_podman rm keepme + run_podman run --rmi --rm $NONLOCAL_IMAGE /bin/true + run_podman 1 image exists $NONLOCAL_IMAGE +} + # vim: filetype=sh diff --git a/test/system/130-kill.bats b/test/system/130-kill.bats index 8085b171e..7c2b9bed8 100644 --- a/test/system/130-kill.bats +++ b/test/system/130-kill.bats @@ -6,12 +6,23 @@ load helpers @test "podman kill - test signal handling in containers" { + # podman-remote and crun interact poorly in f31: crun seems to gobble up + # some signals. + # Workaround: run 'env --default-signal sh' instead of just 'sh' in + # the container. Since env on our regular alpine image doesn't support + # that flag, we need to pull fedora-minimal. See: + # https://github.com/containers/libpod/issues/5004 + # FIXME: remove this kludge once we get rid of podman-remote + local _image=$IMAGE + local _sh_cmd="sh" + if is_remote; then + _image=quay.io/libpod/fedora-minimal:latest + _sh_cmd="env --default-signal sh" + fi + # Start a container that will handle all signals by emitting 'got: N' local -a signals=(1 2 3 4 5 6 8 10 12 13 14 15 16 20 21 22 23 24 25 26 64) - # The --default-signal option not available in busybox implementation of 'env' in $IMAGE - # needed here to ensure handling of SIGINT inside container uses the default handler - _IMAGE=quay.io/libpod/fedora-minimal:latest - run_podman run -d $_IMAGE env --default-signal sh -c \ + run_podman run -d $_image $_sh_cmd -c \ "for i in ${signals[*]}; do trap \"echo got: \$i\" \$i; done; echo READY; while ! test -e /stop; do sleep 0.05; done; @@ -70,6 +81,10 @@ load helpers run_podman wait $cid run_podman rm $cid wait $podman_log_pid + + if [[ $_image != $IMAGE ]]; then + run_podman rmi $_image + fi } @test "podman kill - rejects invalid args" { |