|
1 | 1 | package e2e_test
|
2 | 2 |
|
3 | 3 | import (
|
| 4 | + "archive/tar" |
| 5 | + "bytes" |
4 | 6 | "fmt"
|
| 7 | + "io/fs" |
5 | 8 | "os"
|
| 9 | + "path" |
6 | 10 | "path/filepath"
|
7 | 11 | "runtime"
|
| 12 | + "time" |
8 | 13 |
|
9 | 14 | . "github.com/onsi/ginkgo/v2"
|
10 | 15 | . "github.com/onsi/gomega"
|
11 | 16 | . "github.com/onsi/gomega/gexec"
|
12 | 17 | )
|
13 | 18 |
|
14 |
| -var _ = Describe("podman machine cp", func() { |
15 |
| - It("all tests", func() { |
| 19 | +var _ = Describe("run cp commands", func() { |
| 20 | + It("podman cp", func() { |
| 21 | + var ( |
| 22 | + file = "foo.txt" |
| 23 | + |
| 24 | + directory = "foo-dir" |
| 25 | + |
| 26 | + fileInDirectory = "bar.txt" |
| 27 | + |
| 28 | + stdinFile = "file.txt" |
| 29 | + |
| 30 | + stdinDirectory = "stdin-dir" |
| 31 | + ) |
| 32 | + |
| 33 | + sourceDir, err := os.MkdirTemp("", "host-source") |
| 34 | + Expect(err).ToNot(HaveOccurred()) |
| 35 | + |
| 36 | + destinationDir, err := os.MkdirTemp("", "host-destination") |
| 37 | + Expect(err).ToNot(HaveOccurred()) |
| 38 | + |
| 39 | + f, err := os.Create(filepath.Join(sourceDir, file)) |
| 40 | + Expect(err).ToNot(HaveOccurred()) |
| 41 | + err = f.Close() |
| 42 | + Expect(err).ToNot(HaveOccurred()) |
| 43 | + |
| 44 | + // Get the file stat to check permissions later |
| 45 | + sourceFileStat, err := os.Stat(filepath.Join(sourceDir, file)) |
| 46 | + Expect(err).ToNot(HaveOccurred()) |
| 47 | + |
| 48 | + err = os.MkdirAll(filepath.Join(sourceDir, directory), 0755) |
| 49 | + Expect(err).ToNot(HaveOccurred()) |
| 50 | + |
| 51 | + // Get the directory stat to check permissions later |
| 52 | + sourceDirStat, err := os.Stat(filepath.Join(sourceDir, directory)) |
| 53 | + Expect(err).ToNot(HaveOccurred()) |
| 54 | + |
| 55 | + f, err = os.Create(filepath.Join(sourceDir, directory, fileInDirectory)) |
| 56 | + Expect(err).ToNot(HaveOccurred()) |
| 57 | + err = f.Close() |
| 58 | + Expect(err).ToNot(HaveOccurred()) |
| 59 | + |
| 60 | + // Get the file in directory stat to check permissions later |
| 61 | + sourceFileInDirStat, err := os.Stat(filepath.Join(sourceDir, directory, fileInDirectory)) |
| 62 | + Expect(err).ToNot(HaveOccurred()) |
| 63 | + |
| 64 | + By("copy from host to container") |
| 65 | + name := randomString() |
| 66 | + i := new(initMachine) |
| 67 | + session, err := mb.setName(name).setCmd(i.withImage(mb.imagePath).withNow()).run() |
| 68 | + Expect(err).ToNot(HaveOccurred()) |
| 69 | + Expect(session).To(Exit(0)) |
| 70 | + |
| 71 | + bm := basicMachine{} |
| 72 | + newImgs, err := mb.setCmd(bm.withPodmanCommand([]string{"pull", TESTIMAGE})).run() |
| 73 | + Expect(err).ToNot(HaveOccurred()) |
| 74 | + Expect(newImgs).To(Exit(0)) |
| 75 | + Expect(newImgs.outputToStringSlice()).To(HaveLen(1)) |
| 76 | + |
| 77 | + createAlp, err := mb.setCmd(bm.withPodmanCommand([]string{"create", TESTIMAGE, "top"})).run() |
| 78 | + Expect(err).ToNot(HaveOccurred()) |
| 79 | + Expect(createAlp).To(Exit(0)) |
| 80 | + Expect(createAlp.outputToStringSlice()).To(HaveLen(1)) |
| 81 | + |
| 82 | + containerID := createAlp.outputToStringSlice()[0] |
| 83 | + |
| 84 | + // Copy a single file into the guest |
| 85 | + cpFile, err := mb.setCmd(bm.withPodmanCommand([]string{"cp", filepath.Join(sourceDir, file), containerID + ":/tmp/"})).run() |
| 86 | + Expect(err).ToNot(HaveOccurred()) |
| 87 | + Expect(cpFile).To(Exit(0)) |
| 88 | + |
| 89 | + // Copy a directory into the guest |
| 90 | + cpDir, err := mb.setCmd(bm.withPodmanCommand([]string{"cp", filepath.Join(sourceDir, directory), containerID + ":/tmp"})).run() |
| 91 | + Expect(err).ToNot(HaveOccurred()) |
| 92 | + Expect(cpDir).To(Exit(0)) |
| 93 | + |
| 94 | + start, err := mb.setCmd(bm.withPodmanCommand([]string{"start", containerID})).run() |
| 95 | + Expect(err).ToNot(HaveOccurred()) |
| 96 | + Expect(start).To(Exit(0)) |
| 97 | + |
| 98 | + // Check the single file is created with the appropriate mode, uid, gid |
| 99 | + exec, err := mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", path.Join("/tmp", file)})).run() |
| 100 | + Expect(err).ToNot(HaveOccurred()) |
| 101 | + Expect(exec).To(Exit(0)) |
| 102 | + execStdOut := exec.outputToStringSlice() |
| 103 | + Expect(execStdOut).To(HaveLen(1)) |
| 104 | + Expect(execStdOut[0]).To(Equal(fmt.Sprintf("%o %d %d", sourceFileStat.Mode().Perm(), 0, 0))) |
| 105 | + |
| 106 | + // Check the directory is created with the appropriate mode, uid, gid |
| 107 | + exec, err = mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", path.Join("/tmp", directory)})).run() |
| 108 | + Expect(err).ToNot(HaveOccurred()) |
| 109 | + Expect(exec).To(Exit(0)) |
| 110 | + execStdOut = exec.outputToStringSlice() |
| 111 | + Expect(execStdOut).To(HaveLen(1)) |
| 112 | + Expect(execStdOut[0]).To(Equal(fmt.Sprintf("%o %d %d", sourceDirStat.Mode().Perm(), 0, 0))) |
| 113 | + |
| 114 | + // Check the file in the directory is created with the appropriate mode, uid, gid |
| 115 | + exec, err = mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", path.Join("/tmp", directory, fileInDirectory)})).run() |
| 116 | + Expect(err).ToNot(HaveOccurred()) |
| 117 | + Expect(exec).To(Exit(0)) |
| 118 | + execStdOut = exec.outputToStringSlice() |
| 119 | + Expect(execStdOut).To(HaveLen(1)) |
| 120 | + Expect(execStdOut[0]).To(Equal(fmt.Sprintf("%o %d %d", sourceFileInDirStat.Mode().Perm(), 0, 0))) |
| 121 | + |
| 122 | + By("copy from container to host") |
| 123 | + // Copy the file back from the container to the host |
| 124 | + cpFile, err = mb.setCmd(bm.withPodmanCommand([]string{"cp", containerID + ":" + path.Join("/tmp", file), destinationDir + string(os.PathSeparator)})).run() |
| 125 | + Expect(err).ToNot(HaveOccurred()) |
| 126 | + Expect(cpFile).To(Exit(0)) |
| 127 | + |
| 128 | + // Get the file stat of the copied file to compare against the original |
| 129 | + destinationFileStat, err := os.Stat(filepath.Join(destinationDir, file)) |
| 130 | + Expect(err).ToNot(HaveOccurred()) |
| 131 | + Expect(destinationFileStat.Mode()).To(Equal(sourceFileStat.Mode())) |
| 132 | + // Compare the modification time of the file in the container and the host (with second level precision) |
| 133 | + Expect(destinationFileStat.ModTime()).To(BeTemporally("~", sourceFileStat.ModTime(), time.Second)) |
| 134 | + |
| 135 | + // Copy a directory back from the container to the host |
| 136 | + cpDir, err = mb.setCmd(bm.withPodmanCommand([]string{"cp", containerID + ":" + path.Join("/tmp", directory), destinationDir + string(os.PathSeparator)})).run() |
| 137 | + Expect(err).ToNot(HaveOccurred()) |
| 138 | + Expect(cpDir).To(Exit(0)) |
| 139 | + |
| 140 | + // Get the stat of the copied directory to compare against the original |
| 141 | + destinationDirStat, err := os.Stat(filepath.Join(destinationDir, directory)) |
| 142 | + Expect(err).ToNot(HaveOccurred()) |
| 143 | + Expect(destinationDirStat.Mode()).To(Equal(sourceDirStat.Mode())) |
| 144 | + // Compare the modification time of the folder in the container and the host (with second level precision) |
| 145 | + Expect(destinationDirStat.ModTime()).To(BeTemporally("~", sourceDirStat.ModTime(), time.Second)) |
| 146 | + |
| 147 | + // Get the stat of the copied file in the directory to compare against the original |
| 148 | + destinationFileInDirStat, err := os.Stat(filepath.Join(sourceDir, directory, fileInDirectory)) |
| 149 | + Expect(err).ToNot(HaveOccurred()) |
| 150 | + Expect(destinationFileInDirStat.Mode()).To(Equal(sourceFileInDirStat.Mode())) |
| 151 | + // Compare the modification time of the file in the container and the host (with second level precision) |
| 152 | + Expect(destinationFileInDirStat.ModTime()).To(BeTemporally("~", sourceFileInDirStat.ModTime(), time.Second)) |
| 153 | + |
| 154 | + By("copy stdin to container") |
| 155 | + now := time.Now() |
| 156 | + tarBuffer := &bytes.Buffer{} |
| 157 | + tw := tar.NewWriter(tarBuffer) |
| 158 | + |
| 159 | + // Write a directory header to the tar |
| 160 | + err = tw.WriteHeader(&tar.Header{ |
| 161 | + Name: stdinDirectory, |
| 162 | + Mode: int64(0640 | fs.ModeDir), |
| 163 | + Gid: 1000, |
| 164 | + ModTime: now, |
| 165 | + ChangeTime: now, |
| 166 | + AccessTime: now, |
| 167 | + Typeflag: tar.TypeDir, |
| 168 | + }) |
| 169 | + Expect(err).ToNot(HaveOccurred()) |
| 170 | + |
| 171 | + // Write a file header to the tar |
| 172 | + err = tw.WriteHeader(&tar.Header{ |
| 173 | + Name: path.Join(stdinDirectory, stdinFile), |
| 174 | + Mode: 0755, |
| 175 | + Uid: 1000, |
| 176 | + ModTime: now, |
| 177 | + ChangeTime: now, |
| 178 | + AccessTime: now, |
| 179 | + }) |
| 180 | + Expect(err).ToNot(HaveOccurred()) |
| 181 | + |
| 182 | + err = tw.Close() |
| 183 | + Expect(err).ToNot(HaveOccurred()) |
| 184 | + |
| 185 | + // Testing stdin copy with archive mode disabled (ownership will be determined by the tar file) |
| 186 | + cpTar, err := mb.setCmd(bm.withPodmanCommand([]string{"cp", "-a=false", "-", containerID + ":/tmp"})).setStdin(tarBuffer).run() |
| 187 | + Expect(err).ToNot(HaveOccurred()) |
| 188 | + Expect(cpTar).To(Exit(0)) |
| 189 | + |
| 190 | + // Check the directory is created with the appropriate mode, uid, gid |
| 191 | + exec, err = mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", "/tmp/stdin-dir"})).run() |
| 192 | + Expect(err).ToNot(HaveOccurred()) |
| 193 | + Expect(exec).To(Exit(0)) |
| 194 | + execStdOut = exec.outputToStringSlice() |
| 195 | + Expect(execStdOut).To(HaveLen(1)) |
| 196 | + Expect(execStdOut[0]).To(Equal("640 0 1000")) |
| 197 | + |
| 198 | + // Check the file is created with the appropriate mode, uid, gid |
| 199 | + exec, err = mb.setCmd(bm.withPodmanCommand([]string{"exec", containerID, "stat", "-c", "%a %u %g", "/tmp/stdin-dir/file.txt"})).run() |
| 200 | + Expect(err).ToNot(HaveOccurred()) |
| 201 | + Expect(exec).To(Exit(0)) |
| 202 | + execStdOut = exec.outputToStringSlice() |
| 203 | + Expect(execStdOut).To(HaveLen(1)) |
| 204 | + Expect(execStdOut[0]).To(Equal("755 1000 0")) |
| 205 | + }) |
| 206 | + |
| 207 | + It("podman machine cp", func() { |
16 | 208 | // HOST FILE SYSTEM
|
17 | 209 | // ~/<ginkgo_tmp>
|
18 | 210 | // * foo.txt
|
|
0 commit comments