-
Notifications
You must be signed in to change notification settings - Fork 2.4k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Merge pull request #7588 from HarryMichal/add-toolbox-e2e-tests
tests/e2e: Add Toolbox-specific test cases
- Loading branch information
Showing
2 changed files
with
369 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,368 @@ | ||
package integration | ||
|
||
/* | ||
toolbox_test.go is under the care of the Toolbox Team. | ||
The tests are trying to stress parts of Podman that Toolbox[0] needs for | ||
its functionality. | ||
[0] https://github.com/containers/toolbox | ||
Info about test cases: | ||
- some tests rely on a certain configuration of a container that is done by | ||
executing several commands in the entry-point of a container. To make | ||
sure the initialization had enough time to be executed, | ||
WaitContainerReady() after the container is started. | ||
- in several places there's an invocation of 'podman logs' It is there mainly | ||
to ease debugging when a test goes wrong (during the initialization of a | ||
container) but sometimes it is also used in the test case itself. | ||
Maintainers (Toolbox Team): | ||
- Ondřej Míchal <[email protected]> | ||
- Debarshi Ray <[email protected]> | ||
Also available on Freenode IRC on #silverblue or #podman | ||
*/ | ||
|
||
import ( | ||
"fmt" | ||
"os" | ||
"os/exec" | ||
"os/user" | ||
"strconv" | ||
"strings" | ||
"syscall" | ||
|
||
. "github.com/containers/podman/v2/test/utils" | ||
. "github.com/onsi/ginkgo" | ||
. "github.com/onsi/gomega" | ||
) | ||
|
||
var _ = Describe("Toolbox-specific testing", 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 run --dns=none - allows self-management of /etc/resolv.conf", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
session = podmanTest.Podman([]string{"run", "--dns", "none", ALPINE, "sh", "-c", | ||
"rm -f /etc/resolv.conf; touch -d '1970-01-01 00:02:03' /etc/resolv.conf; stat -c %s:%Y /etc/resolv.conf"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring("0:123")) | ||
}) | ||
|
||
It("podman run --no-hosts - allows self-management of /etc/hosts", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
session = podmanTest.Podman([]string{"run", "--no-hosts", ALPINE, "sh", "-c", | ||
"rm -f /etc/hosts; touch -d '1970-01-01 00:02:03' /etc/hosts; stat -c %s:%Y /etc/hosts"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring("0:123")) | ||
}) | ||
|
||
It("podman create --ulimit host + podman exec - correctly mirrors hosts ulimits", func() { | ||
if podmanTest.RemoteTest { | ||
Skip("Ulimit check does not work with a remote client") | ||
} | ||
var session *PodmanSessionIntegration | ||
var containerHardLimit int | ||
var rlimit syscall.Rlimit | ||
var err error | ||
|
||
err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit) | ||
Expect(err).To(BeNil()) | ||
fmt.Printf("Expected value: %d", rlimit.Max) | ||
|
||
session = podmanTest.Podman([]string{"create", "--name", "test", "--ulimit", "host", ALPINE, | ||
"sleep", "1000"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"exec", "test", "sh", "-c", | ||
"ulimit -H -n"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
containerHardLimit, err = strconv.Atoi(strings.Trim(session.OutputToString(), "\n")) | ||
Expect(err).To(BeNil()) | ||
Expect(containerHardLimit).To(BeNumerically(">=", rlimit.Max)) | ||
}) | ||
|
||
It("podman create --ipc=host --pid=host + podman exec - correct shared memory limit size", func() { | ||
// Comparison of the size of /dev/shm on the host being equal to the one in | ||
// a container | ||
if podmanTest.RemoteTest { | ||
Skip("Shm size check does not work with a remote client") | ||
} | ||
var session *PodmanSessionIntegration | ||
var cmd *exec.Cmd | ||
var hostShmSize, containerShmSize int | ||
var err error | ||
|
||
// Because Alpine uses busybox, most commands don't offer advanced options | ||
// like "--output" in df. Therefore the value of the field 'Size' (or | ||
// ('1K-blocks') needs to be extracted manually. | ||
cmd = exec.Command("df", "/dev/shm") | ||
res, err := cmd.Output() | ||
Expect(err).To(BeNil()) | ||
lines := strings.SplitN(string(res), "\n", 2) | ||
fields := strings.Fields(lines[len(lines)-1]) | ||
hostShmSize, err = strconv.Atoi(fields[1]) | ||
Expect(err).To(BeNil()) | ||
|
||
session = podmanTest.Podman([]string{"create", "--name", "test", "--ipc=host", "--pid=host", ALPINE, | ||
"sleep", "1000"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"exec", "test", | ||
"df", "/dev/shm"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
lines = session.OutputToStringArray() | ||
fields = strings.Fields(lines[len(lines)-1]) | ||
containerShmSize, err = strconv.Atoi(fields[1]) | ||
Expect(err).To(BeNil()) | ||
|
||
// In some cases it may happen that the size of /dev/shm is not exactly | ||
// equal. Therefore it's fine if there's a slight tolerance between the | ||
// compared values. | ||
Expect(hostShmSize).To(BeNumerically("~", containerShmSize, 100)) | ||
}) | ||
|
||
It("podman create --userns=keep-id --user root:root - entrypoint - entrypoint is executed as root", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", ALPINE, | ||
"id"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring("uid=0(root) gid=0(root)")) | ||
}) | ||
|
||
It("podman create --userns=keep-id + podman exec - correct names of user and group", func() { | ||
var session *PodmanSessionIntegration | ||
var err error | ||
|
||
currentUser, err := user.Current() | ||
Expect(err).To(BeNil()) | ||
|
||
currentGroup, err := user.LookupGroupId(currentUser.Gid) | ||
Expect(err).To(BeNil()) | ||
|
||
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", ALPINE, | ||
"sleep", "1000"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(err).To(BeNil()) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
expectedOutput := fmt.Sprintf("uid=%s(%s) gid=%s(%s)", | ||
currentUser.Uid, currentUser.Username, | ||
currentGroup.Gid, currentGroup.Name) | ||
|
||
session = podmanTest.Podman([]string{"exec", "test", | ||
"id"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring(expectedOutput)) | ||
}) | ||
|
||
It("podman create --userns=keep-id - entrypoint - adding user with useradd and then removing their password", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
var username string = "testuser" | ||
var homeDir string = "/home/testuser" | ||
var shell string = "/bin/sh" | ||
var uid string = "1001" | ||
var gid string = "1001" | ||
|
||
useradd := fmt.Sprintf("useradd --home-dir %s --shell %s --uid %s %s", | ||
homeDir, shell, uid, username) | ||
passwd := fmt.Sprintf("passwd --delete %s", username) | ||
|
||
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c", | ||
fmt.Sprintf("%s; %s; echo READY; sleep 1000", useradd, passwd)}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue()) | ||
|
||
expectedOutput := fmt.Sprintf("%s:x:%s:%s::%s:%s", | ||
username, uid, gid, homeDir, shell) | ||
|
||
session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/passwd"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring(expectedOutput)) | ||
|
||
expectedOutput = "passwd: Note: deleting a password also unlocks the password." | ||
|
||
session = podmanTest.Podman([]string{"logs", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring(expectedOutput)) | ||
}) | ||
|
||
It("podman create --userns=keep-id + podman exec - adding group with groupadd", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
var groupName string = "testgroup" | ||
var gid string = "1001" | ||
|
||
groupadd := fmt.Sprintf("groupadd --gid %s %s", gid, groupName) | ||
|
||
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c", | ||
fmt.Sprintf("%s; echo READY; sleep 1000", groupadd)}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue()) | ||
|
||
session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/group"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring(groupName)) | ||
|
||
session = podmanTest.Podman([]string{"logs", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring("READY")) | ||
}) | ||
|
||
It("podman create --userns=keep-id - entrypoint - modifying existing user with usermod - add to new group, change home/shell/uid", func() { | ||
var session *PodmanSessionIntegration | ||
var badHomeDir string = "/home/badtestuser" | ||
var badShell string = "/bin/sh" | ||
var badUID string = "1001" | ||
var username string = "testuser" | ||
var homeDir string = "/home/testuser" | ||
var shell string = "/bin/bash" | ||
var uid string = "2000" | ||
var groupName string = "testgroup" | ||
var gid string = "2000" | ||
|
||
// The use of bad* in the name of variables does not imply the invocation | ||
// of useradd should fail The user is supposed to be created successfuly | ||
// but later his information (uid, home, shell,..) is changed via usermod. | ||
useradd := fmt.Sprintf("useradd --home-dir %s --shell %s --uid %s %s", | ||
badHomeDir, badShell, badUID, username) | ||
groupadd := fmt.Sprintf("groupadd --gid %s %s", | ||
gid, groupName) | ||
usermod := fmt.Sprintf("usermod --append --groups wheel --home %s --shell %s --uid %s --gid %s %s", | ||
homeDir, shell, uid, gid, username) | ||
|
||
session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c", | ||
fmt.Sprintf("%s; %s; %s; echo READY; sleep 1000", useradd, groupadd, usermod)}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue()) | ||
|
||
expectedUser := fmt.Sprintf("%s:x:%s:%s::%s:%s", | ||
username, uid, gid, homeDir, shell) | ||
|
||
session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/passwd"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring(expectedUser)) | ||
|
||
session = podmanTest.Podman([]string{"logs", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring("READY")) | ||
}) | ||
|
||
It("podman run --privileged --userns=keep-id --user root:root - entrypoint - (bind)mounting", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
session = podmanTest.Podman([]string{"run", "--privileged", "--userns=keep-id", "--user", "root:root", ALPINE, | ||
"mount", "-t", "tmpfs", "tmpfs", "/tmp"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"run", "--privileged", "--userns=keep-id", "--user", "root:root", ALPINE, | ||
"mount", "--rbind", "/tmp", "/var/tmp"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
}) | ||
|
||
It("podman create + start - with all needed switches for create - sleep as entry-point", func() { | ||
var session *PodmanSessionIntegration | ||
|
||
// These should be most of the switches that Toolbox uses to create a "toolbox" container | ||
// https://github.com/containers/toolbox/blob/master/src/cmd/create.go | ||
session = podmanTest.Podman([]string{"create", | ||
"--dns", "none", | ||
"--hostname", "toolbox", | ||
"--ipc", "host", | ||
"--label", "com.github.containers.toolbox=true", | ||
"--name", "test", | ||
"--network", "host", | ||
"--no-hosts", | ||
"--pid", "host", | ||
"--privileged", | ||
"--security-opt", "label=disable", | ||
"--ulimit", "host", | ||
"--userns=keep-id", | ||
"--user", "root:root", | ||
fedoraToolbox, "sh", "-c", "echo READY; sleep 1000"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
session = podmanTest.Podman([]string{"start", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
|
||
Expect(WaitContainerReady(podmanTest, "test", "READY", 2, 1)).To(BeTrue()) | ||
|
||
session = podmanTest.Podman([]string{"logs", "test"}) | ||
session.WaitWithDefaultTimeout() | ||
Expect(session.ExitCode()).To(Equal(0)) | ||
Expect(session.OutputToString()).To(ContainSubstring("READY")) | ||
}) | ||
}) |