github.com/arunkumar7540/cli@v6.45.0+incompatible/command/v7/scale_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"errors"
     5  	"time"
     6  
     7  	"code.cloudfoundry.org/cli/actor/actionerror"
     8  	"code.cloudfoundry.org/cli/actor/v7action"
     9  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccv3/constant"
    10  	"code.cloudfoundry.org/cli/command/commandfakes"
    11  	"code.cloudfoundry.org/cli/command/translatableerror"
    12  	. "code.cloudfoundry.org/cli/command/v7"
    13  	"code.cloudfoundry.org/cli/command/v7/v7fakes"
    14  	"code.cloudfoundry.org/cli/integration/helpers"
    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("scale Command", func() {
    24  	var (
    25  		cmd             ScaleCommand
    26  		input           *Buffer
    27  		output          *Buffer
    28  		testUI          *ui.UI
    29  		fakeConfig      *commandfakes.FakeConfig
    30  		fakeSharedActor *commandfakes.FakeSharedActor
    31  		fakeActor       *v7fakes.FakeScaleActor
    32  		appName         string
    33  		binaryName      string
    34  		executeErr      error
    35  	)
    36  
    37  	BeforeEach(func() {
    38  		input = NewBuffer()
    39  		output = NewBuffer()
    40  		testUI = ui.NewTestUI(input, output, NewBuffer())
    41  		fakeConfig = new(commandfakes.FakeConfig)
    42  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    43  		fakeActor = new(v7fakes.FakeScaleActor)
    44  		appName = "some-app"
    45  
    46  		cmd = ScaleCommand{
    47  			UI:          testUI,
    48  			Config:      fakeConfig,
    49  			SharedActor: fakeSharedActor,
    50  			Actor:       fakeActor,
    51  		}
    52  
    53  		binaryName = "faceman"
    54  		fakeConfig.BinaryNameReturns(binaryName)
    55  
    56  		cmd.RequiredArgs.AppName = appName
    57  		cmd.ProcessType = constant.ProcessTypeWeb
    58  	})
    59  
    60  	JustBeforeEach(func() {
    61  		executeErr = cmd.Execute(nil)
    62  	})
    63  
    64  	When("checking target fails", func() {
    65  		BeforeEach(func() {
    66  			fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName})
    67  		})
    68  
    69  		It("returns an error", func() {
    70  			Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName}))
    71  
    72  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
    73  			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
    74  			Expect(checkTargetedOrg).To(BeTrue())
    75  			Expect(checkTargetedSpace).To(BeTrue())
    76  		})
    77  	})
    78  
    79  	When("the user is logged in, and org and space are targeted", func() {
    80  		BeforeEach(func() {
    81  			fakeConfig.HasTargetedOrganizationReturns(true)
    82  			fakeConfig.TargetedOrganizationReturns(configv3.Organization{Name: "some-org"})
    83  			fakeConfig.HasTargetedSpaceReturns(true)
    84  			fakeConfig.TargetedSpaceReturns(configv3.Space{
    85  				GUID: "some-space-guid",
    86  				Name: "some-space"})
    87  			fakeConfig.CurrentUserReturns(
    88  				configv3.User{Name: "some-user"},
    89  				nil)
    90  		})
    91  
    92  		When("getting the current user returns an error", func() {
    93  			var expectedErr error
    94  
    95  			BeforeEach(func() {
    96  				expectedErr = errors.New("getting current user error")
    97  				fakeConfig.CurrentUserReturns(
    98  					configv3.User{},
    99  					expectedErr)
   100  			})
   101  
   102  			It("returns the error", func() {
   103  				Expect(executeErr).To(MatchError(expectedErr))
   104  			})
   105  		})
   106  
   107  		When("the application does not exist", func() {
   108  			BeforeEach(func() {
   109  				fakeActor.GetApplicationByNameAndSpaceReturns(
   110  					v7action.Application{},
   111  					v7action.Warnings{"get-app-warning"},
   112  					actionerror.ApplicationNotFoundError{Name: appName})
   113  			})
   114  
   115  			It("returns an ApplicationNotFoundError and all warnings", func() {
   116  				Expect(executeErr).To(Equal(actionerror.ApplicationNotFoundError{Name: appName}))
   117  
   118  				Expect(testUI.Out).ToNot(Say("Showing | Scaling"))
   119  				Expect(testUI.Err).To(Say("get-app-warning"))
   120  
   121  				Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   122  				appNameArg, spaceGUIDArg := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
   123  				Expect(appNameArg).To(Equal(appName))
   124  				Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   125  			})
   126  		})
   127  
   128  		When("an error occurs getting the application", func() {
   129  			var expectedErr error
   130  
   131  			BeforeEach(func() {
   132  				expectedErr = errors.New("get app error")
   133  				fakeActor.GetApplicationByNameAndSpaceReturns(
   134  					v7action.Application{},
   135  					v7action.Warnings{"get-app-warning"},
   136  					expectedErr)
   137  			})
   138  
   139  			It("returns the error and displays all warnings", func() {
   140  				Expect(executeErr).To(Equal(expectedErr))
   141  				Expect(testUI.Err).To(Say("get-app-warning"))
   142  			})
   143  		})
   144  
   145  		When("the application exists", func() {
   146  			var appSummary v7action.ApplicationSummary
   147  
   148  			BeforeEach(func() {
   149  				appSummary = v7action.ApplicationSummary{
   150  					ProcessSummaries: v7action.ProcessSummaries{
   151  						{
   152  							Process: v7action.Process{
   153  								Type:       constant.ProcessTypeWeb,
   154  								MemoryInMB: types.NullUint64{Value: 32, IsSet: true},
   155  								DiskInMB:   types.NullUint64{Value: 1024, IsSet: true},
   156  							},
   157  							InstanceDetails: []v7action.ProcessInstance{
   158  								v7action.ProcessInstance{
   159  									Index:       0,
   160  									State:       constant.ProcessInstanceRunning,
   161  									MemoryUsage: 1000000,
   162  									DiskUsage:   1000000,
   163  									MemoryQuota: 33554432,
   164  									DiskQuota:   2000000,
   165  									Uptime:      time.Since(time.Unix(267321600, 0)),
   166  								},
   167  								v7action.ProcessInstance{
   168  									Index:       1,
   169  									State:       constant.ProcessInstanceRunning,
   170  									MemoryUsage: 2000000,
   171  									DiskUsage:   2000000,
   172  									MemoryQuota: 33554432,
   173  									DiskQuota:   4000000,
   174  									Uptime:      time.Since(time.Unix(330480000, 0)),
   175  								},
   176  								v7action.ProcessInstance{
   177  									Index:       2,
   178  									State:       constant.ProcessInstanceRunning,
   179  									MemoryUsage: 3000000,
   180  									DiskUsage:   3000000,
   181  									MemoryQuota: 33554432,
   182  									DiskQuota:   6000000,
   183  									Uptime:      time.Since(time.Unix(1277164800, 0)),
   184  								},
   185  							},
   186  						},
   187  						{
   188  							Process: v7action.Process{
   189  								Type:       "console",
   190  								MemoryInMB: types.NullUint64{Value: 16, IsSet: true},
   191  								DiskInMB:   types.NullUint64{Value: 512, IsSet: true},
   192  							},
   193  							InstanceDetails: []v7action.ProcessInstance{
   194  								v7action.ProcessInstance{
   195  									Index:       0,
   196  									State:       constant.ProcessInstanceRunning,
   197  									MemoryUsage: 1000000,
   198  									DiskUsage:   1000000,
   199  									MemoryQuota: 33554432,
   200  									DiskQuota:   8000000,
   201  									Uptime:      time.Since(time.Unix(167572800, 0)),
   202  								},
   203  							},
   204  						},
   205  					},
   206  				}
   207  
   208  				fakeActor.GetApplicationByNameAndSpaceReturns(
   209  					v7action.Application{GUID: "some-app-guid"},
   210  					v7action.Warnings{"get-app-warning"},
   211  					nil)
   212  			})
   213  
   214  			When("no flag options are provided", func() {
   215  				BeforeEach(func() {
   216  					fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   217  						appSummary,
   218  						v7action.Warnings{"get-app-summary-warning"},
   219  						nil)
   220  				})
   221  
   222  				It("displays current scale properties and all warnings", func() {
   223  					Expect(executeErr).ToNot(HaveOccurred())
   224  
   225  					Expect(testUI.Out).To(Say(`Showing current scale of app some-app in org some-org / space some-space as some-user\.\.\.`))
   226  					Expect(testUI.Out).ToNot(Say("Scaling | This will cause the app to restart | Stopping | Starting | Waiting"))
   227  
   228  					firstAppTable := helpers.ParseV3AppProcessTable(output.Contents())
   229  					Expect(len(firstAppTable.Processes)).To(Equal(2))
   230  
   231  					webProcessSummary := firstAppTable.Processes[0]
   232  					Expect(webProcessSummary.Type).To(Equal("web"))
   233  					Expect(webProcessSummary.InstanceCount).To(Equal("3/3"))
   234  					Expect(webProcessSummary.MemUsage).To(Equal("32M"))
   235  
   236  					Expect(webProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   237  					Expect(webProcessSummary.Instances[0].Disk).To(Equal("976.6K of 1.9M"))
   238  					Expect(webProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   239  
   240  					Expect(webProcessSummary.Instances[1].Memory).To(Equal("1.9M of 32M"))
   241  					Expect(webProcessSummary.Instances[1].Disk).To(Equal("1.9M of 3.8M"))
   242  					Expect(webProcessSummary.Instances[1].CPU).To(Equal("0.0%"))
   243  
   244  					Expect(webProcessSummary.Instances[2].Memory).To(Equal("2.9M of 32M"))
   245  					Expect(webProcessSummary.Instances[2].Disk).To(Equal("2.9M of 5.7M"))
   246  					Expect(webProcessSummary.Instances[2].CPU).To(Equal("0.0%"))
   247  
   248  					consoleProcessSummary := firstAppTable.Processes[1]
   249  					Expect(consoleProcessSummary.Type).To(Equal("console"))
   250  					Expect(consoleProcessSummary.InstanceCount).To(Equal("1/1"))
   251  					Expect(consoleProcessSummary.MemUsage).To(Equal("16M"))
   252  
   253  					Expect(consoleProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   254  					Expect(consoleProcessSummary.Instances[0].Disk).To(Equal("976.6K of 7.6M"))
   255  					Expect(consoleProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   256  
   257  					Expect(testUI.Err).To(Say("get-app-warning"))
   258  					Expect(testUI.Err).To(Say("get-app-summary-warning"))
   259  
   260  					Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(0))
   261  				})
   262  
   263  				When("an error is encountered getting process information", func() {
   264  					var expectedErr error
   265  
   266  					BeforeEach(func() {
   267  						expectedErr = errors.New("get process error")
   268  						fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   269  							v7action.ApplicationSummary{},
   270  							v7action.Warnings{"get-process-warning"},
   271  							expectedErr,
   272  						)
   273  					})
   274  
   275  					It("returns the error and displays all warnings", func() {
   276  						Expect(executeErr).To(Equal(expectedErr))
   277  						Expect(testUI.Err).To(Say("get-process-warning"))
   278  					})
   279  				})
   280  			})
   281  
   282  			When("all flag options are provided", func() {
   283  				BeforeEach(func() {
   284  					cmd.Instances.Value = 2
   285  					cmd.Instances.IsSet = true
   286  					cmd.DiskLimit.Value = 50
   287  					cmd.DiskLimit.IsSet = true
   288  					cmd.MemoryLimit.Value = 100
   289  					cmd.MemoryLimit.IsSet = true
   290  					fakeActor.ScaleProcessByApplicationReturns(
   291  						v7action.Warnings{"scale-warning"},
   292  						nil)
   293  					fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   294  						appSummary,
   295  						v7action.Warnings{"get-instances-warning"},
   296  						nil)
   297  				})
   298  
   299  				When("force flag is not provided", func() {
   300  					When("the user chooses default", func() {
   301  						BeforeEach(func() {
   302  							_, err := input.Write([]byte("\n"))
   303  							Expect(err).ToNot(HaveOccurred())
   304  						})
   305  
   306  						It("does not scale the app", func() {
   307  							Expect(executeErr).ToNot(HaveOccurred())
   308  
   309  							Expect(testUI.Out).To(Say(`Scaling app some-app in org some-org / space some-space as some-user\.\.\.`))
   310  							Expect(testUI.Out).To(Say(`This will cause the app to restart\. Are you sure you want to scale some-app\? \[yN\]:`))
   311  							Expect(testUI.Out).To(Say("Scaling cancelled"))
   312  							Expect(testUI.Out).ToNot(Say("Showing | Stopping | Starting | Waiting"))
   313  
   314  							Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(0))
   315  						})
   316  					})
   317  
   318  					When("the user chooses no", func() {
   319  						BeforeEach(func() {
   320  							_, err := input.Write([]byte("n\n"))
   321  							Expect(err).ToNot(HaveOccurred())
   322  						})
   323  
   324  						It("does not scale the app", func() {
   325  							Expect(executeErr).ToNot(HaveOccurred())
   326  
   327  							Expect(testUI.Out).To(Say(`Scaling app some-app in org some-org / space some-space as some-user\.\.\.`))
   328  							Expect(testUI.Out).To(Say(`This will cause the app to restart\. Are you sure you want to scale some-app\? \[yN\]:`))
   329  							Expect(testUI.Out).To(Say("Scaling cancelled"))
   330  							Expect(testUI.Out).ToNot(Say("Showing | Stopping | Starting | Waiting"))
   331  
   332  							Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(0))
   333  						})
   334  					})
   335  
   336  					When("the user chooses yes", func() {
   337  						BeforeEach(func() {
   338  							_, err := input.Write([]byte("y\n"))
   339  							Expect(err).ToNot(HaveOccurred())
   340  						})
   341  
   342  						When("polling succeeds and the app has running instances", func() {
   343  							BeforeEach(func() {
   344  								fakeActor.PollStartReturns(v7action.Warnings{"some-poll-warning-1", "some-poll-warning-2"}, nil)
   345  							})
   346  
   347  							It("delegates the right appGUID", func() {
   348  								Expect(fakeActor.PollStartArgsForCall(0)).To(Equal("some-app-guid"))
   349  							})
   350  
   351  							When("Restarting the app fails to stop the app", func() {
   352  								BeforeEach(func() {
   353  									fakeActor.StopApplicationReturns(v7action.Warnings{"some-restart-warning"}, errors.New("stop-error"))
   354  								})
   355  
   356  								It("Prints warnings and returns an error", func() {
   357  									Expect(executeErr).To(MatchError("stop-error"))
   358  
   359  									Expect(testUI.Err).To(Say("some-restart-warning"))
   360  								})
   361  							})
   362  
   363  							When("Restarting the app fails to start the app", func() {
   364  								BeforeEach(func() {
   365  									fakeActor.StartApplicationReturns(v7action.Application{}, v7action.Warnings{"some-start-warning"}, errors.New("start-error"))
   366  								})
   367  
   368  								It("Delegates the correct appGUID", func() {
   369  									actualGUID := fakeActor.StartApplicationArgsForCall(0)
   370  									Expect(actualGUID).To(Equal("some-app-guid"))
   371  								})
   372  
   373  								It("Prints warnings and returns an error", func() {
   374  									Expect(executeErr).To(MatchError("start-error"))
   375  
   376  									Expect(testUI.Err).To(Say("some-start-warning"))
   377  								})
   378  							})
   379  
   380  							It("scales, restarts, and displays scale properties", func() {
   381  								Expect(executeErr).ToNot(HaveOccurred())
   382  
   383  								Expect(testUI.Out).To(Say(`Scaling app some-app in org some-org / space some-space as some-user\.\.\.`))
   384  								Expect(testUI.Out).To(Say(`This will cause the app to restart\. Are you sure you want to scale some-app\? \[yN\]:`))
   385  								Expect(testUI.Out).To(Say(`Stopping app some-app in org some-org / space some-space as some-user\.\.\.`))
   386  								Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as some-user\.\.\.`))
   387  
   388  								// Note that this does test that the disk quota was scaled to 96M,
   389  								// it is tested below when we check the arguments
   390  								// passed to ScaleProcessByApplication
   391  								firstAppTable := helpers.ParseV3AppProcessTable(output.Contents())
   392  								Expect(len(firstAppTable.Processes)).To(Equal(2))
   393  
   394  								webProcessSummary := firstAppTable.Processes[0]
   395  								Expect(webProcessSummary.Type).To(Equal("web"))
   396  								Expect(webProcessSummary.InstanceCount).To(Equal("3/3"))
   397  								Expect(webProcessSummary.MemUsage).To(Equal("32M"))
   398  
   399  								Expect(webProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   400  								Expect(webProcessSummary.Instances[0].Disk).To(Equal("976.6K of 1.9M"))
   401  								Expect(webProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   402  
   403  								Expect(webProcessSummary.Instances[1].Memory).To(Equal("1.9M of 32M"))
   404  								Expect(webProcessSummary.Instances[1].Disk).To(Equal("1.9M of 3.8M"))
   405  								Expect(webProcessSummary.Instances[1].CPU).To(Equal("0.0%"))
   406  
   407  								Expect(webProcessSummary.Instances[2].Memory).To(Equal("2.9M of 32M"))
   408  								Expect(webProcessSummary.Instances[2].Disk).To(Equal("2.9M of 5.7M"))
   409  								Expect(webProcessSummary.Instances[2].CPU).To(Equal("0.0%"))
   410  
   411  								consoleProcessSummary := firstAppTable.Processes[1]
   412  								Expect(consoleProcessSummary.Type).To(Equal("console"))
   413  								Expect(consoleProcessSummary.InstanceCount).To(Equal("1/1"))
   414  								Expect(consoleProcessSummary.MemUsage).To(Equal("16M"))
   415  
   416  								Expect(consoleProcessSummary.Instances[0].Memory).To(Equal("976.6K of 32M"))
   417  								Expect(consoleProcessSummary.Instances[0].Disk).To(Equal("976.6K of 7.6M"))
   418  								Expect(consoleProcessSummary.Instances[0].CPU).To(Equal("0.0%"))
   419  
   420  								Expect(testUI.Err).To(Say("get-app-warning"))
   421  								Expect(testUI.Err).To(Say("scale-warning"))
   422  								Expect(testUI.Err).To(Say("some-poll-warning-1"))
   423  								Expect(testUI.Err).To(Say("some-poll-warning-2"))
   424  								Expect(testUI.Err).To(Say("get-instances-warning"))
   425  
   426  								Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   427  								appNameArg, spaceGUIDArg := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
   428  								Expect(appNameArg).To(Equal(appName))
   429  								Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   430  
   431  								Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(1))
   432  								appGUIDArg, scaleProcess := fakeActor.ScaleProcessByApplicationArgsForCall(0)
   433  								Expect(appGUIDArg).To(Equal("some-app-guid"))
   434  								Expect(scaleProcess).To(Equal(v7action.Process{
   435  									Type:       constant.ProcessTypeWeb,
   436  									Instances:  types.NullInt{Value: 2, IsSet: true},
   437  									DiskInMB:   types.NullUint64{Value: 50, IsSet: true},
   438  									MemoryInMB: types.NullUint64{Value: 100, IsSet: true},
   439  								}))
   440  
   441  								Expect(fakeActor.StopApplicationCallCount()).To(Equal(1))
   442  								Expect(fakeActor.StopApplicationArgsForCall(0)).To(Equal("some-app-guid"))
   443  
   444  								Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   445  								Expect(fakeActor.StartApplicationArgsForCall(0)).To(Equal("some-app-guid"))
   446  							})
   447  						})
   448  
   449  						When("polling succeeds but all the app's instances have crashed", func() {
   450  							BeforeEach(func() {
   451  								fakeActor.PollStartReturns(v7action.Warnings{"some-poll-warning-1", "some-poll-warning-2"}, actionerror.AllInstancesCrashedError{})
   452  							})
   453  
   454  							It("delegates the right appGUID", func() {
   455  								Expect(fakeActor.PollStartArgsForCall(0)).To(Equal("some-app-guid"))
   456  							})
   457  
   458  							It("displays the process table", func() {
   459  								Expect(testUI.Out).To(Say("Showing current scale of app " + appName))
   460  							})
   461  
   462  							It("displays all warnings and fails", func() {
   463  								Expect(testUI.Err).To(Say("some-poll-warning-1"))
   464  								Expect(testUI.Err).To(Say("some-poll-warning-2"))
   465  
   466  								Expect(executeErr).To(MatchError(translatableerror.ApplicationUnableToStartError{
   467  									AppName:    appName,
   468  									BinaryName: binaryName,
   469  								}))
   470  							})
   471  						})
   472  
   473  						When("polling the start fails", func() {
   474  							BeforeEach(func() {
   475  								fakeActor.PollStartReturns(v7action.Warnings{"some-poll-warning-1", "some-poll-warning-2"}, errors.New("some-error"))
   476  							})
   477  
   478  							It("delegates the right appGUID", func() {
   479  								Expect(fakeActor.PollStartArgsForCall(0)).To(Equal("some-app-guid"))
   480  							})
   481  
   482  							It("displays all warnings and fails", func() {
   483  								Expect(testUI.Err).To(Say("some-poll-warning-1"))
   484  								Expect(testUI.Err).To(Say("some-poll-warning-2"))
   485  
   486  								Expect(executeErr).To(MatchError("some-error"))
   487  							})
   488  						})
   489  
   490  						When("polling times out", func() {
   491  							BeforeEach(func() {
   492  								fakeActor.PollStartReturns(nil, actionerror.StartupTimeoutError{})
   493  							})
   494  
   495  							It("delegates the right appGUID", func() {
   496  								Expect(fakeActor.PollStartArgsForCall(0)).To(Equal("some-app-guid"))
   497  							})
   498  
   499  							It("returns the StartupTimeoutError", func() {
   500  								Expect(executeErr).To(MatchError(translatableerror.StartupTimeoutError{
   501  									AppName:    "some-app",
   502  									BinaryName: binaryName,
   503  								}))
   504  							})
   505  						})
   506  					})
   507  				})
   508  
   509  				When("force flag is provided", func() {
   510  					BeforeEach(func() {
   511  						cmd.Force = true
   512  					})
   513  
   514  					It("does not prompt user to confirm app restart", func() {
   515  						Expect(executeErr).ToNot(HaveOccurred())
   516  
   517  						Expect(testUI.Out).To(Say(`Scaling app some-app in org some-org / space some-space as some-user\.\.\.`))
   518  						Expect(testUI.Out).To(Say(`Stopping app some-app in org some-org / space some-space as some-user\.\.\.`))
   519  						Expect(testUI.Out).To(Say(`Starting app some-app in org some-org / space some-space as some-user\.\.\.`))
   520  						Expect(testUI.Out).NotTo(Say(`This will cause the app to restart\. Are you sure you want to scale some-app\? \[yN\]:`))
   521  
   522  						Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   523  						Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(1))
   524  						Expect(fakeActor.StopApplicationCallCount()).To(Equal(1))
   525  						Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   526  						Expect(fakeActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1))
   527  					})
   528  				})
   529  			})
   530  
   531  			When("only the instances flag option is provided", func() {
   532  				BeforeEach(func() {
   533  					cmd.Instances.Value = 3
   534  					cmd.Instances.IsSet = true
   535  					fakeActor.ScaleProcessByApplicationReturns(
   536  						v7action.Warnings{"scale-warning"},
   537  						nil)
   538  					fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   539  						appSummary,
   540  						v7action.Warnings{"get-instances-warning"},
   541  						nil)
   542  				})
   543  
   544  				It("scales the number of instances, displays scale properties, and does not restart the application", func() {
   545  					Expect(executeErr).ToNot(HaveOccurred())
   546  
   547  					Expect(testUI.Out).To(Say("Scaling"))
   548  					Expect(testUI.Out).NotTo(Say("This will cause the app to restart | Stopping | Starting"))
   549  
   550  					Expect(testUI.Err).To(Say("get-app-warning"))
   551  					Expect(testUI.Err).To(Say("scale-warning"))
   552  					Expect(testUI.Err).To(Say("get-instances-warning"))
   553  
   554  					Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   555  					appNameArg, spaceGUIDArg := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
   556  					Expect(appNameArg).To(Equal(appName))
   557  					Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   558  
   559  					Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(1))
   560  					appGUIDArg, scaleProcess := fakeActor.ScaleProcessByApplicationArgsForCall(0)
   561  					Expect(appGUIDArg).To(Equal("some-app-guid"))
   562  					Expect(scaleProcess).To(Equal(v7action.Process{
   563  						Type:      constant.ProcessTypeWeb,
   564  						Instances: types.NullInt{Value: 3, IsSet: true},
   565  					}))
   566  
   567  					Expect(fakeActor.StopApplicationCallCount()).To(Equal(0))
   568  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(0))
   569  				})
   570  			})
   571  
   572  			When("only the memory flag option is provided", func() {
   573  				BeforeEach(func() {
   574  					cmd.MemoryLimit.Value = 256
   575  					cmd.MemoryLimit.IsSet = true
   576  					fakeActor.ScaleProcessByApplicationReturns(
   577  						v7action.Warnings{"scale-warning"},
   578  						nil)
   579  					fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   580  						appSummary,
   581  						v7action.Warnings{"get-instances-warning"},
   582  						nil)
   583  
   584  					_, err := input.Write([]byte("y\n"))
   585  					Expect(err).ToNot(HaveOccurred())
   586  				})
   587  
   588  				It("scales, restarts, and displays scale properties", func() {
   589  					Expect(executeErr).ToNot(HaveOccurred())
   590  
   591  					Expect(testUI.Out).To(Say("Scaling"))
   592  					Expect(testUI.Out).To(Say("This will cause the app to restart"))
   593  					Expect(testUI.Out).To(Say("Stopping"))
   594  					Expect(testUI.Out).To(Say("Starting"))
   595  
   596  					Expect(testUI.Err).To(Say("get-app-warning"))
   597  					Expect(testUI.Err).To(Say("scale-warning"))
   598  					Expect(testUI.Err).To(Say("get-instances-warning"))
   599  
   600  					Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   601  					appNameArg, spaceGUIDArg := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
   602  					Expect(appNameArg).To(Equal(appName))
   603  					Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   604  
   605  					Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(1))
   606  					appGUIDArg, scaleProcess := fakeActor.ScaleProcessByApplicationArgsForCall(0)
   607  					Expect(appGUIDArg).To(Equal("some-app-guid"))
   608  					Expect(scaleProcess).To(Equal(v7action.Process{
   609  						Type:       constant.ProcessTypeWeb,
   610  						MemoryInMB: types.NullUint64{Value: 256, IsSet: true},
   611  					}))
   612  
   613  					Expect(fakeActor.StopApplicationCallCount()).To(Equal(1))
   614  					appGUID := fakeActor.StopApplicationArgsForCall(0)
   615  					Expect(appGUID).To(Equal("some-app-guid"))
   616  
   617  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   618  					appGUID = fakeActor.StartApplicationArgsForCall(0)
   619  					Expect(appGUID).To(Equal("some-app-guid"))
   620  
   621  					Expect(fakeActor.GetApplicationSummaryByNameAndSpaceCallCount()).To(Equal(1))
   622  				})
   623  			})
   624  
   625  			When("only the disk flag option is provided", func() {
   626  				BeforeEach(func() {
   627  					cmd.DiskLimit.Value = 1025
   628  					cmd.DiskLimit.IsSet = true
   629  					fakeActor.ScaleProcessByApplicationReturns(
   630  						v7action.Warnings{"scale-warning"},
   631  						nil)
   632  					fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   633  						appSummary,
   634  						v7action.Warnings{"get-instances-warning"},
   635  						nil)
   636  					_, err := input.Write([]byte("y\n"))
   637  					Expect(err).ToNot(HaveOccurred())
   638  				})
   639  
   640  				It("scales the number of instances, displays scale properties, and restarts the application", func() {
   641  					Expect(executeErr).ToNot(HaveOccurred())
   642  
   643  					Expect(testUI.Out).To(Say("Scaling"))
   644  					Expect(testUI.Out).To(Say("This will cause the app to restart"))
   645  					Expect(testUI.Out).To(Say("Stopping"))
   646  					Expect(testUI.Out).To(Say("Starting"))
   647  
   648  					Expect(testUI.Err).To(Say("get-app-warning"))
   649  					Expect(testUI.Err).To(Say("scale-warning"))
   650  					Expect(testUI.Err).To(Say("get-instances-warning"))
   651  
   652  					Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   653  					appNameArg, spaceGUIDArg := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
   654  					Expect(appNameArg).To(Equal(appName))
   655  					Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   656  
   657  					Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(1))
   658  					appGUIDArg, scaleProcess := fakeActor.ScaleProcessByApplicationArgsForCall(0)
   659  					Expect(appGUIDArg).To(Equal("some-app-guid"))
   660  					Expect(scaleProcess).To(Equal(v7action.Process{
   661  						Type:     constant.ProcessTypeWeb,
   662  						DiskInMB: types.NullUint64{Value: 1025, IsSet: true},
   663  					}))
   664  
   665  					Expect(fakeActor.StopApplicationCallCount()).To(Equal(1))
   666  					appGUID := fakeActor.StopApplicationArgsForCall(0)
   667  					Expect(appGUID).To(Equal("some-app-guid"))
   668  
   669  					Expect(fakeActor.StartApplicationCallCount()).To(Equal(1))
   670  					appGUID = fakeActor.StartApplicationArgsForCall(0)
   671  					Expect(appGUID).To(Equal("some-app-guid"))
   672  				})
   673  			})
   674  
   675  			When("process flag is provided", func() {
   676  				BeforeEach(func() {
   677  					cmd.ProcessType = "some-process-type"
   678  					cmd.Instances.Value = 2
   679  					cmd.Instances.IsSet = true
   680  					fakeActor.ScaleProcessByApplicationReturns(
   681  						v7action.Warnings{"scale-warning"},
   682  						nil)
   683  					fakeActor.GetApplicationSummaryByNameAndSpaceReturns(
   684  						appSummary,
   685  						v7action.Warnings{"get-instances-warning"},
   686  						nil)
   687  					_, err := input.Write([]byte("y\n"))
   688  					Expect(err).ToNot(HaveOccurred())
   689  				})
   690  
   691  				It("scales the specified process", func() {
   692  					Expect(executeErr).ToNot(HaveOccurred())
   693  
   694  					Expect(testUI.Out).To(Say("Scaling"))
   695  
   696  					Expect(testUI.Err).To(Say("get-app-warning"))
   697  					Expect(testUI.Err).To(Say("scale-warning"))
   698  					Expect(testUI.Err).To(Say("get-instances-warning"))
   699  
   700  					Expect(fakeActor.GetApplicationByNameAndSpaceCallCount()).To(Equal(1))
   701  					appNameArg, spaceGUIDArg := fakeActor.GetApplicationByNameAndSpaceArgsForCall(0)
   702  					Expect(appNameArg).To(Equal(appName))
   703  					Expect(spaceGUIDArg).To(Equal("some-space-guid"))
   704  
   705  					Expect(fakeActor.ScaleProcessByApplicationCallCount()).To(Equal(1))
   706  					appGUIDArg, scaleProcess := fakeActor.ScaleProcessByApplicationArgsForCall(0)
   707  					Expect(appGUIDArg).To(Equal("some-app-guid"))
   708  					Expect(scaleProcess).To(Equal(v7action.Process{
   709  						Type:      "some-process-type",
   710  						Instances: types.NullInt{Value: 2, IsSet: true},
   711  					}))
   712  				})
   713  			})
   714  
   715  			When("an error is encountered scaling the application", func() {
   716  				var expectedErr error
   717  
   718  				BeforeEach(func() {
   719  					cmd.Instances.Value = 3
   720  					cmd.Instances.IsSet = true
   721  					expectedErr = errors.New("scale process error")
   722  					fakeActor.ScaleProcessByApplicationReturns(
   723  						v7action.Warnings{"scale-process-warning"},
   724  						expectedErr,
   725  					)
   726  				})
   727  
   728  				It("returns the error and displays all warnings", func() {
   729  					Expect(executeErr).To(Equal(expectedErr))
   730  					Expect(testUI.Err).To(Say("scale-process-warning"))
   731  				})
   732  			})
   733  		})
   734  	})
   735  })