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