github.com/ablease/cli@v6.37.1-0.20180613014814-3adbb7d7fb19+incompatible/command/v2/restart_command_test.go (about)

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