github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/v7/push_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"context"
     5  	"errors"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/actor/actionerror"
     9  	"code.cloudfoundry.org/cli/actor/v7action"
    10  	"code.cloudfoundry.org/cli/actor/v7action/v7actionfakes"
    11  	"code.cloudfoundry.org/cli/actor/v7pushaction"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    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/v6fakes"
    17  	. "code.cloudfoundry.org/cli/command/v7"
    18  	"code.cloudfoundry.org/cli/command/v7/v7fakes"
    19  	"code.cloudfoundry.org/cli/types"
    20  	"code.cloudfoundry.org/cli/util/configv3"
    21  	"code.cloudfoundry.org/cli/util/manifestparser"
    22  	"code.cloudfoundry.org/cli/util/ui"
    23  	"github.com/cloudfoundry/bosh-cli/director/template"
    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  type Step struct {
    31  	Plan     v7pushaction.PushPlan
    32  	Error    error
    33  	Event    v7pushaction.Event
    34  	Warnings v7pushaction.Warnings
    35  }
    36  
    37  func FillInEvents(steps []Step) <-chan *v7pushaction.PushEvent {
    38  	eventStream := make(chan *v7pushaction.PushEvent)
    39  
    40  	go func() {
    41  		defer close(eventStream)
    42  
    43  		for _, step := range steps {
    44  			eventStream <- &v7pushaction.PushEvent{Plan: step.Plan, Warnings: step.Warnings, Err: step.Error, Event: step.Event}
    45  		}
    46  	}()
    47  
    48  	return eventStream
    49  }
    50  
    51  type LogEvent struct {
    52  	Log   *v7action.LogMessage
    53  	Error error
    54  }
    55  
    56  func ReturnLogs(logevents []LogEvent, passedWarnings v7action.Warnings, passedError error) func(appName string, spaceGUID string, client v7action.LogCacheClient) (<-chan v7action.LogMessage, <-chan error, context.CancelFunc, v7action.Warnings, error) {
    57  	return func(appName string, spaceGUID string, client v7action.LogCacheClient) (<-chan v7action.LogMessage, <-chan error, context.CancelFunc, v7action.Warnings, error) {
    58  		logStream := make(chan v7action.LogMessage)
    59  		errStream := make(chan error)
    60  		go func() {
    61  			defer close(logStream)
    62  			defer close(errStream)
    63  
    64  			for _, log := range logevents {
    65  				if log.Log != nil {
    66  					logStream <- *log.Log
    67  				}
    68  				if log.Error != nil {
    69  					errStream <- log.Error
    70  				}
    71  			}
    72  		}()
    73  
    74  		return logStream, errStream, func() {}, passedWarnings, passedError
    75  	}
    76  }
    77  
    78  var _ = Describe("push Command", func() {
    79  	var (
    80  		cmd                 PushCommand
    81  		input               *Buffer
    82  		testUI              *ui.UI
    83  		fakeConfig          *commandfakes.FakeConfig
    84  		fakeSharedActor     *commandfakes.FakeSharedActor
    85  		fakeActor           *v7fakes.FakePushActor
    86  		fakeVersionActor    *v7fakes.FakeV7ActorForPush
    87  		fakeProgressBar     *v6fakes.FakeProgressBar
    88  		fakeLogCacheClient  *v7actionfakes.FakeLogCacheClient
    89  		fakeManifestLocator *v7fakes.FakeManifestLocator
    90  		fakeManifestParser  *v7fakes.FakeManifestParser
    91  		binaryName          string
    92  		executeErr          error
    93  
    94  		appName1  string
    95  		appName2  string
    96  		userName  string
    97  		spaceName string
    98  		orgName   string
    99  		pwd       string
   100  	)
   101  
   102  	BeforeEach(func() {
   103  		input = NewBuffer()
   104  		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
   105  		fakeConfig = new(commandfakes.FakeConfig)
   106  		fakeSharedActor = new(commandfakes.FakeSharedActor)
   107  		fakeActor = new(v7fakes.FakePushActor)
   108  		fakeVersionActor = new(v7fakes.FakeV7ActorForPush)
   109  		fakeProgressBar = new(v6fakes.FakeProgressBar)
   110  		fakeLogCacheClient = new(v7actionfakes.FakeLogCacheClient)
   111  
   112  		appName1 = "first-app"
   113  		appName2 = "second-app"
   114  		userName = "some-user"
   115  		spaceName = "some-space"
   116  		orgName = "some-org"
   117  		pwd = "/push/cmd/test"
   118  		fakeManifestLocator = new(v7fakes.FakeManifestLocator)
   119  		fakeManifestParser = new(v7fakes.FakeManifestParser)
   120  
   121  		binaryName = "faceman"
   122  		fakeConfig.BinaryNameReturns(binaryName)
   123  
   124  		cmd = PushCommand{
   125  			UI:              testUI,
   126  			Config:          fakeConfig,
   127  			Actor:           fakeActor,
   128  			VersionActor:    fakeVersionActor,
   129  			SharedActor:     fakeSharedActor,
   130  			ProgressBar:     fakeProgressBar,
   131  			LogCacheClient:  fakeLogCacheClient,
   132  			CWD:             pwd,
   133  			ManifestLocator: fakeManifestLocator,
   134  			ManifestParser:  fakeManifestParser,
   135  		}
   136  	})
   137  
   138  	Describe("Execute", func() {
   139  		JustBeforeEach(func() {
   140  			executeErr = cmd.Execute(nil)
   141  		})
   142  
   143  		BeforeEach(func() {
   144  			fakeActor.ActualizeStub = func(v7pushaction.PushPlan, v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   145  				return FillInEvents([]Step{})
   146  			}
   147  		})
   148  
   149  		When("checking target fails", func() {
   150  			BeforeEach(func() {
   151  				fakeSharedActor.CheckTargetReturns(actionerror.NoOrganizationTargetedError{BinaryName: binaryName})
   152  			})
   153  
   154  			It("returns an error", func() {
   155  				Expect(executeErr).To(MatchError(actionerror.NoOrganizationTargetedError{BinaryName: binaryName}))
   156  
   157  				Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
   158  				checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
   159  				Expect(checkTargetedOrg).To(BeTrue())
   160  				Expect(checkTargetedSpace).To(BeTrue())
   161  			})
   162  		})
   163  
   164  		When("checking target fails because the user is not logged in", func() {
   165  			BeforeEach(func() {
   166  				fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName})
   167  			})
   168  
   169  			It("returns an error", func() {
   170  				Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName}))
   171  
   172  				Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
   173  				checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
   174  				Expect(checkTargetedOrg).To(BeTrue())
   175  				Expect(checkTargetedSpace).To(BeTrue())
   176  			})
   177  		})
   178  
   179  		When("the user is logged in, and org and space are targeted", func() {
   180  			BeforeEach(func() {
   181  				fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil)
   182  
   183  				fakeConfig.TargetedOrganizationReturns(configv3.Organization{
   184  					Name: orgName,
   185  					GUID: "some-org-guid",
   186  				})
   187  				fakeConfig.TargetedSpaceReturns(configv3.Space{
   188  					Name: spaceName,
   189  					GUID: "some-space-guid",
   190  				})
   191  			})
   192  
   193  			When("invalid flags are passed", func() {
   194  				BeforeEach(func() {
   195  					cmd.DockerUsername = "some-docker-username"
   196  				})
   197  
   198  				It("returns a validation error", func() {
   199  					Expect(executeErr).To(MatchError(translatableerror.RequiredFlagsError{Arg1: "--docker-image, -o", Arg2: "--docker-username"}))
   200  				})
   201  			})
   202  
   203  			When("the flags are all valid", func() {
   204  				It("delegating to the GetBaseManifest", func() {
   205  					// This tells us GetBaseManifest is being called because we dont have a fake
   206  					Expect(fakeManifestLocator.PathCallCount()).To(Equal(1))
   207  				})
   208  
   209  				When("getting the base manifest fails", func() {
   210  					BeforeEach(func() {
   211  						fakeManifestLocator.PathReturns("", false, errors.New("locate-error"))
   212  					})
   213  
   214  					It("returns the error", func() {
   215  						Expect(executeErr).To(MatchError(errors.New("locate-error")))
   216  					})
   217  				})
   218  
   219  				When("getting the base manifest succeeds", func() {
   220  					BeforeEach(func() {
   221  						// essentially fakes GetBaseManifest
   222  						fakeManifestLocator.PathReturns("", true, nil)
   223  						fakeManifestParser.InterpolateAndParseReturns(
   224  							manifestparser.Manifest{
   225  								Applications: []manifestparser.Application{
   226  									{
   227  										Name: "some-app-name",
   228  									},
   229  								},
   230  							},
   231  							nil,
   232  						)
   233  					})
   234  
   235  					It("delegates to the flag override handler", func() {
   236  						Expect(fakeActor.HandleFlagOverridesCallCount()).To(Equal(1))
   237  						actualManifest, actualFlagOverrides := fakeActor.HandleFlagOverridesArgsForCall(0)
   238  						Expect(actualManifest).To(Equal(
   239  							manifestparser.Manifest{
   240  								Applications: []manifestparser.Application{
   241  									{Name: "some-app-name"},
   242  								},
   243  							},
   244  						))
   245  						Expect(actualFlagOverrides).To(Equal(v7pushaction.FlagOverrides{}))
   246  					})
   247  
   248  					When("handling the flag overrides fails", func() {
   249  						BeforeEach(func() {
   250  							fakeActor.HandleFlagOverridesReturns(manifestparser.Manifest{}, errors.New("override-handler-error"))
   251  						})
   252  
   253  						It("returns the error", func() {
   254  							Expect(executeErr).To(MatchError("override-handler-error"))
   255  						})
   256  					})
   257  
   258  					When("handling the flag overrides succeeds", func() {
   259  						BeforeEach(func() {
   260  							fakeActor.HandleFlagOverridesReturns(
   261  								manifestparser.Manifest{
   262  									Applications: []manifestparser.Application{
   263  										{Name: "some-app-name"},
   264  									},
   265  								},
   266  								nil,
   267  							)
   268  						})
   269  
   270  						When("the docker password is needed", func() {
   271  							// TODO remove this in favor of a fake manifest
   272  							BeforeEach(func() {
   273  								fakeActor.HandleFlagOverridesReturns(
   274  									manifestparser.Manifest{
   275  										Applications: []manifestparser.Application{
   276  											{
   277  												Name:   "some-app-name",
   278  												Docker: &manifestparser.Docker{Username: "username", Image: "image"},
   279  											},
   280  										},
   281  									},
   282  									nil,
   283  								)
   284  							})
   285  
   286  							It("delegates to the GetDockerPassword", func() {
   287  								Expect(fakeConfig.DockerPasswordCallCount()).To(Equal(1))
   288  							})
   289  						})
   290  
   291  						It("delegates to the manifest parser", func() {
   292  							Expect(fakeManifestParser.MarshalManifestCallCount()).To(Equal(1))
   293  							Expect(fakeManifestParser.MarshalManifestArgsForCall(0)).To(Equal(
   294  								manifestparser.Manifest{
   295  									Applications: []manifestparser.Application{
   296  										{Name: "some-app-name"},
   297  									},
   298  								},
   299  							))
   300  						})
   301  
   302  						When("marshalling the manifest fails", func() {
   303  							BeforeEach(func() {
   304  								fakeManifestParser.MarshalManifestReturns([]byte{}, errors.New("marshal error"))
   305  							})
   306  
   307  							It("returns the error", func() {
   308  								Expect(executeErr).To(MatchError("marshal error"))
   309  							})
   310  						})
   311  
   312  						When("marsahlling the manifest succeeds", func() {
   313  							BeforeEach(func() {
   314  								fakeManifestParser.MarshalManifestReturns([]byte("our-manifest"), nil)
   315  							})
   316  
   317  							It("delegates to the version actor", func() {
   318  								Expect(fakeVersionActor.SetSpaceManifestCallCount()).To(Equal(1))
   319  								actualSpaceGUID, actualManifestBytes := fakeVersionActor.SetSpaceManifestArgsForCall(0)
   320  								Expect(actualSpaceGUID).To(Equal("some-space-guid"))
   321  								Expect(actualManifestBytes).To(Equal([]byte("our-manifest")))
   322  							})
   323  
   324  							When("applying the manifest fails", func() {
   325  								BeforeEach(func() {
   326  									fakeVersionActor.SetSpaceManifestReturns(v7action.Warnings{"apply-manifest-warnings"}, errors.New("apply-manifest-error"))
   327  								})
   328  
   329  								It("returns an error and prints warnings", func() {
   330  									Expect(executeErr).To(MatchError("apply-manifest-error"))
   331  									Expect(testUI.Err).To(Say("apply-manifest-warnings"))
   332  								})
   333  
   334  							})
   335  
   336  							When("applying the manifest succeeds", func() {
   337  								BeforeEach(func() {
   338  									fakeVersionActor.SetSpaceManifestReturns(v7action.Warnings{"apply-manifest-warnings"}, nil)
   339  								})
   340  
   341  								It("delegates to the push actor", func() {
   342  									Expect(fakeActor.CreatePushPlansCallCount()).To(Equal(1))
   343  									spaceGUID, orgGUID, manifest, overrides := fakeActor.CreatePushPlansArgsForCall(0)
   344  									Expect(spaceGUID).To(Equal("some-space-guid"))
   345  									Expect(orgGUID).To(Equal("some-org-guid"))
   346  									Expect(manifest).To(Equal(
   347  										manifestparser.Manifest{
   348  											Applications: []manifestparser.Application{
   349  												{Name: "some-app-name"},
   350  											},
   351  										},
   352  									))
   353  									Expect(overrides).To(Equal(v7pushaction.FlagOverrides{}))
   354  								})
   355  
   356  								When("creating the push plans fails", func() {
   357  									BeforeEach(func() {
   358  										fakeActor.CreatePushPlansReturns(
   359  											nil,
   360  											v7action.Warnings{"create-push-plans-warnings"},
   361  											errors.New("create-push-plans-error"),
   362  										)
   363  									})
   364  
   365  									It("returns errors and warnings", func() {
   366  										Expect(executeErr).To(MatchError("create-push-plans-error"))
   367  										Expect(testUI.Err).To(Say("create-push-plans-warnings"))
   368  									})
   369  
   370  								})
   371  
   372  								When("creating the push plans succeeds", func() {
   373  									BeforeEach(func() {
   374  										fakeActor.CreatePushPlansReturns(
   375  											[]v7pushaction.PushPlan{
   376  												v7pushaction.PushPlan{Application: v7action.Application{Name: "first-app", GUID: "potato"}},
   377  												v7pushaction.PushPlan{Application: v7action.Application{Name: "second-app", GUID: "potato"}},
   378  											},
   379  											v7action.Warnings{"create-push-plans-warnings"},
   380  											nil,
   381  										)
   382  									})
   383  
   384  									It("it displays the warnings from create push plans", func() {
   385  										Expect(testUI.Err).To(Say("create-push-plans-warnings"))
   386  									})
   387  
   388  									Describe("delegating to Actor.Actualize", func() {
   389  										When("Actualize returns success", func() {
   390  											BeforeEach(func() {
   391  												fakeActor.ActualizeStub = func(v7pushaction.PushPlan, v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   392  													return FillInEvents([]Step{
   393  														{Plan: v7pushaction.PushPlan{Application: v7action.Application{GUID: "potato"}}},
   394  													})
   395  												}
   396  											})
   397  
   398  											Describe("actualize events", func() {
   399  												BeforeEach(func() {
   400  													fakeActor.ActualizeStub = func(pushPlan v7pushaction.PushPlan, _ v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   401  														return FillInEvents([]Step{
   402  															{
   403  																Plan:  v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   404  																Event: v7pushaction.CreatingArchive,
   405  															},
   406  															{
   407  																Plan:     v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   408  																Event:    v7pushaction.UploadingApplicationWithArchive,
   409  																Warnings: v7pushaction.Warnings{"upload app archive warning"},
   410  															},
   411  															{
   412  																Plan:     v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   413  																Event:    v7pushaction.RetryUpload,
   414  																Warnings: v7pushaction.Warnings{"retry upload warning"},
   415  															},
   416  															{
   417  																Plan:  v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   418  																Event: v7pushaction.UploadWithArchiveComplete,
   419  															},
   420  															{
   421  																Plan:  v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   422  																Event: v7pushaction.RestartingApplication,
   423  															},
   424  															{
   425  																Plan:  v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   426  																Event: v7pushaction.StartingDeployment,
   427  															},
   428  															{
   429  																Plan:  v7pushaction.PushPlan{Application: v7action.Application{GUID: pushPlan.Application.GUID, Name: pushPlan.Application.Name}},
   430  																Event: v7pushaction.WaitingForDeployment,
   431  															},
   432  														})
   433  													}
   434  												})
   435  
   436  												It("actualizes the application and displays events/warnings", func() {
   437  													Expect(executeErr).ToNot(HaveOccurred())
   438  
   439  													Expect(fakeProgressBar.ReadyCallCount()).Should(Equal(2))
   440  													Expect(fakeProgressBar.CompleteCallCount()).Should(Equal(2))
   441  
   442  													Expect(testUI.Out).To(Say("Packaging files to upload..."))
   443  
   444  													Expect(testUI.Out).To(Say("Uploading files..."))
   445  													Expect(testUI.Err).To(Say("upload app archive warning"))
   446  
   447  													Expect(testUI.Out).To(Say("Retrying upload due to an error..."))
   448  													Expect(testUI.Err).To(Say("retry upload warning"))
   449  
   450  													Expect(testUI.Out).To(Say("Waiting for API to complete processing files..."))
   451  
   452  													Expect(testUI.Out).To(Say("Waiting for app first-app to start..."))
   453  
   454  													Expect(testUI.Out).To(Say("Packaging files to upload..."))
   455  
   456  													Expect(testUI.Out).To(Say("Uploading files..."))
   457  													Expect(testUI.Err).To(Say("upload app archive warning"))
   458  
   459  													Expect(testUI.Out).To(Say("Retrying upload due to an error..."))
   460  													Expect(testUI.Err).To(Say("retry upload warning"))
   461  
   462  													Expect(testUI.Out).To(Say("Waiting for API to complete processing files..."))
   463  
   464  													Expect(testUI.Out).To(Say("Waiting for app second-app to start..."))
   465  
   466  													Expect(testUI.Out).To(Say("Starting deployment for app second-app..."))
   467  
   468  													Expect(testUI.Out).To(Say("Waiting for app to deploy..."))
   469  												})
   470  											})
   471  
   472  											Describe("staging logs", func() {
   473  												BeforeEach(func() {
   474  													fakeActor.ActualizeStub = func(pushPlan v7pushaction.PushPlan, _ v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   475  														return FillInEvents([]Step{
   476  															{Plan: pushPlan, Event: v7pushaction.StartingStaging},
   477  														})
   478  													}
   479  												})
   480  
   481  												When("there are no logging errors", func() {
   482  													BeforeEach(func() {
   483  														fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceStub = ReturnLogs(
   484  															[]LogEvent{
   485  																{Log: v7action.NewLogMessage("log-message-1", "OUT", time.Now(), v7action.StagingLog, "source-instance")},
   486  																{Log: v7action.NewLogMessage("log-message-2", "OUT", time.Now(), v7action.StagingLog, "source-instance")},
   487  																{Log: v7action.NewLogMessage("log-message-3", "OUT", time.Now(), "potato", "source-instance")},
   488  															},
   489  															v7action.Warnings{"log-warning-1", "log-warning-2"},
   490  															nil,
   491  														)
   492  													})
   493  
   494  													It("displays the staging logs and warnings", func() {
   495  														Expect(testUI.Out).To(Say("Staging app and tracing logs..."))
   496  
   497  														Expect(testUI.Err).To(Say("log-warning-1"))
   498  														Expect(testUI.Err).To(Say("log-warning-2"))
   499  
   500  														Eventually(testUI.Out).Should(Say("log-message-1"))
   501  														Eventually(testUI.Out).Should(Say("log-message-2"))
   502  														Eventually(testUI.Out).ShouldNot(Say("log-message-3"))
   503  
   504  														Expect(fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceCallCount()).To(Equal(2))
   505  														passedAppName, spaceGUID, _ := fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(0)
   506  														Expect(passedAppName).To(Equal(appName1))
   507  														Expect(spaceGUID).To(Equal("some-space-guid"))
   508  														passedAppName, spaceGUID, _ = fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceArgsForCall(1)
   509  														Expect(passedAppName).To(Equal(appName2))
   510  														Expect(spaceGUID).To(Equal("some-space-guid"))
   511  
   512  													})
   513  												})
   514  
   515  												When("there are logging errors", func() {
   516  													BeforeEach(func() {
   517  														fakeVersionActor.GetStreamingLogsForApplicationByNameAndSpaceStub = ReturnLogs(
   518  															[]LogEvent{
   519  																{Error: errors.New("some-random-err")},
   520  																{Error: actionerror.LogCacheTimeoutError{}},
   521  																{Log: v7action.NewLogMessage("log-message-1", "OUT", time.Now(), v7action.StagingLog, "source-instance")},
   522  															},
   523  															v7action.Warnings{"log-warning-1", "log-warning-2"},
   524  															nil,
   525  														)
   526  													})
   527  
   528  													It("displays the errors as warnings", func() {
   529  														Expect(testUI.Out).To(Say("Staging app and tracing logs..."))
   530  
   531  														Expect(testUI.Err).To(Say("log-warning-1"))
   532  														Expect(testUI.Err).To(Say("log-warning-2"))
   533  														Eventually(testUI.Err).Should(Say("some-random-err"))
   534  														Eventually(testUI.Err).Should(Say("timeout connecting to log server, no log will be shown"))
   535  
   536  														Eventually(testUI.Out).Should(Say("log-message-1"))
   537  													})
   538  												})
   539  											})
   540  
   541  											When("when getting the application summary succeeds", func() {
   542  												BeforeEach(func() {
   543  													summary := v7action.DetailedApplicationSummary{
   544  														ApplicationSummary: v7action.ApplicationSummary{
   545  															Application:      v7action.Application{},
   546  															ProcessSummaries: v7action.ProcessSummaries{},
   547  														},
   548  														CurrentDroplet: v7action.Droplet{},
   549  													}
   550  													fakeVersionActor.GetDetailedAppSummaryReturnsOnCall(0, summary, v7action.Warnings{"app-1-summary-warning-1", "app-1-summary-warning-2"}, nil)
   551  													fakeVersionActor.GetDetailedAppSummaryReturnsOnCall(1, summary, v7action.Warnings{"app-2-summary-warning-1", "app-2-summary-warning-2"}, nil)
   552  												})
   553  
   554  												// TODO: Don't test the shared.AppSummaryDisplayer.AppDisplay method.
   555  												// Use DI to pass in a new AppSummaryDisplayer to the Command instead.
   556  												It("displays the app summary", func() {
   557  													Expect(executeErr).ToNot(HaveOccurred())
   558  													Expect(fakeVersionActor.GetDetailedAppSummaryCallCount()).To(Equal(2))
   559  												})
   560  											})
   561  
   562  											When("getting the application summary fails", func() {
   563  												BeforeEach(func() {
   564  													fakeVersionActor.GetDetailedAppSummaryReturns(
   565  														v7action.DetailedApplicationSummary{},
   566  														v7action.Warnings{"get-application-summary-warnings"},
   567  														errors.New("get-application-summary-error"),
   568  													)
   569  												})
   570  
   571  												It("does not display the app summary", func() {
   572  													Expect(testUI.Out).ToNot(Say(`requested state:`))
   573  												})
   574  
   575  												It("returns the error from GetDetailedAppSummary", func() {
   576  													Expect(executeErr).To(MatchError("get-application-summary-error"))
   577  												})
   578  
   579  												It("prints the warnings", func() {
   580  													Expect(testUI.Err).To(Say("get-application-summary-warnings"))
   581  												})
   582  											})
   583  
   584  										})
   585  
   586  										When("actualize returns an error", func() {
   587  											When("the error is generic", func() {
   588  												BeforeEach(func() {
   589  													fakeActor.ActualizeStub = func(v7pushaction.PushPlan, v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   590  														return FillInEvents([]Step{
   591  															{Error: errors.New("anti avant garde naming")},
   592  														})
   593  													}
   594  												})
   595  
   596  												It("returns the error", func() {
   597  													Expect(executeErr).To(MatchError("anti avant garde naming"))
   598  												})
   599  											})
   600  
   601  											When("the error is a startup timeout error", func() {
   602  												BeforeEach(func() {
   603  													fakeActor.ActualizeStub = func(v7pushaction.PushPlan, v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   604  														return FillInEvents([]Step{
   605  															{Error: actionerror.StartupTimeoutError{}},
   606  														})
   607  													}
   608  												})
   609  
   610  												It("returns the StartupTimeoutError and prints warnings", func() {
   611  													Expect(executeErr).To(MatchError(translatableerror.StartupTimeoutError{
   612  														AppName:    "first-app",
   613  														BinaryName: binaryName,
   614  													}))
   615  												})
   616  											})
   617  
   618  											When("the error is a process crashed error", func() {
   619  												BeforeEach(func() {
   620  													fakeActor.ActualizeStub = func(v7pushaction.PushPlan, v7pushaction.ProgressBar) <-chan *v7pushaction.PushEvent {
   621  														return FillInEvents([]Step{
   622  															{Error: actionerror.AllInstancesCrashedError{}},
   623  														})
   624  													}
   625  												})
   626  
   627  												It("returns the ApplicationUnableToStartError", func() {
   628  													Expect(executeErr).To(MatchError(translatableerror.ApplicationUnableToStartError{
   629  														AppName:    "first-app",
   630  														BinaryName: binaryName,
   631  													}))
   632  												})
   633  
   634  												It("displays the app summary", func() {
   635  													Expect(executeErr).To(HaveOccurred())
   636  													Expect(fakeVersionActor.GetDetailedAppSummaryCallCount()).To(Equal(1))
   637  												})
   638  											})
   639  										})
   640  									})
   641  								})
   642  							})
   643  						})
   644  					})
   645  				})
   646  			})
   647  		})
   648  	})
   649  
   650  	Describe("GetDockerPassword", func() {
   651  		var (
   652  			cmd        PushCommand
   653  			fakeConfig *commandfakes.FakeConfig
   654  			testUI     *ui.UI
   655  
   656  			dockerUsername        string
   657  			containsPrivateDocker bool
   658  
   659  			executeErr     error
   660  			dockerPassword string
   661  
   662  			input *Buffer
   663  		)
   664  
   665  		BeforeEach(func() {
   666  			input = NewBuffer()
   667  			testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
   668  			fakeConfig = new(commandfakes.FakeConfig)
   669  
   670  			cmd = PushCommand{
   671  				Config: fakeConfig,
   672  				UI:     testUI,
   673  			}
   674  		})
   675  
   676  		Describe("Get", func() {
   677  			JustBeforeEach(func() {
   678  				dockerPassword, executeErr = cmd.GetDockerPassword(dockerUsername, containsPrivateDocker)
   679  			})
   680  
   681  			When("docker image is private", func() {
   682  				When("there is a manifest", func() {
   683  					BeforeEach(func() {
   684  						dockerUsername = ""
   685  						containsPrivateDocker = true
   686  					})
   687  
   688  					When("a password is provided via environment variable", func() {
   689  						BeforeEach(func() {
   690  							fakeConfig.DockerPasswordReturns("some-docker-password")
   691  						})
   692  
   693  						It("takes the password from the environment", func() {
   694  							Expect(executeErr).ToNot(HaveOccurred())
   695  
   696  							Expect(testUI.Out).ToNot(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   697  							Expect(testUI.Out).ToNot(Say("Docker password"))
   698  
   699  							Expect(testUI.Out).To(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD."))
   700  
   701  							Expect(dockerPassword).To(Equal("some-docker-password"))
   702  						})
   703  					})
   704  
   705  					When("no password is provided", func() {
   706  						BeforeEach(func() {
   707  							_, err := input.Write([]byte("some-docker-password\n"))
   708  							Expect(err).ToNot(HaveOccurred())
   709  						})
   710  
   711  						It("prompts for a password", func() {
   712  							Expect(executeErr).ToNot(HaveOccurred())
   713  
   714  							Expect(testUI.Out).To(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   715  							Expect(testUI.Out).To(Say("Docker password"))
   716  
   717  							Expect(dockerPassword).To(Equal("some-docker-password"))
   718  						})
   719  					})
   720  				})
   721  
   722  				When("there is no manifest", func() {
   723  					BeforeEach(func() {
   724  						dockerUsername = "some-docker-username"
   725  						containsPrivateDocker = false
   726  					})
   727  
   728  					When("a password is provided via environment variable", func() {
   729  						BeforeEach(func() {
   730  							fakeConfig.DockerPasswordReturns("some-docker-password")
   731  						})
   732  
   733  						It("takes the password from the environment", func() {
   734  							Expect(executeErr).ToNot(HaveOccurred())
   735  
   736  							Expect(testUI.Out).ToNot(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   737  							Expect(testUI.Out).ToNot(Say("Docker password"))
   738  
   739  							Expect(testUI.Out).To(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD."))
   740  
   741  							Expect(dockerPassword).To(Equal("some-docker-password"))
   742  						})
   743  					})
   744  
   745  					When("no password is provided", func() {
   746  						BeforeEach(func() {
   747  							_, err := input.Write([]byte("some-docker-password\n"))
   748  							Expect(err).ToNot(HaveOccurred())
   749  						})
   750  
   751  						It("prompts for a password", func() {
   752  							Expect(executeErr).ToNot(HaveOccurred())
   753  
   754  							Expect(testUI.Out).To(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   755  							Expect(testUI.Out).To(Say("Docker password"))
   756  
   757  							Expect(dockerPassword).To(Equal("some-docker-password"))
   758  						})
   759  					})
   760  				})
   761  			})
   762  			When("docker image is public", func() {
   763  				BeforeEach(func() {
   764  					dockerUsername = ""
   765  					containsPrivateDocker = false
   766  				})
   767  
   768  				It("does not prompt for a password", func() {
   769  					Expect(testUI.Out).ToNot(Say("Environment variable CF_DOCKER_PASSWORD not set."))
   770  					Expect(testUI.Out).ToNot(Say("Docker password"))
   771  					Expect(testUI.Out).ToNot(Say("Using docker repository password from environment variable CF_DOCKER_PASSWORD."))
   772  				})
   773  
   774  				It("returns an empty password", func() {
   775  					Expect(executeErr).ToNot(HaveOccurred())
   776  					Expect(dockerPassword).To(Equal(""))
   777  				})
   778  			})
   779  		})
   780  	})
   781  
   782  	Describe("GetBaseManifest", func() {
   783  		var (
   784  			somePath      string
   785  			flagOverrides v7pushaction.FlagOverrides
   786  			manifest      manifestparser.Manifest
   787  			executeErr    error
   788  		)
   789  
   790  		JustBeforeEach(func() {
   791  			manifest, executeErr = cmd.GetBaseManifest(flagOverrides)
   792  		})
   793  
   794  		When("no flags are specified", func() {
   795  			BeforeEach(func() {
   796  				cmd.CWD = somePath
   797  			})
   798  
   799  			When("a manifest exists in the current dir", func() {
   800  				BeforeEach(func() {
   801  					fakeManifestLocator.PathReturns("/manifest/path", true, nil)
   802  					fakeManifestParser.InterpolateAndParseReturns(
   803  						manifestparser.Manifest{
   804  							Applications: []manifestparser.Application{
   805  								{Name: "new-app"},
   806  							},
   807  						},
   808  						nil,
   809  					)
   810  				})
   811  
   812  				It("uses the manifest in the current directory", func() {
   813  					Expect(executeErr).ToNot(HaveOccurred())
   814  					Expect(manifest).To(Equal(
   815  						manifestparser.Manifest{
   816  							Applications: []manifestparser.Application{
   817  								{Name: "new-app"},
   818  							},
   819  						}),
   820  					)
   821  
   822  					Expect(fakeManifestLocator.PathCallCount()).To(Equal(1))
   823  					Expect(fakeManifestLocator.PathArgsForCall(0)).To(Equal(cmd.CWD))
   824  
   825  					Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(1))
   826  					actualManifestPath, _, _ := fakeManifestParser.InterpolateAndParseArgsForCall(0)
   827  					Expect(actualManifestPath).To(Equal("/manifest/path"))
   828  				})
   829  			})
   830  
   831  			When("there is not a manifest in the current dir", func() {
   832  				BeforeEach(func() {
   833  					flagOverrides.AppName = "new-app"
   834  					fakeManifestLocator.PathReturns("", false, nil)
   835  				})
   836  
   837  				It("ignores the file not found error", func() {
   838  					Expect(executeErr).ToNot(HaveOccurred())
   839  					Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(0))
   840  				})
   841  
   842  				It("returns a default empty manifest", func() {
   843  					Expect(manifest).To(Equal(
   844  						manifestparser.Manifest{
   845  							Applications: []manifestparser.Application{
   846  								{Name: "new-app"},
   847  							},
   848  						}),
   849  					)
   850  				})
   851  			})
   852  
   853  			When("when there is an error locating the manifest in the current directory", func() {
   854  				BeforeEach(func() {
   855  					fakeManifestLocator.PathReturns("", false, errors.New("err-location"))
   856  				})
   857  
   858  				It("returns the error", func() {
   859  					Expect(executeErr).To(MatchError("err-location"))
   860  					Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(0))
   861  				})
   862  			})
   863  
   864  			When("parsing the manifest fails", func() {
   865  				BeforeEach(func() {
   866  					fakeManifestLocator.PathReturns("/manifest/path", true, nil)
   867  					fakeManifestParser.InterpolateAndParseReturns(
   868  						manifestparser.Manifest{},
   869  						errors.New("bad yaml"),
   870  					)
   871  				})
   872  
   873  				It("returns the error", func() {
   874  					Expect(executeErr).To(MatchError("bad yaml"))
   875  					Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(1))
   876  				})
   877  			})
   878  		})
   879  
   880  		When("The -f flag is specified", func() {
   881  			BeforeEach(func() {
   882  				somePath = "some-path"
   883  				flagOverrides.ManifestPath = somePath
   884  				fakeManifestLocator.PathReturns("/manifest/path", true, nil)
   885  				fakeManifestParser.InterpolateAndParseReturns(
   886  					manifestparser.Manifest{
   887  						Applications: []manifestparser.Application{
   888  							{Name: "new-app"},
   889  						},
   890  					},
   891  					nil,
   892  				)
   893  			})
   894  
   895  			It("parses the specified manifest", func() {
   896  				Expect(executeErr).ToNot(HaveOccurred())
   897  
   898  				Expect(fakeManifestLocator.PathCallCount()).To(Equal(1))
   899  				Expect(fakeManifestLocator.PathArgsForCall(0)).To(Equal(somePath))
   900  
   901  				Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(1))
   902  				actualManifestPath, _, _ := fakeManifestParser.InterpolateAndParseArgsForCall(0)
   903  				Expect(actualManifestPath).To(Equal("/manifest/path"))
   904  				Expect(manifest).To(Equal(
   905  					manifestparser.Manifest{
   906  						Applications: []manifestparser.Application{
   907  							{Name: "new-app"},
   908  						},
   909  					}),
   910  				)
   911  			})
   912  		})
   913  
   914  		When("--vars-files are specified", func() {
   915  			var varsFiles []string
   916  
   917  			BeforeEach(func() {
   918  				fakeManifestLocator.PathReturns("/manifest/path", true, nil)
   919  				varsFiles = []string{"path1", "path2"}
   920  				flagOverrides.PathsToVarsFiles = append(flagOverrides.PathsToVarsFiles, varsFiles...)
   921  			})
   922  
   923  			It("passes vars files to the manifest parser", func() {
   924  				Expect(executeErr).ToNot(HaveOccurred())
   925  
   926  				Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(1))
   927  				_, actualVarsFiles, _ := fakeManifestParser.InterpolateAndParseArgsForCall(0)
   928  				Expect(actualVarsFiles).To(Equal(varsFiles))
   929  			})
   930  		})
   931  
   932  		When("The --var flag is provided", func() {
   933  			var vars []template.VarKV
   934  
   935  			BeforeEach(func() {
   936  				fakeManifestLocator.PathReturns("/manifest/path", true, nil)
   937  				vars = []template.VarKV{
   938  					{Name: "put-var-here", Value: "turtle"},
   939  				}
   940  				flagOverrides.Vars = vars
   941  			})
   942  
   943  			It("passes vars files to the manifest parser", func() {
   944  				Expect(executeErr).ToNot(HaveOccurred())
   945  
   946  				Expect(fakeManifestParser.InterpolateAndParseCallCount()).To(Equal(1))
   947  				_, _, actualVars := fakeManifestParser.InterpolateAndParseArgsForCall(0)
   948  				Expect(actualVars).To(Equal(vars))
   949  			})
   950  		})
   951  	})
   952  
   953  	Describe("GetFlagOverrides", func() {
   954  		var (
   955  			overrides    v7pushaction.FlagOverrides
   956  			overridesErr error
   957  		)
   958  
   959  		BeforeEach(func() {
   960  			cmd.Buildpacks = []string{"buildpack-1", "buildpack-2"}
   961  			cmd.Stack = "validStack"
   962  			cmd.HealthCheckType = flag.HealthCheckType{Type: constant.Port}
   963  			cmd.HealthCheckHTTPEndpoint = "/health-check-http-endpoint"
   964  			cmd.HealthCheckTimeout = flag.PositiveInteger{Value: 7}
   965  			cmd.Memory = "64M"
   966  			cmd.Disk = "256M"
   967  			cmd.DropletPath = flag.PathWithExistenceCheck("some-droplet.tgz")
   968  			cmd.StartCommand = flag.Command{FilteredString: types.FilteredString{IsSet: true, Value: "some-start-command"}}
   969  			cmd.NoRoute = true
   970  			cmd.RandomRoute = false
   971  			cmd.NoStart = true
   972  			cmd.NoWait = true
   973  			cmd.Strategy = flag.DeploymentStrategy{Name: constant.DeploymentStrategyRolling}
   974  			cmd.Instances = flag.Instances{NullInt: types.NullInt{Value: 10, IsSet: true}}
   975  			cmd.PathToManifest = "/manifest/path"
   976  			cmd.PathsToVarsFiles = []flag.PathWithExistenceCheck{"/vars1", "/vars2"}
   977  			cmd.Vars = []template.VarKV{{Name: "key", Value: "val"}}
   978  			cmd.Task = true
   979  		})
   980  
   981  		JustBeforeEach(func() {
   982  			overrides, overridesErr = cmd.GetFlagOverrides()
   983  			Expect(overridesErr).ToNot(HaveOccurred())
   984  		})
   985  
   986  		It("sets them on the flag overrides", func() {
   987  			Expect(overridesErr).ToNot(HaveOccurred())
   988  			Expect(overrides.Buildpacks).To(ConsistOf("buildpack-1", "buildpack-2"))
   989  			Expect(overrides.DropletPath).To(Equal("some-droplet.tgz"))
   990  			Expect(overrides.Stack).To(Equal("validStack"))
   991  			Expect(overrides.HealthCheckType).To(Equal(constant.Port))
   992  			Expect(overrides.HealthCheckEndpoint).To(Equal("/health-check-http-endpoint"))
   993  			Expect(overrides.HealthCheckTimeout).To(BeEquivalentTo(7))
   994  			Expect(overrides.Memory).To(Equal("64M"))
   995  			Expect(overrides.Disk).To(Equal("256M"))
   996  			Expect(overrides.StartCommand).To(Equal(types.FilteredString{IsSet: true, Value: "some-start-command"}))
   997  			Expect(overrides.NoRoute).To(BeTrue())
   998  			Expect(overrides.NoStart).To(BeTrue())
   999  			Expect(overrides.NoWait).To(BeTrue())
  1000  			Expect(overrides.RandomRoute).To(BeFalse())
  1001  			Expect(overrides.Strategy).To(Equal(constant.DeploymentStrategyRolling))
  1002  			Expect(overrides.Instances).To(Equal(types.NullInt{Value: 10, IsSet: true}))
  1003  			Expect(overrides.ManifestPath).To(Equal("/manifest/path"))
  1004  			Expect(overrides.PathsToVarsFiles).To(Equal([]string{"/vars1", "/vars2"}))
  1005  			Expect(overrides.Vars).To(Equal([]template.VarKV{{Name: "key", Value: "val"}}))
  1006  			Expect(overrides.Task).To(BeTrue())
  1007  		})
  1008  
  1009  		When("a docker image is provided", func() {
  1010  			BeforeEach(func() {
  1011  				cmd.DockerImage = flag.DockerImage{Path: "some-docker-image"}
  1012  			})
  1013  
  1014  			It("sets docker image on the flag overrides", func() {
  1015  				Expect(overridesErr).ToNot(HaveOccurred())
  1016  				Expect(overrides.DockerImage).To(Equal("some-docker-image"))
  1017  			})
  1018  		})
  1019  	})
  1020  
  1021  	DescribeTable("ValidateFlags returns an error",
  1022  		func(setup func(), expectedErr error) {
  1023  			setup()
  1024  			err := cmd.ValidateFlags()
  1025  			if expectedErr == nil {
  1026  				Expect(err).To(BeNil())
  1027  			} else {
  1028  				Expect(err).To(MatchError(expectedErr))
  1029  			}
  1030  		},
  1031  
  1032  		Entry("when docker username flag is passed *without* docker flag",
  1033  			func() {
  1034  				cmd.DockerUsername = "some-docker-username"
  1035  			},
  1036  			translatableerror.RequiredFlagsError{Arg1: "--docker-image, -o", Arg2: "--docker-username"}),
  1037  
  1038  		Entry("when docker and buildpacks flags are passed",
  1039  			func() {
  1040  				cmd.DockerImage.Path = "some-docker-image"
  1041  				cmd.Buildpacks = []string{"some-buildpack"}
  1042  			},
  1043  			translatableerror.ArgumentCombinationError{Args: []string{"--buildpack, -b", "--docker-image, -o"}}),
  1044  
  1045  		Entry("when docker and stack flags are passed",
  1046  			func() {
  1047  				cmd.DockerImage.Path = "some-docker-image"
  1048  				cmd.Stack = "validStack"
  1049  			},
  1050  			translatableerror.ArgumentCombinationError{Args: []string{"--stack, -s", "--docker-image, -o"}}),
  1051  
  1052  		Entry("when docker and path flags are passed",
  1053  			func() {
  1054  				cmd.DockerImage.Path = "some-docker-image"
  1055  				cmd.AppPath = "some-directory-path"
  1056  			},
  1057  			translatableerror.ArgumentCombinationError{Args: []string{"--docker-image, -o", "--path, -p"}}),
  1058  
  1059  		Entry("when -u http does not have a matching --endpoint",
  1060  			func() {
  1061  				cmd.HealthCheckType.Type = constant.HTTP
  1062  			},
  1063  			translatableerror.RequiredFlagsError{Arg1: "--endpoint", Arg2: "--health-check-type=http, -u=http"}),
  1064  
  1065  		Entry("when -u http does have a matching --endpoint",
  1066  			func() {
  1067  				cmd.HealthCheckType.Type = constant.HTTP
  1068  				cmd.HealthCheckHTTPEndpoint = "/health"
  1069  			},
  1070  			nil),
  1071  
  1072  		Entry("when droplet and path flags are passed",
  1073  			func() {
  1074  				cmd.DropletPath = "some-droplet.tgz"
  1075  				cmd.AppPath = "/my/app"
  1076  			},
  1077  			translatableerror.ArgumentCombinationError{
  1078  				Args: []string{
  1079  					"--droplet", "--docker-image, -o", "--docker-username", "-p",
  1080  				},
  1081  			}),
  1082  
  1083  		Entry("when droplet and docker image flags are passed",
  1084  			func() {
  1085  				cmd.DropletPath = "some-droplet.tgz"
  1086  				cmd.DockerImage.Path = "docker-image"
  1087  			},
  1088  			translatableerror.ArgumentCombinationError{
  1089  				Args: []string{
  1090  					"--droplet", "--docker-image, -o", "--docker-username", "-p",
  1091  				},
  1092  			}),
  1093  
  1094  		Entry("when droplet, docker image, and docker username flags are passed",
  1095  			func() {
  1096  				cmd.DropletPath = "some-droplet.tgz"
  1097  				cmd.DockerImage.Path = "docker-image"
  1098  				cmd.DockerUsername = "docker-username"
  1099  			},
  1100  			translatableerror.ArgumentCombinationError{
  1101  				Args: []string{
  1102  					"--droplet", "--docker-image, -o", "--docker-username", "-p",
  1103  				},
  1104  			}),
  1105  
  1106  		Entry("when strategy 'rolling' and no-start flags are passed",
  1107  			func() {
  1108  				cmd.Strategy = flag.DeploymentStrategy{Name: constant.DeploymentStrategyRolling}
  1109  				cmd.NoStart = true
  1110  			},
  1111  			translatableerror.ArgumentCombinationError{
  1112  				Args: []string{
  1113  					"--no-start", "--strategy=rolling",
  1114  				},
  1115  			}),
  1116  
  1117  		Entry("when strategy is not set and no-start flags are passed",
  1118  			func() {
  1119  				cmd.Strategy = flag.DeploymentStrategy{Name: constant.DeploymentStrategyDefault}
  1120  				cmd.NoStart = true
  1121  			},
  1122  			nil),
  1123  
  1124  		Entry("when no-start and no-wait flags are passed",
  1125  			func() {
  1126  				cmd.NoStart = true
  1127  				cmd.NoWait = true
  1128  			},
  1129  			translatableerror.ArgumentCombinationError{
  1130  				Args: []string{
  1131  					"--no-start", "--no-wait",
  1132  				},
  1133  			}),
  1134  		Entry("when no-route and random-route flags are passed",
  1135  			func() {
  1136  				cmd.NoRoute = true
  1137  				cmd.RandomRoute = true
  1138  			},
  1139  			translatableerror.ArgumentCombinationError{
  1140  				Args: []string{
  1141  					"--no-route", "--random-route",
  1142  				},
  1143  			}),
  1144  
  1145  		Entry("default is combined with non default buildpacks",
  1146  			func() {
  1147  				cmd.Buildpacks = []string{"some-docker-username", "default"}
  1148  			},
  1149  			translatableerror.InvalidBuildpacksError{}),
  1150  
  1151  		Entry("default is combined with non default buildpacks",
  1152  			func() {
  1153  				cmd.Buildpacks = []string{"some-docker-username", "null"}
  1154  			},
  1155  			translatableerror.InvalidBuildpacksError{}),
  1156  
  1157  		Entry("task and strategy flags are passed",
  1158  			func() {
  1159  				cmd.Task = true
  1160  				cmd.Strategy = flag.DeploymentStrategy{Name: constant.DeploymentStrategyRolling}
  1161  			},
  1162  			translatableerror.ArgumentCombinationError{
  1163  				Args: []string{
  1164  					"--task", "--strategy=rolling",
  1165  				},
  1166  			}),
  1167  	)
  1168  })