github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/toolbox_test.go (about) 1 package integration 2 3 /* 4 toolbox_test.go is under the care of the Toolbox Team. 5 6 The tests are trying to stress parts of Podman that Toolbox[0] needs for 7 its functionality. 8 9 [0] https://github.com/containers/toolbox 10 11 Info about test cases: 12 - some tests rely on a certain configuration of a container that is done by 13 executing several commands in the entry-point of a container. To make 14 sure the initialization had enough time to be executed, 15 WaitContainerReady() after the container is started. 16 17 - in several places there's an invocation of 'podman logs' It is there mainly 18 to ease debugging when a test goes wrong (during the initialization of a 19 container) but sometimes it is also used in the test case itself. 20 21 Maintainers (Toolbox Team): 22 - Ondřej Míchal <harrymichal@fedoraproject.org> 23 - Debarshi Ray <rishi@fedoraproject.org> 24 25 Also available on Freenode IRC on #silverblue or #podman 26 */ 27 28 import ( 29 "fmt" 30 "os/exec" 31 "os/user" 32 "path" 33 "strconv" 34 "strings" 35 "syscall" 36 37 "github.com/containers/podman/v5/libpod/define" 38 . "github.com/containers/podman/v5/test/utils" 39 . "github.com/onsi/ginkgo/v2" 40 . "github.com/onsi/gomega" 41 ) 42 43 var _ = Describe("Toolbox-specific testing", func() { 44 45 It("podman run --dns=none - allows self-management of /etc/resolv.conf", func() { 46 session := podmanTest.Podman([]string{"run", "--dns", "none", ALPINE, "sh", "-c", 47 "rm -f /etc/resolv.conf; touch -d '1970-01-01 00:02:03' /etc/resolv.conf; stat -c %s:%Y /etc/resolv.conf"}) 48 session.WaitWithDefaultTimeout() 49 Expect(session).Should(ExitCleanly()) 50 Expect(session.OutputToString()).To(ContainSubstring("0:123")) 51 }) 52 53 It("podman run --no-hosts - allows self-management of /etc/hosts", func() { 54 session := podmanTest.Podman([]string{"run", "--no-hosts", ALPINE, "sh", "-c", 55 "rm -f /etc/hosts; touch -d '1970-01-01 00:02:03' /etc/hosts; stat -c %s:%Y /etc/hosts"}) 56 session.WaitWithDefaultTimeout() 57 Expect(session).Should(ExitCleanly()) 58 Expect(session.OutputToString()).To(ContainSubstring("0:123")) 59 }) 60 61 It("podman create --ulimit host + podman exec - correctly mirrors hosts ulimits", func() { 62 if podmanTest.RemoteTest { 63 Skip("Ulimit check does not work with a remote client") 64 } 65 var session *PodmanSessionIntegration 66 var containerHardLimit int 67 var rlimit syscall.Rlimit 68 var err error 69 70 err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit) 71 Expect(err).ToNot(HaveOccurred()) 72 GinkgoWriter.Printf("Expected value: %d", rlimit.Max) 73 74 session = podmanTest.Podman([]string{"create", "--name", "test", "--ulimit", "host", ALPINE, 75 "sleep", "1000"}) 76 session.WaitWithDefaultTimeout() 77 Expect(session).Should(ExitCleanly()) 78 79 session = podmanTest.Podman([]string{"start", "test"}) 80 session.WaitWithDefaultTimeout() 81 Expect(session).Should(ExitCleanly()) 82 83 session = podmanTest.Podman([]string{"exec", "test", "sh", "-c", 84 "ulimit -H -n"}) 85 session.WaitWithDefaultTimeout() 86 Expect(session).Should(ExitCleanly()) 87 containerHardLimit, err = strconv.Atoi(strings.Trim(session.OutputToString(), "\n")) 88 Expect(err).ToNot(HaveOccurred()) 89 Expect(containerHardLimit).To(BeNumerically(">=", rlimit.Max)) 90 }) 91 92 It("podman create --ipc=host --pid=host + podman exec - correct shared memory limit size", func() { 93 // Comparison of the size of /dev/shm on the host being equal to the one in 94 // a container 95 if podmanTest.RemoteTest { 96 Skip("Shm size check does not work with a remote client") 97 } 98 SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") 99 var session *PodmanSessionIntegration 100 var cmd *exec.Cmd 101 var hostShmSize, containerShmSize int 102 var err error 103 104 // Because Alpine uses busybox, most commands don't offer advanced options 105 // like "--output" in df. Therefore the value of the field 'Size' (or 106 // ('1K-blocks') needs to be extracted manually. 107 cmd = exec.Command("df", "/dev/shm") 108 res, err := cmd.Output() 109 Expect(err).ToNot(HaveOccurred()) 110 lines := strings.SplitN(string(res), "\n", 2) 111 fields := strings.Fields(lines[len(lines)-1]) 112 hostShmSize, err = strconv.Atoi(fields[1]) 113 Expect(err).ToNot(HaveOccurred()) 114 115 session = podmanTest.Podman([]string{"create", "--name", "test", "--ipc=host", "--pid=host", ALPINE, 116 "sleep", "1000"}) 117 session.WaitWithDefaultTimeout() 118 Expect(session).Should(ExitCleanly()) 119 120 session = podmanTest.Podman([]string{"start", "test"}) 121 session.WaitWithDefaultTimeout() 122 Expect(session).Should(ExitCleanly()) 123 124 session = podmanTest.Podman([]string{"exec", "test", 125 "df", "/dev/shm"}) 126 session.WaitWithDefaultTimeout() 127 Expect(session).Should(ExitCleanly()) 128 lines = session.OutputToStringArray() 129 fields = strings.Fields(lines[len(lines)-1]) 130 containerShmSize, err = strconv.Atoi(fields[1]) 131 Expect(err).ToNot(HaveOccurred()) 132 133 // In some cases it may happen that the size of /dev/shm is not exactly 134 // equal. Therefore it's fine if there's a slight tolerance between the 135 // compared values. 136 Expect(hostShmSize).To(BeNumerically("~", containerShmSize, 100)) 137 }) 138 139 It("podman create --userns=keep-id --user root:root - entrypoint - entrypoint is executed as root", func() { 140 SkipIfNotRootless("only meaningful when run rootless") 141 session := podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", ALPINE, 142 "id"}) 143 session.WaitWithDefaultTimeout() 144 Expect(session).Should(ExitCleanly()) 145 Expect(session.OutputToString()).To(ContainSubstring("uid=0(root) gid=0(root)")) 146 }) 147 148 It("podman create --userns=keep-id + podman exec - correct names of user and group", func() { 149 SkipIfNotRootless("only meaningful when run rootless") 150 var session *PodmanSessionIntegration 151 var err error 152 153 currentUser, err := user.Current() 154 Expect(err).ToNot(HaveOccurred()) 155 156 currentGroup, err := user.LookupGroupId(currentUser.Gid) 157 Expect(err).ToNot(HaveOccurred()) 158 159 session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", ALPINE, 160 "sleep", "1000"}) 161 session.WaitWithDefaultTimeout() 162 Expect(session).Should(ExitCleanly()) 163 Expect(err).ToNot(HaveOccurred()) 164 165 session = podmanTest.Podman([]string{"start", "test"}) 166 session.WaitWithDefaultTimeout() 167 Expect(session).Should(ExitCleanly()) 168 169 expectedOutput := fmt.Sprintf("uid=%s(%s) gid=%s(%s)", 170 currentUser.Uid, currentUser.Username, 171 currentGroup.Gid, currentGroup.Name) 172 173 session = podmanTest.Podman([]string{"exec", "test", 174 "id"}) 175 session.WaitWithDefaultTimeout() 176 Expect(session).Should(ExitCleanly()) 177 Expect(session.OutputToString()).To(ContainSubstring(expectedOutput)) 178 }) 179 180 It("podman run --userns=keep-id - modify /etc/passwd and /etc/group", func() { 181 passwdLine := "testuser:x:1001:1001::/home/testuser:/bin/sh" 182 groupLine := "testuser:x:1001:" 183 184 // ensure that the container can edit passwd and group files 185 session := podmanTest.Podman([]string{"run", "--log-driver", "k8s-file", "--name", "test", "--userns=keep-id", 186 "--user", "root:root", ALPINE, "sh", "-c", 187 fmt.Sprintf("echo %s > /etc/passwd && echo %s > /etc/group && cat /etc/passwd && cat /etc/group", passwdLine, groupLine)}) 188 session.WaitWithDefaultTimeout() 189 Expect(session).Should(ExitCleanly()) 190 Expect(session.OutputToString()).Should(ContainSubstring(passwdLine)) 191 Expect(session.OutputToString()).Should(ContainSubstring(groupLine)) 192 }) 193 194 It("podman run --privileged --userns=keep-id --user root:root - entrypoint - (bind)mounting", func() { 195 SkipIfNotRootless("only meaningful when run rootless") 196 var session *PodmanSessionIntegration 197 198 session = podmanTest.Podman([]string{"run", "--privileged", "--userns=keep-id", "--user", "root:root", ALPINE, 199 "mount", "-t", define.TypeTmpfs, define.TypeTmpfs, "/tmp"}) 200 session.WaitWithDefaultTimeout() 201 Expect(session).Should(ExitCleanly()) 202 203 session = podmanTest.Podman([]string{"run", "--privileged", "--userns=keep-id", "--user", "root:root", ALPINE, 204 "mount", "--rbind", "/tmp", "/var/tmp"}) 205 session.WaitWithDefaultTimeout() 206 Expect(session).Should(ExitCleanly()) 207 }) 208 209 It("podman create + start - with all needed switches for create", func() { 210 SkipIfNotRootless("only meaningful when run rootless") 211 212 // These should be most of the switches that Toolbox uses to create a "toolbox" container 213 // https://github.com/containers/toolbox/blob/main/src/cmd/create.go 214 session := podmanTest.Podman([]string{"create", 215 "--log-driver", "k8s-file", 216 "--dns", "none", 217 "--hostname", "toolbox", 218 "--ipc", "host", 219 "--label", "com.github.containers.toolbox=true", 220 "--name", "test", 221 "--network", "host", 222 "--no-hosts", 223 "--pid", "host", 224 "--privileged", 225 "--security-opt", "label=disable", 226 "--ulimit", "host", 227 "--userns=keep-id", 228 "--user", "root:root", 229 ALPINE, "sh", "-c", "echo READY"}) 230 session.WaitWithDefaultTimeout() 231 Expect(session).Should(ExitCleanly()) 232 233 session = podmanTest.Podman([]string{"start", "-a", "test"}) 234 session.WaitWithDefaultTimeout() 235 Expect(session).Should(ExitCleanly()) 236 Expect(session.OutputToString()).Should(ContainSubstring("READY")) 237 }) 238 239 It("podman run --userns=keep-id check $HOME", func() { 240 SkipIfNotRootless("only meaningful when run rootless") 241 var session *PodmanSessionIntegration 242 currentUser, err := user.Current() 243 Expect(err).ToNot(HaveOccurred()) 244 245 session = podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:%s", currentUser.HomeDir, currentUser.HomeDir), "--userns=keep-id", ALPINE, "sh", "-c", "echo $HOME"}) 246 session.WaitWithDefaultTimeout() 247 Expect(session).Should(ExitCleanly()) 248 Expect(session.OutputToString()).To(ContainSubstring(currentUser.HomeDir)) 249 250 location := path.Dir(currentUser.HomeDir) 251 volumeArg := fmt.Sprintf("%s:%s", location, location) 252 session = podmanTest.Podman([]string{"run", 253 "--userns=keep-id", 254 "--volume", volumeArg, 255 ALPINE, "sh", "-c", "echo $HOME"}) 256 session.WaitWithDefaultTimeout() 257 Expect(session).Should(ExitCleanly()) 258 Expect(session.OutputToString()).To(ContainSubstring(currentUser.HomeDir)) 259 }) 260 261 })