github.com/AbhinandanKurakure/podman/v3@v3.4.10/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" 31 "os/exec" 32 "os/user" 33 "path" 34 "strconv" 35 "strings" 36 "syscall" 37 38 "github.com/containers/podman/v3/pkg/rootless" 39 . "github.com/containers/podman/v3/test/utils" 40 . "github.com/onsi/ginkgo" 41 . "github.com/onsi/gomega" 42 . "github.com/onsi/gomega/gexec" 43 ) 44 45 var _ = Describe("Toolbox-specific testing", func() { 46 var ( 47 tempdir string 48 err error 49 podmanTest *PodmanTestIntegration 50 ) 51 52 BeforeEach(func() { 53 tempdir, err = CreateTempDirInTempDir() 54 if err != nil { 55 os.Exit(1) 56 } 57 podmanTest = PodmanTestCreate(tempdir) 58 podmanTest.Setup() 59 podmanTest.SeedImages() 60 }) 61 62 AfterEach(func() { 63 podmanTest.Cleanup() 64 f := CurrentGinkgoTestDescription() 65 processTestResult(f) 66 }) 67 68 It("podman run --dns=none - allows self-management of /etc/resolv.conf", func() { 69 var session *PodmanSessionIntegration 70 71 session = podmanTest.Podman([]string{"run", "--dns", "none", ALPINE, "sh", "-c", 72 "rm -f /etc/resolv.conf; touch -d '1970-01-01 00:02:03' /etc/resolv.conf; stat -c %s:%Y /etc/resolv.conf"}) 73 session.WaitWithDefaultTimeout() 74 Expect(session).Should(Exit(0)) 75 Expect(session.OutputToString()).To(ContainSubstring("0:123")) 76 }) 77 78 It("podman run --no-hosts - allows self-management of /etc/hosts", func() { 79 var session *PodmanSessionIntegration 80 81 session = podmanTest.Podman([]string{"run", "--no-hosts", ALPINE, "sh", "-c", 82 "rm -f /etc/hosts; touch -d '1970-01-01 00:02:03' /etc/hosts; stat -c %s:%Y /etc/hosts"}) 83 session.WaitWithDefaultTimeout() 84 Expect(session).Should(Exit(0)) 85 Expect(session.OutputToString()).To(ContainSubstring("0:123")) 86 }) 87 88 It("podman create --ulimit host + podman exec - correctly mirrors hosts ulimits", func() { 89 if podmanTest.RemoteTest { 90 Skip("Ulimit check does not work with a remote client") 91 } 92 var session *PodmanSessionIntegration 93 var containerHardLimit int 94 var rlimit syscall.Rlimit 95 var err error 96 97 err = syscall.Getrlimit(syscall.RLIMIT_NOFILE, &rlimit) 98 Expect(err).To(BeNil()) 99 fmt.Printf("Expected value: %d", rlimit.Max) 100 101 session = podmanTest.Podman([]string{"create", "--name", "test", "--ulimit", "host", ALPINE, 102 "sleep", "1000"}) 103 session.WaitWithDefaultTimeout() 104 Expect(session).Should(Exit(0)) 105 106 session = podmanTest.Podman([]string{"start", "test"}) 107 session.WaitWithDefaultTimeout() 108 Expect(session).Should(Exit(0)) 109 110 session = podmanTest.Podman([]string{"exec", "test", "sh", "-c", 111 "ulimit -H -n"}) 112 session.WaitWithDefaultTimeout() 113 Expect(session).Should(Exit(0)) 114 containerHardLimit, err = strconv.Atoi(strings.Trim(session.OutputToString(), "\n")) 115 Expect(err).To(BeNil()) 116 Expect(containerHardLimit).To(BeNumerically(">=", rlimit.Max)) 117 }) 118 119 It("podman create --ipc=host --pid=host + podman exec - correct shared memory limit size", func() { 120 // Comparison of the size of /dev/shm on the host being equal to the one in 121 // a container 122 if podmanTest.RemoteTest { 123 Skip("Shm size check does not work with a remote client") 124 } 125 SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1") 126 var session *PodmanSessionIntegration 127 var cmd *exec.Cmd 128 var hostShmSize, containerShmSize int 129 var err error 130 131 // Because Alpine uses busybox, most commands don't offer advanced options 132 // like "--output" in df. Therefore the value of the field 'Size' (or 133 // ('1K-blocks') needs to be extracted manually. 134 cmd = exec.Command("df", "/dev/shm") 135 res, err := cmd.Output() 136 Expect(err).To(BeNil()) 137 lines := strings.SplitN(string(res), "\n", 2) 138 fields := strings.Fields(lines[len(lines)-1]) 139 hostShmSize, err = strconv.Atoi(fields[1]) 140 Expect(err).To(BeNil()) 141 142 session = podmanTest.Podman([]string{"create", "--name", "test", "--ipc=host", "--pid=host", ALPINE, 143 "sleep", "1000"}) 144 session.WaitWithDefaultTimeout() 145 Expect(session).Should(Exit(0)) 146 147 session = podmanTest.Podman([]string{"start", "test"}) 148 session.WaitWithDefaultTimeout() 149 Expect(session).Should(Exit(0)) 150 151 session = podmanTest.Podman([]string{"exec", "test", 152 "df", "/dev/shm"}) 153 session.WaitWithDefaultTimeout() 154 Expect(session).Should(Exit(0)) 155 lines = session.OutputToStringArray() 156 fields = strings.Fields(lines[len(lines)-1]) 157 containerShmSize, err = strconv.Atoi(fields[1]) 158 Expect(err).To(BeNil()) 159 160 // In some cases it may happen that the size of /dev/shm is not exactly 161 // equal. Therefore it's fine if there's a slight tolerance between the 162 // compared values. 163 Expect(hostShmSize).To(BeNumerically("~", containerShmSize, 100)) 164 }) 165 166 It("podman create --userns=keep-id --user root:root - entrypoint - entrypoint is executed as root", func() { 167 var session *PodmanSessionIntegration 168 169 session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--user", "root:root", ALPINE, 170 "id"}) 171 session.WaitWithDefaultTimeout() 172 Expect(session).Should(Exit(0)) 173 Expect(session.OutputToString()).To(ContainSubstring("uid=0(root) gid=0(root)")) 174 }) 175 176 It("podman create --userns=keep-id + podman exec - correct names of user and group", func() { 177 var session *PodmanSessionIntegration 178 var err error 179 180 currentUser, err := user.Current() 181 Expect(err).To(BeNil()) 182 183 currentGroup, err := user.LookupGroupId(currentUser.Gid) 184 Expect(err).To(BeNil()) 185 186 session = podmanTest.Podman([]string{"create", "--name", "test", "--userns=keep-id", ALPINE, 187 "sleep", "1000"}) 188 session.WaitWithDefaultTimeout() 189 Expect(session).Should(Exit(0)) 190 Expect(err).To(BeNil()) 191 192 session = podmanTest.Podman([]string{"start", "test"}) 193 session.WaitWithDefaultTimeout() 194 Expect(session).Should(Exit(0)) 195 196 expectedOutput := fmt.Sprintf("uid=%s(%s) gid=%s(%s)", 197 currentUser.Uid, currentUser.Username, 198 currentGroup.Gid, currentGroup.Name) 199 200 session = podmanTest.Podman([]string{"exec", "test", 201 "id"}) 202 session.WaitWithDefaultTimeout() 203 Expect(session).Should(Exit(0)) 204 Expect(session.OutputToString()).To(ContainSubstring(expectedOutput)) 205 }) 206 207 It("podman create --userns=keep-id - entrypoint - adding user with useradd and then removing their password", func() { 208 var session *PodmanSessionIntegration 209 210 var username string = "testuser" 211 var homeDir string = "/home/testuser" 212 var shell string = "/bin/sh" 213 var uid string = "1001" 214 var gid string = "1001" 215 216 useradd := fmt.Sprintf("useradd --home-dir %s --shell %s --uid %s %s", 217 homeDir, shell, uid, username) 218 passwd := fmt.Sprintf("passwd --delete %s", username) 219 session = podmanTest.Podman([]string{"create", "--log-driver", "k8s-file", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c", 220 fmt.Sprintf("%s; %s; echo READY; sleep 1000", useradd, passwd)}) 221 session.WaitWithDefaultTimeout() 222 Expect(session).Should(Exit(0)) 223 224 session = podmanTest.Podman([]string{"start", "test"}) 225 session.WaitWithDefaultTimeout() 226 Expect(session).Should(Exit(0)) 227 228 Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue()) 229 230 expectedOutput := fmt.Sprintf("%s:x:%s:%s::%s:%s", 231 username, uid, gid, homeDir, shell) 232 233 session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/passwd"}) 234 session.WaitWithDefaultTimeout() 235 Expect(session).Should(Exit(0)) 236 Expect(session.OutputToString()).To(ContainSubstring(expectedOutput)) 237 238 expectedOutput = "passwd: Note: deleting a password also unlocks the password." 239 240 session = podmanTest.Podman([]string{"logs", "test"}) 241 session.WaitWithDefaultTimeout() 242 Expect(session).Should(Exit(0)) 243 Expect(session.ErrorToString()).To(ContainSubstring(expectedOutput)) 244 }) 245 246 It("podman create --userns=keep-id + podman exec - adding group with groupadd", func() { 247 var session *PodmanSessionIntegration 248 249 var groupName string = "testgroup" 250 var gid string = "1001" 251 252 groupadd := fmt.Sprintf("groupadd --gid %s %s", gid, groupName) 253 254 session = podmanTest.Podman([]string{"create", "--log-driver", "k8s-file", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c", 255 fmt.Sprintf("%s; echo READY; sleep 1000", groupadd)}) 256 session.WaitWithDefaultTimeout() 257 Expect(session).Should(Exit(0)) 258 259 session = podmanTest.Podman([]string{"start", "test"}) 260 session.WaitWithDefaultTimeout() 261 Expect(session).Should(Exit(0)) 262 263 Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue()) 264 265 session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/group"}) 266 session.WaitWithDefaultTimeout() 267 Expect(session).Should(Exit(0)) 268 Expect(session.OutputToString()).To(ContainSubstring(groupName)) 269 270 session = podmanTest.Podman([]string{"logs", "test"}) 271 session.WaitWithDefaultTimeout() 272 Expect(session).Should(Exit(0)) 273 Expect(session.OutputToString()).To(ContainSubstring("READY")) 274 }) 275 276 It("podman create --userns=keep-id - entrypoint - modifying existing user with usermod - add to new group, change home/shell/uid", func() { 277 var session *PodmanSessionIntegration 278 var badHomeDir string = "/home/badtestuser" 279 var badShell string = "/bin/sh" 280 var badUID string = "1001" 281 var username string = "testuser" 282 var homeDir string = "/home/testuser" 283 var shell string = "/bin/bash" 284 var uid string = "2000" 285 var groupName string = "testgroup" 286 var gid string = "2000" 287 288 // The use of bad* in the name of variables does not imply the invocation 289 // of useradd should fail The user is supposed to be created successfully 290 // but later his information (uid, home, shell,..) is changed via usermod. 291 useradd := fmt.Sprintf("useradd --home-dir %s --shell %s --uid %s %s", 292 badHomeDir, badShell, badUID, username) 293 groupadd := fmt.Sprintf("groupadd --gid %s %s", 294 gid, groupName) 295 usermod := fmt.Sprintf("usermod --append --groups wheel --home %s --shell %s --uid %s --gid %s %s", 296 homeDir, shell, uid, gid, username) 297 298 session = podmanTest.Podman([]string{"create", "--log-driver", "k8s-file", "--name", "test", "--userns=keep-id", "--user", "root:root", fedoraToolbox, "sh", "-c", 299 fmt.Sprintf("%s; %s; %s; echo READY; sleep 1000", useradd, groupadd, usermod)}) 300 session.WaitWithDefaultTimeout() 301 Expect(session).Should(Exit(0)) 302 303 session = podmanTest.Podman([]string{"start", "test"}) 304 session.WaitWithDefaultTimeout() 305 Expect(session).Should(Exit(0)) 306 307 Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue()) 308 309 expectedUser := fmt.Sprintf("%s:x:%s:%s::%s:%s", 310 username, uid, gid, homeDir, shell) 311 312 session = podmanTest.Podman([]string{"exec", "test", "cat", "/etc/passwd"}) 313 session.WaitWithDefaultTimeout() 314 Expect(session).Should(Exit(0)) 315 Expect(session.OutputToString()).To(ContainSubstring(expectedUser)) 316 317 session = podmanTest.Podman([]string{"logs", "test"}) 318 session.WaitWithDefaultTimeout() 319 Expect(session).Should(Exit(0)) 320 Expect(session.OutputToString()).To(ContainSubstring("READY")) 321 }) 322 323 It("podman run --privileged --userns=keep-id --user root:root - entrypoint - (bind)mounting", func() { 324 var session *PodmanSessionIntegration 325 326 session = podmanTest.Podman([]string{"run", "--privileged", "--userns=keep-id", "--user", "root:root", ALPINE, 327 "mount", "-t", "tmpfs", "tmpfs", "/tmp"}) 328 session.WaitWithDefaultTimeout() 329 Expect(session).Should(Exit(0)) 330 331 session = podmanTest.Podman([]string{"run", "--privileged", "--userns=keep-id", "--user", "root:root", ALPINE, 332 "mount", "--rbind", "/tmp", "/var/tmp"}) 333 session.WaitWithDefaultTimeout() 334 Expect(session).Should(Exit(0)) 335 }) 336 337 It("podman create + start - with all needed switches for create - sleep as entry-point", func() { 338 var session *PodmanSessionIntegration 339 340 // These should be most of the switches that Toolbox uses to create a "toolbox" container 341 // https://github.com/containers/toolbox/blob/master/src/cmd/create.go 342 session = podmanTest.Podman([]string{"create", 343 "--log-driver", "k8s-file", 344 "--dns", "none", 345 "--hostname", "toolbox", 346 "--ipc", "host", 347 "--label", "com.github.containers.toolbox=true", 348 "--name", "test", 349 "--network", "host", 350 "--no-hosts", 351 "--pid", "host", 352 "--privileged", 353 "--security-opt", "label=disable", 354 "--ulimit", "host", 355 "--userns=keep-id", 356 "--user", "root:root", 357 fedoraToolbox, "sh", "-c", "echo READY; sleep 1000"}) 358 session.WaitWithDefaultTimeout() 359 Expect(session).Should(Exit(0)) 360 361 session = podmanTest.Podman([]string{"start", "test"}) 362 session.WaitWithDefaultTimeout() 363 Expect(session).Should(Exit(0)) 364 365 Expect(WaitContainerReady(podmanTest, "test", "READY", 5, 1)).To(BeTrue()) 366 367 session = podmanTest.Podman([]string{"logs", "test"}) 368 session.WaitWithDefaultTimeout() 369 Expect(session).Should(Exit(0)) 370 Expect(session.OutputToString()).To(ContainSubstring("READY")) 371 }) 372 373 It("podman run --userns=keep-id check $HOME", func() { 374 var session *PodmanSessionIntegration 375 376 currentUser, err := user.Current() 377 Expect(err).To(BeNil()) 378 379 session = podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:%s", currentUser.HomeDir, currentUser.HomeDir), "--userns=keep-id", fedoraToolbox, "sh", "-c", "echo $HOME"}) 380 session.WaitWithDefaultTimeout() 381 Expect(session).Should(Exit(0)) 382 Expect(session.OutputToString()).To(ContainSubstring(currentUser.HomeDir)) 383 384 if rootless.IsRootless() { 385 location := path.Dir(currentUser.HomeDir) 386 volumeArg := fmt.Sprintf("%s:%s", location, location) 387 session = podmanTest.Podman([]string{"run", 388 "--userns=keep-id", 389 "--volume", volumeArg, 390 fedoraToolbox, "sh", "-c", "echo $HOME"}) 391 session.WaitWithDefaultTimeout() 392 Expect(session).Should(Exit(0)) 393 Expect(session.OutputToString()).To(ContainSubstring(currentUser.HomeDir)) 394 } 395 }) 396 397 })