github.com/wanddynosios/cli/v8@v8.7.9-0.20240221182337-1a92e3a7017f/actor/sharedaction/resource_unix_test.go (about) 1 //go:build !windows 2 // +build !windows 3 4 package sharedaction_test 5 6 import ( 7 "io/ioutil" 8 "os" 9 "path/filepath" 10 11 "code.cloudfoundry.org/cli/actor/actionerror" 12 . "code.cloudfoundry.org/cli/actor/sharedaction" 13 "code.cloudfoundry.org/cli/actor/sharedaction/sharedactionfakes" 14 "code.cloudfoundry.org/ykk" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 ) 18 19 var _ = Describe("Resource Actions", func() { 20 var ( 21 actor *Actor 22 fakeConfig *sharedactionfakes.FakeConfig 23 srcDir string 24 ) 25 26 BeforeEach(func() { 27 fakeConfig = new(sharedactionfakes.FakeConfig) 28 actor = NewActor(fakeConfig) 29 30 // Creates the following directory structure: 31 // level1/level2/tmpFile1 32 // tmpfile2 33 // tmpfile3 34 35 var err error 36 srcDir, err = ioutil.TempDir("", "v2-resource-actions") 37 Expect(err).ToNot(HaveOccurred()) 38 39 subDir := filepath.Join(srcDir, "level1", "level2") 40 err = os.MkdirAll(subDir, 0777) 41 Expect(err).ToNot(HaveOccurred()) 42 43 err = ioutil.WriteFile(filepath.Join(subDir, "tmpFile1"), []byte("why hello"), 0644) 44 Expect(err).ToNot(HaveOccurred()) 45 46 err = ioutil.WriteFile(filepath.Join(srcDir, "tmpFile2"), []byte("Hello, Binky"), 0751) 47 Expect(err).ToNot(HaveOccurred()) 48 49 err = ioutil.WriteFile(filepath.Join(srcDir, "tmpFile3"), []byte("Bananarama"), 0655) 50 Expect(err).ToNot(HaveOccurred()) 51 }) 52 53 AfterEach(func() { 54 Expect(os.RemoveAll(srcDir)).ToNot(HaveOccurred()) 55 }) 56 57 Describe("GatherArchiveResources", func() { 58 When("the archive exists", func() { 59 var ( 60 archive string 61 62 resources []Resource 63 executeErr error 64 ) 65 66 BeforeEach(func() { 67 tmpfile, err := ioutil.TempFile("", "example") 68 Expect(err).ToNot(HaveOccurred()) 69 archive = tmpfile.Name() 70 Expect(tmpfile.Close()).ToNot(HaveOccurred()) 71 }) 72 73 JustBeforeEach(func() { 74 err := zipit(srcDir, archive, "") 75 Expect(err).ToNot(HaveOccurred()) 76 77 resources, executeErr = actor.GatherArchiveResources(archive) 78 }) 79 80 AfterEach(func() { 81 Expect(os.RemoveAll(archive)).ToNot(HaveOccurred()) 82 }) 83 84 When("archive is empty", func() { 85 BeforeEach(func() { 86 var err error 87 srcDir, err = ioutil.TempDir("", "v2-resource-actions-empty") 88 Expect(err).ToNot(HaveOccurred()) 89 }) 90 91 AfterEach(func() { 92 Expect(os.RemoveAll(srcDir)).ToNot(HaveOccurred()) 93 }) 94 95 It("returns an EmptyArchiveError", func() { 96 _, err := actor.GatherArchiveResources(archive) 97 Expect(err).To(MatchError(actionerror.EmptyArchiveError{Path: archive})) 98 }) 99 }) 100 101 When("the file is a symlink to an archive", func() { 102 var symlinkToArchive string 103 104 BeforeEach(func() { 105 tempFile, err := ioutil.TempFile("", "symlink-to-archive") 106 Expect(err).ToNot(HaveOccurred()) 107 Expect(tempFile.Close()).To(Succeed()) 108 symlinkToArchive = tempFile.Name() 109 Expect(os.Remove(symlinkToArchive)).To(Succeed()) 110 111 Expect(os.Symlink(archive, symlinkToArchive)).To(Succeed()) 112 }) 113 114 JustBeforeEach(func() { 115 resources, executeErr = actor.GatherArchiveResources(symlinkToArchive) 116 }) 117 118 AfterEach(func() { 119 Expect(os.Remove(symlinkToArchive)).To(Succeed()) 120 }) 121 122 It("gathers a list of all files in a source archive", func() { 123 Expect(executeErr).ToNot(HaveOccurred()) 124 125 Expect(resources).To(Equal( 126 []Resource{ 127 {Filename: "/", Mode: DefaultFolderPermissions}, 128 {Filename: "/level1/", Mode: DefaultFolderPermissions}, 129 {Filename: "/level1/level2/", Mode: DefaultFolderPermissions}, 130 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: DefaultArchiveFilePermissions}, 131 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: DefaultArchiveFilePermissions}, 132 {Filename: "/tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: DefaultArchiveFilePermissions}, 133 })) 134 }) 135 }) 136 137 When("a .cfignore file exists in the archive", func() { 138 BeforeEach(func() { 139 err := ioutil.WriteFile(filepath.Join(srcDir, ".cfignore"), []byte("level2"), 0655) 140 Expect(err).ToNot(HaveOccurred()) 141 }) 142 143 It("excludes all patterns of files mentioned in .cfignore", func() { 144 Expect(executeErr).ToNot(HaveOccurred()) 145 146 Expect(resources).To(Equal( 147 []Resource{ 148 {Filename: "/", Mode: DefaultFolderPermissions}, 149 {Filename: "/level1/", Mode: DefaultFolderPermissions}, 150 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: DefaultArchiveFilePermissions}, 151 {Filename: "/tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: DefaultArchiveFilePermissions}, 152 })) 153 }) 154 }) 155 156 When("default ignored files exist in the archive", func() { 157 BeforeEach(func() { 158 for _, filename := range DefaultIgnoreLines { 159 if filename != ".cfignore" { 160 err := ioutil.WriteFile(filepath.Join(srcDir, filename), nil, 0655) 161 Expect(err).ToNot(HaveOccurred()) 162 err = ioutil.WriteFile(filepath.Join(srcDir, "level1", filename), nil, 0655) 163 Expect(err).ToNot(HaveOccurred()) 164 } 165 } 166 }) 167 168 It("excludes all default files", func() { 169 Expect(executeErr).ToNot(HaveOccurred()) 170 171 Expect(resources).To(Equal( 172 []Resource{ 173 {Filename: "/", Mode: DefaultFolderPermissions}, 174 {Filename: "/level1/", Mode: DefaultFolderPermissions}, 175 {Filename: "/level1/level2/", Mode: DefaultFolderPermissions}, 176 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: DefaultArchiveFilePermissions}, 177 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: DefaultArchiveFilePermissions}, 178 {Filename: "/tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: DefaultArchiveFilePermissions}, 179 })) 180 }) 181 }) 182 }) 183 184 When("the archive does not exist", func() { 185 It("returns an error if the file is problematic", func() { 186 _, err := actor.GatherArchiveResources("/does/not/exist") 187 Expect(os.IsNotExist(err)).To(BeTrue()) 188 }) 189 }) 190 }) 191 192 Describe("GatherDirectoryResources", func() { 193 When("files exist in the directory", func() { 194 var ( 195 gatheredResources []Resource 196 executeErr error 197 ) 198 199 JustBeforeEach(func() { 200 gatheredResources, executeErr = actor.GatherDirectoryResources(srcDir) 201 }) 202 203 When("the provided path is a symlink to the directory", func() { 204 var tmpDir string 205 206 BeforeEach(func() { 207 tmpDir = srcDir 208 209 tmpFile, err := ioutil.TempFile("", "symlink-file-") 210 Expect(err).ToNot(HaveOccurred()) 211 Expect(tmpFile.Close()).To(Succeed()) 212 213 srcDir = tmpFile.Name() 214 Expect(os.Remove(srcDir)).To(Succeed()) 215 Expect(os.Symlink(tmpDir, srcDir)).To(Succeed()) 216 }) 217 218 AfterEach(func() { 219 Expect(os.RemoveAll(tmpDir)).To(Succeed()) 220 }) 221 222 It("gathers a list of all directories files in a source directory", func() { 223 Expect(executeErr).ToNot(HaveOccurred()) 224 225 Expect(gatheredResources).To(Equal( 226 []Resource{ 227 {Filename: "level1", Mode: DefaultFolderPermissions}, 228 {Filename: "level1/level2", Mode: DefaultFolderPermissions}, 229 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 230 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 231 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 232 })) 233 }) 234 }) 235 236 When("a .cfignore file exists in the sourceDir", func() { 237 Context("with relative paths", func() { 238 BeforeEach(func() { 239 err := ioutil.WriteFile(filepath.Join(srcDir, ".cfignore"), []byte("level2"), 0655) 240 Expect(err).ToNot(HaveOccurred()) 241 }) 242 243 It("excludes all patterns of files mentioned in .cfignore", func() { 244 Expect(executeErr).ToNot(HaveOccurred()) 245 246 Expect(gatheredResources).To(Equal( 247 []Resource{ 248 {Filename: "level1", Mode: DefaultFolderPermissions}, 249 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 250 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 251 })) 252 }) 253 }) 254 255 Context("with absolute paths - where '/' == sourceDir", func() { 256 BeforeEach(func() { 257 err := ioutil.WriteFile(filepath.Join(srcDir, ".cfignore"), []byte("/level1/level2"), 0655) 258 Expect(err).ToNot(HaveOccurred()) 259 }) 260 261 It("excludes all patterns of files mentioned in .cfignore", func() { 262 Expect(executeErr).ToNot(HaveOccurred()) 263 264 Expect(gatheredResources).To(Equal( 265 []Resource{ 266 {Filename: "level1", Mode: DefaultFolderPermissions}, 267 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 268 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 269 })) 270 }) 271 }) 272 }) 273 274 When("default ignored files exist in the app dir", func() { 275 BeforeEach(func() { 276 for _, filename := range DefaultIgnoreLines { 277 if filename != ".cfignore" { 278 err := ioutil.WriteFile(filepath.Join(srcDir, filename), nil, 0655) 279 Expect(err).ToNot(HaveOccurred()) 280 err = ioutil.WriteFile(filepath.Join(srcDir, "level1", filename), nil, 0655) 281 Expect(err).ToNot(HaveOccurred()) 282 } 283 } 284 }) 285 286 It("excludes all default files", func() { 287 Expect(executeErr).ToNot(HaveOccurred()) 288 289 Expect(gatheredResources).To(Equal( 290 []Resource{ 291 {Filename: "level1", Mode: DefaultFolderPermissions}, 292 {Filename: "level1/level2", Mode: DefaultFolderPermissions}, 293 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 294 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 295 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 296 })) 297 }) 298 }) 299 300 When("trace files are in the source directory", func() { 301 BeforeEach(func() { 302 traceFilePath := filepath.Join(srcDir, "i-am-trace.txt") 303 err := ioutil.WriteFile(traceFilePath, nil, 0655) 304 Expect(err).ToNot(HaveOccurred()) 305 306 fakeConfig.VerboseReturns(false, []string{traceFilePath, "/some-other-path"}) 307 }) 308 309 It("excludes all of the trace files", func() { 310 Expect(executeErr).ToNot(HaveOccurred()) 311 312 Expect(gatheredResources).To(Equal( 313 []Resource{ 314 {Filename: "level1", Mode: DefaultFolderPermissions}, 315 {Filename: "level1/level2", Mode: DefaultFolderPermissions}, 316 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 317 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 318 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 319 })) 320 }) 321 }) 322 }) 323 324 When("the directory is empty", func() { 325 var emptyDir string 326 327 BeforeEach(func() { 328 var err error 329 emptyDir, err = ioutil.TempDir("", "v2-resource-actions-empty") 330 Expect(err).ToNot(HaveOccurred()) 331 }) 332 333 AfterEach(func() { 334 Expect(os.RemoveAll(emptyDir)).ToNot(HaveOccurred()) 335 }) 336 337 It("returns an EmptyDirectoryError", func() { 338 _, err := actor.GatherDirectoryResources(emptyDir) 339 Expect(err).To(MatchError(actionerror.EmptyDirectoryError{Path: emptyDir})) 340 }) 341 }) 342 }) 343 344 Describe("ZipDirectoryResources", func() { 345 var ( 346 resultZip string 347 resources []Resource 348 executeErr error 349 ) 350 351 BeforeEach(func() { 352 resources = []Resource{ 353 {Filename: "level1"}, 354 {Filename: "level1/level2"}, 355 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 356 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 357 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 358 } 359 }) 360 361 JustBeforeEach(func() { 362 resultZip, executeErr = actor.ZipDirectoryResources(srcDir, resources) 363 }) 364 365 AfterEach(func() { 366 err := os.RemoveAll(resultZip) 367 Expect(err).ToNot(HaveOccurred()) 368 }) 369 370 When("zipping on UNIX", func() { 371 It("zips the directory and keeps the file permissions", func() { 372 Expect(executeErr).ToNot(HaveOccurred()) 373 374 Expect(resultZip).ToNot(BeEmpty()) 375 zipFile, err := os.Open(resultZip) 376 Expect(err).ToNot(HaveOccurred()) 377 defer zipFile.Close() 378 379 zipInfo, err := zipFile.Stat() 380 Expect(err).ToNot(HaveOccurred()) 381 382 reader, err := ykk.NewReader(zipFile, zipInfo.Size()) 383 Expect(err).ToNot(HaveOccurred()) 384 385 Expect(reader.File).To(HaveLen(5)) 386 Expect(reader.File[2].Mode()).To(Equal(os.FileMode(0644))) 387 Expect(reader.File[3].Mode()).To(Equal(os.FileMode(0751))) 388 Expect(reader.File[4].Mode()).To(Equal(os.FileMode(0655))) 389 }) 390 }) 391 }) 392 })