github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/integration/v6/isolated/app_command_test.go (about) 1 package isolated 2 3 import ( 4 "fmt" 5 "io/ioutil" 6 "path/filepath" 7 8 "code.cloudfoundry.org/cli/api/cloudcontroller/ccversion" 9 "code.cloudfoundry.org/cli/integration/helpers" 10 . "github.com/onsi/ginkgo" 11 . "github.com/onsi/gomega" 12 . "github.com/onsi/gomega/gbytes" 13 . "github.com/onsi/gomega/gexec" 14 ) 15 16 var _ = Describe("app command", func() { 17 var ( 18 orgName string 19 spaceName string 20 appName string 21 ) 22 23 BeforeEach(func() { 24 orgName = helpers.NewOrgName() 25 spaceName = helpers.NewSpaceName() 26 appName = helpers.PrefixedRandomName("app") 27 }) 28 29 Describe("help", func() { 30 When("--help flag is set", func() { 31 It("Displays command usage to output", func() { 32 session := helpers.CF("app", "--help") 33 Eventually(session).Should(Say("NAME:")) 34 Eventually(session).Should(Say("app - Display health and status for an app")) 35 Eventually(session).Should(Say("USAGE:")) 36 Eventually(session).Should(Say("cf app APP_NAME")) 37 Eventually(session).Should(Say("OPTIONS:")) 38 Eventually(session).Should(Say("--guid Retrieve and display the given app's guid. All other health and status output for the app is suppressed.")) 39 Eventually(session).Should(Say("SEE ALSO:")) 40 Eventually(session).Should(Say("apps, events, logs, map-route, push, unmap-route")) 41 Eventually(session).Should(Exit(0)) 42 }) 43 }) 44 }) 45 46 When("the environment is not setup correctly", func() { 47 It("fails with the appropriate errors", func() { 48 helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "app", "some-app") 49 }) 50 51 When("no API endpoint is set", func() { 52 BeforeEach(func() { 53 helpers.UnsetAPI() 54 }) 55 56 It("fails with no API endpoint set message", func() { 57 session := helpers.CF("app", appName) 58 Eventually(session).Should(Say("FAILED")) 59 Eventually(session.Err).Should(Say("No API endpoint set\\. Use 'cf login' or 'cf api' to target an endpoint\\.")) 60 Eventually(session).Should(Exit(1)) 61 }) 62 }) 63 When("not logged in", func() { 64 BeforeEach(func() { 65 helpers.LogoutCF() 66 }) 67 68 It("fails with not logged in message", func() { 69 session := helpers.CF("app", appName) 70 Eventually(session).Should(Say("FAILED")) 71 Eventually(session.Err).Should(Say("Not logged in\\. Use 'cf login' to log in\\.")) 72 Eventually(session).Should(Exit(1)) 73 }) 74 }) 75 76 When("there is no org set", func() { 77 BeforeEach(func() { 78 helpers.LogoutCF() 79 helpers.LoginCF() 80 }) 81 82 It("fails with no org targeted error message", func() { 83 session := helpers.CF("app", appName) 84 Eventually(session).Should(Say("FAILED")) 85 Eventually(session.Err).Should(Say("No org targeted, use 'cf target -o ORG' to target an org\\.")) 86 Eventually(session).Should(Exit(1)) 87 }) 88 }) 89 90 When("there is no space set", func() { 91 BeforeEach(func() { 92 helpers.LogoutCF() 93 helpers.LoginCF() 94 helpers.TargetOrg(ReadOnlyOrg) 95 }) 96 97 It("fails with no space targeted error message", func() { 98 session := helpers.CF("app", appName) 99 Eventually(session).Should(Say("FAILED")) 100 Eventually(session.Err).Should(Say("No space targeted, use 'cf target -s SPACE' to target a space\\.")) 101 Eventually(session).Should(Exit(1)) 102 }) 103 }) 104 }) 105 106 When("the environment is set up correctly", func() { 107 BeforeEach(func() { 108 helpers.SetupCF(orgName, spaceName) 109 }) 110 111 AfterEach(func() { 112 helpers.QuickDeleteOrg(orgName) 113 }) 114 115 Describe("version dependent display", func() { 116 When("CC API >= 3.27.0", func() { 117 BeforeEach(func() { 118 helpers.SkipIfVersionLessThan(ccversion.MinVersionApplicationFlowV3) 119 }) 120 121 When("CC API >= 3.55.0", func() { 122 BeforeEach(func() { 123 helpers.SkipIfVersionLessThan("3.55.0") 124 }) 125 126 When("all instances of the app are down", func() { 127 BeforeEach(func() { 128 infiniteMemQuota := helpers.QuotaName() 129 Eventually(helpers.CF("create-quota", infiniteMemQuota, "-i", "-1", "-r", "-1", "-m", "2000G")).Should(Exit(0)) 130 Eventually(helpers.CF("set-quota", orgName, infiniteMemQuota)).Should(Exit(0)) 131 132 helpers.WithHelloWorldApp(func(appDir string) { 133 Eventually(helpers.CF("push", appName, "-p", appDir)).Should(Exit(0)) 134 }) 135 Eventually(helpers.CFWithEnv(map[string]string{"CF_STAGING_TIMEOUT": "0.1", "CF_STARTUP_TIMEOUT": "0.1"}, "scale", appName, "-m", "1000G", "-f")).Should(Exit(1)) 136 }) 137 138 It("displays the down app instances", func() { 139 session := helpers.CF("app", appName) 140 141 userName, _ := helpers.GetCredentials() 142 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 143 Eventually(session).Should(Say("name:\\s+%s", appName)) 144 Eventually(session).Should(Say("requested state:\\s+started")) 145 Eventually(session).Should(Say("type:\\s+web")) 146 Eventually(session).Should(Say("#0\\s+down\\s+\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z.+insufficient resources: memory")) 147 Eventually(session).Should(Exit(0)) 148 }) 149 }) 150 }) 151 152 When("the app is created but not pushed", func() { 153 BeforeEach(func() { 154 Eventually(helpers.CF("v3-create-app", appName)).Should(Exit(0)) 155 }) 156 157 It("displays blank fields for unpopulated fields", func() { 158 session := helpers.CF("app", appName) 159 Eventually(session).Should(Say("name:\\s+%s", appName)) 160 Eventually(session).Should(Say("requested state:\\s+stopped")) 161 Eventually(session).Should(Say("routes:\\s+\n")) 162 Eventually(session).Should(Say("last uploaded:\\s+\n")) 163 Eventually(session).Should(Say("stack:\\s+\n")) 164 Eventually(session).Should(Say("buildpacks:\\s+\n")) 165 Eventually(session).Should(Exit(0)) 166 }) 167 }) 168 169 When("the app is a buildpack app", func() { 170 var domainName string 171 172 BeforeEach(func() { 173 domainName = helpers.DefaultSharedDomain() 174 }) 175 176 When("the app is started and has 2 instances", func() { 177 BeforeEach(func() { 178 helpers.WithHelloWorldApp(func(appDir string) { 179 manifestContents := []byte(fmt.Sprintf(` 180 --- 181 applications: 182 - name: %s 183 memory: 128M 184 instances: 2 185 disk_quota: 128M 186 routes: 187 - route: %s.%s 188 `, appName, appName, domainName)) 189 manifestPath := filepath.Join(appDir, "manifest.yml") 190 err := ioutil.WriteFile(manifestPath, manifestContents, 0666) 191 Expect(err).ToNot(HaveOccurred()) 192 193 // Create manifest 194 Eventually(helpers.CF("push", appName, "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0)) 195 }) 196 }) 197 198 // TODO: use multiprocess 199 It("uses the multiprocess display", func() { 200 userName, _ := helpers.GetCredentials() 201 202 session := helpers.CF("app", appName) 203 204 Eventually(session).Should(Say("Showing health and status for app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName)) 205 206 Eventually(session).ShouldNot(Say("This command is in EXPERIMENTAL stage and may change without notice")) 207 Eventually(session).Should(Say("name:\\s+%s", appName)) 208 Eventually(session).Should(Say("requested state:\\s+started")) 209 Eventually(session).Should(Say("routes:\\s+%s\\.%s", appName, domainName)) 210 Eventually(session).Should(Say("last uploaded:\\s+\\w{3} \\d{1,2} \\w{3} \\d{2}:\\d{2}:\\d{2} \\w{3} \\d{4}")) 211 Eventually(session).Should(Say("stack:\\s+cflinuxfs2")) 212 Eventually(session).Should(Say("buildpacks:\\s+staticfile")) 213 Eventually(session).Should(Say("type:\\s+web")) 214 Eventually(session).Should(Say("instances:\\s+\\d/2")) 215 Eventually(session).Should(Say("memory usage:\\s+128M")) 216 Eventually(session).Should(Say("\\s+state\\s+since\\s+cpu\\s+memory\\s+disk\\s+details")) 217 Eventually(session).Should(Say("#0\\s+(starting|running)\\s+\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) 218 219 Eventually(session).Should(Exit(0)) 220 }) 221 }) 222 }) 223 224 When("the app is stopped", func() { 225 BeforeEach(func() { 226 helpers.WithHelloWorldApp(func(appDir string) { 227 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 228 }) 229 }) 230 231 It("displays that there are no running instances of the app", func() { 232 session := helpers.CF("app", appName) 233 234 userName, _ := helpers.GetCredentials() 235 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 236 Eventually(session).Should(Say("name:\\s+%s", appName)) 237 Eventually(session).Should(Say("requested state:\\s+stopped")) 238 Eventually(session).Should(Say("type:\\s+web")) 239 Eventually(session).Should(Say("#0\\s+down\\s+\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) 240 Eventually(session).Should(Exit(0)) 241 }) 242 }) 243 244 When("the app has 0 instances", func() { 245 BeforeEach(func() { 246 helpers.WithHelloWorldApp(func(appDir string) { 247 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "-i", "0")).Should(Exit(0)) 248 }) 249 }) 250 251 It("displays the app information", func() { 252 session := helpers.CF("app", appName) 253 userName, _ := helpers.GetCredentials() 254 255 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 256 Eventually(session).Should(Say("name:\\s+%s", appName)) 257 Eventually(session).Should(Say("requested state:\\s+started")) 258 Eventually(session).Should(Say("type:\\s+web")) 259 Eventually(session).Should(Say("There are no running instances of this process")) 260 Eventually(session).Should(Exit(0)) 261 }) 262 }) 263 264 When("the --guid flag is given", func() { 265 var appGUID string 266 267 BeforeEach(func() { 268 helpers.WithHelloWorldApp(func(appDir string) { 269 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 270 }) 271 272 var AppInfo struct { 273 Resources []struct { 274 GUID string `json:"guid"` 275 } `json:"resources"` 276 } 277 278 helpers.Curl(&AppInfo, "/v3/apps?names=%s", appName) 279 appGUID = AppInfo.Resources[0].GUID 280 }) 281 282 It("displays the app guid", func() { 283 session := helpers.CF("app", "--guid", appName) 284 Eventually(session).Should(Say(appGUID)) 285 Eventually(session).Should(Exit(0)) 286 }) 287 }) 288 289 When("the app uses multiple buildpacks", func() { 290 BeforeEach(func() { 291 // Until version 3.43, droplets did not list all buildpacks they were built with (#150068339). 292 helpers.SkipIfVersionLessThan("3.43.0") 293 294 helpers.WithMultiBuildpackApp(func(appDir string) { 295 Eventually(helpers.CF("v3-push", appName, "-p", appDir, "-b", "ruby_buildpack", "-b", "go_buildpack")).Should(Exit(0)) 296 }) 297 }) 298 299 It("displays the app buildpacks", func() { 300 session := helpers.CF("app", appName) 301 Eventually(session).Should(Say("buildpacks:\\s+ruby_buildpack,\\s+go")) 302 Eventually(session).Should(Exit(0)) 303 }) 304 }) 305 }) 306 307 When("CC API < 3.27.0", func() { 308 BeforeEach(func() { 309 helpers.SkipIfVersionAtLeast(ccversion.MinVersionApplicationFlowV3) 310 }) 311 312 When("the app is a buildpack app", func() { 313 var domainName string 314 315 BeforeEach(func() { 316 domainName = helpers.DefaultSharedDomain() 317 }) 318 319 When("the app is started and has 2 instances", func() { 320 BeforeEach(func() { 321 helpers.WithHelloWorldApp(func(appDir string) { 322 manifestContents := []byte(fmt.Sprintf(` 323 --- 324 applications: 325 - name: %s 326 memory: 128M 327 instances: 2 328 disk_quota: 128M 329 routes: 330 - route: %s.%s 331 `, appName, appName, domainName)) 332 manifestPath := filepath.Join(appDir, "manifest.yml") 333 err := ioutil.WriteFile(manifestPath, manifestContents, 0666) 334 Expect(err).ToNot(HaveOccurred()) 335 336 // Create manifest 337 Eventually(helpers.CF("push", appName, "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0)) 338 }) 339 }) 340 341 It("runs the v6 command", func() { 342 session := helpers.CF("app", appName) 343 Eventually(session).Should(Say("name:\\s+%s", appName)) 344 Eventually(session).Should(Say("requested state:\\s+started")) 345 Eventually(session).Should(Say("instances:\\s+2/2")) 346 Eventually(session).Should(Say("usage:\\s+128M x 2 instances")) 347 Eventually(session).Should(Say("routes:\\s+[\\w\\d-]+\\.%s", domainName)) 348 Eventually(session).Should(Say("last uploaded:\\s+\\w{3} [0-3]\\d \\w{3} [0-2]\\d:[0-5]\\d:[0-5]\\d \\w+ \\d{4}")) 349 Eventually(session).Should(Say("stack:\\s+cflinuxfs2")) 350 Eventually(session).Should(Say("buildpack:\\s+staticfile_buildpack")) 351 Eventually(session).Should(Say("")) 352 Eventually(session).Should(Say("state\\s+since\\s+cpu\\s+memory\\s+disk\\s+details")) 353 Eventually(session).Should(Say("#0\\s+(running|starting)\\s+\\d{4}-[01]\\d-[0-3]\\dT[0-2][0-9]:[0-5]\\d:[0-5]\\dZ\\s+\\d+\\.\\d+%.*of 128M.*of 128M")) 354 Eventually(session).Should(Say("#1\\s+(running|starting)\\s+\\d{4}-[01]\\d-[0-3]\\dT[0-2][0-9]:[0-5]\\d:[0-5]\\dZ\\s+\\d+\\.\\d+%.*of 128M.*of 128M")) 355 Eventually(session).Should(Exit(0)) 356 }) 357 }) 358 }) 359 360 When("the app is stopped", func() { 361 BeforeEach(func() { 362 helpers.WithHelloWorldApp(func(appDir string) { 363 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 364 }) 365 }) 366 367 It("displays that there are no running instances of the app", func() { 368 session := helpers.CF("app", appName) 369 370 userName, _ := helpers.GetCredentials() 371 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 372 Eventually(session).Should(Say("name:\\s+%s", appName)) 373 Eventually(session).Should(Say("requested state:\\s+stopped")) 374 Eventually(session).Should(Say("usage:\\s+\\d+M x 1 instances")) 375 Eventually(session).Should(Say("There are no running instances of this app.")) 376 Eventually(session).Should(Exit(0)) 377 }) 378 }) 379 380 When("the app has 0 instances", func() { 381 BeforeEach(func() { 382 helpers.SkipIfVersionLessThan(ccversion.MinVersionZeroAppInstancesV2) 383 helpers.WithHelloWorldApp(func(appDir string) { 384 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "-i", "0")).Should(Exit(0)) 385 }) 386 }) 387 388 It("displays the app information", func() { 389 session := helpers.CF("app", appName) 390 userName, _ := helpers.GetCredentials() 391 392 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 393 Eventually(session).Should(Say("name:\\s+%s", appName)) 394 Eventually(session).Should(Say("requested state:\\s+started")) 395 Eventually(session).Should(Say("usage:\\s+\\d+M x 0 instances")) 396 Eventually(session).Should(Say("There are no running instances of this app.")) 397 Eventually(session).Should(Exit(0)) 398 }) 399 }) 400 401 When("the --guid flag is given", func() { 402 var appGUID string 403 404 BeforeEach(func() { 405 helpers.WithHelloWorldApp(func(appDir string) { 406 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 407 }) 408 409 var AppInfo struct { 410 Resources []struct { 411 Metadata struct { 412 GUID string `json:"guid"` 413 } `json:"metadata"` 414 } `json:"resources"` 415 } 416 helpers.Curl(&AppInfo, "/v2/apps?q=name:%s", appName) 417 appGUID = AppInfo.Resources[0].Metadata.GUID 418 }) 419 420 It("displays the app guid", func() { 421 session := helpers.CF("app", "--guid", appName) 422 Eventually(session).Should(Say(appGUID)) 423 Eventually(session).Should(Exit(0)) 424 }) 425 }) 426 }) 427 }) 428 429 Describe("version independent display", func() { 430 When("the app name is not provided", func() { 431 It("tells the user that the app name is required, prints help text, and exits 1", func() { 432 session := helpers.CF("app") 433 434 Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `APP_NAME` was not provided")) 435 Eventually(session).Should(Say("NAME:")) 436 Eventually(session).Should(Exit(1)) 437 }) 438 }) 439 440 When("the app does not exist", func() { 441 When("no flags are given", func() { 442 It("tells the user that the app is not found and exits 1", func() { 443 session := helpers.CF("app", appName) 444 445 Eventually(session).Should(Say("FAILED")) 446 Eventually(session.Err).Should(Say("App %s not found", appName)) 447 Eventually(session).Should(Exit(1)) 448 }) 449 }) 450 451 When("the --guid flag is given", func() { 452 It("tells the user that the app is not found and exits 1", func() { 453 session := helpers.CF("app", "--guid", appName) 454 455 Eventually(session).Should(Say("FAILED")) 456 Eventually(session.Err).Should(Say("App %s not found", appName)) 457 Eventually(session).Should(Exit(1)) 458 }) 459 }) 460 }) 461 462 When("the app exists", func() { 463 When("isolation segments are available", func() { 464 BeforeEach(func() { 465 helpers.SkipIfVersionLessThan(ccversion.MinVersionIsolationSegmentV3) 466 467 Eventually(helpers.CF("create-isolation-segment", RealIsolationSegment)).Should(Exit(0)) 468 Eventually(helpers.CF("enable-org-isolation", orgName, RealIsolationSegment)).Should(Exit(0)) 469 Eventually(helpers.CF("set-space-isolation-segment", spaceName, RealIsolationSegment)).Should(Exit(0)) 470 471 helpers.WithHelloWorldApp(func(appDir string) { 472 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0)) 473 }) 474 }) 475 476 It("displays the app isolation segment information", func() { 477 session := helpers.CF("app", appName) 478 479 Eventually(session).Should(Say("isolation segment:\\s+%s", RealIsolationSegment)) 480 Eventually(session).Should(Exit(0)) 481 }) 482 }) 483 484 When("isolation segment is not set for the application", func() { 485 BeforeEach(func() { 486 helpers.WithHelloWorldApp(func(appDir string) { 487 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0)) 488 }) 489 }) 490 491 It("displays the app isolation segment information", func() { 492 session := helpers.CF("app", appName) 493 494 Consistently(session).ShouldNot(Say("isolation segment:")) 495 Eventually(session).Should(Exit(0)) 496 }) 497 }) 498 499 When("the app is a Docker app", func() { 500 BeforeEach(func() { 501 Eventually(helpers.CF("push", appName, "-o", DockerImage)).Should(Exit()) 502 }) 503 504 It("displays the docker image", func() { 505 session := helpers.CF("app", appName) 506 Eventually(session).Should(Say("name:\\s+%s", appName)) 507 Eventually(session).Should(Say("docker image:\\s+%s", DockerImage)) 508 Eventually(session).Should(Exit(0)) 509 }) 510 511 It("does not display buildpack", func() { 512 session := helpers.CF("app", appName) 513 Consistently(session).ShouldNot(Say("buildpacks?:")) 514 Eventually(session).Should(Exit(0)) 515 }) 516 }) 517 518 When("the app has tcp routes", func() { 519 var tcpDomain helpers.Domain 520 521 BeforeEach(func() { 522 helpers.SkipIfVersionLessThan(ccversion.MinVersionRoutingV3) 523 524 tcpDomain = helpers.NewDomain(orgName, helpers.NewDomainName("tcp")) 525 tcpDomain.CreateWithRouterGroup(helpers.FindOrCreateTCPRouterGroup(GinkgoParallelNode())) 526 helpers.WithHelloWorldApp(func(appDir string) { 527 manifestContents := []byte(fmt.Sprintf(` 528 --- 529 applications: 530 - name: %s 531 routes: 532 - route: %s:1024 533 `, appName, tcpDomain.Name)) 534 manifestPath := filepath.Join(appDir, "manifest.yml") 535 err := ioutil.WriteFile(manifestPath, manifestContents, 0666) 536 Expect(err).ToNot(HaveOccurred()) 537 538 // Create manifest 539 Eventually(helpers.CF("push", appName, "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0)) 540 }) 541 542 It("displays the app information", func() { 543 session := helpers.CF("app", appName) 544 Eventually(session).Should(Say("routes:\\s+[\\w\\d-]+\\.%s", tcpDomain)) 545 Eventually(session).Should(Exit(0)) 546 }) 547 }) 548 }) 549 }) 550 }) 551 }) 552 })