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

     1  // +build !remoteclient
     2  
     3  package integration
     4  
     5  import (
     6  	"fmt"
     7  	"os"
     8  	"os/exec"
     9  	"path/filepath"
    10  	"strings"
    11  
    12  	. "github.com/containers/libpod/test/utils"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  	"github.com/onsi/gomega/gexec"
    16  )
    17  
    18  // in-container mount point: using a path that is definitely not present
    19  // on the host system might help to uncover some issues.
    20  const dest = "/unique/path"
    21  
    22  var _ = Describe("Podman run with volumes", func() {
    23  	var (
    24  		tempdir    string
    25  		err        error
    26  		podmanTest *PodmanTestIntegration
    27  	)
    28  
    29  	BeforeEach(func() {
    30  		tempdir, err = CreateTempDirInTempDir()
    31  		if err != nil {
    32  			os.Exit(1)
    33  		}
    34  		podmanTest = PodmanTestCreate(tempdir)
    35  		podmanTest.Setup()
    36  		podmanTest.SeedImages()
    37  	})
    38  
    39  	AfterEach(func() {
    40  		podmanTest.Cleanup()
    41  		f := CurrentGinkgoTestDescription()
    42  		processTestResult(f)
    43  	})
    44  
    45  	It("podman run with volume flag", func() {
    46  		mountPath := filepath.Join(podmanTest.TempDir, "secrets")
    47  		os.Mkdir(mountPath, 0755)
    48  		vol := mountPath + ":" + dest
    49  
    50  		session := podmanTest.Podman([]string{"run", "--rm", "-v", vol, ALPINE, "grep", dest, "/proc/self/mountinfo"})
    51  		session.WaitWithDefaultTimeout()
    52  		Expect(session.ExitCode()).To(Equal(0))
    53  		found, matches := session.GrepString(dest)
    54  		Expect(found).Should(BeTrue())
    55  		Expect(matches[0]).To(ContainSubstring("rw"))
    56  
    57  		session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":ro", ALPINE, "grep", dest, "/proc/self/mountinfo"})
    58  		session.WaitWithDefaultTimeout()
    59  		Expect(session.ExitCode()).To(Equal(0))
    60  		found, matches = session.GrepString(dest)
    61  		Expect(found).Should(BeTrue())
    62  		Expect(matches[0]).To(ContainSubstring("ro"))
    63  
    64  		session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":shared", ALPINE, "grep", dest, "/proc/self/mountinfo"})
    65  		session.WaitWithDefaultTimeout()
    66  		Expect(session.ExitCode()).To(Equal(0))
    67  		found, matches = session.GrepString(dest)
    68  		Expect(found).Should(BeTrue())
    69  		Expect(matches[0]).To(ContainSubstring("rw"))
    70  		Expect(matches[0]).To(ContainSubstring("shared"))
    71  
    72  		// Cached is ignored
    73  		session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":cached", ALPINE, "grep", dest, "/proc/self/mountinfo"})
    74  		session.WaitWithDefaultTimeout()
    75  		Expect(session.ExitCode()).To(Equal(0))
    76  		found, matches = session.GrepString(dest)
    77  		Expect(found).Should(BeTrue())
    78  		Expect(matches[0]).To(ContainSubstring("rw"))
    79  		Expect(matches[0]).To(Not(ContainSubstring("cached")))
    80  
    81  		// Delegated is ignored
    82  		session = podmanTest.Podman([]string{"run", "--rm", "-v", vol + ":delegated", ALPINE, "grep", dest, "/proc/self/mountinfo"})
    83  		session.WaitWithDefaultTimeout()
    84  		Expect(session.ExitCode()).To(Equal(0))
    85  		found, matches = session.GrepString(dest)
    86  		Expect(found).Should(BeTrue())
    87  		Expect(matches[0]).To(ContainSubstring("rw"))
    88  		Expect(matches[0]).To(Not(ContainSubstring("delegated")))
    89  	})
    90  
    91  	It("podman run with --mount flag", func() {
    92  		if podmanTest.Host.Arch == "ppc64le" {
    93  			Skip("skip failing test on ppc64le")
    94  		}
    95  		mountPath := filepath.Join(podmanTest.TempDir, "secrets")
    96  		os.Mkdir(mountPath, 0755)
    97  		mount := "type=bind,src=" + mountPath + ",target=" + dest
    98  
    99  		session := podmanTest.Podman([]string{"run", "--rm", "--mount", mount, ALPINE, "grep", dest, "/proc/self/mountinfo"})
   100  		session.WaitWithDefaultTimeout()
   101  		Expect(session.ExitCode()).To(Equal(0))
   102  		Expect(session.OutputToString()).To(ContainSubstring(dest + " rw"))
   103  
   104  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   105  		session.WaitWithDefaultTimeout()
   106  		Expect(session.ExitCode()).To(Equal(0))
   107  		Expect(session.OutputToString()).To(ContainSubstring(dest + " ro"))
   108  
   109  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",shared", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   110  		session.WaitWithDefaultTimeout()
   111  		Expect(session.ExitCode()).To(Equal(0))
   112  		found, matches := session.GrepString(dest)
   113  		Expect(found).Should(BeTrue())
   114  		Expect(matches[0]).To(ContainSubstring("rw"))
   115  		Expect(matches[0]).To(ContainSubstring("shared"))
   116  
   117  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=" + dest, ALPINE, "grep", dest, "/proc/self/mountinfo"})
   118  		session.WaitWithDefaultTimeout()
   119  		Expect(session.ExitCode()).To(Equal(0))
   120  		Expect(session.OutputToString()).To(ContainSubstring(dest + " rw,nosuid,nodev,relatime - tmpfs"))
   121  
   122  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=/etc/ssl,tmpcopyup", ALPINE, "ls", "/etc/ssl"})
   123  		session.WaitWithDefaultTimeout()
   124  		Expect(session.ExitCode()).To(Equal(0))
   125  		Expect(session.OutputToString()).To(ContainSubstring("certs"))
   126  
   127  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=/etc/ssl,tmpcopyup,notmpcopyup", ALPINE, "ls", "/etc/ssl"})
   128  		session.WaitWithDefaultTimeout()
   129  		Expect(session.ExitCode()).To(Not(Equal(0)))
   130  
   131  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=bind,src=/tmp,target=/tmp,tmpcopyup", ALPINE, "true"})
   132  		session.WaitWithDefaultTimeout()
   133  		Expect(session.ExitCode()).To(Not(Equal(0)))
   134  
   135  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=bind,src=/tmp,target=/tmp,notmpcopyup", ALPINE, "true"})
   136  		session.WaitWithDefaultTimeout()
   137  		Expect(session.ExitCode()).To(Not(Equal(0)))
   138  
   139  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", "type=tmpfs,target=/etc/ssl,notmpcopyup", ALPINE, "ls", "/etc/ssl"})
   140  		session.WaitWithDefaultTimeout()
   141  		Expect(session.ExitCode()).To(Equal(0))
   142  		Expect(session.OutputToString()).To(Not(ContainSubstring("certs")))
   143  	})
   144  
   145  	It("podman run with conflicting volumes errors", func() {
   146  		mountPath := filepath.Join(podmanTest.TmpDir, "secrets")
   147  		os.Mkdir(mountPath, 0755)
   148  		session := podmanTest.Podman([]string{"run", "-v", mountPath + ":" + dest, "-v", "/tmp" + ":" + dest, ALPINE, "ls"})
   149  		session.WaitWithDefaultTimeout()
   150  		Expect(session.ExitCode()).To(Equal(125))
   151  	})
   152  
   153  	It("podman run with conflict between image volume and user mount succeeds", func() {
   154  		podmanTest.RestoreArtifact(redis)
   155  		mountPath := filepath.Join(podmanTest.TempDir, "secrets")
   156  		err := os.Mkdir(mountPath, 0755)
   157  		Expect(err).To(BeNil())
   158  		testFile := filepath.Join(mountPath, "test1")
   159  		f, err := os.Create(testFile)
   160  		f.Close()
   161  		Expect(err).To(BeNil())
   162  		session := podmanTest.Podman([]string{"run", "-v", fmt.Sprintf("%s:/data", mountPath), redis, "ls", "/data/test1"})
   163  		session.WaitWithDefaultTimeout()
   164  		Expect(session.ExitCode()).To(Equal(0))
   165  	})
   166  
   167  	It("podman run with mount flag and boolean options", func() {
   168  		mountPath := filepath.Join(podmanTest.TempDir, "secrets")
   169  		os.Mkdir(mountPath, 0755)
   170  		mount := "type=bind,src=" + mountPath + ",target=" + dest
   171  
   172  		session := podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro=false", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   173  		session.WaitWithDefaultTimeout()
   174  		Expect(session.ExitCode()).To(Equal(0))
   175  		Expect(session.OutputToString()).To(ContainSubstring(dest + " rw"))
   176  
   177  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro=true", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   178  		session.WaitWithDefaultTimeout()
   179  		Expect(session.ExitCode()).To(Equal(0))
   180  		Expect(session.OutputToString()).To(ContainSubstring(dest + " ro"))
   181  
   182  		session = podmanTest.Podman([]string{"run", "--rm", "--mount", mount + ",ro=true,rw=false", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   183  		session.WaitWithDefaultTimeout()
   184  		Expect(session).To(ExitWithError())
   185  	})
   186  
   187  	It("podman run with volume flag and multiple named volumes", func() {
   188  		session := podmanTest.Podman([]string{"run", "--rm", "-v", "testvol1:/testvol1", "-v", "testvol2:/testvol2", ALPINE, "grep", "/testvol", "/proc/self/mountinfo"})
   189  		session.WaitWithDefaultTimeout()
   190  		Expect(session.ExitCode()).To(Equal(0))
   191  		Expect(session.OutputToString()).To(ContainSubstring("/testvol1"))
   192  		Expect(session.OutputToString()).To(ContainSubstring("/testvol2"))
   193  	})
   194  
   195  	It("podman run with volumes and suid/dev/exec options", func() {
   196  		mountPath := filepath.Join(podmanTest.TempDir, "secrets")
   197  		os.Mkdir(mountPath, 0755)
   198  
   199  		session := podmanTest.Podman([]string{"run", "--rm", "-v", mountPath + ":" + dest + ":suid,dev,exec", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   200  		session.WaitWithDefaultTimeout()
   201  		Expect(session.ExitCode()).To(Equal(0))
   202  		found, matches := session.GrepString(dest)
   203  		Expect(found).Should(BeTrue())
   204  		Expect(matches[0]).To(Not(ContainSubstring("noexec")))
   205  		Expect(matches[0]).To(Not(ContainSubstring("nodev")))
   206  		Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
   207  
   208  		session = podmanTest.Podman([]string{"run", "--rm", "--tmpfs", dest + ":suid,dev,exec", ALPINE, "grep", dest, "/proc/self/mountinfo"})
   209  		session.WaitWithDefaultTimeout()
   210  		Expect(session.ExitCode()).To(Equal(0))
   211  		found, matches = session.GrepString(dest)
   212  		Expect(found).Should(BeTrue())
   213  		Expect(matches[0]).To(Not(ContainSubstring("noexec")))
   214  		Expect(matches[0]).To(Not(ContainSubstring("nodev")))
   215  		Expect(matches[0]).To(Not(ContainSubstring("nosuid")))
   216  	})
   217  
   218  	It("podman run with noexec can't exec", func() {
   219  		session := podmanTest.Podman([]string{"run", "--rm", "-v", "/bin:/hostbin:noexec", ALPINE, "/hostbin/ls", "/"})
   220  		session.WaitWithDefaultTimeout()
   221  		Expect(session).To(ExitWithError())
   222  	})
   223  
   224  	It("podman run with tmpfs named volume mounts and unmounts", func() {
   225  		SkipIfRootless()
   226  		volName := "testvol"
   227  		mkVolume := podmanTest.Podman([]string{"volume", "create", "--opt", "type=tmpfs", "--opt", "device=tmpfs", "--opt", "o=nodev", "testvol"})
   228  		mkVolume.WaitWithDefaultTimeout()
   229  		Expect(mkVolume.ExitCode()).To(Equal(0))
   230  
   231  		// Volume not mounted on create
   232  		mountCmd1, err := gexec.Start(exec.Command("mount"), GinkgoWriter, GinkgoWriter)
   233  		Expect(err).To(BeNil())
   234  		mountCmd1.Wait(90)
   235  		Expect(mountCmd1.ExitCode()).To(Equal(0))
   236  		os.Stdout.Sync()
   237  		os.Stderr.Sync()
   238  		mountOut1 := strings.Join(strings.Fields(fmt.Sprintf("%s", mountCmd1.Out.Contents())), " ")
   239  		fmt.Printf("Output: %s", mountOut1)
   240  		Expect(strings.Contains(mountOut1, volName)).To(BeFalse())
   241  
   242  		ctrName := "testctr"
   243  		podmanSession := podmanTest.Podman([]string{"run", "-d", "--name", ctrName, "-v", fmt.Sprintf("%s:/testvol", volName), ALPINE, "top"})
   244  		podmanSession.WaitWithDefaultTimeout()
   245  		Expect(podmanSession.ExitCode()).To(Equal(0))
   246  
   247  		// Volume now mounted as container is running
   248  		mountCmd2, err := gexec.Start(exec.Command("mount"), GinkgoWriter, GinkgoWriter)
   249  		Expect(err).To(BeNil())
   250  		mountCmd2.Wait(90)
   251  		Expect(mountCmd2.ExitCode()).To(Equal(0))
   252  		os.Stdout.Sync()
   253  		os.Stderr.Sync()
   254  		mountOut2 := strings.Join(strings.Fields(fmt.Sprintf("%s", mountCmd2.Out.Contents())), " ")
   255  		fmt.Printf("Output: %s", mountOut2)
   256  		Expect(strings.Contains(mountOut2, volName)).To(BeTrue())
   257  
   258  		// Stop the container to unmount
   259  		podmanStopSession := podmanTest.Podman([]string{"stop", "--time", "0", ctrName})
   260  		podmanStopSession.WaitWithDefaultTimeout()
   261  		Expect(podmanStopSession.ExitCode()).To(Equal(0))
   262  
   263  		// We have to force cleanup so the unmount happens
   264  		podmanCleanupSession := podmanTest.Podman([]string{"container", "cleanup", ctrName})
   265  		podmanCleanupSession.WaitWithDefaultTimeout()
   266  		Expect(podmanCleanupSession.ExitCode()).To(Equal(0))
   267  
   268  		// Ensure volume is unmounted
   269  		mountCmd3, err := gexec.Start(exec.Command("mount"), GinkgoWriter, GinkgoWriter)
   270  		Expect(err).To(BeNil())
   271  		mountCmd3.Wait(90)
   272  		Expect(mountCmd3.ExitCode()).To(Equal(0))
   273  		os.Stdout.Sync()
   274  		os.Stderr.Sync()
   275  		mountOut3 := strings.Join(strings.Fields(fmt.Sprintf("%s", mountCmd3.Out.Contents())), " ")
   276  		fmt.Printf("Output: %s", mountOut3)
   277  		Expect(strings.Contains(mountOut3, volName)).To(BeFalse())
   278  	})
   279  
   280  	It("podman named volume copyup", func() {
   281  		baselineSession := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", ALPINE, "ls", "/etc/apk/"})
   282  		baselineSession.WaitWithDefaultTimeout()
   283  		Expect(baselineSession.ExitCode()).To(Equal(0))
   284  		baselineOutput := baselineSession.OutputToString()
   285  
   286  		inlineVolumeSession := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "-v", "testvol1:/etc/apk", ALPINE, "ls", "/etc/apk/"})
   287  		inlineVolumeSession.WaitWithDefaultTimeout()
   288  		Expect(inlineVolumeSession.ExitCode()).To(Equal(0))
   289  		Expect(inlineVolumeSession.OutputToString()).To(Equal(baselineOutput))
   290  
   291  		makeVolumeSession := podmanTest.Podman([]string{"volume", "create", "testvol2"})
   292  		makeVolumeSession.WaitWithDefaultTimeout()
   293  		Expect(makeVolumeSession.ExitCode()).To(Equal(0))
   294  
   295  		separateVolumeSession := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "-v", "testvol2:/etc/apk", ALPINE, "ls", "/etc/apk/"})
   296  		separateVolumeSession.WaitWithDefaultTimeout()
   297  		Expect(separateVolumeSession.ExitCode()).To(Equal(0))
   298  		Expect(separateVolumeSession.OutputToString()).To(Equal(baselineOutput))
   299  	})
   300  
   301  	It("podman read-only tmpfs conflict with volume", func() {
   302  		session := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "-v", "tmp_volume:" + dest, ALPINE, "touch", dest + "/a"})
   303  		session.WaitWithDefaultTimeout()
   304  		Expect(session.ExitCode()).To(Equal(0))
   305  
   306  		session2 := podmanTest.Podman([]string{"run", "--rm", "-t", "-i", "--read-only", "--tmpfs", dest, ALPINE, "touch", dest + "/a"})
   307  		session2.WaitWithDefaultTimeout()
   308  		Expect(session2.ExitCode()).To(Equal(0))
   309  	})
   310  
   311  	It("podman run with anonymous volume", func() {
   312  		list1 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   313  		list1.WaitWithDefaultTimeout()
   314  		Expect(list1.ExitCode()).To(Equal(0))
   315  		Expect(list1.OutputToString()).To(Equal(""))
   316  
   317  		session := podmanTest.Podman([]string{"create", "-v", "/test", ALPINE, "top"})
   318  		session.WaitWithDefaultTimeout()
   319  		Expect(session.ExitCode()).To(Equal(0))
   320  
   321  		list2 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   322  		list2.WaitWithDefaultTimeout()
   323  		Expect(list2.ExitCode()).To(Equal(0))
   324  		arr := list2.OutputToStringArray()
   325  		Expect(len(arr)).To(Equal(1))
   326  		Expect(arr[0]).To(Not(Equal("")))
   327  	})
   328  
   329  	It("podman rm -v removes anonymous volume", func() {
   330  		list1 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   331  		list1.WaitWithDefaultTimeout()
   332  		Expect(list1.ExitCode()).To(Equal(0))
   333  		Expect(list1.OutputToString()).To(Equal(""))
   334  
   335  		ctrName := "testctr"
   336  		session := podmanTest.Podman([]string{"create", "--name", ctrName, "-v", "/test", ALPINE, "top"})
   337  		session.WaitWithDefaultTimeout()
   338  		Expect(session.ExitCode()).To(Equal(0))
   339  
   340  		list2 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   341  		list2.WaitWithDefaultTimeout()
   342  		Expect(list2.ExitCode()).To(Equal(0))
   343  		arr := list2.OutputToStringArray()
   344  		Expect(len(arr)).To(Equal(1))
   345  		Expect(arr[0]).To(Not(Equal("")))
   346  
   347  		remove := podmanTest.Podman([]string{"rm", "-v", ctrName})
   348  		remove.WaitWithDefaultTimeout()
   349  		Expect(remove.ExitCode()).To(Equal(0))
   350  
   351  		list3 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   352  		list3.WaitWithDefaultTimeout()
   353  		Expect(list3.ExitCode()).To(Equal(0))
   354  		Expect(list3.OutputToString()).To(Equal(""))
   355  	})
   356  
   357  	It("podman rm -v retains named volume", func() {
   358  		list1 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   359  		list1.WaitWithDefaultTimeout()
   360  		Expect(list1.ExitCode()).To(Equal(0))
   361  		Expect(list1.OutputToString()).To(Equal(""))
   362  
   363  		ctrName := "testctr"
   364  		volName := "testvol"
   365  		session := podmanTest.Podman([]string{"create", "--name", ctrName, "-v", fmt.Sprintf("%s:/test", volName), ALPINE, "top"})
   366  		session.WaitWithDefaultTimeout()
   367  		Expect(session.ExitCode()).To(Equal(0))
   368  
   369  		list2 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   370  		list2.WaitWithDefaultTimeout()
   371  		Expect(list2.ExitCode()).To(Equal(0))
   372  		arr := list2.OutputToStringArray()
   373  		Expect(len(arr)).To(Equal(1))
   374  		Expect(arr[0]).To(Equal(volName))
   375  
   376  		remove := podmanTest.Podman([]string{"rm", "-v", ctrName})
   377  		remove.WaitWithDefaultTimeout()
   378  		Expect(remove.ExitCode()).To(Equal(0))
   379  
   380  		list3 := podmanTest.Podman([]string{"volume", "list", "--quiet"})
   381  		list3.WaitWithDefaultTimeout()
   382  		Expect(list3.ExitCode()).To(Equal(0))
   383  		arr2 := list3.OutputToStringArray()
   384  		Expect(len(arr2)).To(Equal(1))
   385  		Expect(arr2[0]).To(Equal(volName))
   386  	})
   387  
   388  	It("podman run image volume is not noexec", func() {
   389  		session := podmanTest.Podman([]string{"run", "--rm", redis, "grep", "/data", "/proc/self/mountinfo"})
   390  		session.WaitWithDefaultTimeout()
   391  		Expect(session.ExitCode()).To(Equal(0))
   392  		Expect(session.OutputToString()).To(Not(ContainSubstring("noexec")))
   393  	})
   394  
   395  	It("podman mount with invalid option fails", func() {
   396  		volName := "testVol"
   397  		volCreate := podmanTest.Podman([]string{"volume", "create", "--opt", "type=tmpfs", "--opt", "device=tmpfs", "--opt", "o=invalid", volName})
   398  		volCreate.WaitWithDefaultTimeout()
   399  		Expect(volCreate.ExitCode()).To(Equal(0))
   400  
   401  		volMount := podmanTest.Podman([]string{"run", "--rm", "-v", fmt.Sprintf("%s:/tmp", volName), ALPINE, "ls"})
   402  		volMount.WaitWithDefaultTimeout()
   403  		Expect(volMount.ExitCode()).To(Not(Equal(0)))
   404  	})
   405  
   406  	It("Podman fix for CVE-2020-1726", func() {
   407  		volName := "testVol"
   408  		volCreate := podmanTest.Podman([]string{"volume", "create", volName})
   409  		volCreate.WaitWithDefaultTimeout()
   410  		Expect(volCreate.ExitCode()).To(Equal(0))
   411  
   412  		volPath := podmanTest.Podman([]string{"volume", "inspect", "--format", "{{.Mountpoint}}", volName})
   413  		volPath.WaitWithDefaultTimeout()
   414  		Expect(volPath.ExitCode()).To(Equal(0))
   415  		path := volPath.OutputToString()
   416  
   417  		fileName := "thisIsATestFile"
   418  		file, err := os.Create(filepath.Join(path, fileName))
   419  		Expect(err).To(BeNil())
   420  		defer file.Close()
   421  
   422  		runLs := podmanTest.Podman([]string{"run", "-t", "-i", "--rm", "-v", fmt.Sprintf("%v:/etc/ssl", volName), ALPINE, "ls", "-1", "/etc/ssl"})
   423  		runLs.WaitWithDefaultTimeout()
   424  		Expect(runLs.ExitCode()).To(Equal(0))
   425  		outputArr := runLs.OutputToStringArray()
   426  		Expect(len(outputArr)).To(Equal(1))
   427  		Expect(strings.Contains(outputArr[0], fileName)).To(BeTrue())
   428  	})
   429  
   430  	It("Podman mount over image volume with trailing /", func() {
   431  		image := "podman-volume-test:trailing"
   432  		dockerfile := `
   433  FROM alpine:latest
   434  VOLUME /test/`
   435  		podmanTest.BuildImage(dockerfile, image, "false")
   436  
   437  		ctrName := "testCtr"
   438  		create := podmanTest.Podman([]string{"create", "-v", "/tmp:/test", "--name", ctrName, image, "ls"})
   439  		create.WaitWithDefaultTimeout()
   440  		Expect(create.ExitCode()).To(Equal(0))
   441  
   442  		data := podmanTest.InspectContainer(ctrName)
   443  		Expect(len(data)).To(Equal(1))
   444  		Expect(len(data[0].Mounts)).To(Equal(1))
   445  		Expect(data[0].Mounts[0].Source).To(Equal("/tmp"))
   446  		Expect(data[0].Mounts[0].Destination).To(Equal("/test"))
   447  	})
   448  })