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