github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/command/v3/v3_scale_command_test.go (about)

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