github.com/containers/libpod@v1.9.4-0.20220419124438-4284fd425507/test/e2e/run_test.go (about)

     1  // +build !remoteclient
     2  
     3  package integration
     4  
     5  import (
     6  	"fmt"
     7  	"io/ioutil"
     8  	"net"
     9  	"os"
    10  	"path/filepath"
    11  	"strconv"
    12  	"strings"
    13  	"syscall"
    14  	"time"
    15  
    16  	"github.com/containers/libpod/pkg/cgroups"
    17  	. "github.com/containers/libpod/test/utils"
    18  	"github.com/containers/storage/pkg/stringid"
    19  	"github.com/mrunalp/fileutils"
    20  	. "github.com/onsi/ginkgo"
    21  	. "github.com/onsi/gomega"
    22  )
    23  
    24  var _ = Describe("Podman run", func() {
    25  	var (
    26  		tempdir    string
    27  		err        error
    28  		podmanTest *PodmanTestIntegration
    29  	)
    30  
    31  	BeforeEach(func() {
    32  		tempdir, err = CreateTempDirInTempDir()
    33  		if err != nil {
    34  			os.Exit(1)
    35  		}
    36  		podmanTest = PodmanTestCreate(tempdir)
    37  		podmanTest.Setup()
    38  		podmanTest.SeedImages()
    39  	})
    40  
    41  	AfterEach(func() {
    42  		podmanTest.Cleanup()
    43  		f := CurrentGinkgoTestDescription()
    44  		processTestResult(f)
    45  
    46  	})
    47  
    48  	It("podman run a container based on local image", func() {
    49  		session := podmanTest.Podman([]string{"run", ALPINE, "ls"})
    50  		session.WaitWithDefaultTimeout()
    51  		Expect(session.ExitCode()).To(Equal(0))
    52  	})
    53  
    54  	It("podman run a container based on a complex local image name", func() {
    55  		SkipIfRootless()
    56  		imageName := strings.TrimPrefix(nginx, "quay.io/")
    57  		session := podmanTest.Podman([]string{"run", imageName, "ls"})
    58  		session.WaitWithDefaultTimeout()
    59  		Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull"))
    60  		Expect(session.ExitCode()).To(Equal(0))
    61  	})
    62  
    63  	It("podman run a container based on on a short name with localhost", func() {
    64  		tag := podmanTest.Podman([]string{"tag", nginx, "localhost/libpod/alpine_nginx:latest"})
    65  		tag.WaitWithDefaultTimeout()
    66  
    67  		rmi := podmanTest.Podman([]string{"rmi", nginx})
    68  		rmi.WaitWithDefaultTimeout()
    69  
    70  		session := podmanTest.Podman([]string{"run", "libpod/alpine_nginx:latest", "ls"})
    71  		session.WaitWithDefaultTimeout()
    72  		Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull"))
    73  		Expect(session.ExitCode()).To(Equal(0))
    74  	})
    75  
    76  	It("podman container run a container based on on a short name with localhost", func() {
    77  		tag := podmanTest.Podman([]string{"image", "tag", nginx, "localhost/libpod/alpine_nginx:latest"})
    78  		tag.WaitWithDefaultTimeout()
    79  
    80  		rmi := podmanTest.Podman([]string{"image", "rm", nginx})
    81  		rmi.WaitWithDefaultTimeout()
    82  
    83  		session := podmanTest.Podman([]string{"container", "run", "libpod/alpine_nginx:latest", "ls"})
    84  		session.WaitWithDefaultTimeout()
    85  		Expect(session.ErrorToString()).ToNot(ContainSubstring("Trying to pull"))
    86  		Expect(session.ExitCode()).To(Equal(0))
    87  	})
    88  
    89  	It("podman run a container based on local image with short options", func() {
    90  		session := podmanTest.Podman([]string{"run", "-dt", ALPINE, "ls"})
    91  		session.WaitWithDefaultTimeout()
    92  		Expect(session.ExitCode()).To(Equal(0))
    93  	})
    94  
    95  	It("podman run a container based on local image with short options and args", func() {
    96  		// regression test for #714
    97  		session := podmanTest.Podman([]string{"run", ALPINE, "find", "/etc", "-name", "hosts"})
    98  		session.WaitWithDefaultTimeout()
    99  		Expect(session.ExitCode()).To(Equal(0))
   100  		match, _ := session.GrepString("/etc/hosts")
   101  		Expect(match).Should(BeTrue())
   102  	})
   103  
   104  	It("podman run a container based on remote image", func() {
   105  		session := podmanTest.Podman([]string{"run", "-dt", BB_GLIBC, "ls"})
   106  		session.WaitWithDefaultTimeout()
   107  		Expect(session.ExitCode()).To(Equal(0))
   108  	})
   109  
   110  	It("podman run a container with a --rootfs", func() {
   111  		rootfs := filepath.Join(tempdir, "rootfs")
   112  		uls := filepath.Join("/", "usr", "local", "share")
   113  		uniqueString := stringid.GenerateNonCryptoID()
   114  		testFilePath := filepath.Join(uls, uniqueString)
   115  		tarball := filepath.Join(tempdir, "rootfs.tar")
   116  
   117  		err := os.Mkdir(rootfs, 0770)
   118  		Expect(err).Should(BeNil())
   119  
   120  		// Change image in predictable way to validate export
   121  		csession := podmanTest.Podman([]string{"run", "--name", uniqueString, ALPINE,
   122  			"/bin/sh", "-c", fmt.Sprintf("echo %s > %s", uniqueString, testFilePath)})
   123  		csession.WaitWithDefaultTimeout()
   124  		Expect(csession.ExitCode()).To(Equal(0))
   125  
   126  		// Export from working container image guarantees working root
   127  		esession := podmanTest.Podman([]string{"export", "--output", tarball, uniqueString})
   128  		esession.WaitWithDefaultTimeout()
   129  		Expect(esession.ExitCode()).To(Equal(0))
   130  		Expect(tarball).Should(BeARegularFile())
   131  
   132  		// N/B: This will loose any extended attributes like SELinux types
   133  		fmt.Fprintf(os.Stderr, "Extracting container root tarball\n")
   134  		tarsession := SystemExec("tar", []string{"xf", tarball, "-C", rootfs})
   135  		Expect(tarsession.ExitCode()).To(Equal(0))
   136  		Expect(filepath.Join(rootfs, uls)).Should(BeADirectory())
   137  
   138  		// Other tests confirm SELinux types, just confirm --rootfs is working.
   139  		session := podmanTest.Podman([]string{"run", "-i", "--security-opt", "label=disable",
   140  			"--rootfs", rootfs, "cat", testFilePath})
   141  		session.WaitWithDefaultTimeout()
   142  		Expect(session.ExitCode()).To(Equal(0))
   143  
   144  		// Validate changes made in original container and export
   145  		stdoutLines := session.OutputToStringArray()
   146  		Expect(stdoutLines).Should(HaveLen(1))
   147  		Expect(stdoutLines[0]).Should(Equal(uniqueString))
   148  	})
   149  
   150  	It("podman run a container with --init", func() {
   151  		session := podmanTest.Podman([]string{"run", "--init", ALPINE, "ls"})
   152  		session.WaitWithDefaultTimeout()
   153  		Expect(session.ExitCode()).To(Equal(0))
   154  	})
   155  
   156  	It("podman run a container with --init and --init-path", func() {
   157  		session := podmanTest.Podman([]string{"run", "--init", "--init-path", "/usr/libexec/podman/catatonit", ALPINE, "ls"})
   158  		session.WaitWithDefaultTimeout()
   159  		Expect(session.ExitCode()).To(Equal(0))
   160  	})
   161  
   162  	It("podman run seccomp test", func() {
   163  
   164  		in := []byte(`{"defaultAction":"SCMP_ACT_ALLOW","syscalls":[{"name":"getcwd","action":"SCMP_ACT_ERRNO"}]}`)
   165  		jsonFile, err := podmanTest.CreateSeccompJson(in)
   166  		if err != nil {
   167  			fmt.Println(err)
   168  			Skip("Failed to prepare seccomp.json for test.")
   169  		}
   170  
   171  		session := podmanTest.Podman([]string{"run", "-it", "--security-opt", strings.Join([]string{"seccomp=", jsonFile}, ""), ALPINE, "pwd"})
   172  		session.WaitWithDefaultTimeout()
   173  		Expect(session).To(ExitWithError())
   174  		match, _ := session.GrepString("Operation not permitted")
   175  		Expect(match).Should(BeTrue())
   176  	})
   177  
   178  	It("podman run capabilities test", func() {
   179  		session := podmanTest.Podman([]string{"run", "--rm", "--cap-add", "all", ALPINE, "cat", "/proc/self/status"})
   180  		session.WaitWithDefaultTimeout()
   181  		Expect(session.ExitCode()).To(Equal(0))
   182  
   183  		session = podmanTest.Podman([]string{"run", "--rm", "--cap-add", "sys_admin", ALPINE, "cat", "/proc/self/status"})
   184  		session.WaitWithDefaultTimeout()
   185  		Expect(session.ExitCode()).To(Equal(0))
   186  
   187  		session = podmanTest.Podman([]string{"run", "--rm", "--cap-drop", "all", ALPINE, "cat", "/proc/self/status"})
   188  		session.WaitWithDefaultTimeout()
   189  		Expect(session.ExitCode()).To(Equal(0))
   190  
   191  		session = podmanTest.Podman([]string{"run", "--rm", "--cap-drop", "setuid", ALPINE, "cat", "/proc/self/status"})
   192  		session.WaitWithDefaultTimeout()
   193  		Expect(session.ExitCode()).To(Equal(0))
   194  	})
   195  
   196  	It("podman run environment test", func() {
   197  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "HOME"})
   198  		session.WaitWithDefaultTimeout()
   199  		Expect(session.ExitCode()).To(Equal(0))
   200  		match, _ := session.GrepString("/root")
   201  		Expect(match).Should(BeTrue())
   202  
   203  		session = podmanTest.Podman([]string{"run", "--rm", "--user", "2", ALPINE, "printenv", "HOME"})
   204  		session.WaitWithDefaultTimeout()
   205  		Expect(session.ExitCode()).To(Equal(0))
   206  		match, _ = session.GrepString("/sbin")
   207  		Expect(match).Should(BeTrue())
   208  
   209  		session = podmanTest.Podman([]string{"run", "--rm", "--env", "HOME=/foo", ALPINE, "printenv", "HOME"})
   210  		session.WaitWithDefaultTimeout()
   211  		Expect(session.ExitCode()).To(Equal(0))
   212  		match, _ = session.GrepString("/foo")
   213  		Expect(match).Should(BeTrue())
   214  
   215  		session = podmanTest.Podman([]string{"run", "--rm", "--env", "FOO=BAR,BAZ", ALPINE, "printenv", "FOO"})
   216  		session.WaitWithDefaultTimeout()
   217  		Expect(session.ExitCode()).To(Equal(0))
   218  		match, _ = session.GrepString("BAR,BAZ")
   219  		Expect(match).Should(BeTrue())
   220  
   221  		session = podmanTest.Podman([]string{"run", "--rm", "--env", "PATH=/bin", ALPINE, "printenv", "PATH"})
   222  		session.WaitWithDefaultTimeout()
   223  		Expect(session.ExitCode()).To(Equal(0))
   224  		match, _ = session.GrepString("/bin")
   225  		Expect(match).Should(BeTrue())
   226  
   227  		os.Setenv("FOO", "BAR")
   228  		session = podmanTest.Podman([]string{"run", "--rm", "--env", "FOO", ALPINE, "printenv", "FOO"})
   229  		session.WaitWithDefaultTimeout()
   230  		Expect(session.ExitCode()).To(Equal(0))
   231  		match, _ = session.GrepString("BAR")
   232  		Expect(match).Should(BeTrue())
   233  		os.Unsetenv("FOO")
   234  
   235  		session = podmanTest.Podman([]string{"run", "--rm", "--env", "FOO", ALPINE, "printenv", "FOO"})
   236  		session.WaitWithDefaultTimeout()
   237  		Expect(len(session.OutputToString())).To(Equal(0))
   238  		Expect(session.ExitCode()).To(Equal(1))
   239  
   240  		session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv"})
   241  		session.WaitWithDefaultTimeout()
   242  		Expect(session.ExitCode()).To(Equal(0))
   243  
   244  		// This currently does not work
   245  		// Re-enable when hostname is an env variable
   246  		session = podmanTest.Podman([]string{"run", "--rm", ALPINE, "sh", "-c", "printenv"})
   247  		session.Wait(10)
   248  		Expect(session.ExitCode()).To(Equal(0))
   249  		match, _ = session.GrepString("HOSTNAME")
   250  		Expect(match).Should(BeTrue())
   251  	})
   252  
   253  	It("podman run --host-env environment test", func() {
   254  		os.Setenv("FOO", "BAR")
   255  		session := podmanTest.Podman([]string{"run", "--rm", "--env-host", ALPINE, "printenv", "FOO"})
   256  		session.WaitWithDefaultTimeout()
   257  		Expect(session.ExitCode()).To(Equal(0))
   258  		match, _ := session.GrepString("BAR")
   259  		Expect(match).Should(BeTrue())
   260  
   261  		session = podmanTest.Podman([]string{"run", "--rm", "--env", "FOO=BAR1", "--env-host", ALPINE, "printenv", "FOO"})
   262  		session.WaitWithDefaultTimeout()
   263  		Expect(session.ExitCode()).To(Equal(0))
   264  		match, _ = session.GrepString("BAR1")
   265  		Expect(match).Should(BeTrue())
   266  		os.Unsetenv("FOO")
   267  	})
   268  
   269  	It("podman run limits test", func() {
   270  		SkipIfRootless()
   271  		session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "rtprio=99", "--cap-add=sys_nice", fedoraMinimal, "cat", "/proc/self/sched"})
   272  		session.WaitWithDefaultTimeout()
   273  		Expect(session.ExitCode()).To(Equal(0))
   274  
   275  		session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=2048:2048", fedoraMinimal, "ulimit", "-n"})
   276  		session.WaitWithDefaultTimeout()
   277  		Expect(session.ExitCode()).To(Equal(0))
   278  		Expect(session.OutputToString()).To(ContainSubstring("2048"))
   279  
   280  		session = podmanTest.Podman([]string{"run", "--rm", "--ulimit", "nofile=1024:1028", fedoraMinimal, "ulimit", "-n"})
   281  		session.WaitWithDefaultTimeout()
   282  		Expect(session.ExitCode()).To(Equal(0))
   283  		Expect(session.OutputToString()).To(ContainSubstring("1024"))
   284  
   285  		cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
   286  		Expect(err).To(BeNil())
   287  
   288  		if !cgroupsv2 {
   289  			// --oom-kill-disable not supported on cgroups v2.
   290  			session = podmanTest.Podman([]string{"run", "--rm", "--oom-kill-disable=true", fedoraMinimal, "echo", "memory-hog"})
   291  			session.WaitWithDefaultTimeout()
   292  			Expect(session.ExitCode()).To(Equal(0))
   293  		}
   294  
   295  		session = podmanTest.Podman([]string{"run", "--rm", "--oom-score-adj=100", fedoraMinimal, "cat", "/proc/self/oom_score_adj"})
   296  		session.WaitWithDefaultTimeout()
   297  		Expect(session.ExitCode()).To(Equal(0))
   298  		Expect(session.OutputToString()).To(ContainSubstring("100"))
   299  	})
   300  
   301  	It("podman run limits host test", func() {
   302  		SkipIfRemote()
   303  
   304  		var l syscall.Rlimit
   305  
   306  		err := syscall.Getrlimit(syscall.RLIMIT_NOFILE, &l)
   307  		Expect(err).To(BeNil())
   308  
   309  		session := podmanTest.Podman([]string{"run", "--rm", "--ulimit", "host", fedoraMinimal, "ulimit", "-Hn"})
   310  		session.WaitWithDefaultTimeout()
   311  		Expect(session.ExitCode()).To(Equal(0))
   312  
   313  		ulimitCtrStr := strings.TrimSpace(session.OutputToString())
   314  		ulimitCtr, err := strconv.ParseUint(ulimitCtrStr, 10, 0)
   315  		Expect(err).To(BeNil())
   316  
   317  		Expect(ulimitCtr).Should(BeNumerically(">=", l.Max))
   318  	})
   319  
   320  	It("podman run with cidfile", func() {
   321  		session := podmanTest.Podman([]string{"run", "--cidfile", tempdir + "cidfile", ALPINE, "ls"})
   322  		session.WaitWithDefaultTimeout()
   323  		Expect(session.ExitCode()).To(Equal(0))
   324  		err := os.Remove(tempdir + "cidfile")
   325  		Expect(err).To(BeNil())
   326  	})
   327  
   328  	It("podman run sysctl test", func() {
   329  		SkipIfRootless()
   330  		session := podmanTest.Podman([]string{"run", "--rm", "--sysctl", "net.core.somaxconn=65535", ALPINE, "sysctl", "net.core.somaxconn"})
   331  		session.WaitWithDefaultTimeout()
   332  		Expect(session.ExitCode()).To(Equal(0))
   333  		Expect(session.OutputToString()).To(ContainSubstring("net.core.somaxconn = 65535"))
   334  	})
   335  
   336  	It("podman run blkio-weight test", func() {
   337  		SkipIfRootless()
   338  		cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
   339  		Expect(err).To(BeNil())
   340  
   341  		if !cgroupsv2 {
   342  			if _, err := os.Stat("/sys/fs/cgroup/blkio/blkio.weight"); os.IsNotExist(err) {
   343  				Skip("Kernel does not support blkio.weight")
   344  			}
   345  		}
   346  
   347  		if cgroupsv2 {
   348  			// convert linearly from [10-1000] to [1-10000]
   349  			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"})
   350  			session.WaitWithDefaultTimeout()
   351  			Expect(session.ExitCode()).To(Equal(0))
   352  			Expect(session.OutputToString()).To(ContainSubstring("51"))
   353  		} else {
   354  			session := podmanTest.Podman([]string{"run", "--rm", "--blkio-weight=15", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.weight"})
   355  			session.WaitWithDefaultTimeout()
   356  			Expect(session.ExitCode()).To(Equal(0))
   357  			Expect(session.OutputToString()).To(ContainSubstring("15"))
   358  		}
   359  	})
   360  
   361  	It("podman run device-read-bps test", func() {
   362  		SkipIfRootless()
   363  
   364  		cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
   365  		Expect(err).To(BeNil())
   366  
   367  		var session *PodmanSessionIntegration
   368  
   369  		if cgroupsv2 {
   370  			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"})
   371  		} else {
   372  			session = podmanTest.Podman([]string{"run", "--rm", "--device-read-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_bps_device"})
   373  		}
   374  
   375  		session.WaitWithDefaultTimeout()
   376  		Expect(session.ExitCode()).To(Equal(0))
   377  		if !cgroupsv2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
   378  			Expect(session.OutputToString()).To(ContainSubstring("1048576"))
   379  		}
   380  	})
   381  
   382  	It("podman run device-write-bps test", func() {
   383  		SkipIfRootless()
   384  
   385  		cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
   386  		Expect(err).To(BeNil())
   387  
   388  		var session *PodmanSessionIntegration
   389  
   390  		if cgroupsv2 {
   391  			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"})
   392  		} else {
   393  			session = podmanTest.Podman([]string{"run", "--rm", "--device-write-bps=/dev/zero:1mb", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_bps_device"})
   394  		}
   395  		session.WaitWithDefaultTimeout()
   396  		Expect(session.ExitCode()).To(Equal(0))
   397  		if !cgroupsv2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
   398  			Expect(session.OutputToString()).To(ContainSubstring("1048576"))
   399  		}
   400  	})
   401  
   402  	It("podman run device-read-iops test", func() {
   403  		SkipIfRootless()
   404  
   405  		cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
   406  		Expect(err).To(BeNil())
   407  
   408  		var session *PodmanSessionIntegration
   409  
   410  		if cgroupsv2 {
   411  			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"})
   412  		} else {
   413  			session = podmanTest.Podman([]string{"run", "--rm", "--device-read-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.read_iops_device"})
   414  		}
   415  
   416  		session.WaitWithDefaultTimeout()
   417  		Expect(session.ExitCode()).To(Equal(0))
   418  		if !cgroupsv2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
   419  			Expect(session.OutputToString()).To(ContainSubstring("100"))
   420  		}
   421  	})
   422  
   423  	It("podman run device-write-iops test", func() {
   424  		SkipIfRootless()
   425  
   426  		cgroupsv2, err := cgroups.IsCgroup2UnifiedMode()
   427  		Expect(err).To(BeNil())
   428  
   429  		var session *PodmanSessionIntegration
   430  
   431  		if cgroupsv2 {
   432  			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"})
   433  		} else {
   434  			session = podmanTest.Podman([]string{"run", "--rm", "--device-write-iops=/dev/zero:100", ALPINE, "cat", "/sys/fs/cgroup/blkio/blkio.throttle.write_iops_device"})
   435  		}
   436  
   437  		session.WaitWithDefaultTimeout()
   438  		Expect(session.ExitCode()).To(Equal(0))
   439  		if !cgroupsv2 { // TODO: Test Simplification.  For now, we only care about exit(0) w/ cgroupsv2
   440  			Expect(session.OutputToString()).To(ContainSubstring("100"))
   441  		}
   442  	})
   443  
   444  	It("podman run notify_socket", func() {
   445  		SkipIfRemote()
   446  
   447  		host := GetHostDistributionInfo()
   448  		if host.Distribution != "rhel" && host.Distribution != "centos" && host.Distribution != "fedora" {
   449  			Skip("this test requires a working runc")
   450  		}
   451  		sock := filepath.Join(podmanTest.TempDir, "notify")
   452  		addr := net.UnixAddr{
   453  			Name: sock,
   454  			Net:  "unixgram",
   455  		}
   456  		socket, err := net.ListenUnixgram("unixgram", &addr)
   457  		Expect(err).To(BeNil())
   458  		defer os.Remove(sock)
   459  		defer socket.Close()
   460  
   461  		os.Setenv("NOTIFY_SOCKET", sock)
   462  		defer os.Unsetenv("NOTIFY_SOCKET")
   463  
   464  		session := podmanTest.Podman([]string{"run", ALPINE, "printenv", "NOTIFY_SOCKET"})
   465  		session.WaitWithDefaultTimeout()
   466  		Expect(session.ExitCode()).To(Equal(0))
   467  		Expect(len(session.OutputToStringArray())).To(BeNumerically(">", 0))
   468  	})
   469  
   470  	It("podman run log-opt", func() {
   471  		log := filepath.Join(podmanTest.TempDir, "/container.log")
   472  		session := podmanTest.Podman([]string{"run", "--rm", "--log-opt", fmt.Sprintf("path=%s", log), ALPINE, "ls"})
   473  		session.WaitWithDefaultTimeout()
   474  		Expect(session.ExitCode()).To(Equal(0))
   475  		_, err := os.Stat(log)
   476  		Expect(err).To(BeNil())
   477  		_ = os.Remove(log)
   478  	})
   479  
   480  	It("podman run tagged image", func() {
   481  		podmanTest.RestoreArtifact(BB)
   482  		tag := podmanTest.PodmanNoCache([]string{"tag", "busybox", "bb"})
   483  		tag.WaitWithDefaultTimeout()
   484  		Expect(tag.ExitCode()).To(Equal(0))
   485  
   486  		session := podmanTest.PodmanNoCache([]string{"run", "--rm", "bb", "ls"})
   487  		session.WaitWithDefaultTimeout()
   488  		Expect(session.ExitCode()).To(Equal(0))
   489  	})
   490  
   491  	It("podman test hooks", func() {
   492  		hcheck := "/run/hookscheck"
   493  		hooksDir := tempdir + "/hooks"
   494  		os.Mkdir(hooksDir, 0755)
   495  		fileutils.CopyFile("hooks/hooks.json", hooksDir)
   496  		os.Setenv("HOOK_OPTION", fmt.Sprintf("--hooks-dir=%s", hooksDir))
   497  		os.Remove(hcheck)
   498  		session := podmanTest.Podman([]string{"run", ALPINE, "ls"})
   499  		session.Wait(10)
   500  		os.Unsetenv("HOOK_OPTION")
   501  		Expect(session.ExitCode()).To(Equal(0))
   502  	})
   503  
   504  	It("podman run with secrets", func() {
   505  		containersDir := filepath.Join(podmanTest.TempDir, "containers")
   506  		err := os.MkdirAll(containersDir, 0755)
   507  		Expect(err).To(BeNil())
   508  
   509  		secretsDir := filepath.Join(podmanTest.TempDir, "rhel", "secrets")
   510  		err = os.MkdirAll(secretsDir, 0755)
   511  		Expect(err).To(BeNil())
   512  
   513  		mountsFile := filepath.Join(containersDir, "mounts.conf")
   514  		mountString := secretsDir + ":/run/secrets"
   515  		err = ioutil.WriteFile(mountsFile, []byte(mountString), 0755)
   516  		Expect(err).To(BeNil())
   517  
   518  		secretsFile := filepath.Join(secretsDir, "test.txt")
   519  		secretsString := "Testing secrets mount. I am mounted!"
   520  		err = ioutil.WriteFile(secretsFile, []byte(secretsString), 0755)
   521  		Expect(err).To(BeNil())
   522  
   523  		targetDir := tempdir + "/symlink/target"
   524  		err = os.MkdirAll(targetDir, 0755)
   525  		Expect(err).To(BeNil())
   526  		keyFile := filepath.Join(targetDir, "key.pem")
   527  		err = ioutil.WriteFile(keyFile, []byte(mountString), 0755)
   528  		Expect(err).To(BeNil())
   529  		execSession := SystemExec("ln", []string{"-s", targetDir, filepath.Join(secretsDir, "mysymlink")})
   530  		Expect(execSession.ExitCode()).To(Equal(0))
   531  
   532  		session := podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "cat", "/run/secrets/test.txt"})
   533  		session.WaitWithDefaultTimeout()
   534  		Expect(session.ExitCode()).To(Equal(0))
   535  		Expect(session.OutputToString()).To(Equal(secretsString))
   536  
   537  		session = podmanTest.Podman([]string{"--default-mounts-file=" + mountsFile, "run", "--rm", ALPINE, "ls", "/run/secrets/mysymlink"})
   538  		session.WaitWithDefaultTimeout()
   539  		Expect(session.ExitCode()).To(Equal(0))
   540  		Expect(session.OutputToString()).To(ContainSubstring("key.pem"))
   541  	})
   542  
   543  	It("podman run with FIPS mode secrets", func() {
   544  		SkipIfRootless()
   545  		fipsFile := "/etc/system-fips"
   546  		err = ioutil.WriteFile(fipsFile, []byte{}, 0755)
   547  		Expect(err).To(BeNil())
   548  
   549  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "ls", "/run/secrets"})
   550  		session.WaitWithDefaultTimeout()
   551  		Expect(session.ExitCode()).To(Equal(0))
   552  		Expect(session.OutputToString()).To(ContainSubstring("system-fips"))
   553  
   554  		err = os.Remove(fipsFile)
   555  		Expect(err).To(BeNil())
   556  	})
   557  
   558  	It("podman run without group-add", func() {
   559  		SkipIfRootless()
   560  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"})
   561  		session.WaitWithDefaultTimeout()
   562  		Expect(session.ExitCode()).To(Equal(0))
   563  		Expect(session.OutputToString()).To(Equal("uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)"))
   564  	})
   565  
   566  	It("podman run with group-add", func() {
   567  		SkipIfRootless()
   568  		session := podmanTest.Podman([]string{"run", "--rm", "--group-add=audio", "--group-add=nogroup", "--group-add=777", ALPINE, "id"})
   569  		session.WaitWithDefaultTimeout()
   570  		Expect(session.ExitCode()).To(Equal(0))
   571  		Expect(session.OutputToString()).To(Equal("uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),18(audio),20(dialout),26(tape),27(video),777,65533(nogroup)"))
   572  	})
   573  
   574  	It("podman run with user (default)", func() {
   575  		SkipIfRootless()
   576  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "id"})
   577  		session.WaitWithDefaultTimeout()
   578  		Expect(session.ExitCode()).To(Equal(0))
   579  		Expect(session.OutputToString()).To(Equal("uid=0(root) gid=0(root) groups=0(root),1(bin),2(daemon),3(sys),4(adm),6(disk),10(wheel),11(floppy),20(dialout),26(tape),27(video)"))
   580  	})
   581  
   582  	It("podman run with user (integer, not in /etc/passwd)", func() {
   583  		session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "id"})
   584  		session.WaitWithDefaultTimeout()
   585  		Expect(session.ExitCode()).To(Equal(0))
   586  		Expect(session.OutputToString()).To(Equal("uid=1234(1234) gid=0(root)"))
   587  	})
   588  
   589  	It("podman run with user (integer, in /etc/passwd)", func() {
   590  		SkipIfRootless()
   591  		session := podmanTest.Podman([]string{"run", "--rm", "--user=8", ALPINE, "id"})
   592  		session.WaitWithDefaultTimeout()
   593  		Expect(session.ExitCode()).To(Equal(0))
   594  		Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=12(mail) groups=12(mail)"))
   595  	})
   596  
   597  	It("podman run with user (username)", func() {
   598  		SkipIfRootless()
   599  		session := podmanTest.Podman([]string{"run", "--rm", "--user=mail", ALPINE, "id"})
   600  		session.WaitWithDefaultTimeout()
   601  		Expect(session.ExitCode()).To(Equal(0))
   602  		Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=12(mail) groups=12(mail)"))
   603  	})
   604  
   605  	It("podman run with user:group (username:integer)", func() {
   606  		session := podmanTest.Podman([]string{"run", "--rm", "--user=mail:21", ALPINE, "id"})
   607  		session.WaitWithDefaultTimeout()
   608  		Expect(session.ExitCode()).To(Equal(0))
   609  		Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp)"))
   610  	})
   611  
   612  	It("podman run with user:group (integer:groupname)", func() {
   613  		session := podmanTest.Podman([]string{"run", "--rm", "--user=8:ftp", ALPINE, "id"})
   614  		session.WaitWithDefaultTimeout()
   615  		Expect(session.ExitCode()).To(Equal(0))
   616  		Expect(session.OutputToString()).To(Equal("uid=8(mail) gid=21(ftp)"))
   617  	})
   618  
   619  	It("podman run with user, verify caps dropped", func() {
   620  		session := podmanTest.Podman([]string{"run", "--rm", "--user=1234", ALPINE, "grep", "CapEff", "/proc/self/status"})
   621  		session.WaitWithDefaultTimeout()
   622  		Expect(session.ExitCode()).To(Equal(0))
   623  		capEff := strings.Split(session.OutputToString(), " ")
   624  		Expect("0000000000000000").To(Equal(capEff[1]))
   625  	})
   626  
   627  	It("podman run with attach stdin outputs container ID", func() {
   628  		session := podmanTest.Podman([]string{"run", "--attach", "stdin", ALPINE, "printenv"})
   629  		session.WaitWithDefaultTimeout()
   630  		Expect(session.ExitCode()).To(Equal(0))
   631  		ps := podmanTest.Podman([]string{"ps", "-aq", "--no-trunc"})
   632  		ps.WaitWithDefaultTimeout()
   633  		Expect(ps.ExitCode()).To(Equal(0))
   634  		Expect(ps.LineInOutputContains(session.OutputToString())).To(BeTrue())
   635  	})
   636  
   637  	It("podman run with attach stdout does not print stderr", func() {
   638  		session := podmanTest.Podman([]string{"run", "--rm", "--attach", "stdout", ALPINE, "ls", "/doesnotexist"})
   639  		session.WaitWithDefaultTimeout()
   640  		Expect(session.OutputToString()).To(Equal(""))
   641  	})
   642  
   643  	It("podman run with attach stderr does not print stdout", func() {
   644  		session := podmanTest.Podman([]string{"run", "--rm", "--attach", "stderr", ALPINE, "ls", "/"})
   645  		session.WaitWithDefaultTimeout()
   646  		Expect(session.ExitCode()).To(Equal(0))
   647  		Expect(session.OutputToString()).To(Equal(""))
   648  	})
   649  
   650  	It("podman run attach nonsense errors", func() {
   651  		session := podmanTest.Podman([]string{"run", "--rm", "--attach", "asdfasdf", ALPINE, "ls", "/"})
   652  		session.WaitWithDefaultTimeout()
   653  		Expect(session.ExitCode()).To(Equal(125))
   654  	})
   655  
   656  	It("podman run exit code on failure to exec", func() {
   657  		session := podmanTest.Podman([]string{"run", ALPINE, "/etc"})
   658  		session.WaitWithDefaultTimeout()
   659  		Expect(session.ExitCode()).To(Equal(126))
   660  	})
   661  
   662  	It("podman run error on exec", func() {
   663  		session := podmanTest.Podman([]string{"run", ALPINE, "sh", "-c", "exit 100"})
   664  		session.WaitWithDefaultTimeout()
   665  		Expect(session.ExitCode()).To(Equal(100))
   666  	})
   667  
   668  	It("podman run with built-in volume image", func() {
   669  		session := podmanTest.Podman([]string{"run", "--rm", redis, "ls"})
   670  		session.WaitWithDefaultTimeout()
   671  		Expect(session.ExitCode()).To(Equal(0))
   672  
   673  		dockerfile := `FROM busybox
   674  RUN mkdir -p /myvol/data && chown -R mail.0 /myvol
   675  VOLUME ["/myvol/data"]
   676  USER mail`
   677  
   678  		podmanTest.BuildImage(dockerfile, "test", "false")
   679  		session = podmanTest.Podman([]string{"run", "--rm", "test", "ls", "-al", "/myvol/data"})
   680  		session.WaitWithDefaultTimeout()
   681  		Expect(session.ExitCode()).To(Equal(0))
   682  		Expect(session.OutputToString()).To(ContainSubstring("mail root"))
   683  	})
   684  
   685  	It("podman run --volumes-from flag", func() {
   686  		vol := filepath.Join(podmanTest.TempDir, "vol-test")
   687  		err := os.MkdirAll(vol, 0755)
   688  		Expect(err).To(BeNil())
   689  
   690  		volFile := filepath.Join(vol, "test.txt")
   691  		data := "Testing --volumes-from!!!"
   692  		err = ioutil.WriteFile(volFile, []byte(data), 0755)
   693  		Expect(err).To(BeNil())
   694  
   695  		session := podmanTest.Podman([]string{"create", "--volume", vol + ":/myvol", redis, "sh"})
   696  		session.WaitWithDefaultTimeout()
   697  		Expect(session.ExitCode()).To(Equal(0))
   698  		ctrID := session.OutputToString()
   699  
   700  		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "echo", "'testing read-write!' >> myvol/test.txt"})
   701  		session.WaitWithDefaultTimeout()
   702  		Expect(session.ExitCode()).To(Equal(0))
   703  
   704  		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID + ":z", ALPINE, "ls"})
   705  		session.WaitWithDefaultTimeout()
   706  		Expect(session.ExitCode()).To(Equal(0))
   707  	})
   708  
   709  	It("podman run --volumes-from flag with built-in volumes", func() {
   710  		session := podmanTest.Podman([]string{"create", redis, "sh"})
   711  		session.WaitWithDefaultTimeout()
   712  		Expect(session.ExitCode()).To(Equal(0))
   713  		ctrID := session.OutputToString()
   714  
   715  		session = podmanTest.Podman([]string{"run", "--volumes-from", ctrID, ALPINE, "ls"})
   716  		session.WaitWithDefaultTimeout()
   717  		Expect(session.ExitCode()).To(Equal(0))
   718  		Expect(session.OutputToString()).To(ContainSubstring("data"))
   719  	})
   720  
   721  	It("podman run --volumes flag with multiple volumes", func() {
   722  		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
   723  		err := os.MkdirAll(vol1, 0755)
   724  		Expect(err).To(BeNil())
   725  		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
   726  		err = os.MkdirAll(vol2, 0755)
   727  		Expect(err).To(BeNil())
   728  
   729  		session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", ALPINE, "touch", "/myvol2/foo.txt"})
   730  		session.WaitWithDefaultTimeout()
   731  		Expect(session.ExitCode()).To(Equal(0))
   732  	})
   733  
   734  	It("podman run --volumes flag with empty host dir", func() {
   735  		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
   736  		err := os.MkdirAll(vol1, 0755)
   737  		Expect(err).To(BeNil())
   738  
   739  		session := podmanTest.Podman([]string{"run", "--volume", ":/myvol1:z", ALPINE, "touch", "/myvol2/foo.txt"})
   740  		session.WaitWithDefaultTimeout()
   741  		Expect(session).To(ExitWithError())
   742  		Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty"))
   743  		session = podmanTest.Podman([]string{"run", "--volume", vol1 + ":", ALPINE, "touch", "/myvol2/foo.txt"})
   744  		session.WaitWithDefaultTimeout()
   745  		Expect(session).To(ExitWithError())
   746  		Expect(session.ErrorToString()).To(ContainSubstring("directory cannot be empty"))
   747  	})
   748  
   749  	It("podman run --mount flag with multiple mounts", func() {
   750  		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
   751  		err := os.MkdirAll(vol1, 0755)
   752  		Expect(err).To(BeNil())
   753  		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
   754  		err = os.MkdirAll(vol2, 0755)
   755  		Expect(err).To(BeNil())
   756  
   757  		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"})
   758  		session.WaitWithDefaultTimeout()
   759  		Expect(session.ExitCode()).To(Equal(0))
   760  	})
   761  
   762  	It("podman run findmnt nothing shared", func() {
   763  		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
   764  		err := os.MkdirAll(vol1, 0755)
   765  		Expect(err).To(BeNil())
   766  		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
   767  		err = os.MkdirAll(vol2, 0755)
   768  		Expect(err).To(BeNil())
   769  
   770  		session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:z", fedoraMinimal, "findmnt", "-o", "TARGET,PROPAGATION"})
   771  		session.WaitWithDefaultTimeout()
   772  		Expect(session.ExitCode()).To(Equal(0))
   773  		match, _ := session.GrepString("shared")
   774  		Expect(match).Should(BeFalse())
   775  	})
   776  
   777  	It("podman run findmnt shared", func() {
   778  		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
   779  		err := os.MkdirAll(vol1, 0755)
   780  		Expect(err).To(BeNil())
   781  		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
   782  		err = os.MkdirAll(vol2, 0755)
   783  		Expect(err).To(BeNil())
   784  
   785  		session := podmanTest.Podman([]string{"run", "--volume", vol1 + ":/myvol1:z", "--volume", vol2 + ":/myvol2:shared,z", fedoraMinimal, "findmnt", "-o", "TARGET,PROPAGATION"})
   786  		session.WaitWithDefaultTimeout()
   787  		Expect(session.ExitCode()).To(Equal(0))
   788  		match, shared := session.GrepString("shared")
   789  		Expect(match).Should(BeTrue())
   790  		// make sure it's only shared (and not 'shared,slave')
   791  		isSharedOnly := !strings.Contains(shared[0], "shared,")
   792  		Expect(isSharedOnly).Should(BeTrue())
   793  	})
   794  
   795  	It("podman run --mount type=bind,bind-nonrecursive", func() {
   796  		SkipIfRootless()
   797  		session := podmanTest.Podman([]string{"run", "--mount", "type=bind,bind-nonrecursive,slave,src=/,target=/host", fedoraMinimal, "findmnt", "-nR", "/host"})
   798  		session.WaitWithDefaultTimeout()
   799  		Expect(session.ExitCode()).To(Equal(0))
   800  		Expect(len(session.OutputToStringArray())).To(Equal(1))
   801  	})
   802  
   803  	It("podman run --pod automatically", func() {
   804  		session := podmanTest.Podman([]string{"run", "--pod", "new:foobar", ALPINE, "ls"})
   805  		session.WaitWithDefaultTimeout()
   806  		Expect(session.ExitCode()).To(Equal(0))
   807  
   808  		check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
   809  		check.WaitWithDefaultTimeout()
   810  		match, _ := check.GrepString("foobar")
   811  		Expect(match).To(BeTrue())
   812  	})
   813  
   814  	It("podman run --rm should work", func() {
   815  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "ls"})
   816  		session.WaitWithDefaultTimeout()
   817  		Expect(session.ExitCode()).To(Equal(0))
   818  
   819  		numContainers := podmanTest.NumberOfContainers()
   820  		Expect(numContainers).To(Equal(0))
   821  	})
   822  
   823  	It("podman run --rm failed container should delete itself", func() {
   824  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "foo"})
   825  		session.WaitWithDefaultTimeout()
   826  		Expect(session).To(ExitWithError())
   827  
   828  		numContainers := podmanTest.NumberOfContainers()
   829  		Expect(numContainers).To(Equal(0))
   830  	})
   831  
   832  	It("podman run failed container should NOT delete itself", func() {
   833  		session := podmanTest.Podman([]string{"run", ALPINE, "foo"})
   834  		session.WaitWithDefaultTimeout()
   835  		Expect(session).To(ExitWithError())
   836  
   837  		numContainers := podmanTest.NumberOfContainers()
   838  		Expect(numContainers).To(Equal(1))
   839  	})
   840  	It("podman run readonly container should NOT mount /dev/shm read/only", func() {
   841  		session := podmanTest.Podman([]string{"run", "--read-only", ALPINE, "mount"})
   842  		session.WaitWithDefaultTimeout()
   843  		Expect(session.ExitCode()).To(Equal(0))
   844  
   845  		Expect(session.OutputToString()).To(Not(ContainSubstring("/dev/shm type tmpfs (ro,")))
   846  	})
   847  
   848  	It("podman run with bad healthcheck retries", func() {
   849  		session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-retries", "0", ALPINE, "top"})
   850  		session.Wait()
   851  		Expect(session).To(ExitWithError())
   852  		Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-retries must be greater than 0"))
   853  	})
   854  
   855  	It("podman run with bad healthcheck timeout", func() {
   856  		session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-timeout", "0s", ALPINE, "top"})
   857  		session.WaitWithDefaultTimeout()
   858  		Expect(session).To(ExitWithError())
   859  		Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-timeout must be at least 1 second"))
   860  	})
   861  
   862  	It("podman run with bad healthcheck start-period", func() {
   863  		session := podmanTest.Podman([]string{"run", "-dt", "--health-cmd", "[\"foo\"]", "--health-start-period", "-1s", ALPINE, "top"})
   864  		session.WaitWithDefaultTimeout()
   865  		Expect(session).To(ExitWithError())
   866  		Expect(session.ErrorToString()).To(ContainSubstring("healthcheck-start-period must be 0 seconds or greater"))
   867  	})
   868  
   869  	It("podman run with --add-host and --no-hosts fails", func() {
   870  		session := podmanTest.Podman([]string{"run", "-dt", "--add-host", "test1:127.0.0.1", "--no-hosts", ALPINE, "top"})
   871  		session.WaitWithDefaultTimeout()
   872  		Expect(session).To(ExitWithError())
   873  	})
   874  
   875  	It("podman run --http-proxy test", func() {
   876  		os.Setenv("http_proxy", "1.2.3.4")
   877  		session := podmanTest.Podman([]string{"run", "--rm", ALPINE, "printenv", "http_proxy"})
   878  		session.WaitWithDefaultTimeout()
   879  		Expect(session.ExitCode()).To(Equal(0))
   880  		match, _ := session.GrepString("1.2.3.4")
   881  		Expect(match).Should(BeTrue())
   882  
   883  		session = podmanTest.Podman([]string{"run", "--http-proxy=false", ALPINE, "printenv", "http_proxy"})
   884  		session.WaitWithDefaultTimeout()
   885  		Expect(session.ExitCode()).To(Equal(1))
   886  		Expect(session.OutputToString()).To(Equal(""))
   887  		os.Unsetenv("http_proxy")
   888  	})
   889  
   890  	It("podman run with restart-policy always restarts containers", func() {
   891  
   892  		testDir := filepath.Join(podmanTest.RunRoot, "restart-test")
   893  		err := os.MkdirAll(testDir, 0755)
   894  		Expect(err).To(BeNil())
   895  
   896  		aliveFile := filepath.Join(testDir, "running")
   897  		file, err := os.Create(aliveFile)
   898  		Expect(err).To(BeNil())
   899  		file.Close()
   900  
   901  		session := podmanTest.Podman([]string{"run", "-dt", "--restart", "always", "-v", fmt.Sprintf("%s:/tmp/runroot:Z", testDir), fedoraMinimal, "bash", "-c", "date +%N > /tmp/runroot/ran && while test -r /tmp/runroot/running; do sleep 0.1s; done"})
   902  
   903  		found := false
   904  		testFile := filepath.Join(testDir, "ran")
   905  		for i := 0; i < 10; i++ {
   906  			time.Sleep(1 * time.Second)
   907  			if _, err := os.Stat(testFile); err == nil {
   908  				found = true
   909  				err = os.Remove(testFile)
   910  				Expect(err).To(BeNil())
   911  				break
   912  			}
   913  		}
   914  		Expect(found).To(BeTrue())
   915  
   916  		err = os.Remove(aliveFile)
   917  		Expect(err).To(BeNil())
   918  
   919  		session.WaitWithDefaultTimeout()
   920  
   921  		// 10 seconds to restart the container
   922  		found = false
   923  		for i := 0; i < 10; i++ {
   924  			time.Sleep(1 * time.Second)
   925  			if _, err := os.Stat(testFile); err == nil {
   926  				found = true
   927  				break
   928  			}
   929  		}
   930  		Expect(found).To(BeTrue())
   931  	})
   932  
   933  	It("podman run with cgroups=disabled runs without cgroups", func() {
   934  		SkipIfRemote()
   935  		SkipIfRootless()
   936  		// Only works on crun
   937  		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
   938  			Skip("Test only works on crun")
   939  		}
   940  
   941  		curCgroupsBytes, err := ioutil.ReadFile("/proc/self/cgroup")
   942  		Expect(err).To(BeNil())
   943  		var curCgroups string = string(curCgroupsBytes)
   944  		fmt.Printf("Output:\n%s\n", curCgroups)
   945  		Expect(curCgroups).To(Not(Equal("")))
   946  
   947  		ctrName := "testctr"
   948  		container := podmanTest.Podman([]string{"run", "--name", ctrName, "-d", "--cgroups=disabled", ALPINE, "top"})
   949  		container.WaitWithDefaultTimeout()
   950  		Expect(container.ExitCode()).To(Equal(0))
   951  
   952  		// Get PID and get cgroups of that PID
   953  		inspectOut := podmanTest.InspectContainer(ctrName)
   954  		Expect(len(inspectOut)).To(Equal(1))
   955  		pid := inspectOut[0].State.Pid
   956  		Expect(pid).To(Not(Equal(0)))
   957  		Expect(inspectOut[0].HostConfig.CgroupParent).To(Equal(""))
   958  
   959  		ctrCgroupsBytes, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
   960  		Expect(err).To(BeNil())
   961  		var ctrCgroups string = string(ctrCgroupsBytes)
   962  		fmt.Printf("Output\n:%s\n", ctrCgroups)
   963  		Expect(curCgroups).To(Equal(ctrCgroups))
   964  	})
   965  
   966  	It("podman run with cgroups=enabled makes cgroups", func() {
   967  		SkipIfRemote()
   968  		SkipIfRootless()
   969  		// Only works on crun
   970  		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
   971  			Skip("Test only works on crun")
   972  		}
   973  
   974  		curCgroupsBytes, err := ioutil.ReadFile("/proc/self/cgroup")
   975  		Expect(err).To(BeNil())
   976  		var curCgroups string = string(curCgroupsBytes)
   977  		fmt.Printf("Output:\n%s\n", curCgroups)
   978  		Expect(curCgroups).To(Not(Equal("")))
   979  
   980  		ctrName := "testctr"
   981  		container := podmanTest.Podman([]string{"run", "--name", ctrName, "-d", "--cgroups=enabled", ALPINE, "top"})
   982  		container.WaitWithDefaultTimeout()
   983  		Expect(container.ExitCode()).To(Equal(0))
   984  
   985  		// Get PID and get cgroups of that PID
   986  		inspectOut := podmanTest.InspectContainer(ctrName)
   987  		Expect(len(inspectOut)).To(Equal(1))
   988  		pid := inspectOut[0].State.Pid
   989  		Expect(pid).To(Not(Equal(0)))
   990  
   991  		ctrCgroupsBytes, err := ioutil.ReadFile(fmt.Sprintf("/proc/%d/cgroup", pid))
   992  		Expect(err).To(BeNil())
   993  		var ctrCgroups string = string(ctrCgroupsBytes)
   994  		fmt.Printf("Output\n:%s\n", ctrCgroups)
   995  		Expect(curCgroups).To(Not(Equal(ctrCgroups)))
   996  	})
   997  
   998  	It("podman run with cgroups=garbage errors", func() {
   999  		session := podmanTest.Podman([]string{"run", "-d", "--cgroups=garbage", ALPINE, "top"})
  1000  		session.WaitWithDefaultTimeout()
  1001  		Expect(session).To(ExitWithError())
  1002  	})
  1003  
  1004  	It("podman run should fail with nonexist authfile", func() {
  1005  		SkipIfRemote()
  1006  		session := podmanTest.Podman([]string{"run", "--authfile", "/tmp/nonexist", ALPINE, "ls"})
  1007  		session.WaitWithDefaultTimeout()
  1008  		Expect(session.ExitCode()).To(Not(Equal(0)))
  1009  	})
  1010  
  1011  	It("podman run --device-cgroup-rule", func() {
  1012  		SkipIfRemote()
  1013  		SkipIfRootless()
  1014  		deviceCgroupRule := "c 42:* rwm"
  1015  		session := podmanTest.Podman([]string{"run", "--name", "test", "-d", "--device-cgroup-rule", deviceCgroupRule, ALPINE, "top"})
  1016  		session.WaitWithDefaultTimeout()
  1017  		Expect(session.ExitCode()).To(Equal(0))
  1018  		session = podmanTest.Podman([]string{"exec", "test", "mknod", "newDev", "c", "42", "1"})
  1019  		session.WaitWithDefaultTimeout()
  1020  		Expect(session.ExitCode()).To(Equal(0))
  1021  	})
  1022  })