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  })