github.com/containers/podman/v5@v5.1.0-rc1/test/e2e/create_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"runtime"
     8  	"strconv"
     9  	"strings"
    10  
    11  	. "github.com/containers/podman/v5/test/utils"
    12  	"github.com/containers/storage/pkg/stringid"
    13  	. "github.com/onsi/ginkgo/v2"
    14  	. "github.com/onsi/gomega"
    15  	. "github.com/onsi/gomega/gexec"
    16  )
    17  
    18  var _ = Describe("Podman create", func() {
    19  
    20  	It("podman create container based on a local image", func() {
    21  		session := podmanTest.Podman([]string{"create", "--name", "local_image_test", ALPINE, "ls"})
    22  		session.WaitWithDefaultTimeout()
    23  		cid := session.OutputToString()
    24  		Expect(session).Should(ExitCleanly())
    25  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
    26  
    27  		check := podmanTest.Podman([]string{"inspect", "local_image_test"})
    28  		check.WaitWithDefaultTimeout()
    29  		data := check.InspectContainerToJSON()
    30  		Expect(data[0].ID).To(ContainSubstring(cid))
    31  	})
    32  
    33  	It("podman create container based on a remote image", func() {
    34  		session := podmanTest.Podman([]string{"create", BB_GLIBC, "ls"})
    35  		session.WaitWithDefaultTimeout()
    36  		Expect(session).Should(Exit(0))
    37  		Expect(session.ErrorToString()).To(ContainSubstring("Trying to pull " + BB_GLIBC))
    38  		Expect(session.ErrorToString()).To(ContainSubstring("Writing manifest to image destination"))
    39  
    40  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
    41  	})
    42  
    43  	It("podman container create --tls-verify", func() {
    44  		port := "5040"
    45  		lock := GetPortLock(port)
    46  		defer lock.Unlock()
    47  		session := podmanTest.Podman([]string{"run", "-d", "--name", "registry", "-p", port + ":5000", REGISTRY_IMAGE, "/entrypoint.sh", "/etc/docker/registry/config.yml"})
    48  		session.WaitWithDefaultTimeout()
    49  		Expect(session).Should(ExitCleanly())
    50  
    51  		if !WaitContainerReady(podmanTest, "registry", "listening on", 20, 1) {
    52  			Fail("Cannot start docker registry.")
    53  		}
    54  
    55  		pushedImage := "localhost:" + port + "/pushed" + strings.ToLower(RandomString(5)) + ":" + RandomString(8)
    56  		push := podmanTest.Podman([]string{"push", "--tls-verify=false", ALPINE, pushedImage})
    57  		push.WaitWithDefaultTimeout()
    58  		Expect(push).To(Exit(0))
    59  		Expect(push.ErrorToString()).To(ContainSubstring("Writing manifest to image destination"))
    60  
    61  		create := podmanTest.Podman([]string{"container", "create", pushedImage})
    62  		create.WaitWithDefaultTimeout()
    63  		Expect(create).Should(ExitWithError(125, "http: server gave HTTP response to HTTPS client"))
    64  		Expect(create.ErrorToString()).To(ContainSubstring("pinging container registry localhost:" + port))
    65  
    66  		create = podmanTest.Podman([]string{"create", "--tls-verify=false", pushedImage, "echo", "got here"})
    67  		create.WaitWithDefaultTimeout()
    68  		Expect(create).Should(Exit(0))
    69  		Expect(create.ErrorToString()).To(ContainSubstring("Trying to pull " + pushedImage))
    70  	})
    71  
    72  	It("podman create using short options", func() {
    73  		session := podmanTest.Podman([]string{"create", ALPINE, "ls"})
    74  		session.WaitWithDefaultTimeout()
    75  		Expect(session).Should(ExitCleanly())
    76  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
    77  	})
    78  
    79  	It("podman create using existing name", func() {
    80  		session := podmanTest.Podman([]string{"create", "--name=foo", ALPINE, "ls"})
    81  		session.WaitWithDefaultTimeout()
    82  		Expect(session).Should(ExitCleanly())
    83  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
    84  
    85  		session = podmanTest.Podman([]string{"create", "--name=foo", ALPINE, "ls"})
    86  		session.WaitWithDefaultTimeout()
    87  		Expect(session).Should(ExitWithError(125, `creating container storage: the container name "foo" is already in use by`))
    88  	})
    89  
    90  	It("podman create adds rdt-class", func() {
    91  		session := podmanTest.Podman([]string{"create", "--rdt-class", "COS1", "--name", "rdt_test", ALPINE, "ls"})
    92  		session.WaitWithDefaultTimeout()
    93  		Expect(session).Should(ExitCleanly())
    94  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
    95  
    96  		check := podmanTest.Podman([]string{"inspect", "rdt_test"})
    97  		check.WaitWithDefaultTimeout()
    98  		data := check.InspectContainerToJSON()
    99  		Expect(data[0].HostConfig.IntelRdtClosID).To(Equal("COS1"))
   100  	})
   101  
   102  	It("podman create adds annotation", func() {
   103  		session := podmanTest.Podman([]string{"create", "--annotation", "HELLO=WORLD,WithComma", "--name", "annotate_test", ALPINE, "ls"})
   104  		session.WaitWithDefaultTimeout()
   105  		Expect(session).Should(ExitCleanly())
   106  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   107  
   108  		check := podmanTest.Podman([]string{"inspect", "annotate_test"})
   109  		check.WaitWithDefaultTimeout()
   110  		data := check.InspectContainerToJSON()
   111  		Expect(data[0].Config.Annotations).To(HaveKeyWithValue("HELLO", "WORLD,WithComma"))
   112  	})
   113  
   114  	It("podman create --entrypoint command", func() {
   115  		session := podmanTest.Podman([]string{"create", "--name", "entrypoint_test", "--entrypoint", "/bin/foobar", ALPINE})
   116  		session.WaitWithDefaultTimeout()
   117  		Expect(session).Should(ExitCleanly())
   118  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   119  
   120  		result := podmanTest.Podman([]string{"inspect", "entrypoint_test", "--format", "{{.Config.Entrypoint}}"})
   121  		result.WaitWithDefaultTimeout()
   122  		Expect(result).Should(ExitCleanly())
   123  		Expect(result.OutputToString()).To(Equal("[/bin/foobar]"))
   124  	})
   125  
   126  	It("podman create --entrypoint \"\"", func() {
   127  		session := podmanTest.Podman([]string{"create", "--entrypoint", "", ALPINE, "ls"})
   128  		session.WaitWithDefaultTimeout()
   129  		Expect(session).Should(ExitCleanly())
   130  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   131  
   132  		result := podmanTest.Podman([]string{"inspect", session.OutputToString(), "--format", "{{.Config.Entrypoint}}"})
   133  		result.WaitWithDefaultTimeout()
   134  		Expect(result).Should(ExitCleanly())
   135  		Expect(result.OutputToString()).To(Equal("[]"))
   136  	})
   137  
   138  	It("podman create --entrypoint json", func() {
   139  		jsonString := `[ "/bin/foo", "-c"]`
   140  		session := podmanTest.Podman([]string{"create", "--name", "entrypoint_json", "--entrypoint", jsonString, ALPINE})
   141  		session.WaitWithDefaultTimeout()
   142  		Expect(session).Should(ExitCleanly())
   143  		Expect(podmanTest.NumberOfContainers()).To(Equal(1))
   144  
   145  		result := podmanTest.Podman([]string{"inspect", "entrypoint_json", "--format", "{{.Config.Entrypoint}}"})
   146  		result.WaitWithDefaultTimeout()
   147  		Expect(result).Should(ExitCleanly())
   148  		Expect(result.OutputToString()).To(Equal("[/bin/foo -c]"))
   149  	})
   150  
   151  	It("podman create --mount flag with multiple mounts", func() {
   152  		vol1 := filepath.Join(podmanTest.TempDir, "vol-test1")
   153  		err := os.MkdirAll(vol1, 0755)
   154  		Expect(err).ToNot(HaveOccurred())
   155  		vol2 := filepath.Join(podmanTest.TempDir, "vol-test2")
   156  		err = os.MkdirAll(vol2, 0755)
   157  		Expect(err).ToNot(HaveOccurred())
   158  
   159  		session := podmanTest.Podman([]string{"create", "--name", "test", "--mount", "type=bind,src=" + vol1 + ",target=/myvol1,z", "--mount", "type=bind,src=" + vol2 + ",target=/myvol2,z", ALPINE, "touch", "/myvol2/foo.txt"})
   160  		session.WaitWithDefaultTimeout()
   161  		Expect(session).Should(ExitCleanly())
   162  
   163  		session = podmanTest.Podman([]string{"start", "-a", "test"})
   164  		session.WaitWithDefaultTimeout()
   165  		Expect(session).Should(ExitCleanly())
   166  		Expect(session.OutputToString()).ToNot(ContainSubstring("cannot touch"))
   167  	})
   168  
   169  	It("podman create with --mount flag", func() {
   170  		if podmanTest.Host.Arch == "ppc64le" {
   171  			Skip("skip failing test on ppc64le")
   172  		}
   173  
   174  		mountPath := filepath.Join(podmanTest.TempDir, "secrets")
   175  		err := os.Mkdir(mountPath, 0755)
   176  		Expect(err).ToNot(HaveOccurred())
   177  		session := podmanTest.Podman([]string{"create", "--name", "test", "--mount", fmt.Sprintf("type=bind,src=%s,target=/create/test", mountPath), ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
   178  		session.WaitWithDefaultTimeout()
   179  		Expect(session).Should(ExitCleanly())
   180  		session = podmanTest.Podman([]string{"start", "-a", "test"})
   181  		session.WaitWithDefaultTimeout()
   182  		Expect(session).Should(ExitCleanly())
   183  		Expect(session.OutputToString()).To(ContainSubstring("/create/test rw"))
   184  
   185  		session = podmanTest.Podman([]string{"create", "--name", "test_ro", "--mount", fmt.Sprintf("type=bind,src=%s,target=/create/test,ro", mountPath), ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
   186  		session.WaitWithDefaultTimeout()
   187  		Expect(session).Should(ExitCleanly())
   188  		session = podmanTest.Podman([]string{"start", "-a", "test_ro"})
   189  		session.WaitWithDefaultTimeout()
   190  		Expect(session).Should(ExitCleanly())
   191  		Expect(session.OutputToString()).To(ContainSubstring("/create/test ro"))
   192  
   193  		session = podmanTest.Podman([]string{"create", "--name", "test_shared", "--mount", fmt.Sprintf("type=bind,src=%s,target=/create/test,shared", mountPath), ALPINE, "awk", `$5 == "/create/test" { print $6 " " $7}`, "/proc/self/mountinfo"})
   194  		session.WaitWithDefaultTimeout()
   195  		Expect(session).Should(ExitCleanly())
   196  		session = podmanTest.Podman([]string{"start", "-a", "test_shared"})
   197  		session.WaitWithDefaultTimeout()
   198  		Expect(session).Should(ExitCleanly())
   199  		Expect(session.OutputToString()).To(ContainSubstring("rw"))
   200  		Expect(session.OutputToString()).To(ContainSubstring("shared"))
   201  
   202  		mountPath = filepath.Join(podmanTest.TempDir, "scratchpad")
   203  		err = os.Mkdir(mountPath, 0755)
   204  		Expect(err).ToNot(HaveOccurred())
   205  		session = podmanTest.Podman([]string{"create", "--name", "test_tmpfs", "--mount", "type=tmpfs,target=/create/test", ALPINE, "grep", "/create/test", "/proc/self/mountinfo"})
   206  		session.WaitWithDefaultTimeout()
   207  		Expect(session).Should(ExitCleanly())
   208  		session = podmanTest.Podman([]string{"start", "-a", "test_tmpfs"})
   209  		session.WaitWithDefaultTimeout()
   210  		Expect(session).Should(ExitCleanly())
   211  		Expect(session.OutputToString()).To(ContainSubstring("/create/test rw,nosuid,nodev,relatime - tmpfs"))
   212  	})
   213  
   214  	It("podman create --pod automatically", func() {
   215  		session := podmanTest.Podman([]string{"create", "--pod", "new:foobar", ALPINE, "ls"})
   216  		session.WaitWithDefaultTimeout()
   217  		Expect(session).Should(ExitCleanly())
   218  
   219  		check := podmanTest.Podman([]string{"pod", "ps", "--no-trunc"})
   220  		check.WaitWithDefaultTimeout()
   221  		Expect(check.OutputToString()).To(ContainSubstring("foobar"))
   222  	})
   223  
   224  	It("podman create --pod-id-file", func() {
   225  		// First, make sure that --pod and --pod-id-file yield an error
   226  		// if used together.
   227  		session := podmanTest.Podman([]string{"create", "--pod", "foo", "--pod-id-file", "bar", ALPINE, "ls"})
   228  		session.WaitWithDefaultTimeout()
   229  		Expect(session).Should(ExitWithError(125, "cannot specify both --pod and --pod-id-file"))
   230  
   231  		podName := "rudolph"
   232  		ctrName := "prancer"
   233  		podIDFile := filepath.Join(tempdir, "pod-id-file")
   234  
   235  		// Now, let's create a pod with --pod-id-file.
   236  		session = podmanTest.Podman([]string{"pod", "create", "--pod-id-file", podIDFile, "--name", podName})
   237  		session.WaitWithDefaultTimeout()
   238  		Expect(session).Should(ExitCleanly())
   239  
   240  		session = podmanTest.Podman([]string{"pod", "inspect", podName})
   241  		session.WaitWithDefaultTimeout()
   242  		Expect(session).Should(ExitCleanly())
   243  		Expect(session.OutputToString()).To(BeValidJSON())
   244  		podData := session.InspectPodToJSON()
   245  
   246  		// Finally we can create a container with --pod-id-file and do
   247  		// some checks to make sure it's working as expected.
   248  		session = podmanTest.Podman([]string{"create", "--pod-id-file", podIDFile, "--name", ctrName, ALPINE, "top"})
   249  		session.WaitWithDefaultTimeout()
   250  		Expect(session).Should(ExitCleanly())
   251  
   252  		ctrJSON := podmanTest.InspectContainer(ctrName)
   253  		Expect(podData).To(HaveField("ID", ctrJSON[0].Pod)) // Make sure the container's pod matches the pod's ID
   254  	})
   255  
   256  	It("podman run entrypoint and cmd test", func() {
   257  		name := "test101"
   258  		create := podmanTest.Podman([]string{"create", "--name", name, REDIS_IMAGE})
   259  		create.WaitWithDefaultTimeout()
   260  		Expect(create).Should(ExitCleanly())
   261  
   262  		ctrJSON := podmanTest.InspectContainer(name)
   263  		Expect(ctrJSON).To(HaveLen(1))
   264  		Expect(ctrJSON[0].Config.Cmd).To(HaveLen(1))
   265  		Expect(ctrJSON[0].Config.Cmd[0]).To(Equal("redis-server"))
   266  		Expect(ctrJSON[0].Config.Entrypoint).To(HaveLen(1))
   267  		Expect(ctrJSON[0].Config.Entrypoint[0]).To(Equal("docker-entrypoint.sh"))
   268  	})
   269  
   270  	It("podman create --pull", func() {
   271  		session := podmanTest.Podman([]string{"create", "--pull", "never", "--name=foo", "testimage:00000000"})
   272  		session.WaitWithDefaultTimeout()
   273  		Expect(session).To(ExitWithError(125, "testimage:00000000: image not known"))
   274  
   275  		session = podmanTest.Podman([]string{"create", "--pull", "always", "--name=foo", "testimage:00000000"})
   276  		session.WaitWithDefaultTimeout()
   277  		Expect(session).Should(Exit(0))
   278  		Expect(session.ErrorToString()).To(ContainSubstring("Copying blob"), "progress message from pull")
   279  	})
   280  
   281  	It("podman create using image list by tag", func() {
   282  		session := podmanTest.Podman([]string{"create", "-q", "--pull=always", "--arch=arm64", "--name=foo", ALPINELISTTAG})
   283  		session.WaitWithDefaultTimeout()
   284  		Expect(session).Should(ExitCleanly())
   285  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.Image}}", "foo"})
   286  		session.WaitWithDefaultTimeout()
   287  		Expect(session).Should(ExitCleanly())
   288  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64ID))
   289  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.ImageName}}", "foo"})
   290  		session.WaitWithDefaultTimeout()
   291  		Expect(session).Should(ExitCleanly())
   292  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTTAG))
   293  	})
   294  
   295  	It("podman create using image list by digest", func() {
   296  		session := podmanTest.Podman([]string{"create", "--pull=always", "--arch=arm64", "--name=foo", ALPINELISTDIGEST})
   297  		session.WaitWithDefaultTimeout()
   298  		Expect(session).Should(Exit(0))
   299  		Expect(session.ErrorToString()).To(ContainSubstring("Writing manifest to image destination"), "progress message from pull")
   300  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.Image}}", "foo"})
   301  		session.WaitWithDefaultTimeout()
   302  		Expect(session).Should(ExitCleanly())
   303  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64ID))
   304  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.ImageName}}", "foo"})
   305  		session.WaitWithDefaultTimeout()
   306  		Expect(session).Should(ExitCleanly())
   307  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINELISTDIGEST))
   308  	})
   309  
   310  	It("podman create using image list instance by digest", func() {
   311  		session := podmanTest.Podman([]string{"create", "-q", "--pull=always", "--arch=arm64", "--name=foo", ALPINEARM64DIGEST})
   312  		session.WaitWithDefaultTimeout()
   313  		Expect(session).Should(ExitCleanly())
   314  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.Image}}", "foo"})
   315  		session.WaitWithDefaultTimeout()
   316  		Expect(session).Should(ExitCleanly())
   317  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64ID))
   318  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.ImageName}}", "foo"})
   319  		session.WaitWithDefaultTimeout()
   320  		Expect(session).Should(ExitCleanly())
   321  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
   322  	})
   323  
   324  	It("podman create using cross-arch image list instance by digest", func() {
   325  		session := podmanTest.Podman([]string{"create", "-q", "--pull=always", "--arch=arm64", "--name=foo", ALPINEARM64DIGEST})
   326  		session.WaitWithDefaultTimeout()
   327  		Expect(session).Should(ExitCleanly())
   328  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.Image}}", "foo"})
   329  		session.WaitWithDefaultTimeout()
   330  		Expect(session).Should(ExitCleanly())
   331  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64ID))
   332  		session = podmanTest.Podman([]string{"inspect", "--format", "{{.ImageName}}", "foo"})
   333  		session.WaitWithDefaultTimeout()
   334  		Expect(session).Should(ExitCleanly())
   335  		Expect(string(session.Out.Contents())).To(ContainSubstring(ALPINEARM64DIGEST))
   336  	})
   337  
   338  	It("podman create --authfile with nonexistent authfile", func() {
   339  		bogus := filepath.Join(podmanTest.TempDir, "bogus.conf")
   340  		session := podmanTest.Podman([]string{"create", "--authfile", bogus, "--name=foo", ALPINE})
   341  		session.WaitWithDefaultTimeout()
   342  		Expect(session).To(ExitWithError(125, "credential file is not accessible: "))
   343  		Expect(session.ErrorToString()).To(ContainSubstring("no such file or directory"))
   344  	})
   345  
   346  	It("podman create --signature-policy", func() {
   347  		session := podmanTest.Podman([]string{"create", "--pull=always", "--signature-policy", "/no/such/file", ALPINE})
   348  		session.WaitWithDefaultTimeout()
   349  		if IsRemote() {
   350  			Expect(session).To(ExitWithError(125, "unknown flag: --signature-policy"))
   351  			return
   352  		} else {
   353  			Expect(session).To(ExitWithError(125, "open /no/such/file: no such file or directory"))
   354  		}
   355  
   356  		session = podmanTest.Podman([]string{"create", "-q", "--pull=always", "--signature-policy", "/etc/containers/policy.json", ALPINE})
   357  		session.WaitWithDefaultTimeout()
   358  		Expect(session).Should(ExitCleanly())
   359  	})
   360  
   361  	It("podman create with unset label", func() {
   362  		// Alpine is assumed to have no labels here, which seems safe
   363  		ctrName := "testctr"
   364  		session := podmanTest.Podman([]string{"create", "--label", "TESTKEY1=", "--label", "TESTKEY2", "--name", ctrName, ALPINE, "top"})
   365  		session.WaitWithDefaultTimeout()
   366  		Expect(session).Should(ExitCleanly())
   367  
   368  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   369  		inspect.WaitWithDefaultTimeout()
   370  		data := inspect.InspectContainerToJSON()
   371  		Expect(data).To(HaveLen(1), "len(InspectContainerToJSON)")
   372  		Expect(data[0].Config.Labels).To(HaveLen(2))
   373  		Expect(data[0].Config.Labels).To(HaveKey("TESTKEY1"))
   374  		Expect(data[0].Config.Labels).To(HaveKey("TESTKEY2"))
   375  	})
   376  
   377  	It("podman create with set label", func() {
   378  		// Alpine is assumed to have no labels here, which seems safe
   379  		ctrName := "testctr"
   380  		session := podmanTest.Podman([]string{"create", "--label", "TESTKEY1=value1", "--label", "TESTKEY2=bar", "--name", ctrName, ALPINE, "top"})
   381  		session.WaitWithDefaultTimeout()
   382  		Expect(session).Should(ExitCleanly())
   383  
   384  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   385  		inspect.WaitWithDefaultTimeout()
   386  		data := inspect.InspectContainerToJSON()
   387  		Expect(data).To(HaveLen(1))
   388  		Expect(data[0].Config.Labels).To(HaveLen(2))
   389  		Expect(data[0].Config.Labels).To(HaveKeyWithValue("TESTKEY1", "value1"))
   390  		Expect(data[0].Config.Labels).To(HaveKeyWithValue("TESTKEY2", "bar"))
   391  	})
   392  
   393  	It("podman create with --restart=on-failure:5 parses correctly", func() {
   394  		ctrName := "testctr"
   395  		session := podmanTest.Podman([]string{"create", "-t", "--restart", "on-failure:5", "--name", ctrName, ALPINE, "/bin/sh"})
   396  		session.WaitWithDefaultTimeout()
   397  		Expect(session).Should(ExitCleanly())
   398  
   399  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   400  		inspect.WaitWithDefaultTimeout()
   401  		data := inspect.InspectContainerToJSON()
   402  		Expect(data).To(HaveLen(1))
   403  		Expect(data[0].HostConfig.RestartPolicy).To(HaveField("Name", "on-failure"))
   404  		Expect(data[0].HostConfig.RestartPolicy).To(HaveField("MaximumRetryCount", uint(5)))
   405  	})
   406  
   407  	It("podman create with --restart-policy=always:5 fails", func() {
   408  		session := podmanTest.Podman([]string{"create", "-t", "--restart", "always:5", ALPINE, "/bin/sh"})
   409  		session.WaitWithDefaultTimeout()
   410  		Expect(session).To(ExitWithError(125, "restart policy retries can only be specified with on-failure restart policy"))
   411  	})
   412  
   413  	It("podman create with --restart-policy unless-stopped", func() {
   414  		ctrName := "testctr"
   415  		unlessStopped := "unless-stopped"
   416  		session := podmanTest.Podman([]string{"create", "-t", "--restart", unlessStopped, "--name", ctrName, ALPINE, "/bin/sh"})
   417  		session.WaitWithDefaultTimeout()
   418  		Expect(session).Should(ExitCleanly())
   419  
   420  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   421  		inspect.WaitWithDefaultTimeout()
   422  		data := inspect.InspectContainerToJSON()
   423  		Expect(data).To(HaveLen(1))
   424  		Expect(data[0].HostConfig.RestartPolicy).To(HaveField("Name", unlessStopped))
   425  	})
   426  
   427  	It("podman create with -m 1000000 sets swap to 2000000", func() {
   428  		SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1")
   429  		numMem := 1000000
   430  		ctrName := "testCtr"
   431  		session := podmanTest.Podman([]string{"create", "-t", "-m", fmt.Sprintf("%db", numMem), "--name", ctrName, ALPINE, "/bin/sh"})
   432  		session.WaitWithDefaultTimeout()
   433  		Expect(session).Should(ExitCleanly())
   434  
   435  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   436  		inspect.WaitWithDefaultTimeout()
   437  		data := inspect.InspectContainerToJSON()
   438  		Expect(data).To(HaveLen(1))
   439  		Expect(data[0].HostConfig).To(HaveField("MemorySwap", int64(2*numMem)))
   440  	})
   441  
   442  	It("podman create --cpus 5 sets nanocpus", func() {
   443  		SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1")
   444  		numCpus := 5
   445  		nanoCPUs := numCpus * 1000000000
   446  		ctrName := "testCtr"
   447  		session := podmanTest.Podman([]string{"create", "-t", "--cpus", strconv.Itoa(numCpus), "--name", ctrName, ALPINE, "/bin/sh"})
   448  		session.WaitWithDefaultTimeout()
   449  		Expect(session).Should(ExitCleanly())
   450  
   451  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   452  		inspect.WaitWithDefaultTimeout()
   453  		data := inspect.InspectContainerToJSON()
   454  		Expect(data).To(HaveLen(1))
   455  		Expect(data[0].HostConfig).To(HaveField("NanoCpus", int64(nanoCPUs)))
   456  	})
   457  
   458  	It("podman create --replace", func() {
   459  		// Make sure we error out with --name.
   460  		session := podmanTest.Podman([]string{"create", "--replace", ALPINE, "/bin/sh"})
   461  		session.WaitWithDefaultTimeout()
   462  		Expect(session).Should(ExitWithError(125, "cannot replace container without --name being set"))
   463  
   464  		// Create and replace 5 times in a row the "same" container.
   465  		ctrName := "testCtr"
   466  		for i := 0; i < 5; i++ {
   467  			session = podmanTest.Podman([]string{"create", "--replace", "--name", ctrName, ALPINE, "/bin/sh"})
   468  			session.WaitWithDefaultTimeout()
   469  			Expect(session).Should(ExitCleanly())
   470  		}
   471  	})
   472  
   473  	It("podman create sets default stop signal 15", func() {
   474  		ctrName := "testCtr"
   475  		session := podmanTest.Podman([]string{"create", "--name", ctrName, ALPINE, "/bin/sh"})
   476  		session.WaitWithDefaultTimeout()
   477  		Expect(session).Should(ExitCleanly())
   478  
   479  		inspect := podmanTest.Podman([]string{"inspect", ctrName})
   480  		inspect.WaitWithDefaultTimeout()
   481  		data := inspect.InspectContainerToJSON()
   482  		Expect(data).To(HaveLen(1))
   483  		Expect(data[0].Config).To(HaveField("StopSignal", "SIGTERM"))
   484  	})
   485  
   486  	It("podman create --tz", func() {
   487  		session := podmanTest.Podman([]string{"create", "--tz", "foo", "--name", "bad", ALPINE, "date"})
   488  		session.WaitWithDefaultTimeout()
   489  		Expect(session).To(ExitWithError(125, "running container create option: finding timezone: unknown time zone foo"))
   490  
   491  		session = podmanTest.Podman([]string{"create", "--tz", "America", "--name", "dir", ALPINE, "date"})
   492  		session.WaitWithDefaultTimeout()
   493  		Expect(session).To(ExitWithError(125, "running container create option: finding timezone: is a directory"))
   494  
   495  		session = podmanTest.Podman([]string{"create", "--tz", "Pacific/Honolulu", "--name", "zone", ALPINE, "date"})
   496  		session.WaitWithDefaultTimeout()
   497  		inspect := podmanTest.Podman([]string{"inspect", "zone"})
   498  		inspect.WaitWithDefaultTimeout()
   499  		data := inspect.InspectContainerToJSON()
   500  		Expect(data).To(HaveLen(1))
   501  		Expect(data[0].Config).To(HaveField("Timezone", "Pacific/Honolulu"))
   502  
   503  		session = podmanTest.Podman([]string{"create", "--tz", "local", "--name", "lcl", ALPINE, "date"})
   504  		session.WaitWithDefaultTimeout()
   505  		inspect = podmanTest.Podman([]string{"inspect", "lcl"})
   506  		inspect.WaitWithDefaultTimeout()
   507  		data = inspect.InspectContainerToJSON()
   508  		Expect(data).To(HaveLen(1))
   509  		Expect(data[0].Config).To(HaveField("Timezone", "local"))
   510  	})
   511  
   512  	It("podman create --umask", func() {
   513  		if !strings.Contains(podmanTest.OCIRuntime, "crun") {
   514  			Skip("Test only works on crun")
   515  		}
   516  
   517  		session := podmanTest.Podman([]string{"create", "--name", "default", ALPINE})
   518  		session.WaitWithDefaultTimeout()
   519  		inspect := podmanTest.Podman([]string{"inspect", "default"})
   520  		inspect.WaitWithDefaultTimeout()
   521  		data := inspect.InspectContainerToJSON()
   522  		Expect(data).To(HaveLen(1))
   523  		Expect(data[0].Config).To(HaveField("Umask", "0022"))
   524  
   525  		session = podmanTest.Podman([]string{"create", "--umask", "0002", "--name", "umask", ALPINE})
   526  		session.WaitWithDefaultTimeout()
   527  		inspect = podmanTest.Podman([]string{"inspect", "umask"})
   528  		inspect.WaitWithDefaultTimeout()
   529  		data = inspect.InspectContainerToJSON()
   530  		Expect(data).To(HaveLen(1))
   531  		Expect(data[0].Config).To(HaveField("Umask", "0002"))
   532  
   533  		session = podmanTest.Podman([]string{"create", "--umask", "0077", "--name", "fedora", fedoraMinimal})
   534  		session.WaitWithDefaultTimeout()
   535  		inspect = podmanTest.Podman([]string{"inspect", "fedora"})
   536  		inspect.WaitWithDefaultTimeout()
   537  		data = inspect.InspectContainerToJSON()
   538  		Expect(data).To(HaveLen(1))
   539  		Expect(data[0].Config).To(HaveField("Umask", "0077"))
   540  
   541  		session = podmanTest.Podman([]string{"create", "--umask", "22", "--name", "umask-short", ALPINE})
   542  		session.WaitWithDefaultTimeout()
   543  		inspect = podmanTest.Podman([]string{"inspect", "umask-short"})
   544  		inspect.WaitWithDefaultTimeout()
   545  		data = inspect.InspectContainerToJSON()
   546  		Expect(data).To(HaveLen(1))
   547  		Expect(data[0].Config).To(HaveField("Umask", "0022"))
   548  
   549  		session = podmanTest.Podman([]string{"create", "--umask", "9999", "--name", "bad", ALPINE})
   550  		session.WaitWithDefaultTimeout()
   551  		Expect(session).To(ExitWithError(125, "invalid umask string 9999: invalid argument"))
   552  	})
   553  
   554  	It("create container in pod with IP should fail", func() {
   555  		SkipIfRootless("Setting IP not supported in rootless mode without network")
   556  		name := "createwithstaticip"
   557  		pod := podmanTest.RunTopContainerInPod("", "new:"+name)
   558  		pod.WaitWithDefaultTimeout()
   559  		Expect(pod).Should(ExitCleanly())
   560  
   561  		session := podmanTest.Podman([]string{"create", "--pod", name, "--ip", "192.168.1.2", ALPINE, "top"})
   562  		session.WaitWithDefaultTimeout()
   563  		Expect(session).Should(ExitWithError(125, "invalid config provided: networks must be defined when the pod is created: network cannot be configured when it is shared with a pod"))
   564  	})
   565  
   566  	It("create container in pod with mac should fail", func() {
   567  		SkipIfRootless("Setting MAC Address not supported in rootless mode without network")
   568  		name := "createwithstaticmac"
   569  		pod := podmanTest.RunTopContainerInPod("", "new:"+name)
   570  		pod.WaitWithDefaultTimeout()
   571  		Expect(pod).Should(ExitCleanly())
   572  
   573  		session := podmanTest.Podman([]string{"create", "--pod", name, "--mac-address", "52:54:00:6d:2f:82", ALPINE, "top"})
   574  		session.WaitWithDefaultTimeout()
   575  		Expect(session).Should(ExitWithError(125, "invalid config provided: networks must be defined when the pod is created: network cannot be configured when it is shared with a pod"))
   576  	})
   577  
   578  	It("create container in pod with network should not fail", func() {
   579  		name := "createwithnetwork"
   580  		pod := podmanTest.RunTopContainerInPod("", "new:"+name)
   581  		pod.WaitWithDefaultTimeout()
   582  		Expect(pod).Should(ExitCleanly())
   583  
   584  		netName := "pod" + stringid.GenerateRandomID()
   585  		session := podmanTest.Podman([]string{"network", "create", netName})
   586  		session.WaitWithDefaultTimeout()
   587  		Expect(session).Should(ExitCleanly())
   588  		defer podmanTest.removeNetwork(netName)
   589  
   590  		session = podmanTest.Podman([]string{"create", "--pod", name, "--network", netName, ALPINE, "top"})
   591  		session.WaitWithDefaultTimeout()
   592  		Expect(session).Should(ExitCleanly())
   593  	})
   594  
   595  	It("create container in pod with ports should fail", func() {
   596  		name := "createwithports"
   597  		pod := podmanTest.RunTopContainerInPod("", "new:"+name)
   598  		pod.WaitWithDefaultTimeout()
   599  		Expect(pod).Should(ExitCleanly())
   600  
   601  		session := podmanTest.Podman([]string{"create", "--pod", name, "-p", "8086:80", ALPINE, "top"})
   602  		session.WaitWithDefaultTimeout()
   603  		Expect(session).Should(ExitWithError(125, "invalid config provided: published or exposed ports must be defined when the pod is created: network cannot be configured when it is shared with a pod"))
   604  	})
   605  
   606  	It("create container in pod publish ports should fail", func() {
   607  		name := "createwithpublishports"
   608  		pod := podmanTest.RunTopContainerInPod("", "new:"+name)
   609  		pod.WaitWithDefaultTimeout()
   610  		Expect(pod).Should(ExitCleanly())
   611  
   612  		session := podmanTest.Podman([]string{"create", "--pod", name, "-P", ALPINE, "top"})
   613  		session.WaitWithDefaultTimeout()
   614  		Expect(session).Should(ExitWithError(125, "invalid config provided: published or exposed ports must be defined when the pod is created: network cannot be configured when it is shared with a pod"))
   615  	})
   616  
   617  	It("create use local store image if input image contains a manifest list", func() {
   618  		session := podmanTest.Podman([]string{"pull", "-q", BB})
   619  		session.WaitWithDefaultTimeout()
   620  		Expect(session).Should(ExitCleanly())
   621  
   622  		session = podmanTest.Podman([]string{"manifest", "create", "mylist"})
   623  		session.WaitWithDefaultTimeout()
   624  		Expect(session).Should(ExitCleanly())
   625  
   626  		session = podmanTest.Podman([]string{"manifest", "add", "--all", "mylist", BB})
   627  		session.WaitWithDefaultTimeout()
   628  		Expect(session).Should(ExitCleanly())
   629  
   630  		session = podmanTest.Podman([]string{"create", "mylist"})
   631  		session.WaitWithDefaultTimeout()
   632  		Expect(session).Should(ExitCleanly())
   633  	})
   634  
   635  	It("podman create -d should fail, can not detach create containers", func() {
   636  		session := podmanTest.Podman([]string{"create", "-d", ALPINE})
   637  		session.WaitWithDefaultTimeout()
   638  		Expect(session).Should(ExitWithError(125, "unknown shorthand flag: 'd' in -d"))
   639  
   640  		session = podmanTest.Podman([]string{"create", "--detach", ALPINE})
   641  		session.WaitWithDefaultTimeout()
   642  		Expect(session).Should(ExitWithError(125, "unknown flag"))
   643  		Expect(session.ErrorToString()).To(ContainSubstring("unknown flag: --detach"))
   644  
   645  		session = podmanTest.Podman([]string{"create", "--detach-keys", "ctrl-x", ALPINE})
   646  		session.WaitWithDefaultTimeout()
   647  		Expect(session).Should(ExitWithError(125, "unknown flag: --detach-keys"))
   648  	})
   649  
   650  	It("podman create --platform", func() {
   651  		session := podmanTest.Podman([]string{"create", "--platform=linux/bogus", ALPINE})
   652  		session.WaitWithDefaultTimeout()
   653  		Expect(session).Should(ExitWithError(125, "no image found in manifest list for architecture bogus"))
   654  
   655  		session = podmanTest.Podman([]string{"create", "--platform=linux/arm64", "--os", "windows", ALPINE})
   656  		session.WaitWithDefaultTimeout()
   657  		Expect(session).Should(ExitWithError(125, "--platform option can not be specified with --arch or --os"))
   658  
   659  		session = podmanTest.Podman([]string{"create", "-q", "--platform=linux/arm64", ALPINE})
   660  		session.WaitWithDefaultTimeout()
   661  		Expect(session).Should(ExitCleanly())
   662  
   663  		setup := podmanTest.Podman([]string{"container", "inspect", session.OutputToString()})
   664  		setup.WaitWithDefaultTimeout()
   665  		Expect(setup).Should(ExitCleanly())
   666  
   667  		data := setup.InspectContainerToJSON()
   668  		setup = podmanTest.Podman([]string{"image", "inspect", data[0].Image})
   669  		setup.WaitWithDefaultTimeout()
   670  		Expect(setup).Should(ExitCleanly())
   671  
   672  		idata := setup.InspectImageJSON() // returns []inspect.ImageData
   673  		Expect(idata).To(HaveLen(1))
   674  		Expect(idata[0]).To(HaveField("Os", runtime.GOOS))
   675  		Expect(idata[0]).To(HaveField("Architecture", "arm64"))
   676  	})
   677  
   678  	It("podman create --uid/gidmap --pod conflict test", func() {
   679  		create := podmanTest.Podman([]string{"create", "--uidmap", "0:1000:1000", "--pod", "new:testing123", ALPINE})
   680  		create.WaitWithDefaultTimeout()
   681  		Expect(create).ShouldNot(ExitCleanly())
   682  		Expect(create.ErrorToString()).To(ContainSubstring("cannot specify a new uid/gid map when entering a pod with an infra container"))
   683  
   684  		create = podmanTest.Podman([]string{"create", "--gidmap", "0:1000:1000", "--pod", "new:testing1234", ALPINE})
   685  		create.WaitWithDefaultTimeout()
   686  		Expect(create).ShouldNot(ExitCleanly())
   687  		Expect(create.ErrorToString()).To(ContainSubstring("cannot specify a new uid/gid map when entering a pod with an infra container"))
   688  
   689  	})
   690  
   691  	It("podman create --chrootdirs inspection test", func() {
   692  		session := podmanTest.Podman([]string{"create", "--chrootdirs", "/var/local/qwerty", ALPINE})
   693  		session.WaitWithDefaultTimeout()
   694  		Expect(session).Should(ExitCleanly())
   695  
   696  		setup := podmanTest.Podman([]string{"container", "inspect", session.OutputToString()})
   697  		setup.WaitWithDefaultTimeout()
   698  		Expect(setup).Should(ExitCleanly())
   699  
   700  		data := setup.InspectContainerToJSON()
   701  		Expect(data).To(HaveLen(1))
   702  		Expect(data[0].Config.ChrootDirs).To(HaveLen(1))
   703  		Expect(data[0].Config.ChrootDirs[0]).To(Equal("/var/local/qwerty"))
   704  	})
   705  
   706  	It("podman create --chrootdirs functionality test", func() {
   707  		session := podmanTest.Podman([]string{"create", "-t", "--chrootdirs", "/var/local/qwerty,withcomma", ALPINE, "/bin/cat"})
   708  		session.WaitWithDefaultTimeout()
   709  		Expect(session).Should(ExitCleanly())
   710  		ctrID := session.OutputToString()
   711  
   712  		setup := podmanTest.Podman([]string{"start", ctrID})
   713  		setup.WaitWithDefaultTimeout()
   714  		Expect(setup).Should(ExitCleanly())
   715  
   716  		setup = podmanTest.Podman([]string{"exec", ctrID, "cmp", "/etc/resolv.conf", "/var/local/qwerty,withcomma/etc/resolv.conf"})
   717  		setup.WaitWithDefaultTimeout()
   718  		Expect(setup).Should(ExitCleanly())
   719  	})
   720  
   721  	It("create container with name subset of existing ID", func() {
   722  		create1 := podmanTest.Podman([]string{"create", "-t", ALPINE, "top"})
   723  		create1.WaitWithDefaultTimeout()
   724  		Expect(create1).Should(ExitCleanly())
   725  		ctr1ID := create1.OutputToString()
   726  
   727  		ctr2Name := ctr1ID[:5]
   728  		create2 := podmanTest.Podman([]string{"create", "-t", "--name", ctr2Name, ALPINE, "top"})
   729  		create2.WaitWithDefaultTimeout()
   730  		Expect(create2).Should(ExitCleanly())
   731  
   732  		inspect := podmanTest.Podman([]string{"inspect", "--format", "{{.Name}}", ctr2Name})
   733  		inspect.WaitWithDefaultTimeout()
   734  		Expect(inspect).Should(ExitCleanly())
   735  		Expect(inspect.OutputToString()).Should(Equal(ctr2Name))
   736  	})
   737  })