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

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