github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+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 Context("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 Context("when the file is a symlink to an archive", func() { 84 var symlinkToArchive string 85 86 BeforeEach(func() { 87 tempFile, err := ioutil.TempFile("", "symlink-to-archive") 88 Expect(err).ToNot(HaveOccurred()) 89 Expect(tempFile.Close()).To(Succeed()) 90 symlinkToArchive = tempFile.Name() 91 Expect(os.Remove(symlinkToArchive)).To(Succeed()) 92 93 Expect(os.Symlink(archive, symlinkToArchive)).To(Succeed()) 94 }) 95 96 JustBeforeEach(func() { 97 resources, executeErr = actor.GatherArchiveResources(symlinkToArchive) 98 }) 99 100 AfterEach(func() { 101 Expect(os.Remove(symlinkToArchive)).To(Succeed()) 102 }) 103 104 It("gathers a list of all files in a source archive", func() { 105 Expect(executeErr).ToNot(HaveOccurred()) 106 107 Expect(resources).To(Equal( 108 []Resource{ 109 {Filename: "/", Mode: DefaultFolderPermissions}, 110 {Filename: "/level1/", Mode: DefaultFolderPermissions}, 111 {Filename: "/level1/level2/", Mode: DefaultFolderPermissions}, 112 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: DefaultArchiveFilePermissions}, 113 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: DefaultArchiveFilePermissions}, 114 {Filename: "/tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: DefaultArchiveFilePermissions}, 115 })) 116 }) 117 }) 118 119 Context("when a .cfignore file exists in the archive", func() { 120 BeforeEach(func() { 121 err := ioutil.WriteFile(filepath.Join(srcDir, ".cfignore"), []byte("level2"), 0655) 122 Expect(err).ToNot(HaveOccurred()) 123 }) 124 125 It("excludes all patterns of files mentioned in .cfignore", func() { 126 Expect(executeErr).ToNot(HaveOccurred()) 127 128 Expect(resources).To(Equal( 129 []Resource{ 130 {Filename: "/", Mode: DefaultFolderPermissions}, 131 {Filename: "/level1/", Mode: DefaultFolderPermissions}, 132 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: DefaultArchiveFilePermissions}, 133 {Filename: "/tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: DefaultArchiveFilePermissions}, 134 })) 135 }) 136 }) 137 138 Context("when default ignored files exist in the archive", func() { 139 BeforeEach(func() { 140 for _, filename := range DefaultIgnoreLines { 141 if filename != ".cfignore" { 142 err := ioutil.WriteFile(filepath.Join(srcDir, filename), nil, 0655) 143 Expect(err).ToNot(HaveOccurred()) 144 err = ioutil.WriteFile(filepath.Join(srcDir, "level1", filename), nil, 0655) 145 Expect(err).ToNot(HaveOccurred()) 146 } 147 } 148 }) 149 150 It("excludes all default files", func() { 151 Expect(executeErr).ToNot(HaveOccurred()) 152 153 Expect(resources).To(Equal( 154 []Resource{ 155 {Filename: "/", Mode: DefaultFolderPermissions}, 156 {Filename: "/level1/", Mode: DefaultFolderPermissions}, 157 {Filename: "/level1/level2/", Mode: DefaultFolderPermissions}, 158 {Filename: "/level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: DefaultArchiveFilePermissions}, 159 {Filename: "/tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: DefaultArchiveFilePermissions}, 160 {Filename: "/tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: DefaultArchiveFilePermissions}, 161 })) 162 }) 163 }) 164 }) 165 166 Context("when the archive does not exist", func() { 167 It("returns an error if the file is problematic", func() { 168 _, err := actor.GatherArchiveResources("/does/not/exist") 169 Expect(os.IsNotExist(err)).To(BeTrue()) 170 }) 171 }) 172 }) 173 174 Describe("GatherDirectoryResources", func() { 175 Context("when files exist in the directory", func() { 176 var ( 177 gatheredResources []Resource 178 executeErr error 179 ) 180 181 JustBeforeEach(func() { 182 gatheredResources, executeErr = actor.GatherDirectoryResources(srcDir) 183 }) 184 185 Context("when the provided path is a symlink to the directory", func() { 186 var tmpDir string 187 188 BeforeEach(func() { 189 tmpDir = srcDir 190 191 tmpFile, err := ioutil.TempFile("", "symlink-file-") 192 Expect(err).ToNot(HaveOccurred()) 193 Expect(tmpFile.Close()).To(Succeed()) 194 195 srcDir = tmpFile.Name() 196 Expect(os.Remove(srcDir)).To(Succeed()) 197 Expect(os.Symlink(tmpDir, srcDir)).To(Succeed()) 198 }) 199 200 AfterEach(func() { 201 Expect(os.RemoveAll(tmpDir)).To(Succeed()) 202 }) 203 204 It("gathers a list of all directories files in a source directory", func() { 205 Expect(executeErr).ToNot(HaveOccurred()) 206 207 Expect(gatheredResources).To(Equal( 208 []Resource{ 209 {Filename: "level1", Mode: DefaultFolderPermissions}, 210 {Filename: "level1/level2", Mode: DefaultFolderPermissions}, 211 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 212 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 213 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 214 })) 215 }) 216 }) 217 218 Context("when a .cfignore file exists in the sourceDir", func() { 219 Context("with relative paths", func() { 220 BeforeEach(func() { 221 err := ioutil.WriteFile(filepath.Join(srcDir, ".cfignore"), []byte("level2"), 0655) 222 Expect(err).ToNot(HaveOccurred()) 223 }) 224 225 It("excludes all patterns of files mentioned in .cfignore", func() { 226 Expect(executeErr).ToNot(HaveOccurred()) 227 228 Expect(gatheredResources).To(Equal( 229 []Resource{ 230 {Filename: "level1", Mode: DefaultFolderPermissions}, 231 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 232 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 233 })) 234 }) 235 }) 236 237 Context("with absolute paths - where '/' == sourceDir", func() { 238 BeforeEach(func() { 239 err := ioutil.WriteFile(filepath.Join(srcDir, ".cfignore"), []byte("/level1/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 256 Context("when default ignored files exist in the app dir", func() { 257 BeforeEach(func() { 258 for _, filename := range DefaultIgnoreLines { 259 if filename != ".cfignore" { 260 err := ioutil.WriteFile(filepath.Join(srcDir, filename), nil, 0655) 261 Expect(err).ToNot(HaveOccurred()) 262 err = ioutil.WriteFile(filepath.Join(srcDir, "level1", filename), nil, 0655) 263 Expect(err).ToNot(HaveOccurred()) 264 } 265 } 266 }) 267 268 It("excludes all default files", func() { 269 Expect(executeErr).ToNot(HaveOccurred()) 270 271 Expect(gatheredResources).To(Equal( 272 []Resource{ 273 {Filename: "level1", Mode: DefaultFolderPermissions}, 274 {Filename: "level1/level2", Mode: DefaultFolderPermissions}, 275 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 276 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 277 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 278 })) 279 }) 280 }) 281 282 Context("when trace files are in the source directory", func() { 283 BeforeEach(func() { 284 traceFilePath := filepath.Join(srcDir, "i-am-trace.txt") 285 err := ioutil.WriteFile(traceFilePath, nil, 0655) 286 Expect(err).ToNot(HaveOccurred()) 287 288 fakeConfig.VerboseReturns(false, []string{traceFilePath, "/some-other-path"}) 289 }) 290 291 It("excludes all of the trace files", func() { 292 Expect(executeErr).ToNot(HaveOccurred()) 293 294 Expect(gatheredResources).To(Equal( 295 []Resource{ 296 {Filename: "level1", Mode: DefaultFolderPermissions}, 297 {Filename: "level1/level2", Mode: DefaultFolderPermissions}, 298 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 299 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 300 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 301 })) 302 }) 303 }) 304 }) 305 306 Context("when the directory is empty", func() { 307 var emptyDir string 308 309 BeforeEach(func() { 310 var err error 311 emptyDir, err = ioutil.TempDir("", "v2-resource-actions-empty") 312 Expect(err).ToNot(HaveOccurred()) 313 }) 314 315 AfterEach(func() { 316 Expect(os.RemoveAll(emptyDir)).ToNot(HaveOccurred()) 317 }) 318 319 It("returns an EmptyDirectoryError", func() { 320 _, err := actor.GatherDirectoryResources(emptyDir) 321 Expect(err).To(MatchError(actionerror.EmptyDirectoryError{Path: emptyDir})) 322 }) 323 }) 324 }) 325 326 Describe("ZipDirectoryResources", func() { 327 var ( 328 resultZip string 329 resources []Resource 330 executeErr error 331 ) 332 333 BeforeEach(func() { 334 resources = []Resource{ 335 {Filename: "level1"}, 336 {Filename: "level1/level2"}, 337 {Filename: "level1/level2/tmpFile1", SHA1: "9e36efec86d571de3a38389ea799a796fe4782f4", Size: 9, Mode: 0644}, 338 {Filename: "tmpFile2", SHA1: "e594bdc795bb293a0e55724137e53a36dc0d9e95", Size: 12, Mode: 0751}, 339 {Filename: "tmpFile3", SHA1: "f4c9ca85f3e084ffad3abbdabbd2a890c034c879", Size: 10, Mode: 0655}, 340 } 341 }) 342 343 JustBeforeEach(func() { 344 resultZip, executeErr = actor.ZipDirectoryResources(srcDir, resources) 345 }) 346 347 AfterEach(func() { 348 err := os.RemoveAll(resultZip) 349 Expect(err).ToNot(HaveOccurred()) 350 }) 351 352 Context("when zipping on UNIX", func() { 353 It("zips the directory and keeps the file permissions", func() { 354 Expect(executeErr).ToNot(HaveOccurred()) 355 356 Expect(resultZip).ToNot(BeEmpty()) 357 zipFile, err := os.Open(resultZip) 358 Expect(err).ToNot(HaveOccurred()) 359 defer zipFile.Close() 360 361 zipInfo, err := zipFile.Stat() 362 Expect(err).ToNot(HaveOccurred()) 363 364 reader, err := ykk.NewReader(zipFile, zipInfo.Size()) 365 Expect(err).ToNot(HaveOccurred()) 366 367 Expect(reader.File).To(HaveLen(5)) 368 Expect(reader.File[2].Mode()).To(Equal(os.FileMode(0644))) 369 Expect(reader.File[3].Mode()).To(Equal(os.FileMode(0751))) 370 Expect(reader.File[4].Mode()).To(Equal(os.FileMode(0655))) 371 }) 372 }) 373 }) 374 })