github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/actor/v7pushaction/create_bits_package_for_application_test.go (about) 1 package v7pushaction_test 2 3 import ( 4 "errors" 5 "fmt" 6 7 "code.cloudfoundry.org/cli/actor/actionerror" 8 "code.cloudfoundry.org/cli/actor/sharedaction" 9 "code.cloudfoundry.org/cli/actor/v7action" 10 . "code.cloudfoundry.org/cli/actor/v7pushaction" 11 "code.cloudfoundry.org/cli/actor/v7pushaction/v7pushactionfakes" 12 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 13 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 14 . "github.com/onsi/ginkgo" 15 . "github.com/onsi/gomega" 16 ) 17 18 func buildEmptyV3Resource(name string) sharedaction.V3Resource { 19 return sharedaction.V3Resource{ 20 FilePath: name, 21 Checksum: ccv3.Checksum{Value: fmt.Sprintf("checksum-%s", name)}, 22 SizeInBytes: 0, 23 } 24 } 25 26 var _ = Describe("CreateBitsPackageForApplication", func() { 27 var ( 28 actor *Actor 29 fakeV7Actor *v7pushactionfakes.FakeV7Actor 30 fakeSharedActor *v7pushactionfakes.FakeSharedActor 31 32 returnedPushPlan PushPlan 33 paramPlan PushPlan 34 fakeProgressBar *v7pushactionfakes.FakeProgressBar 35 36 warnings Warnings 37 executeErr error 38 39 events []Event 40 ) 41 42 BeforeEach(func() { 43 actor, fakeV7Actor, fakeSharedActor = getTestPushActor() 44 45 fakeProgressBar = new(v7pushactionfakes.FakeProgressBar) 46 47 fakeSharedActor.ReadArchiveReturns(new(v7pushactionfakes.FakeReadCloser), 0, nil) 48 49 paramPlan = PushPlan{ 50 Application: v7action.Application{ 51 GUID: "some-app-guid", 52 }, 53 } 54 }) 55 56 JustBeforeEach(func() { 57 events = EventFollower(func(eventStream chan<- *PushEvent) { 58 returnedPushPlan, warnings, executeErr = actor.CreateBitsPackageForApplication(paramPlan, eventStream, fakeProgressBar) 59 }) 60 }) 61 62 Describe("package upload", func() { 63 When("resource match errors ", func() { 64 BeforeEach(func() { 65 paramPlan.AllResources = []sharedaction.V3Resource{ 66 buildV3Resource("some-filename"), 67 } 68 69 fakeV7Actor.ResourceMatchReturns( 70 nil, 71 v7action.Warnings{"some-resource-match-warning"}, 72 errors.New("resource-match-error")) 73 }) 74 75 It("raises the error", func() { 76 Expect(executeErr).To(MatchError("resource-match-error")) 77 Expect(events).To(ConsistOf(ResourceMatching)) 78 Expect(warnings).To(ConsistOf("some-resource-match-warning")) 79 }) 80 }) 81 82 When("resource match is successful", func() { 83 var ( 84 matches []sharedaction.V3Resource 85 unmatches []sharedaction.V3Resource 86 ) 87 88 When("all resources are empty", func() { 89 BeforeEach(func() { 90 emptyFiles := []sharedaction.V3Resource{ 91 buildEmptyV3Resource("empty-filename-1"), 92 buildEmptyV3Resource("empty-filename-2"), 93 } 94 95 paramPlan = PushPlan{ 96 Application: v7action.Application{ 97 Name: "some-app", 98 GUID: "some-app-guid", 99 }, 100 BitsPath: "/some-bits-path", 101 AllResources: emptyFiles, 102 } 103 }) 104 105 It("skips resource matching", func() { 106 Expect(fakeV7Actor.ResourceMatchCallCount()).To(Equal(0)) 107 }) 108 }) 109 110 When("there are unmatched resources", func() { 111 BeforeEach(func() { 112 matches = []sharedaction.V3Resource{ 113 buildV3Resource("some-matching-filename"), 114 } 115 116 unmatches = []sharedaction.V3Resource{ 117 buildV3Resource("some-unmatching-filename"), 118 } 119 120 paramPlan = PushPlan{ 121 Application: v7action.Application{ 122 Name: "some-app", 123 GUID: "some-app-guid", 124 }, 125 BitsPath: "/some-bits-path", 126 AllResources: append( 127 matches, 128 unmatches..., 129 ), 130 } 131 132 fakeV7Actor.ResourceMatchReturns( 133 matches, 134 v7action.Warnings{"some-good-good-resource-match-warnings"}, 135 nil, 136 ) 137 }) 138 139 When("the bits path is an archive", func() { 140 BeforeEach(func() { 141 paramPlan.Archive = true 142 }) 143 144 It("creates the archive with the unmatched resources", func() { 145 Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(Equal(1)) 146 bitsPath, resources := fakeSharedActor.ZipArchiveResourcesArgsForCall(0) 147 Expect(bitsPath).To(Equal("/some-bits-path")) 148 Expect(resources).To(HaveLen(1)) 149 Expect(resources[0].ToV3Resource()).To(Equal(unmatches[0])) 150 }) 151 }) 152 153 When("The bits path is a directory", func() { 154 It("creates the archive", func() { 155 Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(Equal(1)) 156 bitsPath, resources := fakeSharedActor.ZipDirectoryResourcesArgsForCall(0) 157 Expect(bitsPath).To(Equal("/some-bits-path")) 158 Expect(resources).To(HaveLen(1)) 159 Expect(resources[0].ToV3Resource()).To(Equal(unmatches[0])) 160 }) 161 }) 162 163 When("the archive creation is successful", func() { 164 BeforeEach(func() { 165 fakeSharedActor.ZipDirectoryResourcesReturns("/some/archive/path", nil) 166 fakeV7Actor.UpdateApplicationReturns( 167 v7action.Application{ 168 Name: "some-app", 169 GUID: paramPlan.Application.GUID, 170 }, 171 v7action.Warnings{"some-app-update-warnings"}, 172 nil) 173 }) 174 175 It("creates the package", func() { 176 Expect(fakeV7Actor.CreateBitsPackageByApplicationCallCount()).To(Equal(1)) 177 Expect(fakeV7Actor.CreateBitsPackageByApplicationArgsForCall(0)).To(Equal("some-app-guid")) 178 }) 179 180 When("the package creation is successful", func() { 181 BeforeEach(func() { 182 fakeV7Actor.CreateBitsPackageByApplicationReturns(v7action.Package{GUID: "some-guid"}, v7action.Warnings{"some-create-package-warning"}, nil) 183 }) 184 185 It("reads the archive", func() { 186 Expect(fakeSharedActor.ReadArchiveCallCount()).To(Equal(1)) 187 Expect(fakeSharedActor.ReadArchiveArgsForCall(0)).To(Equal("/some/archive/path")) 188 }) 189 190 When("reading the archive is successful", func() { 191 BeforeEach(func() { 192 fakeReadCloser := new(v7pushactionfakes.FakeReadCloser) 193 fakeSharedActor.ReadArchiveReturns(fakeReadCloser, 6, nil) 194 }) 195 196 It("uploads the bits package", func() { 197 Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(1)) 198 pkg, resource, _, size := fakeV7Actor.UploadBitsPackageArgsForCall(0) 199 200 Expect(pkg).To(Equal(v7action.Package{GUID: "some-guid"})) 201 Expect(resource).To(Equal(matches)) 202 Expect(size).To(BeNumerically("==", 6)) 203 }) 204 205 When("the upload is successful", func() { 206 BeforeEach(func() { 207 fakeV7Actor.UploadBitsPackageReturns(v7action.Package{GUID: "some-guid"}, v7action.Warnings{"some-upload-package-warning"}, nil) 208 }) 209 210 It("returns an upload complete event and warnings", func() { 211 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive, UploadWithArchiveComplete)) 212 Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-create-package-warning", "some-upload-package-warning")) 213 }) 214 215 When("the upload errors", func() { 216 When("the upload error is a retryable error", func() { 217 var someErr error 218 219 BeforeEach(func() { 220 someErr = errors.New("I AM A BANANA") 221 fakeV7Actor.UploadBitsPackageReturns(v7action.Package{}, v7action.Warnings{"upload-warnings-1", "upload-warnings-2"}, ccerror.PipeSeekError{Err: someErr}) 222 }) 223 224 It("should send a RetryUpload event and retry uploading", func() { 225 Expect(events).To(ConsistOf( 226 ResourceMatching, CreatingPackage, CreatingArchive, 227 ReadingArchive, UploadingApplicationWithArchive, RetryUpload, 228 ReadingArchive, UploadingApplicationWithArchive, RetryUpload, 229 ReadingArchive, UploadingApplicationWithArchive, RetryUpload, 230 )) 231 232 Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-create-package-warning", "upload-warnings-1", "upload-warnings-2", "upload-warnings-1", "upload-warnings-2", "upload-warnings-1", "upload-warnings-2")) 233 234 Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(3)) 235 Expect(executeErr).To(MatchError(actionerror.UploadFailedError{Err: someErr})) 236 }) 237 238 }) 239 240 When("the upload error is not a retryable error", func() { 241 BeforeEach(func() { 242 fakeV7Actor.UploadBitsPackageReturns(v7action.Package{}, v7action.Warnings{"upload-warnings-1", "upload-warnings-2"}, errors.New("dios mio")) 243 }) 244 245 It("sends warnings and errors, then stops", func() { 246 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive)) 247 Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-create-package-warning", "upload-warnings-1", "upload-warnings-2")) 248 Expect(executeErr).To(MatchError("dios mio")) 249 }) 250 }) 251 }) 252 }) 253 254 When("reading the archive fails", func() { 255 BeforeEach(func() { 256 fakeSharedActor.ReadArchiveReturns(nil, 0, errors.New("the bits")) 257 }) 258 259 It("returns an error", func() { 260 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive)) 261 Expect(executeErr).To(MatchError("the bits")) 262 }) 263 }) 264 }) 265 266 When("the package creation errors", func() { 267 BeforeEach(func() { 268 fakeV7Actor.CreateBitsPackageByApplicationReturns(v7action.Package{}, v7action.Warnings{"package-creation-warning"}, errors.New("the package")) 269 }) 270 271 It("it returns errors and warnings", func() { 272 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage)) 273 274 Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "package-creation-warning")) 275 Expect(executeErr).To(MatchError("the package")) 276 }) 277 }) 278 }) 279 280 When("the archive creation errors", func() { 281 BeforeEach(func() { 282 fakeSharedActor.ZipDirectoryResourcesReturns("", errors.New("oh no")) 283 }) 284 285 It("returns an error and exits", func() { 286 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive)) 287 Expect(executeErr).To(MatchError("oh no")) 288 }) 289 }) 290 }) 291 }) 292 293 When("All resources are matched", func() { 294 BeforeEach(func() { 295 matches = []sharedaction.V3Resource{ 296 buildV3Resource("some-matching-filename"), 297 } 298 299 paramPlan = PushPlan{ 300 Application: v7action.Application{ 301 Name: "some-app", 302 GUID: "some-app-guid", 303 }, 304 BitsPath: "/some-bits-path", 305 AllResources: matches, 306 } 307 308 fakeV7Actor.ResourceMatchReturns( 309 matches, 310 v7action.Warnings{"some-good-good-resource-match-warnings"}, 311 nil, 312 ) 313 }) 314 315 When("package upload succeeds", func() { 316 BeforeEach(func() { 317 fakeV7Actor.UploadBitsPackageReturns(v7action.Package{GUID: "some-guid"}, v7action.Warnings{"upload-warning"}, nil) 318 }) 319 320 It("Uploads the package without a zip", func() { 321 Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(BeZero()) 322 Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(BeZero()) 323 Expect(fakeSharedActor.ReadArchiveCallCount()).To(BeZero()) 324 325 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, UploadingApplication)) 326 Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(1)) 327 _, actualMatchedResources, actualProgressReader, actualSize := fakeV7Actor.UploadBitsPackageArgsForCall(0) 328 329 Expect(actualMatchedResources).To(Equal(matches)) 330 Expect(actualProgressReader).To(BeNil()) 331 Expect(actualSize).To(BeZero()) 332 }) 333 }) 334 335 When("package upload fails", func() { 336 BeforeEach(func() { 337 fakeV7Actor.UploadBitsPackageReturns( 338 v7action.Package{}, 339 v7action.Warnings{"upload-warning"}, 340 errors.New("upload-error"), 341 ) 342 }) 343 344 It("returns an error", func() { 345 Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(BeZero()) 346 Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(BeZero()) 347 Expect(fakeSharedActor.ReadArchiveCallCount()).To(BeZero()) 348 349 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, UploadingApplication)) 350 Expect(fakeV7Actor.UploadBitsPackageCallCount()).To(Equal(1)) 351 _, actualMatchedResources, actualProgressReader, actualSize := fakeV7Actor.UploadBitsPackageArgsForCall(0) 352 353 Expect(actualMatchedResources).To(Equal(matches)) 354 Expect(actualProgressReader).To(BeNil()) 355 Expect(actualSize).To(BeZero()) 356 357 Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "upload-warning")) 358 Expect(executeErr).To(MatchError("upload-error")) 359 }) 360 }) 361 }) 362 }) 363 }) 364 365 Describe("polling package", func() { 366 var ( 367 matches []sharedaction.V3Resource 368 unmatches []sharedaction.V3Resource 369 ) 370 371 BeforeEach(func() { 372 matches = []sharedaction.V3Resource{ 373 buildV3Resource("some-matching-filename"), 374 } 375 376 unmatches = []sharedaction.V3Resource{ 377 buildV3Resource("some-unmatching-filename"), 378 } 379 380 paramPlan = PushPlan{ 381 Application: v7action.Application{ 382 Name: "some-app", 383 GUID: "some-app-guid", 384 }, 385 BitsPath: "/some-bits-path", 386 AllResources: append( 387 matches, 388 unmatches..., 389 ), 390 } 391 392 fakeV7Actor.ResourceMatchReturns( 393 matches, 394 v7action.Warnings{"some-good-good-resource-match-warnings"}, 395 nil, 396 ) 397 }) 398 399 When("the the polling is successful", func() { 400 BeforeEach(func() { 401 fakeV7Actor.PollPackageReturns(v7action.Package{GUID: "some-package-guid"}, v7action.Warnings{"some-poll-package-warning"}, nil) 402 }) 403 404 It("returns warnings", func() { 405 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive, UploadWithArchiveComplete)) 406 Expect(warnings).To(ConsistOf("some-good-good-resource-match-warnings", "some-poll-package-warning")) 407 }) 408 409 It("sets the package guid on push plan", func() { 410 Expect(returnedPushPlan.PackageGUID).To(Equal("some-package-guid")) 411 }) 412 }) 413 414 When("the the polling returns an error", func() { 415 var someErr error 416 417 BeforeEach(func() { 418 someErr = errors.New("I AM A BANANA") 419 fakeV7Actor.PollPackageReturns(v7action.Package{}, v7action.Warnings{"some-poll-package-warning"}, someErr) 420 }) 421 422 It("returns errors and warnings", func() { 423 Expect(events).To(ConsistOf(ResourceMatching, CreatingPackage, CreatingArchive, ReadingArchive, UploadingApplicationWithArchive, UploadWithArchiveComplete)) 424 Expect(executeErr).To(MatchError(someErr)) 425 }) 426 }) 427 }) 428 })