github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/containers_conf_test.go (about) 1 package integration 2 3 import ( 4 "fmt" 5 "os" 6 "os/exec" 7 "path/filepath" 8 "strings" 9 "time" 10 11 "github.com/containers/podman/v5/libpod/define" 12 . "github.com/containers/podman/v5/test/utils" 13 . "github.com/onsi/ginkgo/v2" 14 . "github.com/onsi/gomega" 15 . "github.com/onsi/gomega/gbytes" 16 . "github.com/onsi/gomega/gexec" 17 ) 18 19 var _ = Describe("Verify podman containers.conf usage", func() { 20 21 BeforeEach(func() { 22 os.Setenv("CONTAINERS_CONF", "config/containers.conf") 23 if IsRemote() { 24 podmanTest.RestartRemoteService() 25 } 26 27 }) 28 29 It("limits test", func() { 30 SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") 31 // containers.conf is set to "nofile=500:500" 32 session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) 33 session.WaitWithDefaultTimeout() 34 Expect(session).Should(ExitCleanly()) 35 Expect(session.OutputToString()).To(ContainSubstring("500")) 36 37 session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=2048:2048", fedoraMinimal, "ulimit", "-n"}) 38 session.WaitWithDefaultTimeout() 39 Expect(session).Should(ExitCleanly()) 40 Expect(session.OutputToString()).To(ContainSubstring("2048")) 41 42 // Reset CONTAINERS_CONF to "/dev/null" 43 // Local should go back to defaults but remote should be set on server side 44 os.Setenv("CONTAINERS_CONF", "/dev/null") 45 session = podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) 46 session.WaitWithDefaultTimeout() 47 Expect(session).Should(ExitCleanly()) 48 if IsRemote() { 49 Expect(session.OutputToString()).To(ContainSubstring("500")) 50 } else { 51 Expect(session.OutputToString()).To(Not(Equal("500"))) 52 } 53 54 }) 55 56 It("oom-score-adj", func() { 57 SkipIfRootlessCgroupsV1("Setting limits not supported on cgroupv1 for rootless users") 58 // containers.conf is set to "oom_score_adj=999" 59 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/self/oom_score_adj"}) 60 session.WaitWithDefaultTimeout() 61 Expect(session).Should(ExitCleanly()) 62 Expect(session.OutputToString()).To(Equal("999")) 63 64 raw, err := os.ReadFile("/proc/self/oom_score_adj") 65 Expect(err).ToNot(HaveOccurred()) 66 67 rawS := strings.TrimSuffix(string(raw), "\n") 68 69 // Reset CONTAINERS_CONF to "/dev/null" 70 // Local should go back to defaults but remote should be set on server side 71 os.Setenv("CONTAINERS_CONF", "/dev/null") 72 session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/self/oom_score_adj"}) 73 session.WaitWithDefaultTimeout() 74 Expect(session).Should(ExitCleanly()) 75 if IsRemote() { 76 Expect(session.OutputToString()).To(Equal("999")) 77 } else { 78 if isRootless() { 79 Expect(session.OutputToString()).To(ContainSubstring(rawS)) 80 } else { 81 Expect(session.OutputToString()).To(ContainSubstring("0")) 82 } 83 84 } 85 86 }) 87 88 It("cgroup_conf in containers.conf", func() { 89 if isCgroupsV1() { 90 Skip("Setting cgroup_confs not supported on cgroupv1") 91 } 92 // FIXME: Needs crun-1.8.2-2 to allow this with --cgroup-manager=cgroupfs, once this is available remove the skip below. 93 SkipIfRootless("--cgroup-manager=cgoupfs and --cgroup-conf not supported in rootless mode with crun") 94 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 95 96 err := os.WriteFile(conffile, []byte("[containers]\ncgroup_conf = [\"pids.max=1234\",]\n"), 0755) 97 Expect(err).ToNot(HaveOccurred()) 98 99 os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile) 100 if IsRemote() { 101 podmanTest.RestartRemoteService() 102 } 103 104 // containers.conf is set to "pids.max=1234" 105 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) 106 session.WaitWithDefaultTimeout() 107 Expect(session).Should(ExitCleanly()) 108 Expect(session.OutputToString()).To(Equal("1234")) 109 110 session = podmanTest.Podman([]string{"run", "--rm", "--cgroup-conf", "pids.max=400", ALPINE, "cat", "/sys/fs/cgroup/pids.max"}) 111 session.WaitWithDefaultTimeout() 112 Expect(session).Should(ExitCleanly()) 113 Expect(session.OutputToString()).To(Equal("400")) 114 }) 115 116 It("having additional env", func() { 117 // containers.conf default env includes foo 118 session := podmanTest.Podman([]string{"run", ALPINE, "printenv"}) 119 session.WaitWithDefaultTimeout() 120 Expect(session).Should(ExitCleanly()) 121 Expect(session.OutputToString()).To(ContainSubstring("foo=bar")) 122 }) 123 124 It("additional devices", func() { 125 // containers.conf devices includes notone 126 session := podmanTest.Podman([]string{"run", "--device", "/dev/null:/dev/bar", ALPINE, "ls", "/dev"}) 127 session.WaitWithDefaultTimeout() 128 Expect(session).Should(ExitCleanly()) 129 Expect(session.OutputToString()).To( 130 And( 131 ContainSubstring("bar"), 132 ContainSubstring("notone"), 133 )) 134 }) 135 136 It("shm-size", func() { 137 // containers.conf default sets shm-size=201k, which ends up as 200k 138 session := podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"}) 139 session.WaitWithDefaultTimeout() 140 Expect(session).Should(ExitCleanly()) 141 Expect(session.OutputToString()).To(ContainSubstring("size=200k")) 142 143 session = podmanTest.Podman([]string{"run", "--shm-size", "1g", ALPINE, "grep", "shm", "/proc/self/mounts"}) 144 session.WaitWithDefaultTimeout() 145 Expect(session).Should(ExitCleanly()) 146 Expect(session.OutputToString()).To(ContainSubstring("size=1048576k")) 147 }) 148 149 It("add capabilities", func() { 150 SkipIfRootlessCgroupsV1("Not supported for rootless + CGroupsV1") 151 cap := podmanTest.Podman([]string{"run", ALPINE, "grep", "CapEff", "/proc/self/status"}) 152 cap.WaitWithDefaultTimeout() 153 Expect(cap).Should(ExitCleanly()) 154 155 os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") 156 if IsRemote() { 157 podmanTest.RestartRemoteService() 158 } 159 session := podmanTest.Podman([]string{"run", BB, "grep", "CapEff", "/proc/self/status"}) 160 session.WaitWithDefaultTimeout() 161 Expect(session).Should(ExitCleanly()) 162 Expect(session.OutputToString()).ToNot(Equal(cap.OutputToString())) 163 }) 164 165 It("regular capabilities", func() { 166 setup := podmanTest.RunTopContainer("test1") 167 setup.WaitWithDefaultTimeout() 168 result := podmanTest.Podman([]string{"top", "test1", "capeff"}) 169 result.WaitWithDefaultTimeout() 170 Expect(result).Should(ExitCleanly()) 171 Expect(result.OutputToString()).To( 172 And( 173 ContainSubstring("FOWNER"), 174 ContainSubstring("SETFCAP"), 175 )) 176 }) 177 178 It("drop capabilities", func() { 179 os.Setenv("CONTAINERS_CONF", "config/containers-caps.conf") 180 if IsRemote() { 181 podmanTest.RestartRemoteService() 182 } 183 setup := podmanTest.RunTopContainer("test1") 184 setup.WaitWithDefaultTimeout() 185 result := podmanTest.Podman([]string{"container", "top", "test1", "capeff"}) 186 result.WaitWithDefaultTimeout() 187 Expect(result).Should(ExitCleanly()) 188 Expect(result.OutputToString()).ToNot( 189 And( 190 ContainSubstring("SETUID"), 191 ContainSubstring("FOWNER"), 192 )) 193 }) 194 195 verifyNSHandling := func(nspath, option string) { 196 SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1") 197 os.Setenv("CONTAINERS_CONF", "config/containers-ns.conf") 198 if IsRemote() { 199 podmanTest.RestartRemoteService() 200 } 201 // containers.conf default ipcns to default to host 202 session := podmanTest.Podman([]string{"run", ALPINE, "ls", "-l", nspath}) 203 session.WaitWithDefaultTimeout() 204 Expect(session).Should(ExitCleanly()) 205 fields := strings.Split(session.OutputToString(), " ") 206 ctrNS := strings.TrimSuffix(fields[len(fields)-1], "\n") 207 208 cmd := exec.Command("ls", "-l", nspath) 209 res, err := cmd.Output() 210 Expect(err).ToNot(HaveOccurred()) 211 fields = strings.Split(string(res), " ") 212 hostNS := strings.TrimSuffix(fields[len(fields)-1], "\n") 213 Expect(hostNS).To(Equal(ctrNS)) 214 215 session = podmanTest.Podman([]string{"run", option, "private", ALPINE, "ls", "-l", nspath}) 216 session.WaitWithDefaultTimeout() 217 Expect(session).Should(ExitCleanly()) 218 fields = strings.Split(session.OutputToString(), " ") 219 ctrNS = fields[len(fields)-1] 220 Expect(hostNS).ToNot(Equal(ctrNS)) 221 } 222 223 It("netns", func() { 224 verifyNSHandling("/proc/self/ns/net", "--network") 225 }) 226 227 It("ipcns", func() { 228 verifyNSHandling("/proc/self/ns/ipc", "--ipc") 229 }) 230 231 It("utsns", func() { 232 verifyNSHandling("/proc/self/ns/uts", "--uts") 233 }) 234 235 It("pidns", func() { 236 verifyNSHandling("/proc/self/ns/pid", "--pid") 237 }) 238 239 It("cgroupns", func() { 240 verifyNSHandling("/proc/self/ns/cgroup", "--cgroupns") 241 }) 242 243 It("using journald for container with container log_tag", func() { 244 SkipIfJournaldUnavailable() 245 os.Setenv("CONTAINERS_CONF", "config/containers-journald.conf") 246 if IsRemote() { 247 podmanTest.RestartRemoteService() 248 } 249 logc := podmanTest.Podman([]string{"run", "-d", ALPINE, "sh", "-c", "echo podman; sleep 0.1; echo podman; sleep 0.1; echo podman"}) 250 logc.WaitWithDefaultTimeout() 251 Expect(logc).Should(ExitCleanly()) 252 cid := logc.OutputToString() 253 254 wait := podmanTest.Podman([]string{"wait", cid}) 255 wait.WaitWithDefaultTimeout() 256 Expect(wait).Should(ExitCleanly()) 257 258 // Flake prevention: journalctl makes no timeliness guarantees. 259 time.Sleep(1 * time.Second) 260 cmd := exec.Command("journalctl", "--no-pager", "-o", "json", "--output-fields=CONTAINER_TAG", fmt.Sprintf("CONTAINER_ID_FULL=%s", cid)) 261 out, err := cmd.CombinedOutput() 262 Expect(err).ToNot(HaveOccurred()) 263 Expect(out).To(ContainSubstring("alpine")) 264 }) 265 266 It("add volumes", func() { 267 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 268 269 volume := filepath.Join(podmanTest.TempDir, "vol") 270 err = os.MkdirAll(volume, os.ModePerm) 271 Expect(err).ToNot(HaveOccurred()) 272 err := os.WriteFile(conffile, []byte(fmt.Sprintf("[containers]\nvolumes=[\"%s:%s:Z\",]\n", volume, volume)), 0755) 273 Expect(err).ToNot(HaveOccurred()) 274 275 os.Setenv("CONTAINERS_CONF", conffile) 276 if IsRemote() { 277 podmanTest.RestartRemoteService() 278 } 279 result := podmanTest.Podman([]string{"run", ALPINE, "ls", volume}) 280 result.WaitWithDefaultTimeout() 281 Expect(result).Should(ExitCleanly()) 282 }) 283 284 It("sysctl test", func() { 285 // containers.conf is set to "net.ipv4.ping_group_range=0 1000" 286 session := podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "cat", "/proc/sys/net/ipv4/ping_group_range"}) 287 session.WaitWithDefaultTimeout() 288 Expect(session).Should(ExitCleanly()) 289 Expect(session.OutputToString()).To(ContainSubstring("1000")) 290 291 // Ignore containers.conf setting if --net=host 292 session = podmanTest.Podman([]string{"run", "--rm", "--net", "host", fedoraMinimal, "cat", "/proc/sys/net/ipv4/ping_group_range"}) 293 session.WaitWithDefaultTimeout() 294 Expect(session).Should(ExitCleanly()) 295 Expect(session.OutputToString()).ToNot(ContainSubstring("1000")) 296 }) 297 298 It("search domain", func() { 299 session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) 300 session.WaitWithDefaultTimeout() 301 Expect(session).Should(ExitCleanly()) 302 Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search foobar.com"))) 303 }) 304 305 It("add dns server", func() { 306 session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) 307 session.WaitWithDefaultTimeout() 308 Expect(session).Should(ExitCleanly()) 309 Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("nameserver 1.2.3.4"))) 310 }) 311 312 It("add dns option", func() { 313 session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) 314 session.WaitWithDefaultTimeout() 315 Expect(session).Should(ExitCleanly()) 316 Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("options debug"))) 317 }) 318 319 It("remove all search domain", func() { 320 session := podmanTest.Podman([]string{"run", "--dns-search=.", ALPINE, "cat", "/etc/resolv.conf"}) 321 session.WaitWithDefaultTimeout() 322 Expect(session).Should(ExitCleanly()) 323 Expect(session.OutputToStringArray()).To(Not(ContainElement(HavePrefix("search")))) 324 }) 325 326 It("add search domain", func() { 327 session := podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) 328 session.WaitWithDefaultTimeout() 329 Expect(session).Should(ExitCleanly()) 330 Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search"))) 331 Expect(session.OutputToString()).To( 332 And( 333 ContainSubstring("foobar.com"), 334 ContainSubstring("1.2.3.4"), 335 ContainSubstring("debug"), 336 )) 337 }) 338 339 It("add timezone", func() { 340 // containers.conf timezone set to Pacific/Honolulu 341 session := podmanTest.Podman([]string{"run", "--tz", "", ALPINE, "date", "+'%H %Z'"}) 342 session.WaitWithDefaultTimeout() 343 Expect(session).Should(ExitCleanly()) 344 Expect(session.OutputToString()).To(ContainSubstring("HST")) 345 346 // verify flag still overrides 347 session = podmanTest.Podman([]string{"run", "--tz", "EST", ALPINE, "date", "+'%H %Z'"}) 348 session.WaitWithDefaultTimeout() 349 Expect(session).Should(ExitCleanly()) 350 Expect(session.OutputToString()).To(ContainSubstring("EST")) 351 }) 352 353 It("add umask", func() { 354 // containers.conf umask set to 0002 355 if !strings.Contains(podmanTest.OCIRuntime, "crun") { 356 Skip("Test only works on crun") 357 } 358 359 session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"}) 360 session.WaitWithDefaultTimeout() 361 Expect(session).Should(ExitCleanly()) 362 Expect(session.OutputToString()).To(Equal("0002")) 363 }) 364 365 It("network slirp options to allow host loopback", func() { 366 session := podmanTest.Podman([]string{"run", "--network", "slirp4netns", ALPINE, "ping", "-c1", "10.0.2.2"}) 367 session.Wait(30) 368 Expect(session).Should(ExitCleanly()) 369 }) 370 371 It("podman-remote test localcontainers.conf", func() { 372 SkipIfNotRemote("this test is only for remote") 373 374 os.Setenv("CONTAINERS_CONF", "config/containers-remote.conf") 375 // Configuration that comes from remote server 376 // env 377 session := podmanTest.Podman([]string{"run", ALPINE, "printenv", "foo"}) 378 session.WaitWithDefaultTimeout() 379 Expect(session).Should(ExitCleanly()) 380 Expect(session.OutputToString()).To(Equal("bar")) 381 382 // dns-search, server, options 383 session = podmanTest.Podman([]string{"run", ALPINE, "cat", "/etc/resolv.conf"}) 384 session.WaitWithDefaultTimeout() 385 Expect(session).Should(ExitCleanly()) 386 Expect(session.OutputToStringArray()).To(ContainElement(HavePrefix("search"))) 387 Expect(session.OutputToString()).To( 388 And( 389 ContainSubstring("foobar.com"), 390 ContainSubstring("1.2.3.4"), 391 ContainSubstring("debug"), 392 )) 393 394 // sysctls 395 session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "cat", "/proc/sys/net/ipv4/ping_group_range"}) 396 session.WaitWithDefaultTimeout() 397 Expect(session).Should(ExitCleanly()) 398 Expect(session.OutputToString()).To(ContainSubstring("1000")) 399 400 // shm-size 401 session = podmanTest.Podman([]string{"run", ALPINE, "grep", "shm", "/proc/self/mounts"}) 402 session.WaitWithDefaultTimeout() 403 Expect(session).Should(ExitCleanly()) 404 Expect(session.OutputToString()).To(ContainSubstring("size=200k")) 405 406 // ulimits 407 session = podmanTest.Podman([]string{"run", "--rm", fedoraMinimal, "ulimit", "-n"}) 408 session.WaitWithDefaultTimeout() 409 Expect(session).Should(ExitCleanly()) 410 Expect(session.OutputToString()).To(ContainSubstring("500")) 411 412 // Configuration that comes from remote client 413 // Timezone 414 session = podmanTest.Podman([]string{"run", ALPINE, "date", "+'%H %Z'"}) 415 session.WaitWithDefaultTimeout() 416 Expect(session).Should(ExitCleanly()) 417 Expect(session.OutputToString()).To( 418 Or( 419 ContainSubstring("EST"), 420 ContainSubstring("EDT"), 421 )) 422 423 // Umask 424 session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "umask"}) 425 session.WaitWithDefaultTimeout() 426 Expect(session).Should(ExitCleanly()) 427 Expect(session.OutputToString()).To(Equal("0022")) 428 }) 429 430 It("add annotations", func() { 431 // containers.conf is set to "run.oci.keep_original_groups=1" 432 session := podmanTest.Podman([]string{"create", "--rm", "--name", "test", fedoraMinimal}) 433 session.WaitWithDefaultTimeout() 434 Expect(session).Should(ExitCleanly()) 435 436 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{ .Config.Annotations }}", "test"}) 437 inspect.WaitWithDefaultTimeout() 438 Expect(inspect.OutputToString()).To(ContainSubstring(fmt.Sprintf("%s:1", define.RunOCIKeepOriginalGroups))) 439 }) 440 441 It("--add-host and no-hosts=true fails", func() { 442 session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", ALPINE, "top"}) 443 session.WaitWithDefaultTimeout() 444 Expect(session).To(ExitWithError(125, "--no-hosts and --add-host cannot be set together")) 445 446 session = podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts=false", ALPINE, "top"}) 447 session.WaitWithDefaultTimeout() 448 Expect(session).Should(ExitCleanly()) 449 }) 450 451 It("no-hosts=true /etc/hosts does not include hostname", func() { 452 session := podmanTest.Podman([]string{"run", "--rm", "--name", "test", ALPINE, "cat", "/etc/hosts"}) 453 session.WaitWithDefaultTimeout() 454 Expect(session).Should(ExitCleanly()) 455 Expect(session.OutputToString()).ToNot(ContainSubstring("test")) 456 457 session = podmanTest.Podman([]string{"run", "--rm", "--name", "test", "--no-hosts=false", ALPINE, "cat", "/etc/hosts"}) 458 session.WaitWithDefaultTimeout() 459 Expect(session).Should(ExitCleanly()) 460 Expect(session.OutputToString()).To(ContainSubstring("test")) 461 }) 462 463 It("seccomp profile path", func() { 464 configPath := filepath.Join(podmanTest.TempDir, "containers.conf") 465 os.Setenv("CONTAINERS_CONF", configPath) 466 467 profile := filepath.Join(podmanTest.TempDir, "seccomp.json") 468 containersConf := []byte(fmt.Sprintf("[containers]\nseccomp_profile=\"%s\"", profile)) 469 err = os.WriteFile(configPath, containersConf, os.ModePerm) 470 Expect(err).ToNot(HaveOccurred()) 471 472 if IsRemote() { 473 podmanTest.RestartRemoteService() 474 } 475 476 session := podmanTest.Podman([]string{"info", "--format", "{{.Host.Security.SECCOMPProfilePath}}"}) 477 session.WaitWithDefaultTimeout() 478 Expect(session).Should(ExitCleanly()) 479 Expect(session.OutputToString()).To(Equal(profile)) 480 }) 481 482 It("add image_copy_tmp_dir", func() { 483 // Prevents overwriting of TMPDIR environment 484 if cacheDir, found := os.LookupEnv("TMPDIR"); found { 485 defer os.Setenv("TMPDIR", cacheDir) 486 os.Unsetenv("TMPDIR") 487 } else { 488 defer os.Unsetenv("TMPDIR") 489 } 490 if IsRemote() { 491 podmanTest.RestartRemoteService() 492 } 493 494 session := podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) 495 session.WaitWithDefaultTimeout() 496 Expect(session).Should(ExitCleanly()) 497 Expect(session.OutputToString()).To(Equal("/var/tmp")) 498 499 storagePath := filepath.Join(podmanTest.TempDir, "storage") 500 configPath := filepath.Join(podmanTest.TempDir, "containers.conf") 501 os.Setenv("CONTAINERS_CONF", configPath) 502 503 containersConf := []byte("[engine]\nimage_copy_tmp_dir=\"/foobar\"") 504 err = os.WriteFile(configPath, containersConf, os.ModePerm) 505 Expect(err).ToNot(HaveOccurred()) 506 507 if IsRemote() { 508 podmanTest.RestartRemoteService() 509 } 510 511 session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) 512 session.WaitWithDefaultTimeout() 513 Expect(session).Should(ExitCleanly()) 514 Expect(session.OutputToString()).To(Equal("/foobar")) 515 516 containersConf = []byte(fmt.Sprintf("[engine]\nimage_copy_tmp_dir=%q", storagePath)) 517 err = os.WriteFile(configPath, containersConf, os.ModePerm) 518 Expect(err).ToNot(HaveOccurred()) 519 if IsRemote() { 520 podmanTest.RestartRemoteService() 521 } 522 523 session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) 524 session.WaitWithDefaultTimeout() 525 Expect(session).Should(ExitCleanly()) 526 Expect(session.OutputToString()).To(ContainSubstring(storagePath)) 527 528 containersConf = []byte("[engine]\nimage_copy_tmp_dir=\"storage1\"") 529 err = os.WriteFile(configPath, containersConf, os.ModePerm) 530 Expect(err).ToNot(HaveOccurred()) 531 532 if !IsRemote() { 533 session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) 534 session.WaitWithDefaultTimeout() 535 Expect(session).Should(ExitWithError(125, `invalid image_copy_tmp_dir value "storage1" (relative paths are not accepted)`)) 536 537 os.Setenv("TMPDIR", "/hoge") 538 session = podmanTest.Podman([]string{"info", "--format", "{{.Store.ImageCopyTmpDir}}"}) 539 session.WaitWithDefaultTimeout() 540 Expect(session).Should(ExitCleanly()) 541 Expect(session.OutputToString()).To(Equal("/hoge")) 542 os.Unsetenv("TMPDIR") 543 } 544 }) 545 546 // FIXME not sure why this is here 547 It("system service --help shows (default 20)", func() { 548 SkipIfRemote("system service is not supported on clients") 549 550 result := podmanTest.Podman([]string{"system", "service", "--help"}) 551 result.WaitWithDefaultTimeout() 552 Expect(result).Should(ExitCleanly()) 553 Expect(result.OutputToString()).To(ContainSubstring("(default 1234)")) 554 }) 555 556 It("bad infra_image name", func() { 557 infra1 := "i.do/not/exist:image" 558 infra2 := "i.still.do/not/exist:image" 559 errorString := "initializing source docker://" + infra1 560 error2String := "initializing source docker://" + infra2 561 configPath := filepath.Join(podmanTest.TempDir, "containers.conf") 562 os.Setenv("CONTAINERS_CONF", configPath) 563 564 containersConf := []byte("[engine]\ninfra_image=\"" + infra1 + "\"") 565 err = os.WriteFile(configPath, containersConf, os.ModePerm) 566 Expect(err).ToNot(HaveOccurred()) 567 568 if IsRemote() { 569 podmanTest.RestartRemoteService() 570 } 571 572 result := podmanTest.Podman([]string{"pod", "create", "--infra-image", infra2}) 573 result.WaitWithDefaultTimeout() 574 Expect(result).Should(ExitWithError(125, error2String)) 575 576 result = podmanTest.Podman([]string{"pod", "create"}) 577 result.WaitWithDefaultTimeout() 578 Expect(result).Should(ExitWithError(125, errorString)) 579 580 result = podmanTest.Podman([]string{"create", "--pod", "new:pod1", ALPINE}) 581 result.WaitWithDefaultTimeout() 582 Expect(result).Should(ExitWithError(125, errorString)) 583 }) 584 585 It("set .engine.remote=true", func() { 586 SkipIfRemote("only meaningful when running ABI/local") 587 588 // Need to restore CONTAINERS_CONF or AfterEach() will fail 589 if path, found := os.LookupEnv("CONTAINERS_CONF"); found { 590 defer os.Setenv("CONTAINERS_CONF", path) 591 } 592 593 configPath := filepath.Join(podmanTest.TempDir, "containers-engine-remote.conf") 594 os.Setenv("CONTAINERS_CONF", configPath) 595 defer os.Remove(configPath) 596 597 err := os.WriteFile(configPath, []byte("[engine]\nremote=true"), os.ModePerm) 598 Expect(err).ToNot(HaveOccurred()) 599 600 // podmanTest.Podman() cannot be used as it was initialized remote==false 601 cmd := exec.Command(podmanTest.PodmanBinary, "info", "--format", "{{.Host.ServiceIsRemote}}") 602 session, err := Start(cmd, GinkgoWriter, GinkgoWriter) 603 Expect(err).ToNot(HaveOccurred()) 604 605 description := "Should have failed as there is no running remote API service available." 606 Eventually(session, DefaultWaitTimeout).Should(Exit(125), description) 607 Expect(session.Err).Should(Say("Error: unable to connect to Podman socket")) 608 }) 609 610 It("podman containers.conf cgroups=disabled", func() { 611 if !strings.Contains(podmanTest.OCIRuntime, "crun") { 612 // Assume this will never be fixed in runc 613 Skip("NoCgroups requires crun") 614 } 615 616 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 617 err := os.WriteFile(conffile, []byte("[containers]\ncgroups=\"disabled\"\n"), 0755) 618 Expect(err).ToNot(HaveOccurred()) 619 620 result := podmanTest.Podman([]string{"create", ALPINE, "true"}) 621 result.WaitWithDefaultTimeout() 622 Expect(result).Should(ExitCleanly()) 623 624 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()}) 625 inspect.WaitWithDefaultTimeout() 626 Expect(inspect.OutputToString()).ToNot(Equal("disabled")) 627 628 os.Setenv("CONTAINERS_CONF", conffile) 629 if IsRemote() { 630 podmanTest.RestartRemoteService() 631 } 632 result = podmanTest.Podman([]string{"create", ALPINE, "true"}) 633 result.WaitWithDefaultTimeout() 634 Expect(result).Should(ExitCleanly()) 635 636 inspect = podmanTest.Podman([]string{"inspect", "--format", "{{ .HostConfig.Cgroups }}", result.OutputToString()}) 637 inspect.WaitWithDefaultTimeout() 638 Expect(inspect.OutputToString()).To(Equal("disabled")) 639 640 // Check we can also create a pod when cgroups=disabled 641 result = podmanTest.Podman([]string{"pod", "create"}) 642 result.WaitWithDefaultTimeout() 643 Expect(result).Should(ExitCleanly()) 644 }) 645 646 It("podman containers.conf runtime", func() { 647 SkipIfRemote("--runtime option is not available for remote commands") 648 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 649 err := os.WriteFile(conffile, []byte("[engine]\nruntime=\"testruntime\"\n"), 0755) 650 Expect(err).ToNot(HaveOccurred()) 651 652 os.Setenv("CONTAINERS_CONF", conffile) 653 result := podmanTest.Podman([]string{"--help"}) 654 result.WaitWithDefaultTimeout() 655 Expect(result).Should(ExitCleanly()) 656 Expect(result.OutputToString()).To(ContainSubstring("Path to the OCI-compatible binary used to run containers. (default \"testruntime\")")) 657 }) 658 659 It("podman default_rootless_network_cmd", func() { 660 SkipIfNotRootless("default_rootless_network_cmd is only used rootless") 661 662 for _, mode := range []string{"pasta", "slirp4netns", "invalid"} { 663 conffile := filepath.Join(podmanTest.TempDir, "container.conf") 664 content := "[network]\ndefault_rootless_network_cmd=\"" + mode + "\"\n" 665 err := os.WriteFile(conffile, []byte(content), 0755) 666 Expect(err).ToNot(HaveOccurred()) 667 668 os.Setenv("CONTAINERS_CONF_OVERRIDE", conffile) 669 if IsRemote() { 670 podmanTest.RestartRemoteService() 671 } 672 673 podman := podmanTest.Podman([]string{"create", "--name", mode, ALPINE, "ip", "addr"}) 674 podman.WaitWithDefaultTimeout() 675 676 if mode == "invalid" { 677 Expect(podman).Should(ExitWithError(125, `invalid default_rootless_network_cmd option "invalid"`)) 678 continue 679 } 680 Expect(podman).Should(ExitCleanly()) 681 682 inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.HostConfig.NetworkMode}}", mode}) 683 inspect.WaitWithDefaultTimeout() 684 Expect(inspect).Should(ExitCleanly()) 685 Expect(inspect.OutputToString()).Should(Equal(mode)) 686 } 687 }) 688 })