github.com/lukasheimann/cloudfoundrycli@v7.1.0+incompatible/actor/v7action/package_test.go (about) 1 package v7action_test 2 3 import ( 4 "errors" 5 "io" 6 "io/ioutil" 7 "os" 8 "strings" 9 10 "code.cloudfoundry.org/cli/actor/actionerror" 11 "code.cloudfoundry.org/cli/actor/sharedaction" 12 . "code.cloudfoundry.org/cli/actor/v7action" 13 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 14 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 15 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 16 "code.cloudfoundry.org/cli/resources" 17 18 . "github.com/onsi/ginkgo" 19 . "github.com/onsi/ginkgo/extensions/table" 20 . "github.com/onsi/gomega" 21 . "github.com/onsi/gomega/gstruct" 22 ) 23 24 var _ = Describe("Package Actions", func() { 25 var ( 26 actor *Actor 27 fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient 28 fakeSharedActor *v7actionfakes.FakeSharedActor 29 fakeConfig *v7actionfakes.FakeConfig 30 ) 31 32 BeforeEach(func() { 33 fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient) 34 fakeConfig = new(v7actionfakes.FakeConfig) 35 fakeSharedActor = new(v7actionfakes.FakeSharedActor) 36 actor = NewActor(fakeCloudControllerClient, fakeConfig, fakeSharedActor, nil, nil, nil) 37 }) 38 39 Describe("GetApplicationPackages", func() { 40 When("there are no client errors", func() { 41 BeforeEach(func() { 42 fakeCloudControllerClient.GetApplicationsReturns( 43 []resources.Application{ 44 {GUID: "some-app-guid"}, 45 }, 46 ccv3.Warnings{"get-applications-warning"}, 47 nil, 48 ) 49 50 fakeCloudControllerClient.GetPackagesReturns( 51 []ccv3.Package{ 52 { 53 GUID: "some-package-guid-1", 54 State: constant.PackageReady, 55 CreatedAt: "2017-08-14T21:16:42Z", 56 }, 57 { 58 GUID: "some-package-guid-2", 59 State: constant.PackageFailed, 60 CreatedAt: "2017-08-16T00:18:24Z", 61 }, 62 }, 63 ccv3.Warnings{"get-application-packages-warning"}, 64 nil, 65 ) 66 }) 67 68 It("gets the app's packages", func() { 69 packages, warnings, err := actor.GetApplicationPackages("some-app-name", "some-space-guid") 70 71 Expect(err).ToNot(HaveOccurred()) 72 Expect(warnings).To(ConsistOf("get-applications-warning", "get-application-packages-warning")) 73 Expect(packages).To(Equal([]Package{ 74 { 75 GUID: "some-package-guid-1", 76 State: constant.PackageReady, 77 CreatedAt: "2017-08-14T21:16:42Z", 78 }, 79 { 80 GUID: "some-package-guid-2", 81 State: constant.PackageFailed, 82 CreatedAt: "2017-08-16T00:18:24Z", 83 }, 84 })) 85 86 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 87 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 88 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}}, 89 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 90 )) 91 92 Expect(fakeCloudControllerClient.GetPackagesCallCount()).To(Equal(1)) 93 Expect(fakeCloudControllerClient.GetPackagesArgsForCall(0)).To(ConsistOf( 94 ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{"some-app-guid"}}, 95 ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, 96 )) 97 }) 98 }) 99 100 When("getting the application fails", func() { 101 var expectedErr error 102 103 BeforeEach(func() { 104 expectedErr = errors.New("some get application error") 105 106 fakeCloudControllerClient.GetApplicationsReturns( 107 []resources.Application{}, 108 ccv3.Warnings{"get-applications-warning"}, 109 expectedErr, 110 ) 111 }) 112 113 It("returns the error", func() { 114 _, warnings, err := actor.GetApplicationPackages("some-app-name", "some-space-guid") 115 116 Expect(err).To(Equal(expectedErr)) 117 Expect(warnings).To(ConsistOf("get-applications-warning")) 118 }) 119 }) 120 121 When("getting the application packages fails", func() { 122 var expectedErr error 123 124 BeforeEach(func() { 125 expectedErr = errors.New("some get application error") 126 127 fakeCloudControllerClient.GetApplicationsReturns( 128 []resources.Application{ 129 {GUID: "some-app-guid"}, 130 }, 131 ccv3.Warnings{"get-applications-warning"}, 132 nil, 133 ) 134 135 fakeCloudControllerClient.GetPackagesReturns( 136 []ccv3.Package{}, 137 ccv3.Warnings{"get-application-packages-warning"}, 138 expectedErr, 139 ) 140 }) 141 142 It("returns the error", func() { 143 _, warnings, err := actor.GetApplicationPackages("some-app-name", "some-space-guid") 144 145 Expect(err).To(Equal(expectedErr)) 146 Expect(warnings).To(ConsistOf("get-applications-warning", "get-application-packages-warning")) 147 }) 148 }) 149 }) 150 151 Describe("GetNewestReadyPackageForApplication", func() { 152 var ( 153 app resources.Application 154 executeErr error 155 156 warnings Warnings 157 ) 158 159 BeforeEach(func() { 160 app = resources.Application{ 161 GUID: "some-app-guid", 162 Name: "some-app", 163 } 164 }) 165 166 When("the GetNewestReadyPackageForApplication call succeeds", func() { 167 When("the cloud controller finds a package", func() { 168 BeforeEach(func() { 169 fakeCloudControllerClient.GetPackagesReturns( 170 []ccv3.Package{ 171 { 172 GUID: "some-package-guid-1", 173 State: constant.PackageReady, 174 CreatedAt: "2017-08-14T21:16:42Z", 175 }, 176 { 177 GUID: "some-package-guid-2", 178 State: constant.PackageReady, 179 CreatedAt: "2017-08-16T00:18:24Z", 180 }, 181 }, 182 ccv3.Warnings{"get-application-packages-warning"}, 183 nil, 184 ) 185 }) 186 It("gets the most recent package for the given app guid that has a ready state", func() { 187 expectedPackage, warnings, err := actor.GetNewestReadyPackageForApplication(app) 188 189 Expect(fakeCloudControllerClient.GetPackagesCallCount()).To(Equal(1)) 190 Expect(fakeCloudControllerClient.GetPackagesArgsForCall(0)).To(ConsistOf( 191 ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{"some-app-guid"}}, 192 ccv3.Query{Key: ccv3.StatesFilter, Values: []string{"READY"}}, 193 ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, 194 )) 195 196 Expect(err).ToNot(HaveOccurred()) 197 Expect(warnings).To(ConsistOf("get-application-packages-warning")) 198 Expect(expectedPackage).To(Equal(Package{ 199 GUID: "some-package-guid-1", 200 State: constant.PackageReady, 201 CreatedAt: "2017-08-14T21:16:42Z", 202 }, 203 )) 204 }) 205 }) 206 207 When("the cloud controller does not find any packages", func() { 208 BeforeEach(func() { 209 fakeCloudControllerClient.GetPackagesReturns( 210 []ccv3.Package{}, 211 ccv3.Warnings{"get-application-packages-warning"}, 212 nil, 213 ) 214 }) 215 216 JustBeforeEach(func() { 217 _, warnings, executeErr = actor.GetNewestReadyPackageForApplication(app) 218 }) 219 220 It("returns an error and warnings", func() { 221 Expect(executeErr).To(MatchError(actionerror.NoEligiblePackagesError{AppName: "some-app"})) 222 Expect(warnings).To(ConsistOf("get-application-packages-warning")) 223 }) 224 }) 225 226 }) 227 When("getting the application packages fails", func() { 228 var expectedErr error 229 230 BeforeEach(func() { 231 expectedErr = errors.New("get-packages-error") 232 233 fakeCloudControllerClient.GetPackagesReturns( 234 []ccv3.Package{}, 235 ccv3.Warnings{"get-packages-warning"}, 236 expectedErr, 237 ) 238 }) 239 240 It("returns the error", func() { 241 _, warnings, err := actor.GetNewestReadyPackageForApplication(app) 242 243 Expect(err).To(Equal(expectedErr)) 244 Expect(warnings).To(ConsistOf("get-packages-warning")) 245 }) 246 }) 247 }) 248 249 Describe("CreateDockerPackageByApplicationNameAndSpace", func() { 250 var ( 251 dockerPackage Package 252 warnings Warnings 253 executeErr error 254 ) 255 256 JustBeforeEach(func() { 257 dockerPackage, warnings, executeErr = actor.CreateDockerPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", DockerImageCredentials{Path: "some-docker-image", Password: "some-password", Username: "some-username"}) 258 }) 259 260 When("the application can't be retrieved", func() { 261 BeforeEach(func() { 262 fakeCloudControllerClient.GetApplicationsReturns( 263 []resources.Application{}, 264 ccv3.Warnings{"some-app-warning"}, 265 errors.New("some-app-error"), 266 ) 267 }) 268 269 It("returns the error and all warnings", func() { 270 Expect(executeErr).To(MatchError("some-app-error")) 271 Expect(warnings).To(ConsistOf("some-app-warning")) 272 }) 273 }) 274 275 When("the application can be retrieved", func() { 276 BeforeEach(func() { 277 fakeCloudControllerClient.GetApplicationsReturns( 278 []resources.Application{ 279 { 280 Name: "some-app-name", 281 GUID: "some-app-guid", 282 }, 283 }, 284 ccv3.Warnings{"some-app-warning"}, 285 nil, 286 ) 287 }) 288 289 When("creating the package fails", func() { 290 BeforeEach(func() { 291 fakeCloudControllerClient.CreatePackageReturns( 292 ccv3.Package{}, 293 ccv3.Warnings{"some-create-package-warning"}, 294 errors.New("some-create-package-error"), 295 ) 296 }) 297 It("fails to create the package", func() { 298 Expect(executeErr).To(MatchError("some-create-package-error")) 299 Expect(warnings).To(ConsistOf("some-app-warning", "some-create-package-warning")) 300 }) 301 }) 302 303 When("creating the package succeeds", func() { 304 BeforeEach(func() { 305 createdPackage := ccv3.Package{ 306 DockerImage: "some-docker-image", 307 DockerUsername: "some-username", 308 DockerPassword: "some-password", 309 GUID: "some-pkg-guid", 310 State: constant.PackageReady, 311 Relationships: resources.Relationships{ 312 constant.RelationshipTypeApplication: resources.Relationship{ 313 GUID: "some-app-guid", 314 }, 315 }, 316 } 317 318 fakeCloudControllerClient.CreatePackageReturns( 319 createdPackage, 320 ccv3.Warnings{"some-create-package-warning"}, 321 nil, 322 ) 323 }) 324 325 It("calls CC to create the package and returns the package", func() { 326 Expect(executeErr).ToNot(HaveOccurred()) 327 Expect(warnings).To(ConsistOf("some-app-warning", "some-create-package-warning")) 328 329 expectedPackage := ccv3.Package{ 330 DockerImage: "some-docker-image", 331 DockerUsername: "some-username", 332 DockerPassword: "some-password", 333 GUID: "some-pkg-guid", 334 State: constant.PackageReady, 335 Relationships: resources.Relationships{ 336 constant.RelationshipTypeApplication: resources.Relationship{ 337 GUID: "some-app-guid", 338 }, 339 }, 340 } 341 Expect(dockerPackage).To(Equal(Package(expectedPackage))) 342 343 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 344 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 345 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}}, 346 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 347 )) 348 349 Expect(fakeCloudControllerClient.CreatePackageCallCount()).To(Equal(1)) 350 Expect(fakeCloudControllerClient.CreatePackageArgsForCall(0)).To(Equal(ccv3.Package{ 351 Type: constant.PackageTypeDocker, 352 DockerImage: "some-docker-image", 353 DockerUsername: "some-username", 354 DockerPassword: "some-password", 355 Relationships: resources.Relationships{ 356 constant.RelationshipTypeApplication: resources.Relationship{GUID: "some-app-guid"}, 357 }, 358 })) 359 }) 360 }) 361 }) 362 }) 363 364 Describe("CreateAndUploadBitsPackageByApplicationNameAndSpace", func() { 365 var ( 366 bitsPath string 367 pkg Package 368 warnings Warnings 369 executeErr error 370 ) 371 372 BeforeEach(func() { 373 bitsPath = "" 374 pkg = Package{} 375 warnings = nil 376 executeErr = nil 377 378 // putting this here so the tests don't hang on polling 379 fakeCloudControllerClient.GetPackageReturns( 380 ccv3.Package{GUID: "some-pkg-guid", State: constant.PackageReady}, 381 ccv3.Warnings{}, 382 nil, 383 ) 384 }) 385 386 JustBeforeEach(func() { 387 pkg, warnings, executeErr = actor.CreateAndUploadBitsPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath) 388 }) 389 390 When("retrieving the application errors", func() { 391 BeforeEach(func() { 392 fakeCloudControllerClient.GetApplicationsReturns( 393 []resources.Application{}, 394 ccv3.Warnings{"some-app-warning"}, 395 errors.New("some-get-error"), 396 ) 397 }) 398 399 It("returns the warnings and the error", func() { 400 Expect(executeErr).To(MatchError("some-get-error")) 401 Expect(warnings).To(ConsistOf("some-app-warning")) 402 }) 403 }) 404 405 When("the application can be retrieved", func() { 406 BeforeEach(func() { 407 fakeCloudControllerClient.GetApplicationsReturns( 408 []resources.Application{ 409 { 410 Name: "some-app-name", 411 GUID: "some-app-guid", 412 }, 413 }, 414 ccv3.Warnings{"some-app-warning"}, 415 nil, 416 ) 417 }) 418 419 When("bits path is a directory", func() { 420 BeforeEach(func() { 421 var err error 422 bitsPath, err = ioutil.TempDir("", "example") 423 Expect(err).ToNot(HaveOccurred()) 424 }) 425 426 AfterEach(func() { 427 if bitsPath != "" { 428 err := os.RemoveAll(bitsPath) 429 Expect(err).ToNot(HaveOccurred()) 430 } 431 }) 432 433 It("calls GatherDirectoryResources and ZipDirectoryResources", func() { 434 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(1)) 435 Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(Equal(1)) 436 }) 437 438 When("gathering resources fails", func() { 439 BeforeEach(func() { 440 fakeSharedActor.GatherDirectoryResourcesReturns(nil, errors.New("some-gather-error")) 441 }) 442 443 It("returns the error", func() { 444 Expect(executeErr).To(MatchError("some-gather-error")) 445 Expect(warnings).To(ConsistOf("some-app-warning")) 446 }) 447 }) 448 449 When("gathering resources succeeds", func() { 450 BeforeEach(func() { 451 fakeSharedActor.GatherDirectoryResourcesReturns([]sharedaction.Resource{{Filename: "file-1"}, {Filename: "file-2"}}, nil) 452 }) 453 454 When("zipping gathered resources fails", func() { 455 BeforeEach(func() { 456 fakeSharedActor.ZipDirectoryResourcesReturns("", errors.New("some-archive-error")) 457 }) 458 459 It("returns the error", func() { 460 Expect(executeErr).To(MatchError("some-archive-error")) 461 Expect(warnings).To(ConsistOf("some-app-warning")) 462 }) 463 }) 464 465 When("zipping gathered resources succeeds", func() { 466 BeforeEach(func() { 467 fakeSharedActor.ZipDirectoryResourcesReturns("zipped-archive", nil) 468 }) 469 470 When("creating the package fails", func() { 471 BeforeEach(func() { 472 fakeCloudControllerClient.CreatePackageReturns( 473 ccv3.Package{}, 474 ccv3.Warnings{"create-package-warning"}, 475 errors.New("some-create-error"), 476 ) 477 }) 478 479 It("returns the error", func() { 480 Expect(executeErr).To(MatchError("some-create-error")) 481 Expect(warnings).To(ConsistOf("some-app-warning", "create-package-warning")) 482 }) 483 }) 484 485 When("creating the package succeeds", func() { 486 var createdPackage ccv3.Package 487 488 BeforeEach(func() { 489 createdPackage = ccv3.Package{ 490 GUID: "some-pkg-guid", 491 State: constant.PackageAwaitingUpload, 492 Relationships: resources.Relationships{ 493 constant.RelationshipTypeApplication: resources.Relationship{ 494 GUID: "some-app-guid", 495 }, 496 }, 497 } 498 499 fakeCloudControllerClient.CreatePackageReturns( 500 createdPackage, 501 ccv3.Warnings{"some-package-warning"}, 502 nil, 503 ) 504 }) 505 506 It("uploads the package with the path to the zip", func() { 507 Expect(fakeCloudControllerClient.UploadPackageCallCount()).To(Equal(1)) 508 _, zippedArchive := fakeCloudControllerClient.UploadPackageArgsForCall(0) 509 Expect(zippedArchive).To(Equal("zipped-archive")) 510 }) 511 512 When("uploading fails", func() { 513 BeforeEach(func() { 514 fakeCloudControllerClient.UploadPackageReturns( 515 ccv3.Package{}, 516 ccv3.Warnings{"upload-package-warning"}, 517 errors.New("some-error"), 518 ) 519 }) 520 521 It("returns the error", func() { 522 Expect(executeErr).To(MatchError("some-error")) 523 Expect(warnings).To(ConsistOf("some-app-warning", "some-package-warning", "upload-package-warning")) 524 }) 525 }) 526 527 When("uploading succeeds", func() { 528 BeforeEach(func() { 529 fakeCloudControllerClient.UploadPackageReturns( 530 ccv3.Package{}, 531 ccv3.Warnings{"upload-package-warning"}, 532 nil, 533 ) 534 }) 535 536 When("the polling errors", func() { 537 var expectedErr error 538 539 BeforeEach(func() { 540 expectedErr = errors.New("Fake error during polling") 541 fakeCloudControllerClient.GetPackageReturns( 542 ccv3.Package{}, 543 ccv3.Warnings{"some-get-pkg-warning"}, 544 expectedErr, 545 ) 546 }) 547 548 It("returns the error and warnings", func() { 549 Expect(executeErr).To(MatchError(expectedErr)) 550 Expect(warnings).To(ConsistOf("some-app-warning", "some-package-warning", "upload-package-warning", "some-get-pkg-warning")) 551 }) 552 }) 553 554 When("the polling is successful", func() { 555 It("collects all warnings", func() { 556 Expect(executeErr).NotTo(HaveOccurred()) 557 Expect(warnings).To(ConsistOf("some-app-warning", "some-package-warning", "upload-package-warning")) 558 }) 559 560 It("successfully resolves the app name", func() { 561 Expect(executeErr).ToNot(HaveOccurred()) 562 563 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 564 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 565 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}}, 566 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 567 )) 568 }) 569 570 It("successfully creates the Package", func() { 571 Expect(executeErr).ToNot(HaveOccurred()) 572 573 Expect(fakeCloudControllerClient.CreatePackageCallCount()).To(Equal(1)) 574 inputPackage := fakeCloudControllerClient.CreatePackageArgsForCall(0) 575 Expect(inputPackage).To(Equal(ccv3.Package{ 576 Type: constant.PackageTypeBits, 577 Relationships: resources.Relationships{ 578 constant.RelationshipTypeApplication: resources.Relationship{GUID: "some-app-guid"}, 579 }, 580 })) 581 }) 582 583 It("returns the package", func() { 584 Expect(executeErr).ToNot(HaveOccurred()) 585 586 expectedPackage := ccv3.Package{ 587 GUID: "some-pkg-guid", 588 State: constant.PackageReady, 589 } 590 Expect(pkg).To(Equal(Package(expectedPackage))) 591 592 Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(1)) 593 Expect(fakeCloudControllerClient.GetPackageArgsForCall(0)).To(Equal("some-pkg-guid")) 594 }) 595 596 DescribeTable("polls until terminal state is reached", 597 func(finalState constant.PackageState, expectedErr error) { 598 fakeCloudControllerClient.GetPackageReturns( 599 ccv3.Package{GUID: "some-pkg-guid", State: constant.PackageAwaitingUpload}, 600 ccv3.Warnings{"poll-package-warning"}, 601 nil, 602 ) 603 fakeCloudControllerClient.GetPackageReturnsOnCall( 604 2, 605 ccv3.Package{State: finalState}, 606 ccv3.Warnings{"poll-package-warning"}, 607 nil, 608 ) 609 610 _, tableWarnings, err := actor.CreateAndUploadBitsPackageByApplicationNameAndSpace("some-app-name", "some-space-guid", bitsPath) 611 612 if expectedErr == nil { 613 Expect(err).ToNot(HaveOccurred()) 614 } else { 615 Expect(err).To(MatchError(expectedErr)) 616 } 617 618 Expect(tableWarnings).To(ConsistOf("some-app-warning", "some-package-warning", "upload-package-warning", "poll-package-warning", "poll-package-warning")) 619 620 // hacky, get packages is called an extry time cause the 621 // JustBeforeEach executes everything once as well 622 Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(3)) 623 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(3)) 624 }, 625 626 Entry("READY", constant.PackageReady, nil), 627 Entry("FAILED", constant.PackageFailed, actionerror.PackageProcessingFailedError{}), 628 Entry("EXPIRED", constant.PackageExpired, actionerror.PackageProcessingExpiredError{}), 629 ) 630 }) 631 }) 632 }) 633 }) 634 }) 635 }) 636 637 When("bitsPath is blank", func() { 638 var oldCurrentDir, appDir string 639 BeforeEach(func() { 640 var err error 641 oldCurrentDir, err = os.Getwd() 642 Expect(err).NotTo(HaveOccurred()) 643 644 appDir, err = ioutil.TempDir("", "example") 645 Expect(err).ToNot(HaveOccurred()) 646 647 Expect(os.Chdir(appDir)).NotTo(HaveOccurred()) 648 appDir, err = os.Getwd() 649 Expect(err).ToNot(HaveOccurred()) 650 }) 651 652 AfterEach(func() { 653 Expect(os.Chdir(oldCurrentDir)).NotTo(HaveOccurred()) 654 err := os.RemoveAll(appDir) 655 Expect(err).ToNot(HaveOccurred()) 656 }) 657 658 It("uses the current working directory", func() { 659 Expect(executeErr).NotTo(HaveOccurred()) 660 661 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(1)) 662 Expect(fakeSharedActor.GatherDirectoryResourcesArgsForCall(0)).To(Equal(appDir)) 663 664 Expect(fakeSharedActor.ZipDirectoryResourcesCallCount()).To(Equal(1)) 665 pathArg, _ := fakeSharedActor.ZipDirectoryResourcesArgsForCall(0) 666 Expect(pathArg).To(Equal(appDir)) 667 }) 668 }) 669 670 When("bits path is an archive", func() { 671 BeforeEach(func() { 672 var err error 673 tempFile, err := ioutil.TempFile("", "bits-zip-test") 674 Expect(err).ToNot(HaveOccurred()) 675 Expect(tempFile.Close()).To(Succeed()) 676 tempFilePath := tempFile.Name() 677 678 bitsPathFile, err := ioutil.TempFile("", "example") 679 Expect(err).ToNot(HaveOccurred()) 680 Expect(bitsPathFile.Close()).To(Succeed()) 681 bitsPath = bitsPathFile.Name() 682 683 err = zipit(tempFilePath, bitsPath, "") 684 Expect(err).NotTo(HaveOccurred()) 685 Expect(os.Remove(tempFilePath)).To(Succeed()) 686 }) 687 688 AfterEach(func() { 689 err := os.RemoveAll(bitsPath) 690 Expect(err).ToNot(HaveOccurred()) 691 }) 692 693 It("calls GatherArchiveResources and ZipArchiveResources", func() { 694 Expect(fakeSharedActor.GatherArchiveResourcesCallCount()).To(Equal(1)) 695 Expect(fakeSharedActor.ZipArchiveResourcesCallCount()).To(Equal(1)) 696 }) 697 698 When("gathering archive resources fails", func() { 699 BeforeEach(func() { 700 fakeSharedActor.GatherArchiveResourcesReturns(nil, errors.New("some-archive-resource-error")) 701 }) 702 It("should return an error", func() { 703 Expect(executeErr).To(MatchError("some-archive-resource-error")) 704 Expect(warnings).To(ConsistOf("some-app-warning")) 705 }) 706 707 }) 708 709 When("gathering resources succeeds", func() { 710 BeforeEach(func() { 711 fakeSharedActor.GatherArchiveResourcesReturns([]sharedaction.Resource{{Filename: "file-1"}, {Filename: "file-2"}}, nil) 712 }) 713 714 When("zipping gathered resources fails", func() { 715 BeforeEach(func() { 716 fakeSharedActor.ZipArchiveResourcesReturns("", errors.New("some-archive-error")) 717 }) 718 719 It("returns the error", func() { 720 Expect(executeErr).To(MatchError("some-archive-error")) 721 Expect(warnings).To(ConsistOf("some-app-warning")) 722 }) 723 }) 724 725 When("zipping gathered resources succeeds", func() { 726 BeforeEach(func() { 727 fakeSharedActor.ZipArchiveResourcesReturns("zipped-archive", nil) 728 }) 729 730 It("uploads the package", func() { 731 Expect(executeErr).ToNot(HaveOccurred()) 732 Expect(warnings).To(ConsistOf("some-app-warning")) 733 734 Expect(fakeCloudControllerClient.UploadPackageCallCount()).To(Equal(1)) 735 _, archivePathArg := fakeCloudControllerClient.UploadPackageArgsForCall(0) 736 Expect(archivePathArg).To(Equal("zipped-archive")) 737 }) 738 }) 739 }) 740 }) 741 742 When("bits path is a symlink to a directory", func() { 743 var tempDir string 744 745 BeforeEach(func() { 746 var err error 747 tempDir, err = ioutil.TempDir("", "example") 748 Expect(err).ToNot(HaveOccurred()) 749 750 tempFile, err := ioutil.TempFile("", "example-file-") 751 Expect(err).ToNot(HaveOccurred()) 752 Expect(tempFile.Close()).To(Succeed()) 753 754 bitsPath = tempFile.Name() 755 Expect(os.Remove(bitsPath)).To(Succeed()) 756 Expect(os.Symlink(tempDir, bitsPath)).To(Succeed()) 757 }) 758 759 AfterEach(func() { 760 Expect(os.RemoveAll(tempDir)).To(Succeed()) 761 Expect(os.Remove(bitsPath)).To(Succeed()) 762 }) 763 764 It("calls GatherDirectoryResources and returns without an error", func() { 765 Expect(fakeSharedActor.GatherDirectoryResourcesCallCount()).To(Equal(1)) 766 Expect(fakeSharedActor.GatherDirectoryResourcesArgsForCall(0)).To(Equal(bitsPath)) 767 Expect(executeErr).ToNot(HaveOccurred()) 768 }) 769 }) 770 771 When("bits path is symlink to an archive", func() { 772 var archivePath string 773 774 BeforeEach(func() { 775 var err error 776 tempArchiveFile, err := ioutil.TempFile("", "bits-zip-test") 777 Expect(err).ToNot(HaveOccurred()) 778 Expect(tempArchiveFile.Close()).To(Succeed()) 779 tempArchiveFilePath := tempArchiveFile.Name() 780 781 archivePathFile, err := ioutil.TempFile("", "example") 782 Expect(err).ToNot(HaveOccurred()) 783 Expect(archivePathFile.Close()).To(Succeed()) 784 archivePath = archivePathFile.Name() 785 786 err = zipit(tempArchiveFilePath, archivePath, "") 787 Expect(err).NotTo(HaveOccurred()) 788 Expect(os.Remove(tempArchiveFilePath)).To(Succeed()) 789 790 tempFile, err := ioutil.TempFile("", "example-file-") 791 Expect(err).ToNot(HaveOccurred()) 792 Expect(tempFile.Close()).To(Succeed()) 793 794 bitsPath = tempFile.Name() 795 Expect(os.Remove(bitsPath)).To(Succeed()) 796 Expect(os.Symlink(archivePath, bitsPath)).To(Succeed()) 797 }) 798 799 AfterEach(func() { 800 Expect(os.Remove(archivePath)).To(Succeed()) 801 Expect(os.Remove(bitsPath)).To(Succeed()) 802 }) 803 804 It("calls GatherArchiveResources and returns without an error", func() { 805 Expect(fakeSharedActor.GatherArchiveResourcesCallCount()).To(Equal(1)) 806 Expect(fakeSharedActor.GatherArchiveResourcesArgsForCall(0)).To(Equal(bitsPath)) 807 Expect(executeErr).ToNot(HaveOccurred()) 808 }) 809 }) 810 }) 811 }) 812 813 Describe("CreateBitsPackageByApplication", func() { 814 var ( 815 appGUID string 816 817 pkg Package 818 executeErr error 819 warnings Warnings 820 ) 821 822 JustBeforeEach(func() { 823 pkg, warnings, executeErr = actor.CreateBitsPackageByApplication(appGUID) 824 }) 825 826 When("creating the package fails", func() { 827 BeforeEach(func() { 828 fakeCloudControllerClient.CreatePackageReturns( 829 ccv3.Package{}, 830 ccv3.Warnings{"create-package-warning"}, 831 errors.New("some-create-error"), 832 ) 833 }) 834 835 It("returns the error", func() { 836 Expect(executeErr).To(MatchError("some-create-error")) 837 Expect(warnings).To(ConsistOf("create-package-warning")) 838 }) 839 }) 840 841 When("creating the package succeeds", func() { 842 var createdPackage ccv3.Package 843 844 BeforeEach(func() { 845 createdPackage = ccv3.Package{GUID: "some-pkg-guid"} 846 fakeCloudControllerClient.CreatePackageReturns( 847 createdPackage, 848 ccv3.Warnings{"create-package-warning"}, 849 nil, 850 ) 851 }) 852 853 It("returns all warnings and the package", func() { 854 Expect(executeErr).ToNot(HaveOccurred()) 855 856 Expect(fakeCloudControllerClient.CreatePackageCallCount()).To(Equal(1)) 857 Expect(fakeCloudControllerClient.CreatePackageArgsForCall(0)).To(Equal(ccv3.Package{ 858 Type: constant.PackageTypeBits, 859 Relationships: resources.Relationships{ 860 constant.RelationshipTypeApplication: resources.Relationship{GUID: appGUID}, 861 }, 862 })) 863 864 Expect(warnings).To(ConsistOf("create-package-warning")) 865 Expect(pkg).To(MatchFields(IgnoreExtras, Fields{ 866 "GUID": Equal("some-pkg-guid"), 867 })) 868 }) 869 }) 870 }) 871 872 Describe("UploadBitsPackage", func() { 873 var ( 874 pkg Package 875 matchedResources []sharedaction.V3Resource 876 reader io.Reader 877 readerLength int64 878 879 appPkg Package 880 warnings Warnings 881 executeErr error 882 ) 883 884 BeforeEach(func() { 885 pkg = Package{GUID: "some-package-guid"} 886 887 matchedResources = []sharedaction.V3Resource{{FilePath: "some-resource"}, {FilePath: "another-resource"}} 888 someString := "who reads these days" 889 reader = strings.NewReader(someString) 890 readerLength = int64(len([]byte(someString))) 891 }) 892 893 JustBeforeEach(func() { 894 appPkg, warnings, executeErr = actor.UploadBitsPackage(pkg, matchedResources, reader, readerLength) 895 }) 896 897 When("the upload is successful", func() { 898 BeforeEach(func() { 899 fakeCloudControllerClient.UploadBitsPackageReturns(ccv3.Package{GUID: "some-package-guid"}, ccv3.Warnings{"upload-warning-1", "upload-warning-2"}, nil) 900 }) 901 902 It("returns all warnings", func() { 903 Expect(executeErr).ToNot(HaveOccurred()) 904 Expect(warnings).To(ConsistOf("upload-warning-1", "upload-warning-2")) 905 Expect(appPkg).To(Equal(Package{GUID: "some-package-guid"})) 906 907 Expect(fakeCloudControllerClient.UploadBitsPackageCallCount()).To(Equal(1)) 908 passedPackage, passedExistingResources, passedReader, passedReaderLength := fakeCloudControllerClient.UploadBitsPackageArgsForCall(0) 909 Expect(passedPackage).To(Equal(ccv3.Package(appPkg))) 910 Expect(passedExistingResources).To(ConsistOf(ccv3.Resource{FilePath: "some-resource"}, ccv3.Resource{FilePath: "another-resource"})) 911 Expect(passedReader).To(Equal(reader)) 912 Expect(passedReaderLength).To(Equal(readerLength)) 913 }) 914 }) 915 916 When("the upload returns an error", func() { 917 var err error 918 919 BeforeEach(func() { 920 err = errors.New("some-error") 921 fakeCloudControllerClient.UploadBitsPackageReturns(ccv3.Package{}, ccv3.Warnings{"upload-warning-1", "upload-warning-2"}, err) 922 }) 923 924 It("returns the error", func() { 925 Expect(executeErr).To(MatchError(err)) 926 Expect(warnings).To(ConsistOf("upload-warning-1", "upload-warning-2")) 927 }) 928 }) 929 }) 930 931 Describe("PollPackage", func() { 932 Context("Polling Behavior", func() { 933 var ( 934 pkg Package 935 936 appPkg Package 937 warnings Warnings 938 executeErr error 939 ) 940 941 BeforeEach(func() { 942 pkg = Package{ 943 GUID: "some-pkg-guid", 944 } 945 946 warnings = nil 947 executeErr = nil 948 949 // putting this here so the tests don't hang on polling 950 fakeCloudControllerClient.GetPackageReturns( 951 ccv3.Package{ 952 GUID: "some-pkg-guid", 953 State: constant.PackageReady, 954 }, 955 ccv3.Warnings{}, 956 nil, 957 ) 958 }) 959 960 JustBeforeEach(func() { 961 appPkg, warnings, executeErr = actor.PollPackage(pkg) 962 }) 963 964 When("the polling errors", func() { 965 var expectedErr error 966 967 BeforeEach(func() { 968 expectedErr = errors.New("Fake error during polling") 969 fakeCloudControllerClient.GetPackageReturns( 970 ccv3.Package{}, 971 ccv3.Warnings{"some-get-pkg-warning"}, 972 expectedErr, 973 ) 974 }) 975 976 It("returns the error and warnings", func() { 977 Expect(executeErr).To(MatchError(expectedErr)) 978 Expect(warnings).To(ConsistOf("some-get-pkg-warning")) 979 }) 980 }) 981 982 When("the polling is successful", func() { 983 It("returns the package", func() { 984 Expect(executeErr).ToNot(HaveOccurred()) 985 986 expectedPackage := ccv3.Package{ 987 GUID: "some-pkg-guid", 988 State: constant.PackageReady, 989 } 990 991 Expect(appPkg).To(Equal(Package(expectedPackage))) 992 Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(1)) 993 Expect(fakeCloudControllerClient.GetPackageArgsForCall(0)).To(Equal("some-pkg-guid")) 994 }) 995 }) 996 }) 997 998 DescribeTable("Polling states", 999 func(finalState constant.PackageState, expectedErr error) { 1000 fakeCloudControllerClient.GetPackageReturns( 1001 ccv3.Package{GUID: "some-pkg-guid", State: constant.PackageAwaitingUpload}, 1002 ccv3.Warnings{"poll-package-warning"}, 1003 nil, 1004 ) 1005 1006 fakeCloudControllerClient.GetPackageReturnsOnCall( 1007 1, 1008 ccv3.Package{State: finalState}, 1009 ccv3.Warnings{"poll-package-warning"}, 1010 nil, 1011 ) 1012 1013 _, tableWarnings, err := actor.PollPackage(Package{ 1014 GUID: "some-pkg-guid", 1015 }) 1016 1017 if expectedErr == nil { 1018 Expect(err).ToNot(HaveOccurred()) 1019 } else { 1020 Expect(err).To(MatchError(expectedErr)) 1021 } 1022 1023 Expect(tableWarnings).To(ConsistOf("poll-package-warning", "poll-package-warning")) 1024 1025 Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(2)) 1026 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(2)) 1027 }, 1028 1029 Entry("READY", constant.PackageReady, nil), 1030 Entry("FAILED", constant.PackageFailed, actionerror.PackageProcessingFailedError{}), 1031 Entry("EXPIRED", constant.PackageExpired, actionerror.PackageProcessingExpiredError{}), 1032 ) 1033 }) 1034 1035 Describe("CopyPackage", func() { 1036 var ( 1037 sourceApp resources.Application 1038 targetApp resources.Application 1039 pkg Package 1040 warnings Warnings 1041 executeErr error 1042 ) 1043 1044 BeforeEach(func() { 1045 targetApp = resources.Application{ 1046 GUID: "target-app-guid", 1047 Name: "target-app", 1048 } 1049 1050 fakeCloudControllerClient.GetPackagesReturns( 1051 []ccv3.Package{{GUID: "source-package-guid"}}, 1052 ccv3.Warnings{"get-source-package-warning"}, 1053 nil, 1054 ) 1055 1056 fakeCloudControllerClient.CopyPackageReturns( 1057 ccv3.Package{GUID: "target-package-guid"}, 1058 ccv3.Warnings{"copy-package-warning"}, 1059 nil, 1060 ) 1061 1062 fakeCloudControllerClient.GetPackageReturnsOnCall(0, 1063 ccv3.Package{State: constant.PackageCopying, GUID: "target-package-guid"}, 1064 ccv3.Warnings{"get-package-warning-copying"}, 1065 nil, 1066 ) 1067 fakeCloudControllerClient.GetPackageReturnsOnCall(1, 1068 ccv3.Package{State: constant.PackageReady, GUID: "target-package-guid"}, 1069 ccv3.Warnings{"get-package-warning-ready"}, 1070 nil, 1071 ) 1072 }) 1073 1074 JustBeforeEach(func() { 1075 pkg, warnings, executeErr = actor.CopyPackage(sourceApp, targetApp) 1076 }) 1077 1078 When("getting the source package fails", func() { 1079 var err error 1080 1081 BeforeEach(func() { 1082 err = errors.New("get-package-error") 1083 fakeCloudControllerClient.GetPackagesReturns( 1084 []ccv3.Package{}, 1085 ccv3.Warnings{"get-source-package-warning"}, 1086 err, 1087 ) 1088 }) 1089 1090 It("returns the error", func() { 1091 Expect(executeErr).To(MatchError(err)) 1092 Expect(warnings).To(ConsistOf("get-source-package-warning")) 1093 1094 queries := fakeCloudControllerClient.GetPackagesArgsForCall(0) 1095 Expect(queries).To(Equal([]ccv3.Query{ 1096 ccv3.Query{ 1097 Key: ccv3.AppGUIDFilter, 1098 Values: []string{sourceApp.GUID}, 1099 }, 1100 ccv3.Query{ 1101 Key: ccv3.StatesFilter, 1102 Values: []string{string(constant.PackageReady)}, 1103 }, 1104 ccv3.Query{ 1105 Key: ccv3.OrderBy, 1106 Values: []string{ccv3.CreatedAtDescendingOrder}, 1107 }, 1108 })) 1109 }) 1110 }) 1111 1112 When("copying the package fails", func() { 1113 var err error 1114 1115 BeforeEach(func() { 1116 err = errors.New("copy-package-error") 1117 fakeCloudControllerClient.CopyPackageReturns( 1118 ccv3.Package{GUID: "target-package-guid"}, 1119 ccv3.Warnings{"copy-package-warning"}, 1120 err, 1121 ) 1122 }) 1123 1124 It("returns the error", func() { 1125 Expect(executeErr).To(MatchError(err)) 1126 Expect(warnings).To(ConsistOf("get-source-package-warning", "copy-package-warning")) 1127 1128 sourcePkgGUID, appGUID := fakeCloudControllerClient.CopyPackageArgsForCall(0) 1129 Expect(sourcePkgGUID).To(Equal("source-package-guid")) 1130 Expect(appGUID).To(Equal(targetApp.GUID)) 1131 }) 1132 }) 1133 1134 It("polls to make sure the package has finished copying", func() { 1135 Expect(executeErr).To(Not(HaveOccurred())) 1136 Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(2)) 1137 }) 1138 1139 When("the package fails to copy while polling the package", func() { 1140 BeforeEach(func() { 1141 fakeCloudControllerClient.GetPackageReturnsOnCall(0, 1142 ccv3.Package{State: constant.PackageFailed}, 1143 ccv3.Warnings{"get-package-warning-copying"}, 1144 nil, 1145 ) 1146 1147 }) 1148 It("fails", func() { 1149 Expect(fakeCloudControllerClient.GetPackageCallCount()).To(Equal(1)) 1150 Expect(executeErr).To(MatchError(actionerror.PackageProcessingFailedError{})) 1151 }) 1152 }) 1153 1154 It("returns all warnings", func() { 1155 Expect(executeErr).ToNot(HaveOccurred()) 1156 Expect(warnings).To(ConsistOf("get-source-package-warning", "copy-package-warning", "get-package-warning-copying", "get-package-warning-ready")) 1157 Expect(pkg).To(Equal(Package{State: constant.PackageReady, GUID: "target-package-guid"})) 1158 }) 1159 }) 1160 })