github.com/containers/podman/v2@v2.2.2-0.20210501105131-c1e07d070c4c/test/e2e/run_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "net" 7 "os" 8 "path/filepath" 9 "strconv" 10 "strings" 11 "syscall" 12 "time" 13 14 . "github.com/containers/podman/v2/test/utils" 15 "github.com/containers/storage/pkg/stringid" 16 "github.com/mrunalp/fileutils" 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 ) 20 21 var _ = Describe("Podman run", func() { 22 var ( 23 tempdir string 24 err error 25 podmanTest *PodmanTestIntegration 26 ) 27 28 BeforeEach(func() { 29 tempdir, err = CreateTempDirInTempDir() 30 if err != nil { 31 os.Exit(1) 32 } 33 podmanTest = PodmanTestCreate(tempdir) 34 podmanTest.Setup() 35 podmanTest.SeedImages() 36 }) 37 38 AfterEach(func() { 39 podmanTest.Cleanup() 40 f := CurrentGinkgoTestDescription() 41 processTestResult(f) 42 }) 43 44 It("podman run a container based on local image", func() { 45 session := podmanTest.Podman([]string{"run", ALPINE, "ls"}) 46 session.WaitWithDefaultTimeout() 47 Expect(session.ExitCode()).To(Equal(0)) 48 }) 49 50 It("podman run a container based on a complex local image name", func() { 51 imageName := strings.TrimPrefix(nginx, "quay.io/") 52 session := podmanTest.Podman([]string{"run", imageName, "ls"}) 53 session.WaitWithDefaultTimeout() 54 Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) 55 Expect(session.ExitCode()).To(Equal(0)) 56 }) 57 58 It("podman run --signature-policy", func() { 59 SkipIfRemote("SigPolicy not handled by remote") 60 session := podmanTest.Podman([]string{"run", "--pull=always", "--signature-policy", "/no/such/file", ALPINE}) 61 session.WaitWithDefaultTimeout() 62 Expect(session.ExitCode()).To(Not(Equal(0))) 63 64 session = podmanTest.Podman([]string{"run", "--pull=always", "--signature-policy", "/etc/containers/policy.json", ALPINE}) 65 session.WaitWithDefaultTimeout() 66 Expect(session.ExitCode()).To(Equal(0)) 67 }) 68 69 It("podman run --rm with --restart", func() { 70 session := podmanTest.Podman([]string{"run", "--rm", "--restart", "", ALPINE}) 71 session.WaitWithDefaultTimeout() 72 Expect(session.ExitCode()).To(Equal(0)) 73 74 session = podmanTest.Podman([]string{"run", "--rm", "--restart", "no", ALPINE}) 75 session.WaitWithDefaultTimeout() 76 Expect(session.ExitCode()).To(Equal(0)) 77 78 session = podmanTest.Podman([]string{"run", "--rm", "--restart", "on-failure", ALPINE}) 79 session.WaitWithDefaultTimeout() 80 Expect(session.ExitCode()).To(Equal(0)) 81 82 session = podmanTest.Podman([]string{"run", "--rm", "--restart", "always", ALPINE}) 83 session.WaitWithDefaultTimeout() 84 Expect(session.ExitCode()).To(Not(Equal(0))) 85 86 session = podmanTest.Podman([]string{"run", "--rm", "--restart", "unless-stopped", ALPINE}) 87 session.WaitWithDefaultTimeout() 88 Expect(session.ExitCode()).To(Not(Equal(0))) 89 }) 90 91 It("podman run a container based on on a short name with localhost", func() { 92 tag := podmanTest.Podman([]string{"tag", nginx, "localhost/libpod/alpine_nginx:latest"}) 93 tag.WaitWithDefaultTimeout() 94 95 rmi := podmanTest.Podman([]string{"rmi", nginx}) 96 rmi.WaitWithDefaultTimeout() 97 98 session := podmanTest.Podman([]string{"run", "libpod/alpine_nginx:latest", "ls"}) 99 session.WaitWithDefaultTimeout() 100 Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) 101 Expect(session.ExitCode()).To(Equal(0)) 102 }) 103 104 It("podman container run a container based on on a short name with localhost", func() { 105 tag := podmanTest.Podman([]string{"image", "tag", nginx, "localhost/libpod/alpine_nginx:latest"}) 106 tag.WaitWithDefaultTimeout() 107 108 rmi := podmanTest.Podman([]string{"image", "rm", nginx}) 109 rmi.WaitWithDefaultTimeout() 110 111 session := podmanTest.Podman([]string{"container", "run", "libpod/alpine_nginx:latest", "ls"}) 112 session.WaitWithDefaultTimeout() 113 Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) 114 Expect(session.ExitCode()).To(Equal(0)) 115 }) 116 117 It("podman run a container based on local image with short options", func() { 118 session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "ls"}) 119 session.WaitWithDefaultTimeout() 120 Expect(session.ExitCode()).To(Equal(0)) 121 }) 122 123 It("podman run a container based on local image with short options and args", func() { 124 // regression test for #714 125 session := podmanTest.Podman([]string{"run", ALPINE, "find", "/etc", "-name", "hosts"}) 126 session.WaitWithDefaultTimeout() 127 Expect(session.ExitCode()).To(Equal(0)) 128 match, _ := session.GrepString("/etc/hosts") 129 Expect(match).Should(BeTrue()) 130 }) 131 132 It("podman create pod with name in /etc/hosts", func() { 133 name := "test_container" 134 hostname := "test_hostname" 135 session := podmanTest.Podman([]string{"run", "-ti", "--rm", "--name", name, "--hostname", hostname, ALPINE, "cat", "/etc/hosts"}) 136 session.WaitWithDefaultTimeout() 137 Expect(session.ExitCode()).To(Equal(0)) 138 match, _ := session.GrepString(name) 139 Expect(match).Should(BeTrue()) 140 match, _ = session.GrepString(hostname) 141 Expect(match).Should(BeTrue()) 142 }) 143 144 It("podman run a container based on remote image", func() { 145 session := podmanTest.Podman([]string{"run", "-dt", BB_GLIBC, "ls"}) 146 session.WaitWithDefaultTimeout() 147 Expect(session.ExitCode()).To(Equal(0)) 148 }) 149 150 It("podman run a container with a --rootfs", func() { 151 rootfs := filepath.Join(tempdir, "rootfs") 152 uls := filepath.Join("/", "usr", "local", "share") 153 uniqueString := stringid.GenerateNonCryptoID() 154 testFilePath := filepath.Join(uls, uniqueString) 155 tarball := filepath.Join(tempdir, "rootfs.tar") 156 157 err := os.Mkdir(rootfs, 0770) 158 Expect(err).Should(BeNil()) 159 160 // Change image in predictable way to validate export 161 csession := podmanTest.Podman([]string{"run", "--name", uniqueString, ALPINE, 162 "/bin/sh", "-c", fmt.Sprintf("echo %s > %s", uniqueString, testFilePath)}) 163 csession.WaitWithDefaultTimeout() 164 Expect(csession.ExitCode()).To(Equal(0)) 165 166 // Export from working container image guarantees working root 167 esession := podmanTest.Podman([]string{"export", "--output", tarball, uniqueString}) 168 esession.WaitWithDefaultTimeout() 169 Expect(esession.ExitCode()).To(Equal(0)) 170 Expect(tarball).Should(BeARegularFile()) 171 172 // N/B: This will loose any extended attributes like SELinux types 173 fmt.Fprintf(os.Stderr, "Extracting container root tarball\n") 174 tarsession := SystemExec("tar", []string{"xf", tarball, "-C", rootfs}) 175 Expect(tarsession.ExitCode()).To(Equal(0)) 176 Expect(filepath.Join(rootfs, uls)).Should(BeADirectory()) 177 178 // Other tests confirm SELinux types, just confirm --rootfs is working. 179 session := podmanTest.Podman([]string{"run", "-i", "--security-opt", "label=disable", 180 "--rootfs", rootfs, "cat", testFilePath}) 181 session.WaitWithDefaultTimeout() 182 Expect(session.ExitCode()).To(Equal(0)) 183 184 // Validate changes made in original container and export 185 stdoutLines := session.OutputToStringArray() 186 Expect(stdoutLines).Should(HaveLen(1)) 187 Expect(stdoutLines[0]).Should(Equal(uniqueString)) 188 }) 189 190 It("podman run a container with --init", func() { 191 session := podmanTest.Podman([]string{"run", "--name", "test", "--init", ALPINE, "ls"}) 192 session.WaitWithDefaultTimeout() 193 Expect(session.ExitCode()).To(Equal(0)) 194 result := podmanTest.Podman([]string{"inspect", "test"}) 195 result.WaitWithDefaultTimeout() 196 Expect(result.ExitCode()).To(Equal(0)) 197 conData := result.InspectContainerToJSON() 198 Expect(conData[0].Path).To(Equal("/dev/init")) 199 Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("TRUE")) 200 }) 201 202 It("podman run a container with --init and --init-path", func() { 203 session := podmanTest.Podman([]string{"run", "--name", "test", "--init", "--init-path", "/usr/libexec/podman/catatonit", ALPINE, "ls"}) 204 session.WaitWithDefaultTimeout() 205 Expect(session.ExitCode()).To(Equal(0)) 206 result := podmanTest.Podman([]string{"inspect", "test"}) 207 result.WaitWithDefaultTimeout() 208 Expect(result.ExitCode()).To(Equal(0)) 209 conData := result.InspectContainerToJSON() 210 Expect(conData[0].Path).To(Equal("/dev/init")) 211 Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("TRUE")) 212 }) 213 214 It("podman run a container without --init", func() { 215 session := podmanTest.Podman([]string{"run", "--name", "test", ALPINE, "ls"}) 216 session.WaitWithDefaultTimeout() 217 Expect(session.ExitCode()).To(Equal(0)) 218 result := podmanTest.Podman([]string{"inspect", "test"}) 219 result.WaitWithDefaultTimeout() 220 Expect(result.ExitCode()).To(Equal(0)) 221 conData := result.InspectContainerToJSON() 222 Expect(conData[0].Path).To(Equal("ls")) 223 Expect(conData[0].Config.Annotations["io.podman.annotations.init"]).To(Equal("FALSE")) 224 }) 225 226 forbidGetCWDSeccompProfile := func() string { 227 in := []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`) 228 jsonFile, err := podmanTest.CreateSeccompJson(in) 229 if err != nil { 230 fmt.Println(err) 231 Skip("Failed to prepare seccomp.json for test.") 232 } 233 return jsonFile 234 } 235 236 It("podman run seccomp test", func() { 237 session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"}) 238 session.WaitWithDefaultTimeout() 239 Expect(session).To(ExitWithError()) 240 match, _ := session.GrepString("Operation not permitted") 241 Expect(match).Should(BeTrue()) 242 }) 243 244 It("podman run seccomp test --privileged", func() { 245 session := podmanTest.Podman([]string{"run", "-it", "--privileged", "--security-opt", strings.Join([]string{"seccomp=", forbidGetCWDSeccompProfile()}, ""), ALPINE, "pwd"}) 246 session.WaitWithDefaultTimeout() 247 Expect(session).To(ExitWithError()) 248 match, _ := session.GrepString("Operation not permitted") 249 Expect(match).Should(BeTrue()) 250 }) 251 252 It("podman run seccomp test --privileged no profile should be unconfined", func() { 253 session := podmanTest.Podman([]string{"run", "-it", "--privileged", ALPINE, "grep", "Seccomp", "/proc/self/status"}) 254 session.WaitWithDefaultTimeout() 255 Expect(session.OutputToString()).To(ContainSubstring("0")) 256 Expect(session.ExitCode()).To(Equal(0)) 257 }) 258 259 It("podman run seccomp test no profile should be default", func() { 260 session := podmanTest.Podman([]string{"run", "-it", ALPINE, "grep", "Seccomp", "/proc/self/status"}) 261 session.WaitWithDefaultTimeout() 262 Expect(session.OutputToString()).To(ContainSubstring("2")) 263 Expect(session.ExitCode()).To(Equal(0)) 264 }) 265 266 It("podman run capabilities test", func() { 267 session := podmanTest.Podman([]string{"run", "--rm", "--cap-add", "all", ALPINE, "cat", "/proc/self/status"}) 268 session.WaitWithDefaultTimeout() 269 Expect(session.ExitCode()).To(Equal(0)) 270 271 session = podmanTest.Podman([]string{"run", "--rm", "--cap-add", "sys_admin", ALPINE, "cat", "/proc/self/status"}) 272 session.WaitWithDefaultTimeout() 273 Expect(session.ExitCode()).To(Equal(0)) 274 275 session = podmanTest.Podman([]string{"run", "--rm", "--cap-drop", "all", ALPINE, "cat", "/proc/self/status"}) 276 session.WaitWithDefaultTimeout() 277 Expect(session.ExitCode()).To(Equal(0)) 278 279 session = podmanTest.Podman([]string{"run", "--rm", "--cap-drop", "setuid", ALPINE, "cat", "/proc/self/status"}) 280 session.WaitWithDefaultTimeout() 281 Expect(session.ExitCode()).To(Equal(0)) 282 }) 283 284 It("podman run user capabilities test", func() { 285 // We need to ignore the containers.conf on the test distribution for this test 286 os.Setenv("CONTAINERS_CONF", "/dev/null") 287 session := podmanTest.Podman([]string{"run", "--rm", "--user", "bin", ALPINE, "grep", "CapBnd", "/proc/self/status"}) 288 session.WaitWithDefaultTimeout() 289 Expect(session.ExitCode()).To(Equal(0)) 290 Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) 291 292 session = podmanTest.Podman([]string{"run", "--rm", "--user", "bin", ALPINE, "grep", "CapEff", "/proc/self/status"}) 293 session.WaitWithDefaultTimeout() 294 Expect(session.ExitCode()).To(Equal(0)) 295 Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) 296 297 session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapBnd", "/proc/self/status"}) 298 session.WaitWithDefaultTimeout() 299 Expect(session.ExitCode()).To(Equal(0)) 300 Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) 301 302 session = podmanTest.Podman([]string{"run", "--rm", "--user", "root", ALPINE, "grep", "CapEff", "/proc/self/status"}) 303 session.WaitWithDefaultTimeout() 304 Expect(session.ExitCode()).To(Equal(0)) 305 Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) 306 307 session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "grep", "CapBnd", "/proc/self/status"}) 308 session.WaitWithDefaultTimeout() 309 Expect(session.ExitCode()).To(Equal(0)) 310 Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) 311 312 session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "grep", "CapEff", "/proc/self/status"}) 313 session.WaitWithDefaultTimeout() 314 Expect(session.ExitCode()).To(Equal(0)) 315 Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) 316 317 session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"}) 318 session.WaitWithDefaultTimeout() 319 Expect(session.ExitCode()).To(Equal(0)) 320 Expect(session.OutputToString()).To(ContainSubstring("0000000000000002")) 321 322 session = podmanTest.Podman([]string{"run", "--user=1000:1000", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"}) 323 session.WaitWithDefaultTimeout() 324 Expect(session.ExitCode()).To(Equal(0)) 325 Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) 326 327 session = podmanTest.Podman([]string{"run", "--user=0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"}) 328 session.WaitWithDefaultTimeout() 329 Expect(session.ExitCode()).To(Equal(0)) 330 Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) 331 332 session = podmanTest.Podman([]string{"run", "--user=0:0", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"}) 333 session.WaitWithDefaultTimeout() 334 Expect(session.ExitCode()).To(Equal(0)) 335 Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) 336 337 if os.Geteuid() > 0 { 338 if os.Getenv("SKIP_USERNS") != "" { 339 Skip("Skip userns tests.") 340 } 341 if _, err := os.Stat("/proc/self/uid_map"); err != nil { 342 Skip("User namespaces not supported.") 343 } 344 session = podmanTest.Podman([]string{"run", "--userns=keep-id", "--cap-add=DAC_OVERRIDE", "--rm", ALPINE, "grep", "CapAmb", "/proc/self/status"}) 345 session.WaitWithDefaultTimeout() 346 Expect(session.ExitCode()).To(Equal(0)) 347 Expect(session.OutputToString()).To(ContainSubstring("0000000000000002")) 348 } 349 }) 350 351 It("podman run user capabilities test with image", func() { 352 // We need to ignore the containers.conf on the test distribution for this test 353 os.Setenv("CONTAINERS_CONF", "/dev/null") 354 dockerfile := `FROM busybox 355 USER bin` 356 podmanTest.BuildImage(dockerfile, "test", "false") 357 session := podmanTest.Podman([]string{"run", "--rm", "--user", "bin", "test", "grep", "CapBnd", "/proc/self/status"}) 358 session.WaitWithDefaultTimeout() 359 Expect(session.ExitCode()).To(Equal(0)) 360 Expect(session.OutputToString()).To(ContainSubstring("00000000a80425fb")) 361 362 session = podmanTest.Podman([]string{"run", "--rm", "--user", "bin", "test", "grep", "CapEff", "/proc/self/status"}) 363 session.WaitWithDefaultTimeout() 364 Expect(session.ExitCode()).To(Equal(0)) 365 Expect(session.OutputToString()).To(ContainSubstring("0000000000000000")) 366 }) 367 368 It("podman run limits test", func() { 369 SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") 370 371 if !isRootless() { 372 session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "rtprio=99", "--cap-add=sys_nice", fedoraMinimal, "cat", "/proc/self/sched"}) 373 session.WaitWithDefaultTimeout() 374 Expect(session.ExitCode()).To(Equal(0)) 375 } 376 377 session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=2048:2048", fedoraMinimal, "ulimit", "-n"}) 378 session.WaitWithDefaultTimeout() 379 Expect(session.ExitCode()).To(Equal(0)) 380 Expect(session.OutputToString()).To(ContainSubstring("2048")) 381 382 session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=1024:1028", fedoraMinimal, "ulimit", "-n"}) 383 session.WaitWithDefaultTimeout() 384 Expect(session.ExitCode()).To(Equal(0)) 385 Expect(session.OutputToString()).To(ContainSubstring("1024")) 386 387 if !CGROUPSV2 { 388 // --oom-kill-disable not supported on cgroups v2. 389 session = podmanTest.Podman([]string{"run", "--rm", "--oom-kill-disable=true", fedoraMinimal, "echo", "memory-hog"}) 390 session.WaitWithDefaultTimeout() 391 Expect(session.ExitCode()).To(Equal(0)) 392 } 393 394 session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=111", fedoraMinimal, "cat", "/proc/self/oom_score_adj"}) 395 session.WaitWithDefaultTimeout() 396 Expect(session.ExitCode()).To(Equal(0)) 397 Expect(session.OutputToString()).To(Equal("111")) 398 }) 399 400 It("podman run limits host test", func() { 401 SkipIfRemote("This can only be used for local tests") 402 403 var l syscall.Rlimit 404 405 err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l) 406 Expect(err).To(BeNil()) 407 408 session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "host", fedoraMinimal, "ulimit", "-Hn"}) 409 session.WaitWithDefaultTimeout() 410 Expect(session.ExitCode()).To(Equal(0)) 411 412 ulimitCtrStr := strings.TrimSpace(session.OutputToString()) 413 ulimitCtr, err := strconv.ParseUint(ulimitCtrStr, 10, 0) 414 Expect(err).To(BeNil()) 415 416 Expect(ulimitCtr).Should(BeNumerically(">=", l.Max)) 417 }) 418 419 It("podman run with cidfile", func() { 420 session := podmanTest.Podman([]string{"run", "--cidfile", tempdir + "cidfile", ALPINE, "ls"}) 421 session.WaitWithDefaultTimeout() 422 Expect(session.ExitCode()).To(Equal(0)) 423 err := os.Remove(tempdir + "cidfile") 424 Expect(err).To(BeNil()) 425 }) 426 427 It("podman run sysctl test", func() { 428 SkipIfRootless("Network sysctls are not available root rootless") 429 session := podmanTest.Podman([]string{"run", "--rm", "--sysctl", "net.core.somaxconn=65535", ALPINE, "sysctl", "net.core.somaxconn"}) 430 session.WaitWithDefaultTimeout() 431 Expect(session.ExitCode()).To(Equal(0)) 432 Expect(session.OutputToString()).To(ContainSubstring("net.core.somaxconn = 65535")) 433 434 // network sysctls should fail if --net=host is set 435 session = podmanTest.Podman([]string{"run", "--net", "host", "--rm", "--sysctl", "net.core.somaxconn=65535", ALPINE, "sysctl", "net.core.somaxconn"}) 436 session.WaitWithDefaultTimeout() 437 Expect(session.ExitCode()).To(Equal(125)) 438 }) 439 440 It("podman run blkio-weight test", func() { 441 SkipIfRootless("FIXME: This is blowing up because of no /sys/fs/cgroup/user.slice/user-14467.slice/user@14467.service/cgroup.subtree_control file") 442 SkipIfRootlessCgroupsV1("Setting blkio-weight not supported on cgroupv1 for rootless users") 443 if !CGROUPSV2 { 444 if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) { 445 Skip("Kernel does not support blkio.weight") 446 } 447 } 448 449 if CGROUPSV2 { 450 // convert linearly from [10-1000] to [1-10000] 451 session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.bfq.weight"}) 452 session.WaitWithDefaultTimeout() 453 Expect(session.ExitCode()).To(Equal(0)) 454 Expect(session.OutputToString()).To(ContainSubstring("51")) 455 } else { 456 session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"}) 457 session.WaitWithDefaultTimeout() 458 Expect(session.ExitCode()).To(Equal(0)) 459 Expect(session.OutputToString()).To(ContainSubstring("15")) 460 } 461 }) 462 463 It("podman run device-read-bps test", func() { 464 SkipIfRootless("FIXME: Missing /sys/fs/cgroup/user.slice/user-14467.slice/user@14467.service/cgroup.subtree_control") 465 SkipIfRootlessCgroupsV1("Setting device-read-bps not supported on cgroupv1 for rootless users") 466 467 var session *PodmanSessionIntegration 468 469 if CGROUPSV2 { 470 session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) 471 } else { 472 session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"}) 473 } 474 475 session.WaitWithDefaultTimeout() 476 Expect(session.ExitCode()).To(Equal(0)) 477 if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 478 Expect(session.OutputToString()).To(ContainSubstring("1048576")) 479 } 480 }) 481 482 It("podman run device-write-bps test", func() { 483 SkipIfRootless("FIXME /sys/fs/cgroup/user.slice/user-14467.slice/user@14467.service/cgroup.subtree_control does not exist") 484 SkipIfRootlessCgroupsV1("Setting device-write-bps not supported on cgroupv1 for rootless users") 485 486 var session *PodmanSessionIntegration 487 488 if CGROUPSV2 { 489 session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) 490 } else { 491 session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"}) 492 } 493 session.WaitWithDefaultTimeout() 494 Expect(session.ExitCode()).To(Equal(0)) 495 if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 496 Expect(session.OutputToString()).To(ContainSubstring("1048576")) 497 } 498 }) 499 500 It("podman run device-read-iops test", func() { 501 SkipIfRootless("FIXME /sys/fs/cgroup/user.slice/user-14467.slice/user@14467.service/cgroup.subtree_control does not exist") 502 SkipIfRootlessCgroupsV1("Setting device-read-iops not supported on cgroupv1 for rootless users") 503 var session *PodmanSessionIntegration 504 505 if CGROUPSV2 { 506 session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) 507 } else { 508 session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"}) 509 } 510 511 session.WaitWithDefaultTimeout() 512 Expect(session.ExitCode()).To(Equal(0)) 513 if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 514 Expect(session.OutputToString()).To(ContainSubstring("100")) 515 } 516 }) 517 518 It("podman run device-write-iops test", func() { 519 SkipIfRootless("FIXME /sys/fs/cgroup/user.slice/user-14467.slice/user@14467.service/cgroup.subtree_control does not exist") 520 SkipIfRootlessCgroupsV1("Setting device-write-iops not supported on cgroupv1 for rootless users") 521 var session *PodmanSessionIntegration 522 523 if CGROUPSV2 { 524 session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "sh", "-c", "cat /sys/fs/cgroup/$(sed -e 's|0::||' < /proc/self/cgroup)/io.max"}) 525 } else { 526 session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"}) 527 } 528 529 session.WaitWithDefaultTimeout() 530 Expect(session.ExitCode()).To(Equal(0)) 531 if !CGROUPSV2 { // TODO: Test Simplification. For now, we only care about exit(0) w/ cgroupsv2 532 Expect(session.OutputToString()).To(ContainSubstring("100")) 533 } 534 }) 535 536 It("podman run notify_socket", func() { 537 SkipIfRemote("This can only be used for local tests") 538 539 host := GetHostDistributionInfo() 540 if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" { 541 Skip("this test requires a working runc") 542 } 543 sock := filepath.Join(podmanTest.TempDir, "notify") 544 addr := net.UnixAddr{ 545 Name: sock, 546 Net: "unixgram", 547 } 548 socket, err := net.ListenUnixgram("unixgram", &addr) 549 Expect(err).To(BeNil()) 550 defer os.Remove(sock) 551 defer socket.Close() 552 553 os.Setenv("NOTIFY_SOCKET", sock) 554 defer os.Unsetenv("NOTIFY_SOCKET") 555 556 session := podmanTest.Podman([]string{"run", ALPINE, "printenv", "NOTIFY_SOCKET"}) 557 session.WaitWithDefaultTimeout() 558 Expect(session.ExitCode()).To(Equal(0)) 559 Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 0)) 560 }) 561 562 It("podman run log-opt", func() { 563 log := filepath.Join(podmanTest.TempDir, "/container.log") 564 session := podmanTest.Podman([]string{"run", "--rm", "--log-opt", fmt.Sprintf("path=%s", log), ALPINE, "ls"}) 565 session.WaitWithDefaultTimeout() 566 Expect(session.ExitCode()).To(Equal(0)) 567 _, err := os.Stat(log) 568 Expect(err).To(BeNil()) 569 _ = os.Remove(log) 570 }) 571 572 It("podman run tagged image", func() { 573 podmanTest.AddImageToRWStore(BB) 574 tag := podmanTest.Podman([]string{"tag", BB, "bb"}) 575 tag.WaitWithDefaultTimeout() 576 Expect(tag.ExitCode()).To(Equal(0)) 577 578 session := podmanTest.Podman([]string{"run", "--rm", "bb", "ls"}) 579 session.WaitWithDefaultTimeout() 580 Expect(session.ExitCode()).To(Equal(0)) 581 }) 582 583 It("podman test hooks", func() { 584 hcheck := "/run/hookscheck" 585 hooksDir := tempdir + "/hooks" 586 os.Mkdir(hooksDir, 0755) 587 fileutils.CopyFile("hooks/hooks.json", hooksDir) 588 os.Setenv("HOOK_OPTION", fmt.Sprintf("--hooks-dir=%s", hooksDir)) 589 os.Remove(hcheck) 590 session := podmanTest.Podman([]string{"run", ALPINE, "ls"}) 591 session.Wait(10) 592 os.Unsetenv("HOOK_OPTION") 593 Expect(session.ExitCode()).To(Equal(0)) 594 }) 595 596 It("podman run with secrets", func() { 597 SkipIfRemote("--default-mount-file option is not supported in podman-remote") 598 containersDir := filepath.Join(podmanTest.TempDir, "containers") 599 err := os.MkdirAll(containersDir, 0755) 600 Expect(err).To(BeNil()) 601 602 secretsDir := filepath.Join(podmanTest.TempDir, "rhel", "secrets") 603 err = os.MkdirAll(secretsDir, 0755) 604 Expect(err).To(BeNil()) 605 606 mountsFile := filepath.Join(containersDir, "mounts.conf") 607 mountString := secretsDir + ":/run/secrets" 608 err = ioutil.WriteFile(mountsFile, []byte(mountString), 0755) 609 Expect(err).To(BeNil()) 610 611 secretsFile := filepath.Join(secretsDir, "test.txt") 612 secretsString := "Testing secrets mount. I am mounted!" 613 err = ioutil.WriteFile(secretsFile, []byte(secretsString), 0755) 614 Expect(err).To(BeNil()) 615 616 targetDir := tempdir + "/symlink/target" 617 err = os.MkdirAll(targetDir, 0755) 618 Expect(err).To(BeNil()) 619 keyFile := filepath.Join(targetDir, "key.pem") 620 err = ioutil.WriteFile(keyFile, []byte(mountString), 0755) 621 Expect(err).To(BeNil()) 622 execSession := SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")}) 623 Expect(execSession.ExitCode()).To(Equal(0)) 624 625 session := podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "cat", "/run/secrets/test.txt"}) 626 session.WaitWithDefaultTimeout() 627 Expect(session.ExitCode()).To(Equal(0)) 628 Expect(session.OutputToString()).To(Equal(secretsString)) 629 630 session = podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "ls", "/run/secrets/mysymlink"}) 631 session.WaitWithDefaultTimeout() 632 Expect(session.ExitCode()).To(Equal(0)) 633 Expect(session.OutputToString()).To(ContainSubstring("key.pem")) 634 }) 635 636 It("podman run with FIPS mode secrets", func() { 637 SkipIfRootless("rootless can not manipulate system-fips file") 638 fipsFile := "/etc/system-fips" 639 err = ioutil.WriteFile(fipsFile, []byte{}, 0755) 640 Expect(err).To(BeNil()) 641 642 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "ls", "/run/secrets"}) 643 session.WaitWithDefaultTimeout() 644 Expect(session.ExitCode()).To(Equal(0)) 645 Expect(session.OutputToString()).To(ContainSubstring("system-fips")) 646 647 err = os.Remove(fipsFile) 648 Expect(err).To(BeNil()) 649 }) 650 651 It("podman run without group-add", func() { 652 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"}) 653 session.WaitWithDefaultTimeout() 654 Expect(session.ExitCode()).To(Equal(0)) 655 Expect(session.LineInOutputContains("27(video),777,65533(nogroup)")).To(BeFalse()) 656 }) 657 658 It("podman run with group-add", func() { 659 session := podmanTest.Podman([]string{"run", "--rm", "--group-add=audio", "--group-add=nogroup", "--group-add=777", ALPINE, "id"}) 660 session.WaitWithDefaultTimeout() 661 Expect(session.ExitCode()).To(Equal(0)) 662 Expect(session.LineInOutputContains("777,65533(nogroup)")).To(BeTrue()) 663 }) 664 665 It("podman run with user (default)", func() { 666 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"}) 667 session.WaitWithDefaultTimeout() 668 Expect(session.ExitCode()).To(Equal(0)) 669 Expect(session.LineInOutputContains("uid=0(root) gid=0(root)")).To(BeTrue()) 670 }) 671 672 It("podman run with user (integer, not in /etc/passwd)", func() { 673 session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "id"}) 674 session.WaitWithDefaultTimeout() 675 Expect(session.ExitCode()).To(Equal(0)) 676 Expect(session.OutputToString()).To(Equal("uid=1234(1234) gid=0(root)")) 677 }) 678 679 It("podman run with user (integer, in /etc/passwd)", func() { 680 session := podmanTest.Podman([]string{"run", "--rm", "--user=8", ALPINE, "id"}) 681 session.WaitWithDefaultTimeout() 682 Expect(session.ExitCode()).To(Equal(0)) 683 Expect(session.LineInOutputContains("uid=8(mail) gid=12(mail)")).To(BeTrue()) 684 }) 685 686 It("podman run with user (username)", func() { 687 session := podmanTest.Podman([]string{"run", "--rm", "--user=mail", ALPINE, "id"}) 688 session.WaitWithDefaultTimeout() 689 Expect(session.ExitCode()).To(Equal(0)) 690 Expect(session.LineInOutputContains("uid=8(mail) gid=12(mail)")).To(BeTrue()) 691 }) 692 693 It("podman run with user:group (username:integer)", func() { 694 session := podmanTest.Podman([]string{"run", "--rm", "--user=mail:21", ALPINE, "id"}) 695 session.WaitWithDefaultTimeout() 696 Expect(session.ExitCode()).To(Equal(0)) 697 Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp)")) 698 }) 699 700 It("podman run with user:group (integer:groupname)", func() { 701 session := podmanTest.Podman([]string{"run", "--rm", "--user=8:ftp", ALPINE, "id"}) 702 session.WaitWithDefaultTimeout() 703 Expect(session.ExitCode()).To(Equal(0)) 704 Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp)")) 705 }) 706 707 It("podman run with user, verify caps dropped", func() { 708 session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "grep", "CapEff", "/proc/self/status"}) 709 session.WaitWithDefaultTimeout() 710 Expect(session.ExitCode()).To(Equal(0)) 711 capEff := strings.Split(session.OutputToString(), " ") 712 Expect("0000000000000000").To(Equal(capEff[1])) 713 }) 714 715 It("podman run with attach stdin outputs container ID", func() { 716 session := podmanTest.Podman([]string{"run", "--attach", "stdin", ALPINE, "printenv"}) 717 session.WaitWithDefaultTimeout() 718 Expect(session.ExitCode()).To(Equal(0)) 719 ps := podmanTest.Podman([]string{"ps", "-aq", "--no-trunc"}) 720 ps.WaitWithDefaultTimeout() 721 Expect(ps.ExitCode()).To(Equal(0)) 722 Expect(ps.LineInOutputContains(session.OutputToString())).To(BeTrue()) 723 }) 724 725 It("podman run with attach stdout does not print stderr", func() { 726 session := podmanTest.Podman([]string{"run", "--rm", "--attach", "stdout", ALPINE, "ls", "/doesnotexist"}) 727 session.WaitWithDefaultTimeout() 728 Expect(session.OutputToString()).To(Equal("")) 729 }) 730 731 It("podman run with attach stderr does not print stdout", func() { 732 session := podmanTest.Podman([]string{"run", "--rm", "--attach", "stderr", ALPINE, "ls", "/"}) 733 session.WaitWithDefaultTimeout() 734 Expect(session.ExitCode()).To(Equal(0)) 735 Expect(session.OutputToString()).To(Equal("")) 736 }) 737 738 It("podman run attach nonsense errors", func() { 739 session := podmanTest.Podman([]string{"run", "--rm", "--attach", "asdfasdf", ALPINE, "ls", "/"}) 740 session.WaitWithDefaultTimeout() 741 Expect(session.ExitCode()).To(Equal(125)) 742 }) 743 744 It("podman run exit code on failure to exec", func() { 745 session := podmanTest.Podman([]string{"run", ALPINE, "/etc"}) 746 session.WaitWithDefaultTimeout() 747 Expect(session.ExitCode()).To(Equal(126)) 748 }) 749 750 It("podman run error on exec", func() { 751 session := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 100"}) 752 session.WaitWithDefaultTimeout() 753 Expect(session.ExitCode()).To(Equal(100)) 754 }) 755 756 It("podman run with built-in volume image", func() { 757 session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"}) 758 session.WaitWithDefaultTimeout() 759 Expect(session.ExitCode()).To(Equal(0)) 760 761 dockerfile := `FROM busybox 762 RUN mkdir -p /myvol/data && chown -R mail.0 /myvol 763 VOLUME ["/myvol/data"] 764 USER mail` 765 766 podmanTest.BuildImage(dockerfile, "test", "false") 767 session = podmanTest.Podman([]string{"run", "--rm", "test", "ls", "-al", "/myvol/data"}) 768 session.WaitWithDefaultTimeout() 769 Expect(session.ExitCode()).To(Equal(0)) 770 Expect(session.OutputToString()).To(ContainSubstring("mail root")) 771 }) 772 773 It("podman run --volumes-from flag", func() { 774 vol := filepath.Join(podmanTest.TempDir, "vol-test") 775 err := os.MkdirAll(vol, 0755) 776 Expect(err).To(BeNil()) 777 778 filename := "test.txt" 779 volFile := filepath.Join(vol, filename) 780 data := "Testing --volumes-from!!!" 781 err = ioutil.WriteFile(volFile, []byte(data), 0755) 782 Expect(err).To(BeNil()) 783 mountpoint := "/myvol/" 784 785 session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename}) 786 session.WaitWithDefaultTimeout() 787 Expect(session.ExitCode()).To(Equal(0)) 788 ctrID := session.OutputToString() 789 790 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "cat", mountpoint + filename}) 791 session.WaitWithDefaultTimeout() 792 Expect(session.ExitCode()).To(Equal(0)) 793 Expect(session.OutputToString()).To(Equal(data)) 794 795 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "sh", "-c", "echo test >> " + mountpoint + filename}) 796 session.WaitWithDefaultTimeout() 797 Expect(session.ExitCode()).To(Equal(0)) 798 799 session = podmanTest.Podman([]string{"start", "--attach", ctrID}) 800 session.WaitWithDefaultTimeout() 801 Expect(session.ExitCode()).To(Equal(0)) 802 Expect(session.OutputToString()).To(Equal(data + "test")) 803 }) 804 805 It("podman run --volumes-from flag options", func() { 806 vol := filepath.Join(podmanTest.TempDir, "vol-test") 807 err := os.MkdirAll(vol, 0755) 808 Expect(err).To(BeNil()) 809 810 filename := "test.txt" 811 volFile := filepath.Join(vol, filename) 812 data := "Testing --volumes-from!!!" 813 err = ioutil.WriteFile(volFile, []byte(data), 0755) 814 Expect(err).To(BeNil()) 815 mountpoint := "/myvol/" 816 817 session := podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint, ALPINE, "cat", mountpoint + filename}) 818 session.WaitWithDefaultTimeout() 819 Expect(session.ExitCode()).To(Equal(0)) 820 ctrID := session.OutputToString() 821 822 // check that the read only option works 823 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro", ALPINE, "touch", mountpoint + "abc.txt"}) 824 session.WaitWithDefaultTimeout() 825 Expect(session.ExitCode()).To(Equal(1)) 826 Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system")) 827 828 // check that both z and ro options work 829 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,z", ALPINE, "cat", mountpoint + filename}) 830 session.WaitWithDefaultTimeout() 831 Expect(session.ExitCode()).To(Equal(0)) 832 Expect(session.OutputToString()).To(Equal(data)) 833 834 // check that multiple ro/rw are not working 835 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":ro,rw", ALPINE, "cat", mountpoint + filename}) 836 session.WaitWithDefaultTimeout() 837 Expect(session.ExitCode()).To(Equal(125)) 838 Expect(session.ErrorToString()).To(ContainSubstring("cannot set ro or rw options more than once")) 839 840 // check that multiple z options are not working 841 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z,z,ro", ALPINE, "cat", mountpoint + filename}) 842 session.WaitWithDefaultTimeout() 843 Expect(session.ExitCode()).To(Equal(125)) 844 Expect(session.ErrorToString()).To(ContainSubstring("cannot set :z more than once in mount options")) 845 846 // create new read only volume 847 session = podmanTest.Podman([]string{"create", "--volume", vol + ":" + mountpoint + ":ro", ALPINE, "cat", mountpoint + filename}) 848 session.WaitWithDefaultTimeout() 849 Expect(session.ExitCode()).To(Equal(0)) 850 ctrID = session.OutputToString() 851 852 // check if the original volume was mounted as read only that --volumes-from also mount it as read only 853 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "touch", mountpoint + "abc.txt"}) 854 session.WaitWithDefaultTimeout() 855 Expect(session.ExitCode()).To(Equal(1)) 856 Expect(session.ErrorToString()).To(ContainSubstring("Read-only file system")) 857 }) 858 859 It("podman run --volumes-from flag with built-in volumes", func() { 860 session := podmanTest.Podman([]string{"create", redis, "sh"}) 861 session.WaitWithDefaultTimeout() 862 Expect(session.ExitCode()).To(Equal(0)) 863 ctrID := session.OutputToString() 864 865 session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "ls"}) 866 session.WaitWithDefaultTimeout() 867 Expect(session.ExitCode()).To(Equal(0)) 868 Expect(session.OutputToString()).To(ContainSubstring("data")) 869 }) 870 871 It("podman run --volumes flag with multiple volumes", func() { 872 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 873 err := os.MkdirAll(vol1, 0755) 874 Expect(err).To(BeNil()) 875 vol2 := filepath.Join(podmanTest.TempDir, "vol-test2") 876 err = os.MkdirAll(vol2, 0755) 877 Expect(err).To(BeNil()) 878 879 session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", ALPINE, "touch", "/myvol2/foo.txt"}) 880 session.WaitWithDefaultTimeout() 881 Expect(session.ExitCode()).To(Equal(0)) 882 }) 883 884 It("podman run --volumes flag with empty host dir", func() { 885 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 886 err := os.MkdirAll(vol1, 0755) 887 Expect(err).To(BeNil()) 888 889 session := podmanTest.Podman([]string{"run", "--volume", ":/myvol1:z", ALPINE, "touch", "/myvol2/foo.txt"}) 890 session.WaitWithDefaultTimeout() 891 Expect(session).To(ExitWithError()) 892 Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty")) 893 session = podmanTest.Podman([]string{"run", "--volume", vol1 + ":", ALPINE, "touch", "/myvol2/foo.txt"}) 894 session.WaitWithDefaultTimeout() 895 Expect(session).To(ExitWithError()) 896 Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty")) 897 }) 898 899 It("podman run --mount flag with multiple mounts", func() { 900 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 901 err := os.MkdirAll(vol1, 0755) 902 Expect(err).To(BeNil()) 903 vol2 := filepath.Join(podmanTest.TempDir, "vol-test2") 904 err = os.MkdirAll(vol2, 0755) 905 Expect(err).To(BeNil()) 906 907 session := podmanTest.Podman([]string{"run", "--mount", "type=bind,src=" + vol1 + ",target=/myvol1,z", "--mount", "type=bind,src=" + vol2 + ",target=/myvol2,z", ALPINE, "touch", "/myvol2/foo.txt"}) 908 session.WaitWithDefaultTimeout() 909 Expect(session.ExitCode()).To(Equal(0)) 910 }) 911 912 It("podman run findmnt nothing shared", func() { 913 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 914 err := os.MkdirAll(vol1, 0755) 915 Expect(err).To(BeNil()) 916 vol2 := filepath.Join(podmanTest.TempDir, "vol-test2") 917 err = os.MkdirAll(vol2, 0755) 918 Expect(err).To(BeNil()) 919 920 session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", fedoraMinimal, "findmnt", "-o", "TARGET,PROPAGATION"}) 921 session.WaitWithDefaultTimeout() 922 Expect(session.ExitCode()).To(Equal(0)) 923 match, _ := session.GrepString("shared") 924 Expect(match).Should(BeFalse()) 925 }) 926 927 It("podman run findmnt shared", func() { 928 vol1 := filepath.Join(podmanTest.TempDir, "vol-test1") 929 err := os.MkdirAll(vol1, 0755) 930 Expect(err).To(BeNil()) 931 vol2 := filepath.Join(podmanTest.TempDir, "vol-test2") 932 err = os.MkdirAll(vol2, 0755) 933 Expect(err).To(BeNil()) 934 935 session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:shared,z", fedoraMinimal, "findmnt", "-o", "TARGET,PROPAGATION"}) 936 session.WaitWithDefaultTimeout() 937 Expect(session.ExitCode()).To(Equal(0)) 938 match, shared := session.GrepString("shared") 939 Expect(match).Should(BeTrue()) 940 // make sure it's only shared (and not 'shared,slave') 941 isSharedOnly := !strings.Contains(shared[0], "shared,") 942 Expect(isSharedOnly).Should(BeTrue()) 943 }) 944 945 It("podman run --security-opts proc-opts=", func() { 946 session := podmanTest.Podman([]string{"run", "--security-opt", "proc-opts=nosuid,exec", fedoraMinimal, "findmnt", "-noOPTIONS", "/proc"}) 947 session.WaitWithDefaultTimeout() 948 Expect(session.ExitCode()).To(Equal(0)) 949 output := session.OutputToString() 950 Expect(output).To(ContainSubstring("nosuid")) 951 Expect(output).To(Not(ContainSubstring("exec"))) 952 }) 953 954 It("podman run --mount type=bind,bind-nonrecursive", func() { 955 SkipIfRootless("FIXME: rootless users are not allowed to mount bind-nonrecursive (Could this be a Kernel bug?") 956 session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"}) 957 session.WaitWithDefaultTimeout() 958 Expect(session.ExitCode()).To(Equal(0)) 959 Expect(len(session.OutputToStringArray())).To(Equal(1)) 960 }) 961 962 It("podman run --mount type=devpts,target=/foo/bar", func() { 963 session := podmanTest.Podman([]string{"run", "--mount", "type=devpts,target=/foo/bar", fedoraMinimal, "stat", "-f", "-c%T", "/foo/bar"}) 964 session.WaitWithDefaultTimeout() 965 Expect(session.ExitCode()).To(Equal(0)) 966 Expect(session.OutputToString()).To(ContainSubstring("devpts")) 967 }) 968 969 It("podman run --pod automatically", func() { 970 session := podmanTest.Podman([]string{"run", "-d", "--pod", "new:foobar", ALPINE, "nc", "-l", "-p", "8080"}) 971 session.WaitWithDefaultTimeout() 972 Expect(session.ExitCode()).To(Equal(0)) 973 974 session = podmanTest.Podman([]string{"run", "--pod", "foobar", ALPINE, "/bin/sh", "-c", "echo test | nc -w 1 127.0.0.1 8080"}) 975 session.WaitWithDefaultTimeout() 976 Expect(session.ExitCode()).To(Equal(0)) 977 978 check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"}) 979 check.WaitWithDefaultTimeout() 980 match, _ := check.GrepString("foobar") 981 Expect(match).To(BeTrue()) 982 }) 983 984 It("podman run --pod new with hostname", func() { 985 hostname := "abc" 986 session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", "--hostname", hostname, ALPINE, "cat", "/etc/hostname"}) 987 session.WaitWithDefaultTimeout() 988 Expect(session.ExitCode()).To(Equal(0)) 989 Expect(session.OutputToString()).To(ContainSubstring(hostname)) 990 }) 991 992 It("podman run --rm should work", func() { 993 session := podmanTest.Podman([]string{"run", "--name", "test", "--rm", ALPINE, "ls"}) 994 session.WaitWithDefaultTimeout() 995 Expect(session.ExitCode()).To(Equal(0)) 996 session = podmanTest.Podman([]string{"wait", "test"}) 997 session.WaitWithDefaultTimeout() 998 Expect(session).To(ExitWithError()) 999 1000 numContainers := podmanTest.NumberOfContainers() 1001 Expect(numContainers).To(Equal(0)) 1002 }) 1003 1004 It("podman run --rm failed container should delete itself", func() { 1005 session := podmanTest.Podman([]string{"run", "--name", "test", "--rm", ALPINE, "foo"}) 1006 session.WaitWithDefaultTimeout() 1007 Expect(session).To(ExitWithError()) 1008 session = podmanTest.Podman([]string{"wait", "test"}) 1009 session.WaitWithDefaultTimeout() 1010 Expect(session).To(ExitWithError()) 1011 1012 numContainers := podmanTest.NumberOfContainers() 1013 Expect(numContainers).To(Equal(0)) 1014 }) 1015 1016 It("podman run failed container should NOT delete itself", func() { 1017 session := podmanTest.Podman([]string{"run", ALPINE, "foo"}) 1018 session.WaitWithDefaultTimeout() 1019 Expect(session).To(ExitWithError()) 1020 // If remote we could have a race condition 1021 session = podmanTest.Podman([]string{"wait", "test"}) 1022 session.WaitWithDefaultTimeout() 1023 Expect(session).To(ExitWithError()) 1024 1025 numContainers := podmanTest.NumberOfContainers() 1026 Expect(numContainers).To(Equal(1)) 1027 }) 1028 It("podman run readonly container should NOT mount /dev/shm read/only", func() { 1029 session := podmanTest.Podman([]string{"run", "--read-only", ALPINE, "mount"}) 1030 session.WaitWithDefaultTimeout() 1031 Expect(session.ExitCode()).To(Equal(0)) 1032 1033 Expect(session.OutputToString()).To(Not(ContainSubstring("/dev/shm type tmpfs (ro,"))) 1034 }) 1035 1036 It("podman run readonly container should NOT mount /run noexec", func() { 1037 session := podmanTest.Podman([]string{"run", "--read-only", ALPINE, "sh", "-c", "mount | grep \"/run \""}) 1038 session.WaitWithDefaultTimeout() 1039 Expect(session.ExitCode()).To(Equal(0)) 1040 1041 Expect(session.OutputToString()).To(Not(ContainSubstring("noexec"))) 1042 }) 1043 1044 It("podman run with bad healthcheck retries", func() { 1045 session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-retries", "0", ALPINE, "top"}) 1046 session.Wait() 1047 Expect(session).To(ExitWithError()) 1048 Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-retries must be greater than 0")) 1049 }) 1050 1051 It("podman run with bad healthcheck timeout", func() { 1052 session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-timeout", "0s", ALPINE, "top"}) 1053 session.WaitWithDefaultTimeout() 1054 Expect(session).To(ExitWithError()) 1055 Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-timeout must be at least 1 second")) 1056 }) 1057 1058 It("podman run with bad healthcheck start-period", func() { 1059 session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-start-period", "-1s", ALPINE, "top"}) 1060 session.WaitWithDefaultTimeout() 1061 Expect(session).To(ExitWithError()) 1062 Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-start-period must be 0 seconds or greater")) 1063 }) 1064 1065 It("podman run with --add-host and --no-hosts fails", func() { 1066 session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts", ALPINE, "top"}) 1067 session.WaitWithDefaultTimeout() 1068 Expect(session).To(ExitWithError()) 1069 }) 1070 1071 It("podman run with restart-policy always restarts containers", func() { 1072 testDir := filepath.Join(podmanTest.RunRoot, "restart-test") 1073 err := os.MkdirAll(testDir, 0755) 1074 Expect(err).To(BeNil()) 1075 1076 aliveFile := filepath.Join(testDir, "running") 1077 file, err := os.Create(aliveFile) 1078 Expect(err).To(BeNil()) 1079 file.Close() 1080 1081 session := podmanTest.Podman([]string{"run", "-dt", "--restart", "always", "-v", fmt.Sprintf("%s:/tmp/runroot:Z", testDir), ALPINE, "sh", "-c", "date +%N > /tmp/runroot/ran && while test -r /tmp/runroot/running; do sleep 0.1s; done"}) 1082 1083 found := false 1084 testFile := filepath.Join(testDir, "ran") 1085 for i := 0; i < 30; i++ { 1086 time.Sleep(1 * time.Second) 1087 if _, err := os.Stat(testFile); err == nil { 1088 found = true 1089 err = os.Remove(testFile) 1090 Expect(err).To(BeNil()) 1091 break 1092 } 1093 } 1094 Expect(found).To(BeTrue()) 1095 1096 err = os.Remove(aliveFile) 1097 Expect(err).To(BeNil()) 1098 1099 session.WaitWithDefaultTimeout() 1100 1101 // 10 seconds to restart the container 1102 found = false 1103 for i := 0; i < 10; i++ { 1104 time.Sleep(1 * time.Second) 1105 if _, err := os.Stat(testFile); err == nil { 1106 found = true 1107 break 1108 } 1109 } 1110 Expect(found).To(BeTrue()) 1111 }) 1112 1113 It("podman run with cgroups=disabled runs without cgroups", func() { 1114 SkipIfRootless("FIXME: I believe this should work but need to fix this test") 1115 SkipIfRootlessCgroupsV1("Disable cgroups not supported on cgroupv1 for rootless users") 1116 // Only works on crun 1117 if !strings.Contains(podmanTest.OCIRuntime, "crun") { 1118 Skip("Test only works on crun") 1119 } 1120 1121 curCgroupsBytes, err := ioutil.ReadFile("/proc/self/cgroup") 1122 Expect(err).To(BeNil()) 1123 var curCgroups string = string(curCgroupsBytes) 1124 fmt.Printf("Output:\n%s\n", curCgroups) 1125 Expect(curCgroups).To(Not(Equal(""))) 1126 1127 ctrName := "testctr" 1128 container := podmanTest.Podman([]string{"run", "--name", ctrName, "-d", "--cgroups=disabled", ALPINE, "top"}) 1129 container.WaitWithDefaultTimeout() 1130 Expect(container.ExitCode()).To(Equal(0)) 1131 1132 // Get PID and get cgroups of that PID 1133 inspectOut := podmanTest.InspectContainer(ctrName) 1134 Expect(len(inspectOut)).To(Equal(1)) 1135 pid := inspectOut[0].State.Pid 1136 Expect(pid).To(Not(Equal(0))) 1137 Expect(inspectOut[0].HostConfig.CgroupParent).To(Equal("")) 1138 1139 ctrCgroupsBytes, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid)) 1140 Expect(err).To(BeNil()) 1141 var ctrCgroups string = string(ctrCgroupsBytes) 1142 fmt.Printf("Output\n:%s\n", ctrCgroups) 1143 Expect(curCgroups).To(Equal(ctrCgroups)) 1144 }) 1145 1146 It("podman run with cgroups=enabled makes cgroups", func() { 1147 SkipIfRootlessCgroupsV1("Enable cgroups not supported on cgroupv1 for rootless users") 1148 // Only works on crun 1149 if !strings.Contains(podmanTest.OCIRuntime, "crun") { 1150 Skip("Test only works on crun") 1151 } 1152 1153 curCgroupsBytes, err := ioutil.ReadFile("/proc/self/cgroup") 1154 Expect(err).To(BeNil()) 1155 var curCgroups string = string(curCgroupsBytes) 1156 fmt.Printf("Output:\n%s\n", curCgroups) 1157 Expect(curCgroups).To(Not(Equal(""))) 1158 1159 ctrName := "testctr" 1160 container := podmanTest.Podman([]string{"run", "--name", ctrName, "-d", "--cgroups=enabled", ALPINE, "top"}) 1161 container.WaitWithDefaultTimeout() 1162 Expect(container.ExitCode()).To(Equal(0)) 1163 1164 // Get PID and get cgroups of that PID 1165 inspectOut := podmanTest.InspectContainer(ctrName) 1166 Expect(len(inspectOut)).To(Equal(1)) 1167 pid := inspectOut[0].State.Pid 1168 Expect(pid).To(Not(Equal(0))) 1169 1170 ctrCgroupsBytes, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid)) 1171 Expect(err).To(BeNil()) 1172 var ctrCgroups string = string(ctrCgroupsBytes) 1173 fmt.Printf("Output\n:%s\n", ctrCgroups) 1174 Expect(curCgroups).To(Not(Equal(ctrCgroups))) 1175 }) 1176 1177 It("podman run with cgroups=garbage errors", func() { 1178 session := podmanTest.Podman([]string{"run", "-d", "--cgroups=garbage", ALPINE, "top"}) 1179 session.WaitWithDefaultTimeout() 1180 Expect(session).To(ExitWithError()) 1181 }) 1182 1183 It("podman run should fail with nonexist authfile", func() { 1184 session := podmanTest.Podman([]string{"run", "--authfile", "/tmp/nonexist", ALPINE, "ls"}) 1185 session.WaitWithDefaultTimeout() 1186 Expect(session.ExitCode()).To(Not(Equal(0))) 1187 }) 1188 1189 It("podman run --device-cgroup-rule", func() { 1190 SkipIfRootless("rootless users are not allowed to mknod") 1191 deviceCgroupRule := "c 42:* rwm" 1192 session := podmanTest.Podman([]string{"run", "--cap-add", "mknod", "--name", "test", "-d", "--device-cgroup-rule", deviceCgroupRule, ALPINE, "top"}) 1193 session.WaitWithDefaultTimeout() 1194 Expect(session.ExitCode()).To(Equal(0)) 1195 session = podmanTest.Podman([]string{"exec", "test", "mknod", "newDev", "c", "42", "1"}) 1196 session.WaitWithDefaultTimeout() 1197 Expect(session.ExitCode()).To(Equal(0)) 1198 }) 1199 1200 It("podman run --replace", func() { 1201 // Make sure we error out with --name. 1202 session := podmanTest.Podman([]string{"create", "--replace", ALPINE, "/bin/sh"}) 1203 session.WaitWithDefaultTimeout() 1204 Expect(session.ExitCode()).To(Equal(125)) 1205 1206 // Run and replace 5 times in a row the "same" container. 1207 ctrName := "testCtr" 1208 for i := 0; i < 5; i++ { 1209 session := podmanTest.Podman([]string{"run", "--detach", "--replace", "--name", ctrName, ALPINE, "/bin/sh"}) 1210 session.WaitWithDefaultTimeout() 1211 Expect(session.ExitCode()).To(Equal(0)) 1212 } 1213 }) 1214 1215 It("podman run --preserve-fds", func() { 1216 devNull, err := os.Open("/dev/null") 1217 Expect(err).To(BeNil()) 1218 defer devNull.Close() 1219 files := []*os.File{ 1220 devNull, 1221 } 1222 session := podmanTest.PodmanExtraFiles([]string{"run", "--preserve-fds", "1", ALPINE, "ls"}, files) 1223 session.WaitWithDefaultTimeout() 1224 Expect(session.ExitCode()).To(Equal(0)) 1225 }) 1226 1227 It("podman run --preserve-fds invalid fd", func() { 1228 session := podmanTest.Podman([]string{"run", "--preserve-fds", "2", ALPINE}) 1229 session.WaitWithDefaultTimeout() 1230 Expect(session.ExitCode()).To(Not(Equal(0))) 1231 Expect(session.ErrorToString()).To(ContainSubstring("file descriptor 3 is not available")) 1232 }) 1233 1234 It("podman run --privileged and --group-add", func() { 1235 groupName := "kvm" 1236 session := podmanTest.Podman([]string{"run", "-t", "-i", "--group-add", groupName, "--privileged", fedoraMinimal, "groups"}) 1237 session.WaitWithDefaultTimeout() 1238 Expect(session.ExitCode()).To(Equal(0)) 1239 Expect(strings.Contains(session.OutputToString(), groupName)).To(BeTrue()) 1240 }) 1241 1242 It("podman run --tz", func() { 1243 session := podmanTest.Podman([]string{"run", "--tz", "foo", "--rm", ALPINE, "date"}) 1244 session.WaitWithDefaultTimeout() 1245 Expect(session.ExitCode()).To(Not(Equal(0))) 1246 1247 session = podmanTest.Podman([]string{"run", "--tz", "America", "--rm", ALPINE, "date"}) 1248 session.WaitWithDefaultTimeout() 1249 Expect(session.ExitCode()).To(Not(Equal(0))) 1250 1251 session = podmanTest.Podman([]string{"run", "--tz", "Pacific/Honolulu", "--rm", ALPINE, "date", "+'%H %Z'"}) 1252 session.WaitWithDefaultTimeout() 1253 Expect(session.ExitCode()).To(Equal(0)) 1254 Expect(session.OutputToString()).To(ContainSubstring("HST")) 1255 1256 session = podmanTest.Podman([]string{"run", "--tz", "local", "--rm", ALPINE, "date", "+'%H %Z'"}) 1257 session.WaitWithDefaultTimeout() 1258 Expect(session.ExitCode()).To(Equal(0)) 1259 t := time.Now() 1260 z, _ := t.Zone() 1261 h := strconv.Itoa(t.Hour()) 1262 Expect(session.OutputToString()).To(ContainSubstring(z)) 1263 Expect(session.OutputToString()).To(ContainSubstring(h)) 1264 1265 }) 1266 1267 It("podman run verify pids-limit", func() { 1268 SkipIfCgroupV1("pids-limit not supported on cgroup V1") 1269 limit := "4321" 1270 session := podmanTest.Podman([]string{"run", "--pids-limit", limit, "--net=none", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) 1271 session.WaitWithDefaultTimeout() 1272 Expect(session.ExitCode()).To(Equal(0)) 1273 Expect(session.OutputToString()).To(ContainSubstring(limit)) 1274 }) 1275 1276 It("podman run umask", func() { 1277 if !strings.Contains(podmanTest.OCIRuntime, "crun") { 1278 Skip("Test only works on crun") 1279 } 1280 1281 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"}) 1282 session.WaitWithDefaultTimeout() 1283 Expect(session.ExitCode()).To(Equal(0)) 1284 Expect(session.OutputToString()).To(Equal("0022")) 1285 1286 session = podmanTest.Podman([]string{"run", "--umask", "0002", "--rm", ALPINE, "sh", "-c", "umask"}) 1287 session.WaitWithDefaultTimeout() 1288 Expect(session.ExitCode()).To(Equal(0)) 1289 Expect(session.OutputToString()).To(Equal("0002")) 1290 1291 session = podmanTest.Podman([]string{"run", "--umask", "0077", "--rm", fedoraMinimal, "umask"}) 1292 session.WaitWithDefaultTimeout() 1293 Expect(session.ExitCode()).To(Equal(0)) 1294 Expect(session.OutputToString()).To(Equal("0077")) 1295 1296 session = podmanTest.Podman([]string{"run", "--umask", "22", "--rm", ALPINE, "sh", "-c", "umask"}) 1297 session.WaitWithDefaultTimeout() 1298 Expect(session.ExitCode()).To(Equal(0)) 1299 Expect(session.OutputToString()).To(Equal("0022")) 1300 1301 session = podmanTest.Podman([]string{"run", "--umask", "9999", "--rm", ALPINE, "sh", "-c", "umask"}) 1302 session.WaitWithDefaultTimeout() 1303 Expect(session.ExitCode()).To(Not(Equal(0))) 1304 Expect(session.ErrorToString()).To(ContainSubstring("Invalid umask")) 1305 }) 1306 1307 It("podman run makes workdir from image", func() { 1308 // BuildImage does not seem to work remote 1309 dockerfile := `FROM busybox 1310 WORKDIR /madethis` 1311 podmanTest.BuildImage(dockerfile, "test", "false") 1312 session := podmanTest.Podman([]string{"run", "--rm", "test", "pwd"}) 1313 session.WaitWithDefaultTimeout() 1314 Expect(session.ExitCode()).To(Equal(0)) 1315 Expect(session.OutputToString()).To(ContainSubstring("/madethis")) 1316 }) 1317 1318 It("podman run --entrypoint does not use image command", func() { 1319 session := podmanTest.Podman([]string{"run", "--entrypoint", "/bin/echo", ALPINE}) 1320 session.WaitWithDefaultTimeout() 1321 Expect(session.ExitCode()).To(Equal(0)) 1322 // We can't guarantee the output is completely empty, some 1323 // nonprintables seem to work their way in. 1324 Expect(session.OutputToString()).To(Not(ContainSubstring("/bin/sh"))) 1325 }) 1326 1327 It("podman run a container with log-level (lower case)", func() { 1328 session := podmanTest.Podman([]string{"--log-level=info", "run", ALPINE, "ls"}) 1329 session.WaitWithDefaultTimeout() 1330 Expect(session.ExitCode()).To(Equal(0)) 1331 }) 1332 1333 It("podman run a container with log-level (upper case)", func() { 1334 session := podmanTest.Podman([]string{"--log-level=INFO", "run", ALPINE, "ls"}) 1335 session.WaitWithDefaultTimeout() 1336 Expect(session.ExitCode()).To(Equal(0)) 1337 }) 1338 1339 It("podman run a container with --pull never should fail if no local store", func() { 1340 session := podmanTest.Podman([]string{"run", "--pull", "never", "docker.io/library/debian:latest", "ls"}) 1341 session.WaitWithDefaultTimeout() 1342 Expect(session.ExitCode()).To(Equal(125)) 1343 }) 1344 1345 It("podman run container with --pull missing and only pull once", func() { 1346 session := podmanTest.Podman([]string{"run", "--pull", "missing", cirros, "ls"}) 1347 session.WaitWithDefaultTimeout() 1348 Expect(session.ExitCode()).To(Equal(0)) 1349 Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) 1350 1351 session = podmanTest.Podman([]string{"run", "--pull", "missing", cirros, "ls"}) 1352 session.WaitWithDefaultTimeout() 1353 Expect(session.ExitCode()).To(Equal(0)) 1354 Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull")) 1355 }) 1356 1357 It("podman run container with --pull missing should pull image multiple times", func() { 1358 session := podmanTest.Podman([]string{"run", "--pull", "always", cirros, "ls"}) 1359 session.WaitWithDefaultTimeout() 1360 Expect(session.ExitCode()).To(Equal(0)) 1361 Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) 1362 1363 session = podmanTest.Podman([]string{"run", "--pull", "always", cirros, "ls"}) 1364 session.WaitWithDefaultTimeout() 1365 Expect(session.ExitCode()).To(Equal(0)) 1366 Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull")) 1367 }) 1368 })