github.com/willmadison/cli@v6.40.1-0.20181018160101-29d5937903ff+incompatible/actor/v2action/application_test.go (about) 1 package v2action_test 2 3 import ( 4 "errors" 5 "time" 6 7 "code.cloudfoundry.org/cli/actor/actionerror" 8 . "code.cloudfoundry.org/cli/actor/v2action" 9 "code.cloudfoundry.org/cli/actor/v2action/v2actionfakes" 10 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 11 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2" 12 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant" 13 "code.cloudfoundry.org/cli/types" 14 15 "github.com/cloudfoundry/sonde-go/events" 16 . "github.com/onsi/ginkgo" 17 . "github.com/onsi/gomega" 18 ) 19 20 var _ = Describe("Application Actions", func() { 21 var ( 22 actor *Actor 23 fakeCloudControllerClient *v2actionfakes.FakeCloudControllerClient 24 fakeConfig *v2actionfakes.FakeConfig 25 ) 26 27 BeforeEach(func() { 28 actor, fakeCloudControllerClient, _, fakeConfig = NewTestActor() 29 fakeConfig.DialTimeoutReturns(time.Millisecond) 30 }) 31 32 Describe("Application", func() { 33 var app Application 34 BeforeEach(func() { 35 app = Application{} 36 }) 37 38 Describe("CalculatedCommand", func() { 39 When("command is set", func() { 40 BeforeEach(func() { 41 app.Command = types.FilteredString{IsSet: true, Value: "foo"} 42 app.DetectedStartCommand = types.FilteredString{IsSet: true, Value: "bar"} 43 }) 44 45 It("returns back the command", func() { 46 Expect(app.CalculatedCommand()).To(Equal("foo")) 47 }) 48 }) 49 50 Context("only detected start command is set", func() { 51 BeforeEach(func() { 52 app.DetectedStartCommand = types.FilteredString{IsSet: true, Value: "bar"} 53 }) 54 55 It("returns back the detected start command", func() { 56 Expect(app.CalculatedCommand()).To(Equal("bar")) 57 }) 58 }) 59 60 Context("neither command nor detected start command are set", func() { 61 It("returns an empty string", func() { 62 Expect(app.CalculatedCommand()).To(BeEmpty()) 63 }) 64 }) 65 }) 66 67 Describe("CalculatedBuildpack", func() { 68 When("buildpack is set", func() { 69 BeforeEach(func() { 70 app.Buildpack = types.FilteredString{IsSet: true, Value: "foo"} 71 app.DetectedBuildpack = types.FilteredString{IsSet: true, Value: "bar"} 72 }) 73 74 It("returns back the buildpack", func() { 75 Expect(app.CalculatedBuildpack()).To(Equal("foo")) 76 }) 77 }) 78 79 Context("only detected buildpack is set", func() { 80 BeforeEach(func() { 81 app.DetectedBuildpack = types.FilteredString{IsSet: true, Value: "bar"} 82 }) 83 84 It("returns back the detected buildpack", func() { 85 Expect(app.CalculatedBuildpack()).To(Equal("bar")) 86 }) 87 }) 88 89 Context("neither buildpack nor detected buildpack are set", func() { 90 It("returns an empty string", func() { 91 Expect(app.CalculatedBuildpack()).To(BeEmpty()) 92 }) 93 }) 94 }) 95 96 Describe("CalculatedHealthCheckEndpoint", func() { 97 When("the health check type is http", func() { 98 BeforeEach(func() { 99 app.HealthCheckType = "http" 100 app.HealthCheckHTTPEndpoint = "/some-endpoint" 101 }) 102 103 It("returns the endpoint field", func() { 104 Expect(app.CalculatedHealthCheckEndpoint()).To(Equal( 105 "/some-endpoint")) 106 }) 107 }) 108 109 When("the health check type is not http", func() { 110 BeforeEach(func() { 111 app.HealthCheckType = "process" 112 app.HealthCheckHTTPEndpoint = "/some-endpoint" 113 }) 114 115 It("returns the empty string", func() { 116 Expect(app.CalculatedHealthCheckEndpoint()).To(Equal("")) 117 }) 118 }) 119 }) 120 121 Describe("StagingCompleted", func() { 122 When("staging the application completes", func() { 123 It("returns true", func() { 124 app.PackageState = constant.ApplicationPackageStaged 125 Expect(app.StagingCompleted()).To(BeTrue()) 126 }) 127 }) 128 129 When("the application is *not* staged", func() { 130 It("returns false", func() { 131 app.PackageState = constant.ApplicationPackageFailed 132 Expect(app.StagingCompleted()).To(BeFalse()) 133 }) 134 }) 135 }) 136 137 Describe("StagingFailed", func() { 138 When("staging the application fails", func() { 139 It("returns true", func() { 140 app.PackageState = constant.ApplicationPackageFailed 141 Expect(app.StagingFailed()).To(BeTrue()) 142 }) 143 }) 144 145 When("staging the application does *not* fail", func() { 146 It("returns false", func() { 147 app.PackageState = constant.ApplicationPackageStaged 148 Expect(app.StagingFailed()).To(BeFalse()) 149 }) 150 }) 151 }) 152 153 Describe("StagingFailedMessage", func() { 154 When("the application has a staging failed description", func() { 155 BeforeEach(func() { 156 app.StagingFailedDescription = "An app was not successfully detected by any available buildpack" 157 app.StagingFailedReason = "NoAppDetectedError" 158 }) 159 It("returns that description", func() { 160 Expect(app.StagingFailedMessage()).To(Equal("An app was not successfully detected by any available buildpack")) 161 }) 162 }) 163 164 When("the application does not have a staging failed description", func() { 165 BeforeEach(func() { 166 app.StagingFailedDescription = "" 167 app.StagingFailedReason = "NoAppDetectedError" 168 }) 169 It("returns the staging failed code", func() { 170 Expect(app.StagingFailedMessage()).To(Equal("NoAppDetectedError")) 171 }) 172 }) 173 }) 174 175 Describe("StagingFailedNoAppDetected", func() { 176 When("staging the application fails due to a no app detected error", func() { 177 It("returns true", func() { 178 app.StagingFailedReason = "NoAppDetectedError" 179 Expect(app.StagingFailedNoAppDetected()).To(BeTrue()) 180 }) 181 }) 182 183 When("staging the application fails due to any other reason", func() { 184 It("returns false", func() { 185 app.StagingFailedReason = "InsufficientResources" 186 Expect(app.StagingFailedNoAppDetected()).To(BeFalse()) 187 }) 188 }) 189 }) 190 191 Describe("Started", func() { 192 When("app is started", func() { 193 It("returns true", func() { 194 Expect(Application{State: constant.ApplicationStarted}.Started()).To(BeTrue()) 195 }) 196 }) 197 198 When("app is stopped", func() { 199 It("returns false", func() { 200 Expect(Application{State: constant.ApplicationStopped}.Started()).To(BeFalse()) 201 }) 202 }) 203 }) 204 205 Describe("Stopped", func() { 206 When("app is started", func() { 207 It("returns true", func() { 208 Expect(Application{State: constant.ApplicationStopped}.Stopped()).To(BeTrue()) 209 }) 210 }) 211 212 When("app is stopped", func() { 213 It("returns false", func() { 214 Expect(Application{State: constant.ApplicationStarted}.Stopped()).To(BeFalse()) 215 }) 216 }) 217 }) 218 }) 219 220 Describe("CreateApplication", func() { 221 When("the create is successful", func() { 222 var expectedApp ccv2.Application 223 BeforeEach(func() { 224 expectedApp = ccv2.Application{ 225 GUID: "some-app-guid", 226 Name: "some-app-name", 227 SpaceGUID: "some-space-guid", 228 } 229 fakeCloudControllerClient.CreateApplicationReturns(expectedApp, ccv2.Warnings{"some-app-warning-1"}, nil) 230 }) 231 232 It("creates and returns the application", func() { 233 newApp := Application{ 234 Name: "some-app-name", 235 SpaceGUID: "some-space-guid", 236 } 237 app, warnings, err := actor.CreateApplication(newApp) 238 Expect(err).ToNot(HaveOccurred()) 239 Expect(warnings).To(ConsistOf("some-app-warning-1")) 240 Expect(app).To(Equal(Application(expectedApp))) 241 242 Expect(fakeCloudControllerClient.CreateApplicationCallCount()).To(Equal(1)) 243 Expect(fakeCloudControllerClient.CreateApplicationArgsForCall(0)).To(Equal(ccv2.Application(newApp))) 244 }) 245 }) 246 247 When("the client returns back an error", func() { 248 var expectedErr error 249 BeforeEach(func() { 250 expectedErr = errors.New("some create app error") 251 fakeCloudControllerClient.CreateApplicationReturns(ccv2.Application{}, ccv2.Warnings{"some-app-warning-1"}, expectedErr) 252 }) 253 254 It("returns warnings and an error", func() { 255 newApp := Application{ 256 Name: "some-app-name", 257 SpaceGUID: "some-space-guid", 258 } 259 _, warnings, err := actor.CreateApplication(newApp) 260 Expect(warnings).To(ConsistOf("some-app-warning-1")) 261 Expect(err).To(MatchError(expectedErr)) 262 }) 263 }) 264 }) 265 266 Describe("GetApplication", func() { 267 When("the application exists", func() { 268 BeforeEach(func() { 269 fakeCloudControllerClient.GetApplicationReturns( 270 ccv2.Application{ 271 GUID: "some-app-guid", 272 Name: "some-app", 273 }, 274 ccv2.Warnings{"foo"}, 275 nil, 276 ) 277 }) 278 279 It("returns the application and warnings", func() { 280 app, warnings, err := actor.GetApplication("some-app-guid") 281 Expect(err).ToNot(HaveOccurred()) 282 Expect(app).To(Equal(Application{ 283 GUID: "some-app-guid", 284 Name: "some-app", 285 })) 286 Expect(warnings).To(Equal(Warnings{"foo"})) 287 288 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(1)) 289 Expect(fakeCloudControllerClient.GetApplicationArgsForCall(0)).To(Equal("some-app-guid")) 290 }) 291 }) 292 293 When("the application does not exist", func() { 294 BeforeEach(func() { 295 fakeCloudControllerClient.GetApplicationReturns(ccv2.Application{}, nil, ccerror.ResourceNotFoundError{}) 296 }) 297 298 It("returns an ApplicationNotFoundError", func() { 299 _, _, err := actor.GetApplication("some-app-guid") 300 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{GUID: "some-app-guid"})) 301 }) 302 }) 303 }) 304 305 Describe("GetApplicationByNameAndSpace", func() { 306 When("the application exists", func() { 307 BeforeEach(func() { 308 fakeCloudControllerClient.GetApplicationsReturns( 309 []ccv2.Application{ 310 { 311 GUID: "some-app-guid", 312 Name: "some-app", 313 }, 314 }, 315 ccv2.Warnings{"foo"}, 316 nil, 317 ) 318 }) 319 320 It("returns the application and warnings", func() { 321 app, warnings, err := actor.GetApplicationByNameAndSpace("some-app", "some-space-guid") 322 Expect(err).ToNot(HaveOccurred()) 323 Expect(app).To(Equal(Application{ 324 GUID: "some-app-guid", 325 Name: "some-app", 326 })) 327 Expect(warnings).To(Equal(Warnings{"foo"})) 328 329 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 330 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf([]ccv2.Filter{ 331 ccv2.Filter{ 332 Type: constant.NameFilter, 333 Operator: constant.EqualOperator, 334 Values: []string{"some-app"}, 335 }, 336 ccv2.Filter{ 337 Type: constant.SpaceGUIDFilter, 338 Operator: constant.EqualOperator, 339 Values: []string{"some-space-guid"}, 340 }, 341 })) 342 }) 343 }) 344 345 When("the application does not exists", func() { 346 BeforeEach(func() { 347 fakeCloudControllerClient.GetApplicationsReturns([]ccv2.Application{}, nil, nil) 348 }) 349 350 It("returns an ApplicationNotFoundError", func() { 351 _, _, err := actor.GetApplicationByNameAndSpace("some-app", "some-space-guid") 352 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app"})) 353 }) 354 }) 355 356 When("the cloud controller client returns an error", func() { 357 var expectedError error 358 359 BeforeEach(func() { 360 expectedError = errors.New("I am a CloudControllerClient Error") 361 fakeCloudControllerClient.GetApplicationsReturns([]ccv2.Application{}, nil, expectedError) 362 }) 363 364 It("returns the error", func() { 365 _, _, err := actor.GetApplicationByNameAndSpace("some-app", "some-space-guid") 366 Expect(err).To(MatchError(expectedError)) 367 }) 368 }) 369 }) 370 371 Describe("GetApplicationsBySpace", func() { 372 When("the there are applications in the space", func() { 373 BeforeEach(func() { 374 fakeCloudControllerClient.GetApplicationsReturns( 375 []ccv2.Application{ 376 { 377 GUID: "some-app-guid-1", 378 Name: "some-app-1", 379 }, 380 { 381 GUID: "some-app-guid-2", 382 Name: "some-app-2", 383 }, 384 }, 385 ccv2.Warnings{"warning-1", "warning-2"}, 386 nil, 387 ) 388 }) 389 390 It("returns the application and warnings", func() { 391 apps, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 392 Expect(err).ToNot(HaveOccurred()) 393 Expect(apps).To(ConsistOf( 394 Application{ 395 GUID: "some-app-guid-1", 396 Name: "some-app-1", 397 }, 398 Application{ 399 GUID: "some-app-guid-2", 400 Name: "some-app-2", 401 }, 402 )) 403 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 404 405 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 406 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf([]ccv2.Filter{ 407 ccv2.Filter{ 408 Type: constant.SpaceGUIDFilter, 409 Operator: constant.EqualOperator, 410 Values: []string{"some-space-guid"}, 411 }, 412 })) 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("some cc error") 421 fakeCloudControllerClient.GetApplicationsReturns( 422 []ccv2.Application{}, 423 ccv2.Warnings{"warning-1", "warning-2"}, 424 expectedError) 425 }) 426 427 It("returns the error and warnings", func() { 428 _, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 429 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 430 Expect(err).To(MatchError(expectedError)) 431 }) 432 }) 433 }) 434 435 Describe("GetRouteApplications", func() { 436 When("the CC client returns no errors", func() { 437 BeforeEach(func() { 438 fakeCloudControllerClient.GetRouteApplicationsReturns( 439 []ccv2.Application{ 440 { 441 GUID: "application-guid", 442 Name: "application-name", 443 }, 444 }, ccv2.Warnings{"route-applications-warning"}, nil) 445 }) 446 It("returns the applications bound to the route and warnings", func() { 447 applications, warnings, err := actor.GetRouteApplications("route-guid") 448 Expect(fakeCloudControllerClient.GetRouteApplicationsCallCount()).To(Equal(1)) 449 Expect(fakeCloudControllerClient.GetRouteApplicationsArgsForCall(0)).To(Equal("route-guid")) 450 451 Expect(err).ToNot(HaveOccurred()) 452 Expect(warnings).To(ConsistOf("route-applications-warning")) 453 Expect(applications).To(ConsistOf( 454 Application{ 455 GUID: "application-guid", 456 Name: "application-name", 457 }, 458 )) 459 }) 460 }) 461 462 When("the CC client returns an error", func() { 463 BeforeEach(func() { 464 fakeCloudControllerClient.GetRouteApplicationsReturns( 465 []ccv2.Application{}, ccv2.Warnings{"route-applications-warning"}, errors.New("get-route-applications-error")) 466 }) 467 468 It("returns the error and warnings", func() { 469 apps, warnings, err := actor.GetRouteApplications("route-guid") 470 Expect(fakeCloudControllerClient.GetRouteApplicationsCallCount()).To(Equal(1)) 471 Expect(fakeCloudControllerClient.GetRouteApplicationsArgsForCall(0)).To(Equal("route-guid")) 472 473 Expect(err).To(MatchError("get-route-applications-error")) 474 Expect(warnings).To(ConsistOf("route-applications-warning")) 475 Expect(apps).To(BeNil()) 476 }) 477 }) 478 }) 479 480 Describe("SetApplicationHealthCheckTypeByNameAndSpace", func() { 481 When("setting an http endpoint with a health check that is not http", func() { 482 It("returns an http health check invalid error", func() { 483 _, _, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 484 "some-app", "some-space-guid", "some-health-check-type", "/foo") 485 Expect(err).To(MatchError(actionerror.HTTPHealthCheckInvalidError{})) 486 }) 487 }) 488 489 When("the app exists", func() { 490 When("the desired health check type is different", func() { 491 BeforeEach(func() { 492 fakeCloudControllerClient.GetApplicationsReturns( 493 []ccv2.Application{ 494 {GUID: "some-app-guid"}, 495 }, 496 ccv2.Warnings{"get application warning"}, 497 nil, 498 ) 499 fakeCloudControllerClient.UpdateApplicationReturns( 500 ccv2.Application{ 501 GUID: "some-app-guid", 502 HealthCheckType: "process", 503 }, 504 ccv2.Warnings{"update warnings"}, 505 nil, 506 ) 507 }) 508 509 It("sets the desired health check type and returns the warnings", func() { 510 returnedApp, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 511 "some-app", "some-space-guid", "process", "/") 512 Expect(err).ToNot(HaveOccurred()) 513 Expect(warnings).To(ConsistOf("get application warning", "update warnings")) 514 515 Expect(returnedApp).To(Equal(Application{ 516 GUID: "some-app-guid", 517 HealthCheckType: "process", 518 })) 519 520 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 521 app := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 522 Expect(app).To(Equal(ccv2.Application{ 523 GUID: "some-app-guid", 524 HealthCheckType: "process", 525 })) 526 }) 527 }) 528 529 When("the desired health check type is 'http'", func() { 530 When("the desired http endpoint is already set", func() { 531 BeforeEach(func() { 532 fakeCloudControllerClient.GetApplicationsReturns( 533 []ccv2.Application{ 534 {GUID: "some-app-guid", HealthCheckType: "http", HealthCheckHTTPEndpoint: "/"}, 535 }, 536 ccv2.Warnings{"get application warning"}, 537 nil, 538 ) 539 }) 540 541 It("does not send the update", func() { 542 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 543 "some-app", "some-space-guid", "http", "/") 544 Expect(err).ToNot(HaveOccurred()) 545 Expect(warnings).To(ConsistOf("get application warning")) 546 547 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(0)) 548 }) 549 }) 550 551 When("the desired http endpoint is not set", func() { 552 BeforeEach(func() { 553 fakeCloudControllerClient.GetApplicationsReturns( 554 []ccv2.Application{ 555 {GUID: "some-app-guid", HealthCheckType: "http", HealthCheckHTTPEndpoint: "/"}, 556 }, 557 ccv2.Warnings{"get application warning"}, 558 nil, 559 ) 560 fakeCloudControllerClient.UpdateApplicationReturns( 561 ccv2.Application{}, 562 ccv2.Warnings{"update warnings"}, 563 nil, 564 ) 565 }) 566 567 It("sets the desired health check type and returns the warnings", func() { 568 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 569 "some-app", "some-space-guid", "http", "/v2/anything") 570 Expect(err).ToNot(HaveOccurred()) 571 572 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 573 app := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 574 Expect(app).To(Equal(ccv2.Application{ 575 GUID: "some-app-guid", 576 HealthCheckType: "http", 577 HealthCheckHTTPEndpoint: "/v2/anything", 578 })) 579 580 Expect(warnings).To(ConsistOf("get application warning", "update warnings")) 581 }) 582 }) 583 }) 584 585 When("the application health check type is already set to the desired type", func() { 586 BeforeEach(func() { 587 fakeCloudControllerClient.GetApplicationsReturns( 588 []ccv2.Application{ 589 { 590 GUID: "some-app-guid", 591 HealthCheckType: "process", 592 }, 593 }, 594 ccv2.Warnings{"get application warning"}, 595 nil, 596 ) 597 }) 598 599 It("does not update the health check type", func() { 600 returnedApp, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 601 "some-app", "some-space-guid", "process", "/") 602 Expect(err).ToNot(HaveOccurred()) 603 Expect(warnings).To(ConsistOf("get application warning")) 604 Expect(returnedApp).To(Equal(Application{ 605 GUID: "some-app-guid", 606 HealthCheckType: "process", 607 })) 608 609 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(0)) 610 }) 611 }) 612 }) 613 614 When("getting the application returns an error", func() { 615 BeforeEach(func() { 616 fakeCloudControllerClient.GetApplicationsReturns( 617 []ccv2.Application{}, ccv2.Warnings{"get application warning"}, errors.New("get application error")) 618 }) 619 620 It("returns the error and warnings", func() { 621 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 622 "some-app", "some-space-guid", "process", "/") 623 624 Expect(warnings).To(ConsistOf("get application warning")) 625 Expect(err).To(MatchError("get application error")) 626 }) 627 }) 628 629 When("updating the application returns an error", func() { 630 var expectedErr error 631 632 BeforeEach(func() { 633 expectedErr = errors.New("foo bar") 634 fakeCloudControllerClient.GetApplicationsReturns( 635 []ccv2.Application{ 636 {GUID: "some-app-guid"}, 637 }, 638 ccv2.Warnings{"get application warning"}, 639 nil, 640 ) 641 fakeCloudControllerClient.UpdateApplicationReturns( 642 ccv2.Application{}, 643 ccv2.Warnings{"update warnings"}, 644 expectedErr, 645 ) 646 }) 647 648 It("returns the error and warnings", func() { 649 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 650 "some-app", "some-space-guid", "process", "/") 651 Expect(err).To(MatchError(expectedErr)) 652 Expect(warnings).To(ConsistOf("get application warning", "update warnings")) 653 }) 654 }) 655 }) 656 657 Describe("StartApplication/RestartApplication", func() { 658 var ( 659 app Application 660 fakeNOAAClient *v2actionfakes.FakeNOAAClient 661 662 messages <-chan *LogMessage 663 logErrs <-chan error 664 appState <-chan ApplicationStateChange 665 warnings <-chan string 666 errs <-chan error 667 668 eventStream chan *events.LogMessage 669 errStream chan error 670 ) 671 672 BeforeEach(func() { 673 fakeConfig.StagingTimeoutReturns(time.Minute) 674 fakeConfig.StartupTimeoutReturns(time.Minute) 675 676 app = Application{ 677 GUID: "some-app-guid", 678 Name: "some-app", 679 Instances: types.NullInt{Value: 2, IsSet: true}, 680 } 681 682 fakeNOAAClient = new(v2actionfakes.FakeNOAAClient) 683 fakeNOAAClient.TailingLogsStub = func(_ string, _ string) (<-chan *events.LogMessage, <-chan error) { 684 eventStream = make(chan *events.LogMessage) 685 errStream = make(chan error) 686 return eventStream, errStream 687 } 688 689 closed := false 690 fakeNOAAClient.CloseStub = func() error { 691 if !closed { 692 closed = true 693 close(errStream) 694 close(eventStream) 695 } 696 return nil 697 } 698 699 appCount := 0 700 fakeCloudControllerClient.GetApplicationStub = func(appGUID string) (ccv2.Application, ccv2.Warnings, error) { 701 if appCount == 0 { 702 appCount++ 703 return ccv2.Application{ 704 GUID: "some-app-guid", 705 Instances: types.NullInt{Value: 2, IsSet: true}, 706 Name: "some-app", 707 PackageState: constant.ApplicationPackagePending, 708 }, ccv2.Warnings{"app-warnings-1"}, nil 709 } 710 711 return ccv2.Application{ 712 GUID: "some-app-guid", 713 Name: "some-app", 714 Instances: types.NullInt{Value: 2, IsSet: true}, 715 PackageState: constant.ApplicationPackageStaged, 716 }, ccv2.Warnings{"app-warnings-2"}, nil 717 } 718 719 instanceCount := 0 720 fakeCloudControllerClient.GetApplicationApplicationInstancesStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 721 if instanceCount == 0 { 722 instanceCount++ 723 return map[int]ccv2.ApplicationInstance{ 724 0: {State: constant.ApplicationInstanceStarting}, 725 1: {State: constant.ApplicationInstanceStarting}, 726 }, ccv2.Warnings{"app-instance-warnings-1"}, nil 727 } 728 729 return map[int]ccv2.ApplicationInstance{ 730 0: {State: constant.ApplicationInstanceStarting}, 731 1: {State: constant.ApplicationInstanceRunning}, 732 }, ccv2.Warnings{"app-instance-warnings-2"}, nil 733 } 734 }) 735 736 AfterEach(func() { 737 Eventually(messages).Should(BeClosed()) 738 Eventually(logErrs).Should(BeClosed()) 739 Eventually(appState).Should(BeClosed()) 740 Eventually(warnings).Should(BeClosed()) 741 Eventually(errs).Should(BeClosed()) 742 }) 743 744 var ItHandlesStagingIssues = func() { 745 Context("staging issues", func() { 746 When("polling fails", func() { 747 var expectedErr error 748 BeforeEach(func() { 749 expectedErr = errors.New("I am a banana!!!!") 750 fakeCloudControllerClient.GetApplicationStub = func(appGUID string) (ccv2.Application, ccv2.Warnings, error) { 751 return ccv2.Application{}, ccv2.Warnings{"app-warnings-1"}, expectedErr 752 } 753 }) 754 755 It("sends the error and stops polling", func() { 756 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 757 Eventually(warnings).Should(Receive(Equal("state-warning"))) 758 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 759 Eventually(errs).Should(Receive(MatchError(expectedErr))) 760 761 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 762 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(1)) 763 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 764 }) 765 }) 766 767 When("the application fails to stage", func() { 768 Context("due to a NoAppDetectedError", func() { 769 BeforeEach(func() { 770 fakeCloudControllerClient.GetApplicationStub = func(appGUID string) (ccv2.Application, ccv2.Warnings, error) { 771 return ccv2.Application{ 772 GUID: "some-app-guid", 773 Name: "some-app", 774 Instances: types.NullInt{Value: 2, IsSet: true}, 775 PackageState: constant.ApplicationPackageFailed, 776 StagingFailedReason: "NoAppDetectedError", 777 }, ccv2.Warnings{"app-warnings-1"}, nil 778 } 779 }) 780 781 It("sends a StagingFailedNoAppDetectedError and stops polling", func() { 782 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 783 Eventually(warnings).Should(Receive(Equal("state-warning"))) 784 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 785 Eventually(errs).Should(Receive(MatchError(actionerror.StagingFailedNoAppDetectedError{Reason: "NoAppDetectedError"}))) 786 787 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 788 Expect(fakeConfig.StagingTimeoutCallCount()).To(Equal(1)) 789 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(1)) 790 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 791 }) 792 }) 793 794 Context("due to any other error", func() { 795 BeforeEach(func() { 796 fakeCloudControllerClient.GetApplicationStub = func(appGUID string) (ccv2.Application, ccv2.Warnings, error) { 797 return ccv2.Application{ 798 GUID: "some-app-guid", 799 Name: "some-app", 800 Instances: types.NullInt{Value: 2, IsSet: true}, 801 PackageState: constant.ApplicationPackageFailed, 802 StagingFailedReason: "OhNoes", 803 }, ccv2.Warnings{"app-warnings-1"}, nil 804 } 805 }) 806 807 It("sends a StagingFailedError and stops polling", func() { 808 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 809 Eventually(warnings).Should(Receive(Equal("state-warning"))) 810 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 811 Eventually(errs).Should(Receive(MatchError(actionerror.StagingFailedError{Reason: "OhNoes"}))) 812 813 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 814 Expect(fakeConfig.StagingTimeoutCallCount()).To(Equal(1)) 815 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(1)) 816 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 817 }) 818 }) 819 }) 820 821 When("the application takes too long to stage", func() { 822 BeforeEach(func() { 823 fakeConfig.StagingTimeoutReturns(0) 824 fakeCloudControllerClient.GetApplicationApplicationInstancesStub = nil 825 }) 826 827 It("sends a timeout error and stops polling", func() { 828 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 829 Eventually(warnings).Should(Receive(Equal("state-warning"))) 830 Eventually(errs).Should(Receive(MatchError(actionerror.StagingTimeoutError{AppName: "some-app", Timeout: 0}))) 831 832 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 833 Expect(fakeConfig.StagingTimeoutCallCount()).To(Equal(2)) 834 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(0)) 835 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 836 }) 837 }) 838 }) 839 } 840 841 var ItHandlesStartingIssues = func() { 842 Context("starting issues", func() { 843 When("polling fails", func() { 844 var expectedErr error 845 BeforeEach(func() { 846 expectedErr = errors.New("I am a banana!!!!") 847 fakeCloudControllerClient.GetApplicationApplicationInstancesStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 848 return nil, ccv2.Warnings{"app-instance-warnings-1"}, expectedErr 849 } 850 }) 851 852 It("sends the error and stops polling", func() { 853 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 854 Eventually(warnings).Should(Receive(Equal("state-warning"))) 855 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 856 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 857 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 858 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 859 Eventually(errs).Should(Receive(MatchError(expectedErr))) 860 861 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 862 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(1)) 863 }) 864 }) 865 866 When("the application takes too long to start", func() { 867 BeforeEach(func() { 868 fakeConfig.StartupTimeoutReturns(0) 869 }) 870 871 It("sends a timeout error and stops polling", func() { 872 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 873 Eventually(warnings).Should(Receive(Equal("state-warning"))) 874 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 875 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 876 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 877 Eventually(errs).Should(Receive(MatchError(actionerror.StartupTimeoutError{Name: "some-app"}))) 878 879 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 880 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 881 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 882 }) 883 }) 884 885 When("the application crashes", func() { 886 BeforeEach(func() { 887 fakeCloudControllerClient.GetApplicationApplicationInstancesStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 888 return map[int]ccv2.ApplicationInstance{ 889 0: {State: constant.ApplicationInstanceCrashed}, 890 }, ccv2.Warnings{"app-instance-warnings-1"}, nil 891 } 892 }) 893 894 It("returns an ApplicationInstanceCrashedError and stops polling", func() { 895 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 896 Eventually(warnings).Should(Receive(Equal("state-warning"))) 897 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 898 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 899 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 900 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 901 Eventually(errs).Should(Receive(MatchError(actionerror.ApplicationInstanceCrashedError{Name: "some-app"}))) 902 903 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 904 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 905 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(1)) 906 }) 907 }) 908 909 When("the application flaps", func() { 910 BeforeEach(func() { 911 fakeCloudControllerClient.GetApplicationApplicationInstancesStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 912 return map[int]ccv2.ApplicationInstance{ 913 0: {State: constant.ApplicationInstanceFlapping}, 914 }, ccv2.Warnings{"app-instance-warnings-1"}, nil 915 } 916 }) 917 918 It("returns an ApplicationInstanceFlappingError and stops polling", func() { 919 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 920 Eventually(warnings).Should(Receive(Equal("state-warning"))) 921 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 922 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 923 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 924 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 925 Eventually(errs).Should(Receive(MatchError(actionerror.ApplicationInstanceFlappingError{Name: "some-app"}))) 926 927 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 928 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 929 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(1)) 930 }) 931 }) 932 }) 933 } 934 935 var ItStartsApplication = func() { 936 When("the app is not running", func() { 937 It("starts and polls for an app instance", func() { 938 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 939 Eventually(warnings).Should(Receive(Equal("state-warning"))) 940 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 941 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 942 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 943 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 944 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-2"))) 945 946 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(2)) 947 948 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 949 passedApp := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 950 Expect(passedApp).To(Equal(ccv2.Application{ 951 GUID: "some-app-guid", 952 State: constant.ApplicationStarted, 953 })) 954 955 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 956 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(2)) 957 Eventually(fakeNOAAClient.CloseCallCount).Should(Equal(2)) 958 }) 959 }) 960 961 When("the app has zero instances", func() { 962 BeforeEach(func() { 963 fakeCloudControllerClient.UpdateApplicationReturns(ccv2.Application{GUID: "some-app-guid", 964 Instances: types.NullInt{Value: 0, IsSet: true}, 965 Name: "some-app", 966 }, ccv2.Warnings{"state-warning"}, nil) 967 }) 968 969 It("starts and only polls for staging to finish", func() { 970 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 971 Eventually(warnings).Should(Receive(Equal("state-warning"))) 972 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 973 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 974 Consistently(appState).ShouldNot(Receive(Equal(ApplicationStateStarting))) 975 976 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 977 978 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 979 passedApp := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 980 Expect(passedApp).To(Equal(ccv2.Application{ 981 GUID: "some-app-guid", 982 State: constant.ApplicationStarted, 983 })) 984 985 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 986 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 987 }) 988 }) 989 990 When("updating the application fails", func() { 991 var expectedErr error 992 BeforeEach(func() { 993 expectedErr = errors.New("I am a banana!!!!") 994 fakeCloudControllerClient.UpdateApplicationReturns(ccv2.Application{}, ccv2.Warnings{"state-warning"}, expectedErr) 995 }) 996 997 It("sends the update error and never polls", func() { 998 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 999 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1000 Eventually(errs).Should(Receive(MatchError(expectedErr))) 1001 1002 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 1003 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(0)) 1004 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 1005 }) 1006 }) 1007 1008 ItHandlesStagingIssues() 1009 1010 ItHandlesStartingIssues() 1011 } 1012 1013 Describe("StartApplication", func() { 1014 BeforeEach(func() { 1015 fakeCloudControllerClient.UpdateApplicationReturns(ccv2.Application{GUID: "some-app-guid", 1016 Instances: types.NullInt{Value: 2, IsSet: true}, 1017 Name: "some-app", 1018 }, ccv2.Warnings{"state-warning"}, nil) 1019 }) 1020 1021 JustBeforeEach(func() { 1022 messages, logErrs, appState, warnings, errs = actor.StartApplication(app, fakeNOAAClient) 1023 }) 1024 1025 When("the app is already staged", func() { 1026 BeforeEach(func() { 1027 app.PackageState = constant.ApplicationPackageStaged 1028 }) 1029 1030 It("does not send ApplicationStateStaging", func() { 1031 Consistently(appState).ShouldNot(Receive(Equal(ApplicationStateStaging))) 1032 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1033 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 1034 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 1035 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 1036 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 1037 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-2"))) 1038 1039 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 1040 passedApp := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 1041 Expect(passedApp).To(Equal(ccv2.Application{ 1042 GUID: "some-app-guid", 1043 State: constant.ApplicationStarted, 1044 })) 1045 }) 1046 }) 1047 1048 ItStartsApplication() 1049 }) 1050 1051 Describe("RestartApplication", func() { 1052 BeforeEach(func() { 1053 fakeCloudControllerClient.UpdateApplicationReturns(ccv2.Application{GUID: "some-app-guid", 1054 Instances: types.NullInt{Value: 2, IsSet: true}, 1055 Name: "some-app", 1056 }, ccv2.Warnings{"state-warning"}, nil) 1057 }) 1058 1059 JustBeforeEach(func() { 1060 messages, logErrs, appState, warnings, errs = actor.RestartApplication(app, fakeNOAAClient) 1061 }) 1062 1063 When("application is running", func() { 1064 BeforeEach(func() { 1065 app.State = constant.ApplicationStarted 1066 }) 1067 1068 It("stops, starts and polls for an app instance", func() { 1069 Eventually(appState).Should(Receive(Equal(ApplicationStateStopping))) 1070 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1071 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 1072 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1073 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 1074 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 1075 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 1076 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 1077 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-2"))) 1078 1079 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(2)) 1080 1081 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(2)) 1082 passedApp := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 1083 Expect(passedApp).To(Equal(ccv2.Application{ 1084 GUID: "some-app-guid", 1085 State: constant.ApplicationStopped, 1086 })) 1087 1088 passedApp = fakeCloudControllerClient.UpdateApplicationArgsForCall(1) 1089 Expect(passedApp).To(Equal(ccv2.Application{ 1090 GUID: "some-app-guid", 1091 State: constant.ApplicationStarted, 1092 })) 1093 1094 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 1095 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(2)) 1096 Eventually(fakeNOAAClient.CloseCallCount).Should(Equal(2)) 1097 }) 1098 1099 When("updating the application to stop fails", func() { 1100 var expectedErr error 1101 BeforeEach(func() { 1102 expectedErr = errors.New("I am a banana!!!!") 1103 updateApplicationCalled := false 1104 fakeCloudControllerClient.UpdateApplicationStub = func(app ccv2.Application) (ccv2.Application, ccv2.Warnings, error) { 1105 if !updateApplicationCalled { 1106 return ccv2.Application{}, ccv2.Warnings{"state-warning"}, expectedErr 1107 } 1108 1109 updateApplicationCalled = true 1110 return ccv2.Application{GUID: "some-app-guid", 1111 Instances: types.NullInt{Value: 2, IsSet: true}, 1112 Name: "some-app", 1113 }, ccv2.Warnings{"state-warning"}, nil 1114 } 1115 }) 1116 1117 It("sends the update error and never polls", func() { 1118 Eventually(appState).Should(Receive(Equal(ApplicationStateStopping))) 1119 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1120 Eventually(errs).Should(Receive(MatchError(expectedErr))) 1121 Eventually(appState).ShouldNot(Receive(Equal(ApplicationStateStaging))) 1122 1123 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 1124 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(0)) 1125 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 1126 }) 1127 }) 1128 }) 1129 1130 When("the app is not running", func() { 1131 BeforeEach(func() { 1132 app.State = constant.ApplicationStopped 1133 }) 1134 1135 It("does not stop an app instance", func() { 1136 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 1137 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1138 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 1139 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 1140 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 1141 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 1142 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-2"))) 1143 1144 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 1145 passedApp := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 1146 Expect(passedApp).To(Equal(ccv2.Application{ 1147 GUID: "some-app-guid", 1148 State: constant.ApplicationStarted, 1149 })) 1150 }) 1151 }) 1152 1153 When("the app is already staged", func() { 1154 BeforeEach(func() { 1155 app.PackageState = constant.ApplicationPackageStaged 1156 }) 1157 1158 It("does not send ApplicationStateStaging", func() { 1159 Consistently(appState).ShouldNot(Receive(Equal(ApplicationStateStaging))) 1160 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1161 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 1162 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 1163 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 1164 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 1165 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-2"))) 1166 1167 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 1168 passedApp := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 1169 Expect(passedApp).To(Equal(ccv2.Application{ 1170 GUID: "some-app-guid", 1171 State: constant.ApplicationStarted, 1172 })) 1173 }) 1174 }) 1175 1176 ItStartsApplication() 1177 }) 1178 1179 Describe("RestageApplication", func() { 1180 JustBeforeEach(func() { 1181 messages, logErrs, appState, warnings, errs = actor.RestageApplication(app, fakeNOAAClient) 1182 }) 1183 1184 When("restaging succeeds", func() { 1185 BeforeEach(func() { 1186 fakeCloudControllerClient.RestageApplicationReturns(ccv2.Application{GUID: "some-app-guid", 1187 Instances: types.NullInt{Value: 2, IsSet: true}, 1188 Name: "some-app", 1189 }, ccv2.Warnings{"state-warning"}, nil) 1190 }) 1191 1192 It("restages and polls for app instances", func() { 1193 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 1194 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1195 Eventually(warnings).Should(Receive(Equal("app-warnings-1"))) 1196 Eventually(warnings).Should(Receive(Equal("app-warnings-2"))) 1197 Eventually(appState).Should(Receive(Equal(ApplicationStateStarting))) 1198 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-1"))) 1199 Eventually(warnings).Should(Receive(Equal("app-instance-warnings-2"))) 1200 1201 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(2)) 1202 1203 Expect(fakeCloudControllerClient.RestageApplicationCallCount()).To(Equal(1)) 1204 app := fakeCloudControllerClient.RestageApplicationArgsForCall(0) 1205 Expect(app).To(Equal(ccv2.Application{ 1206 GUID: "some-app-guid", 1207 })) 1208 1209 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 1210 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(2)) 1211 Eventually(fakeNOAAClient.CloseCallCount).Should(Equal(2)) 1212 }) 1213 1214 ItHandlesStagingIssues() 1215 1216 ItHandlesStartingIssues() 1217 }) 1218 1219 When("restaging errors", func() { 1220 BeforeEach(func() { 1221 fakeCloudControllerClient.RestageApplicationReturns(ccv2.Application{GUID: "some-app-guid", 1222 Instances: types.NullInt{Value: 2, IsSet: true}, 1223 Name: "some-app", 1224 }, ccv2.Warnings{"state-warning"}, errors.New("some-error")) 1225 }) 1226 1227 It("sends the restage error and never polls", func() { 1228 Eventually(appState).Should(Receive(Equal(ApplicationStateStaging))) 1229 Eventually(warnings).Should(Receive(Equal("state-warning"))) 1230 Eventually(errs).Should(Receive(MatchError("some-error"))) 1231 1232 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(0)) 1233 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(0)) 1234 Expect(fakeCloudControllerClient.GetApplicationApplicationInstancesCallCount()).To(Equal(0)) 1235 }) 1236 }) 1237 }) 1238 }) 1239 1240 Describe("UpdateApplication", func() { 1241 When("the update is successful", func() { 1242 var expectedApp ccv2.Application 1243 BeforeEach(func() { 1244 expectedApp = ccv2.Application{ 1245 GUID: "some-app-guid", 1246 Name: "some-app-name", 1247 SpaceGUID: "some-space-guid", 1248 } 1249 fakeCloudControllerClient.UpdateApplicationReturns(expectedApp, ccv2.Warnings{"some-app-warning-1"}, nil) 1250 }) 1251 1252 It("updates and returns the application", func() { 1253 newApp := Application{ 1254 Name: "some-app-name", 1255 SpaceGUID: "some-space-guid", 1256 } 1257 app, warnings, err := actor.UpdateApplication(newApp) 1258 Expect(err).ToNot(HaveOccurred()) 1259 Expect(warnings).To(ConsistOf("some-app-warning-1")) 1260 Expect(app).To(Equal(Application(expectedApp))) 1261 1262 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 1263 Expect(fakeCloudControllerClient.UpdateApplicationArgsForCall(0)).To(Equal(ccv2.Application(newApp))) 1264 }) 1265 }) 1266 1267 When("the client returns back an error", func() { 1268 var expectedErr error 1269 BeforeEach(func() { 1270 expectedErr = errors.New("some update app error") 1271 fakeCloudControllerClient.UpdateApplicationReturns(ccv2.Application{}, ccv2.Warnings{"some-app-warning-1"}, expectedErr) 1272 }) 1273 1274 It("returns warnings and an error", func() { 1275 newApp := Application{ 1276 Name: "some-app-name", 1277 SpaceGUID: "some-space-guid", 1278 } 1279 _, warnings, err := actor.UpdateApplication(newApp) 1280 Expect(warnings).To(ConsistOf("some-app-warning-1")) 1281 Expect(err).To(MatchError(expectedErr)) 1282 }) 1283 }) 1284 }) 1285 })