github.com/Thanhphan1147/cloudfoundry-cli@v7.1.0+incompatible/actor/v7action/application_test.go (about) 1 package v7action_test 2 3 import ( 4 "errors" 5 "time" 6 7 "code.cloudfoundry.org/cli/actor/actionerror" 8 . "code.cloudfoundry.org/cli/actor/v7action" 9 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 12 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 13 "code.cloudfoundry.org/cli/resources" 14 "code.cloudfoundry.org/cli/types" 15 "code.cloudfoundry.org/clock/fakeclock" 16 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 ) 20 21 var _ = Describe("Application Actions", func() { 22 var ( 23 actor *Actor 24 fakeCloudControllerClient *v7actionfakes.FakeCloudControllerClient 25 fakeConfig *v7actionfakes.FakeConfig 26 fakeClock *fakeclock.FakeClock 27 ) 28 29 BeforeEach(func() { 30 fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient) 31 fakeConfig = new(v7actionfakes.FakeConfig) 32 fakeClock = fakeclock.NewFakeClock(time.Now()) 33 actor = NewActor(fakeCloudControllerClient, fakeConfig, nil, nil, nil, fakeClock) 34 }) 35 36 Describe("DeleteApplicationByNameAndSpace", func() { 37 var ( 38 warnings Warnings 39 executeErr error 40 deleteMappedRoutes bool 41 appName string 42 ) 43 44 JustBeforeEach(func() { 45 appName = "some-app" 46 warnings, executeErr = actor.DeleteApplicationByNameAndSpace(appName, "some-space-guid", deleteMappedRoutes) 47 }) 48 49 When("looking up the app guid fails", func() { 50 BeforeEach(func() { 51 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{}, ccv3.Warnings{"some-get-app-warning"}, errors.New("some-get-app-error")) 52 }) 53 54 It("returns the warnings and error", func() { 55 Expect(warnings).To(ConsistOf("some-get-app-warning")) 56 Expect(executeErr).To(MatchError("some-get-app-error")) 57 }) 58 }) 59 60 When("looking up the app guid succeeds without routes", func() { 61 BeforeEach(func() { 62 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{Name: "some-app", GUID: "abc123"}}, ccv3.Warnings{"some-get-app-warning"}, nil) 63 deleteMappedRoutes = false 64 }) 65 66 When("sending the delete fails", func() { 67 BeforeEach(func() { 68 fakeCloudControllerClient.DeleteApplicationReturns("", ccv3.Warnings{"some-delete-app-warning"}, errors.New("some-delete-app-error")) 69 }) 70 71 It("returns the warnings and error", func() { 72 Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning")) 73 Expect(executeErr).To(MatchError("some-delete-app-error")) 74 }) 75 }) 76 77 When("sending the delete succeeds", func() { 78 BeforeEach(func() { 79 fakeCloudControllerClient.DeleteApplicationReturns("/some-job-url", ccv3.Warnings{"some-delete-app-warning"}, nil) 80 }) 81 82 When("polling fails", func() { 83 BeforeEach(func() { 84 fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"some-poll-warning"}, errors.New("some-poll-error")) 85 }) 86 87 It("returns the warnings and poll error", func() { 88 Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning", "some-poll-warning")) 89 Expect(executeErr).To(MatchError("some-poll-error")) 90 }) 91 }) 92 93 When("polling succeeds", func() { 94 BeforeEach(func() { 95 fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"some-poll-warning"}, nil) 96 }) 97 98 It("returns all the warnings and no error", func() { 99 Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning", "some-poll-warning")) 100 Expect(executeErr).ToNot(HaveOccurred()) 101 }) 102 }) 103 }) 104 }) 105 106 When("looking up the app guid succeeds with routes", func() { 107 BeforeEach(func() { 108 deleteMappedRoutes = true 109 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{Name: "some-app", GUID: "abc123"}}, nil, nil) 110 }) 111 112 When("getting the routes fails", func() { 113 BeforeEach(func() { 114 fakeCloudControllerClient.GetApplicationRoutesReturns(nil, ccv3.Warnings{"get-routes-warning"}, errors.New("get-routes-error")) 115 }) 116 117 It("returns the warnings and an error", func() { 118 Expect(warnings).To(ConsistOf("get-routes-warning")) 119 Expect(executeErr).To(MatchError("get-routes-error")) 120 }) 121 }) 122 123 When("getting the routes succeeds", func() { 124 When("there are no routes", func() { 125 BeforeEach(func() { 126 fakeCloudControllerClient.GetApplicationRoutesReturns([]resources.Route{}, nil, nil) 127 }) 128 129 It("does not delete any routes", func() { 130 Expect(fakeCloudControllerClient.DeleteRouteCallCount()).To(Equal(0)) 131 }) 132 }) 133 134 When("there are routes", func() { 135 BeforeEach(func() { 136 fakeCloudControllerClient.GetApplicationRoutesReturns([]resources.Route{{GUID: "route-1-guid"}, {GUID: "route-2-guid", URL: "route-2.example.com"}}, nil, nil) 137 }) 138 139 It("deletes the routes", func() { 140 Expect(fakeCloudControllerClient.GetApplicationRoutesCallCount()).To(Equal(1)) 141 Expect(fakeCloudControllerClient.GetApplicationRoutesArgsForCall(0)).To(Equal("abc123")) 142 Expect(fakeCloudControllerClient.DeleteRouteCallCount()).To(Equal(2)) 143 guids := []string{fakeCloudControllerClient.DeleteRouteArgsForCall(0), fakeCloudControllerClient.DeleteRouteArgsForCall(1)} 144 Expect(guids).To(ConsistOf("route-1-guid", "route-2-guid")) 145 }) 146 147 When("the route has already been deleted", func() { 148 BeforeEach(func() { 149 fakeCloudControllerClient.DeleteRouteReturnsOnCall(0, 150 "", 151 ccv3.Warnings{"delete-route-1-warning"}, 152 ccerror.ResourceNotFoundError{}, 153 ) 154 fakeCloudControllerClient.DeleteRouteReturnsOnCall(1, 155 "poll-job-url", 156 ccv3.Warnings{"delete-route-2-warning"}, 157 nil, 158 ) 159 fakeCloudControllerClient.PollJobReturnsOnCall(1, ccv3.Warnings{"poll-job-warning"}, nil) 160 }) 161 162 It("does **not** fail", func() { 163 Expect(executeErr).ToNot(HaveOccurred()) 164 Expect(warnings).To(ConsistOf("delete-route-1-warning", "delete-route-2-warning", "poll-job-warning")) 165 Expect(fakeCloudControllerClient.DeleteRouteCallCount()).To(Equal(2)) 166 Expect(fakeCloudControllerClient.PollJobCallCount()).To(Equal(2)) 167 Expect(fakeCloudControllerClient.PollJobArgsForCall(1)).To(BeEquivalentTo("poll-job-url")) 168 }) 169 }) 170 171 When("app to delete has a route bound to another app", func() { 172 BeforeEach(func() { 173 fakeCloudControllerClient.GetApplicationRoutesReturns( 174 []resources.Route{ 175 {GUID: "route-1-guid"}, 176 {GUID: "route-2-guid", 177 URL: "route-2.example.com", 178 Destinations: []resources.RouteDestination{ 179 {App: resources.RouteDestinationApp{GUID: "abc123"}}, 180 {App: resources.RouteDestinationApp{GUID: "different-app-guid"}}, 181 }, 182 }, 183 }, 184 nil, 185 nil, 186 ) 187 }) 188 189 It("refuses the entire operation", func() { 190 Expect(executeErr).To(MatchError(actionerror.RouteBoundToMultipleAppsError{AppName: "some-app", RouteURL: "route-2.example.com"})) 191 Expect(warnings).To(BeEmpty()) 192 Expect(fakeCloudControllerClient.DeleteApplicationCallCount()).To(Equal(0)) 193 Expect(fakeCloudControllerClient.DeleteRouteCallCount()).To(Equal(0)) 194 }) 195 }) 196 197 When("deleting the route fails", func() { 198 BeforeEach(func() { 199 fakeCloudControllerClient.DeleteRouteReturnsOnCall(0, 200 "poll-job-url", 201 ccv3.Warnings{"delete-route-1-warning"}, 202 nil, 203 ) 204 fakeCloudControllerClient.DeleteRouteReturnsOnCall(1, 205 "", 206 ccv3.Warnings{"delete-route-2-warning"}, 207 errors.New("delete-route-2-error"), 208 ) 209 }) 210 211 It("returns the error", func() { 212 Expect(executeErr).To(MatchError("delete-route-2-error")) 213 Expect(warnings).To(ConsistOf("delete-route-1-warning", "delete-route-2-warning")) 214 }) 215 }) 216 217 When("the polling job fails", func() { 218 BeforeEach(func() { 219 fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"poll-job-warning"}, errors.New("poll-job-error")) 220 }) 221 222 It("returns the error", func() { 223 Expect(executeErr).To(MatchError("poll-job-error")) 224 }) 225 }) 226 227 }) 228 }) 229 }) 230 }) 231 232 Describe("GetApplicationsByGUIDs", func() { 233 When("all of the requested apps exist", func() { 234 BeforeEach(func() { 235 fakeCloudControllerClient.GetApplicationsReturns( 236 []resources.Application{ 237 { 238 Name: "some-app-name", 239 GUID: "some-app-guid", 240 }, 241 { 242 Name: "other-app-name", 243 GUID: "other-app-guid", 244 }, 245 }, 246 ccv3.Warnings{"some-warning"}, 247 nil, 248 ) 249 }) 250 251 It("returns the applications and warnings", func() { 252 apps, warnings, err := actor.GetApplicationsByGUIDs([]string{"some-app-guid", "other-app-guid"}) 253 Expect(err).ToNot(HaveOccurred()) 254 Expect(apps).To(ConsistOf( 255 resources.Application{ 256 Name: "some-app-name", 257 GUID: "some-app-guid", 258 }, 259 resources.Application{ 260 Name: "other-app-name", 261 GUID: "other-app-guid", 262 }, 263 )) 264 Expect(warnings).To(ConsistOf("some-warning")) 265 266 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 267 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 268 ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{"some-app-guid", "other-app-guid"}}, 269 )) 270 }) 271 }) 272 273 When("at least one of the requested apps does not exist", func() { 274 BeforeEach(func() { 275 fakeCloudControllerClient.GetApplicationsReturns( 276 []resources.Application{ 277 { 278 Name: "some-app-name", 279 GUID: "some-app-guid", 280 }, 281 }, 282 ccv3.Warnings{"some-warning"}, 283 nil, 284 ) 285 }) 286 287 It("returns an ApplicationNotFoundError and the warnings", func() { 288 _, warnings, err := actor.GetApplicationsByGUIDs([]string{"some-app-guid", "non-existent-app-guid"}) 289 Expect(warnings).To(ConsistOf("some-warning")) 290 Expect(err).To(MatchError(actionerror.ApplicationsNotFoundError{})) 291 }) 292 }) 293 294 When("a single app has two routes", func() { 295 BeforeEach(func() { 296 fakeCloudControllerClient.GetApplicationsReturns( 297 []resources.Application{ 298 { 299 Name: "some-app-name", 300 GUID: "some-app-guid", 301 }, 302 }, 303 ccv3.Warnings{"some-warning"}, 304 nil, 305 ) 306 }) 307 308 It("returns an ApplicationNotFoundError and the warnings", func() { 309 _, warnings, err := actor.GetApplicationsByGUIDs([]string{"some-app-guid", "some-app-guid"}) 310 Expect(err).ToNot(HaveOccurred()) 311 Expect(warnings).To(ConsistOf("some-warning")) 312 }) 313 }) 314 315 When("the cloud controller client returns an error", func() { 316 var expectedError error 317 318 BeforeEach(func() { 319 expectedError = errors.New("I am a CloudControllerClient Error") 320 fakeCloudControllerClient.GetApplicationsReturns( 321 []resources.Application{}, 322 ccv3.Warnings{"some-warning"}, 323 expectedError) 324 }) 325 326 It("returns the warnings and the error", func() { 327 _, warnings, err := actor.GetApplicationsByGUIDs([]string{"some-app-guid"}) 328 Expect(warnings).To(ConsistOf("some-warning")) 329 Expect(err).To(MatchError(expectedError)) 330 }) 331 }) 332 }) 333 334 Describe("GetApplicationsByNameAndSpace", func() { 335 When("all of the requested apps exist", func() { 336 BeforeEach(func() { 337 fakeCloudControllerClient.GetApplicationsReturns( 338 []resources.Application{ 339 { 340 Name: "some-app-name", 341 GUID: "some-app-guid", 342 }, 343 { 344 Name: "other-app-name", 345 GUID: "other-app-guid", 346 }, 347 }, 348 ccv3.Warnings{"some-warning"}, 349 nil, 350 ) 351 }) 352 353 It("returns the applications and warnings", func() { 354 apps, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name", "other-app-name"}, "some-space-guid") 355 Expect(err).ToNot(HaveOccurred()) 356 Expect(apps).To(ConsistOf( 357 resources.Application{ 358 Name: "some-app-name", 359 GUID: "some-app-guid", 360 }, 361 resources.Application{ 362 Name: "other-app-name", 363 GUID: "other-app-guid", 364 }, 365 )) 366 Expect(warnings).To(ConsistOf("some-warning")) 367 368 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 369 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 370 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name", "other-app-name"}}, 371 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 372 )) 373 }) 374 }) 375 376 When("at least one of the requested apps does not exist", func() { 377 BeforeEach(func() { 378 fakeCloudControllerClient.GetApplicationsReturns( 379 []resources.Application{ 380 { 381 Name: "some-app-name", 382 }, 383 }, 384 ccv3.Warnings{"some-warning"}, 385 nil, 386 ) 387 }) 388 389 It("returns an ApplicationNotFoundError and the warnings", func() { 390 _, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name", "other-app-name"}, "some-space-guid") 391 Expect(warnings).To(ConsistOf("some-warning")) 392 Expect(err).To(MatchError(actionerror.ApplicationsNotFoundError{})) 393 }) 394 }) 395 396 When("a given app has two routes", func() { 397 BeforeEach(func() { 398 fakeCloudControllerClient.GetApplicationsReturns( 399 []resources.Application{ 400 { 401 Name: "some-app-name", 402 }, 403 }, 404 ccv3.Warnings{"some-warning"}, 405 nil, 406 ) 407 }) 408 409 It("returns an ApplicationNotFoundError and the warnings", func() { 410 _, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name", "some-app-name"}, "some-space-guid") 411 Expect(err).ToNot(HaveOccurred()) 412 Expect(warnings).To(ConsistOf("some-warning")) 413 }) 414 }) 415 416 When("the cloud controller client returns an error", func() { 417 var expectedError error 418 419 BeforeEach(func() { 420 expectedError = errors.New("I am a CloudControllerClient Error") 421 fakeCloudControllerClient.GetApplicationsReturns( 422 []resources.Application{}, 423 ccv3.Warnings{"some-warning"}, 424 expectedError) 425 }) 426 427 It("returns the warnings and the error", func() { 428 _, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name"}, "some-space-guid") 429 Expect(warnings).To(ConsistOf("some-warning")) 430 Expect(err).To(MatchError(expectedError)) 431 }) 432 }) 433 }) 434 435 Describe("GetApplicationByNameAndSpace", func() { 436 When("the app exists", func() { 437 BeforeEach(func() { 438 fakeCloudControllerClient.GetApplicationsReturns( 439 []resources.Application{ 440 { 441 Name: "some-app-name", 442 GUID: "some-app-guid", 443 Metadata: &resources.Metadata{ 444 Labels: map[string]types.NullString{ 445 "some-key": types.NewNullString("some-value"), 446 }, 447 }, 448 }, 449 }, 450 ccv3.Warnings{"some-warning"}, 451 nil, 452 ) 453 }) 454 455 It("returns the application and warnings", func() { 456 app, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 457 Expect(err).ToNot(HaveOccurred()) 458 Expect(app).To(Equal(resources.Application{ 459 Name: "some-app-name", 460 GUID: "some-app-guid", 461 Metadata: &resources.Metadata{ 462 Labels: map[string]types.NullString{"some-key": types.NewNullString("some-value")}, 463 }, 464 })) 465 Expect(warnings).To(ConsistOf("some-warning")) 466 467 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 468 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 469 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}}, 470 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 471 )) 472 }) 473 }) 474 475 When("the cloud controller client returns an error", func() { 476 var expectedError error 477 478 BeforeEach(func() { 479 expectedError = errors.New("I am a CloudControllerClient Error") 480 fakeCloudControllerClient.GetApplicationsReturns( 481 []resources.Application{}, 482 ccv3.Warnings{"some-warning"}, 483 expectedError) 484 }) 485 486 It("returns the warnings and the error", func() { 487 _, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 488 Expect(warnings).To(ConsistOf("some-warning")) 489 Expect(err).To(MatchError(expectedError)) 490 }) 491 }) 492 493 When("the app does not exist", func() { 494 BeforeEach(func() { 495 fakeCloudControllerClient.GetApplicationsReturns( 496 []resources.Application{}, 497 ccv3.Warnings{"some-warning"}, 498 nil, 499 ) 500 }) 501 502 It("returns an ApplicationNotFoundError and the warnings", func() { 503 _, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 504 Expect(warnings).To(ConsistOf("some-warning")) 505 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app-name"})) 506 }) 507 }) 508 }) 509 510 Describe("GetApplicationsBySpace", func() { 511 When("the there are applications in the space", func() { 512 BeforeEach(func() { 513 fakeCloudControllerClient.GetApplicationsReturns( 514 []resources.Application{ 515 { 516 GUID: "some-app-guid-1", 517 Name: "some-app-1", 518 }, 519 { 520 GUID: "some-app-guid-2", 521 Name: "some-app-2", 522 }, 523 }, 524 ccv3.Warnings{"warning-1", "warning-2"}, 525 nil, 526 ) 527 }) 528 529 It("returns the application and warnings", func() { 530 apps, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 531 Expect(err).ToNot(HaveOccurred()) 532 Expect(apps).To(ConsistOf( 533 resources.Application{ 534 GUID: "some-app-guid-1", 535 Name: "some-app-1", 536 }, 537 resources.Application{ 538 GUID: "some-app-guid-2", 539 Name: "some-app-2", 540 }, 541 )) 542 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 543 544 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 545 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 546 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 547 )) 548 }) 549 }) 550 551 When("the cloud controller client returns an error", func() { 552 var expectedError error 553 554 BeforeEach(func() { 555 expectedError = errors.New("I am a CloudControllerClient Error") 556 fakeCloudControllerClient.GetApplicationsReturns( 557 []resources.Application{}, 558 ccv3.Warnings{"some-warning"}, 559 expectedError) 560 }) 561 562 It("returns the error and warnings", func() { 563 _, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 564 Expect(warnings).To(ConsistOf("some-warning")) 565 Expect(err).To(MatchError(expectedError)) 566 }) 567 }) 568 }) 569 570 Describe("CreateApplicationInSpace", func() { 571 var ( 572 application resources.Application 573 warnings Warnings 574 err error 575 ) 576 577 JustBeforeEach(func() { 578 application, warnings, err = actor.CreateApplicationInSpace(resources.Application{ 579 Name: "some-app-name", 580 LifecycleType: constant.AppLifecycleTypeBuildpack, 581 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 582 }, "some-space-guid") 583 }) 584 585 When("the app successfully gets created", func() { 586 BeforeEach(func() { 587 fakeCloudControllerClient.CreateApplicationReturns( 588 resources.Application{ 589 Name: "some-app-name", 590 GUID: "some-app-guid", 591 LifecycleType: constant.AppLifecycleTypeBuildpack, 592 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 593 }, 594 ccv3.Warnings{"some-warning"}, 595 nil, 596 ) 597 }) 598 599 It("creates and returns the application and warnings", func() { 600 Expect(err).ToNot(HaveOccurred()) 601 Expect(application).To(Equal(resources.Application{ 602 Name: "some-app-name", 603 GUID: "some-app-guid", 604 LifecycleType: constant.AppLifecycleTypeBuildpack, 605 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 606 })) 607 Expect(warnings).To(ConsistOf("some-warning")) 608 609 Expect(fakeCloudControllerClient.CreateApplicationCallCount()).To(Equal(1)) 610 Expect(fakeCloudControllerClient.CreateApplicationArgsForCall(0)).To(Equal(resources.Application{ 611 Name: "some-app-name", 612 SpaceGUID: "some-space-guid", 613 LifecycleType: constant.AppLifecycleTypeBuildpack, 614 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 615 })) 616 }) 617 }) 618 619 When("the cc client returns an error", func() { 620 var expectedError error 621 622 BeforeEach(func() { 623 expectedError = errors.New("I am a CloudControllerClient Error") 624 fakeCloudControllerClient.CreateApplicationReturns( 625 resources.Application{}, 626 ccv3.Warnings{"some-warning"}, 627 expectedError, 628 ) 629 }) 630 631 It("raises the error and warnings", func() { 632 Expect(err).To(MatchError(expectedError)) 633 Expect(warnings).To(ConsistOf("some-warning")) 634 }) 635 }) 636 637 When("the cc client returns an NameNotUniqueInSpaceError", func() { 638 BeforeEach(func() { 639 fakeCloudControllerClient.CreateApplicationReturns( 640 resources.Application{}, 641 ccv3.Warnings{"some-warning"}, 642 ccerror.NameNotUniqueInSpaceError{}, 643 ) 644 }) 645 646 It("returns the NameNotUniqueInSpaceError and warnings", func() { 647 Expect(err).To(MatchError(ccerror.NameNotUniqueInSpaceError{})) 648 Expect(warnings).To(ConsistOf("some-warning")) 649 }) 650 }) 651 }) 652 653 Describe("UpdateApplication", func() { 654 var ( 655 submitApp, resultApp resources.Application 656 warnings Warnings 657 err error 658 ) 659 660 JustBeforeEach(func() { 661 submitApp = resources.Application{ 662 GUID: "some-app-guid", 663 StackName: "some-stack-name", 664 Name: "some-app-name", 665 LifecycleType: constant.AppLifecycleTypeBuildpack, 666 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 667 Metadata: &resources.Metadata{Labels: map[string]types.NullString{ 668 "some-label": types.NewNullString("some-value"), 669 "other-label": types.NewNullString("other-value"), 670 }}, 671 } 672 673 resultApp, warnings, err = actor.UpdateApplication(submitApp) 674 }) 675 676 When("the app successfully gets updated", func() { 677 var apiResponseApp resources.Application 678 679 BeforeEach(func() { 680 apiResponseApp = resources.Application{ 681 GUID: "response-app-guid", 682 StackName: "response-stack-name", 683 Name: "response-app-name", 684 LifecycleType: constant.AppLifecycleTypeBuildpack, 685 LifecycleBuildpacks: []string{"response-buildpack-1", "response-buildpack-2"}, 686 } 687 fakeCloudControllerClient.UpdateApplicationReturns( 688 apiResponseApp, 689 ccv3.Warnings{"some-warning"}, 690 nil, 691 ) 692 }) 693 694 It("creates and returns the application and warnings", func() { 695 Expect(err).ToNot(HaveOccurred()) 696 Expect(resultApp).To(Equal(resources.Application{ 697 Name: apiResponseApp.Name, 698 GUID: apiResponseApp.GUID, 699 StackName: apiResponseApp.StackName, 700 LifecycleType: apiResponseApp.LifecycleType, 701 LifecycleBuildpacks: apiResponseApp.LifecycleBuildpacks, 702 })) 703 Expect(warnings).To(ConsistOf("some-warning")) 704 705 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 706 Expect(fakeCloudControllerClient.UpdateApplicationArgsForCall(0)).To(Equal(resources.Application{ 707 GUID: submitApp.GUID, 708 StackName: submitApp.StackName, 709 LifecycleType: submitApp.LifecycleType, 710 LifecycleBuildpacks: submitApp.LifecycleBuildpacks, 711 Name: submitApp.Name, 712 Metadata: submitApp.Metadata, 713 })) 714 }) 715 }) 716 717 When("the cc client returns an error", func() { 718 var expectedError error 719 720 BeforeEach(func() { 721 expectedError = errors.New("I am a CloudControllerClient Error") 722 fakeCloudControllerClient.UpdateApplicationReturns( 723 resources.Application{}, 724 ccv3.Warnings{"some-warning"}, 725 expectedError, 726 ) 727 }) 728 729 It("raises the error and warnings", func() { 730 Expect(err).To(MatchError(expectedError)) 731 Expect(warnings).To(ConsistOf("some-warning")) 732 }) 733 }) 734 }) 735 736 Describe("PollStart", func() { 737 var ( 738 app resources.Application 739 noWait bool 740 handleInstanceDetails func(string) 741 742 done chan bool 743 744 warnings Warnings 745 executeErr error 746 reportedInstanceDetails []string 747 ) 748 749 BeforeEach(func() { 750 done = make(chan bool) 751 fakeConfig.StartupTimeoutReturns(2 * time.Second) 752 fakeConfig.PollingIntervalReturns(1 * time.Second) 753 app = resources.Application{GUID: "some-guid"} 754 noWait = false 755 756 reportedInstanceDetails = []string{} 757 handleInstanceDetails = func(instanceDetails string) { 758 reportedInstanceDetails = append(reportedInstanceDetails, instanceDetails) 759 } 760 }) 761 762 JustBeforeEach(func() { 763 go func() { 764 defer close(done) 765 warnings, executeErr = actor.PollStart(app, noWait, handleInstanceDetails) 766 done <- true 767 }() 768 }) 769 770 It("gets the apps processes", func() { 771 // advanced clock so function exits 772 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 773 774 // wait for function to finish 775 Eventually(done).Should(Receive(BeTrue())) 776 777 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(1)) 778 Expect(fakeCloudControllerClient.GetApplicationProcessesArgsForCall(0)).To(Equal("some-guid")) 779 780 }) 781 782 When("getting the application processes fails", func() { 783 BeforeEach(func() { 784 fakeCloudControllerClient.GetApplicationProcessesReturns(nil, ccv3.Warnings{"get-app-warning-1", "get-app-warning-2"}, errors.New("some-error")) 785 }) 786 787 It("returns the error and all warnings", func() { 788 // wait for function to finish 789 Eventually(done).Should(Receive(BeTrue())) 790 791 Expect(executeErr).To(MatchError(errors.New("some-error"))) 792 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-app-warning-2")) 793 }) 794 }) 795 796 When("getting the application process succeeds", func() { 797 BeforeEach(func() { 798 fakeCloudControllerClient.GetApplicationProcessesReturns( 799 []ccv3.Process{ 800 {GUID: "process1", Type: "web"}, 801 }, 802 ccv3.Warnings{"get-app-warning-1"}, 803 nil, 804 ) 805 806 }) 807 808 It("gets the startup timeout", func() { 809 // advanced clock so function exits 810 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 811 812 // wait for function to finish 813 Eventually(done).Should(Receive(BeTrue())) 814 815 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 816 }) 817 818 When("the no-wait flag is provided", func() { 819 BeforeEach(func() { 820 noWait = true 821 fakeCloudControllerClient.GetApplicationProcessesReturns( 822 []ccv3.Process{ 823 {GUID: "process1", Type: "web"}, 824 {GUID: "process2", Type: "worker"}, 825 }, 826 ccv3.Warnings{"get-app-warning-1"}, 827 nil, 828 ) 829 }) 830 831 It("filters out the non web processes", func() { 832 // send something on the timer channel 833 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 834 835 // Wait for function to finish 836 Eventually(done).Should(Receive(BeTrue())) 837 838 // assert on the cc call made within poll processes to make sure there is only the web process 839 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(1)) 840 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("process1")) 841 842 }) 843 }) 844 845 When("polling processes returns an error", func() { 846 BeforeEach(func() { 847 fakeCloudControllerClient.GetProcessInstancesReturns(nil, ccv3.Warnings{"poll-process-warning"}, errors.New("poll-process-error")) 848 }) 849 850 It("returns the error and warnings", func() { 851 // send something on the timer channel 852 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 853 854 // Wait for function to finish 855 Eventually(done).Should(Receive(BeTrue())) 856 857 Expect(executeErr).Should(MatchError("poll-process-error")) 858 Expect(warnings).Should(ConsistOf("poll-process-warning", "get-app-warning-1")) 859 }) 860 }) 861 862 When("polling start times out", func() { 863 BeforeEach(func() { 864 fakeCloudControllerClient.GetProcessInstancesReturns( 865 []ccv3.ProcessInstance{ 866 {State: constant.ProcessInstanceStarting}, 867 }, 868 ccv3.Warnings{"poll-process-warning"}, 869 nil, 870 ) 871 872 fakeConfig.StartupTimeoutReturns(2 * time.Millisecond) 873 }) 874 875 It("returns a timeout error and any warnings", func() { 876 // send something on the timer channel for first tick 877 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 878 879 fakeClock.Increment(1 * time.Millisecond) 880 881 // Wait for function to finish 882 Eventually(done).Should(Receive(BeTrue())) 883 884 Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) 885 Expect(warnings).To(ConsistOf("poll-process-warning", "get-app-warning-1")) 886 }) 887 }) 888 889 When("polling process eventually returns we should stop polling", func() { 890 BeforeEach(func() { 891 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(0, 892 []ccv3.ProcessInstance{ 893 {State: constant.ProcessInstanceStarting}, 894 }, 895 ccv3.Warnings{"poll-process-warning1"}, 896 nil, 897 ) 898 899 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(1, 900 []ccv3.ProcessInstance{ 901 {State: constant.ProcessInstanceRunning}, 902 }, 903 ccv3.Warnings{"poll-process-warning2"}, 904 nil, 905 ) 906 }) 907 908 It("returns success and any warnings", func() { 909 // send something on the timer channel 910 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 911 912 Eventually(fakeConfig.PollingIntervalCallCount).Should(Equal(1)) 913 914 fakeClock.Increment(1 * time.Second) 915 916 // Wait for function to finish 917 Eventually(done).Should(Receive(BeTrue())) 918 Expect(executeErr).NotTo(HaveOccurred()) 919 Expect(warnings).To(ConsistOf("poll-process-warning1", "get-app-warning-1", "poll-process-warning2")) 920 }) 921 922 }) 923 }) 924 }) 925 926 Describe("PollStartForRolling", func() { 927 var ( 928 app resources.Application 929 deploymentGUID string 930 noWait bool 931 handleInstanceDetails func(string) 932 933 done chan bool 934 935 warnings Warnings 936 executeErr error 937 reportedInstanceDetails []string 938 ) 939 940 BeforeEach(func() { 941 reportedInstanceDetails = []string{} 942 handleInstanceDetails = func(instanceDetails string) { 943 reportedInstanceDetails = append(reportedInstanceDetails, instanceDetails) 944 } 945 946 app = resources.Application{GUID: "some-rolling-app-guid"} 947 deploymentGUID = "some-deployment-guid" 948 noWait = false 949 950 done = make(chan bool) 951 952 fakeConfig.StartupTimeoutReturns(5 * time.Second) 953 fakeConfig.PollingIntervalReturns(1 * time.Second) 954 }) 955 956 JustBeforeEach(func() { 957 go func() { 958 warnings, executeErr = actor.PollStartForRolling(app, deploymentGUID, noWait, handleInstanceDetails) 959 done <- true 960 }() 961 }) 962 963 When("There is a non-timeout failure in the loop", func() { 964 // this may need to be expanded to also include when the deployment is superseded or cancelled 965 When("getting the deployment fails", func() { 966 When("it is because the deployment was cancelled", func() { 967 BeforeEach(func() { 968 fakeCloudControllerClient.GetDeploymentReturns( 969 ccv3.Deployment{ 970 StatusValue: constant.DeploymentStatusValueFinalized, 971 StatusReason: constant.DeploymentStatusReasonCanceled, 972 }, 973 ccv3.Warnings{"get-deployment-warning"}, 974 nil, 975 ) 976 }) 977 978 It("returns warnings and the error", func() { 979 // initial tick 980 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 981 982 // wait for func to finish 983 Eventually(done).Should(Receive(BeTrue())) 984 985 Expect(executeErr).To(MatchError("Deployment has been canceled")) 986 Expect(warnings).To(ConsistOf("get-deployment-warning")) 987 988 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(1)) 989 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 990 991 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(0)) 992 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(0)) 993 994 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 995 }) 996 997 }) 998 999 When("it is because the deployment was superseded", func() { 1000 BeforeEach(func() { 1001 fakeCloudControllerClient.GetDeploymentReturns( 1002 ccv3.Deployment{ 1003 StatusValue: constant.DeploymentStatusValueFinalized, 1004 StatusReason: constant.DeploymentStatusReasonSuperseded, 1005 }, 1006 ccv3.Warnings{"get-deployment-warning"}, 1007 nil, 1008 ) 1009 }) 1010 1011 It("returns warnings and the error", func() { 1012 // initial tick 1013 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1014 1015 // wait for func to finish 1016 Eventually(done).Should(Receive(BeTrue())) 1017 1018 Expect(executeErr).To(MatchError("Deployment has been superseded")) 1019 Expect(warnings).To(ConsistOf("get-deployment-warning")) 1020 1021 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(1)) 1022 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1023 1024 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(0)) 1025 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(0)) 1026 1027 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 1028 }) 1029 1030 }) 1031 1032 When("it is because of an API error", func() { 1033 BeforeEach(func() { 1034 fakeCloudControllerClient.GetDeploymentReturns( 1035 ccv3.Deployment{}, 1036 ccv3.Warnings{"get-deployment-warning"}, 1037 errors.New("get-deployment-error"), 1038 ) 1039 }) 1040 1041 It("returns warnings and the error", func() { 1042 // initial tick 1043 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1044 1045 // wait for func to finish 1046 Eventually(done).Should(Receive(BeTrue())) 1047 1048 Expect(executeErr).To(MatchError("get-deployment-error")) 1049 Expect(warnings).To(ConsistOf("get-deployment-warning")) 1050 1051 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(1)) 1052 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1053 1054 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(0)) 1055 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(0)) 1056 1057 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 1058 }) 1059 1060 }) 1061 }) 1062 1063 When("getting the deployment succeeds", func() { 1064 BeforeEach(func() { 1065 // get processes requires the deployment to be deployed so we need this to indirectly test the error case 1066 fakeCloudControllerClient.GetDeploymentReturns( 1067 ccv3.Deployment{StatusValue: constant.DeploymentStatusValueFinalized, StatusReason: constant.DeploymentStatusReasonDeployed}, 1068 ccv3.Warnings{"get-deployment-warning"}, 1069 nil, 1070 ) 1071 1072 }) 1073 1074 When("getting the processes fails", func() { 1075 BeforeEach(func() { 1076 fakeCloudControllerClient.GetApplicationProcessesReturns( 1077 []ccv3.Process{}, 1078 ccv3.Warnings{"get-processes-warning"}, 1079 errors.New("get-processes-error"), 1080 ) 1081 }) 1082 1083 It("returns warnings and the error", func() { 1084 // initial tick 1085 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1086 1087 // wait for func to finish 1088 Eventually(done).Should(Receive(BeTrue())) 1089 1090 Expect(executeErr).To(MatchError("get-processes-error")) 1091 Expect(warnings).To(ConsistOf("get-deployment-warning", "get-processes-warning")) 1092 1093 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(1)) 1094 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1095 1096 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(1)) 1097 Expect(fakeCloudControllerClient.GetApplicationProcessesArgsForCall(0)).To(Equal(app.GUID)) 1098 1099 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(0)) 1100 1101 }) 1102 }) 1103 1104 When("getting the processes succeeds", func() { 1105 BeforeEach(func() { 1106 fakeCloudControllerClient.GetApplicationProcessesReturns( 1107 []ccv3.Process{{GUID: "process-guid"}}, 1108 ccv3.Warnings{"get-processes-warning"}, 1109 nil, 1110 ) 1111 }) 1112 1113 When("polling the processes fails", func() { 1114 BeforeEach(func() { 1115 fakeCloudControllerClient.GetProcessInstancesReturns( 1116 []ccv3.ProcessInstance{}, 1117 ccv3.Warnings{"poll-processes-warning"}, 1118 errors.New("poll-processes-error"), 1119 ) 1120 }) 1121 1122 It("returns all warnings and errors", func() { 1123 // initial tick 1124 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1125 1126 // wait for func to finish 1127 Eventually(done).Should(Receive(BeTrue())) 1128 1129 Expect(executeErr).To(MatchError("poll-processes-error")) 1130 Expect(warnings).To(ConsistOf("get-deployment-warning", "get-processes-warning", "poll-processes-warning")) 1131 1132 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(1)) 1133 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1134 1135 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(1)) 1136 Expect(fakeCloudControllerClient.GetApplicationProcessesArgsForCall(0)).To(Equal(app.GUID)) 1137 1138 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(1)) 1139 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("process-guid")) 1140 }) 1141 1142 }) 1143 }) 1144 1145 }) 1146 1147 }) 1148 1149 // intentionally ignore the no-wait flag here for simplicity. One of these two things must cause timeout regardless of no-wait state 1150 When("there is a timeout error", func() { 1151 BeforeEach(func() { 1152 // 1 millisecond for initial tick then 1 to trigger timeout 1153 fakeConfig.StartupTimeoutReturns(2 * time.Millisecond) 1154 }) 1155 1156 When("the deployment never deploys", func() { 1157 BeforeEach(func() { 1158 fakeCloudControllerClient.GetDeploymentReturns( 1159 ccv3.Deployment{StatusValue: constant.DeploymentStatusValueActive}, 1160 ccv3.Warnings{"get-deployment-warning"}, 1161 nil, 1162 ) 1163 }) 1164 1165 It("returns a timeout error and any warnings", func() { 1166 // initial tick 1167 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1168 1169 Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(1)) 1170 1171 // timeout tick 1172 fakeClock.Increment(1 * time.Millisecond) 1173 1174 // wait for func to finish 1175 Eventually(done).Should(Receive(BeTrue())) 1176 1177 Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) 1178 Expect(warnings).To(ConsistOf("get-deployment-warning")) 1179 }) 1180 }) 1181 1182 When("the processes dont become healthy", func() { 1183 BeforeEach(func() { 1184 fakeCloudControllerClient.GetDeploymentReturns( 1185 ccv3.Deployment{StatusValue: constant.DeploymentStatusValueFinalized, StatusReason: constant.DeploymentStatusReasonDeployed}, 1186 ccv3.Warnings{"get-deployment-warning"}, 1187 nil, 1188 ) 1189 1190 fakeCloudControllerClient.GetApplicationProcessesReturns( 1191 []ccv3.Process{{GUID: "process-guid"}}, 1192 ccv3.Warnings{"get-processes-warning"}, 1193 nil, 1194 ) 1195 1196 fakeCloudControllerClient.GetProcessInstancesReturns( 1197 []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, 1198 ccv3.Warnings{"poll-processes-warning"}, 1199 nil, 1200 ) 1201 }) 1202 1203 It("returns a timeout error and any warnings", func() { 1204 // initial tick 1205 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1206 1207 Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(1)) 1208 Eventually(fakeCloudControllerClient.GetApplicationProcessesCallCount).Should(Equal(1)) 1209 Eventually(fakeCloudControllerClient.GetProcessInstancesCallCount).Should(Equal(1)) 1210 1211 // timeout tick 1212 fakeClock.Increment(1 * time.Millisecond) 1213 1214 // wait for func to finish 1215 Eventually(done).Should(Receive(BeTrue())) 1216 1217 Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) 1218 Expect(warnings).To(ConsistOf("get-deployment-warning", "get-processes-warning", "poll-processes-warning")) 1219 }) 1220 1221 }) 1222 }) 1223 1224 When("things eventually become healthy", func() { 1225 When("the no wait flag is given", func() { 1226 BeforeEach(func() { 1227 // in total three loops 1: deployment still deploying 2: deployment deployed processes starting 3: processes started 1228 noWait = true 1229 1230 // Always return deploying as a way to check we respect no wait 1231 fakeCloudControllerClient.GetDeploymentReturns( 1232 ccv3.Deployment{ 1233 StatusValue: constant.DeploymentStatusValueActive, 1234 NewProcesses: []ccv3.Process{{GUID: "new-deployment-process"}}, 1235 }, 1236 ccv3.Warnings{"get-deployment-warning"}, 1237 nil, 1238 ) 1239 1240 // We only poll the processes. Two loops for fun 1241 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(0, 1242 []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, 1243 ccv3.Warnings{"poll-processes-warning-1"}, 1244 nil, 1245 ) 1246 1247 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(1, 1248 []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}}, 1249 ccv3.Warnings{"poll-processes-warning-2"}, 1250 nil, 1251 ) 1252 }) 1253 1254 It("polls the start of the application correctly and returns warnings and no error", func() { 1255 // Initial tick 1256 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1257 1258 // assert one of our watcher is the timeout 1259 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 1260 1261 // the first time through we always get the deployment regardless of no-wait 1262 Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(1)) 1263 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1264 Eventually(fakeCloudControllerClient.GetProcessInstancesCallCount).Should(Equal(1)) 1265 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("new-deployment-process")) 1266 Eventually(fakeConfig.PollingIntervalCallCount).Should(Equal(1)) 1267 1268 fakeClock.Increment(1 * time.Second) 1269 1270 Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(2)) 1271 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1272 Eventually(fakeCloudControllerClient.GetProcessInstancesCallCount).Should(Equal(2)) 1273 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("new-deployment-process")) 1274 1275 Eventually(done).Should(Receive(BeTrue())) 1276 1277 Expect(executeErr).NotTo(HaveOccurred()) 1278 Expect(warnings).To(ConsistOf( 1279 "get-deployment-warning", 1280 "poll-processes-warning-1", 1281 "get-deployment-warning", 1282 "poll-processes-warning-2", 1283 )) 1284 1285 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(2)) 1286 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(0)) 1287 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(2)) 1288 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 1289 1290 }) 1291 1292 }) 1293 1294 When("the no wait flag is not given", func() { 1295 BeforeEach(func() { 1296 // in total three loops 1: deployment still deploying 2: deployment deployed processes starting 3: processes started 1297 fakeCloudControllerClient.GetDeploymentReturnsOnCall(0, 1298 ccv3.Deployment{StatusValue: constant.DeploymentStatusValueActive}, 1299 ccv3.Warnings{"get-deployment-warning-1"}, 1300 nil, 1301 ) 1302 1303 // Poll the deployment twice to make sure we are polling (one in the above before each) 1304 fakeCloudControllerClient.GetDeploymentReturnsOnCall(1, 1305 ccv3.Deployment{StatusValue: constant.DeploymentStatusValueFinalized, StatusReason: constant.DeploymentStatusReasonDeployed}, 1306 ccv3.Warnings{"get-deployment-warning-2"}, 1307 nil, 1308 ) 1309 1310 // then we get the processes. This should only be called once 1311 fakeCloudControllerClient.GetApplicationProcessesReturns( 1312 []ccv3.Process{{GUID: "process-guid"}}, 1313 ccv3.Warnings{"get-processes-warning"}, 1314 nil, 1315 ) 1316 1317 // then we poll the processes. Two loops for fun 1318 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(0, 1319 []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, 1320 ccv3.Warnings{"poll-processes-warning-1"}, 1321 nil, 1322 ) 1323 1324 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(1, 1325 []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}}, 1326 ccv3.Warnings{"poll-processes-warning-2"}, 1327 nil, 1328 ) 1329 }) 1330 1331 It("polls the start of the application correctly and returns warnings and no error", func() { 1332 // Initial tick 1333 fakeClock.WaitForNWatchersAndIncrement(1*time.Millisecond, 2) 1334 1335 // assert one of our watchers is for the timeout 1336 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 1337 1338 Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(1)) 1339 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(0)).To(Equal(deploymentGUID)) 1340 Eventually(fakeConfig.PollingIntervalCallCount).Should(Equal(1)) 1341 1342 // start the second loop where the deployment is deployed so we poll processes 1343 fakeClock.Increment(1 * time.Second) 1344 1345 Eventually(fakeCloudControllerClient.GetDeploymentCallCount).Should(Equal(2)) 1346 Expect(fakeCloudControllerClient.GetDeploymentArgsForCall(1)).To(Equal(deploymentGUID)) 1347 Eventually(fakeCloudControllerClient.GetApplicationProcessesCallCount).Should(Equal(1)) 1348 Expect(fakeCloudControllerClient.GetApplicationProcessesArgsForCall(0)).To(Equal(app.GUID)) 1349 Eventually(fakeCloudControllerClient.GetProcessInstancesCallCount).Should(Equal(1)) 1350 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("process-guid")) 1351 Eventually(fakeConfig.PollingIntervalCallCount).Should(Equal(2)) 1352 1353 fakeClock.Increment(1 * time.Second) 1354 1355 // we should stop polling because it is deployed 1356 Eventually(fakeCloudControllerClient.GetProcessInstancesCallCount).Should(Equal(2)) 1357 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("process-guid")) 1358 1359 Eventually(done).Should(Receive(BeTrue())) 1360 1361 Expect(executeErr).NotTo(HaveOccurred()) 1362 Expect(warnings).To(ConsistOf( 1363 "get-deployment-warning-1", 1364 "get-deployment-warning-2", 1365 "get-processes-warning", 1366 "poll-processes-warning-1", 1367 "poll-processes-warning-2", 1368 )) 1369 1370 Expect(fakeCloudControllerClient.GetDeploymentCallCount()).To(Equal(2)) 1371 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(1)) 1372 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(2)) 1373 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(2)) 1374 1375 }) 1376 1377 }) 1378 1379 }) 1380 }) 1381 1382 Describe("SetApplicationProcessHealthCheckTypeByNameAndSpace", func() { 1383 var ( 1384 healthCheckType constant.HealthCheckType 1385 healthCheckEndpoint string 1386 1387 warnings Warnings 1388 err error 1389 app resources.Application 1390 ) 1391 1392 BeforeEach(func() { 1393 healthCheckType = constant.HTTP 1394 healthCheckEndpoint = "some-http-endpoint" 1395 }) 1396 1397 JustBeforeEach(func() { 1398 app, warnings, err = actor.SetApplicationProcessHealthCheckTypeByNameAndSpace( 1399 "some-app-name", 1400 "some-space-guid", 1401 healthCheckType, 1402 healthCheckEndpoint, 1403 "some-process-type", 1404 42, 1405 ) 1406 }) 1407 1408 When("getting application returns an error", func() { 1409 var expectedErr error 1410 1411 BeforeEach(func() { 1412 expectedErr = errors.New("some-error") 1413 fakeCloudControllerClient.GetApplicationsReturns( 1414 []resources.Application{}, 1415 ccv3.Warnings{"some-warning"}, 1416 expectedErr, 1417 ) 1418 }) 1419 1420 It("returns the error and warnings", func() { 1421 Expect(err).To(Equal(expectedErr)) 1422 Expect(warnings).To(ConsistOf("some-warning")) 1423 }) 1424 }) 1425 1426 When("application exists", func() { 1427 var ccv3App resources.Application 1428 1429 BeforeEach(func() { 1430 ccv3App = resources.Application{ 1431 GUID: "some-app-guid", 1432 } 1433 1434 fakeCloudControllerClient.GetApplicationsReturns( 1435 []resources.Application{ccv3App}, 1436 ccv3.Warnings{"some-warning"}, 1437 nil, 1438 ) 1439 }) 1440 1441 When("setting the health check returns an error", func() { 1442 var expectedErr error 1443 1444 BeforeEach(func() { 1445 expectedErr = errors.New("some-error") 1446 fakeCloudControllerClient.GetApplicationProcessByTypeReturns( 1447 ccv3.Process{}, 1448 ccv3.Warnings{"some-process-warning"}, 1449 expectedErr, 1450 ) 1451 }) 1452 1453 It("returns the error and warnings", func() { 1454 Expect(err).To(Equal(expectedErr)) 1455 Expect(warnings).To(ConsistOf("some-warning", "some-process-warning")) 1456 }) 1457 }) 1458 1459 When("application process exists", func() { 1460 BeforeEach(func() { 1461 fakeCloudControllerClient.GetApplicationProcessByTypeReturns( 1462 ccv3.Process{GUID: "some-process-guid"}, 1463 ccv3.Warnings{"some-process-warning"}, 1464 nil, 1465 ) 1466 1467 fakeCloudControllerClient.UpdateProcessReturns( 1468 ccv3.Process{GUID: "some-process-guid"}, 1469 ccv3.Warnings{"some-health-check-warning"}, 1470 nil, 1471 ) 1472 }) 1473 1474 It("returns the application", func() { 1475 Expect(err).NotTo(HaveOccurred()) 1476 Expect(warnings).To(ConsistOf("some-warning", "some-process-warning", "some-health-check-warning")) 1477 1478 Expect(app).To(Equal(resources.Application{ 1479 GUID: ccv3App.GUID, 1480 })) 1481 1482 Expect(fakeCloudControllerClient.GetApplicationProcessByTypeCallCount()).To(Equal(1)) 1483 appGUID, processType := fakeCloudControllerClient.GetApplicationProcessByTypeArgsForCall(0) 1484 Expect(appGUID).To(Equal("some-app-guid")) 1485 Expect(processType).To(Equal("some-process-type")) 1486 1487 Expect(fakeCloudControllerClient.UpdateProcessCallCount()).To(Equal(1)) 1488 process := fakeCloudControllerClient.UpdateProcessArgsForCall(0) 1489 Expect(process.GUID).To(Equal("some-process-guid")) 1490 Expect(process.HealthCheckType).To(Equal(constant.HTTP)) 1491 Expect(process.HealthCheckEndpoint).To(Equal("some-http-endpoint")) 1492 Expect(process.HealthCheckInvocationTimeout).To(BeEquivalentTo(42)) 1493 }) 1494 }) 1495 }) 1496 }) 1497 1498 Describe("StopApplication", func() { 1499 var ( 1500 warnings Warnings 1501 executeErr error 1502 ) 1503 1504 JustBeforeEach(func() { 1505 warnings, executeErr = actor.StopApplication("some-app-guid") 1506 }) 1507 1508 When("there are no client errors", func() { 1509 BeforeEach(func() { 1510 fakeCloudControllerClient.UpdateApplicationStopReturns( 1511 resources.Application{GUID: "some-app-guid"}, 1512 ccv3.Warnings{"stop-application-warning"}, 1513 nil, 1514 ) 1515 }) 1516 1517 It("stops the application", func() { 1518 Expect(executeErr).ToNot(HaveOccurred()) 1519 Expect(warnings).To(ConsistOf("stop-application-warning")) 1520 1521 Expect(fakeCloudControllerClient.UpdateApplicationStopCallCount()).To(Equal(1)) 1522 Expect(fakeCloudControllerClient.UpdateApplicationStopArgsForCall(0)).To(Equal("some-app-guid")) 1523 }) 1524 }) 1525 1526 When("stopping the application fails", func() { 1527 var expectedErr error 1528 BeforeEach(func() { 1529 expectedErr = errors.New("some set stop-application error") 1530 fakeCloudControllerClient.UpdateApplicationStopReturns( 1531 resources.Application{}, 1532 ccv3.Warnings{"stop-application-warning"}, 1533 expectedErr, 1534 ) 1535 }) 1536 1537 It("returns the error", func() { 1538 Expect(executeErr).To(Equal(expectedErr)) 1539 Expect(warnings).To(ConsistOf("stop-application-warning")) 1540 }) 1541 }) 1542 }) 1543 1544 Describe("StartApplication", func() { 1545 var ( 1546 warnings Warnings 1547 executeErr error 1548 ) 1549 1550 BeforeEach(func() { 1551 fakeConfig.StartupTimeoutReturns(time.Second) 1552 fakeConfig.PollingIntervalReturns(0) 1553 }) 1554 1555 JustBeforeEach(func() { 1556 warnings, executeErr = actor.StartApplication("some-app-guid") 1557 }) 1558 1559 When("there are no client errors", func() { 1560 BeforeEach(func() { 1561 fakeCloudControllerClient.UpdateApplicationStartReturns( 1562 resources.Application{GUID: "some-app-guid"}, 1563 ccv3.Warnings{"start-application-warning"}, 1564 nil, 1565 ) 1566 }) 1567 1568 It("starts the application", func() { 1569 Expect(executeErr).ToNot(HaveOccurred()) 1570 Expect(warnings).To(ConsistOf("start-application-warning")) 1571 1572 Expect(fakeCloudControllerClient.UpdateApplicationStartCallCount()).To(Equal(1)) 1573 Expect(fakeCloudControllerClient.UpdateApplicationStartArgsForCall(0)).To(Equal("some-app-guid")) 1574 }) 1575 }) 1576 1577 When("starting the application fails", func() { 1578 var expectedErr error 1579 1580 BeforeEach(func() { 1581 expectedErr = errors.New("some set start-application error") 1582 fakeCloudControllerClient.UpdateApplicationStartReturns( 1583 resources.Application{}, 1584 ccv3.Warnings{"start-application-warning"}, 1585 expectedErr, 1586 ) 1587 }) 1588 1589 It("returns the error", func() { 1590 warnings, err := actor.StartApplication("some-app-guid") 1591 1592 Expect(err).To(Equal(expectedErr)) 1593 Expect(warnings).To(ConsistOf("start-application-warning")) 1594 }) 1595 }) 1596 }) 1597 1598 Describe("RestartApplication", func() { 1599 var ( 1600 warnings Warnings 1601 executeErr error 1602 noWait bool 1603 ) 1604 1605 BeforeEach(func() { 1606 fakeConfig.StartupTimeoutReturns(time.Second) 1607 fakeConfig.PollingIntervalReturns(0) 1608 noWait = false 1609 }) 1610 1611 JustBeforeEach(func() { 1612 warnings, executeErr = actor.RestartApplication("some-app-guid", noWait) 1613 }) 1614 1615 When("restarting the application is successful", func() { 1616 BeforeEach(func() { 1617 fakeCloudControllerClient.UpdateApplicationRestartReturns( 1618 resources.Application{GUID: "some-app-guid"}, 1619 ccv3.Warnings{"restart-application-warning"}, 1620 nil, 1621 ) 1622 }) 1623 1624 It("does not error", func() { 1625 Expect(executeErr).ToNot(HaveOccurred()) 1626 Expect(warnings).To(ConsistOf("restart-application-warning")) 1627 }) 1628 }) 1629 1630 When("restarting the application fails", func() { 1631 var expectedErr error 1632 1633 BeforeEach(func() { 1634 expectedErr = errors.New("some set restart-application error") 1635 fakeCloudControllerClient.UpdateApplicationRestartReturns( 1636 resources.Application{}, 1637 ccv3.Warnings{"restart-application-warning"}, 1638 expectedErr, 1639 ) 1640 }) 1641 1642 It("returns the warnings and error", func() { 1643 Expect(executeErr).To(Equal(expectedErr)) 1644 Expect(warnings).To(ConsistOf("restart-application-warning")) 1645 }) 1646 }) 1647 }) 1648 1649 Describe("PollProcesses", func() { 1650 var ( 1651 processes []ccv3.Process 1652 handleInstanceDetails func(string) 1653 reportedInstanceDetails []string 1654 1655 keepPolling bool 1656 warnings Warnings 1657 executeErr error 1658 ) 1659 1660 BeforeEach(func() { 1661 reportedInstanceDetails = []string{} 1662 handleInstanceDetails = func(instanceDetails string) { 1663 reportedInstanceDetails = append(reportedInstanceDetails, instanceDetails) 1664 } 1665 1666 processes = []ccv3.Process{ 1667 {GUID: "process-1"}, 1668 {GUID: "process-2"}, 1669 } 1670 }) 1671 1672 JustBeforeEach(func() { 1673 keepPolling, warnings, executeErr = actor.PollProcesses(processes, handleInstanceDetails) 1674 }) 1675 1676 It("gets process instances for each process", func() { 1677 Expect(executeErr).NotTo(HaveOccurred()) 1678 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(2)) 1679 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("process-1")) 1680 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(1)).To(Equal("process-2")) 1681 }) 1682 1683 When("getting the process instances fails", func() { 1684 BeforeEach(func() { 1685 fakeCloudControllerClient.GetProcessInstancesReturns(nil, ccv3.Warnings{"get-instances-warning"}, errors.New("get-instances-error")) 1686 }) 1687 1688 It("returns an error and warnings and terminates the loop", func() { 1689 Expect(executeErr).To(MatchError("get-instances-error")) 1690 Expect(warnings).To(ConsistOf("get-instances-warning")) 1691 Expect(keepPolling).To(BeTrue()) 1692 1693 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(1)) 1694 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("process-1")) 1695 }) 1696 }) 1697 1698 When("getting the process instances is always successful", func() { 1699 When("a process has all instances crashed", func() { 1700 BeforeEach(func() { 1701 fakeCloudControllerClient.GetProcessInstancesReturns( 1702 []ccv3.ProcessInstance{ 1703 {State: constant.ProcessInstanceCrashed, Details: "details1"}, 1704 }, 1705 ccv3.Warnings{"get-process1-instances-warning"}, 1706 nil, 1707 ) 1708 }) 1709 1710 It("calls the callback function with the retrieved instances", func() { 1711 Expect(reportedInstanceDetails).To(Equal([]string{ 1712 "Error starting instances: 'details1'", 1713 })) 1714 }) 1715 1716 It("returns an all instances crashed error", func() { 1717 Expect(executeErr).To(MatchError(actionerror.AllInstancesCrashedError{})) 1718 Expect(warnings).To(ConsistOf("get-process1-instances-warning")) 1719 Expect(keepPolling).To(BeTrue()) 1720 }) 1721 }) 1722 1723 When("there are still instances in the starting state for a process", func() { 1724 BeforeEach(func() { 1725 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(0, 1726 []ccv3.ProcessInstance{ 1727 {State: constant.ProcessInstanceRunning}, 1728 }, 1729 ccv3.Warnings{"get-process1-instances-warning"}, 1730 nil, 1731 ) 1732 1733 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(1, 1734 []ccv3.ProcessInstance{ 1735 {State: constant.ProcessInstanceStarting, Details: "details2"}, 1736 }, 1737 ccv3.Warnings{"get-process2-instances-warning"}, 1738 nil, 1739 ) 1740 }) 1741 1742 It("calls the callback function with the retrieved instances", func() { 1743 Expect(reportedInstanceDetails).To(Equal([]string{ 1744 "Instances starting...", 1745 "Error starting instances: 'details2'", 1746 })) 1747 }) 1748 1749 It("returns success and that we should keep polling", func() { 1750 Expect(executeErr).NotTo(HaveOccurred()) 1751 Expect(warnings).To(ConsistOf("get-process1-instances-warning", "get-process2-instances-warning")) 1752 Expect(keepPolling).To(BeFalse()) 1753 }) 1754 }) 1755 1756 When("all the instances of all processes are stable", func() { 1757 BeforeEach(func() { 1758 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(0, 1759 []ccv3.ProcessInstance{ 1760 {State: constant.ProcessInstanceRunning, Details: "details1"}, 1761 }, 1762 ccv3.Warnings{"get-process1-instances-warning"}, 1763 nil, 1764 ) 1765 1766 fakeCloudControllerClient.GetProcessInstancesReturnsOnCall(1, 1767 []ccv3.ProcessInstance{ 1768 {State: constant.ProcessInstanceRunning}, 1769 }, 1770 ccv3.Warnings{"get-process2-instances-warning"}, 1771 nil, 1772 ) 1773 }) 1774 1775 It("calls the callback function with the retrieved instances", func() { 1776 Expect(reportedInstanceDetails).To(Equal([]string{ 1777 "Error starting instances: 'details1'", 1778 "Instances starting...", 1779 })) 1780 }) 1781 1782 It("returns success and that we should keep polling", func() { 1783 Expect(executeErr).NotTo(HaveOccurred()) 1784 Expect(warnings).To(ConsistOf("get-process1-instances-warning", "get-process2-instances-warning")) 1785 Expect(keepPolling).To(BeTrue()) 1786 }) 1787 1788 }) 1789 }) 1790 1791 }) 1792 1793 Describe("GetUnstagedNewestPackageGUID", func() { 1794 var ( 1795 packageToStage string 1796 warnings Warnings 1797 executeErr error 1798 ) 1799 1800 JustBeforeEach(func() { 1801 packageToStage, warnings, executeErr = actor.GetUnstagedNewestPackageGUID("some-app-guid") 1802 }) 1803 1804 // Nothing to stage. 1805 When("There are no packages on the app", func() { 1806 When("getting the packages succeeds", func() { 1807 BeforeEach(func() { 1808 fakeCloudControllerClient.GetPackagesReturns([]ccv3.Package{}, ccv3.Warnings{"get-packages-warnings"}, nil) 1809 }) 1810 1811 It("checks for packages", func() { 1812 Expect(fakeCloudControllerClient.GetPackagesCallCount()).To(Equal(1)) 1813 Expect(fakeCloudControllerClient.GetPackagesArgsForCall(0)).To(ConsistOf( 1814 ccv3.Query{Key: ccv3.AppGUIDFilter, Values: []string{"some-app-guid"}}, 1815 ccv3.Query{Key: ccv3.OrderBy, Values: []string{ccv3.CreatedAtDescendingOrder}}, 1816 ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}}, 1817 )) 1818 }) 1819 1820 It("returns empty string", func() { 1821 Expect(packageToStage).To(Equal("")) 1822 Expect(warnings).To(ConsistOf("get-packages-warnings")) 1823 Expect(executeErr).To(BeNil()) 1824 }) 1825 }) 1826 1827 When("getting the packages fails", func() { 1828 BeforeEach(func() { 1829 fakeCloudControllerClient.GetPackagesReturns( 1830 nil, 1831 ccv3.Warnings{"get-packages-warnings"}, 1832 errors.New("get-packages-error"), 1833 ) 1834 }) 1835 1836 It("returns the error", func() { 1837 Expect(warnings).To(ConsistOf("get-packages-warnings")) 1838 Expect(executeErr).To(MatchError("get-packages-error")) 1839 }) 1840 }) 1841 }) 1842 1843 When("there are packages", func() { 1844 BeforeEach(func() { 1845 fakeCloudControllerClient.GetPackagesReturns( 1846 []ccv3.Package{{GUID: "package-guid", CreatedAt: "2019-01-01T06:00:00Z"}}, 1847 ccv3.Warnings{"get-packages-warning"}, 1848 nil) 1849 }) 1850 1851 It("checks for the packages latest droplet", func() { 1852 Expect(fakeCloudControllerClient.GetPackageDropletsCallCount()).To(Equal(1)) 1853 packageGuid, queries := fakeCloudControllerClient.GetPackageDropletsArgsForCall(0) 1854 Expect(packageGuid).To(Equal("package-guid")) 1855 Expect(queries).To(ConsistOf( 1856 ccv3.Query{Key: ccv3.PerPage, Values: []string{"1"}}, 1857 ccv3.Query{Key: ccv3.StatesFilter, Values: []string{"STAGED"}}, 1858 )) 1859 }) 1860 1861 When("the newest package's has a STAGED droplet", func() { 1862 BeforeEach(func() { 1863 fakeCloudControllerClient.GetPackageDropletsReturns( 1864 []resources.Droplet{{State: constant.DropletStaged}}, 1865 ccv3.Warnings{"get-package-droplet-warning"}, 1866 nil, 1867 ) 1868 }) 1869 1870 It("returns empty string", func() { 1871 Expect(packageToStage).To(Equal("")) 1872 Expect(warnings).To(ConsistOf("get-packages-warning", "get-package-droplet-warning")) 1873 Expect(executeErr).To(BeNil()) 1874 }) 1875 }) 1876 1877 When("the package has no STAGED droplets", func() { 1878 BeforeEach(func() { 1879 fakeCloudControllerClient.GetPackageDropletsReturns( 1880 []resources.Droplet{}, 1881 ccv3.Warnings{"get-package-droplet-warning"}, 1882 nil, 1883 ) 1884 }) 1885 1886 It("returns the guid of the newest package", func() { 1887 Expect(packageToStage).To(Equal("package-guid")) 1888 Expect(warnings).To(ConsistOf("get-packages-warning", "get-package-droplet-warning")) 1889 Expect(executeErr).To(BeNil()) 1890 }) 1891 }) 1892 }) 1893 }) 1894 1895 Describe("RenameApplicationByNameAndSpaceGUID", func() { 1896 When("the app does not exist", func() { 1897 BeforeEach(func() { 1898 fakeCloudControllerClient.GetApplicationsReturns( 1899 []resources.Application{}, 1900 ccv3.Warnings{"some-warning"}, 1901 nil, 1902 ) 1903 }) 1904 1905 It("returns an ApplicationNotFoundError and the warnings", func() { 1906 _, warnings, err := actor.RenameApplicationByNameAndSpaceGUID("old-app-name", "new-app-name", "space-guid") 1907 Expect(warnings).To(ConsistOf("some-warning")) 1908 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "old-app-name"})) 1909 }) 1910 }) 1911 1912 When("the cloud controller client returns an error on application find", func() { 1913 var expectedError error 1914 1915 BeforeEach(func() { 1916 expectedError = errors.New("I am a CloudControllerClient Error") 1917 fakeCloudControllerClient.GetApplicationsReturns( 1918 []resources.Application{}, 1919 ccv3.Warnings{"some-warning"}, 1920 expectedError) 1921 }) 1922 1923 It("returns the warnings and the error", func() { 1924 _, warnings, err := actor.RenameApplicationByNameAndSpaceGUID("old-app-name", "new-app-name", "space-guid") 1925 Expect(warnings).To(ConsistOf("some-warning")) 1926 Expect(err).To(MatchError(expectedError)) 1927 }) 1928 }) 1929 1930 When("the cloud controller client returns an error on application update", func() { 1931 var expectedError error 1932 1933 BeforeEach(func() { 1934 expectedError = errors.New("I am a CloudControllerClient Error") 1935 fakeCloudControllerClient.GetApplicationsReturns( 1936 []resources.Application{ 1937 { 1938 Name: "old-app-name", 1939 GUID: "old-app-guid", 1940 }, 1941 }, 1942 ccv3.Warnings{"get-app-warning"}, 1943 nil) 1944 fakeCloudControllerClient.UpdateApplicationReturns( 1945 resources.Application{}, 1946 ccv3.Warnings{"update-app-warning"}, 1947 expectedError) 1948 }) 1949 1950 It("returns the warnings and the error", func() { 1951 _, warnings, err := actor.RenameApplicationByNameAndSpaceGUID("old-app-name", "new-app-name", "space-guid") 1952 Expect(warnings).To(ConsistOf("get-app-warning", "update-app-warning")) 1953 Expect(err).To(MatchError(expectedError)) 1954 }) 1955 }) 1956 1957 When("the app exists", func() { 1958 BeforeEach(func() { 1959 fakeCloudControllerClient.GetApplicationsReturns( 1960 []resources.Application{ 1961 { 1962 Name: "old-app-name", 1963 GUID: "old-app-guid", 1964 }, 1965 }, 1966 ccv3.Warnings{"get-app-warning"}, 1967 nil, 1968 ) 1969 1970 fakeCloudControllerClient.UpdateApplicationReturns( 1971 resources.Application{ 1972 Name: "new-app-name", 1973 GUID: "old-app-guid", 1974 }, 1975 ccv3.Warnings{"update-app-warning"}, 1976 nil, 1977 ) 1978 }) 1979 1980 It("changes the app name and returns the application and warnings", func() { 1981 app, warnings, err := actor.RenameApplicationByNameAndSpaceGUID("old-app-name", "new-app-name", "some-space-guid") 1982 Expect(err).ToNot(HaveOccurred()) 1983 Expect(app).To(Equal(resources.Application{ 1984 Name: "new-app-name", 1985 GUID: "old-app-guid", 1986 })) 1987 Expect(warnings).To(ConsistOf("get-app-warning", "update-app-warning")) 1988 1989 Expect(fakeCloudControllerClient.UpdateApplicationArgsForCall(0)).To(Equal( 1990 resources.Application{ 1991 Name: "new-app-name", 1992 GUID: "old-app-guid", 1993 })) 1994 1995 }) 1996 }) 1997 1998 }) 1999 })