diff options
Diffstat (limited to 'test')
-rw-r--r-- | test/e2e/pod_initcontainers_test.go | 171 | ||||
-rw-r--r-- | test/e2e/run_test.go | 11 | ||||
-rw-r--r-- | test/system/255-auto-update.bats | 117 |
3 files changed, 294 insertions, 5 deletions
diff --git a/test/e2e/pod_initcontainers_test.go b/test/e2e/pod_initcontainers_test.go new file mode 100644 index 000000000..606294f51 --- /dev/null +++ b/test/e2e/pod_initcontainers_test.go @@ -0,0 +1,171 @@ +package integration + +import ( + "fmt" + "os" + "path/filepath" + + "github.com/containers/podman/v3/libpod/define" + . "github.com/containers/podman/v3/test/utils" + . "github.com/onsi/ginkgo" + . "github.com/onsi/gomega" + . "github.com/onsi/gomega/gexec" +) + +var _ = Describe("Podman init containers", 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 create init container without --pod should fail", func() { + session := podmanTest.Podman([]string{"create", "--init-ctr", "always", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + }) + + It("podman create init container with bad init type should fail", func() { + session := podmanTest.Podman([]string{"create", "--init-ctr", "unknown", "--pod", "new:foobar", ALPINE, "top"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + }) + + It("podman init containers should not degrade pod status", func() { + // create a pod + topPod := podmanTest.Podman([]string{"create", "-t", "--pod", "new:foobar", ALPINE, "top"}) + topPod.WaitWithDefaultTimeout() + Expect(topPod).Should(Exit(0)) + // add an init container + session := podmanTest.Podman([]string{"create", "--init-ctr", "always", "--pod", "foobar", ALPINE, "date"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + // start a pod + start := podmanTest.Podman([]string{"pod", "start", "foobar"}) + start.WaitWithDefaultTimeout() + Expect(start).Should(Exit(0)) + + inspect := podmanTest.Podman([]string{"pod", "inspect", "foobar"}) + inspect.WaitWithDefaultTimeout() + Expect(inspect).Should(Exit(0)) + data := inspect.InspectPodToJSON() + Expect(data.State).To(Equal(define.PodStateRunning)) + }) + + It("podman create init container should fail in running pod", func() { + // create a running pod + topPod := podmanTest.Podman([]string{"run", "-dt", "--pod", "new:foobar", ALPINE, "top"}) + topPod.WaitWithDefaultTimeout() + Expect(topPod).Should(Exit(0)) + // adding init-ctr to running pod should fail + session := podmanTest.Podman([]string{"create", "--init-ctr", "always", "--pod", "foobar", ALPINE, "date"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(125)) + }) + + It("podman make sure init container runs before pod containers", func() { + filename := filepath.Join("/dev/shm", RandomString(12)) + content := RandomString(16) + session := podmanTest.Podman([]string{"create", "--init-ctr", "always", "--pod", "new:foobar", ALPINE, "bin/sh", "-c", fmt.Sprintf("echo %s > %s", content, filename)}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + verify := podmanTest.Podman([]string{"create", "--pod", "foobar", "-t", ALPINE, "top"}) + verify.WaitWithDefaultTimeout() + Expect(verify).Should(Exit(0)) + start := podmanTest.Podman([]string{"pod", "start", "foobar"}) + start.WaitWithDefaultTimeout() + Expect(start).Should(Exit(0)) + checkLog := podmanTest.Podman([]string{"exec", "-it", verify.OutputToString(), "cat", filename}) + checkLog.WaitWithDefaultTimeout() + Expect(checkLog).Should(Exit(0)) + Expect(checkLog.OutputToString()).To(Equal(content)) + }) + + It("podman make sure oneshot container is removed", func() { + filename := filepath.Join("/dev/shm", RandomString(12)) + content := RandomString(16) + session := podmanTest.Podman([]string{"create", "--init-ctr", "oneshot", "--pod", "new:foobar", ALPINE, "bin/sh", "-c", fmt.Sprintf("echo %s > %s", content, filename)}) + session.WaitWithDefaultTimeout() + initContainerID := session.OutputToString() + Expect(session).Should(Exit(0)) + verify := podmanTest.Podman([]string{"create", "--pod", "foobar", "-t", ALPINE, "top"}) + verify.WaitWithDefaultTimeout() + Expect(verify).Should(Exit(0)) + start := podmanTest.Podman([]string{"pod", "start", "foobar"}) + start.WaitWithDefaultTimeout() + Expect(start).Should(Exit(0)) + check := podmanTest.Podman([]string{"container", "exists", initContainerID}) + check.WaitWithDefaultTimeout() + // Container was rm'd + //Expect(check).Should(Exit(1)) + Expect(check.ExitCode()).To(Equal(1), "I dont understand why the other way does not work") + // Lets double check with a stop and start + stopPod := podmanTest.Podman([]string{"pod", "stop", "foobar"}) + stopPod.WaitWithDefaultTimeout() + Expect(stopPod).Should(Exit(0)) + startPod := podmanTest.Podman([]string{"pod", "start", "foobar"}) + startPod.WaitWithDefaultTimeout() + Expect(startPod).Should(Exit(0)) + + // Because no init was run, the file should not even exist + doubleCheck := podmanTest.Podman([]string{"exec", "-it", verify.OutputToString(), "cat", filename}) + doubleCheck.WaitWithDefaultTimeout() + Expect(doubleCheck).Should(Exit(1)) + + }) + + It("podman ensure always init containers always run", func() { + filename := filepath.Join("/dev/shm", RandomString(12)) + + // Write the date to a file + session := podmanTest.Podman([]string{"create", "--init-ctr", "always", "--pod", "new:foobar", ALPINE, "bin/sh", "-c", fmt.Sprintf("date > %s", filename)}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + verify := podmanTest.Podman([]string{"create", "--pod", "foobar", "-t", ALPINE, "top"}) + verify.WaitWithDefaultTimeout() + Expect(verify).Should(Exit(0)) + start := podmanTest.Podman([]string{"pod", "start", "foobar"}) + start.WaitWithDefaultTimeout() + Expect(start).Should(Exit(0)) + + // capture the date written + checkLog := podmanTest.Podman([]string{"exec", "-it", verify.OutputToString(), "cat", filename}) + checkLog.WaitWithDefaultTimeout() + firstResult := checkLog.OutputToString() + Expect(checkLog).Should(Exit(0)) + + // Stop and start the pod + stopPod := podmanTest.Podman([]string{"pod", "stop", "foobar"}) + stopPod.WaitWithDefaultTimeout() + Expect(stopPod).Should(Exit(0)) + startPod := podmanTest.Podman([]string{"pod", "start", "foobar"}) + startPod.WaitWithDefaultTimeout() + Expect(startPod).Should(Exit(0)) + + // Check the file again with exec + secondCheckLog := podmanTest.Podman([]string{"exec", "-it", verify.OutputToString(), "cat", filename}) + secondCheckLog.WaitWithDefaultTimeout() + Expect(secondCheckLog).Should(Exit(0)) + + // Dates should not match + Expect(firstResult).ToNot(Equal(secondCheckLog.OutputToString())) + }) + +}) diff --git a/test/e2e/run_test.go b/test/e2e/run_test.go index 3c65c02d1..d68aa6ac4 100644 --- a/test/e2e/run_test.go +++ b/test/e2e/run_test.go @@ -1790,4 +1790,15 @@ WORKDIR /madethis`, BB) _, err = strconv.Atoi(containerPID) // Make sure it's a proper integer Expect(err).To(BeNil()) }) + + It("podman run check personality support", func() { + // TODO: Remove this as soon as this is merged and made available in our CI https://github.com/opencontainers/runc/pull/3126. + if !strings.Contains(podmanTest.OCIRuntime, "crun") { + Skip("Test only works on crun") + } + session := podmanTest.Podman([]string{"run", "--personality=LINUX32", "--name=testpersonality", ALPINE, "uname", "-a"}) + session.WaitWithDefaultTimeout() + Expect(session).Should(Exit(0)) + Expect(session.OutputToString()).To(ContainSubstring("i686")) + }) }) diff --git a/test/system/255-auto-update.bats b/test/system/255-auto-update.bats index 6fb40f41e..4e242e1f1 100644 --- a/test/system/255-auto-update.bats +++ b/test/system/255-auto-update.bats @@ -26,9 +26,17 @@ function teardown() { done < $SNAME_FILE rm -f $SNAME_FILE - run_podman ? rmi quay.io/libpod/alpine:latest - run_podman ? rmi quay.io/libpod/busybox:latest - run_podman ? rmi quay.io/libpod/localtest:latest + run_podman ? rmi -f \ + quay.io/libpod/alpine:latest \ + quay.io/libpod/busybox:latest \ + quay.io/libpod/localtest:latest \ + quay.io/libpod/autoupdatebroken:latest \ + quay.io/libpod/test:latest \ + quay.io/libpod/fedora:31 + + # The rollback tests may leave some dangling images behind, so let's prune + # them to leave a clean state. + run_podman ? image prune -f basic_teardown } @@ -43,18 +51,30 @@ function teardown() { function generate_service() { local target_img_basename=$1 local autoupdate=$2 + local command=$3 + local extraArgs=$4 + local noTag=$5 + + # Unless specified, set a default command. + if [[ -z "$command" ]]; then + command="top -d 120" + fi # Container name. Include the autoupdate type, to make debugging easier. # IMPORTANT: variable 'cname' is passed (out of scope) up to caller! cname=c_${autoupdate//\'/}_$(random_string) target_img="quay.io/libpod/$target_img_basename:latest" - run_podman tag $IMAGE $target_img + + if [[ -z "$noTag" ]]; then + run_podman tag $IMAGE $target_img + fi + if [[ -n "$autoupdate" ]]; then label="--label io.containers.autoupdate=$autoupdate" else label="" fi - run_podman run -d --name $cname $label $target_img top -d 120 + run_podman create $extraArgs --name $cname $label $target_img $command (cd $UNIT_DIR; run_podman generate systemd --new --files --name $cname) echo "container-$cname" >> $SNAME_FILE @@ -128,6 +148,38 @@ function _confirm_update() { _confirm_update $cname $ori_image } +@test "podman auto-update - label io.containers.autoupdate=image with rollback" { + # Note: the autoupdatebroken image is empty on purpose so it cannot be + # executed and force a rollback. The rollback test for the local policy + # is exercising the case where the container doesn't send a ready message. + image=quay.io/libpod/autoupdatebroken + + run_podman tag $IMAGE $image + generate_service autoupdatebroken image + + _wait_service_ready container-$cname.service + run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" ".*container-$cname.service,$image:latest,pending,registry.*" "Image update is pending." + + run_podman container inspect --format "{{.Image}}" $cname + oldID="$output" + + run_podman inspect --format "{{.ID}}" $cname + containerID="$output" + + run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" "Trying to pull.*" "Image is updated." + is "$output" ".*container-$cname.service,$image:latest,rolled back,registry.*" "Image has been rolled back." + + run_podman container inspect --format "{{.Image}}" $cname + is "$output" "$oldID" "container rolled back to previous image" + + run_podman container inspect --format "{{.ID}}" $cname + if [[ $output == $containerID ]]; then + die "container has not been restarted during rollback (previous id: $containerID, current id: $output)" + fi +} + @test "podman auto-update - label io.containers.autoupdate=disabled" { generate_service alpine disabled @@ -168,6 +220,61 @@ function _confirm_update() { _confirm_update $cname $ori_image } +@test "podman auto-update - label io.containers.autoupdate=local with rollback" { + # sdnotify fails with runc 1.0.0-3-dev2 on Ubuntu. Let's just + # assume that we work only with crun, nothing else. + # [copied from 260-sdnotify.bats] + runtime=$(podman_runtime) + if [[ "$runtime" != "crun" ]]; then + skip "this test only works with crun, not $runtime" + fi + + dockerfile1=$PODMAN_TMPDIR/Dockerfile.1 + cat >$dockerfile1 <<EOF +FROM quay.io/libpod/fedora:31 +RUN echo -e "#!/bin/sh\n\ +printenv NOTIFY_SOCKET; echo READY; systemd-notify --ready;\n\ +trap 'echo Received SIGTERM, finishing; exit' SIGTERM; echo WAITING; while :; do sleep 0.1; done" \ +>> /runme +RUN chmod +x /runme +EOF + + dockerfile2=$PODMAN_TMPDIR/Dockerfile.2 + cat >$dockerfile2 <<EOF +FROM quay.io/libpod/fedora:31 +RUN echo -e "#!/bin/sh\n\ +exit 1" >> /runme +RUN chmod +x /runme +EOF + image=test + + # Generate a healthy image that will run correctly. + run_podman build -t quay.io/libpod/$image -f $dockerfile1 + podman image inspect --format "{{.ID}}" $image + oldID="$output" + + generate_service $image local /runme --sdnotify=container noTag + _wait_service_ready container-$cname.service + + run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" ".*container-$cname.service,quay.io/libpod/$image:latest,false,local.*" "No update available" + + # Generate an unhealthy image that will fail. + run_podman build -t quay.io/libpod/$image -f $dockerfile2 + podman image inspect --format "{{.ID}}" $image + newID="$output" + + run_podman auto-update --dry-run --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" ".*container-$cname.service,quay.io/libpod/$image:latest,pending,local.*" "Image updated is pending" + + # Note: we rollback automatically by default. + run_podman auto-update --format "{{.Unit}},{{.Image}},{{.Updated}},{{.Policy}}" + is "$output" ".*container-$cname.service,quay.io/libpod/$image:latest,rolled back,local.*" "Rolled back to old image" + + # Make sure that new container is not using the new image ID anymore. + _confirm_update $cname $newID +} + @test "podman auto-update with multiple services" { # Preserve original image ID, to confirm that it changes (or not) run_podman inspect --format "{{.Id}}" $IMAGE |