github.com/cloudfoundry-attic/cli-with-i18n@v6.32.1-0.20171002233121-7401370d3b85+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/types" 13 14 "github.com/cloudfoundry/sonde-go/events" 15 . "github.com/onsi/ginkgo" 16 . "github.com/onsi/gomega" 17 ) 18 19 var _ = Describe("Application Actions", func() { 20 var ( 21 actor *Actor 22 fakeCloudControllerClient *v2actionfakes.FakeCloudControllerClient 23 ) 24 25 BeforeEach(func() { 26 fakeCloudControllerClient = new(v2actionfakes.FakeCloudControllerClient) 27 actor = NewActor(fakeCloudControllerClient, nil, nil) 28 }) 29 30 Describe("Application", func() { 31 var app Application 32 BeforeEach(func() { 33 app = Application{} 34 }) 35 36 Describe("CalculatedCommand", func() { 37 Context("when command is set", func() { 38 BeforeEach(func() { 39 app.Command = types.FilteredString{IsSet: true, Value: "foo"} 40 app.DetectedStartCommand = types.FilteredString{IsSet: true, Value: "bar"} 41 }) 42 43 It("returns back the command", func() { 44 Expect(app.CalculatedCommand()).To(Equal("foo")) 45 }) 46 }) 47 48 Context("only detected start command is set", func() { 49 BeforeEach(func() { 50 app.DetectedStartCommand = types.FilteredString{IsSet: true, Value: "bar"} 51 }) 52 53 It("returns back the detected start command", func() { 54 Expect(app.CalculatedCommand()).To(Equal("bar")) 55 }) 56 }) 57 58 Context("neither command nor detected start command are set", func() { 59 It("returns an empty string", func() { 60 Expect(app.CalculatedCommand()).To(BeEmpty()) 61 }) 62 }) 63 }) 64 65 Describe("CalculatedBuildpack", func() { 66 Context("when buildpack is set", func() { 67 BeforeEach(func() { 68 app.Buildpack = types.FilteredString{IsSet: true, Value: "foo"} 69 app.DetectedBuildpack = types.FilteredString{IsSet: true, Value: "bar"} 70 }) 71 72 It("returns back the buildpack", func() { 73 Expect(app.CalculatedBuildpack()).To(Equal("foo")) 74 }) 75 }) 76 77 Context("only detected buildpack is set", func() { 78 BeforeEach(func() { 79 app.DetectedBuildpack = types.FilteredString{IsSet: true, Value: "bar"} 80 }) 81 82 It("returns back the detected buildpack", func() { 83 Expect(app.CalculatedBuildpack()).To(Equal("bar")) 84 }) 85 }) 86 87 Context("neither buildpack nor detected buildpack are set", func() { 88 It("returns an empty string", func() { 89 Expect(app.CalculatedBuildpack()).To(BeEmpty()) 90 }) 91 }) 92 }) 93 94 Describe("CalculatedHealthCheckEndpoint", func() { 95 Context("when the health check type is http", func() { 96 BeforeEach(func() { 97 app.HealthCheckType = "http" 98 app.HealthCheckHTTPEndpoint = "/some-endpoint" 99 }) 100 101 It("returns the endpoint field", func() { 102 Expect(app.CalculatedHealthCheckEndpoint()).To(Equal( 103 "/some-endpoint")) 104 }) 105 }) 106 107 Context("when the health check type is not http", func() { 108 BeforeEach(func() { 109 app.HealthCheckType = "process" 110 app.HealthCheckHTTPEndpoint = "/some-endpoint" 111 }) 112 113 It("returns the empty string", func() { 114 Expect(app.CalculatedHealthCheckEndpoint()).To(Equal("")) 115 }) 116 }) 117 }) 118 119 Describe("StagingCompleted", func() { 120 Context("when staging the application completes", func() { 121 It("returns true", func() { 122 app.PackageState = ccv2.ApplicationPackageStaged 123 Expect(app.StagingCompleted()).To(BeTrue()) 124 }) 125 }) 126 127 Context("when the application is *not* staged", func() { 128 It("returns false", func() { 129 app.PackageState = ccv2.ApplicationPackageFailed 130 Expect(app.StagingCompleted()).To(BeFalse()) 131 }) 132 }) 133 }) 134 135 Describe("StagingFailed", func() { 136 Context("when staging the application fails", func() { 137 It("returns true", func() { 138 app.PackageState = ccv2.ApplicationPackageFailed 139 Expect(app.StagingFailed()).To(BeTrue()) 140 }) 141 }) 142 143 Context("when staging the application does *not* fail", func() { 144 It("returns false", func() { 145 app.PackageState = ccv2.ApplicationPackageStaged 146 Expect(app.StagingFailed()).To(BeFalse()) 147 }) 148 }) 149 }) 150 151 Describe("StagingFailedMessage", func() { 152 Context("when the application has a staging failed description", func() { 153 BeforeEach(func() { 154 app.StagingFailedDescription = "An app was not successfully detected by any available buildpack" 155 app.StagingFailedReason = "NoAppDetectedError" 156 }) 157 It("returns that description", func() { 158 Expect(app.StagingFailedMessage()).To(Equal("An app was not successfully detected by any available buildpack")) 159 }) 160 }) 161 162 Context("when the application does not have a staging failed description", func() { 163 BeforeEach(func() { 164 app.StagingFailedDescription = "" 165 app.StagingFailedReason = "NoAppDetectedError" 166 }) 167 It("returns the staging failed code", func() { 168 Expect(app.StagingFailedMessage()).To(Equal("NoAppDetectedError")) 169 }) 170 }) 171 }) 172 173 Describe("StagingFailedNoAppDetected", func() { 174 Context("when staging the application fails due to a no app detected error", func() { 175 It("returns true", func() { 176 app.StagingFailedReason = "NoAppDetectedError" 177 Expect(app.StagingFailedNoAppDetected()).To(BeTrue()) 178 }) 179 }) 180 181 Context("when staging the application fails due to any other reason", func() { 182 It("returns false", func() { 183 app.StagingFailedReason = "InsufficientResources" 184 Expect(app.StagingFailedNoAppDetected()).To(BeFalse()) 185 }) 186 }) 187 }) 188 189 Describe("Started", func() { 190 Context("when app is started", func() { 191 It("returns true", func() { 192 Expect(Application{State: ccv2.ApplicationStarted}.Started()).To(BeTrue()) 193 }) 194 }) 195 196 Context("when app is stopped", func() { 197 It("returns false", func() { 198 Expect(Application{State: ccv2.ApplicationStopped}.Started()).To(BeFalse()) 199 }) 200 }) 201 }) 202 203 Describe("Stopped", func() { 204 Context("when app is started", func() { 205 It("returns true", func() { 206 Expect(Application{State: ccv2.ApplicationStopped}.Stopped()).To(BeTrue()) 207 }) 208 }) 209 210 Context("when app is stopped", func() { 211 It("returns false", func() { 212 Expect(Application{State: ccv2.ApplicationStarted}.Stopped()).To(BeFalse()) 213 }) 214 }) 215 }) 216 }) 217 218 Describe("CreateApplication", func() { 219 Context("when the create is successful", func() { 220 var expectedApp ccv2.Application 221 BeforeEach(func() { 222 expectedApp = ccv2.Application{ 223 GUID: "some-app-guid", 224 Name: "some-app-name", 225 SpaceGUID: "some-space-guid", 226 } 227 fakeCloudControllerClient.CreateApplicationReturns(expectedApp, ccv2.Warnings{"some-app-warning-1"}, nil) 228 }) 229 230 It("creates and returns the application", func() { 231 newApp := Application{ 232 Name: "some-app-name", 233 SpaceGUID: "some-space-guid", 234 } 235 app, warnings, err := actor.CreateApplication(newApp) 236 Expect(err).ToNot(HaveOccurred()) 237 Expect(warnings).To(ConsistOf("some-app-warning-1")) 238 Expect(app).To(Equal(Application(expectedApp))) 239 240 Expect(fakeCloudControllerClient.CreateApplicationCallCount()).To(Equal(1)) 241 Expect(fakeCloudControllerClient.CreateApplicationArgsForCall(0)).To(Equal(ccv2.Application(newApp))) 242 }) 243 }) 244 245 Context("when the client returns back an error", func() { 246 var expectedErr error 247 BeforeEach(func() { 248 expectedErr = errors.New("some create app error") 249 fakeCloudControllerClient.CreateApplicationReturns(ccv2.Application{}, ccv2.Warnings{"some-app-warning-1"}, expectedErr) 250 }) 251 252 It("returns warnings and an error", func() { 253 newApp := Application{ 254 Name: "some-app-name", 255 SpaceGUID: "some-space-guid", 256 } 257 _, warnings, err := actor.CreateApplication(newApp) 258 Expect(warnings).To(ConsistOf("some-app-warning-1")) 259 Expect(err).To(MatchError(expectedErr)) 260 }) 261 }) 262 }) 263 264 Describe("GetApplication", func() { 265 Context("when the application exists", func() { 266 BeforeEach(func() { 267 fakeCloudControllerClient.GetApplicationReturns( 268 ccv2.Application{ 269 GUID: "some-app-guid", 270 Name: "some-app", 271 }, 272 ccv2.Warnings{"foo"}, 273 nil, 274 ) 275 }) 276 277 It("returns the application and warnings", func() { 278 app, warnings, err := actor.GetApplication("some-app-guid") 279 Expect(err).ToNot(HaveOccurred()) 280 Expect(app).To(Equal(Application{ 281 GUID: "some-app-guid", 282 Name: "some-app", 283 })) 284 Expect(warnings).To(Equal(Warnings{"foo"})) 285 286 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(1)) 287 Expect(fakeCloudControllerClient.GetApplicationArgsForCall(0)).To(Equal("some-app-guid")) 288 }) 289 }) 290 291 Context("when the application does not exist", func() { 292 BeforeEach(func() { 293 fakeCloudControllerClient.GetApplicationReturns(ccv2.Application{}, nil, ccerror.ResourceNotFoundError{}) 294 }) 295 296 It("returns an ApplicationNotFoundError", func() { 297 _, _, err := actor.GetApplication("some-app-guid") 298 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{GUID: "some-app-guid"})) 299 }) 300 }) 301 }) 302 303 Describe("GetApplicationByNameAndSpace", func() { 304 Context("when the application exists", func() { 305 BeforeEach(func() { 306 fakeCloudControllerClient.GetApplicationsReturns( 307 []ccv2.Application{ 308 { 309 GUID: "some-app-guid", 310 Name: "some-app", 311 }, 312 }, 313 ccv2.Warnings{"foo"}, 314 nil, 315 ) 316 }) 317 318 It("returns the application and warnings", func() { 319 app, warnings, err := actor.GetApplicationByNameAndSpace("some-app", "some-space-guid") 320 Expect(err).ToNot(HaveOccurred()) 321 Expect(app).To(Equal(Application{ 322 GUID: "some-app-guid", 323 Name: "some-app", 324 })) 325 Expect(warnings).To(Equal(Warnings{"foo"})) 326 327 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 328 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf([]ccv2.Query{ 329 ccv2.Query{ 330 Filter: ccv2.NameFilter, 331 Operator: ccv2.EqualOperator, 332 Values: []string{"some-app"}, 333 }, 334 ccv2.Query{ 335 Filter: ccv2.SpaceGUIDFilter, 336 Operator: ccv2.EqualOperator, 337 Values: []string{"some-space-guid"}, 338 }, 339 })) 340 }) 341 }) 342 343 Context("when the application does not exists", func() { 344 BeforeEach(func() { 345 fakeCloudControllerClient.GetApplicationsReturns([]ccv2.Application{}, nil, nil) 346 }) 347 348 It("returns an ApplicationNotFoundError", func() { 349 _, _, err := actor.GetApplicationByNameAndSpace("some-app", "some-space-guid") 350 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app"})) 351 }) 352 }) 353 354 Context("when the cloud controller client returns an error", func() { 355 var expectedError error 356 357 BeforeEach(func() { 358 expectedError = errors.New("I am a CloudControllerClient Error") 359 fakeCloudControllerClient.GetApplicationsReturns([]ccv2.Application{}, nil, expectedError) 360 }) 361 362 It("returns the error", func() { 363 _, _, err := actor.GetApplicationByNameAndSpace("some-app", "some-space-guid") 364 Expect(err).To(MatchError(expectedError)) 365 }) 366 }) 367 }) 368 369 Describe("GetApplicationsBySpace", func() { 370 Context("when the there are applications in the space", func() { 371 BeforeEach(func() { 372 fakeCloudControllerClient.GetApplicationsReturns( 373 []ccv2.Application{ 374 { 375 GUID: "some-app-guid-1", 376 Name: "some-app-1", 377 }, 378 { 379 GUID: "some-app-guid-2", 380 Name: "some-app-2", 381 }, 382 }, 383 ccv2.Warnings{"warning-1", "warning-2"}, 384 nil, 385 ) 386 }) 387 388 It("returns the application and warnings", func() { 389 apps, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 390 Expect(err).ToNot(HaveOccurred()) 391 Expect(apps).To(ConsistOf( 392 Application{ 393 GUID: "some-app-guid-1", 394 Name: "some-app-1", 395 }, 396 Application{ 397 GUID: "some-app-guid-2", 398 Name: "some-app-2", 399 }, 400 )) 401 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 402 403 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 404 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf([]ccv2.Query{ 405 ccv2.Query{ 406 Filter: ccv2.SpaceGUIDFilter, 407 Operator: ccv2.EqualOperator, 408 Values: []string{"some-space-guid"}, 409 }, 410 })) 411 }) 412 }) 413 414 Context("when the cloud controller client returns an error", func() { 415 var expectedError error 416 417 BeforeEach(func() { 418 expectedError = errors.New("some cc error") 419 fakeCloudControllerClient.GetApplicationsReturns( 420 []ccv2.Application{}, 421 ccv2.Warnings{"warning-1", "warning-2"}, 422 expectedError) 423 }) 424 425 It("returns the error and warnings", func() { 426 _, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 427 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 428 Expect(err).To(MatchError(expectedError)) 429 }) 430 }) 431 }) 432 433 Describe("GetRouteApplications", func() { 434 Context("when the CC client returns no errors", func() { 435 BeforeEach(func() { 436 fakeCloudControllerClient.GetRouteApplicationsReturns( 437 []ccv2.Application{ 438 { 439 GUID: "application-guid", 440 Name: "application-name", 441 }, 442 }, ccv2.Warnings{"route-applications-warning"}, nil) 443 }) 444 It("returns the applications bound to the route and warnings", func() { 445 applications, warnings, err := actor.GetRouteApplications("route-guid") 446 Expect(fakeCloudControllerClient.GetRouteApplicationsCallCount()).To(Equal(1)) 447 Expect(fakeCloudControllerClient.GetRouteApplicationsArgsForCall(0)).To(Equal("route-guid")) 448 449 Expect(err).ToNot(HaveOccurred()) 450 Expect(warnings).To(ConsistOf("route-applications-warning")) 451 Expect(applications).To(ConsistOf( 452 Application{ 453 GUID: "application-guid", 454 Name: "application-name", 455 }, 456 )) 457 }) 458 }) 459 460 Context("when the CC client returns an error", func() { 461 BeforeEach(func() { 462 fakeCloudControllerClient.GetRouteApplicationsReturns( 463 []ccv2.Application{}, ccv2.Warnings{"route-applications-warning"}, errors.New("get-route-applications-error")) 464 }) 465 466 It("returns the error and warnings", func() { 467 apps, warnings, err := actor.GetRouteApplications("route-guid") 468 Expect(fakeCloudControllerClient.GetRouteApplicationsCallCount()).To(Equal(1)) 469 Expect(fakeCloudControllerClient.GetRouteApplicationsArgsForCall(0)).To(Equal("route-guid")) 470 471 Expect(err).To(MatchError("get-route-applications-error")) 472 Expect(warnings).To(ConsistOf("route-applications-warning")) 473 Expect(apps).To(BeNil()) 474 }) 475 }) 476 }) 477 478 Describe("SetApplicationHealthCheckTypeByNameAndSpace", func() { 479 Context("when setting an http endpoint with a health check that is not http", func() { 480 It("returns an http health check invalid error", func() { 481 _, _, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 482 "some-app", "some-space-guid", "some-health-check-type", "/foo") 483 Expect(err).To(MatchError(actionerror.HTTPHealthCheckInvalidError{})) 484 }) 485 }) 486 487 Context("when the app exists", func() { 488 Context("when the desired health check type is different", func() { 489 BeforeEach(func() { 490 fakeCloudControllerClient.GetApplicationsReturns( 491 []ccv2.Application{ 492 {GUID: "some-app-guid"}, 493 }, 494 ccv2.Warnings{"get application warning"}, 495 nil, 496 ) 497 fakeCloudControllerClient.UpdateApplicationReturns( 498 ccv2.Application{ 499 GUID: "some-app-guid", 500 HealthCheckType: "process", 501 }, 502 ccv2.Warnings{"update warnings"}, 503 nil, 504 ) 505 }) 506 507 It("sets the desired health check type and returns the warnings", func() { 508 returnedApp, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 509 "some-app", "some-space-guid", "process", "/") 510 Expect(err).ToNot(HaveOccurred()) 511 Expect(warnings).To(ConsistOf("get application warning", "update warnings")) 512 513 Expect(returnedApp).To(Equal(Application{ 514 GUID: "some-app-guid", 515 HealthCheckType: "process", 516 })) 517 518 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 519 app := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 520 Expect(app).To(Equal(ccv2.Application{ 521 GUID: "some-app-guid", 522 HealthCheckType: "process", 523 })) 524 }) 525 }) 526 527 Context("when the desired health check type is 'http'", func() { 528 Context("when the desired http endpoint is already set", func() { 529 BeforeEach(func() { 530 fakeCloudControllerClient.GetApplicationsReturns( 531 []ccv2.Application{ 532 {GUID: "some-app-guid", HealthCheckType: "http", HealthCheckHTTPEndpoint: "/"}, 533 }, 534 ccv2.Warnings{"get application warning"}, 535 nil, 536 ) 537 }) 538 539 It("does not send the update", func() { 540 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 541 "some-app", "some-space-guid", "http", "/") 542 Expect(err).ToNot(HaveOccurred()) 543 Expect(warnings).To(ConsistOf("get application warning")) 544 545 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(0)) 546 }) 547 }) 548 549 Context("when the desired http endpoint is not set", func() { 550 BeforeEach(func() { 551 fakeCloudControllerClient.GetApplicationsReturns( 552 []ccv2.Application{ 553 {GUID: "some-app-guid", HealthCheckType: "http", HealthCheckHTTPEndpoint: "/"}, 554 }, 555 ccv2.Warnings{"get application warning"}, 556 nil, 557 ) 558 fakeCloudControllerClient.UpdateApplicationReturns( 559 ccv2.Application{}, 560 ccv2.Warnings{"update warnings"}, 561 nil, 562 ) 563 }) 564 565 It("sets the desired health check type and returns the warnings", func() { 566 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 567 "some-app", "some-space-guid", "http", "/v2/anything") 568 Expect(err).ToNot(HaveOccurred()) 569 570 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 571 app := fakeCloudControllerClient.UpdateApplicationArgsForCall(0) 572 Expect(app).To(Equal(ccv2.Application{ 573 GUID: "some-app-guid", 574 HealthCheckType: "http", 575 HealthCheckHTTPEndpoint: "/v2/anything", 576 })) 577 578 Expect(warnings).To(ConsistOf("get application warning", "update warnings")) 579 }) 580 }) 581 }) 582 583 Context("when the application health check type is already set to the desired type", func() { 584 BeforeEach(func() { 585 fakeCloudControllerClient.GetApplicationsReturns( 586 []ccv2.Application{ 587 { 588 GUID: "some-app-guid", 589 HealthCheckType: "process", 590 }, 591 }, 592 ccv2.Warnings{"get application warning"}, 593 nil, 594 ) 595 }) 596 597 It("does not update the health check type", func() { 598 returnedApp, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 599 "some-app", "some-space-guid", "process", "/") 600 Expect(err).ToNot(HaveOccurred()) 601 Expect(warnings).To(ConsistOf("get application warning")) 602 Expect(returnedApp).To(Equal(Application{ 603 GUID: "some-app-guid", 604 HealthCheckType: "process", 605 })) 606 607 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(0)) 608 }) 609 }) 610 }) 611 612 Context("when getting the application returns an error", func() { 613 BeforeEach(func() { 614 fakeCloudControllerClient.GetApplicationsReturns( 615 []ccv2.Application{}, ccv2.Warnings{"get application warning"}, errors.New("get application error")) 616 }) 617 618 It("returns the error and warnings", func() { 619 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 620 "some-app", "some-space-guid", "process", "/") 621 622 Expect(warnings).To(ConsistOf("get application warning")) 623 Expect(err).To(MatchError("get application error")) 624 }) 625 }) 626 627 Context("when updating the application returns an error", func() { 628 var expectedErr error 629 630 BeforeEach(func() { 631 expectedErr = errors.New("foo bar") 632 fakeCloudControllerClient.GetApplicationsReturns( 633 []ccv2.Application{ 634 {GUID: "some-app-guid"}, 635 }, 636 ccv2.Warnings{"get application warning"}, 637 nil, 638 ) 639 fakeCloudControllerClient.UpdateApplicationReturns( 640 ccv2.Application{}, 641 ccv2.Warnings{"update warnings"}, 642 expectedErr, 643 ) 644 }) 645 646 It("returns the error and warnings", func() { 647 _, warnings, err := actor.SetApplicationHealthCheckTypeByNameAndSpace( 648 "some-app", "some-space-guid", "process", "/") 649 Expect(err).To(MatchError(expectedErr)) 650 Expect(warnings).To(ConsistOf("get application warning", "update warnings")) 651 }) 652 }) 653 }) 654 655 Describe("StartApplication/RestartApplication", func() { 656 var ( 657 app Application 658 fakeNOAAClient *v2actionfakes.FakeNOAAClient 659 fakeConfig *v2actionfakes.FakeConfig 660 661 messages <-chan *LogMessage 662 logErrs <-chan error 663 appState <-chan ApplicationStateChange 664 warnings <-chan string 665 errs <-chan error 666 667 eventStream chan *events.LogMessage 668 errStream chan error 669 ) 670 671 BeforeEach(func() { 672 fakeConfig = new(v2actionfakes.FakeConfig) 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 += 1 703 return ccv2.Application{ 704 GUID: "some-app-guid", 705 Instances: types.NullInt{Value: 2, IsSet: true}, 706 Name: "some-app", 707 PackageState: ccv2.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: ccv2.ApplicationPackageStaged, 716 }, ccv2.Warnings{"app-warnings-2"}, nil 717 } 718 719 instanceCount := 0 720 fakeCloudControllerClient.GetApplicationInstancesByApplicationStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 721 if instanceCount == 0 { 722 instanceCount += 1 723 return map[int]ccv2.ApplicationInstance{ 724 0: {State: ccv2.ApplicationInstanceStarting}, 725 1: {State: ccv2.ApplicationInstanceStarting}, 726 }, ccv2.Warnings{"app-instance-warnings-1"}, nil 727 } 728 729 return map[int]ccv2.ApplicationInstance{ 730 0: {State: ccv2.ApplicationInstanceStarting}, 731 1: {State: ccv2.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 Context("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.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 764 }) 765 }) 766 767 Context("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: ccv2.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.GetApplicationInstancesByApplicationCallCount()).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: ccv2.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.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 817 }) 818 }) 819 }) 820 821 Context("when the application takes too long to stage", func() { 822 BeforeEach(func() { 823 fakeConfig.StagingTimeoutReturns(0) 824 fakeCloudControllerClient.GetApplicationInstancesByApplicationStub = 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{Name: "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.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 836 }) 837 }) 838 }) 839 } 840 841 var ItHandlesStartingIssues = func() { 842 Context("starting issues", func() { 843 Context("when polling fails", func() { 844 var expectedErr error 845 BeforeEach(func() { 846 expectedErr = errors.New("I am a banana!!!!") 847 fakeCloudControllerClient.GetApplicationInstancesByApplicationStub = 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.GetApplicationInstancesByApplicationCallCount()).To(Equal(1)) 863 }) 864 }) 865 866 Context("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.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 882 }) 883 }) 884 885 Context("when the application crashes", func() { 886 BeforeEach(func() { 887 fakeCloudControllerClient.GetApplicationInstancesByApplicationStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 888 return map[int]ccv2.ApplicationInstance{ 889 0: {State: ccv2.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.GetApplicationInstancesByApplicationCallCount()).To(Equal(1)) 906 }) 907 }) 908 909 Context("when the application flaps", func() { 910 BeforeEach(func() { 911 fakeCloudControllerClient.GetApplicationInstancesByApplicationStub = func(guid string) (map[int]ccv2.ApplicationInstance, ccv2.Warnings, error) { 912 return map[int]ccv2.ApplicationInstance{ 913 0: {State: ccv2.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.GetApplicationInstancesByApplicationCallCount()).To(Equal(1)) 930 }) 931 }) 932 }) 933 } 934 935 var ItStartsApplication = func() { 936 Context("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: ccv2.ApplicationStarted, 953 })) 954 955 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 956 Expect(fakeCloudControllerClient.GetApplicationInstancesByApplicationCallCount()).To(Equal(2)) 957 Eventually(fakeNOAAClient.CloseCallCount).Should(Equal(2)) 958 }) 959 }) 960 961 Context("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: ccv2.ApplicationStarted, 983 })) 984 985 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 986 Expect(fakeCloudControllerClient.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 987 }) 988 }) 989 990 Context("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.GetApplicationInstancesByApplicationCallCount()).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, fakeConfig) 1023 }) 1024 1025 Context("when the app is already staged", func() { 1026 BeforeEach(func() { 1027 app.PackageState = ccv2.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: ccv2.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, fakeConfig) 1061 }) 1062 1063 Context("when application is running", func() { 1064 BeforeEach(func() { 1065 app.State = ccv2.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: ccv2.ApplicationStopped, 1086 })) 1087 1088 passedApp = fakeCloudControllerClient.UpdateApplicationArgsForCall(1) 1089 Expect(passedApp).To(Equal(ccv2.Application{ 1090 GUID: "some-app-guid", 1091 State: ccv2.ApplicationStarted, 1092 })) 1093 1094 Expect(fakeCloudControllerClient.GetApplicationCallCount()).To(Equal(2)) 1095 Expect(fakeCloudControllerClient.GetApplicationInstancesByApplicationCallCount()).To(Equal(2)) 1096 Eventually(fakeNOAAClient.CloseCallCount).Should(Equal(2)) 1097 }) 1098 1099 Context("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.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 1126 }) 1127 }) 1128 }) 1129 1130 Context("when the app is not running", func() { 1131 BeforeEach(func() { 1132 app.State = ccv2.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: ccv2.ApplicationStarted, 1149 })) 1150 }) 1151 }) 1152 1153 Context("when the app is already staged", func() { 1154 BeforeEach(func() { 1155 app.PackageState = ccv2.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: ccv2.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, fakeConfig) 1182 }) 1183 1184 Context("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.GetApplicationInstancesByApplicationCallCount()).To(Equal(2)) 1211 Eventually(fakeNOAAClient.CloseCallCount).Should(Equal(2)) 1212 }) 1213 1214 ItHandlesStagingIssues() 1215 1216 ItHandlesStartingIssues() 1217 }) 1218 1219 Context("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.GetApplicationInstancesByApplicationCallCount()).To(Equal(0)) 1235 }) 1236 }) 1237 }) 1238 }) 1239 1240 Describe("UpdateApplication", func() { 1241 Context("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 Context("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 })