summaryrefslogtreecommitdiff
path: root/test
diff options
context:
space:
mode:
Diffstat (limited to 'test')
-rw-r--r--test/e2e/checkpoint_image_test.go296
-rw-r--r--test/e2e/common_test.go11
-rw-r--r--test/e2e/create_test.go9
-rw-r--r--test/e2e/libpod_suite_remote_test.go3
-rw-r--r--test/e2e/pod_create_test.go8
-rw-r--r--test/system/200-pod.bats2
-rw-r--r--test/system/520-checkpoint.bats3
-rw-r--r--test/upgrade/test-upgrade.bats8
-rw-r--r--test/utils/utils.go2
9 files changed, 322 insertions, 20 deletions
diff --git a/test/e2e/checkpoint_image_test.go b/test/e2e/checkpoint_image_test.go
new file mode 100644
index 000000000..8274dfc80
--- /dev/null
+++ b/test/e2e/checkpoint_image_test.go
@@ -0,0 +1,296 @@
+package integration
+
+import (
+ "os"
+ "os/exec"
+ "strconv"
+ "strings"
+
+ "github.com/containers/podman/v4/pkg/criu"
+ . "github.com/containers/podman/v4/test/utils"
+ . "github.com/onsi/ginkgo"
+ . "github.com/onsi/gomega"
+ . "github.com/onsi/gomega/gexec"
+)
+
+var _ = Describe("Podman checkpoint", func() {
+ var (
+ tempdir string
+ err error
+ podmanTest *PodmanTestIntegration
+ )
+
+ BeforeEach(func() {
+ SkipIfRootless("checkpoint not supported in rootless mode")
+ tempdir, err = CreateTempDirInTempDir()
+ if err != nil {
+ os.Exit(1)
+ }
+ podmanTest = PodmanTestCreate(tempdir)
+ podmanTest.Setup()
+ podmanTest.SeedImages()
+ // Check if the runtime implements checkpointing. Currently only
+ // runc's checkpoint/restore implementation is supported.
+ cmd := exec.Command(podmanTest.OCIRuntime, "checkpoint", "--help")
+ if err := cmd.Start(); err != nil {
+ Skip("OCI runtime does not support checkpoint/restore")
+ }
+ if err := cmd.Wait(); err != nil {
+ Skip("OCI runtime does not support checkpoint/restore")
+ }
+
+ if !criu.CheckForCriu(criu.MinCriuVersion) {
+ Skip("CRIU is missing or too old.")
+ }
+ })
+
+ AfterEach(func() {
+ podmanTest.Cleanup()
+ f := CurrentGinkgoTestDescription()
+ processTestResult(f)
+ })
+
+ It("podman checkpoint --create-image with bogus container", func() {
+ checkpointImage := "foobar-checkpoint"
+ session := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "foobar"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).To(ExitWithError())
+ Expect(session.ErrorToString()).To(ContainSubstring("no container with name or ID \"foobar\" found"))
+ })
+
+ It("podman checkpoint --create-image with running container", func() {
+ // Container image must be lowercase
+ checkpointImage := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
+ containerName := "alpine-container-" + RandomString(6)
+
+ localRunString := []string{
+ "run",
+ "-it",
+ "-d",
+ "--ip", GetRandomIPAddress(),
+ "--name", containerName,
+ ALPINE,
+ "top",
+ }
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ containerID := session.OutputToString()
+
+ // Checkpoint image should not exist
+ session = podmanTest.Podman([]string{"images"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeFalse())
+
+ // Check if none of the checkpoint/restore specific information is displayed
+ // for newly started containers.
+ inspect := podmanTest.Podman([]string{"inspect", containerID})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ inspectOut := inspect.InspectContainerToJSON()
+ Expect(inspectOut[0].State.Checkpointed).To(BeFalse(), ".State.Checkpointed")
+ Expect(inspectOut[0].State.Restored).To(BeFalse(), ".State.Restored")
+ Expect(inspectOut[0].State.CheckpointPath).To(Equal(""))
+ Expect(inspectOut[0].State.CheckpointLog).To(Equal(""))
+ Expect(inspectOut[0].State.RestoreLog).To(Equal(""))
+
+ result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "--keep", containerID})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
+
+ inspect = podmanTest.Podman([]string{"inspect", containerID})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ inspectOut = inspect.InspectContainerToJSON()
+ Expect(inspectOut[0].State.Checkpointed).To(BeTrue(), ".State.Checkpointed")
+ Expect(inspectOut[0].State.CheckpointPath).To(ContainSubstring("userdata/checkpoint"))
+ Expect(inspectOut[0].State.CheckpointLog).To(ContainSubstring("userdata/dump.log"))
+
+ // Check if checkpoint image has been created
+ session = podmanTest.Podman([]string{"images"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeTrue())
+
+ // Check if the checkpoint image contains annotations
+ inspect = podmanTest.Podman([]string{"inspect", checkpointImage})
+ inspect.WaitWithDefaultTimeout()
+ Expect(inspect).Should(Exit(0))
+ inspectImageOut := inspect.InspectImageJSON()
+ Expect(inspectImageOut[0].Annotations["io.podman.annotations.checkpoint.name"]).To(
+ BeEquivalentTo(containerName),
+ "io.podman.annotations.checkpoint.name",
+ )
+
+ ociRuntimeName := ""
+ if strings.Contains(podmanTest.OCIRuntime, "runc") {
+ ociRuntimeName = "runc"
+ } else if strings.Contains(podmanTest.OCIRuntime, "crun") {
+ ociRuntimeName = "crun"
+ }
+ if ociRuntimeName != "" {
+ Expect(inspectImageOut[0].Annotations["io.podman.annotations.checkpoint.runtime.name"]).To(
+ BeEquivalentTo(ociRuntimeName),
+ "io.podman.annotations.checkpoint.runtime.name",
+ )
+ }
+
+ // Remove existing container
+ result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerID})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+
+ // Restore container from checkpoint image
+ result = podmanTest.Podman([]string{"container", "restore", checkpointImage})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Up"))
+
+ // Clean-up
+ result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+
+ result = podmanTest.Podman([]string{"rmi", checkpointImage})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ })
+
+ It("podman restore multiple containers from single checkpint image", func() {
+ // Container image must be lowercase
+ checkpointImage := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
+ containerName := "alpine-container-" + RandomString(6)
+
+ localRunString := []string{"run", "-d", "--name", containerName, ALPINE, "top"}
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ containerID := session.OutputToString()
+
+ // Checkpoint image should not exist
+ session = podmanTest.Podman([]string{"images"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeFalse())
+
+ result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage, "--keep", containerID})
+ result.WaitWithDefaultTimeout()
+
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ Expect(podmanTest.GetContainerStatus()).To(ContainSubstring("Exited"))
+
+ // Check if checkpoint image has been created
+ session = podmanTest.Podman([]string{"images"})
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ Expect(session.LineInOutputContainsTag("localhost/"+checkpointImage, "latest")).To(BeTrue())
+
+ // Remove existing container
+ result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerID})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+
+ for i := 1; i < 5; i++ {
+ // Restore container from checkpoint image
+ name := containerName + strconv.Itoa(i)
+ result = podmanTest.Podman([]string{"container", "restore", "--name", name, checkpointImage})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(i))
+
+ // Check that the container is running
+ status := podmanTest.Podman([]string{"inspect", name, "--format={{.State.Status}}"})
+ status.WaitWithDefaultTimeout()
+ Expect(status).Should(Exit(0))
+ Expect(status.OutputToString()).To(Equal("running"))
+ }
+
+ // Clean-up
+ result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+
+ result = podmanTest.Podman([]string{"rmi", checkpointImage})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ })
+
+ It("podman restore multiple containers from multiple checkpint images", func() {
+ // Container image must be lowercase
+ checkpointImage1 := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
+ checkpointImage2 := "alpine-checkpoint-" + strings.ToLower(RandomString(6))
+ containerName1 := "alpine-container-" + RandomString(6)
+ containerName2 := "alpine-container-" + RandomString(6)
+
+ // Create first container
+ localRunString := []string{"run", "-d", "--name", containerName1, ALPINE, "top"}
+ session := podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ containerID1 := session.OutputToString()
+
+ // Create second container
+ localRunString = []string{"run", "-d", "--name", containerName2, ALPINE, "top"}
+ session = podmanTest.Podman(localRunString)
+ session.WaitWithDefaultTimeout()
+ Expect(session).Should(Exit(0))
+ containerID2 := session.OutputToString()
+
+ // Checkpoint first container
+ result := podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage1, "--keep", containerID1})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(1))
+
+ // Checkpoint second container
+ result = podmanTest.Podman([]string{"container", "checkpoint", "--create-image", checkpointImage2, "--keep", containerID2})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+
+ // Remove existing containers
+ result = podmanTest.Podman([]string{"rm", "-t", "1", "-f", containerName1, containerName2})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+
+ // Restore both containers from images
+ result = podmanTest.Podman([]string{"container", "restore", checkpointImage1, checkpointImage2})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(2))
+
+ // Check if first container is running
+ status := podmanTest.Podman([]string{"inspect", containerName1, "--format={{.State.Status}}"})
+ status.WaitWithDefaultTimeout()
+ Expect(status).Should(Exit(0))
+ Expect(status.OutputToString()).To(Equal("running"))
+
+ // Check if second container is running
+ status = podmanTest.Podman([]string{"inspect", containerName2, "--format={{.State.Status}}"})
+ status.WaitWithDefaultTimeout()
+ Expect(status).Should(Exit(0))
+ Expect(status.OutputToString()).To(Equal("running"))
+
+ // Clean-up
+ result = podmanTest.Podman([]string{"rm", "-t", "0", "-fa"})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+
+ result = podmanTest.Podman([]string{"rmi", checkpointImage1, checkpointImage2})
+ result.WaitWithDefaultTimeout()
+ Expect(result).Should(Exit(0))
+ Expect(podmanTest.NumberOfContainersRunning()).To(Equal(0))
+ })
+})
diff --git a/test/e2e/common_test.go b/test/e2e/common_test.go
index 9580230b5..2f4146bba 100644
--- a/test/e2e/common_test.go
+++ b/test/e2e/common_test.go
@@ -858,18 +858,15 @@ func (p *PodmanTestIntegration) makeOptions(args []string, noEvents, noCache boo
eventsType = "none"
}
- networkBackend := p.NetworkBackend.ToString()
- networkDir := p.NetworkConfigDir
- if p.NetworkBackend == Netavark {
- networkDir = p.NetworkConfigDir
- }
podmanOptions := strings.Split(fmt.Sprintf("%s--root %s --runroot %s --runtime %s --conmon %s --network-config-dir %s --cgroup-manager %s --tmpdir %s --events-backend %s",
- debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, networkDir, p.CgroupManager, p.TmpDir, eventsType), " ")
+ debug, p.Root, p.RunRoot, p.OCIRuntime, p.ConmonBinary, p.NetworkConfigDir, p.CgroupManager, p.TmpDir, eventsType), " ")
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
- podmanOptions = append(podmanOptions, "--network-backend", networkBackend)
+ if !p.RemoteTest {
+ podmanOptions = append(podmanOptions, "--network-backend", p.NetworkBackend.ToString())
+ }
podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
if !noCache {
diff --git a/test/e2e/create_test.go b/test/e2e/create_test.go
index 11f8b5abf..4c3b5604a 100644
--- a/test/e2e/create_test.go
+++ b/test/e2e/create_test.go
@@ -118,7 +118,7 @@ var _ = Describe("Podman create", func() {
result := podmanTest.Podman([]string{"inspect", "entrypoint_test", "--format", "{{.Config.Entrypoint}}"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(Equal("[/bin/foobar]"))
+ Expect(result.OutputToString()).To(Equal("/bin/foobar"))
})
It("podman create --entrypoint \"\"", func() {
@@ -130,7 +130,7 @@ var _ = Describe("Podman create", func() {
result := podmanTest.Podman([]string{"inspect", session.OutputToString(), "--format", "{{.Config.Entrypoint}}"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(Equal("[]"))
+ Expect(result.OutputToString()).To(Equal(""))
})
It("podman create --entrypoint json", func() {
@@ -143,7 +143,7 @@ var _ = Describe("Podman create", func() {
result := podmanTest.Podman([]string{"inspect", "entrypoint_json", "--format", "{{.Config.Entrypoint}}"})
result.WaitWithDefaultTimeout()
Expect(result).Should(Exit(0))
- Expect(result.OutputToString()).To(Equal("[/bin/foo -c]"))
+ Expect(result.OutputToString()).To(Equal("/bin/foo -c"))
})
It("podman create --mount flag with multiple mounts", func() {
@@ -281,8 +281,7 @@ var _ = Describe("Podman create", func() {
Expect(ctrJSON).To(HaveLen(1))
Expect(ctrJSON[0].Config.Cmd).To(HaveLen(1))
Expect(ctrJSON[0].Config.Cmd[0]).To(Equal("redis-server"))
- Expect(ctrJSON[0].Config.Entrypoint).To(HaveLen(1))
- Expect(ctrJSON[0].Config.Entrypoint[0]).To(Equal("docker-entrypoint.sh"))
+ Expect(ctrJSON[0].Config.Entrypoint).To(Equal("docker-entrypoint.sh"))
})
It("podman create --pull", func() {
diff --git a/test/e2e/libpod_suite_remote_test.go b/test/e2e/libpod_suite_remote_test.go
index dddcf5c14..9ad2bf7b9 100644
--- a/test/e2e/libpod_suite_remote_test.go
+++ b/test/e2e/libpod_suite_remote_test.go
@@ -137,6 +137,9 @@ func getRemoteOptions(p *PodmanTestIntegration, args []string) []string {
if os.Getenv("HOOK_OPTION") != "" {
podmanOptions = append(podmanOptions, os.Getenv("HOOK_OPTION"))
}
+ if p.NetworkBackend.ToString() == "netavark" {
+ podmanOptions = append(podmanOptions, "--network-backend", "netavark")
+ }
podmanOptions = append(podmanOptions, strings.Split(p.StorageOptions, " ")...)
podmanOptions = append(podmanOptions, args...)
return podmanOptions
diff --git a/test/e2e/pod_create_test.go b/test/e2e/pod_create_test.go
index dc43ce6fd..8def80213 100644
--- a/test/e2e/pod_create_test.go
+++ b/test/e2e/pod_create_test.go
@@ -368,7 +368,7 @@ var _ = Describe("Podman pod create", func() {
check1 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Config.Entrypoint}}", data.Containers[0].ID})
check1.WaitWithDefaultTimeout()
Expect(check1).Should(Exit(0))
- Expect(check1.OutputToString()).To(Equal("[/catatonit -P]"))
+ Expect(check1.OutputToString()).To(Equal("/catatonit -P"))
// check the Path and Args
check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
@@ -391,7 +391,7 @@ var _ = Describe("Podman pod create", func() {
check1 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Config.Entrypoint}}", data.Containers[0].ID})
check1.WaitWithDefaultTimeout()
Expect(check1).Should(Exit(0))
- Expect(check1.OutputToString()).To(Equal("[/pause1]"))
+ Expect(check1.OutputToString()).To(Equal("/pause1"))
// check the Path and Args
check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
@@ -418,7 +418,7 @@ entrypoint ["/fromimage"]
check1 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Config.Entrypoint}}", data.Containers[0].ID})
check1.WaitWithDefaultTimeout()
Expect(check1).Should(Exit(0))
- Expect(check1.OutputToString()).To(Equal("[/fromimage]"))
+ Expect(check1.OutputToString()).To(Equal("/fromimage"))
// check the Path and Args
check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
@@ -445,7 +445,7 @@ entrypoint ["/fromimage"]
check1 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Config.Entrypoint}}", data.Containers[0].ID})
check1.WaitWithDefaultTimeout()
Expect(check1).Should(Exit(0))
- Expect(check1.OutputToString()).To(Equal("[/fromcommand]"))
+ Expect(check1.OutputToString()).To(Equal("/fromcommand"))
// check the Path and Args
check2 := podmanTest.Podman([]string{"container", "inspect", "--format", "{{.Path}}:{{.Args}}", data.Containers[0].ID})
diff --git a/test/system/200-pod.bats b/test/system/200-pod.bats
index e6f4ecdbc..f5fe41924 100644
--- a/test/system/200-pod.bats
+++ b/test/system/200-pod.bats
@@ -234,7 +234,7 @@ EOF
local infra_cid="$output"
# confirm that entrypoint is what we set
run_podman container inspect --format '{{.Config.Entrypoint}}' $infra_cid
- is "$output" "[$infra_command]" "infra-command took effect"
+ is "$output" "$infra_command" "infra-command took effect"
# confirm that infra container name is set
run_podman container inspect --format '{{.Name}}' $infra_cid
is "$output" "$infra_name" "infra-name took effect"
diff --git a/test/system/520-checkpoint.bats b/test/system/520-checkpoint.bats
index 046dfd126..b41d460a4 100644
--- a/test/system/520-checkpoint.bats
+++ b/test/system/520-checkpoint.bats
@@ -47,7 +47,8 @@ function teardown() {
# Checkpoint, and confirm via inspect
run_podman container checkpoint $cid
- is "$output" "$cid" "podman container checkpoint"
+ # FIXME: remove the `.*` prefix after fix packaged for https://github.com/checkpoint-restore/criu/pull/1706
+ is "$output" ".*$cid" "podman container checkpoint"
run_podman container inspect \
--format '{{.State.Status}}:{{.State.Running}}:{{.State.Paused}}:{{.State.Checkpointed}}' $cid
diff --git a/test/upgrade/test-upgrade.bats b/test/upgrade/test-upgrade.bats
index 198d8a169..5efe05d49 100644
--- a/test/upgrade/test-upgrade.bats
+++ b/test/upgrade/test-upgrade.bats
@@ -146,6 +146,12 @@ EOF
# cause connectivity issues since cni and netavark should never be mixed.
mkdir -p /run/netns /run/cni /run/containers /var/lib/cni /etc/cni/net.d
+ # Containers-common around release 1-55 no-longer supplies this file
+ sconf=/etc/containers/storage.conf
+ v_sconf=
+ if [[ -e "$sconf" ]]; then
+ v_sconf="-v $sconf:$sconf"
+ fi
#
# Use new-podman to run the above script under old-podman.
@@ -165,7 +171,7 @@ EOF
--net=host \
--cgroupns=host \
--pid=host \
- -v /etc/containers/storage.conf:/etc/containers/storage.conf \
+ $v_sconf \
-v /dev/fuse:/dev/fuse \
-v /run/crun:/run/crun \
-v /run/netns:/run/netns:rshared \
diff --git a/test/utils/utils.go b/test/utils/utils.go
index da56a3a2e..39a0ac875 100644
--- a/test/utils/utils.go
+++ b/test/utils/utils.go
@@ -110,7 +110,7 @@ func (p *PodmanTest) PodmanAsUserBase(args []string, uid, gid uint32, cwd string
}
runCmd := append(wrapper, podmanBinary)
- if p.NetworkBackend == Netavark {
+ if !p.RemoteTest && p.NetworkBackend == Netavark {
runCmd = append(runCmd, []string{"--network-backend", "netavark"}...)
}