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