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