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 })