github.com/arunkumar7540/cli@v6.45.0+incompatible/actor/v7action/application_test.go (about) 1 package v7action_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/v7action" 11 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 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/types" 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 *v7actionfakes.FakeCloudControllerClient 25 fakeConfig *v7actionfakes.FakeConfig 26 ) 27 28 BeforeEach(func() { 29 fakeCloudControllerClient = new(v7actionfakes.FakeCloudControllerClient) 30 fakeConfig = new(v7actionfakes.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([]ccv3.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([]ccv3.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("GetApplicationsByNameAndSpace", func() { 102 When("all of the requested apps exist", func() { 103 BeforeEach(func() { 104 fakeCloudControllerClient.GetApplicationsReturns( 105 []ccv3.Application{ 106 { 107 Name: "some-app-name", 108 GUID: "some-app-guid", 109 }, 110 { 111 Name: "other-app-name", 112 GUID: "other-app-guid", 113 }, 114 }, 115 ccv3.Warnings{"some-warning"}, 116 nil, 117 ) 118 }) 119 120 It("returns the applications and warnings", func() { 121 apps, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name", "other-app-name"}, "some-space-guid") 122 Expect(err).ToNot(HaveOccurred()) 123 Expect(apps).To(ConsistOf( 124 Application{ 125 Name: "some-app-name", 126 GUID: "some-app-guid", 127 }, 128 Application{ 129 Name: "other-app-name", 130 GUID: "other-app-guid", 131 }, 132 )) 133 Expect(warnings).To(ConsistOf("some-warning")) 134 135 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 136 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 137 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name", "other-app-name"}}, 138 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 139 )) 140 }) 141 }) 142 143 When("at least one of the requested apps does not exist", func() { 144 BeforeEach(func() { 145 fakeCloudControllerClient.GetApplicationsReturns( 146 []ccv3.Application{ 147 { 148 Name: "some-app-name", 149 }, 150 }, 151 ccv3.Warnings{"some-warning"}, 152 nil, 153 ) 154 }) 155 156 It("returns an ApplicationNotFoundError and the warnings", func() { 157 _, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name", "other-app-name"}, "some-space-guid") 158 Expect(warnings).To(ConsistOf("some-warning")) 159 Expect(err).To(MatchError(actionerror.ApplicationsNotFoundError{})) 160 }) 161 }) 162 163 When("the cloud controller client returns an error", func() { 164 var expectedError error 165 166 BeforeEach(func() { 167 expectedError = errors.New("I am a CloudControllerClient Error") 168 fakeCloudControllerClient.GetApplicationsReturns( 169 []ccv3.Application{}, 170 ccv3.Warnings{"some-warning"}, 171 expectedError) 172 }) 173 174 It("returns the warnings and the error", func() { 175 _, warnings, err := actor.GetApplicationsByNamesAndSpace([]string{"some-app-name"}, "some-space-guid") 176 Expect(warnings).To(ConsistOf("some-warning")) 177 Expect(err).To(MatchError(expectedError)) 178 }) 179 }) 180 }) 181 182 Describe("GetApplicationByNameAndSpace", func() { 183 When("the app exists", func() { 184 BeforeEach(func() { 185 fakeCloudControllerClient.GetApplicationsReturns( 186 []ccv3.Application{ 187 { 188 Name: "some-app-name", 189 GUID: "some-app-guid", 190 Metadata: &ccv3.Metadata{ 191 Labels: map[string]types.NullString{ 192 "some-key": types.NewNullString("some-value"), 193 }, 194 }, 195 }, 196 }, 197 ccv3.Warnings{"some-warning"}, 198 nil, 199 ) 200 }) 201 202 It("returns the application and warnings", func() { 203 app, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 204 Expect(err).ToNot(HaveOccurred()) 205 Expect(app).To(Equal(Application{ 206 Name: "some-app-name", 207 GUID: "some-app-guid", 208 Metadata: &Metadata{ 209 Labels: map[string]types.NullString{"some-key": types.NewNullString("some-value")}, 210 }, 211 })) 212 Expect(warnings).To(ConsistOf("some-warning")) 213 214 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 215 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 216 ccv3.Query{Key: ccv3.NameFilter, Values: []string{"some-app-name"}}, 217 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 218 )) 219 }) 220 }) 221 222 When("the cloud controller client returns an error", func() { 223 var expectedError error 224 225 BeforeEach(func() { 226 expectedError = errors.New("I am a CloudControllerClient Error") 227 fakeCloudControllerClient.GetApplicationsReturns( 228 []ccv3.Application{}, 229 ccv3.Warnings{"some-warning"}, 230 expectedError) 231 }) 232 233 It("returns the warnings and the error", func() { 234 _, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 235 Expect(warnings).To(ConsistOf("some-warning")) 236 Expect(err).To(MatchError(expectedError)) 237 }) 238 }) 239 240 When("the app does not exist", func() { 241 BeforeEach(func() { 242 fakeCloudControllerClient.GetApplicationsReturns( 243 []ccv3.Application{}, 244 ccv3.Warnings{"some-warning"}, 245 nil, 246 ) 247 }) 248 249 It("returns an ApplicationNotFoundError and the warnings", func() { 250 _, warnings, err := actor.GetApplicationByNameAndSpace("some-app-name", "some-space-guid") 251 Expect(warnings).To(ConsistOf("some-warning")) 252 Expect(err).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app-name"})) 253 }) 254 }) 255 }) 256 257 Describe("GetApplicationsBySpace", func() { 258 When("the there are applications in the space", func() { 259 BeforeEach(func() { 260 fakeCloudControllerClient.GetApplicationsReturns( 261 []ccv3.Application{ 262 { 263 GUID: "some-app-guid-1", 264 Name: "some-app-1", 265 }, 266 { 267 GUID: "some-app-guid-2", 268 Name: "some-app-2", 269 }, 270 }, 271 ccv3.Warnings{"warning-1", "warning-2"}, 272 nil, 273 ) 274 }) 275 276 It("returns the application and warnings", func() { 277 apps, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 278 Expect(err).ToNot(HaveOccurred()) 279 Expect(apps).To(ConsistOf( 280 Application{ 281 GUID: "some-app-guid-1", 282 Name: "some-app-1", 283 }, 284 Application{ 285 GUID: "some-app-guid-2", 286 Name: "some-app-2", 287 }, 288 )) 289 Expect(warnings).To(ConsistOf("warning-1", "warning-2")) 290 291 Expect(fakeCloudControllerClient.GetApplicationsCallCount()).To(Equal(1)) 292 Expect(fakeCloudControllerClient.GetApplicationsArgsForCall(0)).To(ConsistOf( 293 ccv3.Query{Key: ccv3.SpaceGUIDFilter, Values: []string{"some-space-guid"}}, 294 )) 295 }) 296 }) 297 298 When("the cloud controller client returns an error", func() { 299 var expectedError error 300 301 BeforeEach(func() { 302 expectedError = errors.New("I am a CloudControllerClient Error") 303 fakeCloudControllerClient.GetApplicationsReturns( 304 []ccv3.Application{}, 305 ccv3.Warnings{"some-warning"}, 306 expectedError) 307 }) 308 309 It("returns the error and warnings", func() { 310 _, warnings, err := actor.GetApplicationsBySpace("some-space-guid") 311 Expect(warnings).To(ConsistOf("some-warning")) 312 Expect(err).To(MatchError(expectedError)) 313 }) 314 }) 315 }) 316 317 Describe("CreateApplicationInSpace", func() { 318 var ( 319 application Application 320 warnings Warnings 321 err error 322 ) 323 324 JustBeforeEach(func() { 325 application, warnings, err = actor.CreateApplicationInSpace(Application{ 326 Name: "some-app-name", 327 LifecycleType: constant.AppLifecycleTypeBuildpack, 328 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 329 }, "some-space-guid") 330 }) 331 332 When("the app successfully gets created", func() { 333 BeforeEach(func() { 334 fakeCloudControllerClient.CreateApplicationReturns( 335 ccv3.Application{ 336 Name: "some-app-name", 337 GUID: "some-app-guid", 338 LifecycleType: constant.AppLifecycleTypeBuildpack, 339 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 340 }, 341 ccv3.Warnings{"some-warning"}, 342 nil, 343 ) 344 }) 345 346 It("creates and returns the application and warnings", func() { 347 Expect(err).ToNot(HaveOccurred()) 348 Expect(application).To(Equal(Application{ 349 Name: "some-app-name", 350 GUID: "some-app-guid", 351 LifecycleType: constant.AppLifecycleTypeBuildpack, 352 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 353 })) 354 Expect(warnings).To(ConsistOf("some-warning")) 355 356 Expect(fakeCloudControllerClient.CreateApplicationCallCount()).To(Equal(1)) 357 Expect(fakeCloudControllerClient.CreateApplicationArgsForCall(0)).To(Equal(ccv3.Application{ 358 Name: "some-app-name", 359 Relationships: ccv3.Relationships{ 360 constant.RelationshipTypeSpace: ccv3.Relationship{GUID: "some-space-guid"}, 361 }, 362 LifecycleType: constant.AppLifecycleTypeBuildpack, 363 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 364 })) 365 }) 366 }) 367 368 When("the cc client returns an error", func() { 369 var expectedError error 370 371 BeforeEach(func() { 372 expectedError = errors.New("I am a CloudControllerClient Error") 373 fakeCloudControllerClient.CreateApplicationReturns( 374 ccv3.Application{}, 375 ccv3.Warnings{"some-warning"}, 376 expectedError, 377 ) 378 }) 379 380 It("raises the error and warnings", func() { 381 Expect(err).To(MatchError(expectedError)) 382 Expect(warnings).To(ConsistOf("some-warning")) 383 }) 384 }) 385 386 When("the cc client returns an NameNotUniqueInSpaceError", func() { 387 BeforeEach(func() { 388 fakeCloudControllerClient.CreateApplicationReturns( 389 ccv3.Application{}, 390 ccv3.Warnings{"some-warning"}, 391 ccerror.NameNotUniqueInSpaceError{}, 392 ) 393 }) 394 395 It("returns the ApplicationAlreadyExistsError and warnings", func() { 396 Expect(err).To(MatchError(actionerror.ApplicationAlreadyExistsError{Name: "some-app-name"})) 397 Expect(warnings).To(ConsistOf("some-warning")) 398 }) 399 }) 400 }) 401 402 Describe("UpdateApplication", func() { 403 var ( 404 submitApp, resultApp Application 405 warnings Warnings 406 err error 407 ) 408 409 JustBeforeEach(func() { 410 submitApp = Application{ 411 GUID: "some-app-guid", 412 StackName: "some-stack-name", 413 LifecycleType: constant.AppLifecycleTypeBuildpack, 414 LifecycleBuildpacks: []string{"buildpack-1", "buildpack-2"}, 415 Metadata: &Metadata{Labels: map[string]types.NullString{ 416 "some-label": types.NewNullString("some-value"), 417 "other-label": types.NewNullString("other-value"), 418 }}, 419 } 420 421 resultApp, warnings, err = actor.UpdateApplication(submitApp) 422 }) 423 424 When("the app successfully gets updated", func() { 425 var apiResponseApp ccv3.Application 426 427 BeforeEach(func() { 428 apiResponseApp = ccv3.Application{ 429 GUID: "response-app-guid", 430 StackName: "response-stack-name", 431 LifecycleType: constant.AppLifecycleTypeBuildpack, 432 LifecycleBuildpacks: []string{"response-buildpack-1", "response-buildpack-2"}, 433 } 434 fakeCloudControllerClient.UpdateApplicationReturns( 435 apiResponseApp, 436 ccv3.Warnings{"some-warning"}, 437 nil, 438 ) 439 }) 440 441 It("creates and returns the application and warnings", func() { 442 Expect(err).ToNot(HaveOccurred()) 443 Expect(resultApp).To(Equal(Application{ 444 GUID: apiResponseApp.GUID, 445 StackName: apiResponseApp.StackName, 446 LifecycleType: apiResponseApp.LifecycleType, 447 LifecycleBuildpacks: apiResponseApp.LifecycleBuildpacks, 448 })) 449 Expect(warnings).To(ConsistOf("some-warning")) 450 451 Expect(fakeCloudControllerClient.UpdateApplicationCallCount()).To(Equal(1)) 452 Expect(fakeCloudControllerClient.UpdateApplicationArgsForCall(0)).To(Equal(ccv3.Application{ 453 GUID: submitApp.GUID, 454 StackName: submitApp.StackName, 455 LifecycleType: submitApp.LifecycleType, 456 LifecycleBuildpacks: submitApp.LifecycleBuildpacks, 457 Metadata: (*ccv3.Metadata)(submitApp.Metadata), 458 })) 459 }) 460 }) 461 462 When("the cc client returns an error", func() { 463 var expectedError error 464 465 BeforeEach(func() { 466 expectedError = errors.New("I am a CloudControllerClient Error") 467 fakeCloudControllerClient.UpdateApplicationReturns( 468 ccv3.Application{}, 469 ccv3.Warnings{"some-warning"}, 470 expectedError, 471 ) 472 }) 473 474 It("raises the error and warnings", func() { 475 Expect(err).To(MatchError(expectedError)) 476 Expect(warnings).To(ConsistOf("some-warning")) 477 }) 478 }) 479 }) 480 481 Describe("PollStart", func() { 482 var ( 483 appGUID string 484 485 warnings Warnings 486 executeErr error 487 ) 488 489 BeforeEach(func() { 490 appGUID = "some-guid" 491 }) 492 493 JustBeforeEach(func() { 494 warnings, executeErr = actor.PollStart(appGUID) 495 }) 496 497 When("getting the application processes fails", func() { 498 BeforeEach(func() { 499 fakeCloudControllerClient.GetApplicationProcessesReturns(nil, ccv3.Warnings{"get-app-warning-1", "get-app-warning-2"}, errors.New("some-error")) 500 }) 501 502 It("returns the error and all warnings", func() { 503 Expect(executeErr).To(MatchError(errors.New("some-error"))) 504 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-app-warning-2")) 505 }) 506 }) 507 508 When("getting the application processes succeeds", func() { 509 var processes []ccv3.Process 510 511 BeforeEach(func() { 512 fakeConfig.StartupTimeoutReturns(time.Second) 513 fakeConfig.PollingIntervalReturns(0) 514 }) 515 516 When("there is a single process", func() { 517 BeforeEach(func() { 518 processes = []ccv3.Process{{GUID: "abc123"}} 519 fakeCloudControllerClient.GetApplicationProcessesReturns( 520 processes, 521 ccv3.Warnings{"get-app-warning-1"}, nil) 522 }) 523 524 When("the polling times out", func() { 525 BeforeEach(func() { 526 fakeConfig.StartupTimeoutReturns(time.Millisecond) 527 fakeConfig.PollingIntervalReturns(time.Millisecond * 2) 528 fakeCloudControllerClient.GetProcessInstancesReturns( 529 []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, 530 ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"}, 531 nil, 532 ) 533 }) 534 535 It("returns the timeout error", func() { 536 Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) 537 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2")) 538 }) 539 540 It("gets polling and timeout values from the config", func() { 541 Expect(fakeConfig.StartupTimeoutCallCount()).To(Equal(1)) 542 Expect(fakeConfig.PollingIntervalCallCount()).To(Equal(1)) 543 }) 544 }) 545 546 When("getting the process instances errors", func() { 547 BeforeEach(func() { 548 fakeCloudControllerClient.GetProcessInstancesReturns( 549 nil, 550 ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"}, 551 errors.New("some-error"), 552 ) 553 }) 554 555 It("returns the error", func() { 556 Expect(executeErr).To(MatchError("some-error")) 557 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2")) 558 }) 559 }) 560 561 When("getting the process instances succeeds", func() { 562 var ( 563 initialInstanceStates []ccv3.ProcessInstance 564 eventualInstanceStates []ccv3.ProcessInstance 565 processInstanceCallCount int 566 ) 567 568 BeforeEach(func() { 569 processInstanceCallCount = 0 570 571 fakeCloudControllerClient.GetProcessInstancesStub = func(processGuid string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) { 572 defer func() { processInstanceCallCount++ }() 573 if processInstanceCallCount == 0 { 574 return initialInstanceStates, 575 ccv3.Warnings{"get-process-warning-1", "get-process-warning-2"}, 576 nil 577 } else { 578 return eventualInstanceStates, 579 ccv3.Warnings{fmt.Sprintf("get-process-warning-%d", processInstanceCallCount+2)}, 580 nil 581 } 582 } 583 }) 584 585 When("there are no process instances", func() { 586 BeforeEach(func() { 587 initialInstanceStates = []ccv3.ProcessInstance{} 588 eventualInstanceStates = []ccv3.ProcessInstance{} 589 }) 590 591 It("should not return an error", func() { 592 Expect(executeErr).NotTo(HaveOccurred()) 593 }) 594 595 It("should only call GetProcessInstances once before exiting", func() { 596 Expect(processInstanceCallCount).To(Equal(1)) 597 }) 598 599 It("should return correct warnings", func() { 600 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2")) 601 }) 602 }) 603 604 When("all instances become running by the second call", func() { 605 BeforeEach(func() { 606 initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}} 607 eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}, {State: constant.ProcessInstanceRunning}} 608 }) 609 610 It("should not return an error", func() { 611 Expect(executeErr).NotTo(HaveOccurred()) 612 }) 613 614 It("should call GetProcessInstances twice", func() { 615 Expect(processInstanceCallCount).To(Equal(2)) 616 }) 617 618 It("should return correct warnings", func() { 619 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3")) 620 }) 621 }) 622 623 When("at least one instance has become running by the second call", func() { 624 BeforeEach(func() { 625 initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}} 626 eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceRunning}} 627 }) 628 629 It("should not return an error", func() { 630 Expect(executeErr).NotTo(HaveOccurred()) 631 }) 632 633 It("should call GetProcessInstances twice", func() { 634 Expect(processInstanceCallCount).To(Equal(2)) 635 }) 636 637 It("should return correct warnings", func() { 638 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3")) 639 }) 640 }) 641 642 When("all of the instances have crashed by the second call", func() { 643 BeforeEach(func() { 644 initialInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}, {State: constant.ProcessInstanceStarting}} 645 eventualInstanceStates = []ccv3.ProcessInstance{{State: constant.ProcessInstanceCrashed}, {State: constant.ProcessInstanceCrashed}, {State: constant.ProcessInstanceCrashed}} 646 }) 647 648 It("should not return an error", func() { 649 Expect(executeErr).To(MatchError(actionerror.AllInstancesCrashedError{})) 650 }) 651 652 It("should call GetProcessInstances twice", func() { 653 Expect(processInstanceCallCount).To(Equal(2)) 654 }) 655 656 It("should return correct warnings", func() { 657 Expect(warnings).To(ConsistOf("get-app-warning-1", "get-process-warning-1", "get-process-warning-2", "get-process-warning-3")) 658 }) 659 }) 660 }) 661 }) 662 663 Context("where there are multiple processes", func() { 664 var ( 665 processInstanceCallCount int 666 ) 667 668 BeforeEach(func() { 669 processInstanceCallCount = 0 670 fakeConfig.StartupTimeoutReturns(time.Millisecond) 671 fakeConfig.PollingIntervalReturns(time.Millisecond * 2) 672 673 fakeCloudControllerClient.GetProcessInstancesStub = func(processGuid string) ([]ccv3.ProcessInstance, ccv3.Warnings, error) { 674 defer func() { processInstanceCallCount++ }() 675 if strings.HasPrefix(processGuid, "good") { 676 return []ccv3.ProcessInstance{{State: constant.ProcessInstanceRunning}}, nil, nil 677 } else { 678 return []ccv3.ProcessInstance{{State: constant.ProcessInstanceStarting}}, nil, nil 679 } 680 } 681 }) 682 683 When("none of the processes are ready", func() { 684 BeforeEach(func() { 685 processes = []ccv3.Process{{GUID: "bad-1"}, {GUID: "bad-2"}} 686 fakeCloudControllerClient.GetApplicationProcessesReturns( 687 processes, 688 ccv3.Warnings{"get-app-warning-1"}, nil) 689 }) 690 691 It("returns the timeout error", func() { 692 Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) 693 }) 694 }) 695 696 When("some of the processes are ready", func() { 697 BeforeEach(func() { 698 processes = []ccv3.Process{{GUID: "bad-1"}, {GUID: "good-1"}} 699 fakeCloudControllerClient.GetApplicationProcessesReturns( 700 processes, 701 ccv3.Warnings{"get-app-warning-1"}, nil) 702 }) 703 704 It("returns the timeout error", func() { 705 Expect(executeErr).To(MatchError(actionerror.StartupTimeoutError{})) 706 }) 707 }) 708 709 When("all of the processes are ready", func() { 710 BeforeEach(func() { 711 processes = []ccv3.Process{{GUID: "good-1"}, {GUID: "good-2"}} 712 fakeCloudControllerClient.GetApplicationProcessesReturns( 713 processes, 714 ccv3.Warnings{"get-app-warning-1"}, nil) 715 }) 716 717 It("returns nil", func() { 718 Expect(executeErr).ToNot(HaveOccurred()) 719 }) 720 }) 721 }) 722 }) 723 }) 724 725 Describe("SetApplicationProcessHealthCheckTypeByNameAndSpace", func() { 726 var ( 727 healthCheckType constant.HealthCheckType 728 healthCheckEndpoint string 729 730 warnings Warnings 731 err error 732 app Application 733 ) 734 735 BeforeEach(func() { 736 healthCheckType = constant.HTTP 737 healthCheckEndpoint = "some-http-endpoint" 738 }) 739 740 JustBeforeEach(func() { 741 app, warnings, err = actor.SetApplicationProcessHealthCheckTypeByNameAndSpace( 742 "some-app-name", 743 "some-space-guid", 744 healthCheckType, 745 healthCheckEndpoint, 746 "some-process-type", 747 42, 748 ) 749 }) 750 751 When("getting application returns an error", func() { 752 var expectedErr error 753 754 BeforeEach(func() { 755 expectedErr = errors.New("some-error") 756 fakeCloudControllerClient.GetApplicationsReturns( 757 []ccv3.Application{}, 758 ccv3.Warnings{"some-warning"}, 759 expectedErr, 760 ) 761 }) 762 763 It("returns the error and warnings", func() { 764 Expect(err).To(Equal(expectedErr)) 765 Expect(warnings).To(ConsistOf("some-warning")) 766 }) 767 }) 768 769 When("application exists", func() { 770 var ccv3App ccv3.Application 771 772 BeforeEach(func() { 773 ccv3App = ccv3.Application{ 774 GUID: "some-app-guid", 775 } 776 777 fakeCloudControllerClient.GetApplicationsReturns( 778 []ccv3.Application{ccv3App}, 779 ccv3.Warnings{"some-warning"}, 780 nil, 781 ) 782 }) 783 784 When("setting the health check returns an error", func() { 785 var expectedErr error 786 787 BeforeEach(func() { 788 expectedErr = errors.New("some-error") 789 fakeCloudControllerClient.GetApplicationProcessByTypeReturns( 790 ccv3.Process{}, 791 ccv3.Warnings{"some-process-warning"}, 792 expectedErr, 793 ) 794 }) 795 796 It("returns the error and warnings", func() { 797 Expect(err).To(Equal(expectedErr)) 798 Expect(warnings).To(ConsistOf("some-warning", "some-process-warning")) 799 }) 800 }) 801 802 When("application process exists", func() { 803 BeforeEach(func() { 804 fakeCloudControllerClient.GetApplicationProcessByTypeReturns( 805 ccv3.Process{ 806 GUID: "some-process-guid", 807 }, 808 ccv3.Warnings{"some-process-warning"}, 809 nil, 810 ) 811 812 fakeCloudControllerClient.UpdateProcessReturns( 813 ccv3.Process{GUID: "some-process-guid"}, 814 ccv3.Warnings{"some-health-check-warning"}, 815 nil, 816 ) 817 }) 818 819 It("returns the application", func() { 820 Expect(err).NotTo(HaveOccurred()) 821 Expect(warnings).To(ConsistOf("some-warning", "some-process-warning", "some-health-check-warning")) 822 823 Expect(app).To(Equal(Application{ 824 GUID: ccv3App.GUID, 825 })) 826 827 Expect(fakeCloudControllerClient.GetApplicationProcessByTypeCallCount()).To(Equal(1)) 828 appGUID, processType := fakeCloudControllerClient.GetApplicationProcessByTypeArgsForCall(0) 829 Expect(appGUID).To(Equal("some-app-guid")) 830 Expect(processType).To(Equal("some-process-type")) 831 832 Expect(fakeCloudControllerClient.UpdateProcessCallCount()).To(Equal(1)) 833 process := fakeCloudControllerClient.UpdateProcessArgsForCall(0) 834 Expect(process.GUID).To(Equal("some-process-guid")) 835 Expect(process.HealthCheckType).To(Equal(constant.HTTP)) 836 Expect(process.HealthCheckEndpoint).To(Equal("some-http-endpoint")) 837 Expect(process.HealthCheckInvocationTimeout).To(BeEquivalentTo(42)) 838 }) 839 }) 840 }) 841 }) 842 843 Describe("StopApplication", func() { 844 var ( 845 warnings Warnings 846 executeErr error 847 ) 848 849 JustBeforeEach(func() { 850 warnings, executeErr = actor.StopApplication("some-app-guid") 851 }) 852 853 When("there are no client errors", func() { 854 BeforeEach(func() { 855 fakeCloudControllerClient.UpdateApplicationStopReturns( 856 ccv3.Application{GUID: "some-app-guid"}, 857 ccv3.Warnings{"stop-application-warning"}, 858 nil, 859 ) 860 }) 861 862 It("stops the application", func() { 863 Expect(executeErr).ToNot(HaveOccurred()) 864 Expect(warnings).To(ConsistOf("stop-application-warning")) 865 866 Expect(fakeCloudControllerClient.UpdateApplicationStopCallCount()).To(Equal(1)) 867 Expect(fakeCloudControllerClient.UpdateApplicationStopArgsForCall(0)).To(Equal("some-app-guid")) 868 }) 869 }) 870 871 When("stopping the application fails", func() { 872 var expectedErr error 873 BeforeEach(func() { 874 expectedErr = errors.New("some set stop-application error") 875 fakeCloudControllerClient.UpdateApplicationStopReturns( 876 ccv3.Application{}, 877 ccv3.Warnings{"stop-application-warning"}, 878 expectedErr, 879 ) 880 }) 881 882 It("returns the error", func() { 883 Expect(executeErr).To(Equal(expectedErr)) 884 Expect(warnings).To(ConsistOf("stop-application-warning")) 885 }) 886 }) 887 }) 888 889 Describe("StartApplication", func() { 890 When("there are no client errors", func() { 891 BeforeEach(func() { 892 fakeCloudControllerClient.UpdateApplicationStartReturns( 893 ccv3.Application{GUID: "some-app-guid"}, 894 ccv3.Warnings{"start-application-warning"}, 895 nil, 896 ) 897 }) 898 899 It("starts the application", func() { 900 app, warnings, err := actor.StartApplication("some-app-guid") 901 902 Expect(err).ToNot(HaveOccurred()) 903 Expect(warnings).To(ConsistOf("start-application-warning")) 904 Expect(app).To(Equal(Application{GUID: "some-app-guid"})) 905 906 Expect(fakeCloudControllerClient.UpdateApplicationStartCallCount()).To(Equal(1)) 907 Expect(fakeCloudControllerClient.UpdateApplicationStartArgsForCall(0)).To(Equal("some-app-guid")) 908 }) 909 }) 910 911 When("starting the application fails", func() { 912 var expectedErr error 913 BeforeEach(func() { 914 expectedErr = errors.New("some set start-application error") 915 fakeCloudControllerClient.UpdateApplicationStartReturns( 916 ccv3.Application{}, 917 ccv3.Warnings{"start-application-warning"}, 918 expectedErr, 919 ) 920 }) 921 922 It("returns the error", func() { 923 _, warnings, err := actor.StartApplication("some-app-guid") 924 925 Expect(err).To(Equal(expectedErr)) 926 Expect(warnings).To(ConsistOf("start-application-warning")) 927 }) 928 }) 929 }) 930 931 Describe("RestartApplication", func() { 932 var ( 933 warnings Warnings 934 executeErr error 935 ) 936 937 BeforeEach(func() { 938 fakeConfig.StartupTimeoutReturns(time.Second) 939 fakeConfig.PollingIntervalReturns(0) 940 }) 941 942 JustBeforeEach(func() { 943 warnings, executeErr = actor.RestartApplication("some-app-guid") 944 }) 945 946 When("restarting the application is successful", func() { 947 BeforeEach(func() { 948 fakeCloudControllerClient.UpdateApplicationRestartReturns( 949 ccv3.Application{GUID: "some-app-guid"}, 950 ccv3.Warnings{"restart-application-warning"}, 951 nil, 952 ) 953 }) 954 955 When("polling the application start is successful", func() { 956 BeforeEach(func() { 957 processes := []ccv3.Process{{GUID: "some-process-guid"}} 958 fakeCloudControllerClient.GetApplicationProcessesReturns(processes, ccv3.Warnings{"get-process-warnings"}, nil) 959 fakeCloudControllerClient.GetProcessInstancesReturns(nil, ccv3.Warnings{"some-process-instance-warnings"}, nil) 960 }) 961 962 It("returns all the warnings", func() { 963 Expect(executeErr).ToNot(HaveOccurred()) 964 Expect(warnings).To(ConsistOf("restart-application-warning", "get-process-warnings", "some-process-instance-warnings")) 965 }) 966 967 It("calls restart", func() { 968 Expect(fakeCloudControllerClient.UpdateApplicationRestartCallCount()).To(Equal(1)) 969 Expect(fakeCloudControllerClient.UpdateApplicationRestartArgsForCall(0)).To(Equal("some-app-guid")) 970 }) 971 972 It("polls for the application's process to start", func() { 973 Expect(fakeCloudControllerClient.GetApplicationProcessesCallCount()).To(Equal(1)) 974 Expect(fakeCloudControllerClient.GetApplicationProcessesArgsForCall(0)).To(Equal("some-app-guid")) 975 976 Expect(fakeCloudControllerClient.GetProcessInstancesCallCount()).To(Equal(1)) 977 Expect(fakeCloudControllerClient.GetProcessInstancesArgsForCall(0)).To(Equal("some-process-guid")) 978 }) 979 }) 980 981 When("polling the application start errors", func() { 982 var expectedErr error 983 BeforeEach(func() { 984 expectedErr = errors.New("some polling error") 985 fakeCloudControllerClient.GetApplicationProcessesReturns(nil, ccv3.Warnings{"get-process-warnings"}, expectedErr) 986 }) 987 988 It("returns the warnings and error", func() { 989 Expect(executeErr).To(Equal(expectedErr)) 990 Expect(warnings).To(ConsistOf("restart-application-warning", "get-process-warnings")) 991 }) 992 }) 993 }) 994 995 When("restarting the application fails", func() { 996 var expectedErr error 997 BeforeEach(func() { 998 expectedErr = errors.New("some set restart-application error") 999 fakeCloudControllerClient.UpdateApplicationRestartReturns( 1000 ccv3.Application{}, 1001 ccv3.Warnings{"restart-application-warning"}, 1002 expectedErr, 1003 ) 1004 }) 1005 1006 It("returns the warnings and error", func() { 1007 Expect(executeErr).To(Equal(expectedErr)) 1008 Expect(warnings).To(ConsistOf("restart-application-warning")) 1009 }) 1010 }) 1011 }) 1012 })