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

     1  package v6_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/bytefmt"
     8  	"code.cloudfoundry.org/cli/actor/actionerror"
     9  	"code.cloudfoundry.org/cli/actor/v2action"
    10  	"code.cloudfoundry.org/cli/actor/v2v3action"
    11  	"code.cloudfoundry.org/cli/actor/v3action"
    12  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv2/constant"
    13  	"code.cloudfoundry.org/cli/command/commandfakes"
    14  	"code.cloudfoundry.org/cli/command/translatableerror"
    15  	. "code.cloudfoundry.org/cli/command/v6"
    16  	"code.cloudfoundry.org/cli/command/v6/shared/sharedfakes"
    17  	"code.cloudfoundry.org/cli/command/v6/v6fakes"
    18  	"code.cloudfoundry.org/cli/types"
    19  	"code.cloudfoundry.org/cli/util/configv3"
    20  	"code.cloudfoundry.org/cli/util/ui"
    21  	. "github.com/onsi/ginkgo"
    22  	. "github.com/onsi/gomega"
    23  	. "github.com/onsi/gomega/gbytes"
    24  )
    25  
    26  var _ = Describe("Start Command", func() {
    27  	var (
    28  		cmd                         StartCommand
    29  		testUI                      *ui.UI
    30  		fakeConfig                  *commandfakes.FakeConfig
    31  		fakeSharedActor             *commandfakes.FakeSharedActor
    32  		fakeActor                   *v6fakes.FakeStartActor
    33  		fakeApplicationSummaryActor *sharedfakes.FakeApplicationSummaryActor
    34  		binaryName                  string
    35  		appName                     string
    36  		executeErr                  error
    37  	)
    38  
    39  	BeforeEach(func() {
    40  		testUI = ui.NewTestUI(nil, NewBuffer(), NewBuffer())
    41  		fakeConfig = new(commandfakes.FakeConfig)
    42  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    43  		fakeActor = new(v6fakes.FakeStartActor)
    44  		fakeApplicationSummaryActor = new(sharedfakes.FakeApplicationSummaryActor)
    45  
    46  		cmd = StartCommand{
    47  			UI:                      testUI,
    48  			Config:                  fakeConfig,
    49  			SharedActor:             fakeSharedActor,
    50  			Actor:                   fakeActor,
    51  			ApplicationSummaryActor: fakeApplicationSummaryActor,
    52  		}
    53  
    54  		appName = "some-app"
    55  		cmd.RequiredArgs.AppName = appName
    56  
    57  		binaryName = "faceman"
    58  		fakeConfig.BinaryNameReturns(binaryName)
    59  
    60  		var err error
    61  		testUI.TimezoneLocation, err = time.LoadLocation("America/Los_Angeles")
    62  		Expect(err).NotTo(HaveOccurred())
    63  
    64  		fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
    65  			messages := make(chan *v2action.LogMessage)
    66  			logErrs := make(chan error)
    67  			appState := make(chan v2action.ApplicationStateChange)
    68  			warnings := make(chan string)
    69  			errs := make(chan error)
    70  
    71  			go func() {
    72  				close(messages)
    73  				close(logErrs)
    74  				close(appState)
    75  				close(warnings)
    76  				close(errs)
    77  			}()
    78  
    79  			return messages, logErrs, appState, warnings, errs
    80  		}
    81  	})
    82  
    83  	JustBeforeEach(func() {
    84  		executeErr = cmd.Execute(nil)
    85  	})
    86  
    87  	When("checking target fails", func() {
    88  		BeforeEach(func() {
    89  			fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName})
    90  		})
    91  
    92  		It("returns an error if the check fails", func() {
    93  			Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: "faceman"}))
    94  
    95  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    96  			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
    97  			Expect(checkTargetedOrg).To(BeTrue())
    98  			Expect(checkTargetedSpace).To(BeTrue())
    99  		})
   100  	})
   101  
   102  	When("the user is logged in, and org and space are targeted", func() {
   103  		BeforeEach(func() {
   104  			fakeConfig.HasTargetedOrganizationReturns(true)
   105  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"})
   106  			fakeConfig.HasTargetedSpaceReturns(true)
   107  			fakeConfig.TargetedSpaceReturns(configv3.Space{
   108  				GUID: "some-space-guid",
   109  				Name: "some-space"})
   110  			fakeConfig.CurrentUserReturns(
   111  				configv3.User{Name: "some-user"},
   112  				nil)
   113  		})
   114  
   115  		When("getting the current user returns an error", func() {
   116  			var expectedErr error
   117  
   118  			BeforeEach(func() {
   119  				expectedErr = errors.New("getting current user error")
   120  				fakeConfig.CurrentUserReturns(
   121  					configv3.User{},
   122  					expectedErr)
   123  			})
   124  
   125  			It("returns the error", func() {
   126  				Expect(executeErr).To(MatchError(expectedErr))
   127  			})
   128  		})
   129  
   130  		It("displays flavor text", func() {
   131  			Expect(testUI.Out).To(Say("Starting app %s in org some-org / space some-space as some-user...", appName))
   132  		})
   133  
   134  		When("the app exists", func() {
   135  			When("the app is already started", func() {
   136  				BeforeEach(func() {
   137  					fakeActor.GetApplicationByNameAndSpaceReturns(
   138  						v2action.Application{State: constant.ApplicationStarted},
   139  						v2action.Warnings{"warning-1", "warning-2"},
   140  						nil,
   141  					)
   142  				})
   143  
   144  				It("short circuits and displays message", func() {
   145  					Expect(executeErr).ToNot(HaveOccurred())
   146  
   147  					Expect(testUI.Out).To(Say("App %s is already started", appName))
   148  
   149  					Expect(testUI.Err).To(Say("warning-1"))
   150  					Expect(testUI.Err).To(Say("warning-2"))
   151  
   152  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(0))
   153  				})
   154  			})
   155  
   156  			When("the app is not already started", func() {
   157  				BeforeEach(func() {
   158  					fakeActor.GetApplicationByNameAndSpaceReturns(
   159  						v2action.Application{GUID: "app-guid", State: constant.ApplicationStopped},
   160  						v2action.Warnings{"warning-1", "warning-2"},
   161  						nil,
   162  					)
   163  				})
   164  
   165  				It("starts the app", func() {
   166  					Expect(executeErr).ToNot(HaveOccurred())
   167  
   168  					Expect(testUI.Err).To(Say("warning-1"))
   169  					Expect(testUI.Err).To(Say("warning-2"))
   170  
   171  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   172  					app, _ := fakeActor.StartApplicationArgsForCall(0)
   173  					Expect(app.GUID).To(Equal("app-guid"))
   174  				})
   175  
   176  				When("passed an ApplicationStateStarting message", func() {
   177  					BeforeEach(func() {
   178  						fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   179  							messages := make(chan *v2action.LogMessage)
   180  							logErrs := make(chan error)
   181  							appState := make(chan v2action.ApplicationStateChange)
   182  							warnings := make(chan string)
   183  							errs := make(chan error)
   184  
   185  							go func() {
   186  								messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1")
   187  								messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1")
   188  								appState <- v2action.ApplicationStateStarting
   189  								close(messages)
   190  								close(logErrs)
   191  								close(appState)
   192  								close(warnings)
   193  								close(errs)
   194  							}()
   195  
   196  							return messages, logErrs, appState, warnings, errs
   197  						}
   198  					})
   199  
   200  					It("displays the log", func() {
   201  						Expect(executeErr).ToNot(HaveOccurred())
   202  						Expect(testUI.Out).To(Say("log message 1"))
   203  						Expect(testUI.Out).To(Say("log message 2"))
   204  						Expect(testUI.Out).To(Say("Waiting for app to start..."))
   205  					})
   206  				})
   207  
   208  				When("passed a log message", func() {
   209  					BeforeEach(func() {
   210  						fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   211  							messages := make(chan *v2action.LogMessage)
   212  							logErrs := make(chan error)
   213  							appState := make(chan v2action.ApplicationStateChange)
   214  							warnings := make(chan string)
   215  							errs := make(chan error)
   216  
   217  							go func() {
   218  								messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1")
   219  								messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1")
   220  								messages <- v2action.NewLogMessage("log message 3", 1, time.Unix(0, 0), "Something else", "1")
   221  								close(messages)
   222  								close(logErrs)
   223  								close(appState)
   224  								close(warnings)
   225  								close(errs)
   226  							}()
   227  
   228  							return messages, logErrs, appState, warnings, errs
   229  						}
   230  					})
   231  
   232  					It("displays the log", func() {
   233  						Expect(executeErr).ToNot(HaveOccurred())
   234  						Expect(testUI.Out).To(Say("log message 1"))
   235  						Expect(testUI.Out).To(Say("log message 2"))
   236  						Expect(testUI.Out).ToNot(Say("log message 3"))
   237  					})
   238  				})
   239  
   240  				When("passed an log err", func() {
   241  					Context("NOAA connection times out/closes", func() {
   242  						BeforeEach(func() {
   243  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   244  								messages := make(chan *v2action.LogMessage)
   245  								logErrs := make(chan error)
   246  								appState := make(chan v2action.ApplicationStateChange)
   247  								warnings := make(chan string)
   248  								errs := make(chan error)
   249  
   250  								go func() {
   251  									messages <- v2action.NewLogMessage("log message 1", 1, time.Unix(0, 0), "STG", "1")
   252  									messages <- v2action.NewLogMessage("log message 2", 1, time.Unix(0, 0), "STG", "1")
   253  									messages <- v2action.NewLogMessage("log message 3", 1, time.Unix(0, 0), "STG", "1")
   254  									logErrs <- actionerror.NOAATimeoutError{}
   255  									close(messages)
   256  									close(logErrs)
   257  									close(appState)
   258  									close(warnings)
   259  									close(errs)
   260  								}()
   261  
   262  								return messages, logErrs, appState, warnings, errs
   263  							}
   264  
   265  							applicationSummary := v2action.ApplicationSummary{
   266  								Application: v2action.Application{
   267  									Name:                 appName,
   268  									GUID:                 "some-app-guid",
   269  									Instances:            types.NullInt{Value: 3, IsSet: true},
   270  									Memory:               types.NullByteSizeInMb{IsSet: true, Value: 128},
   271  									PackageUpdatedAt:     time.Unix(0, 0),
   272  									DetectedBuildpack:    types.FilteredString{IsSet: true, Value: "some-buildpack"},
   273  									State:                "STARTED",
   274  									DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"},
   275  								},
   276  								Stack: v2action.Stack{
   277  									Name: "potatos",
   278  								},
   279  								Routes: []v2action.Route{
   280  									{
   281  										Host: "banana",
   282  										Domain: v2action.Domain{
   283  											Name: "fruit.com",
   284  										},
   285  										Path: "/hi",
   286  									},
   287  									{
   288  										Domain: v2action.Domain{
   289  											Name: "foobar.com",
   290  										},
   291  										Port: types.NullInt{IsSet: true, Value: 13},
   292  									},
   293  								},
   294  							}
   295  							warnings := []string{"app-summary-warning"}
   296  
   297  							applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{}
   298  
   299  							fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   300  						})
   301  
   302  						It("displays a warning and continues until app has started", func() {
   303  							Expect(executeErr).To(BeNil())
   304  							Expect(testUI.Out).To(Say("message 1"))
   305  							Expect(testUI.Out).To(Say("message 2"))
   306  							Expect(testUI.Out).To(Say("message 3"))
   307  							Expect(testUI.Err).To(Say("timeout connecting to log server, no log will be shown"))
   308  							Expect(testUI.Out).To(Say(`name:\s+%s`, appName))
   309  						})
   310  					})
   311  
   312  					Context("an unexpected error occurs", func() {
   313  						var expectedErr error
   314  
   315  						BeforeEach(func() {
   316  							expectedErr = errors.New("err log message")
   317  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   318  								messages := make(chan *v2action.LogMessage)
   319  								logErrs := make(chan error)
   320  								appState := make(chan v2action.ApplicationStateChange)
   321  								warnings := make(chan string)
   322  								errs := make(chan error)
   323  
   324  								go func() {
   325  									logErrs <- expectedErr
   326  									close(messages)
   327  									close(logErrs)
   328  									close(appState)
   329  									close(warnings)
   330  									close(errs)
   331  								}()
   332  
   333  								return messages, logErrs, appState, warnings, errs
   334  							}
   335  						})
   336  
   337  						It("displays the error and continues to poll", func() {
   338  							Expect(executeErr).NotTo(HaveOccurred())
   339  							Expect(testUI.Err).To(Say(expectedErr.Error()))
   340  						})
   341  					})
   342  				})
   343  
   344  				When("passed a warning", func() {
   345  					Context("while NOAA is still logging", func() {
   346  						BeforeEach(func() {
   347  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   348  								messages := make(chan *v2action.LogMessage)
   349  								logErrs := make(chan error)
   350  								appState := make(chan v2action.ApplicationStateChange)
   351  								warnings := make(chan string)
   352  								errs := make(chan error)
   353  
   354  								go func() {
   355  									warnings <- "warning 1"
   356  									warnings <- "warning 2"
   357  									close(messages)
   358  									close(logErrs)
   359  									close(appState)
   360  									close(warnings)
   361  									close(errs)
   362  								}()
   363  
   364  								return messages, logErrs, appState, warnings, errs
   365  							}
   366  						})
   367  
   368  						It("displays the warnings to STDERR", func() {
   369  							Expect(executeErr).ToNot(HaveOccurred())
   370  							Expect(testUI.Err).To(Say("warning 1"))
   371  							Expect(testUI.Err).To(Say("warning 2"))
   372  						})
   373  					})
   374  
   375  					Context("while NOAA is no longer logging", func() {
   376  						BeforeEach(func() {
   377  							fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   378  								messages := make(chan *v2action.LogMessage)
   379  								logErrs := make(chan error)
   380  								appState := make(chan v2action.ApplicationStateChange)
   381  								warnings := make(chan string)
   382  								errs := make(chan error)
   383  
   384  								go func() {
   385  									warnings <- "warning 1"
   386  									warnings <- "warning 2"
   387  									logErrs <- actionerror.NOAATimeoutError{}
   388  									close(messages)
   389  									close(logErrs)
   390  									warnings <- "warning 3"
   391  									warnings <- "warning 4"
   392  									close(appState)
   393  									close(warnings)
   394  									close(errs)
   395  								}()
   396  
   397  								return messages, logErrs, appState, warnings, errs
   398  							}
   399  						})
   400  
   401  						It("displays the warnings to STDERR", func() {
   402  							Expect(executeErr).ToNot(HaveOccurred())
   403  							Expect(testUI.Err).To(Say("warning 1"))
   404  							Expect(testUI.Err).To(Say("warning 2"))
   405  							Expect(testUI.Err).To(Say("timeout connecting to log server, no log will be shown"))
   406  							Expect(testUI.Err).To(Say("warning 3"))
   407  							Expect(testUI.Err).To(Say("warning 4"))
   408  						})
   409  					})
   410  				})
   411  
   412  				When("passed an API err", func() {
   413  					var apiErr error
   414  
   415  					BeforeEach(func() {
   416  						fakeActor.StartApplicationStub = func(app v2action.Application, client v2action.NOAAClient) (<-chan *v2action.LogMessage, <-chan error, <-chan v2action.ApplicationStateChange, <-chan string, <-chan error) {
   417  							messages := make(chan *v2action.LogMessage)
   418  							logErrs := make(chan error)
   419  							appState := make(chan v2action.ApplicationStateChange)
   420  							warnings := make(chan string)
   421  							errs := make(chan error)
   422  
   423  							go func() {
   424  								errs <- apiErr
   425  								close(messages)
   426  								close(logErrs)
   427  								close(appState)
   428  								close(warnings)
   429  								close(errs)
   430  							}()
   431  
   432  							return messages, logErrs, appState, warnings, errs
   433  						}
   434  					})
   435  
   436  					Context("an unexpected error", func() {
   437  						BeforeEach(func() {
   438  							apiErr = errors.New("err log message")
   439  						})
   440  
   441  						It("stops logging and returns the error", func() {
   442  							Expect(executeErr).To(MatchError(apiErr))
   443  						})
   444  					})
   445  
   446  					Context("staging failed", func() {
   447  						BeforeEach(func() {
   448  							apiErr = actionerror.StagingFailedError{Reason: "Something, but not nothing"}
   449  						})
   450  
   451  						It("stops logging and returns StagingFailedError", func() {
   452  							Expect(executeErr).To(MatchError(translatableerror.StagingFailedError{Message: "Something, but not nothing"}))
   453  						})
   454  					})
   455  
   456  					Context("staging timed out", func() {
   457  						BeforeEach(func() {
   458  							apiErr = actionerror.StagingTimeoutError{AppName: appName, Timeout: time.Nanosecond}
   459  						})
   460  
   461  						It("stops logging and returns StagingTimeoutError", func() {
   462  							Expect(executeErr).To(MatchError(translatableerror.StagingTimeoutError{AppName: appName, Timeout: time.Nanosecond}))
   463  						})
   464  					})
   465  
   466  					When("the app instance crashes", func() {
   467  						BeforeEach(func() {
   468  							apiErr = actionerror.ApplicationInstanceCrashedError{Name: appName}
   469  						})
   470  
   471  						It("stops logging and returns UnsuccessfulStartError", func() {
   472  							Expect(executeErr).To(MatchError(translatableerror.UnsuccessfulStartError{AppName: appName, BinaryName: "faceman"}))
   473  						})
   474  					})
   475  
   476  					When("the app instance flaps", func() {
   477  						BeforeEach(func() {
   478  							apiErr = actionerror.ApplicationInstanceFlappingError{Name: appName}
   479  						})
   480  
   481  						It("stops logging and returns UnsuccessfulStartError", func() {
   482  							Expect(executeErr).To(MatchError(translatableerror.UnsuccessfulStartError{AppName: appName, BinaryName: "faceman"}))
   483  						})
   484  					})
   485  
   486  					Context("starting timeout", func() {
   487  						BeforeEach(func() {
   488  							apiErr = actionerror.StartupTimeoutError{Name: appName}
   489  						})
   490  
   491  						It("stops logging and returns StartupTimeoutError", func() {
   492  							Expect(executeErr).To(MatchError(translatableerror.StartupTimeoutError{AppName: appName, BinaryName: "faceman"}))
   493  						})
   494  					})
   495  				})
   496  
   497  				When("the app finishes starting", func() {
   498  					Describe("version-dependent display", func() {
   499  						When("CC API >= 3.27.0", func() {
   500  							var (
   501  								applicationSummary v2v3action.ApplicationSummary
   502  							)
   503  
   504  							BeforeEach(func() {
   505  								fakeApplicationSummaryActor.CloudControllerV3APIVersionReturns("3.50.0")
   506  								v3ApplicationSummary := v3action.ApplicationSummary{
   507  									Application: v3action.Application{
   508  										Name: appName,
   509  									},
   510  									ProcessSummaries: v3action.ProcessSummaries{
   511  										{
   512  											Process: v3action.Process{
   513  												Type:       "aba",
   514  												Command:    *types.NewFilteredString("some-command-1"),
   515  												MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   516  												DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   517  											},
   518  										},
   519  										{
   520  											Process: v3action.Process{
   521  												Type:       "console",
   522  												Command:    *types.NewFilteredString("some-command-2"),
   523  												MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
   524  												DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
   525  											},
   526  										},
   527  									},
   528  								}
   529  								applicationSummary = v2v3action.ApplicationSummary{
   530  									ApplicationSummary: v3ApplicationSummary,
   531  								}
   532  
   533  								fakeApplicationSummaryActor.GetApplicationSummaryByNameAndSpaceReturns(
   534  									applicationSummary,
   535  									v2v3action.Warnings{"combo-summary-warning"},
   536  									nil)
   537  
   538  							})
   539  
   540  							It("uses the multiprocess display", func() {
   541  								Expect(executeErr).ToNot(HaveOccurred())
   542  
   543  								Expect(fakeApplicationSummaryActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1))
   544  								passedAppName, spaceGUID, withObfuscatedValues := fakeApplicationSummaryActor.GetApplicationSummaryByNameAndSpaceArgsForCall(0)
   545  								Expect(passedAppName).To(Equal(appName))
   546  								Expect(spaceGUID).To(Equal("some-space-guid"))
   547  								Expect(withObfuscatedValues).To(BeTrue())
   548  
   549  								Expect(testUI.Out).To(Say(`name:\s+%s`, appName))
   550  								Expect(testUI.Out).To(Say(`type:\s+aba`))
   551  								Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   552  								Expect(testUI.Out).To(Say(`memory usage:\s+32M`))
   553  								Expect(testUI.Out).To(Say(`start command:\s+some-command-1`))
   554  								Expect(testUI.Out).To(Say(`type:\s+console`))
   555  								Expect(testUI.Out).To(Say(`instances:\s+0/0`))
   556  								Expect(testUI.Out).To(Say(`memory usage:\s+16M`))
   557  								Expect(testUI.Out).To(Say(`start command:\s+some-command-2`))
   558  
   559  								Expect(testUI.Err).To(Say("combo-summary-warning"))
   560  							})
   561  						})
   562  
   563  						When("CC API < 3.27.0", func() {
   564  							var (
   565  								applicationSummary v2action.ApplicationSummary
   566  							)
   567  
   568  							BeforeEach(func() {
   569  								fakeApplicationSummaryActor.CloudControllerV3APIVersionReturns("3.26.0")
   570  
   571  								applicationSummary = v2action.ApplicationSummary{
   572  									Application: v2action.Application{
   573  										Name:                 appName,
   574  										GUID:                 "some-app-guid",
   575  										Instances:            types.NullInt{Value: 3, IsSet: true},
   576  										Memory:               types.NullByteSizeInMb{IsSet: true, Value: 128},
   577  										PackageUpdatedAt:     time.Unix(0, 0),
   578  										DetectedBuildpack:    types.FilteredString{IsSet: true, Value: "some-buildpack"},
   579  										State:                "STARTED",
   580  										DetectedStartCommand: types.FilteredString{IsSet: true, Value: "some start command"},
   581  									},
   582  									Stack: v2action.Stack{
   583  										Name: "potatos",
   584  									},
   585  									Routes: []v2action.Route{
   586  										{
   587  											Host: "banana",
   588  											Domain: v2action.Domain{
   589  												Name: "fruit.com",
   590  											},
   591  											Path: "/hi",
   592  										},
   593  										{
   594  											Domain: v2action.Domain{
   595  												Name: "foobar.com",
   596  											},
   597  											Port: types.NullInt{IsSet: true, Value: 13},
   598  										},
   599  									},
   600  								}
   601  								warnings := []string{"app-summary-warning"}
   602  
   603  								applicationSummary.RunningInstances = []v2action.ApplicationInstanceWithStats{
   604  									{
   605  										ID:          0,
   606  										State:       v2action.ApplicationInstanceState(constant.ApplicationInstanceRunning),
   607  										Since:       1403140717.984577,
   608  										CPU:         0.73,
   609  										Disk:        50 * bytefmt.MEGABYTE,
   610  										DiskQuota:   2048 * bytefmt.MEGABYTE,
   611  										Memory:      100 * bytefmt.MEGABYTE,
   612  										MemoryQuota: 128 * bytefmt.MEGABYTE,
   613  										Details:     "info from the backend",
   614  									},
   615  								}
   616  
   617  								fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   618  							})
   619  
   620  							It("uses the v2 display", func() {
   621  								Expect(executeErr).ToNot(HaveOccurred())
   622  								Expect(testUI.Out).To(Say(`name:\s+some-app`))
   623  								Expect(testUI.Out).To(Say(`requested state:\s+started`))
   624  								Expect(testUI.Out).To(Say(`instances:\s+1\/3`))
   625  								Expect(testUI.Out).To(Say(`usage:\s+128M x 3 instances`))
   626  								Expect(testUI.Out).To(Say(`routes:\s+banana.fruit.com/hi, foobar.com:13`))
   627  								Expect(testUI.Out).To(Say(`last uploaded:\s+\w{3} [0-3]\d \w{3} [0-2]\d:[0-5]\d:[0-5]\d \w+ \d{4}`))
   628  								Expect(testUI.Out).To(Say(`stack:\s+potatos`))
   629  								Expect(testUI.Out).To(Say(`buildpack:\s+some-buildpack`))
   630  								Expect(testUI.Out).To(Say(`start command:\s+some start command`))
   631  
   632  								Expect(testUI.Err).To(Say("app-summary-warning"))
   633  							})
   634  						})
   635  					})
   636  
   637  					When("the isolation segment is not empty", func() {
   638  						BeforeEach(func() {
   639  							fakeApplicationSummaryActor.CloudControllerV3APIVersionReturns("3.26.0")
   640  
   641  							applicationSummary := v2action.ApplicationSummary{
   642  								Application: v2action.Application{
   643  									Name: appName,
   644  								},
   645  								IsolationSegment: "some-isolation-segment",
   646  							}
   647  							warnings := []string{"app-summary-warning"}
   648  
   649  							fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   650  						})
   651  
   652  						It("displays the app summary with isolation segments as well as warnings", func() {
   653  							Expect(executeErr).ToNot(HaveOccurred())
   654  							Expect(testUI.Out).To(Say(`name:\s+some-app`))
   655  							Expect(testUI.Out).To(Say(`isolation segment:\s+some-isolation-segment`))
   656  
   657  							Expect(testUI.Err).To(Say("app-summary-warning"))
   658  						})
   659  					})
   660  
   661  					When("the isolation segment is empty", func() {
   662  						BeforeEach(func() {
   663  							fakeApplicationSummaryActor.CloudControllerV3APIVersionReturns("3.26.0")
   664  
   665  							applicationSummary := v2action.ApplicationSummary{
   666  								Application: v2action.Application{
   667  									Name: appName,
   668  								},
   669  								IsolationSegment: "",
   670  							}
   671  							warnings := []string{"app-summary-warning"}
   672  
   673  							fakeActor.GetApplicationSummaryByNameAndSpaceReturns(applicationSummary, warnings, nil)
   674  						})
   675  
   676  						It("displays the app summary without isolation segment as well as warnings", func() {
   677  							Expect(executeErr).ToNot(HaveOccurred())
   678  							Expect(testUI.Out).To(Say(`name:\s+some-app`))
   679  							Expect(testUI.Out).NotTo(Say("isolation segment:"))
   680  
   681  							Expect(testUI.Err).To(Say("app-summary-warning"))
   682  						})
   683  					})
   684  				})
   685  			})
   686  		})
   687  
   688  		When("the app does *not* exists", func() {
   689  			BeforeEach(func() {
   690  				fakeActor.GetApplicationByNameAndSpaceReturns(
   691  					v2action.Application{},
   692  					v2action.Warnings{"warning-1", "warning-2"},
   693  					actionerror.ApplicationNotFoundError{Name: appName},
   694  				)
   695  			})
   696  
   697  			It("returns back an error", func() {
   698  				Expect(executeErr).To(MatchError(actionerror.ApplicationNotFoundError{Name: "some-app"}))
   699  
   700  				Expect(testUI.Err).To(Say("warning-1"))
   701  				Expect(testUI.Err).To(Say("warning-2"))
   702  			})
   703  		})
   704  	})
   705  })