github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/v7/push_command_test.go (about) 1 package v7_test 2 3 import ( 4 "errors" 5 "fmt" 6 "io/ioutil" 7 "os" 8 "path/filepath" 9 "time" 10 11 "code.cloudfoundry.org/cli/command/translatableerror" 12 13 "code.cloudfoundry.org/cli/actor/actionerror" 14 "code.cloudfoundry.org/cli/actor/v7action" 15 "code.cloudfoundry.org/cli/actor/v7action/v7actionfakes" 16 "code.cloudfoundry.org/cli/actor/v7pushaction" 17 "code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant" 18 "code.cloudfoundry.org/cli/command/commandfakes" 19 "code.cloudfoundry.org/cli/command/flag" 20 "code.cloudfoundry.org/cli/command/v6/v6fakes" 21 . "code.cloudfoundry.org/cli/command/v7" 22 "code.cloudfoundry.org/cli/command/v7/v7fakes" 23 "code.cloudfoundry.org/cli/types" 24 "code.cloudfoundry.org/cli/util/configv3" 25 "code.cloudfoundry.org/cli/util/ui" 26 . "github.com/onsi/ginkgo" 27 . "github.com/onsi/ginkgo/extensions/table" 28 . "github.com/onsi/gomega" 29 . "github.com/onsi/gomega/gbytes" 30 . "github.com/onsi/gomega/gstruct" 31 ) 32 33 type Step struct { 34 Error error 35 Event v7pushaction.Event 36 Warnings v7pushaction.Warnings 37 } 38 39 func FillInValues(tuples []Step, state v7pushaction.PushState) func(v7pushaction.PushState, v7pushaction.ProgressBar) (<-chan v7pushaction.PushState, <-chan v7pushaction.Event, <-chan v7pushaction.Warnings, <-chan error) { 40 return func(v7pushaction.PushState, v7pushaction.ProgressBar) (<-chan v7pushaction.PushState, <-chan v7pushaction.Event, <-chan v7pushaction.Warnings, <-chan error) { 41 stateStream := make(chan v7pushaction.PushState) 42 43 eventStream := make(chan v7pushaction.Event) 44 warningsStream := make(chan v7pushaction.Warnings) 45 errorStream := make(chan error) 46 47 go func() { 48 defer close(stateStream) 49 defer close(eventStream) 50 defer close(warningsStream) 51 defer close(errorStream) 52 53 for _, tuple := range tuples { 54 warningsStream <- tuple.Warnings 55 if tuple.Error != nil { 56 errorStream <- tuple.Error 57 return 58 } else { 59 eventStream <- tuple.Event 60 } 61 } 62 63 stateStream <- state 64 eventStream <- v7pushaction.Complete 65 }() 66 67 return stateStream, eventStream, warningsStream, errorStream 68 } 69 } 70 71 type LogEvent struct { 72 Log *v7action.LogMessage 73 Error error 74 } 75 76 func ReturnLogs(logevents []LogEvent, passedWarnings v7action.Warnings, passedError error) func(appName string, spaceGUID string, client v7action.NOAAClient) (<-chan *v7action.LogMessage, <-chan error, v7action.Warnings, error) { 77 return func(appName string, spaceGUID string, client v7action.NOAAClient) (<-chan *v7action.LogMessage, <-chan error, v7action.Warnings, error) { 78 logStream := make(chan *v7action.LogMessage) 79 errStream := make(chan error) 80 go func() { 81 defer close(logStream) 82 defer close(errStream) 83 84 for _, log := range logevents { 85 if log.Log != nil { 86 logStream <- log.Log 87 } 88 if log.Error != nil { 89 errStream <- log.Error 90 } 91 } 92 }() 93 94 return logStream, errStream, passedWarnings, passedError 95 } 96 } 97 98 var _ = Describe("push Command", func() { 99 var ( 100 cmd PushCommand 101 input *Buffer 102 testUI *ui.UI 103 fakeConfig *commandfakes.FakeConfig 104 fakeSharedActor *commandfakes.FakeSharedActor 105 fakeActor *v7fakes.FakePushActor 106 fakeVersionActor *v7fakes.FakeV7ActorForPush 107 fakeProgressBar *v6fakes.FakeProgressBar 108 fakeNOAAClient *v7actionfakes.FakeNOAAClient 109 binaryName string 110 executeErr error 111 112 appName string 113 userName string 114 spaceName string 115 orgName string 116 pwd string 117 ) 118 119 BeforeEach(func() { 120 input = NewBuffer() 121 testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer()) 122 fakeConfig = new(commandfakes.FakeConfig) 123 fakeSharedActor = new(commandfakes.FakeSharedActor) 124 fakeActor = new(v7fakes.FakePushActor) 125 fakeVersionActor = new(v7fakes.FakeV7ActorForPush) 126 fakeProgressBar = new(v6fakes.FakeProgressBar) 127 fakeNOAAClient = new(v7actionfakes.FakeNOAAClient) 128 129 appName = "some-app" 130 userName = "some-user" 131 spaceName = "some-space" 132 orgName = "some-org" 133 pwd = "/push/cmd/test" 134 135 binaryName = "faceman" 136 fakeConfig.BinaryNameReturns(binaryName) 137 fakeConfig.ExperimentalReturns(true) // TODO: Delete once we remove the experimental flag 138 139 cmd = PushCommand{ 140 RequiredArgs: flag.AppName{AppName: "some-app"}, 141 UI: testUI, 142 Config: fakeConfig, 143 Actor: fakeActor, 144 VersionActor: fakeVersionActor, 145 SharedActor: fakeSharedActor, 146 ProgressBar: fakeProgressBar, 147 NOAAClient: fakeNOAAClient, 148 PWD: pwd, 149 } 150 }) 151 152 Describe("Execute", func() { 153 JustBeforeEach(func() { 154 executeErr = cmd.Execute(nil) 155 }) 156 157 When("checking target fails", func() { 158 BeforeEach(func() { 159 fakeSharedActor.CheckTargetReturns(actionerror.NoOrganizationTargetedError{BinaryName: binaryName}) 160 }) 161 162 It("returns an error", func() { 163 Expect(executeErr).To(MatchError(actionerror.NoOrganizationTargetedError{BinaryName: binaryName})) 164 165 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 166 checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 167 Expect(checkTargetedOrg).To(BeTrue()) 168 Expect(checkTargetedSpace).To(BeTrue()) 169 }) 170 }) 171 172 When("checking target fails because the user is not logged in", func() { 173 BeforeEach(func() { 174 fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName}) 175 }) 176 177 It("returns an error", func() { 178 Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName})) 179 180 Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1)) 181 checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0) 182 Expect(checkTargetedOrg).To(BeTrue()) 183 Expect(checkTargetedSpace).To(BeTrue()) 184 }) 185 }) 186 187 When("the user is logged in, and org and space are targeted", func() { 188 BeforeEach(func() { 189 fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil) 190 191 fakeConfig.TargetedOrganizationReturns(configv3.Organization{ 192 Name: orgName, 193 GUID: "some-org-guid", 194 }) 195 fakeConfig.TargetedSpaceReturns(configv3.Space{ 196 Name: spaceName, 197 GUID: "some-space-guid", 198 }) 199 }) 200 201 It("displays the experimental warning", func() { 202 Expect(testUI.Err).To(Say("This command is in EXPERIMENTAL stage and may change without notice")) 203 }) 204 205 When("invalid flags are passed", func() { 206 BeforeEach(func() { 207 cmd.DockerUsername = "some-docker-username" 208 }) 209 210 It("returns a validation error", func() { 211 Expect(executeErr).To(MatchError(translatableerror.RequiredFlagsError{Arg1: "--docker-image, -o", Arg2: "--docker-username"})) 212 }) 213 }) 214 215 Describe("manifest", func() { 216 var tempDir string 217 218 BeforeEach(func() { 219 var err error 220 tempDir, err = ioutil.TempDir("", "manifest-push-unit") 221 Expect(err).ToNot(HaveOccurred()) 222 }) 223 224 AfterEach(func() { 225 Expect(os.RemoveAll(tempDir)).ToNot(HaveOccurred()) 226 }) 227 228 When("No path is provided", func() { 229 BeforeEach(func() { 230 cmd.PWD = tempDir 231 }) 232 233 When("there is a manifest file in the current dir", func() { 234 var yamlContents []byte 235 236 BeforeEach(func() { 237 yamlContents = []byte(`---\n- banana`) 238 pathToYAMLFile := filepath.Join(tempDir, "manifest.yml") 239 err := ioutil.WriteFile(pathToYAMLFile, yamlContents, 0644) 240 Expect(err).ToNot(HaveOccurred()) 241 }) 242 243 It("reads the manifest and passes through to conceptualize", func() { 244 Expect(executeErr).ToNot(HaveOccurred()) 245 Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1)) 246 _, _, _, _, _, manifest := fakeActor.ConceptualizeArgsForCall(0) 247 Expect(manifest).To(Equal(yamlContents)) 248 }) 249 }) 250 251 When("there is not a manifest in the current dir", func() { 252 It("does not pass a manifest to conceptualize", func() { 253 Expect(executeErr).ToNot(HaveOccurred()) 254 Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1)) 255 _, _, _, _, _, manifest := fakeActor.ConceptualizeArgsForCall(0) 256 Expect(manifest).To(BeNil()) 257 }) 258 }) 259 }) 260 261 When("The -f flag is specified", func() { 262 When("The manifest exists at the path", func() { 263 var yamlContents []byte 264 265 BeforeEach(func() { 266 yamlContents = []byte(`---\n- banana`) 267 pathToYAMLFile := filepath.Join(tempDir, "manifest.yml") 268 err := ioutil.WriteFile(pathToYAMLFile, yamlContents, 0644) 269 Expect(err).ToNot(HaveOccurred()) 270 cmd.PathToManifest = flag.PathWithExistenceCheck(pathToYAMLFile) 271 }) 272 273 It("reads the manifest and passes through to conceptualize", func() { 274 Expect(executeErr).ToNot(HaveOccurred()) 275 Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1)) 276 _, _, _, _, _, manifest := fakeActor.ConceptualizeArgsForCall(0) 277 Expect(manifest).To(Equal(yamlContents)) 278 }) 279 }) 280 281 When("The manifest does not exist at the path", func() { 282 BeforeEach(func() { 283 cmd.PathToManifest = "/some/non-existant/path.yml" 284 }) 285 286 It("throws an error", func() { 287 Expect(os.IsNotExist(executeErr)).To(BeTrue(), fmt.Sprintf("expected to get an 'is not exists' error but got %#v", executeErr)) 288 }) 289 }) 290 }) 291 }) 292 293 When("there are no flag overrides", func() { 294 BeforeEach(func() { 295 fakeActor.ConceptualizeReturns( 296 []v7pushaction.PushState{ 297 { 298 Application: v7action.Application{Name: appName}, 299 }, 300 }, 301 v7pushaction.Warnings{"some-warning-1"}, nil) 302 }) 303 304 When("the app is successfully actualized", func() { 305 BeforeEach(func() { 306 fakeActor.ActualizeStub = FillInValues([]Step{ 307 {}, 308 }, v7pushaction.PushState{Application: v7action.Application{GUID: "potato"}}) 309 }) 310 311 Describe("actualize events", func() { 312 BeforeEach(func() { 313 fakeActor.ActualizeStub = FillInValues([]Step{ 314 { 315 Event: v7pushaction.SkippingApplicationCreation, 316 Warnings: v7pushaction.Warnings{"skipping app creation warnings"}, 317 }, 318 { 319 Event: v7pushaction.CreatingApplication, 320 Warnings: v7pushaction.Warnings{"app creation warnings"}, 321 }, 322 { 323 Event: v7pushaction.CreatingAndMappingRoutes, 324 }, 325 { 326 Event: v7pushaction.CreatedRoutes, 327 Warnings: v7pushaction.Warnings{"routes warnings"}, 328 }, 329 { 330 Event: v7pushaction.CreatingArchive, 331 }, 332 { 333 Event: v7pushaction.UploadingApplicationWithArchive, 334 Warnings: v7pushaction.Warnings{"upload app archive warning"}, 335 }, 336 { 337 Event: v7pushaction.RetryUpload, 338 Warnings: v7pushaction.Warnings{"retry upload warning"}, 339 }, 340 { 341 Event: v7pushaction.UploadWithArchiveComplete, 342 }, 343 { 344 Event: v7pushaction.StagingComplete, 345 }, 346 }, v7pushaction.PushState{}) 347 }) 348 349 It("generates a push state with the specified app path", func() { 350 Expect(executeErr).ToNot(HaveOccurred()) 351 Expect(testUI.Out).To(Say("Pushing app %s to org some-org / space some-space as some-user", appName)) 352 Expect(testUI.Out).To(Say(`Getting app info\.\.\.`)) 353 Expect(testUI.Err).To(Say("some-warning-1")) 354 355 Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1)) 356 name, spaceGUID, orgGUID, currentDirectory, _, _ := fakeActor.ConceptualizeArgsForCall(0) 357 Expect(name).To(Equal(appName)) 358 Expect(spaceGUID).To(Equal("some-space-guid")) 359 Expect(orgGUID).To(Equal("some-org-guid")) 360 Expect(currentDirectory).To(Equal(pwd)) 361 }) 362 363 It("actualizes the application and displays events/warnings", func() { 364 Expect(executeErr).ToNot(HaveOccurred()) 365 366 Expect(testUI.Out).To(Say("Updating app some-app...")) 367 Expect(testUI.Err).To(Say("skipping app creation warnings")) 368 369 Expect(testUI.Out).To(Say("Creating app some-app...")) 370 Expect(testUI.Err).To(Say("app creation warnings")) 371 372 Expect(testUI.Out).To(Say("Mapping routes...")) 373 Expect(testUI.Err).To(Say("routes warnings")) 374 375 Expect(testUI.Out).To(Say("Packaging files to upload...")) 376 377 Expect(testUI.Out).To(Say("Uploading files...")) 378 Expect(testUI.Err).To(Say("upload app archive warning")) 379 Expect(fakeProgressBar.ReadyCallCount()).Should(Equal(1)) 380 381 Expect(testUI.Out).To(Say("Retrying upload due to an error...")) 382 Expect(testUI.Err).To(Say("retry upload warning")) 383 384 Expect(testUI.Out).To(Say("Waiting for API to complete processing files...")) 385 386 Expect(testUI.Out).To(Say("Waiting for app to start...")) 387 Expect(fakeProgressBar.CompleteCallCount()).Should(Equal(1)) 388 }) 389 }) 390 391 Describe("staging logs", func() { 392 BeforeEach(func() { 393 fakeActor.ActualizeStub = FillInValues([]Step{ 394 { 395 Event: v7pushaction.StartingStaging, 396 }, 397 }, v7pushaction.PushState{}) 398 }) 399 400 When("there are no logging errors", func() { 401 BeforeEach(func() { 402 fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceStub = ReturnLogs( 403 []LogEvent{ 404 {Log: v7action.NewLogMessage("log-message-1", 1, time.Now(), v7action.StagingLog, "source-instance")}, 405 {Log: v7action.NewLogMessage("log-message-2", 1, time.Now(), v7action.StagingLog, "source-instance")}, 406 {Log: v7action.NewLogMessage("log-message-3", 1, time.Now(), "potato", "source-instance")}, 407 }, 408 v7action.Warnings{"log-warning-1", "log-warning-2"}, 409 nil, 410 ) 411 }) 412 413 It("displays the staging logs and warnings", func() { 414 Expect(testUI.Out).To(Say("Staging app and tracing logs...")) 415 416 Expect(testUI.Err).To(Say("log-warning-1")) 417 Expect(testUI.Err).To(Say("log-warning-2")) 418 419 Eventually(testUI.Out).Should(Say("log-message-1")) 420 Eventually(testUI.Out).Should(Say("log-message-2")) 421 Eventually(testUI.Out).ShouldNot(Say("log-message-3")) 422 423 Expect(fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(1)) 424 passedAppName, spaceGUID, _ := fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0) 425 Expect(passedAppName).To(Equal(appName)) 426 Expect(spaceGUID).To(Equal("some-space-guid")) 427 }) 428 }) 429 430 When("there are logging errors", func() { 431 BeforeEach(func() { 432 fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceStub = ReturnLogs( 433 []LogEvent{ 434 {Error: errors.New("some-random-err")}, 435 {Error: actionerror.NOAATimeoutError{}}, 436 {Log: v7action.NewLogMessage("log-message-1", 1, time.Now(), v7action.StagingLog, "source-instance")}, 437 }, 438 v7action.Warnings{"log-warning-1", "log-warning-2"}, 439 nil, 440 ) 441 }) 442 443 It("displays the errors as warnings", func() { 444 Expect(testUI.Out).To(Say("Staging app and tracing logs...")) 445 446 Expect(testUI.Err).To(Say("log-warning-1")) 447 Expect(testUI.Err).To(Say("log-warning-2")) 448 Eventually(testUI.Err).Should(Say("some-random-err")) 449 Eventually(testUI.Err).Should(Say("timeout connecting to log server, no log will be shown")) 450 451 Eventually(testUI.Out).Should(Say("log-message-1")) 452 }) 453 }) 454 }) 455 456 When("restarting the app succeeds", func() { 457 BeforeEach(func() { 458 fakeVersionActor.RestartApplicationReturns(v7action.Warnings{"some-restart-warning"}, nil) 459 460 summary := v7action.ApplicationSummary{ 461 Application: v7action.Application{ 462 Name: appName, 463 State: constant.ApplicationStarted, 464 }, 465 CurrentDroplet: v7action.Droplet{ 466 Stack: "cflinuxfs2", 467 Buildpacks: []v7action.Buildpack{ 468 { 469 Name: "ruby_buildpack", 470 DetectOutput: "some-detect-output", 471 }, 472 { 473 Name: "some-buildpack", 474 DetectOutput: "", 475 }, 476 }, 477 }, 478 ProcessSummaries: v7action.ProcessSummaries{ 479 { 480 Process: v7action.Process{ 481 Type: constant.ProcessTypeWeb, 482 Command: *types.NewFilteredString("some-command-1"), 483 }, 484 }, 485 { 486 Process: v7action.Process{ 487 Type: "console", 488 Command: *types.NewFilteredString("some-command-2"), 489 }, 490 }, 491 }, 492 } 493 fakeVersionActor.GetApplicationSummaryByNameAndSpaceReturns(summary, v7action.Warnings{"app-summary-warning-1", "app-summary-warning-2"}, nil) 494 }) 495 496 It("restarts the app and displays warnings", func() { 497 Expect(executeErr).ToNot(HaveOccurred()) 498 499 Expect(testUI.Err).To(Say("some-restart-warning")) 500 501 Expect(fakeVersionActor.RestartApplicationCallCount()).To(Equal(1)) 502 Expect(fakeVersionActor.RestartApplicationArgsForCall(0)).To(Equal("potato")) 503 }) 504 505 It("displays the app summary", func() { 506 Expect(executeErr).ToNot(HaveOccurred()) 507 Expect(testUI.Out).To(Say(`name:\s+some-app`)) 508 Expect(testUI.Out).To(Say(`requested state:\s+started`)) 509 Expect(testUI.Out).To(Say("type:\\s+web")) 510 Expect(testUI.Out).To(Say("start command:\\s+some-command-1")) 511 Expect(testUI.Out).To(Say("type:\\s+console")) 512 Expect(testUI.Out).To(Say("start command:\\s+some-command-2")) 513 514 Expect(testUI.Err).To(Say("warning-1")) 515 Expect(testUI.Err).To(Say("warning-2")) 516 517 Expect(fakeVersionActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1)) 518 name, spaceGUID, withObfuscatedValues, _ := fakeVersionActor.GetApplicationSummaryByNameAndSpaceArgsForCall(0) 519 Expect(name).To(Equal("some-app")) 520 Expect(spaceGUID).To(Equal("some-space-guid")) 521 Expect(withObfuscatedValues).To(BeTrue()) 522 }) 523 }) 524 525 When("restarting the app fails", func() { 526 When("restarting fails in a generic way", func() { 527 BeforeEach(func() { 528 fakeVersionActor.RestartApplicationReturns(v7action.Warnings{"some-restart-warning"}, errors.New("restart failure")) 529 }) 530 531 It("returns an error and any warnings", func() { 532 Expect(executeErr).To(MatchError("restart failure")) 533 Expect(testUI.Err).To(Say("some-restart-warning")) 534 535 }) 536 }) 537 538 When("the error is an AllInstancesCrashedError", func() { 539 BeforeEach(func() { 540 fakeVersionActor.RestartApplicationReturns(nil, actionerror.AllInstancesCrashedError{}) 541 }) 542 543 It("returns the ApplicationUnableToStartError", func() { 544 Expect(executeErr).To(MatchError(translatableerror.ApplicationUnableToStartError{ 545 AppName: "some-app", 546 BinaryName: binaryName, 547 })) 548 }) 549 550 }) 551 552 When("restart times out", func() { 553 BeforeEach(func() { 554 fakeVersionActor.RestartApplicationReturns(v7action.Warnings{"some-restart-warning"}, actionerror.StartupTimeoutError{}) 555 }) 556 557 It("returns the StartupTimeoutError and prints warnings", func() { 558 Expect(executeErr).To(MatchError(translatableerror.StartupTimeoutError{ 559 AppName: "some-app", 560 BinaryName: binaryName, 561 })) 562 563 Expect(testUI.Err).To(Say("some-restart-warning")) 564 }) 565 }) 566 }) 567 }) 568 569 When("actualizing fails", func() { 570 BeforeEach(func() { 571 fakeActor.ActualizeStub = FillInValues([]Step{ 572 { 573 Error: errors.New("anti avant garde naming"), 574 }, 575 }, v7pushaction.PushState{}) 576 }) 577 578 It("returns the error", func() { 579 Expect(executeErr).To(MatchError("anti avant garde naming")) 580 }) 581 }) 582 }) 583 584 When("flag overrides are specified", func() { 585 BeforeEach(func() { 586 cmd.AppPath = "some/app/path" 587 }) 588 589 It("generates a push state with the specified flag overrides", func() { 590 Expect(fakeActor.ConceptualizeCallCount()).To(Equal(1)) 591 _, _, _, _, overrides, _ := fakeActor.ConceptualizeArgsForCall(0) 592 Expect(overrides).To(MatchFields(IgnoreExtras, Fields{ 593 "ProvidedAppPath": Equal("some/app/path"), 594 })) 595 }) 596 }) 597 598 When("conceptualize returns an error", func() { 599 var expectedErr error 600 601 BeforeEach(func() { 602 expectedErr = errors.New("some-error") 603 fakeActor.ConceptualizeReturns(nil, v7pushaction.Warnings{"some-warning-1"}, expectedErr) 604 }) 605 606 It("generates a push state with the specified app path", func() { 607 Expect(executeErr).To(MatchError(expectedErr)) 608 Expect(testUI.Err).To(Say("some-warning-1")) 609 }) 610 }) 611 }) 612 }) 613 614 Describe("GetFlagOverrides", func() { 615 var ( 616 overrides v7pushaction.FlagOverrides 617 overridesErr error 618 ) 619 620 BeforeEach(func() { 621 cmd.Buildpacks = []string{"buildpack-1", "buildpack-2"} 622 cmd.HealthCheckType = flag.HealthCheckType{Type: constant.Port} 623 cmd.Memory = flag.Megabytes{NullUint64: types.NullUint64{Value: 100, IsSet: true}} 624 cmd.StartCommand = flag.Command{FilteredString: types.FilteredString{IsSet: true, Value: "some-start-command"}} 625 cmd.NoRoute = true 626 cmd.NoStart = true 627 cmd.Instances = flag.Instances{NullInt: types.NullInt{Value: 10, IsSet: true}} 628 }) 629 630 JustBeforeEach(func() { 631 overrides, overridesErr = cmd.GetFlagOverrides() 632 Expect(overridesErr).ToNot(HaveOccurred()) 633 }) 634 635 It("sets them on the flag overrides", func() { 636 Expect(overridesErr).ToNot(HaveOccurred()) 637 Expect(overrides.Buildpacks).To(ConsistOf("buildpack-1", "buildpack-2")) 638 Expect(overrides.HealthCheckType).To(Equal(constant.Port)) 639 Expect(overrides.Memory).To(Equal(types.NullUint64{Value: 100, IsSet: true})) 640 Expect(overrides.StartCommand).To(Equal(types.FilteredString{IsSet: true, Value: "some-start-command"})) 641 Expect(overrides.SkipRouteCreation).To(BeTrue()) 642 Expect(overrides.NoStart).To(BeTrue()) 643 Expect(overrides.Instances).To(Equal(types.NullInt{Value: 10, IsSet: true})) 644 }) 645 646 When("a docker image is provided", func() { 647 BeforeEach(func() { 648 cmd.DockerImage = flag.DockerImage{Path: "some-docker-image"} 649 }) 650 651 It("sets docker image on the flag overrides", func() { 652 Expect(overridesErr).ToNot(HaveOccurred()) 653 Expect(overrides.DockerImage).To(Equal("some-docker-image")) 654 }) 655 656 When("docker username is provided", func() { 657 When("a password is provided via environment variable", func() { 658 BeforeEach(func() { 659 cmd.DockerUsername = "some-docker-username" 660 fakeConfig.DockerPasswordReturns("some-docker-password") 661 }) 662 663 It("takes the password from the environment", func() { 664 Expect(overridesErr).ToNot(HaveOccurred()) 665 666 Expect(testUI.Out).ToNot(Say("Environment variable CF_DOCKER_PASSWORD not set.")) 667 Expect(testUI.Out).ToNot(Say("Docker password")) 668 669 Expect(testUI.Out).To(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD.")) 670 671 Expect(overrides.DockerUsername).To(Equal("some-docker-username")) 672 Expect(overrides.DockerPassword).To(Equal("some-docker-password")) 673 }) 674 }) 675 676 When("no password is provided", func() { 677 BeforeEach(func() { 678 cmd.DockerUsername = "some-docker-username" 679 input.Write([]byte("some-docker-password\n")) 680 }) 681 682 It("prompts for a password", func() { 683 Expect(overridesErr).ToNot(HaveOccurred()) 684 685 Expect(testUI.Out).To(Say("Environment variable CF_DOCKER_PASSWORD not set.")) 686 Expect(testUI.Out).To(Say("Docker password")) 687 688 Expect(overrides.DockerUsername).To(Equal("some-docker-username")) 689 Expect(overrides.DockerPassword).To(Equal("some-docker-password")) 690 }) 691 }) 692 }) 693 }) 694 }) 695 696 DescribeTable("ValidateFlags returns an error", 697 func(setup func(), expectedErr error) { 698 setup() 699 err := cmd.ValidateFlags() 700 Expect(err).To(MatchError(expectedErr)) 701 }, 702 703 Entry("when docker username flag is passed *without* docker flag", 704 func() { 705 cmd.DockerUsername = "some-docker-username" 706 }, 707 translatableerror.RequiredFlagsError{Arg1: "--docker-image, -o", Arg2: "--docker-username"}), 708 709 Entry("when docker and buildpacks flags are passed", 710 func() { 711 cmd.DockerImage.Path = "some-docker-image" 712 cmd.Buildpacks = []string{"some-buildpack"} 713 }, 714 translatableerror.ArgumentCombinationError{Args: []string{"--buildpack, -b", "--docker-image, -o"}}), 715 716 Entry("when docker and path flags are passed", 717 func() { 718 cmd.DockerImage.Path = "some-docker-image" 719 cmd.AppPath = "some-directory-path" 720 }, 721 translatableerror.ArgumentCombinationError{Args: []string{"--docker-image, -o", "--path, -p"}}), 722 ) 723 724 })