github.com/hanks177/podman/v4@v4.1.3-0.20220613032544-16d90015bc83/test/e2e/cp_test.go (about)

     1  package integration
     2  
     3  import (
     4  	"io/ioutil"
     5  	"os"
     6  	"os/exec"
     7  	"os/user"
     8  	"path/filepath"
     9  
    10  	. "github.com/hanks177/podman/v4/test/utils"
    11  	. "github.com/onsi/ginkgo"
    12  	. "github.com/onsi/gomega"
    13  	. "github.com/onsi/gomega/gexec"
    14  )
    15  
    16  // NOTE: Only smoke tests.  The system tests (i.e., "./test/system/*") take
    17  // care of function and regression tests.  Please consider adding system tests
    18  // rather than e2e tests.  System tests are used in RHEL gating.
    19  
    20  var _ = Describe("Podman cp", func() {
    21  	var (
    22  		tempdir    string
    23  		err        error
    24  		podmanTest *PodmanTestIntegration
    25  	)
    26  
    27  	BeforeEach(func() {
    28  		tempdir, err = CreateTempDirInTempDir()
    29  		if err != nil {
    30  			os.Exit(1)
    31  		}
    32  		podmanTest = PodmanTestCreate(tempdir)
    33  		podmanTest.Setup()
    34  	})
    35  
    36  	AfterEach(func() {
    37  		podmanTest.Cleanup()
    38  		f := CurrentGinkgoTestDescription()
    39  		processTestResult(f)
    40  
    41  	})
    42  
    43  	// Copy a file to the container, then back to the host and make sure
    44  	// that the contents match.
    45  	It("podman cp file", func() {
    46  		srcFile, err := ioutil.TempFile("", "")
    47  		Expect(err).To(BeNil())
    48  		defer srcFile.Close()
    49  		defer os.Remove(srcFile.Name())
    50  
    51  		originalContent := []byte("podman cp file test")
    52  		err = ioutil.WriteFile(srcFile.Name(), originalContent, 0644)
    53  		Expect(err).To(BeNil())
    54  
    55  		// Create a container. NOTE that container mustn't be running for copying.
    56  		session := podmanTest.Podman([]string{"create", ALPINE})
    57  		session.WaitWithDefaultTimeout()
    58  		Expect(session).Should(Exit(0))
    59  		name := session.OutputToString()
    60  
    61  		// Copy TO the container.
    62  
    63  		// Cannot copy to a nonexistent path (note the trailing "/").
    64  		session = podmanTest.Podman([]string{"cp", srcFile.Name(), name + ":foo/"})
    65  		session.WaitWithDefaultTimeout()
    66  		Expect(session).To(ExitWithError())
    67  
    68  		// The file will now be created (and written to).
    69  		session = podmanTest.Podman([]string{"cp", srcFile.Name(), name + ":foo"})
    70  		session.WaitWithDefaultTimeout()
    71  		Expect(session).Should(Exit(0))
    72  
    73  		// Copy FROM the container.
    74  
    75  		destFile, err := ioutil.TempFile("", "")
    76  		Expect(err).To(BeNil())
    77  		defer destFile.Close()
    78  		defer os.Remove(destFile.Name())
    79  
    80  		session = podmanTest.Podman([]string{"cp", name + ":foo", destFile.Name()})
    81  		session.WaitWithDefaultTimeout()
    82  		Expect(session).Should(Exit(0))
    83  
    84  		session = podmanTest.Podman([]string{"start", name})
    85  		session.WaitWithDefaultTimeout()
    86  		Expect(session).Should(Exit(0))
    87  
    88  		// Now make sure the content matches.
    89  		roundtripContent, err := ioutil.ReadFile(destFile.Name())
    90  		Expect(err).To(BeNil())
    91  		Expect(roundtripContent).To(Equal(originalContent))
    92  	})
    93  
    94  	// Copy a file to the container, then back to the host in --pid=host
    95  	It("podman cp --pid=host file", func() {
    96  		SkipIfRootlessCgroupsV1("Not supported for rootless + CgroupsV1")
    97  		srcFile, err := ioutil.TempFile("", "")
    98  		Expect(err).To(BeNil())
    99  		defer srcFile.Close()
   100  		defer os.Remove(srcFile.Name())
   101  
   102  		originalContent := []byte("podman cp file test")
   103  		err = ioutil.WriteFile(srcFile.Name(), originalContent, 0644)
   104  		Expect(err).To(BeNil())
   105  
   106  		// Create a container. NOTE that container mustn't be running for copying.
   107  		session := podmanTest.Podman([]string{"create", "--pid=host", ALPINE, "top"})
   108  		session.WaitWithDefaultTimeout()
   109  		Expect(session).Should(Exit(0))
   110  		name := session.OutputToString()
   111  
   112  		session = podmanTest.Podman([]string{"start", name})
   113  		session.WaitWithDefaultTimeout()
   114  		Expect(session).Should(Exit(0))
   115  
   116  		// The file will now be created (and written to).
   117  		session = podmanTest.Podman([]string{"cp", srcFile.Name(), name + ":foo"})
   118  		session.WaitWithDefaultTimeout()
   119  		Expect(session).Should(Exit(0))
   120  
   121  		// Copy FROM the container.
   122  
   123  		destFile, err := ioutil.TempFile("", "")
   124  		Expect(err).To(BeNil())
   125  		defer destFile.Close()
   126  		defer os.Remove(destFile.Name())
   127  
   128  		session = podmanTest.Podman([]string{"cp", name + ":foo", destFile.Name()})
   129  		session.WaitWithDefaultTimeout()
   130  		Expect(session).Should(Exit(0))
   131  
   132  		// Now make sure the content matches.
   133  		roundtripContent, err := ioutil.ReadFile(destFile.Name())
   134  		Expect(err).To(BeNil())
   135  		Expect(roundtripContent).To(Equal(originalContent))
   136  	})
   137  
   138  	// Create a symlink in the container, use it as a copy destination and
   139  	// make sure that the link and the resolved path are accessible and
   140  	// give the right content.
   141  	It("podman cp symlink", func() {
   142  		srcFile, err := ioutil.TempFile("", "")
   143  		Expect(err).To(BeNil())
   144  		defer srcFile.Close()
   145  		defer os.Remove(srcFile.Name())
   146  
   147  		originalContent := []byte("podman cp symlink test")
   148  		err = ioutil.WriteFile(srcFile.Name(), originalContent, 0644)
   149  		Expect(err).To(BeNil())
   150  
   151  		session := podmanTest.Podman([]string{"run", "-d", ALPINE, "top"})
   152  		session.WaitWithDefaultTimeout()
   153  		Expect(session).Should(Exit(0))
   154  		name := session.OutputToString()
   155  
   156  		session = podmanTest.Podman([]string{"exec", name, "ln", "-s", "/tmp", "/test"})
   157  		session.WaitWithDefaultTimeout()
   158  		Expect(session).Should(Exit(0))
   159  
   160  		session = podmanTest.Podman([]string{"cp", "--pause=false", srcFile.Name(), name + ":/test"})
   161  		session.WaitWithDefaultTimeout()
   162  		Expect(session).Should(Exit(0))
   163  
   164  		session = podmanTest.Podman([]string{"exec", name, "cat", "/tmp/" + filepath.Base(srcFile.Name())})
   165  		session.WaitWithDefaultTimeout()
   166  		Expect(session).Should(Exit(0))
   167  		Expect(session.OutputToString()).To(ContainSubstring(string(originalContent)))
   168  
   169  		session = podmanTest.Podman([]string{"exec", name, "cat", "/test/" + filepath.Base(srcFile.Name())})
   170  		session.WaitWithDefaultTimeout()
   171  		Expect(session).Should(Exit(0))
   172  		Expect(session.OutputToString()).To(ContainSubstring(string(originalContent)))
   173  	})
   174  
   175  	// Copy a file to a volume in the container.  The tricky part is that
   176  	// containers mustn't be running for copying, so Podman has to do some
   177  	// intense Yoga and 1) detect volume paths on the container, 2) resolve
   178  	// the path to the volume's mount point on the host, and 3) copy the
   179  	// data to the volume and not the container.
   180  	It("podman cp volume", func() {
   181  		srcFile, err := ioutil.TempFile("", "")
   182  		Expect(err).To(BeNil())
   183  		defer srcFile.Close()
   184  		defer os.Remove(srcFile.Name())
   185  
   186  		originalContent := []byte("podman cp volume")
   187  		err = ioutil.WriteFile(srcFile.Name(), originalContent, 0644)
   188  		Expect(err).To(BeNil())
   189  		session := podmanTest.Podman([]string{"volume", "create", "data"})
   190  		session.WaitWithDefaultTimeout()
   191  		Expect(session).Should(Exit(0))
   192  
   193  		session = podmanTest.Podman([]string{"create", "-v", "data:/data", "--name", "container1", ALPINE})
   194  		session.WaitWithDefaultTimeout()
   195  		Expect(session).Should(Exit(0))
   196  
   197  		session = podmanTest.Podman([]string{"cp", srcFile.Name(), "container1" + ":/data/file.txt"})
   198  		session.WaitWithDefaultTimeout()
   199  		Expect(session).Should(Exit(0))
   200  
   201  		// Now get the volume's mount point, read the file and make
   202  		// sure the contents match.
   203  		session = podmanTest.Podman([]string{"volume", "inspect", "data", "--format", "{{.Mountpoint}}"})
   204  		session.WaitWithDefaultTimeout()
   205  		Expect(session).Should(Exit(0))
   206  
   207  		volumeMountPoint := session.OutputToString()
   208  		copiedContent, err := ioutil.ReadFile(filepath.Join(volumeMountPoint, "file.txt"))
   209  		Expect(err).To(BeNil())
   210  		Expect(copiedContent).To(Equal(originalContent))
   211  	})
   212  
   213  	// Create another user in the container, let them create a file, copy
   214  	// it to the host and back to the container and make sure that we can
   215  	// access it, and (roughly) the right users own it.
   216  	It("podman cp from ctr chown ", func() {
   217  		srcFile, err := ioutil.TempFile("", "")
   218  		Expect(err).To(BeNil())
   219  		defer srcFile.Close()
   220  		defer os.Remove(srcFile.Name())
   221  
   222  		setup := podmanTest.RunTopContainer("testctr")
   223  		setup.WaitWithDefaultTimeout()
   224  		Expect(setup).Should(Exit(0))
   225  
   226  		session := podmanTest.Podman([]string{"exec", "testctr", "adduser", "-S", "testuser"})
   227  		session.WaitWithDefaultTimeout()
   228  		Expect(session).Should(Exit(0))
   229  
   230  		session = podmanTest.Podman([]string{"exec", "-u", "testuser", "testctr", "touch", "/tmp/testfile"})
   231  		session.WaitWithDefaultTimeout()
   232  		Expect(session).Should(Exit(0))
   233  
   234  		session = podmanTest.Podman([]string{"cp", "--pause=false", "testctr:/tmp/testfile", srcFile.Name()})
   235  		session.WaitWithDefaultTimeout()
   236  		Expect(session).Should(Exit(0))
   237  
   238  		// owner of the file copied to local machine is not testuser
   239  		u, err := user.Current()
   240  		Expect(err).To(BeNil())
   241  		cmd := exec.Command("ls", "-l", srcFile.Name())
   242  		cmdRet, err := cmd.Output()
   243  		Expect(err).To(BeNil())
   244  		Expect(string(cmdRet)).To(ContainSubstring(u.Username))
   245  
   246  		session = podmanTest.Podman([]string{"cp", "--pause=false", srcFile.Name(), "testctr:testfile2"})
   247  		session.WaitWithDefaultTimeout()
   248  		Expect(session).Should(Exit(0))
   249  
   250  		// owner of the file copied to a container is the root user
   251  		session = podmanTest.Podman([]string{"exec", "-it", "testctr", "ls", "-l", "testfile2"})
   252  		session.WaitWithDefaultTimeout()
   253  		Expect(session).Should(Exit(0))
   254  		Expect(session.OutputToString()).To(ContainSubstring("root"))
   255  	})
   256  
   257  	// Copy the root dir "/" of a container to the host.
   258  	It("podman cp the root directory from the ctr to an existing directory on the host ", func() {
   259  		container := "copyroottohost"
   260  		session := podmanTest.RunTopContainer(container)
   261  		session.WaitWithDefaultTimeout()
   262  		Expect(session).Should(Exit(0))
   263  
   264  		session = podmanTest.Podman([]string{"exec", container, "touch", "/dummy.txt"})
   265  		session.WaitWithDefaultTimeout()
   266  		Expect(session).Should(Exit(0))
   267  
   268  		tmpDir, err := ioutil.TempDir("", "")
   269  		Expect(err).To(BeNil())
   270  
   271  		session = podmanTest.Podman([]string{"cp", container + ":/", tmpDir})
   272  		session.WaitWithDefaultTimeout()
   273  		Expect(session).Should(Exit(0))
   274  
   275  		cmd := exec.Command("ls", "-la", tmpDir)
   276  		output, err := cmd.Output()
   277  		lsOutput := string(output)
   278  		Expect(err).To(BeNil())
   279  		Expect(lsOutput).To(ContainSubstring("dummy.txt"))
   280  		Expect(lsOutput).To(ContainSubstring("tmp"))
   281  		Expect(lsOutput).To(ContainSubstring("etc"))
   282  		Expect(lsOutput).To(ContainSubstring("var"))
   283  		Expect(lsOutput).To(ContainSubstring("bin"))
   284  		Expect(lsOutput).To(ContainSubstring("usr"))
   285  	})
   286  })