github.com/swisscom/cloudfoundry-cli@v7.1.0+incompatible/actor/v3action/application_test.go (about) 1 package v3action_test 2 3 import ( 4 "errors" 5 "fmt" 6 "strings" 7 "time" 8 9 "code.cloudfoundry.org/cli/actor/actionerror" 10 . "code.cloudfoundry.org/cli/actor/v3action" 11 "code.cloudfoundry.org/cli/actor/v3action/v3actionfakes" 12 "code.cloudfoundry.org/cli/api/cloudcontroller/ccerror" 13 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3" 14 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 15 "code.cloudfoundry.org/cli/resources" 16 17 . "github.com/onsi/ginkgo" 18 . "github.com/onsi/gomega" 19 ) 20 21 var _ = Describe("Application Actions", func() { 22 var ( 23 actor *Actor 24 fakeCloudControllerClient *v3actionfakes.FakeCloudControllerClient 25 fakeConfig *v3actionfakes.FakeConfig 26 ) 27 28 BeforeEach(func() { 29 fakeCloudControllerClient = new(v3actionfakes.FakeCloudControllerClient) 30 fakeConfig = new(v3actionfakes.FakeConfig) 31 actor = NewActor(fakeCloudControllerClient, fakeConfig, nil, nil) 32 }) 33 34 Describe("DeleteApplicationByNameAndSpace", func() { 35 var ( 36 warnings Warnings 37 executeErr error 38 ) 39 40 JustBeforeEach(func() { 41 warnings, executeErr = actor.DeleteApplicationByNameAndSpace("some-app", "some-space-guid") 42 }) 43 44 When("looking up the app guid fails", func() { 45 BeforeEach(func() { 46 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{}, ccv3.Warnings{"some-get-app-warning"}, errors.New("some-get-app-error")) 47 }) 48 49 It("returns the warnings and error", func() { 50 Expect(warnings).To(ConsistOf("some-get-app-warning")) 51 Expect(executeErr).To(MatchError("some-get-app-error")) 52 }) 53 }) 54 55 When("looking up the app guid succeeds", func() { 56 BeforeEach(func() { 57 fakeCloudControllerClient.GetApplicationsReturns([]resources.Application{{Name: "some-app", GUID: "abc123"}}, ccv3.Warnings{"some-get-app-warning"}, nil) 58 }) 59 60 When("sending the delete fails", func() { 61 BeforeEach(func() { 62 fakeCloudControllerClient.DeleteApplicationReturns("", ccv3.Warnings{"some-delete-app-warning"}, errors.New("some-delete-app-error")) 63 }) 64 65 It("returns the warnings and error", func() { 66 Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning")) 67 Expect(executeErr).To(MatchError("some-delete-app-error")) 68 }) 69 }) 70 71 When("sending the delete succeeds", func() { 72 BeforeEach(func() { 73 fakeCloudControllerClient.DeleteApplicationReturns("/some-job-url", ccv3.Warnings{"some-delete-app-warning"}, nil) 74 }) 75 76 When("polling fails", func() { 77 BeforeEach(func() { 78 fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"some-poll-warning"}, errors.New("some-poll-error")) 79 }) 80 81 It("returns the warnings and poll error", func() { 82 Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning", "some-poll-warning")) 83 Expect(executeErr).To(MatchError("some-poll-error")) 84 }) 85 }) 86 87 When("polling succeeds", func() { 88 BeforeEach(func() { 89 fakeCloudControllerClient.PollJobReturns(ccv3.Warnings{"some-poll-warning"}, nil) 90 }) 91 92 It("returns all the warnings and no error", func() { 93 Expect(warnings).To(ConsistOf("some-get-app-warning", "some-delete-app-warning", "some-poll-warning")) 94 Expect(executeErr).ToNot(HaveOccurred()) 95 }) 96 }) 97 }) 98 }) 99 }) 100 101 Describe("GetApplicationByNameAndSpace", func() { 102 When("the app exists", func() { 103 var ( 104 warnings Warnings 105 executeErr error 106 app Application 107 ) 108 109 BeforeEach(func() { 110 fakeCloudControllerClient.GetApplicationsReturns( 111 []resources.Application{ 112 { 113 Name: "some-app-name", 114 GUID: "some-app-guid", 115 SpaceGUID: "some-space-guid", 116 }, 117 }, 118 ccv3.Warnings{"some-warning"}, 119 nil, 120 ) 121 }) 122 123 JustBeforeEach(func() { 124 app, warnings, executeErr = actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 125 }) 126 127 It("returns the application and warnings", func() { 128 Expect(executeErr).ToNot(HaveOccurred()) 129 Expect(app).To(Equal(Application{ 130 Name: "some-app-name", 131 GUID: "some-app-guid", 132 SpaceGUID: "some-space-guid", 133 })) 134 Expect(warnings).To(ConsistOf("some-warning")) 135 136 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 137 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 138 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}}, 139 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 140 )) 141 }) 142 }) 143 144 When("the cloud controller client returns an error", func() { 145 var expectedError error 146 147 BeforeEach(func() { 148 expectedError = errors.New("I am a CloudControllerClient Error") 149 fakeCloudControllerClient.GetApplicationsReturns( 150 []resources.Application{}, 151 ccv3.Warnings{"some-warning"}, 152 expectedError) 153 }) 154 155 It("returns the warnings and the error", func() { 156 _, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 157 Expect(warnings).To(ConsistOf("some-warning")) 158 Expect(err).To(MatchError(expectedError)) 159 }) 160 }) 161 162 When("the app does not exist", func() { 163 BeforeEach(func() { 164 fakeCloudControllerClient.GetApplicationsReturns( 165 []resources.Application{}, 166 ccv3.Warnings{"some-warning"}, 167 nil, 168 ) 169 }) 170 171 It("returns an ApplicationNotFoundError and the warnings", func() { 172 _, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 173 Expect(warnings).To(ConsistOf("some-warning")) 174 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app-name"})) 175 }) 176 }) 177 }) 178 179 Describe("GetApplicationsBySpace", func() { 180 When("there are applications in the space", func() { 181 BeforeEach(func() { 182 fakeCloudControllerClient.GetApplicationsReturns( 183 []resources.Application{ 184 { 185 GUID: "some-app-guid-1", 186 Name: "some-app-1", 187 SpaceGUID: "some-space-guid-1", 188 }, 189 { 190 GUID: "some-app-guid-2", 191 Name: "some-app-2", 192 SpaceGUID: "some-space-guid-2", 193 }, 194 }, 195 ccv3.Warnings{"warning-1", "warning-2"}, 196 nil, 197 ) 198 }) 199 200 It("returns the application and warnings", func() { 201 apps, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 202 Expect(err).ToNot(HaveOccurred()) 203 Expect(apps).To(ConsistOf( 204 Application{ 205 GUID: "some-app-guid-1", 206 Name: "some-app-1", 207 SpaceGUID: "some-space-guid-1", 208 }, 209 Application{ 210 GUID: "some-app-guid-2", 211 Name: "some-app-2", 212 SpaceGUID: "some-space-guid-2", 213 }, 214 )) 215 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 216 217 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 218 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 219 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 220 )) 221 }) 222 }) 223 224 When("the cloud controller client returns an error", func() { 225 var expectedError error 226 227 BeforeEach(func() { 228 expectedError = errors.New("I am a CloudControllerClient Error") 229 fakeCloudControllerClient.GetApplicationsReturns( 230 []resources.Application{}, 231 ccv3.Warnings{"some-warning"}, 232 expectedError) 233 }) 234 235 It("returns the error and warnings", func() { 236 _, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 237 Expect(warnings).To(ConsistOf("some-warning")) 238 Expect(err).To(MatchError(expectedError)) 239 }) 240 }) 241 }) 242 243 Describe("GetApplicationsByGUIDs", func() { 244 When("there are applications that match provided guids", func() { 245 BeforeEach(func() { 246 fakeCloudControllerClient.GetApplicationsReturns( 247 []resources.Application{ 248 { 249 GUID: "some-app-guid-1", 250 Name: "some-app-1", 251 SpaceGUID: "some-space-guid-1", 252 }, 253 { 254 GUID: "some-app-guid-2", 255 Name: "some-app-2", 256 SpaceGUID: "some-space-guid-2", 257 }, 258 }, 259 ccv3.Warnings{"warning-1", "warning-2"}, 260 nil, 261 ) 262 }) 263 264 It("returns the applications and warnings", func() { 265 apps, warnings, err := actor.GetApplicationsByGUIDs("some-app-guid-1", "some-app-guid-2") 266 Expect(err).ToNot(HaveOccurred()) 267 Expect(apps).To(ConsistOf( 268 Application{ 269 GUID: "some-app-guid-1", 270 Name: "some-app-1", 271 SpaceGUID: "some-space-guid-1", 272 }, 273 Application{ 274 GUID: "some-app-guid-2", 275 Name: "some-app-2", 276 SpaceGUID: "some-space-guid-2", 277 }, 278 )) 279 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 280 281 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 282 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 283 ccv3.Query{Key: ccv3.GUIDFilter, Values: []string{"some-app-guid-1", "some-app-guid-2"}}, 284 )) 285 }) 286 }) 287 288 When("the cloud controller client returns an error", func() { 289 var expectedError error 290 291 BeforeEach(func() { 292 expectedError = errors.New("I am a CloudControllerClient Error") 293 fakeCloudControllerClient.GetApplicationsReturns( 294 []resources.Application{}, 295 ccv3.Warnings{"some-warning"}, 296 expectedError) 297 }) 298 299 It("returns the error and warnings", func() { 300 _, warnings, err := actor.GetApplicationsByGUIDs("some-space-guid") 301 Expect(warnings).To(ConsistOf("some-warning")) 302 Expect(err).To(MatchError(expectedError)) 303 }) 304 }) 305 }) 306 307 Describe("CreateApplicationInSpace", func() { 308 var ( 309 application Application 310 warnings Warnings 311 err error 312 ) 313 314 JustBeforeEach(func() { 315 application, warnings, err = actor.CreateApplicationInSpace(Application{ 316 Name: "some-app-name", 317 LifecycleType: constant.AppLifecycleTypeBuildpack, 318 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 319 }, "some-space-guid") 320 }) 321 322 When("the app successfully gets created", func() { 323 BeforeEach(func() { 324 fakeCloudControllerClient.CreateApplicationReturns( 325 resources.Application{ 326 Name: "some-app-name", 327 GUID: "some-app-guid", 328 LifecycleType: constant.AppLifecycleTypeBuildpack, 329 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 330 SpaceGUID: "some-space-guid", 331 }, 332 ccv3.Warnings{"some-warning"}, 333 nil, 334 ) 335 }) 336 337 It("creates and returns the application and warnings", func() { 338 Expect(err).ToNot(HaveOccurred()) 339 Expect(application).To(Equal(Application{ 340 Name: "some-app-name", 341 GUID: "some-app-guid", 342 LifecycleType: constant.AppLifecycleTypeBuildpack, 343 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 344 SpaceGUID: "some-space-guid", 345 })) 346 Expect(warnings).To(ConsistOf("some-warning")) 347 348 Expect(fakeCloudControllerClient.CreateApplicationCallCount()).To(Equal(1)) 349 Expect(fakeCloudControllerClient.CreateApplicationArgsForCall(0)).To(Equal(resources.Application{ 350 Name: "some-app-name", 351 SpaceGUID: "some-space-guid", 352 LifecycleType: constant.AppLifecycleTypeBuildpack, 353 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 354 })) 355 }) 356 }) 357 358 When("the cc client returns an error", func() { 359 var expectedError error 360 361 BeforeEach(func() { 362 expectedError = errors.New("I am a CloudControllerClient Error") 363 fakeCloudControllerClient.CreateApplicationReturns( 364 resources.Application{}, 365 ccv3.Warnings{"some-warning"}, 366 expectedError, 367 ) 368 }) 369 370 It("raises the error and warnings", func() { 371 Expect(err).To(MatchError(expectedError)) 372 Expect(warnings).To(ConsistOf("some-warning")) 373 }) 374 }) 375 376 When("the cc client returns an NameNotUniqueInSpaceError", func() { 377 BeforeEach(func() { 378 fakeCloudControllerClient.CreateApplicationReturns( 379 resources.Application{}, 380 ccv3.Warnings{"some-warning"}, 381 ccerror.NameNotUniqueInSpaceError{}, 382 ) 383 }) 384 385 It("returns the NameNotUniqueInSpaceError and warnings", func() { 386 Expect(err).To(MatchError(ccerror.NameNotUniqueInSpaceError{})) 387 Expect(warnings).To(ConsistOf("some-warning")) 388 }) 389 }) 390 }) 391 392 Describe("UpdateApplication", func() { 393 var ( 394 submitApp, resultApp Application 395 warnings Warnings 396 err error 397 ) 398 399 JustBeforeEach(func() { 400 submitApp = Application{ 401 GUID: "some-app-guid", 402 StackName: "some-stack-name", 403 LifecycleType: constant.AppLifecycleTypeBuildpack, 404 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 405 } 406 resultApp, warnings, err = actor.UpdateApplication(submitApp) 407 }) 408 409 When("the app successfully gets updated", func() { 410 var apiResponseApp resources.Application 411 412 BeforeEach(func() { 413 apiResponseApp = resources.Application{ 414 GUID: "response-app-guid", 415 StackName: "response-stack-name", 416 LifecycleType: constant.AppLifecycleTypeBuildpack, 417 LifecycleBuildpacks: []string{"response-buildpack-1", "response-buildpack-2"}, 418 SpaceGUID: "some-space-guid", 419 } 420 fakeCloudControllerClient.UpdateApplicationReturns( 421 apiResponseApp, 422 ccv3.Warnings{"some-warning"}, 423 nil, 424 ) 425 }) 426 427 It("creates and returns the application and warnings", func() { 428 Expect(err).ToNot(HaveOccurred()) 429 Expect(resultApp).To(Equal(Application{ 430 GUID: apiResponseApp.GUID, 431 StackName: apiResponseApp.StackName, 432 LifecycleType: apiResponseApp.LifecycleType, 433 LifecycleBuildpacks: apiResponseApp.LifecycleBuildpacks, 434 SpaceGUID: "some-space-guid", 435 })) 436 Expect(warnings).To(ConsistOf("some-warning")) 437 438 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 439 Expect(fakeCloudControllerClient.UpdateApplicationArgsForCall(0)).To(Equal(resources.Application{ 440 GUID: submitApp.GUID, 441 StackName: submitApp.StackName, 442 LifecycleType: submitApp.LifecycleType, 443 LifecycleBuildpacks: submitApp.LifecycleBuildpacks, 444 })) 445 }) 446 }) 447 448 When("the cc client returns an error", func() { 449 var expectedError error 450 451 BeforeEach(func() { 452 expectedError = errors.New("I am a CloudControllerClient Error") 453 fakeCloudControllerClient.UpdateApplicationReturns( 454 resources.Application{}, 455 ccv3.Warnings{"some-warning"}, 456 expectedError, 457 ) 458 }) 459 460 It("raises the error and warnings", func() { 461 Expect(err).To(MatchError(expectedError)) 462 Expect(warnings).To(ConsistOf("some-warning")) 463 }) 464 }) 465 }) 466 467 Describe("PollStart", func() { 468 var warningsChannel chan Warnings 469 var allWarnings Warnings 470 var funcDone chan interface{} 471 472 BeforeEach(func() { 473 warningsChannel = make(chan Warnings) 474 funcDone = make(chan interface{}) 475 allWarnings = Warnings{} 476 go func() { 477 for { 478 select { 479 case warnings := <-warningsChannel: 480 allWarnings = append(allWarnings, warnings...) 481 case <-funcDone: 482 return 483 } 484 } 485 }() 486 }) 487 488 When("getting the application processes fails", func() { 489 BeforeEach(func() { 490 fakeCloudControllerClient.GetApplicationProcessesReturns(nil, ccv3.Warnings{"get-app-warning-1", "get-app-warning-2"}, errors.New("some-error")) 491 }) 492 493 It("returns the error and all warnings", func() { 494 err := actor.PollStart("some-guid", warningsChannel) 495 funcDone <- nil 496 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-app-warning-2")) 497 Expect(err).To(MatchError(errors.New("some-error"))) 498 }) 499 }) 500 501 When("getting the application processes succeeds", func() { 502 var processes []ccv3.Process 503 504 BeforeEach(func() { 505 fakeConfig.StartupTimeoutReturns(time.Second) 506 fakeConfig.PollingIntervalReturns(0) 507 }) 508 509 JustBeforeEach(func() { 510 fakeCloudControllerClient.GetApplicationProcessesReturns( 511 processes, 512 ccv3.Warnings{"get-app-warning-1"}, nil) 513 }) 514 515 When("there is a single process", func() { 516 BeforeEach(func() { 517 processes = []ccv3.Process{{GUID: "abc123"}} 518 }) 519 520 When("the polling times out", func() { 521 BeforeEach(func() { 522 fakeConfig.StartupTimeoutReturns(time.Millisecond) 523 fakeConfig.PollingIntervalReturns(time.Millisecond * 2) 524 fakeCloudControllerClient.GetProcessInstancesReturns( 525 []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, 526 ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"}, 527 nil, 528 ) 529 }) 530 531 It("returns the timeout error", func() { 532 err := actor.PollStart("some-guid", warningsChannel) 533 funcDone <- nil 534 535 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2")) 536 Expect(err).To(MatchError(actionerror.StartupTimeoutError{})) 537 }) 538 539 It("gets polling and timeout values from the config", func() { 540 err := actor.PollStart("some-guid", warningsChannel) 541 Expect(err).To(MatchError(actionerror.StartupTimeoutError{})) 542 funcDone <- nil 543 544 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 545 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 546 }) 547 }) 548 549 When("getting the process instances errors", func() { 550 BeforeEach(func() { 551 fakeCloudControllerClient.GetProcessInstancesReturns( 552 nil, 553 ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"}, 554 errors.New("some-error"), 555 ) 556 }) 557 558 It("returns the error", func() { 559 err := actor.PollStart("some-guid", warningsChannel) 560 funcDone <- nil 561 562 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2")) 563 Expect(err).To(MatchError("some-error")) 564 }) 565 }) 566 567 When("getting the process instances succeeds", func() { 568 var ( 569 initialInstanceStates []ccv3.ProcessInstance 570 eventualInstanceStates []ccv3.ProcessInstance 571 pollStartErr error 572 processInstanceCallCount int 573 ) 574 575 BeforeEach(func() { 576 processInstanceCallCount = 0 577 }) 578 579 JustBeforeEach(func() { 580 fakeCloudControllerClient.GetProcessInstancesStub = func(processGuid string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) { 581 defer func() { processInstanceCallCount++ }() 582 if processInstanceCallCount == 0 { 583 return initialInstanceStates, 584 ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"}, 585 nil 586 } else { 587 return eventualInstanceStates, 588 ccv3.Warnings{fmt.Sprintf("get-process-warning-%d", processInstanceCallCount+2)}, 589 nil 590 } 591 } 592 593 pollStartErr = actor.PollStart("some-guid", warningsChannel) 594 funcDone <- nil 595 }) 596 597 When("there are no process instances", func() { 598 BeforeEach(func() { 599 initialInstanceStates = []ccv3.ProcessInstance{} 600 eventualInstanceStates = []ccv3.ProcessInstance{} 601 }) 602 603 It("should not return an error", func() { 604 Expect(pollStartErr).NotTo(HaveOccurred()) 605 }) 606 607 It("should only call GetProcessInstances once before exiting", func() { 608 Expect(processInstanceCallCount).To(Equal(1)) 609 }) 610 611 It("should return correct warnings", func() { 612 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2")) 613 }) 614 }) 615 616 When("all instances become running by the second call", func() { 617 BeforeEach(func() { 618 initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}} 619 eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}, {State: constant.ProcessInstanceRunning}} 620 }) 621 622 It("should not return an error", func() { 623 Expect(pollStartErr).NotTo(HaveOccurred()) 624 }) 625 626 It("should call GetProcessInstances twice", func() { 627 Expect(processInstanceCallCount).To(Equal(2)) 628 }) 629 630 It("should return correct warnings", func() { 631 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3")) 632 }) 633 }) 634 635 When("at least one instance has become running by the second call", func() { 636 BeforeEach(func() { 637 initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}} 638 eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceRunning}} 639 }) 640 641 It("should not return an error", func() { 642 Expect(pollStartErr).NotTo(HaveOccurred()) 643 }) 644 645 It("should call GetProcessInstances twice", func() { 646 Expect(processInstanceCallCount).To(Equal(2)) 647 }) 648 649 It("should return correct warnings", func() { 650 Expect(len(allWarnings)).To(Equal(4)) 651 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3")) 652 }) 653 }) 654 655 When("all of the instances have crashed by the second call", func() { 656 BeforeEach(func() { 657 initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}} 658 eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceCrashed}, {State: constant.ProcessInstanceCrashed}, {State: constant.ProcessInstanceCrashed}} 659 }) 660 661 It("should not return an error", func() { 662 Expect(pollStartErr).NotTo(HaveOccurred()) 663 }) 664 665 It("should call GetProcessInstances twice", func() { 666 Expect(processInstanceCallCount).To(Equal(2)) 667 }) 668 669 It("should return correct warnings", func() { 670 Expect(len(allWarnings)).To(Equal(4)) 671 Expect(allWarnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3")) 672 }) 673 }) 674 }) 675 }) 676 677 Context("where there are multiple processes", func() { 678 var ( 679 pollStartErr error 680 processInstanceCallCount int 681 ) 682 683 BeforeEach(func() { 684 processInstanceCallCount = 0 685 fakeConfig.StartupTimeoutReturns(time.Millisecond) 686 fakeConfig.PollingIntervalReturns(time.Millisecond * 2) 687 }) 688 689 JustBeforeEach(func() { 690 fakeCloudControllerClient.GetProcessInstancesStub = func(processGuid string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) { 691 defer func() { processInstanceCallCount++ }() 692 if strings.HasPrefix(processGuid, "good") { 693 return []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}}, nil, nil 694 } else { 695 return []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, nil, nil 696 } 697 } 698 699 pollStartErr = actor.PollStart("some-guid", warningsChannel) 700 funcDone <- nil 701 }) 702 703 When("none of the processes are ready", func() { 704 BeforeEach(func() { 705 processes = []ccv3.Process{{GUID: "bad-1"}, {GUID: "bad-2"}} 706 }) 707 708 It("returns the timeout error", func() { 709 Expect(pollStartErr).To(MatchError(actionerror.StartupTimeoutError{})) 710 }) 711 712 }) 713 714 When("some of the processes are ready", func() { 715 BeforeEach(func() { 716 processes = []ccv3.Process{{GUID: "bad-1"}, {GUID: "good-1"}} 717 }) 718 719 It("returns the timeout error", func() { 720 Expect(pollStartErr).To(MatchError(actionerror.StartupTimeoutError{})) 721 }) 722 }) 723 724 When("all of the processes are ready", func() { 725 BeforeEach(func() { 726 processes = []ccv3.Process{{GUID: "good-1"}, {GUID: "good-2"}} 727 }) 728 729 It("returns nil", func() { 730 Expect(pollStartErr).ToNot(HaveOccurred()) 731 }) 732 }) 733 }) 734 }) 735 }) 736 737 Describe("StopApplication", func() { 738 var ( 739 warnings Warnings 740 executeErr error 741 ) 742 743 JustBeforeEach(func() { 744 warnings, executeErr = actor.StopApplication("some-app-guid") 745 }) 746 747 When("there are no client errors", func() { 748 BeforeEach(func() { 749 fakeCloudControllerClient.UpdateApplicationStopReturns( 750 resources.Application{GUID: "some-app-guid"}, 751 ccv3.Warnings{"stop-application-warning"}, 752 nil, 753 ) 754 }) 755 756 It("stops the application", func() { 757 Expect(executeErr).ToNot(HaveOccurred()) 758 Expect(warnings).To(ConsistOf("stop-application-warning")) 759 760 Expect(fakeCloudControllerClient.UpdateApplicationStopCallCount()).To(Equal(1)) 761 Expect(fakeCloudControllerClient.UpdateApplicationStopArgsForCall(0)).To(Equal("some-app-guid")) 762 }) 763 }) 764 765 When("stopping the application fails", func() { 766 var expectedErr error 767 BeforeEach(func() { 768 expectedErr = errors.New("some set stop-application error") 769 fakeCloudControllerClient.UpdateApplicationStopReturns( 770 resources.Application{}, 771 ccv3.Warnings{"stop-application-warning"}, 772 expectedErr, 773 ) 774 }) 775 776 It("returns the error", func() { 777 Expect(executeErr).To(Equal(expectedErr)) 778 Expect(warnings).To(ConsistOf("stop-application-warning")) 779 }) 780 }) 781 }) 782 783 Describe("StartApplication", func() { 784 When("there are no client errors", func() { 785 BeforeEach(func() { 786 fakeCloudControllerClient.UpdateApplicationStartReturns( 787 resources.Application{GUID: "some-app-guid"}, 788 ccv3.Warnings{"start-application-warning"}, 789 nil, 790 ) 791 }) 792 793 It("starts the application", func() { 794 warnings, err := actor.StartApplication("some-app-guid") 795 796 Expect(err).ToNot(HaveOccurred()) 797 Expect(warnings).To(ConsistOf("start-application-warning")) 798 799 Expect(fakeCloudControllerClient.UpdateApplicationStartCallCount()).To(Equal(1)) 800 Expect(fakeCloudControllerClient.UpdateApplicationStartArgsForCall(0)).To(Equal("some-app-guid")) 801 }) 802 }) 803 804 When("starting the application fails", func() { 805 var expectedErr error 806 BeforeEach(func() { 807 expectedErr = errors.New("some set start-application error") 808 fakeCloudControllerClient.UpdateApplicationStartReturns( 809 resources.Application{}, 810 ccv3.Warnings{"start-application-warning"}, 811 expectedErr, 812 ) 813 }) 814 815 It("returns the error", func() { 816 warnings, err := actor.StartApplication("some-app-guid") 817 818 Expect(err).To(Equal(expectedErr)) 819 Expect(warnings).To(ConsistOf("start-application-warning")) 820 }) 821 }) 822 }) 823 824 Describe("RestartApplication", func() { 825 var ( 826 warnings Warnings 827 executeErr error 828 ) 829 830 JustBeforeEach(func() { 831 warnings, executeErr = actor.RestartApplication("some-app-guid") 832 }) 833 834 When("there are no client errors", func() { 835 BeforeEach(func() { 836 fakeCloudControllerClient.UpdateApplicationRestartReturns( 837 resources.Application{GUID: "some-app-guid"}, 838 ccv3.Warnings{"restart-application-warning"}, 839 nil, 840 ) 841 }) 842 843 It("stops the application", func() { 844 Expect(executeErr).ToNot(HaveOccurred()) 845 Expect(warnings).To(ConsistOf("restart-application-warning")) 846 847 Expect(fakeCloudControllerClient.UpdateApplicationRestartCallCount()).To(Equal(1)) 848 Expect(fakeCloudControllerClient.UpdateApplicationRestartArgsForCall(0)).To(Equal("some-app-guid")) 849 }) 850 }) 851 852 When("restarting the application fails", func() { 853 var expectedErr error 854 BeforeEach(func() { 855 expectedErr = errors.New("some set restart-application error") 856 fakeCloudControllerClient.UpdateApplicationRestartReturns( 857 resources.Application{}, 858 ccv3.Warnings{"restart-application-warning"}, 859 expectedErr, 860 ) 861 }) 862 863 It("returns the error", func() { 864 Expect(executeErr).To(Equal(expectedErr)) 865 Expect(warnings).To(ConsistOf("restart-application-warning")) 866 }) 867 }) 868 }) 869 870 })