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