github.com/DaAlbrecht/cf-cli@v0.0.0-20231128151943-1fe19bb400b9/integration/v7/isolated/scale_command_test.go (about)

     1  package isolated
     2  
     3  import (
     4  	"fmt"
     5  	"strings"
     6  	"time"
     7  
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
     9  	. "code.cloudfoundry.org/cli/cf/util/testhelpers/matchers"
    10  
    11  	"code.cloudfoundry.org/cli/integration/helpers"
    12  	. "github.com/onsi/ginkgo"
    13  	. "github.com/onsi/gomega"
    14  	. "github.com/onsi/gomega/gbytes"
    15  	. "github.com/onsi/gomega/gexec"
    16  )
    17  
    18  var _ = Describe("scale command", func() {
    19  	var (
    20  		orgName   string
    21  		spaceName string
    22  		appName   string
    23  		userName  string
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		orgName = helpers.NewOrgName()
    28  		spaceName = helpers.NewSpaceName()
    29  		appName = helpers.PrefixedRandomName("app")
    30  		userName, _ = helpers.GetCredentials()
    31  	})
    32  
    33  	Describe("help", func() {
    34  		When("--help flag is set", func() {
    35  			It("appears in cf help -a", func() {
    36  				session := helpers.CF("help", "-a")
    37  				Eventually(session).Should(Exit(0))
    38  				Expect(session).To(HaveCommandInCategoryWithDescription("scale", "APPS", "Change or view the instance count, disk space limit, memory limit, and log rate limit for an app"))
    39  			})
    40  
    41  			It("displays command usage to output", func() {
    42  				session := helpers.CF("scale", "--help")
    43  
    44  				Eventually(session).Should(Say("NAME:"))
    45  				Eventually(session).Should(Say("scale - Change or view the instance count, disk space limit, memory limit, and log rate limit for an app"))
    46  
    47  				Eventually(session).Should(Say("USAGE:"))
    48  				Eventually(session).Should(Say(`cf scale APP_NAME \[--process PROCESS\] \[-i INSTANCES\] \[-k DISK\] \[-m MEMORY\] \[-l LOG_RATE_LIMIT\]`))
    49  				Eventually(session).Should(Say("Modifying the app's disk, memory, or log rate will cause the app to restart."))
    50  
    51  				Eventually(session).Should(Say("OPTIONS:"))
    52  				Eventually(session).Should(Say(`-f\s+Force restart of app without prompt`))
    53  				Eventually(session).Should(Say(`-i\s+Number of instances`))
    54  				Eventually(session).Should(Say(`-k\s+Disk limit \(e\.g\. 256M, 1024M, 1G\)`))
    55  				Eventually(session).Should(Say(`-l\s+Log rate limit per second, in bytes \(e\.g\. 128B, 4K, 1M\). -l=-1 represents unlimited`))
    56  				Eventually(session).Should(Say(`-m\s+Memory limit \(e\.g\. 256M, 1024M, 1G\)`))
    57  				Eventually(session).Should(Say(`--process\s+App process to scale \(Default: web\)`))
    58  
    59  				Eventually(session).Should(Say("ENVIRONMENT:"))
    60  				Eventually(session).Should(Say(`CF_STARTUP_TIMEOUT=5\s+Max wait time for app instance startup, in minutes`))
    61  
    62  				Eventually(session).Should(Exit(0))
    63  			})
    64  		})
    65  	})
    66  
    67  	When("the environment is not setup correctly", func() {
    68  		It("fails with the appropriate errors", func() {
    69  			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "scale", appName)
    70  		})
    71  	})
    72  
    73  	When("the environment is set up correctly", func() {
    74  		BeforeEach(func() {
    75  			helpers.SetupCF(orgName, spaceName)
    76  		})
    77  
    78  		AfterEach(func() {
    79  			helpers.QuickDeleteOrg(orgName)
    80  		})
    81  
    82  		When("the app name is not provided", func() {
    83  			It("tells the user that the app name is required, prints help text, and exits 1", func() {
    84  				session := helpers.CF("scale")
    85  				Eventually(session).Should(Exit(1))
    86  
    87  				Expect(session.Err).To(Say("Incorrect Usage: the required argument `APP_NAME` was not provided"))
    88  				Expect(session).To(Say("NAME:"))
    89  			})
    90  		})
    91  
    92  		When("the app does not exist", func() {
    93  			It("displays app not found and exits 1", func() {
    94  				invalidAppName := "invalid-app-name"
    95  				session := helpers.CF("scale", invalidAppName)
    96  				Eventually(session).Should(Exit(1))
    97  
    98  				Expect(session.Err).To(Say("App '%s' not found", invalidAppName))
    99  				Expect(session).To(Say("FAILED"))
   100  			})
   101  		})
   102  
   103  		When("the app exists", func() {
   104  			BeforeEach(func() {
   105  				helpers.WithProcfileApp(func(appDir string) {
   106  					Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName)).Should(Exit(0))
   107  				})
   108  				helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "1G")
   109  			})
   110  
   111  			When("scale option flags are not provided", func() {
   112  				It("displays the current scale properties for all processes", func() {
   113  					session := helpers.CF("scale", appName)
   114  
   115  					Eventually(session).Should(Exit(0))
   116  
   117  					Expect(session).To(Say(`Showing current scale of app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   118  					Expect(session).To(Say(`name:\s+%s`, appName))
   119  					Expect(session).To(Say(`requested state:\s+started`))
   120  
   121  					Consistently(session).ShouldNot(Say("Scaling"))
   122  					Consistently(session).ShouldNot(Say("This will cause the app to restart"))
   123  					Consistently(session).ShouldNot(Say("Stopping"))
   124  					Consistently(session).ShouldNot(Say("Starting"))
   125  					Consistently(session).ShouldNot(Say("Waiting"))
   126  
   127  					appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   128  					Expect(len(appTable.Processes)).To(Equal(2))
   129  
   130  					processSummary := appTable.Processes[0]
   131  					Expect(processSummary.Type).To(Equal("web"))
   132  					Expect(processSummary.InstanceCount).To(Equal("1/1"))
   133  
   134  					instanceSummary := processSummary.Instances[0]
   135  					Expect(instanceSummary.Memory).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of \d+?[KMG]?`))
   136  					Expect(instanceSummary.Disk).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of \d+?[KMG]?`))
   137  
   138  					Expect(appTable.Processes[1].Type).To(Equal("console"))
   139  					Expect(appTable.Processes[1].InstanceCount).To(Equal("0/0"))
   140  				})
   141  			})
   142  
   143  			When("only one scale option flag is provided", func() {
   144  				When("scaling the number of instances", func() {
   145  					It("Scales to the correct number of instances", func() {
   146  						By("Verifying we start with one instance")
   147  						session := helpers.CF("scale", appName)
   148  						Eventually(session).Should(Exit(0))
   149  
   150  						appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   151  						Expect(appTable.Processes).To(HaveLen(2))
   152  
   153  						processSummary := appTable.Processes[0]
   154  						Expect(processSummary.Type).To(Equal("web"))
   155  						Expect(processSummary.InstanceCount).To(Equal("1/1"))
   156  
   157  						By("then scaling to 3 instances")
   158  						session = helpers.CF("scale", appName, "-i", "3")
   159  						Eventually(session).Should(Exit(0))
   160  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   161  						Consistently(session).ShouldNot(Say("This will cause the app to restart"))
   162  						Consistently(session).ShouldNot(Say("Stopping"))
   163  						Consistently(session).ShouldNot(Say("Starting"))
   164  
   165  						helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, true, "1G")
   166  
   167  						session = helpers.CF("app", appName)
   168  						Eventually(session).Should(Exit(0))
   169  
   170  						updatedAppTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   171  						Expect(updatedAppTable.Processes).To(HaveLen(2))
   172  
   173  						processSummary = updatedAppTable.Processes[0]
   174  						instanceSummary := processSummary.Instances[0]
   175  						Expect(processSummary.Type).To(Equal("web"))
   176  						Expect(processSummary.InstanceCount).To(MatchRegexp(`\d/3`))
   177  						Expect(instanceSummary.Disk).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of \d+[KMG]`))
   178  						Expect(instanceSummary.Memory).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of \d+[KMG]`))
   179  					})
   180  				})
   181  
   182  				When("Scaling the memory", func() {
   183  					It("scales memory to 64M", func() {
   184  						buffer := NewBuffer()
   185  						_, err := buffer.Write([]byte("y\n"))
   186  						Expect(err).ToNot(HaveOccurred())
   187  						session := helpers.CFWithStdin(buffer, "scale", appName, "-m", "64M")
   188  						Eventually(session).Should(Exit(0))
   189  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   190  						Expect(session).To(Say(`This will cause the app to restart\. Are you sure you want to scale %s\? \[yN\]:`, appName))
   191  						Expect(session).To(Say(`Stopping app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   192  						Expect(session).To(Say(`Starting app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   193  
   194  						helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "64M")
   195  					})
   196  
   197  					When("-f flag provided", func() {
   198  						It("scales without prompt", func() {
   199  							session := helpers.CF("scale", appName, "-m", "64M", "-f")
   200  							Eventually(session).Should(Exit(0))
   201  							Expect(session).To(Say("Scaling app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName))
   202  
   203  							helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "64M")
   204  						})
   205  					})
   206  				})
   207  
   208  				When("Scaling the disk space", func() {
   209  					It("scales disk to 512M", func() {
   210  						buffer := NewBuffer()
   211  						_, err := buffer.Write([]byte("y\n"))
   212  						Expect(err).ToNot(HaveOccurred())
   213  						session := helpers.CFWithStdin(buffer, "scale", appName, "-k", "512M")
   214  						Eventually(session).Should(Exit(0))
   215  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   216  						Expect(session).To(Say(`This will cause the app to restart\. Are you sure you want to scale %s\? \[yN\]:`, appName))
   217  						Expect(session).To(Say(`Stopping app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   218  						Expect(session).To(Say(`Starting app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   219  						Expect(session).To(Say(`Instances starting\.\.\.`))
   220  
   221  						helpers.WaitForAppDiskToTakeEffect(appName, 0, 0, false, "512M")
   222  					})
   223  
   224  					When("-f flag provided", func() {
   225  						It("scales without prompt", func() {
   226  							session := helpers.CF("scale", appName, "-k", "512M", "-f")
   227  							Eventually(session).Should(Exit(0))
   228  							Expect(session).To(Say("Scaling app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName))
   229  
   230  							helpers.WaitForAppDiskToTakeEffect(appName, 0, 0, false, "512M")
   231  						})
   232  					})
   233  				})
   234  
   235  				When("Scaling the log rate limit", func() {
   236  					BeforeEach(func() {
   237  						helpers.SkipIfVersionLessThan(ccversion.MinVersionLogRateLimitingV3)
   238  					})
   239  
   240  					It("scales log rate limit to 1M", func() {
   241  						buffer := NewBuffer()
   242  						_, err := buffer.Write([]byte("y\n"))
   243  						Expect(err).ToNot(HaveOccurred())
   244  						session := helpers.CFWithStdin(buffer, "scale", appName, "-l", "1M")
   245  						Eventually(session).Should(Exit(0))
   246  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   247  						Expect(session).To(Say(`This will cause the app to restart\. Are you sure you want to scale %s\? \[yN\]:`, appName))
   248  						Expect(session).To(Say(`Stopping app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   249  						Expect(session).To(Say(`Starting app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   250  						Expect(session).To(Say(`Instances starting\.\.\.`))
   251  
   252  						helpers.WaitForLogRateLimitToTakeEffect(appName, 0, 0, false, "1M")
   253  					})
   254  
   255  					When("-f flag provided", func() {
   256  						It("scales without prompt", func() {
   257  							session := helpers.CF("scale", appName, "-l", "1M", "-f")
   258  							Eventually(session).Should(Exit(0))
   259  							Expect(session).To(Say("Scaling app %s in org %s / space %s as %s...", appName, orgName, spaceName, userName))
   260  
   261  							helpers.WaitForLogRateLimitToTakeEffect(appName, 0, 0, false, "1M")
   262  						})
   263  					})
   264  				})
   265  
   266  				When("Scaling to 0 instances", func() {
   267  					It("scales to 0 instances", func() {
   268  						session := helpers.CF("scale", appName, "-i", "0")
   269  						Eventually(session).Should(Exit(0))
   270  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   271  						Consistently(session).ShouldNot(Say(`This will cause the app to restart|Stopping|Starting`))
   272  						updatedAppTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   273  						Expect(updatedAppTable.Processes[0].InstanceCount).To(Equal("0/0"))
   274  						Expect(updatedAppTable.Processes[0].Instances).To(BeEmpty())
   275  					})
   276  				})
   277  
   278  				When("the user chooses not to restart the app", func() {
   279  					It("cancels the scale", func() {
   280  						buffer := NewBuffer()
   281  						_, err := buffer.Write([]byte("n\n"))
   282  						session := helpers.CFWithStdin(buffer, "scale", appName, "-i", "2", "-k", "90M")
   283  						Eventually(session).Should(Exit(0))
   284  						Expect(err).ToNot(HaveOccurred())
   285  						Expect(session).To(Say("This will cause the app to restart"))
   286  						Expect(session).To(Say("Scaling cancelled"))
   287  
   288  						Consistently(session).ShouldNot(Say("Stopping"))
   289  						Consistently(session).ShouldNot(Say("Starting"))
   290  						Consistently(session).ShouldNot(Say(`Waiting for app to start\.\.\.`))
   291  
   292  						appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   293  						Expect(appTable.Processes).To(BeEmpty())
   294  					})
   295  				})
   296  			})
   297  
   298  			When("all scale option flags are provided", func() {
   299  				When("the app starts successfully", func() {
   300  					It("scales the app accordingly", func() {
   301  						buffer := NewBuffer()
   302  						_, err := buffer.Write([]byte("y\n"))
   303  						Expect(err).ToNot(HaveOccurred())
   304  
   305  						//Delay to reduce flakiness
   306  						time.Sleep(3 * time.Second)
   307  
   308  						session := helpers.CFWithStdin(buffer, "scale", appName, "-i", "2", "-k", "512M", "-m", "60M")
   309  						Eventually(session).Should(Exit(0))
   310  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   311  						Expect(session).To(Say(`This will cause the app to restart\. Are you sure you want to scale %s\? \[yN\]:`, appName))
   312  						Expect(session).To(Say(`Stopping app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   313  						Expect(session).To(Say(`Starting app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   314  
   315  						helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "60M")
   316  
   317  						//Delay to reduce flakiness
   318  						time.Sleep(5 * time.Second)
   319  
   320  						session = helpers.CF("app", appName)
   321  						Eventually(session).Should(Exit(0))
   322  
   323  						appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   324  						Expect(appTable.Processes).To(HaveLen(2))
   325  
   326  						processSummary := appTable.Processes[0]
   327  						instanceSummary := processSummary.Instances[0]
   328  						Expect(processSummary.Type).To(Equal("web"))
   329  						Expect(processSummary.InstanceCount).To(MatchRegexp(`\d/2`))
   330  						Expect(instanceSummary.State).To(MatchRegexp(`running|starting`))
   331  						Expect(instanceSummary.Memory).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of 60M`))
   332  						Expect(instanceSummary.Disk).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of 512M`))
   333  					})
   334  				})
   335  
   336  				When("the app does not start successfully", func() {
   337  					It("scales the app and displays the app summary", func() {
   338  						buffer := NewBuffer()
   339  						_, err := buffer.Write([]byte("y\n"))
   340  						Expect(err).ToNot(HaveOccurred())
   341  						session := helpers.CFWithStdin(buffer, "scale", appName, "-i", "2", "-k", "10M", "-m", "6M")
   342  						Eventually(session).Should(Exit(1))
   343  						Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   344  						Expect(session).To(Say(`This will cause the app to restart\. Are you sure you want to scale %s\? \[yN\]:`, appName))
   345  						Expect(session).To(Say(`Stopping app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   346  						Expect(session).To(Say(`Starting app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   347  
   348  						helpers.WaitForAppMemoryToTakeEffect(appName, 0, 0, false, "6M")
   349  
   350  						session = helpers.CF("restart", appName)
   351  						Eventually(session).Should(Exit(1))
   352  
   353  						session = helpers.CF("app", appName)
   354  						Eventually(session).Should(Exit(0))
   355  
   356  						appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   357  						Expect(appTable.Processes).To(HaveLen(2))
   358  
   359  						processSummary := appTable.Processes[0]
   360  						instanceSummary := processSummary.Instances[0]
   361  						Expect(processSummary.Type).To(Equal("web"))
   362  						Expect(processSummary.InstanceCount).To(MatchRegexp(`\d/2`))
   363  						Expect(instanceSummary.State).To(MatchRegexp(`crashed`))
   364  						Expect(instanceSummary.Memory).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of 6M`))
   365  						Expect(instanceSummary.Disk).To(MatchRegexp(`\d+(\.\d+)?[KMG]? of 10M`))
   366  					})
   367  				})
   368  			})
   369  
   370  			PWhen("the provided scale options are the same as the existing scale properties", func() {
   371  				var (
   372  					session          *Session
   373  					currentInstances string
   374  					maxMemory        string
   375  					maxDiskSize      string
   376  				)
   377  
   378  				BeforeEach(func() {
   379  					session = helpers.CF("scale", appName)
   380  					Eventually(session).Should(Exit(0))
   381  
   382  					appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   383  					instanceSummary := appTable.Processes[0].Instances[0]
   384  					currentInstances = fmt.Sprint(len(appTable.Processes[0].Instances))
   385  					maxMemory = strings.Fields(instanceSummary.Memory)[2]
   386  					maxDiskSize = strings.Fields(instanceSummary.Disk)[2]
   387  				})
   388  
   389  				It("the action should be a no-op", func() {
   390  					session = helpers.CF("scale", appName, "-i", currentInstances, "-m", maxMemory, "-k", maxDiskSize)
   391  					Eventually(session).Should(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   392  					Consistently(session).ShouldNot(Say("This will cause the app to restart"))
   393  					Consistently(session).ShouldNot(Say("Stopping"))
   394  					Consistently(session).ShouldNot(Say("Starting"))
   395  					Consistently(session).ShouldNot(Say("Waiting for app to start"))
   396  					Eventually(session).Should(Exit(0))
   397  
   398  					appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   399  					Expect(appTable.Processes).To(HaveLen(1))
   400  
   401  					newProcessSummary := appTable.Processes[0]
   402  					newInstanceSummary := newProcessSummary.Instances[0]
   403  					Expect(newProcessSummary.Type).To(Equal("web"))
   404  					Expect(newProcessSummary.InstanceCount).To(MatchRegexp(fmt.Sprintf(`\d/%s`, currentInstances)))
   405  					Expect(newInstanceSummary.Memory).To(MatchRegexp(fmt.Sprintf(`\d+(\.\d+)?[KMG]? of %s`, maxMemory)))
   406  					Expect(newInstanceSummary.Disk).To(MatchRegexp(fmt.Sprintf(`\d+(\.\d+)?[KMG]? of %s`, maxDiskSize)))
   407  				})
   408  			})
   409  
   410  			When("the process flag is provided", func() {
   411  				It("scales the requested process", func() {
   412  					session := helpers.CF("scale", appName, "-i", "2", "--process", "console")
   413  					Eventually(session).Should(Exit(0))
   414  					Expect(session).To(Say(`Scaling app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName))
   415  
   416  					session = helpers.CF("app", appName)
   417  					Eventually(session).Should(Exit(0))
   418  
   419  					appTable := helpers.ParseV3AppProcessTable(session.Out.Contents())
   420  					Expect(appTable.Processes).To(HaveLen(2))
   421  
   422  					processSummary := appTable.Processes[1]
   423  					Expect(processSummary.Instances).To(HaveLen(2))
   424  					Expect(processSummary.Type).To(Equal("console"))
   425  					Expect(processSummary.InstanceCount).To(MatchRegexp(`\d/2`))
   426  				})
   427  			})
   428  		})
   429  	})
   430  
   431  	When("invalid scale option values are provided", func() {
   432  		When("a negative value is passed to a flag argument", func() {
   433  			It("outputs an error message to the user, provides help text, and exits 1", func() {
   434  				session := helpers.CF("scale", "some-app", "-i=-5")
   435  				Eventually(session).Should(Exit(1))
   436  				Expect(session.Err).To(Say(`Incorrect Usage: invalid argument for flag '-i' \(expected int > 0\)`))
   437  				Expect(session).To(Say("cf scale APP_NAME"))
   438  				session = helpers.CF("scale", "some-app", "-k=-5")
   439  				Eventually(session).Should(Exit(1))
   440  				Expect(session.Err).To(Say("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB"))
   441  				Expect(session).To(Say("cf scale APP_NAME"))
   442  				session = helpers.CF("scale", "some-app", "-m=-5")
   443  				Eventually(session).Should(Exit(1))
   444  				Expect(session.Err).To(Say("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB"))
   445  				Expect(session).To(Say("cf scale APP_NAME"))
   446  			})
   447  		})
   448  
   449  		When("a non-integer value is passed to a flag argument", func() {
   450  			It("outputs an error message to the user, provides help text, and exits 1", func() {
   451  				session := helpers.CF("scale", "some-app", "-i", "not-an-integer")
   452  				Eventually(session).Should(Exit(1))
   453  				Expect(session.Err).To(Say(`Incorrect Usage: invalid argument for flag '-i' \(expected int > 0\)`))
   454  				Expect(session).To(Say("cf scale APP_NAME"))
   455  
   456  				session = helpers.CF("scale", "some-app", "-k", "not-an-integer")
   457  				Eventually(session).Should(Exit(1))
   458  				Expect(session.Err).To(Say("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB"))
   459  				Expect(session).To(Say("cf scale APP_NAME"))
   460  
   461  				session = helpers.CF("scale", "some-app", "-m", "not-an-integer")
   462  				Eventually(session).Should(Exit(1))
   463  				Expect(session.Err).To(Say("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB"))
   464  				Expect(session).To(Say("cf scale APP_NAME"))
   465  			})
   466  		})
   467  
   468  		When("the unit of measurement is not provided", func() {
   469  			It("outputs an error message to the user, provides help text, and exits 1", func() {
   470  				session := helpers.CF("scale", "some-app", "-k", "9")
   471  				Eventually(session).Should(Exit(1))
   472  				Expect(session.Err).To(Say("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB"))
   473  				Expect(session).To(Say("cf scale APP_NAME"))
   474  
   475  				session = helpers.CF("scale", "some-app", "-m", "7")
   476  				Eventually(session).Should(Exit(1))
   477  				Expect(session.Err).To(Say("Byte quantity must be an integer with a unit of measurement like M, MB, G, or GB"))
   478  				Expect(session).To(Say("cf scale APP_NAME"))
   479  			})
   480  		})
   481  	})
   482  })