diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/README.md | 3 | ||||
-rw-r--r-- | test/e2e/exec_test.go | 27 | ||||
-rw-r--r-- | test/e2e/generate_systemd_test.go | 110 | ||||
-rw-r--r-- | test/e2e/healthcheck_run_test.go | 2 | ||||
-rw-r--r-- | test/e2e/libpod_suite_remoteclient_test.go | 7 | ||||
-rw-r--r-- | test/e2e/libpod_suite_test.go | 7 | ||||
-rw-r--r-- | test/e2e/play_kube_test.go | 54 | ||||
-rw-r--r-- | test/e2e/pull_test.go | 28 | ||||
-rw-r--r-- | test/e2e/push_test.go | 8 | ||||
-rw-r--r-- | test/e2e/run_exit_test.go | 4 | ||||
-rw-r--r-- | test/e2e/run_selinux_test.go | 12 | ||||
-rw-r--r-- | test/e2e/run_test.go | 2 | ||||
-rw-r--r-- | test/e2e/run_volume_test.go | 8 | ||||
-rw-r--r-- | test/e2e/start_test.go | 4 | ||||
-rw-r--r-- | test/e2e/systemd_test.go | 48 | ||||
-rw-r--r-- | test/endpoint/config.go | 22 | ||||
-rw-r--r-- | test/endpoint/endpoint.go | 218 | ||||
-rw-r--r-- | test/endpoint/endpoint_suite_test.go | 70 | ||||
-rw-r--r-- | test/endpoint/exists_test.go | 66 | ||||
-rw-r--r-- | test/endpoint/pull_test.go | 44 | ||||
-rw-r--r-- | test/endpoint/setup.go | 219 | ||||
-rw-r--r-- | test/endpoint/version_test.go | 41 | ||||
-rw-r--r-- | test/system/065-cp.bats | 229 | ||||
-rw-r--r-- | test/system/070-build.bats | 16 |
24 files changed, 1206 insertions, 43 deletions
diff --git a/test/README.md b/test/README.md index 9bea679dc..d7710cc95 100644 --- a/test/README.md +++ b/test/README.md @@ -39,8 +39,9 @@ The following instructions assume your GOPATH is ~/go. Adjust as needed for your environment. ### Installing ginkgo -Build ginkgo and install it under $GOPATH/bin with the following command: +Build ginkgo and install it under $GOPATH/bin with the following commands: ``` +export GOCACHE="$(mktemp -d)" GOPATH=~/go make .install.ginkgo ``` If your PATH does not include $GOPATH/bin, you might consider adding it. diff --git a/test/e2e/exec_test.go b/test/e2e/exec_test.go index 3f9639fda..f3190978c 100644 --- a/test/e2e/exec_test.go +++ b/test/e2e/exec_test.go @@ -146,6 +146,25 @@ var _ = Describe("Podman exec", func() { Expect(session2.OutputToString()).To(Equal(testUser)) }) + It("podman exec with user from run", func() { + testUser := "guest" + setup := podmanTest.Podman([]string{"run", "--user", testUser, "-d", ALPINE, "top"}) + setup.WaitWithDefaultTimeout() + Expect(setup.ExitCode()).To(Equal(0)) + ctrID := setup.OutputToString() + + session := podmanTest.Podman([]string{"exec", ctrID, "whoami"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(testUser)) + + overrideUser := "root" + session = podmanTest.Podman([]string{"exec", "--user", overrideUser, ctrID, "whoami"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring(overrideUser)) + }) + It("podman exec simple working directory test", func() { setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() @@ -171,16 +190,14 @@ var _ = Describe("Podman exec", func() { session := podmanTest.Podman([]string{"exec", "--workdir", "/missing", "test1", "pwd"}) session.WaitWithDefaultTimeout() - Expect(session.ExitCode()).To(Equal(1)) + Expect(session.ExitCode()).To(Not(Equal(0))) session = podmanTest.Podman([]string{"exec", "-w", "/missing", "test1", "pwd"}) session.WaitWithDefaultTimeout() - Expect(session.ExitCode()).To(Equal(1)) + Expect(session.ExitCode()).To(Not(Equal(0))) }) It("podman exec cannot be invoked", func() { - SkipIfNotRunc() - setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) @@ -191,8 +208,6 @@ var _ = Describe("Podman exec", func() { }) It("podman exec command not found", func() { - SkipIfNotRunc() - setup := podmanTest.RunTopContainer("test1") setup.WaitWithDefaultTimeout() Expect(setup.ExitCode()).To(Equal(0)) diff --git a/test/e2e/generate_systemd_test.go b/test/e2e/generate_systemd_test.go index 5bb040206..314743a92 100644 --- a/test/e2e/generate_systemd_test.go +++ b/test/e2e/generate_systemd_test.go @@ -3,10 +3,11 @@ package integration import ( + "os" + . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" - "os" ) var _ = Describe("Podman generate systemd", func() { @@ -33,7 +34,7 @@ var _ = Describe("Podman generate systemd", func() { }) - It("podman generate systemd on bogus container", func() { + It("podman generate systemd on bogus container/pod", func() { session := podmanTest.Podman([]string{"generate", "systemd", "foobar"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) @@ -51,6 +52,19 @@ var _ = Describe("Podman generate systemd", func() { Expect(session.ExitCode()).To(Not(Equal(0))) }) + It("podman generate systemd good timeout value", func() { + session := podmanTest.Podman([]string{"create", "--name", "foobar", "alpine", "top"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + session = podmanTest.Podman([]string{"generate", "systemd", "--timeout", "1234", "foobar"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + found, _ := session.GrepString(" stop -t 1234 ") + Expect(found).To(BeTrue()) + }) + It("podman generate systemd", func() { n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) n.WaitWithDefaultTimeout() @@ -61,6 +75,23 @@ var _ = Describe("Podman generate systemd", func() { Expect(session.ExitCode()).To(Equal(0)) }) + It("podman generate systemd --files --name", func() { + n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--files", "--name", "nginx"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + for _, file := range session.OutputToStringArray() { + os.Remove(file) + } + + found, _ := session.GrepString("/container-nginx.service") + Expect(found).To(BeTrue()) + }) + It("podman generate systemd with timeout", func() { n := podmanTest.Podman([]string{"run", "--name", "nginx", "-dt", nginx}) n.WaitWithDefaultTimeout() @@ -69,6 +100,81 @@ var _ = Describe("Podman generate systemd", func() { session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "5", "nginx"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + + found, _ := session.GrepString("podman stop -t 5") + Expect(found).To(BeTrue()) }) + It("podman generate systemd pod --name", func() { + n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-1", "alpine", "top"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-2", "alpine", "top"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--timeout", "42", "--name", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + // Grepping the output (in addition to unit tests) + found, _ := session.GrepString("# pod-foo.service") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("Requires=container-foo-1.service container-foo-2.service") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("# container-foo-1.service") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString(" start foo-1") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("-infra") // infra container + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("# container-foo-2.service") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString(" stop -t 42 foo-2") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("BindsTo=pod-foo.service") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("PIDFile=") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("/userdata/conmon.pid") + Expect(found).To(BeTrue()) + }) + + It("podman generate systemd pod --name --files", func() { + n := podmanTest.Podman([]string{"pod", "create", "--name", "foo"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + n = podmanTest.Podman([]string{"create", "--pod", "foo", "--name", "foo-1", "alpine", "top"}) + n.WaitWithDefaultTimeout() + Expect(n.ExitCode()).To(Equal(0)) + + session := podmanTest.Podman([]string{"generate", "systemd", "--name", "--files", "foo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + + for _, file := range session.OutputToStringArray() { + os.Remove(file) + } + + found, _ := session.GrepString("/pod-foo.service") + Expect(found).To(BeTrue()) + + found, _ = session.GrepString("/container-foo-1.service") + Expect(found).To(BeTrue()) + }) }) diff --git a/test/e2e/healthcheck_run_test.go b/test/e2e/healthcheck_run_test.go index dafc8a837..e10aef427 100644 --- a/test/e2e/healthcheck_run_test.go +++ b/test/e2e/healthcheck_run_test.go @@ -1,5 +1,3 @@ -// +build !remoteclient - package integration import ( diff --git a/test/e2e/libpod_suite_remoteclient_test.go b/test/e2e/libpod_suite_remoteclient_test.go index a6cedfc58..7f33fec87 100644 --- a/test/e2e/libpod_suite_remoteclient_test.go +++ b/test/e2e/libpod_suite_remoteclient_test.go @@ -28,13 +28,6 @@ func SkipIfRootless() { } } -func SkipIfNotRunc() { - runtime := os.Getenv("OCI_RUNTIME") - if runtime != "" && filepath.Base(runtime) != "runc" { - ginkgo.Skip("Not using runc as runtime") - } -} - // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { podmanSession := p.PodmanBase(args, false, false) diff --git a/test/e2e/libpod_suite_test.go b/test/e2e/libpod_suite_test.go index 22cc14d6b..1df59dbe3 100644 --- a/test/e2e/libpod_suite_test.go +++ b/test/e2e/libpod_suite_test.go @@ -21,13 +21,6 @@ func SkipIfRootless() { } } -func SkipIfNotRunc() { - runtime := os.Getenv("OCI_RUNTIME") - if runtime != "" && filepath.Base(runtime) != "runc" { - ginkgo.Skip("Not using runc as runtime") - } -} - // Podman is the exec call to podman on the filesystem func (p *PodmanTestIntegration) Podman(args []string) *PodmanSessionIntegration { podmanSession := p.PodmanBase(args, false, false) diff --git a/test/e2e/play_kube_test.go b/test/e2e/play_kube_test.go index b0a9f2ead..af3cab379 100644 --- a/test/e2e/play_kube_test.go +++ b/test/e2e/play_kube_test.go @@ -21,6 +21,7 @@ metadata: app: {{ .Name }} name: {{ .Name }} spec: + hostname: {{ .Hostname }} containers: {{ with .Containers }} {{ range . }} @@ -66,6 +67,7 @@ status: {} type Pod struct { Name string + Hostname string Containers []Container } @@ -78,13 +80,13 @@ type Container struct { CapDrop []string } -func generateKubeYaml(ctrs []Container, fileName string) error { +func generateKubeYaml(name string, hostname string, ctrs []Container, fileName string) error { f, err := os.Create(fileName) if err != nil { return err } defer f.Close() - testPod := Pod{"test", ctrs} + testPod := Pod{name, hostname, ctrs} t, err := template.New("pod").Parse(yamlTemplate) if err != nil { @@ -127,7 +129,7 @@ var _ = Describe("Podman generate kube", func() { testContainer := Container{ctrCmd, ALPINE, ctrName, false, nil, nil} tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml") - err := generateKubeYaml([]Container{testContainer}, tempFile) + err := generateKubeYaml("test", "", []Container{testContainer}, tempFile) Expect(err).To(BeNil()) kube := podmanTest.Podman([]string{"play", "kube", tempFile}) @@ -146,7 +148,7 @@ var _ = Describe("Podman generate kube", func() { testContainer := Container{ctrCmd, ALPINE, ctrName, false, nil, nil} tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml") - err := generateKubeYaml([]Container{testContainer}, tempFile) + err := generateKubeYaml("test", "", []Container{testContainer}, tempFile) Expect(err).To(BeNil()) kube := podmanTest.Podman([]string{"play", "kube", tempFile}) @@ -164,6 +166,46 @@ var _ = Describe("Podman generate kube", func() { Expect(inspect.OutputToString()).To(ContainSubstring("hello")) }) + It("podman play kube test hostname", func() { + podName := "test" + ctrName := "testCtr" + ctrCmd := []string{"top"} + testContainer := Container{ctrCmd, ALPINE, ctrName, false, nil, nil} + tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml") + + err := generateKubeYaml(podName, "", []Container{testContainer}, tempFile) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", tempFile}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"inspect", ctrName, "--format", "{{ .Config.Hostname }}"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(Equal(podName)) + }) + + It("podman play kube test with customized hostname", func() { + hostname := "myhostname" + ctrName := "testCtr" + ctrCmd := []string{"top"} + testContainer := Container{ctrCmd, ALPINE, ctrName, false, nil, nil} + tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml") + + err := generateKubeYaml("test", hostname, []Container{testContainer}, tempFile) + Expect(err).To(BeNil()) + + kube := podmanTest.Podman([]string{"play", "kube", tempFile}) + kube.WaitWithDefaultTimeout() + Expect(kube.ExitCode()).To(Equal(0)) + + inspect := podmanTest.Podman([]string{"inspect", ctrName, "--format", "{{ .Config.Hostname }}"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect.ExitCode()).To(Equal(0)) + Expect(inspect.OutputToString()).To(Equal(hostname)) + }) + It("podman play kube cap add", func() { ctrName := "testCtr" ctrCmd := []string{"cat", "/proc/self/status"} @@ -171,7 +213,7 @@ var _ = Describe("Podman generate kube", func() { testContainer := Container{ctrCmd, ALPINE, ctrName, true, []string{capAdd}, nil} tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml") - err := generateKubeYaml([]Container{testContainer}, tempFile) + err := generateKubeYaml("test", "", []Container{testContainer}, tempFile) Expect(err).To(BeNil()) kube := podmanTest.Podman([]string{"play", "kube", tempFile}) @@ -191,7 +233,7 @@ var _ = Describe("Podman generate kube", func() { testContainer := Container{ctrCmd, ALPINE, ctrName, true, []string{capDrop}, nil} tempFile := filepath.Join(podmanTest.TempDir, "kube.yaml") - err := generateKubeYaml([]Container{testContainer}, tempFile) + err := generateKubeYaml("test", "", []Container{testContainer}, tempFile) Expect(err).To(BeNil()) kube := podmanTest.Podman([]string{"play", "kube", tempFile}) diff --git a/test/e2e/pull_test.go b/test/e2e/pull_test.go index d6e7b44d1..68fcaf133 100644 --- a/test/e2e/pull_test.go +++ b/test/e2e/pull_test.go @@ -150,6 +150,34 @@ var _ = Describe("Podman pull", func() { session = podmanTest.PodmanNoCache([]string{"pull", imgPath}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.PodmanNoCache([]string{"images"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.LineInOutputContainsTag(filepath.Join("localhost", dirpath), "latest")).To(BeTrue()) + session = podmanTest.PodmanNoCache([]string{"rmi", "alpine"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + }) + + It("podman pull from local OCI directory", func() { + podmanTest.RestoreArtifact(ALPINE) + dirpath := filepath.Join(podmanTest.TempDir, "alpine") + os.MkdirAll(dirpath, os.ModePerm) + imgPath := fmt.Sprintf("oci:%s", dirpath) + + session := podmanTest.PodmanNoCache([]string{"push", "alpine", imgPath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.PodmanNoCache([]string{"rmi", "alpine"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.PodmanNoCache([]string{"pull", imgPath}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + session = podmanTest.PodmanNoCache([]string{"images"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.LineInOutputContainsTag(filepath.Join("localhost", dirpath), "latest")).To(BeTrue()) session = podmanTest.PodmanNoCache([]string{"rmi", "alpine"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/e2e/push_test.go b/test/e2e/push_test.go index cf6279f2f..4360eeece 100644 --- a/test/e2e/push_test.go +++ b/test/e2e/push_test.go @@ -76,6 +76,14 @@ var _ = Describe("Podman push", func() { push := podmanTest.PodmanNoCache([]string{"push", "--tls-verify=false", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"}) push.WaitWithDefaultTimeout() Expect(push.ExitCode()).To(Equal(0)) + + // Test --digestfile option + push2 := podmanTest.PodmanNoCache([]string{"push", "--tls-verify=false", "--digestfile=/tmp/digestfile.txt", "--remove-signatures", ALPINE, "localhost:5000/my-alpine"}) + push2.WaitWithDefaultTimeout() + fi, err := os.Lstat("/tmp/digestfile.txt") + Expect(err).To(BeNil()) + Expect(fi.Name()).To(Equal("digestfile.txt")) + Expect(push2.ExitCode()).To(Equal(0)) }) It("podman push to local registry with authorization", func() { diff --git a/test/e2e/run_exit_test.go b/test/e2e/run_exit_test.go index b05849ddb..861d6b3b7 100644 --- a/test/e2e/run_exit_test.go +++ b/test/e2e/run_exit_test.go @@ -41,16 +41,12 @@ var _ = Describe("Podman run exit", func() { }) It("podman run exit 126", func() { - SkipIfNotRunc() - result := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(126)) }) It("podman run exit 127", func() { - SkipIfNotRunc() - result := podmanTest.Podman([]string{"run", ALPINE, "foobar"}) result.WaitWithDefaultTimeout() Expect(result.ExitCode()).To(Equal(127)) diff --git a/test/e2e/run_selinux_test.go b/test/e2e/run_selinux_test.go index a2228411e..dfe71531a 100644 --- a/test/e2e/run_selinux_test.go +++ b/test/e2e/run_selinux_test.go @@ -153,4 +153,16 @@ var _ = Describe("Podman run", func() { Expect(match).Should(BeTrue()) }) + It("podman run selinux file type setup test", func() { + session := podmanTest.Podman([]string{"run", "-it", "--security-opt", "label=type:spc_t", "--security-opt", "label=filetype:container_var_lib_t", fedoraMinimal, "ls", "-Z", "/dev"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + match, _ := session.GrepString("container_var_lib_t") + Expect(match).Should(BeTrue()) + + session = podmanTest.Podman([]string{"run", "-it", "--security-opt", "label=type:spc_t", "--security-opt", "label=filetype:foobar", fedoraMinimal, "ls", "-Z", "/dev"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(127)) + }) + }) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index ce2044a72..6e102cfa5 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -417,7 +417,6 @@ var _ = Describe("Podman run", func() { It("podman run notify_socket", func() { SkipIfRemote() - SkipIfNotRunc() host := GetHostDistributionInfo() if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" { @@ -629,7 +628,6 @@ var _ = Describe("Podman run", func() { }) It("podman run exit code on failure to exec", func() { - SkipIfNotRunc() session := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(126)) diff --git a/test/e2e/run_volume_test.go b/test/e2e/run_volume_test.go index 1e0b84310..abb93a149 100644 --- a/test/e2e/run_volume_test.go +++ b/test/e2e/run_volume_test.go @@ -154,4 +154,12 @@ var _ = Describe("Podman run with volumes", func() { session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Not(Equal(0))) }) + + It("podman run with volume flag and multiple named volumes", func() { + session := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol1:/testvol1", "-v", "testvol2:/testvol2", ALPINE, "grep", "/testvol", "/proc/self/mountinfo"}) + session.WaitWithDefaultTimeout() + Expect(session.ExitCode()).To(Equal(0)) + Expect(session.OutputToString()).To(ContainSubstring("/testvol1")) + Expect(session.OutputToString()).To(ContainSubstring("/testvol2")) + }) }) diff --git a/test/e2e/start_test.go b/test/e2e/start_test.go index 2dbb9545b..fc1203ed1 100644 --- a/test/e2e/start_test.go +++ b/test/e2e/start_test.go @@ -101,8 +101,6 @@ var _ = Describe("Podman start", func() { }) It("podman failed to start with --rm should delete the container", func() { - SkipIfNotRunc() - session := podmanTest.Podman([]string{"create", "-it", "--rm", ALPINE, "foo"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) @@ -116,8 +114,6 @@ var _ = Describe("Podman start", func() { }) It("podman failed to start without --rm should NOT delete the container", func() { - SkipIfNotRunc() - session := podmanTest.Podman([]string{"create", "-it", ALPINE, "foo"}) session.WaitWithDefaultTimeout() Expect(session.ExitCode()).To(Equal(0)) diff --git a/test/e2e/systemd_test.go b/test/e2e/systemd_test.go index 91604867d..02778d493 100644 --- a/test/e2e/systemd_test.go +++ b/test/e2e/systemd_test.go @@ -5,7 +5,10 @@ package integration import ( "io/ioutil" "os" + "strings" + "time" + "github.com/containers/libpod/pkg/cgroups" . "github.com/containers/libpod/test/utils" . "github.com/onsi/ginkgo" . "github.com/onsi/gomega" @@ -77,4 +80,49 @@ WantedBy=multi-user.target status := SystemExec("bash", []string{"-c", "systemctl status redis"}) Expect(status.OutputToString()).To(ContainSubstring("active (running)")) }) + + It("podman run container with systemd PID1", func() { + cgroupsv2, err := cgroups.IsCgroup2UnifiedMode() + Expect(err).To(BeNil()) + if cgroupsv2 { + Skip("systemd test does not work in cgroups V2 mode yet") + } + + systemdImage := "fedora" + pull := podmanTest.Podman([]string{"pull", systemdImage}) + pull.WaitWithDefaultTimeout() + Expect(pull.ExitCode()).To(Equal(0)) + + ctrName := "testSystemd" + run := podmanTest.Podman([]string{"run", "--name", ctrName, "-t", "-i", "-d", systemdImage, "init"}) + run.WaitWithDefaultTimeout() + Expect(run.ExitCode()).To(Equal(0)) + ctrID := run.OutputToString() + + logs := podmanTest.Podman([]string{"logs", ctrName}) + logs.WaitWithDefaultTimeout() + Expect(logs.ExitCode()).To(Equal(0)) + + // Give container 10 seconds to start + started := false + for i := 0; i < 10; i++ { + runningCtrs := podmanTest.Podman([]string{"ps", "-q", "--no-trunc"}) + runningCtrs.WaitWithDefaultTimeout() + Expect(runningCtrs.ExitCode()).To(Equal(0)) + + if strings.Contains(runningCtrs.OutputToString(), ctrID) { + started = true + break + } + + time.Sleep(1 * time.Second) + } + + Expect(started).To(BeTrue()) + + systemctl := podmanTest.Podman([]string{"exec", "-t", "-i", ctrName, "systemctl", "status", "--no-pager"}) + systemctl.WaitWithDefaultTimeout() + Expect(systemctl.ExitCode()).To(Equal(0)) + Expect(strings.Contains(systemctl.OutputToString(), "State:")).To(BeTrue()) + }) }) diff --git a/test/endpoint/config.go b/test/endpoint/config.go new file mode 100644 index 000000000..15ee23547 --- /dev/null +++ b/test/endpoint/config.go @@ -0,0 +1,22 @@ +package endpoint + +import "encoding/json" + +var ( + STORAGE_FS = "vfs" + STORAGE_OPTIONS = "--storage-driver vfs" + ROOTLESS_STORAGE_FS = "vfs" + ROOTLESS_STORAGE_OPTIONS = "--storage-driver vfs" + CACHE_IMAGES = []string{ALPINE, BB, fedoraMinimal, nginx, redis, registry, infra, labels} + nginx = "quay.io/libpod/alpine_nginx:latest" + BB_GLIBC = "docker.io/library/busybox:glibc" + registry = "docker.io/library/registry:2" + labels = "quay.io/libpod/alpine_labels:latest" +) + +func makeNameMessage(name string) string { + n := make(map[string]string) + n["name"] = name + b, _ := json.Marshal(n) + return string(b) +} diff --git a/test/endpoint/endpoint.go b/test/endpoint/endpoint.go new file mode 100644 index 000000000..4f9e6055e --- /dev/null +++ b/test/endpoint/endpoint.go @@ -0,0 +1,218 @@ +package endpoint + +import ( + "bytes" + "encoding/json" + "fmt" + "os" + "os/exec" + "strconv" + "strings" + "syscall" + "time" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/pkg/rootless" + . "github.com/onsi/ginkgo" + "github.com/onsi/gomega/gexec" +) + +var ( + ARTIFACT_DIR = "/tmp/.artifacts" + CGROUP_MANAGER = "systemd" + defaultWaitTimeout = 90 + //RESTORE_IMAGES = []string{ALPINE, BB} + INTEGRATION_ROOT string + ImageCacheDir = "/tmp/podman/imagecachedir" + VarlinkBinary = "/usr/bin/varlink" + ALPINE = "docker.io/library/alpine:latest" + infra = "k8s.gcr.io/pause:3.1" + BB = "docker.io/library/busybox:latest" + redis = "docker.io/library/redis:alpine" + fedoraMinimal = "registry.fedoraproject.org/fedora-minimal:latest" +) + +type EndpointTestIntegration struct { + ArtifactPath string + CNIConfigDir string + CgroupManager string + ConmonBinary string + CrioRoot string + //Host HostOS + ImageCacheDir string + ImageCacheFS string + OCIRuntime string + PodmanBinary string + RemoteTest bool + RunRoot string + SignaturePolicyPath string + StorageOptions string + TmpDir string + Timings []string + VarlinkBinary string + VarlinkCommand *exec.Cmd + VarlinkEndpoint string + VarlinkSession *os.Process +} + +func (p *EndpointTestIntegration) StartVarlink() { + p.startVarlink(false) +} + +func (p *EndpointTestIntegration) StartVarlinkWithCache() { + p.startVarlink(true) +} + +func (p *EndpointTestIntegration) startVarlink(useImageCache bool) { + var ( + counter int + ) + if os.Geteuid() == 0 { + os.MkdirAll("/run/podman", 0755) + } + varlinkEndpoint := p.VarlinkEndpoint + //p.SetVarlinkAddress(p.VarlinkEndpoint) + + args := []string{"varlink", "--timeout", "0", varlinkEndpoint} + podmanOptions := getVarlinkOptions(p, args) + if useImageCache { + cacheOptions := []string{"--storage-opt", fmt.Sprintf("%s.imagestore=%s", p.ImageCacheFS, p.ImageCacheDir)} + podmanOptions = append(cacheOptions, podmanOptions...) + } + command := exec.Command(p.PodmanBinary, podmanOptions...) + fmt.Printf("Running: %s %s\n", p.PodmanBinary, strings.Join(podmanOptions, " ")) + command.Start() + command.SysProcAttr = &syscall.SysProcAttr{Setpgid: true} + p.VarlinkCommand = command + p.VarlinkSession = command.Process + for { + if result := p.endpointReady(); result == 0 { + break + } + fmt.Println("Waiting for varlink connection to become active", counter) + time.Sleep(250 * time.Millisecond) + counter++ + if counter > 40 { + Fail("varlink endpoint never became ready") + } + } +} + +func (p *EndpointTestIntegration) endpointReady() int { + session := p.Varlink("GetVersion", "", false) + return session.ExitCode() +} + +func (p *EndpointTestIntegration) StopVarlink() { + var out bytes.Buffer + var pids []int + varlinkSession := p.VarlinkSession + + if !rootless.IsRootless() { + if err := varlinkSession.Kill(); err != nil { + fmt.Fprintf(os.Stderr, "error on varlink stop-kill %q", err) + } + if _, err := varlinkSession.Wait(); err != nil { + fmt.Fprintf(os.Stderr, "error on varlink stop-wait %q", err) + } + + } else { + //p.ResetVarlinkAddress() + parentPid := fmt.Sprintf("%d", p.VarlinkSession.Pid) + pgrep := exec.Command("pgrep", "-P", parentPid) + fmt.Printf("running: pgrep %s\n", parentPid) + pgrep.Stdout = &out + err := pgrep.Run() + if err != nil { + fmt.Fprint(os.Stderr, "unable to find varlink pid") + } + + for _, s := range strings.Split(out.String(), "\n") { + if len(s) == 0 { + continue + } + p, err := strconv.Atoi(s) + if err != nil { + fmt.Fprintf(os.Stderr, "unable to convert %s to int", s) + } + if p != 0 { + pids = append(pids, p) + } + } + + pids = append(pids, p.VarlinkSession.Pid) + for _, pid := range pids { + syscall.Kill(pid, syscall.SIGKILL) + } + } + socket := strings.Split(p.VarlinkEndpoint, ":")[1] + if err := os.Remove(socket); err != nil { + fmt.Println(err) + } +} + +type EndpointSession struct { + *gexec.Session +} + +func getVarlinkOptions(p *EndpointTestIntegration, args []string) []string { + podmanOptions := strings.Split(fmt.Sprintf("--root %s --runroot %s --runtime %s --conmon %s --cni-config-dir %s --cgroup-manager %s", + p.CrioRoot, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.CNIConfigDir, p.CgroupManager), " ") + if os.Getenv("HOOK_OPTION") != "" { + podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION")) + } + podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...) + podmanOptions = append(podmanOptions, args...) + return podmanOptions +} + +func (p *EndpointTestIntegration) Varlink(endpoint, message string, more bool) *EndpointSession { + //call unix:/run/user/1000/podman/io.podman/io.podman.GetContainerStats '{"name": "foobar" }' + var ( + command *exec.Cmd + ) + + args := []string{"call"} + if more { + args = append(args, "-m") + } + args = append(args, []string{fmt.Sprintf("%s/io.podman.%s", p.VarlinkEndpoint, endpoint)}...) + if len(message) > 0 { + args = append(args, message) + } + command = exec.Command(p.VarlinkBinary, args...) + session, err := gexec.Start(command, GinkgoWriter, GinkgoWriter) + if err != nil { + Fail(fmt.Sprintf("unable to run varlink command: %s\n%v", strings.Join(args, " "), err)) + } + session.Wait(defaultWaitTimeout) + return &EndpointSession{session} +} + +func (s *EndpointSession) OutputToString() string { + fields := strings.Fields(fmt.Sprintf("%s", s.Out.Contents())) + return strings.Join(fields, " ") +} + +func (s *EndpointSession) OutputToBytes() []byte { + out := s.OutputToString() + return []byte(out) +} + +func (s *EndpointSession) OutputToStringMap() map[string]string { + var out map[string]string + json.Unmarshal(s.OutputToBytes(), &out) + return out +} + +func (s *EndpointSession) OutputToMapToInt() map[string]int { + var out map[string]int + json.Unmarshal(s.OutputToBytes(), &out) + return out +} + +func (s *EndpointSession) OutputToMoreResponse() iopodman.MoreResponse { + out := make(map[string]iopodman.MoreResponse) + json.Unmarshal(s.OutputToBytes(), &out) + return out["reply"] +} diff --git a/test/endpoint/endpoint_suite_test.go b/test/endpoint/endpoint_suite_test.go new file mode 100644 index 000000000..401da94c2 --- /dev/null +++ b/test/endpoint/endpoint_suite_test.go @@ -0,0 +1,70 @@ +package endpoint + +import ( + "fmt" + "io/ioutil" + "os" + "path/filepath" + "testing" + + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +func TestEndpoint(t *testing.T) { + RegisterFailHandler(Fail) + RunSpecs(t, "Endpoint Suite") +} + +var LockTmpDir string + +var _ = SynchronizedBeforeSuite(func() []byte { + // Cache images + cwd, _ := os.Getwd() + INTEGRATION_ROOT = filepath.Join(cwd, "../../") + podman := Setup("/tmp") + podman.ArtifactPath = ARTIFACT_DIR + if _, err := os.Stat(ARTIFACT_DIR); os.IsNotExist(err) { + if err = os.Mkdir(ARTIFACT_DIR, 0777); err != nil { + fmt.Printf("%q\n", err) + os.Exit(1) + } + } + + // make cache dir + if err := os.MkdirAll(ImageCacheDir, 0777); err != nil { + fmt.Printf("%q\n", err) + os.Exit(1) + } + + podman.StartVarlink() + for _, image := range CACHE_IMAGES { + podman.createArtifact(image) + } + podman.StopVarlink() + // If running localized tests, the cache dir is created and populated. if the + // tests are remote, this is a no-op + populateCache(podman) + + path, err := ioutil.TempDir("", "libpodlock") + if err != nil { + fmt.Println(err) + os.Exit(1) + } + return []byte(path) +}, func(data []byte) { + LockTmpDir = string(data) +}) + +var _ = SynchronizedAfterSuite(func() {}, + func() { + podman := Setup("/tmp") + if err := os.RemoveAll(podman.CrioRoot); err != nil { + fmt.Printf("%q\n", err) + os.Exit(1) + } + if err := os.RemoveAll(podman.ImageCacheDir); err != nil { + fmt.Printf("%q\n", err) + os.Exit(1) + } + }) diff --git a/test/endpoint/exists_test.go b/test/endpoint/exists_test.go new file mode 100644 index 000000000..c8ab9e0f2 --- /dev/null +++ b/test/endpoint/exists_test.go @@ -0,0 +1,66 @@ +package endpoint + +import ( + "os" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman pull", func() { + var ( + tempdir string + err error + endpointTest *EndpointTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + endpointTest = Setup(tempdir) + endpointTest.StartVarlinkWithCache() + }) + + AfterEach(func() { + endpointTest.Cleanup() + //f := CurrentGinkgoTestDescription() + //processTestResult(f) + + }) + + It("image exists in local storage", func() { + result := endpointTest.Varlink("ImageExists", makeNameMessage(ALPINE), false) + Expect(result.ExitCode()).To(BeZero()) + + output := result.OutputToMapToInt() + Expect(output["exists"]).To(BeZero()) + }) + + It("image exists in local storage by shortname", func() { + result := endpointTest.Varlink("ImageExists", makeNameMessage("alpine"), false) + Expect(result.ExitCode()).To(BeZero()) + + output := result.OutputToMapToInt() + Expect(output["exists"]).To(BeZero()) + }) + + It("image does not exist in local storage", func() { + result := endpointTest.Varlink("ImageExists", makeNameMessage("alpineforest"), false) + Expect(result.ExitCode()).To(BeZero()) + + output := result.OutputToMapToInt() + Expect(output["exists"]).To(Equal(1)) + }) + + It("container exists in local storage by name", func() { + _ = endpointTest.startTopContainer("top") + result := endpointTest.Varlink("ContainerExists", makeNameMessage("top"), false) + Expect(result.ExitCode()).To(BeZero()) + output := result.OutputToMapToInt() + Expect(output["exists"]).To(BeZero()) + }) + +}) diff --git a/test/endpoint/pull_test.go b/test/endpoint/pull_test.go new file mode 100644 index 000000000..51eb9c760 --- /dev/null +++ b/test/endpoint/pull_test.go @@ -0,0 +1,44 @@ +package endpoint + +import ( + "os" + + . "github.com/containers/libpod/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman pull", func() { + var ( + tempdir string + err error + endpointTest *EndpointTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + endpointTest = Setup(tempdir) + endpointTest.StartVarlink() + }) + + AfterEach(func() { + endpointTest.Cleanup() + //f := CurrentGinkgoTestDescription() + //processTestResult(f) + + }) + + It("podman pull", func() { + session := endpointTest.Varlink("PullImage", makeNameMessage(ALPINE), false) + Expect(session.ExitCode()).To(BeZero()) + + result := endpointTest.Varlink("ImageExists", makeNameMessage(ALPINE), false) + Expect(result.ExitCode()).To(BeZero()) + + output := result.OutputToMapToInt() + Expect(output["exists"]).To(BeZero()) + }) +}) diff --git a/test/endpoint/setup.go b/test/endpoint/setup.go new file mode 100644 index 000000000..727f29ec6 --- /dev/null +++ b/test/endpoint/setup.go @@ -0,0 +1,219 @@ +package endpoint + +import ( + "encoding/json" + "fmt" + "os" + "os/exec" + "path/filepath" + "strings" + + iopodman "github.com/containers/libpod/cmd/podman/varlink" + "github.com/containers/libpod/pkg/rootless" + "github.com/containers/storage/pkg/stringid" + "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + "github.com/sirupsen/logrus" +) + +func Setup(tempDir string) *EndpointTestIntegration { + var ( + endpoint string + ) + cwd, _ := os.Getwd() + INTEGRATION_ROOT = filepath.Join(cwd, "../../") + + podmanBinary := filepath.Join(cwd, "../../bin/podman") + if os.Getenv("PODMAN_BINARY") != "" { + podmanBinary = os.Getenv("PODMAN_BINARY") + } + conmonBinary := filepath.Join("/usr/libexec/podman/conmon") + altConmonBinary := "/usr/bin/conmon" + if _, err := os.Stat(conmonBinary); os.IsNotExist(err) { + conmonBinary = altConmonBinary + } + if os.Getenv("CONMON_BINARY") != "" { + conmonBinary = os.Getenv("CONMON_BINARY") + } + storageOptions := STORAGE_OPTIONS + if os.Getenv("STORAGE_OPTIONS") != "" { + storageOptions = os.Getenv("STORAGE_OPTIONS") + } + cgroupManager := CGROUP_MANAGER + if rootless.IsRootless() { + cgroupManager = "cgroupfs" + } + if os.Getenv("CGROUP_MANAGER") != "" { + cgroupManager = os.Getenv("CGROUP_MANAGER") + } + + ociRuntime := os.Getenv("OCI_RUNTIME") + if ociRuntime == "" { + var err error + ociRuntime, err = exec.LookPath("runc") + // If we cannot find the runc binary, setting to something static as we have no way + // to return an error. The tests will fail and point out that the runc binary could + // not be found nicely. + if err != nil { + ociRuntime = "/usr/bin/runc" + } + } + os.Setenv("DISABLE_HC_SYSTEMD", "true") + CNIConfigDir := "/etc/cni/net.d" + + storageFs := STORAGE_FS + if rootless.IsRootless() { + storageFs = ROOTLESS_STORAGE_FS + } + + uuid := stringid.GenerateNonCryptoID() + if !rootless.IsRootless() { + endpoint = fmt.Sprintf("unix:/run/podman/io.podman-%s", uuid) + } else { + runtimeDir := os.Getenv("XDG_RUNTIME_DIR") + socket := fmt.Sprintf("io.podman-%s", uuid) + fqpath := filepath.Join(runtimeDir, socket) + endpoint = fmt.Sprintf("unix:%s", fqpath) + } + + eti := EndpointTestIntegration{ + ArtifactPath: ARTIFACT_DIR, + CNIConfigDir: CNIConfigDir, + CgroupManager: cgroupManager, + ConmonBinary: conmonBinary, + CrioRoot: filepath.Join(tempDir, "crio"), + ImageCacheDir: ImageCacheDir, + ImageCacheFS: storageFs, + OCIRuntime: ociRuntime, + PodmanBinary: podmanBinary, + RunRoot: filepath.Join(tempDir, "crio-run"), + SignaturePolicyPath: filepath.Join(INTEGRATION_ROOT, "test/policy.json"), + StorageOptions: storageOptions, + TmpDir: tempDir, + //Timings: nil, + VarlinkBinary: VarlinkBinary, + VarlinkCommand: nil, + VarlinkEndpoint: endpoint, + VarlinkSession: nil, + } + return &eti +} + +func (p *EndpointTestIntegration) Cleanup() { + // Remove all containers + // TODO Make methods to do all this? + + p.stopAllContainers() + + //TODO need to make stop all pods + + p.StopVarlink() + // Nuke tempdir + if err := os.RemoveAll(p.TmpDir); err != nil { + fmt.Printf("%q\n", err) + } + + // Clean up the registries configuration file ENV variable set in Create + resetRegistriesConfigEnv() +} + +func (p *EndpointTestIntegration) listContainers() []iopodman.Container { + containers := p.Varlink("ListContainers", "", false) + var varlinkContainers map[string][]iopodman.Container + if err := json.Unmarshal(containers.OutputToBytes(), &varlinkContainers); err != nil { + logrus.Error("failed to unmarshal containers") + } + return varlinkContainers["containers"] +} + +func (p *EndpointTestIntegration) stopAllContainers() { + containers := p.listContainers() + for _, container := range containers { + p.stopContainer(container.Id) + } +} + +func (p *EndpointTestIntegration) stopContainer(cid string) { + p.Varlink("StopContainer", fmt.Sprintf("{\"name\":\"%s\", \"timeout\":0}", cid), false) +} + +func resetRegistriesConfigEnv() { + os.Setenv("REGISTRIES_CONFIG_PATH", "") +} + +func (p *EndpointTestIntegration) createArtifact(image string) { + if os.Getenv("NO_TEST_CACHE") != "" { + return + } + dest := strings.Split(image, "/") + destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1)) + fmt.Printf("Caching %s at %s...", image, destName) + if _, err := os.Stat(destName); os.IsNotExist(err) { + pull := p.Varlink("PullImage", fmt.Sprintf("{\"name\":\"%s\"}", image), false) + Expect(pull.ExitCode()).To(Equal(0)) + + imageSave := iopodman.ImageSaveOptions{ + //Name:image, + //Output: destName, + //Format: "oci-archive", + } + imageSave.Name = image + imageSave.Output = destName + imageSave.Format = "oci-archive" + foo := make(map[string]iopodman.ImageSaveOptions) + foo["options"] = imageSave + f, _ := json.Marshal(foo) + save := p.Varlink("ImageSave", string(f), false) + result := save.OutputToMoreResponse() + Expect(save.ExitCode()).To(Equal(0)) + Expect(os.Rename(result.Id, destName)).To(BeNil()) + fmt.Printf("\n") + } else { + fmt.Printf(" already exists.\n") + } +} + +func populateCache(p *EndpointTestIntegration) { + p.CrioRoot = p.ImageCacheDir + p.StartVarlink() + for _, image := range CACHE_IMAGES { + p.RestoreArtifactToCache(image) + } + p.StopVarlink() +} + +func (p *EndpointTestIntegration) RestoreArtifactToCache(image string) error { + fmt.Printf("Restoring %s...\n", image) + dest := strings.Split(image, "/") + destName := fmt.Sprintf("/tmp/%s.tar", strings.Replace(strings.Join(strings.Split(dest[len(dest)-1], "/"), ""), ":", "-", -1)) + //fmt.Println(destName, p.ImageCacheDir) + load := p.Varlink("LoadImage", fmt.Sprintf("{\"name\": \"%s\", \"inputFile\": \"%s\"}", image, destName), false) + Expect(load.ExitCode()).To(BeZero()) + return nil +} + +func (p *EndpointTestIntegration) startTopContainer(name string) string { + t := true + args := iopodman.Create{ + Args: []string{"docker.io/library/alpine:latest", "top"}, + Tty: &t, + Detach: &t, + } + if len(name) > 0 { + args.Name = &name + } + b, err := json.Marshal(args) + if err != nil { + ginkgo.Fail("failed to marshal data for top container") + } + input := fmt.Sprintf("{\"create\":%s}", string(b)) + top := p.Varlink("CreateContainer", input, false) + if top.ExitCode() != 0 { + ginkgo.Fail("failed to start top container") + } + start := p.Varlink("StartContainer", fmt.Sprintf("{\"name\":\"%s\"}", name), false) + if start.ExitCode() != 0 { + ginkgo.Fail("failed to start top container") + } + return start.OutputToString() +} diff --git a/test/endpoint/version_test.go b/test/endpoint/version_test.go new file mode 100644 index 000000000..a1168da70 --- /dev/null +++ b/test/endpoint/version_test.go @@ -0,0 +1,41 @@ +package endpoint + +import ( + "os" + + . "github.com/containers/libpod/test/utils" + "github.com/containers/libpod/version" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" +) + +var _ = Describe("Podman version", func() { + var ( + tempdir string + err error + endpointTest *EndpointTestIntegration + ) + + BeforeEach(func() { + tempdir, err = CreateTempDirInTempDir() + if err != nil { + os.Exit(1) + } + endpointTest = Setup(tempdir) + endpointTest.StartVarlink() + }) + + AfterEach(func() { + endpointTest.Cleanup() + //f := CurrentGinkgoTestDescription() + //processTestResult(f) + + }) + + It("podman version", func() { + session := endpointTest.Varlink("GetVersion", "", false) + result := session.OutputToStringMap() + Expect(result["version"]).To(Equal(version.Version)) + Expect(session.ExitCode()).To(Equal(0)) + }) +}) diff --git a/test/system/065-cp.bats b/test/system/065-cp.bats new file mode 100644 index 000000000..204065bdb --- /dev/null +++ b/test/system/065-cp.bats @@ -0,0 +1,229 @@ +#!/usr/bin/env bats -*- bats -*- +# +# Tests for 'podman cp' +# +# ASSUMPTION FOR ALL THESE TESTS: /tmp in the container starts off empty +# + +load helpers + +# Create two random-name random-content files in /tmp in the container +# podman-cp them into the host using '/tmp/*', i.e. asking podman to +# perform wildcard expansion in the container. We should get both +# files copied into the host. +@test "podman cp * - wildcard copy multiple files from container to host" { + skip_if_remote "podman-remote does not yet handle cp" + + srcdir=$PODMAN_TMPDIR/cp-test-in + dstdir=$PODMAN_TMPDIR/cp-test-out + mkdir -p $srcdir $dstdir + + rand_filename1=$(random_string 20) + rand_content1=$(random_string 50) + rand_filename2=$(random_string 20) + rand_content2=$(random_string 50) + + run_podman run --name cpcontainer $IMAGE sh -c \ + "echo $rand_content1 >/tmp/$rand_filename1; + echo $rand_content2 >/tmp/$rand_filename2" + + run_podman cp 'cpcontainer:/tmp/*' $dstdir + + test -e $dstdir/$rand_filename1 || die "file 1 not copied from container" + test -e $dstdir/$rand_filename2 || die "file 2 not copied from container" + + is "$(<$dstdir/$rand_filename1)" "$rand_content1" "content of file 1" + is "$(<$dstdir/$rand_filename2)" "$rand_content2" "content of file 2" + + run_podman rm cpcontainer +} + + +# Create a file on the host; make a symlink in the container pointing +# into host-only space. Try to podman-cp that symlink. It should fail. +@test "podman cp - will not recognize symlink pointing into host space" { + skip_if_remote "podman-remote does not yet handle cp" + skip "BROKEN: PLEASE ENABLE ONCE #3829 GETS FIXED" + + srcdir=$PODMAN_TMPDIR/cp-test-in + dstdir=$PODMAN_TMPDIR/cp-test-out + mkdir -p $srcdir $dstdir + echo "this file is on the host" >$srcdir/hostfile + + run_podman run --name cpcontainer $IMAGE \ + sh -c "ln -s $srcdir/hostfile /tmp/badlink" + # This should fail because, from the container's perspective, the symlink + # points to a nonexistent file + run_podman 125 cp 'cpcontainer:/tmp/*' $dstdir/ + + # FIXME: this might not be the exactly correct error message + is "$output" ".*error evaluating symlinks.*lstat.*no such file or dir" \ + "Expected error from copying invalid symlink" + + # make sure there are no files in dstdir + is "$(/bin/ls -1 $dstdir)" "" "incorrectly copied symlink from host" + + run_podman rm cpcontainer +} + + +# Issue #3829 - like the above, but with a level of indirection in the +# wildcard expansion: create a file on the host; create a symlink in +# the container named 'file1' pointing to this file; then another symlink +# in the container pointing to 'file*' (file star). Try to podman-cp +# this invalid double symlink. It must fail. +@test "podman cp - will not expand globs in host space (#3829)" { + skip_if_remote "podman-remote does not yet handle cp" + skip "BROKEN: PLEASE ENABLE ONCE #3829 GETS FIXED" + + srcdir=$PODMAN_TMPDIR/cp-test-in + dstdir=$PODMAN_TMPDIR/cp-test-out + mkdir -p $srcdir $dstdir + echo "This file is on the host" > $srcdir/hostfile + + run_podman run --name cpcontainer $IMAGE \ + sh -c "ln -s $srcdir/hostfile file1;ln -s file\* copyme" + run_podman 125 cp cpcontainer:copyme $dstdir + + is "$output" ".*error evaluating symlinks.*lstat.*no such file or dir" \ + "Expected error from copying invalid symlink" + + # make sure there are no files in dstdir + is "$(/bin/ls -1 $dstdir)" "" "incorrectly copied symlink from host" + + run_podman rm cpcontainer +} + + +# Another symlink into host space, this one named '*' (star). cp should fail. +@test "podman cp - will not expand wildcard" { + skip_if_remote "podman-remote does not yet handle cp" + + srcdir=$PODMAN_TMPDIR/cp-test-in + dstdir=$PODMAN_TMPDIR/cp-test-out + mkdir -p $srcdir $dstdir + echo "This file lives on the host" > $srcdir/hostfile + + run_podman run --name cpcontainer $IMAGE \ + sh -c "ln -s $srcdir/hostfile /tmp/\*" + run_podman 125 cp 'cpcontainer:/tmp/*' $dstdir + + is "$output" ".*error evaluating symlinks.*lstat.*no such file or dir" \ + "Expected error from copying invalid symlink" + + # dstdir must be empty + is "$(/bin/ls -1 $dstdir)" "" "incorrectly copied symlink from host" + + run_podman rm cpcontainer +} + +############################################################################### +# cp INTO container + +# THIS IS EXTREMELY WEIRD. Podman expands symlinks in weird ways. +@test "podman cp into container: weird symlink expansion" { + skip_if_remote "podman-remote does not yet handle cp" + + srcdir=$PODMAN_TMPDIR/cp-test-in + dstdir=$PODMAN_TMPDIR/cp-test-out + mkdir -p $srcdir $dstdir + + rand_filename1=$(random_string 20) + rand_content1=$(random_string 50) + echo $rand_content1 > $srcdir/$rand_filename1 + + rand_filename2=$(random_string 20) + rand_content2=$(random_string 50) + echo $rand_content2 > $srcdir/$rand_filename2 + + rand_filename3=$(random_string 20) + rand_content3=$(random_string 50) + echo $rand_content3 > $srcdir/$rand_filename3 + + # Create tmp subdirectories in container, most with an invalid 'x' symlink + # Keep container running so we can exec into it. + run_podman run -d --name cpcontainer $IMAGE \ + sh -c "mkdir /tmp/d1;ln -s /tmp/nonesuch1 /tmp/d1/x; + mkdir /tmp/d2;ln -s /tmp/nonesuch2 /tmp/d2/x; + mkdir /tmp/d3; + trap 'exit 0' 15;while :;do sleep 0.5;done" + + # Copy file from host into container, into a file named 'x' + # Note that the second has a trailing slash; this will trigger mkdir + run_podman cp $srcdir/$rand_filename1 cpcontainer:/tmp/d1/x + is "$output" "" "output from podman cp 1" + + run_podman cp $srcdir/$rand_filename2 cpcontainer:/tmp/d2/x/ + is "$output" "" "output from podman cp 3" + + run_podman cp $srcdir/$rand_filename3 cpcontainer:/tmp/d3/x + is "$output" "" "output from podman cp 3" + + # Read back. + # In the first case, podman actually creates the file nonesuch1 (i.e. + # podman expands 'x -> nonesuch1' and, instead of overwriting x, + # creates an actual file). + run_podman exec cpcontainer cat /tmp/nonesuch1 + is "$output" "$rand_content1" "cp creates destination file" + + # In the second case, podman creates a directory nonesuch2, then + # creates a file with the same name as the input file. THIS IS WEIRD! + run_podman exec cpcontainer cat /tmp/nonesuch2/$rand_filename2 + is "$output" "$rand_content2" "cp creates destination dir and file" + + # In the third case, podman (correctly imo) creates a file named 'x' + run_podman exec cpcontainer cat /tmp/d3/x + is "$output" "$rand_content3" "cp creates file named x" + + run_podman rm -f cpcontainer + + +} + + +# rhbz1741718 : file copied into container:/var/lib/foo appears as /foo +# (docker only, never seems to have affected podman. Make sure it never does). +@test "podman cp into a subdirectory matching GraphRoot" { + skip_if_remote "podman-remote does not yet handle cp" + + # Create tempfile with random name and content + srcdir=$PODMAN_TMPDIR/cp-test-in + mkdir -p $srcdir + rand_filename=$(random_string 20) + rand_content=$(random_string 50) + echo $rand_content > $srcdir/$rand_filename + chmod 644 $srcdir/$rand_filename + + # Determine path to podman storage (eg /var/lib/c/s, or $HOME/.local/...) + run_podman info --format '{{.store.GraphRoot}}' + graphroot=$output + + # Create that directory in the container, and sleep (to keep container + # running, so we can exec into it). The trap/while is so podman-rm will + # run quickly instead of taking 10 seconds. + run_podman run -d --name cpcontainer $IMAGE sh -c \ + "mkdir -p $graphroot; trap 'exit 0' 15;while :;do sleep 0.5;done" + + # Copy from host into container. + run_podman cp $srcdir/$rand_filename cpcontainer:$graphroot/$rand_filename + + # ls, and confirm it's there. + run_podman exec cpcontainer ls -l $graphroot/$rand_filename + is "$output" "-rw-r--r-- .* 1 .* root .* 51 .* $graphroot/$rand_filename" \ + "File is copied into container in the correct (full) path" + + # Confirm it has the expected content (this is unlikely to ever fail) + run_podman exec cpcontainer cat $graphroot/$rand_filename + is "$output" "$rand_content" "Contents of file copied into container" + + run_podman rm -f cpcontainer +} + + +function teardown() { + # In case any test fails, clean up the container we left behind + run_podman rm -f cpcontainer + basic_teardown +} + +# vim: filetype=sh diff --git a/test/system/070-build.bats b/test/system/070-build.bats index 5ef84e9b8..a9d2ed1b7 100644 --- a/test/system/070-build.bats +++ b/test/system/070-build.bats @@ -22,12 +22,24 @@ RUN apk add nginx RUN echo $rand_content > /$rand_filename EOF - run_podman build -t build_test --format=docker $tmpdir + # The 'apk' command can take a long time to fetch files; bump timeout + PODMAN_TIMEOUT=240 run_podman build -t build_test --format=docker $tmpdir is "$output" ".*STEP 4: COMMIT" "COMMIT seen in log" run_podman run --rm build_test cat /$rand_filename is "$output" "$rand_content" "reading generated file in image" - run_podman rmi build_test + run_podman rmi -f build_test } + +function teardown() { + # A timeout or other error in 'build' can leave behind stale images + # that podman can't even see and which will cascade into subsequent + # test failures. Try a last-ditch force-rm in cleanup, ignoring errors. + run_podman '?' rm -a -f + run_podman '?' rmi -f build_test + + basic_teardown +} + # vim: filetype=sh |