github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/v6/v3_push_original_command_test.go (about) 1 package v6_test 2 3 import ( 4 "errors" 5 "time" 6 7 "code.cloudfoundry.org/cli/actor/actionerror" 8 "code.cloudfoundry.org/cli/actor/pushaction" 9 "code.cloudfoundry.org/cli/actor/v2action" 10 "code.cloudfoundry.org/cli/actor/v3action" 11 "code.cloudfoundry.org/cli/actor/v3action/v3actionfakes" 12 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 13 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 14 "code.cloudfoundry.org/cli/command/commandfakes" 15 "code.cloudfoundry.org/cli/command/flag" 16 "code.cloudfoundry.org/cli/command/translatableerror" 17 . "code.cloudfoundry.org/cli/command/v6" 18 "code.cloudfoundry.org/cli/command/v6/shared" 19 "code.cloudfoundry.org/cli/command/v6/shared/sharedfakes" 20 "code.cloudfoundry.org/cli/command/v6/v6fakes" 21 "code.cloudfoundry.org/cli/types" 22 "code.cloudfoundry.org/cli/util/configv3" 23 "code.cloudfoundry.org/cli/util/ui" 24 . "github.com/onsi/ginkgo" 25 . "github.com/onsi/ginkgo/extensions/table" 26 . "github.com/onsi/gomega" 27 . "github.com/onsi/gomega/gbytes" 28 ) 29 30 var _ = Describe("v3-push Command", func() { 31 var ( 32 cmd V3PushCommand 33 testUI *ui.UI 34 fakeConfig *commandfakes.FakeConfig 35 fakeSharedActor *commandfakes.FakeSharedActor 36 fakeNOAAClient *v3actionfakes.FakeNOAAClient 37 fakeActor *v6fakes.FakeOriginalV3PushActor 38 fakeV2PushActor *v6fakes.FakeOriginalV2PushActor 39 fakeV2AppActor *sharedfakes.FakeV2AppActor 40 binaryName string 41 executeErr error 42 app string 43 userName string 44 spaceName string 45 orgName string 46 ) 47 48 BeforeEach(func() { 49 testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer()) 50 fakeConfig = new(commandfakes.FakeConfig) 51 fakeSharedActor = new(commandfakes.FakeSharedActor) 52 fakeActor = new(v6fakes.FakeOriginalV3PushActor) 53 fakeV2PushActor = new(v6fakes.FakeOriginalV2PushActor) 54 fakeV2AppActor = new(sharedfakes.FakeV2AppActor) 55 fakeNOAAClient = new(v3actionfakes.FakeNOAAClient) 56 57 fakeConfig.StagingTimeoutReturns(10 * time.Minute) 58 59 binaryName = "faceman" 60 fakeConfig.BinaryNameReturns(binaryName) 61 app = "some-app" 62 userName = "banana" 63 spaceName = "some-space" 64 orgName = "some-org" 65 66 appSummaryDisplayer := shared.AppSummaryDisplayer{ 67 UI: testUI, 68 Config: fakeConfig, 69 Actor: fakeActor, 70 V2AppActor: fakeV2AppActor, 71 AppName: app, 72 } 73 packageDisplayer := shared.NewPackageDisplayer( 74 testUI, 75 fakeConfig, 76 ) 77 78 cmd = V3PushCommand{ 79 RequiredArgs: flag.AppName{AppName: app}, 80 81 UI: testUI, 82 Config: fakeConfig, 83 SharedActor: fakeSharedActor, 84 OriginalActor: fakeActor, 85 OriginalV2PushActor: fakeV2PushActor, 86 87 NOAAClient: fakeNOAAClient, 88 AppSummaryDisplayer: appSummaryDisplayer, 89 PackageDisplayer: packageDisplayer, 90 } 91 92 // we stub out StagePackage out here so the happy paths below don't hang 93 fakeActor.StagePackageStub = func(_ string, _ string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) { 94 dropletStream := make(chan v3action.Droplet) 95 warningsStream := make(chan v3action.Warnings) 96 errorStream := make(chan error) 97 98 go func() { 99 defer close(dropletStream) 100 defer close(warningsStream) 101 defer close(errorStream) 102 }() 103 104 return dropletStream, warningsStream, errorStream 105 } 106 }) 107 108 JustBeforeEach(func() { 109 executeErr = cmd.Execute(nil) 110 }) 111 112 When("the API version is below the minimum", func() { 113 BeforeEach(func() { 114 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinV3ClientVersion) 115 }) 116 117 It("returns a MinimumAPIVersionNotMetError", func() { 118 Expect(executeErr).To(MatchError(translatableerror.MinimumCFAPIVersionNotMetError{ 119 CurrentVersion: ccversion.MinV3ClientVersion, 120 MinimumVersion: ccversion.MinVersionApplicationFlowV3, 121 })) 122 }) 123 124 It("displays the experimental warning", func() { 125 Expect(testUI.Err).To(Say("This command is in EXPERIMENTAL stage and may change without notice")) 126 }) 127 }) 128 129 DescribeTable("argument combinations", 130 func(dockerImage string, dockerUsername string, dockerPassword string, 131 buildpacks []string, appPath string, 132 expectedErr error) { 133 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionApplicationFlowV3) 134 135 cmd.DockerImage.Path = dockerImage 136 cmd.DockerUsername = dockerUsername 137 fakeConfig.DockerPasswordReturns(dockerPassword) 138 cmd.Buildpacks = buildpacks 139 cmd.AppPath = flag.PathWithExistenceCheck(appPath) 140 Expect(cmd.Execute(nil)).To(MatchError(expectedErr)) 141 }, 142 Entry("docker username", 143 "", "some-docker-username", "", []string{}, "", 144 translatableerror.RequiredFlagsError{ 145 Arg1: "--docker-image, -o", 146 Arg2: "--docker-username", 147 }), 148 Entry("docker username, password", 149 "", "some-docker-username", "my-password", []string{}, "", 150 translatableerror.RequiredFlagsError{ 151 Arg1: "--docker-image, -o", 152 Arg2: "--docker-username", 153 }), 154 Entry("docker username, app path", 155 "", "some-docker-username", "", []string{}, "some/app/path", 156 translatableerror.RequiredFlagsError{ 157 Arg1: "--docker-image, -o", 158 Arg2: "--docker-username", 159 }), 160 Entry("docker username, buildpacks", 161 "", "some-docker-username", "", []string{"ruby_buildpack"}, "", 162 translatableerror.RequiredFlagsError{ 163 Arg1: "--docker-image, -o", 164 Arg2: "--docker-username", 165 }), 166 Entry("docker image, docker username", 167 "some-docker-image", "some-docker-username", "", []string{}, "", 168 translatableerror.DockerPasswordNotSetError{}), 169 Entry("docker image, app path", 170 "some-docker-image", "", "", []string{}, "some/app/path", 171 translatableerror.ArgumentCombinationError{ 172 Args: []string{"--docker-image", "-o", "-p"}, 173 }), 174 Entry("docker image, buildpacks", 175 "some-docker-image", "", "", []string{"ruby_buildpack"}, "", 176 translatableerror.ArgumentCombinationError{ 177 Args: []string{"-b", "--docker-image", "-o"}, 178 }), 179 ) 180 181 When("checking target fails", func() { 182 BeforeEach(func() { 183 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionApplicationFlowV3) 184 fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName}) 185 }) 186 187 It("returns an error", func() { 188 Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName})) 189 190 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 191 checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 192 Expect(checkTargetedOrg).To(BeTrue()) 193 Expect(checkTargetedSpace).To(BeTrue()) 194 }) 195 }) 196 197 When("the user is logged in", func() { 198 BeforeEach(func() { 199 fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionApplicationFlowV3) 200 fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil) 201 fakeConfig.TargetedSpaceReturns(configv3.Space{Name: spaceName, GUID: "some-space-guid"}) 202 fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: orgName, GUID: "some-org-guid"}) 203 }) 204 205 When("looking up the application returns some api error", func() { 206 BeforeEach(func() { 207 fakeActor.GetApplicationByNameAndSpaceReturns(v3action.Application{}, v3action.Warnings{"get-warning"}, errors.New("some-error")) 208 }) 209 210 It("returns the error and displays all warnings", func() { 211 Expect(executeErr).To(MatchError("some-error")) 212 213 Expect(testUI.Err).To(Say("get-warning")) 214 }) 215 }) 216 217 When("the application doesn't exist", func() { 218 It("doesn't stop the application", func() { 219 Expect(fakeActor.StopApplicationCallCount()).To(Equal(0)) 220 }) 221 222 BeforeEach(func() { 223 fakeActor.GetApplicationByNameAndSpaceReturns(v3action.Application{}, v3action.Warnings{"get-warning"}, actionerror.ApplicationNotFoundError{Name: "some-app"}) 224 }) 225 226 When("creating the application returns an error", func() { 227 var expectedErr error 228 229 BeforeEach(func() { 230 expectedErr = errors.New("I am an error") 231 fakeActor.CreateApplicationInSpaceReturns(v3action.Application{}, v3action.Warnings{"I am a warning", "I am also a warning"}, expectedErr) 232 }) 233 234 It("displays the warnings and error", func() { 235 Expect(executeErr).To(MatchError(expectedErr)) 236 237 Expect(testUI.Err).To(Say("I am a warning")) 238 Expect(testUI.Err).To(Say("I am also a warning")) 239 Expect(testUI.Out).ToNot(Say("app some-app in org some-org / space some-space as banana...")) 240 }) 241 }) 242 243 When("creating the application does not error", func() { 244 BeforeEach(func() { 245 fakeActor.CreateApplicationInSpaceReturns(v3action.Application{Name: "some-app", GUID: "some-app-guid"}, v3action.Warnings{"I am a warning", "I am also a warning"}, nil) 246 }) 247 248 It("calls CreateApplication", func() { 249 Expect(fakeActor.CreateApplicationInSpaceCallCount()).To(Equal(1), "Expected CreateApplicationInSpace to be called once") 250 createApp, createSpaceGUID := fakeActor.CreateApplicationInSpaceArgsForCall(0) 251 Expect(createApp).To(Equal(v3action.Application{ 252 Name: "some-app", 253 LifecycleType: constant.AppLifecycleTypeBuildpack, 254 })) 255 Expect(createSpaceGUID).To(Equal("some-space-guid")) 256 }) 257 258 When("creating the package fails", func() { 259 var expectedErr error 260 261 BeforeEach(func() { 262 expectedErr = errors.New("I am an error") 263 fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceReturns(v3action.Package{}, v3action.Warnings{"I am a package warning", "I am also a package warning"}, expectedErr) 264 }) 265 266 It("displays the header and error", func() { 267 Expect(executeErr).To(MatchError(expectedErr)) 268 269 Expect(testUI.Out).To(Say("Uploading and creating bits package for app some-app in org some-org / space some-space as banana...")) 270 271 Expect(testUI.Err).To(Say("I am a package warning")) 272 Expect(testUI.Err).To(Say("I am also a package warning")) 273 274 Expect(testUI.Out).ToNot(Say("Staging package for %s in org some-org / space some-space as banana...", app)) 275 }) 276 }) 277 278 When("creating the package succeeds", func() { 279 BeforeEach(func() { 280 fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceReturns(v3action.Package{GUID: "some-guid"}, v3action.Warnings{"I am a package warning", "I am also a package warning"}, nil) 281 }) 282 283 When("the -p flag is provided", func() { 284 BeforeEach(func() { 285 cmd.AppPath = "some-app-path" 286 }) 287 288 It("creates the package with the provided path", func() { 289 Expect(testUI.Out).To(Say("Uploading and creating bits package for app %s in org %s / space %s as %s", app, orgName, spaceName, userName)) 290 Expect(testUI.Err).To(Say("I am a package warning")) 291 Expect(testUI.Err).To(Say("I am also a package warning")) 292 Expect(testUI.Out).To(Say("OK")) 293 Expect(testUI.Out).To(Say("Staging package for app %s in org some-org / space some-space as banana...", app)) 294 295 Expect(fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceCallCount()).To(Equal(1)) 296 _, _, appPath := fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceArgsForCall(0) 297 298 Expect(appPath).To(Equal("some-app-path")) 299 }) 300 }) 301 302 When("the -o flag is provided", func() { 303 BeforeEach(func() { 304 cmd.DockerImage.Path = "example.com/docker/docker/docker:docker" 305 fakeActor.CreateDockerPackageByApplicationNameAndSpaceReturns(v3action.Package{GUID: "some-guid"}, v3action.Warnings{"I am a docker package warning", "I am also a docker package warning"}, nil) 306 }) 307 308 It("creates a docker package with the provided image path", func() { 309 310 Expect(testUI.Out).To(Say("Creating docker package for app %s in org %s / space %s as %s", app, orgName, spaceName, userName)) 311 Expect(testUI.Err).To(Say("I am a docker package warning")) 312 Expect(testUI.Err).To(Say("I am also a docker package warning")) 313 Expect(testUI.Out).To(Say("OK")) 314 Expect(testUI.Out).To(Say("Staging package for app %s in org some-org / space some-space as banana...", app)) 315 316 Expect(fakeActor.CreateDockerPackageByApplicationNameAndSpaceCallCount()).To(Equal(1)) 317 _, _, dockerImageCredentials := fakeActor.CreateDockerPackageByApplicationNameAndSpaceArgsForCall(0) 318 319 Expect(dockerImageCredentials.Path).To(Equal("example.com/docker/docker/docker:docker")) 320 }) 321 }) 322 323 When("neither -p nor -o flags are provided", func() { 324 It("calls CreateAndUploadBitsPackageByApplicationNameAndSpace with empty string", func() { 325 Expect(testUI.Out).To(Say("Uploading and creating bits package for app %s in org %s / space %s as %s", app, orgName, spaceName, userName)) 326 327 Expect(fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceCallCount()).To(Equal(1)) 328 _, _, appPath := fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceArgsForCall(0) 329 330 Expect(appPath).To(BeEmpty()) 331 }) 332 }) 333 334 When("getting streaming logs fails", func() { 335 var expectedErr error 336 BeforeEach(func() { 337 expectedErr = errors.New("something is wrong!") 338 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceReturns(nil, nil, v3action.Warnings{"some-logging-warning", "some-other-logging-warning"}, expectedErr) 339 }) 340 341 It("returns the error and displays warnings", func() { 342 Expect(executeErr).To(Equal(expectedErr)) 343 344 Expect(testUI.Out).To(Say("Staging package for app %s in org some-org / space some-space as banana...", app)) 345 346 Expect(testUI.Err).To(Say("some-logging-warning")) 347 Expect(testUI.Err).To(Say("some-other-logging-warning")) 348 349 }) 350 }) 351 352 When("--no-start is provided", func() { 353 BeforeEach(func() { 354 cmd.NoStart = true 355 }) 356 357 It("does not stage the package and returns", func() { 358 Expect(testUI.Out).To(Say("Uploading and creating bits package for app %s in org %s / space %s as %s", app, orgName, spaceName, userName)) 359 Expect(fakeActor.CreateAndUploadBitsPackageByApplicationNameAndSpaceCallCount()).To(Equal(1)) 360 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(0)) 361 362 Expect(executeErr).ToNot(HaveOccurred()) 363 }) 364 }) 365 366 When("the logging does not error", func() { 367 var allLogsWritten chan bool 368 369 BeforeEach(func() { 370 allLogsWritten = make(chan bool) 371 fakeActor.GetStreamingLogsForApplicationByNameAndSpaceStub = func(appName string, spaceGUID string, client v3action.NOAAClient) (<-chan *v3action.LogMessage, <-chan error, v3action.Warnings, error) { 372 logStream := make(chan *v3action.LogMessage) 373 errorStream := make(chan error) 374 375 go func() { 376 logStream <- v3action.NewLogMessage("Here are some staging logs!", 1, time.Now(), v3action.StagingLog, "sourceInstance") 377 logStream <- v3action.NewLogMessage("Here are some other staging logs!", 1, time.Now(), v3action.StagingLog, "sourceInstance") 378 logStream <- v3action.NewLogMessage("not from staging", 1, time.Now(), "potato", "sourceInstance") 379 allLogsWritten <- true 380 }() 381 382 return logStream, errorStream, v3action.Warnings{"steve for all I care"}, nil 383 } 384 }) 385 386 When("the staging returns an error", func() { 387 var expectedErr error 388 389 BeforeEach(func() { 390 expectedErr = errors.New("any gibberish") 391 fakeActor.StagePackageStub = func(packageGUID string, _ string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) { 392 dropletStream := make(chan v3action.Droplet) 393 warningsStream := make(chan v3action.Warnings) 394 errorStream := make(chan error) 395 396 go func() { 397 <-allLogsWritten 398 defer close(dropletStream) 399 defer close(warningsStream) 400 defer close(errorStream) 401 warningsStream <- v3action.Warnings{"some-staging-warning", "some-other-staging-warning"} 402 errorStream <- expectedErr 403 }() 404 405 return dropletStream, warningsStream, errorStream 406 } 407 }) 408 409 It("returns the error and displays warnings", func() { 410 Expect(executeErr).To(Equal(expectedErr)) 411 412 Expect(testUI.Out).To(Say("Staging package for app %s in org some-org / space some-space as banana...", app)) 413 414 Expect(testUI.Err).To(Say("some-staging-warning")) 415 Expect(testUI.Err).To(Say("some-other-staging-warning")) 416 417 Expect(testUI.Out).ToNot(Say("Setting app some-app to droplet some-droplet-guid in org some-org / space some-space as banana...")) 418 }) 419 }) 420 421 When("the staging is successful", func() { 422 BeforeEach(func() { 423 fakeActor.StagePackageStub = func(packageGUID string, _ string) (<-chan v3action.Droplet, <-chan v3action.Warnings, <-chan error) { 424 dropletStream := make(chan v3action.Droplet) 425 warningsStream := make(chan v3action.Warnings) 426 errorStream := make(chan error) 427 428 go func() { 429 <-allLogsWritten 430 defer close(dropletStream) 431 defer close(warningsStream) 432 defer close(errorStream) 433 warningsStream <- v3action.Warnings{"some-staging-warning", "some-other-staging-warning"} 434 dropletStream <- v3action.Droplet{GUID: "some-droplet-guid"} 435 }() 436 437 return dropletStream, warningsStream, errorStream 438 } 439 }) 440 441 It("outputs the staging message and warnings", func() { 442 Expect(executeErr).ToNot(HaveOccurred()) 443 444 Expect(testUI.Out).To(Say("Staging package for app %s in org some-org / space some-space as banana...", app)) 445 Expect(testUI.Out).To(Say("OK")) 446 447 Expect(testUI.Err).To(Say("some-staging-warning")) 448 Expect(testUI.Err).To(Say("some-other-staging-warning")) 449 }) 450 451 It("stages the package", func() { 452 Expect(executeErr).ToNot(HaveOccurred()) 453 Expect(fakeActor.StagePackageCallCount()).To(Equal(1)) 454 guidArg, _ := fakeActor.StagePackageArgsForCall(0) 455 Expect(guidArg).To(Equal("some-guid")) 456 }) 457 458 It("displays staging logs and their warnings", func() { 459 Expect(testUI.Out).To(Say("Here are some staging logs!")) 460 Expect(testUI.Out).To(Say("Here are some other staging logs!")) 461 Expect(testUI.Out).ToNot(Say("not from staging")) 462 463 Expect(testUI.Err).To(Say("steve for all I care")) 464 465 Expect(fakeActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 466 appName, spaceGUID, noaaClient := fakeActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0) 467 Expect(appName).To(Equal(app)) 468 Expect(spaceGUID).To(Equal("some-space-guid")) 469 Expect(noaaClient).To(Equal(fakeNOAAClient)) 470 471 guidArg, _ := fakeActor.StagePackageArgsForCall(0) 472 Expect(guidArg).To(Equal("some-guid")) 473 }) 474 475 When("setting the droplet fails", func() { 476 BeforeEach(func() { 477 fakeActor.SetApplicationDropletByApplicationNameAndSpaceReturns(v3action.Warnings{"droplet-warning-1", "droplet-warning-2"}, errors.New("some-error")) 478 }) 479 480 It("returns the error", func() { 481 Expect(executeErr).To(Equal(errors.New("some-error"))) 482 483 Expect(testUI.Out).To(Say("Setting app some-app to droplet some-droplet-guid in org some-org / space some-space as banana...")) 484 485 Expect(testUI.Err).To(Say("droplet-warning-1")) 486 Expect(testUI.Err).To(Say("droplet-warning-2")) 487 488 Expect(testUI.Out).ToNot(Say(`Starting app some-app in org some-org / space some-space as banana\.\.\.`)) 489 }) 490 }) 491 492 When("setting the application droplet is successful", func() { 493 BeforeEach(func() { 494 fakeActor.SetApplicationDropletByApplicationNameAndSpaceReturns(v3action.Warnings{"droplet-warning-1", "droplet-warning-2"}, nil) 495 }) 496 497 It("displays that the droplet was assigned", func() { 498 Expect(testUI.Out).To(Say("Staging package for app %s in org some-org / space some-space as banana...", app)) 499 Expect(testUI.Out).To(Say("OK")) 500 501 Expect(testUI.Out).ToNot(Say("Stopping .*")) 502 503 Expect(testUI.Out).To(Say("Setting app some-app to droplet some-droplet-guid in org some-org / space some-space as banana...")) 504 505 Expect(testUI.Err).To(Say("droplet-warning-1")) 506 Expect(testUI.Err).To(Say("droplet-warning-2")) 507 Expect(testUI.Out).To(Say("OK")) 508 509 Expect(fakeActor.SetApplicationDropletByApplicationNameAndSpaceCallCount()).To(Equal(1)) 510 appName, spaceGUID, dropletGUID := fakeActor.SetApplicationDropletByApplicationNameAndSpaceArgsForCall(0) 511 Expect(appName).To(Equal("some-app")) 512 Expect(spaceGUID).To(Equal("some-space-guid")) 513 Expect(dropletGUID).To(Equal("some-droplet-guid")) 514 }) 515 516 When("--no-route flag is set to true", func() { 517 BeforeEach(func() { 518 cmd.NoRoute = true 519 }) 520 521 It("does not create any routes", func() { 522 Expect(fakeV2PushActor.CreateAndMapDefaultApplicationRouteCallCount()).To(Equal(0)) 523 524 Expect(fakeActor.StartApplicationCallCount()).To(Equal(1)) 525 }) 526 }) 527 528 When("buildpack(s) are provided via -b flag", func() { 529 BeforeEach(func() { 530 cmd.Buildpacks = []string{"some-buildpack"} 531 }) 532 533 It("creates the app with the specified buildpack and prints the buildpack name in the summary", func() { 534 Expect(fakeActor.CreateApplicationInSpaceCallCount()).To(Equal(1), "Expected CreateApplicationInSpace to be called once") 535 createApp, createSpaceGUID := fakeActor.CreateApplicationInSpaceArgsForCall(0) 536 Expect(createApp).To(Equal(v3action.Application{ 537 Name: "some-app", 538 LifecycleType: constant.AppLifecycleTypeBuildpack, 539 LifecycleBuildpacks: []string{"some-buildpack"}, 540 })) 541 Expect(createSpaceGUID).To(Equal("some-space-guid")) 542 }) 543 }) 544 545 When("a docker image is specified", func() { 546 BeforeEach(func() { 547 cmd.DockerImage.Path = "example.com/docker/docker/docker:docker" 548 }) 549 550 It("creates the app with a docker lifecycle", func() { 551 Expect(fakeActor.CreateApplicationInSpaceCallCount()).To(Equal(1), "Expected CreateApplicationInSpace to be called once") 552 createApp, createSpaceGUID := fakeActor.CreateApplicationInSpaceArgsForCall(0) 553 Expect(createApp).To(Equal(v3action.Application{ 554 Name: "some-app", 555 LifecycleType: constant.AppLifecycleTypeDocker, 556 })) 557 Expect(createSpaceGUID).To(Equal("some-space-guid")) 558 }) 559 }) 560 561 When("mapping routes fails", func() { 562 BeforeEach(func() { 563 fakeV2PushActor.CreateAndMapDefaultApplicationRouteReturns(pushaction.Warnings{"route-warning"}, errors.New("some-error")) 564 }) 565 566 It("returns the error", func() { 567 Expect(executeErr).To(MatchError("some-error")) 568 Expect(testUI.Out).To(Say(`Mapping routes\.\.\.`)) 569 Expect(testUI.Err).To(Say("route-warning")) 570 571 Expect(fakeActor.StartApplicationCallCount()).To(Equal(0)) 572 }) 573 }) 574 575 When("mapping routes succeeds", func() { 576 BeforeEach(func() { 577 fakeV2PushActor.CreateAndMapDefaultApplicationRouteReturns(pushaction.Warnings{"route-warning"}, nil) 578 }) 579 580 It("displays the header and OK", func() { 581 Expect(testUI.Out).To(Say(`Mapping routes\.\.\.`)) 582 Expect(testUI.Out).To(Say("OK")) 583 584 Expect(testUI.Err).To(Say("route-warning")) 585 586 Expect(fakeV2PushActor.CreateAndMapDefaultApplicationRouteCallCount()).To(Equal(1), "Expected CreateAndMapDefaultApplicationRoute to be called") 587 orgArg, spaceArg, appArg := fakeV2PushActor.CreateAndMapDefaultApplicationRouteArgsForCall(0) 588 Expect(orgArg).To(Equal("some-org-guid")) 589 Expect(spaceArg).To(Equal("some-space-guid")) 590 Expect(appArg).To(Equal(v2action.Application{Name: "some-app", GUID: "some-app-guid"})) 591 592 Expect(fakeActor.StartApplicationCallCount()).To(Equal(1)) 593 }) 594 595 When("starting the application fails", func() { 596 BeforeEach(func() { 597 fakeActor.StartApplicationReturns(v3action.Application{}, v3action.Warnings{"start-warning-1", "start-warning-2"}, errors.New("some-error")) 598 }) 599 600 It("says that the app failed to start", func() { 601 Expect(executeErr).To(Equal(errors.New("some-error"))) 602 Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as banana\.\.\.`)) 603 604 Expect(testUI.Err).To(Say("start-warning-1")) 605 Expect(testUI.Err).To(Say("start-warning-2")) 606 607 Expect(testUI.Out).ToNot(Say(`Showing health and status for app some-app in org some-org / space some-space as banana\.\.\.`)) 608 }) 609 }) 610 611 When("starting the application succeeds", func() { 612 BeforeEach(func() { 613 fakeActor.StartApplicationReturns(v3action.Application{GUID: "some-app-guid"}, v3action.Warnings{"start-warning-1", "start-warning-2"}, nil) 614 }) 615 616 It("says that the app was started and outputs warnings", func() { 617 Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as banana\.\.\.`)) 618 619 Expect(testUI.Err).To(Say("start-warning-1")) 620 Expect(testUI.Err).To(Say("start-warning-2")) 621 Expect(testUI.Out).To(Say("OK")) 622 623 Expect(fakeActor.StartApplicationCallCount()).To(Equal(1)) 624 appGUID := fakeActor.StartApplicationArgsForCall(0) 625 Expect(appGUID).To(Equal("some-app-guid")) 626 }) 627 }) 628 629 When("polling the start fails", func() { 630 BeforeEach(func() { 631 fakeActor.PollStartStub = func(appGUID string, warnings chan<- v3action.Warnings) error { 632 warnings <- v3action.Warnings{"some-poll-warning-1", "some-poll-warning-2"} 633 return errors.New("some-error") 634 } 635 }) 636 637 It("displays all warnings and fails", func() { 638 Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`)) 639 640 Expect(testUI.Err).To(Say("some-poll-warning-1")) 641 Expect(testUI.Err).To(Say("some-poll-warning-2")) 642 643 Expect(executeErr).To(MatchError("some-error")) 644 }) 645 }) 646 647 When("polling times out", func() { 648 BeforeEach(func() { 649 fakeActor.PollStartReturns(actionerror.StartupTimeoutError{}) 650 }) 651 652 It("returns the StartupTimeoutError", func() { 653 Expect(executeErr).To(MatchError(translatableerror.StartupTimeoutError{ 654 AppName: "some-app", 655 BinaryName: binaryName, 656 })) 657 }) 658 }) 659 660 When("polling the start succeeds", func() { 661 BeforeEach(func() { 662 fakeActor.PollStartStub = func(appGUID string, warnings chan<- v3action.Warnings) error { 663 warnings <- v3action.Warnings{"some-poll-warning-1", "some-poll-warning-2"} 664 return nil 665 } 666 }) 667 668 It("displays all warnings", func() { 669 Expect(testUI.Out).To(Say(`Waiting for app to start\.\.\.`)) 670 671 Expect(testUI.Err).To(Say("some-poll-warning-1")) 672 Expect(testUI.Err).To(Say("some-poll-warning-2")) 673 674 Expect(executeErr).ToNot(HaveOccurred()) 675 }) 676 677 When("displaying the application info fails", func() { 678 BeforeEach(func() { 679 var expectedErr error 680 expectedErr = actionerror.ApplicationNotFoundError{Name: app} 681 fakeActor.GetApplicationSummaryByNameAndSpaceReturns(v3action.ApplicationSummary{}, v3action.Warnings{"display-warning-1", "display-warning-2"}, expectedErr) 682 }) 683 684 It("returns the error and prints warnings", func() { 685 Expect(executeErr).To(Equal(actionerror.ApplicationNotFoundError{Name: app})) 686 687 Expect(testUI.Out).To(Say(`Showing health and status for app some-app in org some-org / space some-space as banana\.\.\.`)) 688 689 Expect(testUI.Err).To(Say("display-warning-1")) 690 Expect(testUI.Err).To(Say("display-warning-2")) 691 692 Expect(testUI.Out).ToNot(Say(`name:\s+some-app`)) 693 }) 694 }) 695 696 When("getting the application summary is successful", func() { 697 BeforeEach(func() { 698 summary := v3action.ApplicationSummary{ 699 Application: v3action.Application{ 700 Name: "some-app", 701 GUID: "some-app-guid", 702 State: "started", 703 }, 704 CurrentDroplet: v3action.Droplet{ 705 Stack: "cflinuxfs2", 706 Buildpacks: []v3action.Buildpack{ 707 { 708 Name: "ruby_buildpack", 709 DetectOutput: "some-detect-output", 710 }, 711 }, 712 }, 713 ProcessSummaries: []v3action.ProcessSummary{ 714 { 715 Process: v3action.Process{ 716 Type: "worker", 717 MemoryInMB: types.NullUint64{Value: 64, IsSet: true}, 718 }, 719 InstanceDetails: []v3action.ProcessInstance{ 720 v3action.ProcessInstance{ 721 Index: 0, 722 State: constant.ProcessInstanceRunning, 723 MemoryUsage: 4000000, 724 DiskUsage: 4000000, 725 MemoryQuota: 67108864, 726 DiskQuota: 8000000, 727 Uptime: int(time.Now().Sub(time.Unix(1371859200, 0)).Seconds()), 728 }, 729 }, 730 }, 731 }, 732 } 733 734 fakeActor.GetApplicationSummaryByNameAndSpaceReturns(summary, v3action.Warnings{"display-warning-1", "display-warning-2"}, nil) 735 }) 736 737 When("getting the application routes fails", func() { 738 BeforeEach(func() { 739 fakeV2AppActor.GetApplicationRoutesReturns([]v2action.Route{}, 740 v2action.Warnings{"route-warning-1", "route-warning-2"}, errors.New("some-error")) 741 }) 742 743 It("displays all warnings and returns the error", func() { 744 Expect(executeErr).To(MatchError("some-error")) 745 746 Expect(testUI.Out).To(Say(`Showing health and status for app some-app in org some-org / space some-space as banana\.\.\.`)) 747 748 Expect(testUI.Err).To(Say("display-warning-1")) 749 Expect(testUI.Err).To(Say("display-warning-2")) 750 Expect(testUI.Err).To(Say("route-warning-1")) 751 Expect(testUI.Err).To(Say("route-warning-2")) 752 753 Expect(testUI.Out).ToNot(Say(`name:\s+some-app`)) 754 }) 755 }) 756 757 When("getting the application routes is successful", func() { 758 BeforeEach(func() { 759 fakeV2AppActor.GetApplicationRoutesReturns([]v2action.Route{ 760 {Domain: v2action.Domain{Name: "some-other-domain"}}, { 761 Domain: v2action.Domain{Name: "some-domain"}}}, 762 v2action.Warnings{"route-warning-1", "route-warning-2"}, nil) 763 }) 764 765 It("prints the application summary and outputs warnings", func() { 766 Expect(executeErr).ToNot(HaveOccurred()) 767 768 Expect(testUI.Out).To(Say(`(?m)Showing health and status for app some-app in org some-org / space some-space as banana\.\.\.\n\n`)) 769 Expect(testUI.Out).To(Say(`name:\s+some-app`)) 770 Expect(testUI.Out).To(Say(`requested state:\s+started`)) 771 Expect(testUI.Out).To(Say(`routes:\s+some-other-domain, some-domain`)) 772 Expect(testUI.Out).To(Say(`stack:\s+cflinuxfs2`)) 773 Expect(testUI.Out).To(Say(`(?m)buildpacks:\s+some-detect-output\n\n`)) 774 775 Expect(testUI.Out).To(Say(`type:\s+worker`)) 776 Expect(testUI.Out).To(Say(`instances:\s+1/1`)) 777 Expect(testUI.Out).To(Say(`memory usage:\s+64M`)) 778 Expect(testUI.Out).To(Say(`\s+state\s+since\s+cpu\s+memory\s+disk`)) 779 Expect(testUI.Out).To(Say(`#0\s+running\s+2013-\d{2}-\d{2} \d{2}:\d{2}:\d{2} [AP]M\s+0.0%\s+3.8M of 64M\s+3.8M of 7.6M`)) 780 781 Expect(testUI.Err).To(Say("display-warning-1")) 782 Expect(testUI.Err).To(Say("display-warning-2")) 783 Expect(testUI.Err).To(Say("route-warning-1")) 784 Expect(testUI.Err).To(Say("route-warning-2")) 785 786 Expect(fakeActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1)) 787 appName, spaceGUID, withObfuscatedValues := fakeActor.GetApplicationSummaryByNameAndSpaceArgsForCall(0) 788 Expect(appName).To(Equal("some-app")) 789 Expect(spaceGUID).To(Equal("some-space-guid")) 790 791 Expect(fakeV2AppActor.GetApplicationRoutesCallCount()).To(Equal(1)) 792 Expect(fakeV2AppActor.GetApplicationRoutesArgsForCall(0)).To(Equal("some-app-guid")) 793 Expect(withObfuscatedValues).To(BeFalse()) 794 }) 795 }) 796 }) 797 }) 798 }) 799 }) 800 }) 801 }) 802 }) 803 }) 804 }) 805 806 When("looking up the application succeeds", func() { 807 BeforeEach(func() { 808 fakeActor.GetApplicationByNameAndSpaceReturns(v3action.Application{ 809 Name: "some-app", 810 GUID: "some-app-guid", 811 }, v3action.Warnings{"get-warning"}, nil) 812 }) 813 814 It("updates the application", func() { 815 Expect(fakeActor.CreateApplicationInSpaceCallCount()).To(Equal(0)) 816 Expect(fakeActor.UpdateApplicationCallCount()).To(Equal(1)) 817 }) 818 819 When("updating the application fails", func() { 820 BeforeEach(func() { 821 fakeActor.UpdateApplicationReturns(v3action.Application{}, v3action.Warnings{"update-warning-1"}, errors.New("some-error")) 822 }) 823 824 It("returns the error and displays warnings", func() { 825 Expect(executeErr).To(MatchError("some-error")) 826 827 Expect(testUI.Err).To(Say("get-warning")) 828 Expect(testUI.Err).To(Say("update-warning")) 829 }) 830 }) 831 832 When("a docker image is provided", func() { 833 BeforeEach(func() { 834 cmd.DockerImage.Path = "example.com/docker/docker/docker:docker" 835 cmd.DockerUsername = "username" 836 fakeConfig.DockerPasswordReturns("password") 837 }) 838 839 When("a username/password are provided", func() { 840 It("updates the app with the provided credentials", func() { 841 appName, spaceGuid, dockerImageCredentials := fakeActor.CreateDockerPackageByApplicationNameAndSpaceArgsForCall(0) 842 Expect(appName).To(Equal("some-app")) 843 Expect(spaceGuid).To(Equal("some-space-guid")) 844 Expect(dockerImageCredentials.Path).To(Equal(cmd.DockerImage.Path)) 845 Expect(dockerImageCredentials.Username).To(Equal("username")) 846 Expect(dockerImageCredentials.Password).To(Equal("password")) 847 }) 848 }) 849 850 It("updates the app with a docker lifecycle", func() { 851 Expect(fakeActor.UpdateApplicationCallCount()).To(Equal(1), "Expected UpdateApplication to be called once") 852 updateApp := fakeActor.UpdateApplicationArgsForCall(0) 853 Expect(updateApp).To(Equal(v3action.Application{ 854 GUID: "some-app-guid", 855 LifecycleType: constant.AppLifecycleTypeDocker, 856 })) 857 }) 858 }) 859 860 When("the app has a buildpack lifecycle", func() { 861 When("a buildpack was not provided", func() { 862 BeforeEach(func() { 863 cmd.Buildpacks = []string{} 864 }) 865 866 It("does not update the buildpack", func() { 867 appArg := fakeActor.UpdateApplicationArgsForCall(0) 868 Expect(appArg).To(Equal(v3action.Application{ 869 GUID: "some-app-guid", 870 LifecycleType: constant.AppLifecycleTypeBuildpack, 871 LifecycleBuildpacks: []string{}, 872 })) 873 }) 874 }) 875 876 When("a buildpack was provided", func() { 877 BeforeEach(func() { 878 cmd.Buildpacks = []string{"some-buildpack"} 879 }) 880 881 It("updates the buildpack", func() { 882 appArg := fakeActor.UpdateApplicationArgsForCall(0) 883 Expect(appArg).To(Equal(v3action.Application{ 884 GUID: "some-app-guid", 885 LifecycleType: constant.AppLifecycleTypeBuildpack, 886 LifecycleBuildpacks: []string{"some-buildpack"}, 887 })) 888 }) 889 }) 890 891 When("multiple buildpacks are provided", func() { 892 BeforeEach(func() { 893 cmd.Buildpacks = []string{"some-buildpack-1", "some-buildpack-2"} 894 }) 895 896 It("updates the buildpacks", func() { 897 appArg := fakeActor.UpdateApplicationArgsForCall(0) 898 Expect(appArg).To(Equal(v3action.Application{ 899 GUID: "some-app-guid", 900 LifecycleType: constant.AppLifecycleTypeBuildpack, 901 LifecycleBuildpacks: []string{"some-buildpack-1", "some-buildpack-2"}, 902 })) 903 }) 904 905 When("default was also provided", func() { 906 BeforeEach(func() { 907 cmd.Buildpacks = []string{"default", "some-buildpack-2"} 908 }) 909 910 It("returns the ConflictingBuildpacksError", func() { 911 Expect(executeErr).To(Equal(translatableerror.ConflictingBuildpacksError{})) 912 Expect(fakeActor.UpdateApplicationCallCount()).To(Equal(0)) 913 }) 914 }) 915 916 When("null was also provided", func() { 917 BeforeEach(func() { 918 cmd.Buildpacks = []string{"null", "some-buildpack-2"} 919 }) 920 921 It("returns the ConflictingBuildpacksError", func() { 922 Expect(executeErr).To(Equal(translatableerror.ConflictingBuildpacksError{})) 923 Expect(fakeActor.UpdateApplicationCallCount()).To(Equal(0)) 924 }) 925 }) 926 }) 927 }) 928 929 When("updating the application succeeds", func() { 930 When("the application is stopped", func() { 931 BeforeEach(func() { 932 fakeActor.UpdateApplicationReturns(v3action.Application{GUID: "some-app-guid", State: constant.ApplicationStopped}, v3action.Warnings{"update-warning"}, nil) 933 }) 934 935 It("skips stopping the application and pushes it", func() { 936 Expect(executeErr).ToNot(HaveOccurred()) 937 938 Expect(testUI.Err).To(Say("get-warning")) 939 Expect(testUI.Err).To(Say("update-warning")) 940 941 Expect(testUI.Out).ToNot(Say("Stopping")) 942 943 Expect(fakeActor.StopApplicationCallCount()).To(Equal(0), "Expected StopApplication to not be called") 944 945 Expect(fakeActor.StartApplicationCallCount()).To(Equal(1), "Expected StartApplication to be called") 946 }) 947 }) 948 949 When("the application is started", func() { 950 BeforeEach(func() { 951 fakeActor.UpdateApplicationReturns(v3action.Application{GUID: "some-app-guid", State: constant.ApplicationStarted}, nil, nil) 952 }) 953 954 It("stops the application and pushes it", func() { 955 Expect(executeErr).ToNot(HaveOccurred()) 956 Expect(testUI.Out).To(Say("Stopping app some-app in org some-org / space some-space as banana...")) 957 958 Expect(fakeActor.StopApplicationCallCount()).To(Equal(1)) 959 960 Expect(fakeActor.StartApplicationCallCount()).To(Equal(1), "Expected StartApplication to be called") 961 }) 962 963 When("no-start is provided", func() { 964 BeforeEach(func() { 965 cmd.NoStart = true 966 }) 967 968 It("stops the application and returns", func() { 969 Expect(executeErr).ToNot(HaveOccurred()) 970 Expect(testUI.Out).To(Say("Stopping app some-app in org some-org / space some-space as banana...")) 971 972 Expect(fakeActor.StopApplicationCallCount()).To(Equal(1)) 973 974 Expect(fakeActor.StartApplicationCallCount()).To(Equal(0)) 975 }) 976 }) 977 }) 978 }) 979 }) 980 }) 981 })