github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/command/v6/v3_push_command_test.go (about)

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