github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/integration/v7/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", appName) 49 }) 50 }) 51 52 When("the environment is set up correctly", func() { 53 BeforeEach(func() { 54 helpers.SetupCF(orgName, spaceName) 55 }) 56 57 AfterEach(func() { 58 helpers.QuickDeleteOrg(orgName) 59 }) 60 61 Describe("version dependent display", func() { 62 When("CC API >= 3.27.0", func() { 63 BeforeEach(func() { 64 helpers.SkipIfVersionLessThan(ccversion.MinVersionApplicationFlowV3) 65 }) 66 67 When("the app is created but not pushed", func() { 68 BeforeEach(func() { 69 Eventually(helpers.CF("v3-create-app", appName)).Should(Exit(0)) 70 }) 71 72 It("displays blank fields for unpopulated fields", func() { 73 session := helpers.CF("app", appName) 74 Eventually(session).Should(Say(`name:\s+%s`, appName)) 75 Eventually(session).Should(Say(`requested state:\s+stopped`)) 76 Eventually(session).Should(Say(`routes:\s+\n`)) 77 Eventually(session).Should(Say(`last uploaded:\s+\n`)) 78 Eventually(session).Should(Say(`stack:\s+\n`)) 79 Eventually(session).Should(Say(`buildpacks:\s+\n`)) 80 Eventually(session).Should(Exit(0)) 81 }) 82 }) 83 84 When("the app is a buildpack app", func() { 85 var domainName string 86 87 BeforeEach(func() { 88 domainName = helpers.DefaultSharedDomain() 89 }) 90 91 When("the app is started and has 2 instances", func() { 92 BeforeEach(func() { 93 helpers.WithHelloWorldApp(func(appDir string) { 94 manifestContents := []byte(fmt.Sprintf(` 95 --- 96 applications: 97 - name: %s 98 memory: 128M 99 instances: 2 100 disk_quota: 128M 101 routes: 102 - route: %s.%s 103 `, appName, appName, domainName)) 104 manifestPath := filepath.Join(appDir, "manifest.yml") 105 err := ioutil.WriteFile(manifestPath, manifestContents, 0666) 106 Expect(err).ToNot(HaveOccurred()) 107 108 // Create manifest 109 Eventually(helpers.CF("push", appName, "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0)) 110 }) 111 }) 112 113 // TODO: use multiprocess 114 It("uses the multiprocess display", func() { 115 userName, _ := helpers.GetCredentials() 116 117 session := helpers.CF("app", appName) 118 119 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 120 121 Eventually(session).ShouldNot(Say("This command is in EXPERIMENTAL stage and may change without notice")) 122 Eventually(session).Should(Say(`name:\s+%s`, appName)) 123 Eventually(session).Should(Say(`requested state:\s+started`)) 124 Eventually(session).Should(Say(`routes:\s+%s\.%s`, appName, domainName)) 125 Eventually(session).Should(Say(`last uploaded:\s+\w{3} \d{1,2} \w{3} \d{2}:\d{2}:\d{2} \w{3} \d{4}`)) 126 Eventually(session).Should(Say(`stack:\s+cflinuxfs2`)) 127 Eventually(session).Should(Say(`buildpacks:\s+staticfile`)) 128 Eventually(session).Should(Say(`type:\s+web`)) 129 Eventually(session).Should(Say(`instances:\s+\d/2`)) 130 Eventually(session).Should(Say(`memory usage:\s+128M`)) 131 Eventually(session).Should(Say(`\s+state\s+since\s+cpu\s+memory\s+disk\s+details`)) 132 Eventually(session).Should(Say(`#0\s+(starting|running)\s+\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z`)) 133 134 Eventually(session).Should(Exit(0)) 135 }) 136 }) 137 }) 138 139 When("the app is stopped", func() { 140 BeforeEach(func() { 141 helpers.WithHelloWorldApp(func(appDir string) { 142 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 143 }) 144 }) 145 146 It("displays that there are no running instances of the app", func() { 147 session := helpers.CF("app", appName) 148 149 userName, _ := helpers.GetCredentials() 150 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 151 Eventually(session).Should(Say(`name:\s+%s`, appName)) 152 Eventually(session).Should(Say(`requested state:\s+stopped`)) 153 Eventually(session).Should(Say(`type:\s+web`)) 154 Eventually(session).Should(Say("#0\\s+down\\s+\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) 155 Eventually(session).Should(Exit(0)) 156 }) 157 }) 158 159 When("all instances of the app are down", func() { 160 BeforeEach(func() { 161 infiniteMemQuota := helpers.QuotaName() 162 Eventually(helpers.CF("create-quota", infiniteMemQuota, "-i", "-1", "-r", "-1", "-m", "2000G")).Should(Exit(0)) 163 Eventually(helpers.CF("set-quota", orgName, infiniteMemQuota)).Should(Exit(0)) 164 helpers.WithHelloWorldApp(func(appDir string) { 165 Eventually(helpers.CF("push", appName, "-p", appDir)).Should(Exit(0)) 166 }) 167 Eventually(helpers.CFWithEnv(map[string]string{"CF_STAGING_TIMEOUT": "0.1", "CF_STARTUP_TIMEOUT": "0.1"}, "scale", appName, "-m", "1000G", "-f")).Should(Exit(1)) 168 }) 169 170 It("displays the down app instances", func() { 171 session := helpers.CF("app", appName) 172 userName, _ := helpers.GetCredentials() 173 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 174 Eventually(session).Should(Say("name:\\s+%s", appName)) 175 Eventually(session).Should(Say("requested state:\\s+started")) 176 Eventually(session).Should(Say("type:\\s+web")) 177 Eventually(session).Should(Say("#0\\s+down\\s+\\d{4}-\\d{2}-\\d{2}T\\d{2}:\\d{2}:\\d{2}Z")) 178 Eventually(session).Should(Exit(0)) 179 }) 180 }) 181 182 When("the app has 0 instances", func() { 183 BeforeEach(func() { 184 helpers.WithHelloWorldApp(func(appDir string) { 185 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "-i", "0")).Should(Exit(0)) 186 }) 187 }) 188 189 It("displays the app information", func() { 190 session := helpers.CF("app", appName) 191 userName, _ := helpers.GetCredentials() 192 193 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 194 Eventually(session).Should(Say(`name:\s+%s`, appName)) 195 Eventually(session).Should(Say(`requested state:\s+started`)) 196 Eventually(session).Should(Say(`type:\s+web`)) 197 Eventually(session).Should(Say("There are no running instances of this process")) 198 Eventually(session).Should(Exit(0)) 199 }) 200 }) 201 202 When("the --guid flag is given", func() { 203 var appGUID string 204 205 BeforeEach(func() { 206 helpers.WithHelloWorldApp(func(appDir string) { 207 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 208 }) 209 210 var AppInfo struct { 211 Resources []struct { 212 GUID string `json:"guid"` 213 } `json:"resources"` 214 } 215 216 helpers.Curl(&AppInfo, "/v3/apps?names=%s", appName) 217 appGUID = AppInfo.Resources[0].GUID 218 }) 219 220 It("displays the app guid", func() { 221 session := helpers.CF("app", "--guid", appName) 222 Eventually(session).Should(Say(appGUID)) 223 Eventually(session).Should(Exit(0)) 224 }) 225 }) 226 227 When("the app uses multiple buildpacks", func() { 228 BeforeEach(func() { 229 helpers.WithMultiBuildpackApp(func(appDir string) { 230 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "ruby_buildpack", "-b", "go_buildpack")).Should(Exit(0)) 231 }) 232 }) 233 234 It("displays the app buildpacks", func() { 235 session := helpers.CF("app", appName) 236 Eventually(session).Should(Say(`buildpacks:\s+ruby_buildpack,\s+go`)) 237 Eventually(session).Should(Exit(0)) 238 }) 239 }) 240 }) 241 242 When("CC API < 3.27.0", func() { 243 BeforeEach(func() { 244 helpers.SkipIfVersionAtLeast(ccversion.MinVersionApplicationFlowV3) 245 }) 246 247 When("the app is a buildpack app", func() { 248 var domainName string 249 250 BeforeEach(func() { 251 domainName = helpers.DefaultSharedDomain() 252 }) 253 254 When("the app is started and has 2 instances", func() { 255 BeforeEach(func() { 256 helpers.WithHelloWorldApp(func(appDir string) { 257 manifestContents := []byte(fmt.Sprintf(` 258 --- 259 applications: 260 - name: %s 261 memory: 128M 262 instances: 2 263 disk_quota: 128M 264 routes: 265 - route: %s.%s 266 `, appName, appName, domainName)) 267 manifestPath := filepath.Join(appDir, "manifest.yml") 268 err := ioutil.WriteFile(manifestPath, manifestContents, 0666) 269 Expect(err).ToNot(HaveOccurred()) 270 271 // Create manifest 272 Eventually(helpers.CF("push", appName, "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0)) 273 }) 274 }) 275 276 It("runs the v6 command", func() { 277 session := helpers.CF("app", appName) 278 Eventually(session).Should(Say(`name:\s+%s`, appName)) 279 Eventually(session).Should(Say(`requested state:\s+started`)) 280 Eventually(session).Should(Say(`instances:\s+2/2`)) 281 Eventually(session).Should(Say(`usage:\s+128M x 2 instances`)) 282 Eventually(session).Should(Say(`routes:\s+[\w\d-]+\.%s`, domainName)) 283 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}`)) 284 Eventually(session).Should(Say(`stack:\s+cflinuxfs2`)) 285 Eventually(session).Should(Say(`buildpack:\s+staticfile_buildpack`)) 286 Eventually(session).Should(Say("")) 287 Eventually(session).Should(Say(`state\s+since\s+cpu\s+memory\s+disk\s+details`)) 288 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`)) 289 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`)) 290 Eventually(session).Should(Exit(0)) 291 }) 292 }) 293 }) 294 295 When("the app is stopped", func() { 296 BeforeEach(func() { 297 helpers.WithHelloWorldApp(func(appDir string) { 298 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 299 }) 300 }) 301 302 It("displays that there are no running instances of the app", func() { 303 session := helpers.CF("app", appName) 304 305 userName, _ := helpers.GetCredentials() 306 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 307 Eventually(session).Should(Say(`name:\s+%s`, appName)) 308 Eventually(session).Should(Say(`requested state:\s+stopped`)) 309 Eventually(session).Should(Say(`usage:\s+\d+M x 1 instances`)) 310 Eventually(session).Should(Say("There are no running instances of this app.")) 311 Eventually(session).Should(Exit(0)) 312 }) 313 }) 314 315 When("the app has 0 instances", func() { 316 BeforeEach(func() { 317 helpers.SkipIfVersionLessThan(ccversion.MinVersionZeroAppInstancesV2) 318 helpers.WithHelloWorldApp(func(appDir string) { 319 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "-i", "0")).Should(Exit(0)) 320 }) 321 }) 322 323 It("displays the app information", func() { 324 session := helpers.CF("app", appName) 325 userName, _ := helpers.GetCredentials() 326 327 Eventually(session).Should(Say(`Showing health and status for app %s in org %s / space %s as %s\.\.\.`, appName, orgName, spaceName, userName)) 328 Eventually(session).Should(Say(`name:\s+%s`, appName)) 329 Eventually(session).Should(Say(`requested state:\s+started`)) 330 Eventually(session).Should(Say(`usage:\s+\d+M x 0 instances`)) 331 Eventually(session).Should(Say("There are no running instances of this app.")) 332 Eventually(session).Should(Exit(0)) 333 }) 334 }) 335 336 When("the --guid flag is given", func() { 337 var appGUID string 338 339 BeforeEach(func() { 340 helpers.WithHelloWorldApp(func(appDir string) { 341 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack", "--no-start")).Should(Exit(0)) 342 }) 343 344 var AppInfo struct { 345 Resources []struct { 346 Metadata struct { 347 GUID string `json:"guid"` 348 } `json:"metadata"` 349 } `json:"resources"` 350 } 351 helpers.Curl(&AppInfo, "/v2/apps?q=name:%s", appName) 352 appGUID = AppInfo.Resources[0].Metadata.GUID 353 }) 354 355 It("displays the app guid", func() { 356 session := helpers.CF("app", "--guid", appName) 357 Eventually(session).Should(Say(appGUID)) 358 Eventually(session).Should(Exit(0)) 359 }) 360 }) 361 }) 362 }) 363 364 Describe("version independent display", func() { 365 When("the app name is not provided", func() { 366 It("tells the user that the app name is required, prints help text, and exits 1", func() { 367 session := helpers.CF("app") 368 369 Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `APP_NAME` was not provided")) 370 Eventually(session).Should(Say("NAME:")) 371 Eventually(session).Should(Exit(1)) 372 }) 373 }) 374 375 When("the app does not exist", func() { 376 When("no flags are given", func() { 377 It("tells the user that the app is not found and exits 1", func() { 378 session := helpers.CF("app", appName) 379 380 Eventually(session).Should(Say("FAILED")) 381 Eventually(session.Err).Should(Say("App %s not found", appName)) 382 Eventually(session).Should(Exit(1)) 383 }) 384 }) 385 386 When("the --guid flag is given", func() { 387 It("tells the user that the app is not found and exits 1", func() { 388 session := helpers.CF("app", "--guid", appName) 389 390 Eventually(session).Should(Say("FAILED")) 391 Eventually(session.Err).Should(Say("App %s not found", appName)) 392 Eventually(session).Should(Exit(1)) 393 }) 394 }) 395 }) 396 397 When("the app exists", func() { 398 When("isolation segments are available", func() { 399 BeforeEach(func() { 400 helpers.SkipIfVersionLessThan(ccversion.MinVersionIsolationSegmentV3) 401 402 Eventually(helpers.CF("create-isolation-segment", RealIsolationSegment)).Should(Exit(0)) 403 Eventually(helpers.CF("enable-org-isolation", orgName, RealIsolationSegment)).Should(Exit(0)) 404 Eventually(helpers.CF("set-space-isolation-segment", spaceName, RealIsolationSegment)).Should(Exit(0)) 405 406 helpers.WithHelloWorldApp(func(appDir string) { 407 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0)) 408 }) 409 }) 410 411 It("displays the app isolation segment information", func() { 412 session := helpers.CF("app", appName) 413 414 Eventually(session).Should(Say(`isolation segment:\s+%s`, RealIsolationSegment)) 415 Eventually(session).Should(Exit(0)) 416 }) 417 }) 418 419 When("isolation segment is not set for the application", func() { 420 BeforeEach(func() { 421 helpers.WithHelloWorldApp(func(appDir string) { 422 Eventually(helpers.CF("push", appName, "-p", appDir, "-b", "staticfile_buildpack")).Should(Exit(0)) 423 }) 424 }) 425 426 It("displays the app isolation segment information", func() { 427 session := helpers.CF("app", appName) 428 429 Consistently(session).ShouldNot(Say("isolation segment:")) 430 Eventually(session).Should(Exit(0)) 431 }) 432 }) 433 434 When("the app is a Docker app", func() { 435 BeforeEach(func() { 436 Eventually(helpers.CF("push", appName, "-o", DockerImage)).Should(Exit()) 437 }) 438 439 It("displays the docker image", func() { 440 session := helpers.CF("app", appName) 441 Eventually(session).Should(Say(`name:\s+%s`, appName)) 442 Eventually(session).Should(Say(`docker image:\s+%s`, DockerImage)) 443 Eventually(session).Should(Exit(0)) 444 }) 445 446 It("does not display buildpack", func() { 447 session := helpers.CF("app", appName) 448 Consistently(session).ShouldNot(Say("buildpacks?:")) 449 Eventually(session).Should(Exit(0)) 450 }) 451 }) 452 453 When("the app has tcp routes", func() { 454 var tcpDomain helpers.Domain 455 456 BeforeEach(func() { 457 helpers.SkipIfVersionLessThan(ccversion.MinVersionRoutingV3) 458 459 tcpDomain = helpers.NewDomain(orgName, helpers.NewDomainName("tcp")) 460 tcpDomain.CreateWithRouterGroup(helpers.FindOrCreateTCPRouterGroup(GinkgoParallelNode())) 461 helpers.WithHelloWorldApp(func(appDir string) { 462 manifestContents := []byte(fmt.Sprintf(` 463 --- 464 applications: 465 - name: %s 466 routes: 467 - route: %s:1024 468 `, appName, tcpDomain.Name)) 469 manifestPath := filepath.Join(appDir, "manifest.yml") 470 err := ioutil.WriteFile(manifestPath, manifestContents, 0666) 471 Expect(err).ToNot(HaveOccurred()) 472 473 // Create manifest 474 Eventually(helpers.CF("push", appName, "-p", appDir, "-f", manifestPath, "-b", "staticfile_buildpack")).Should(Exit(0)) 475 }) 476 477 It("displays the app information", func() { 478 session := helpers.CF("app", appName) 479 Eventually(session).Should(Say(`routes:\s+[\w\d-]+\.%s`, tcpDomain)) 480 Eventually(session).Should(Exit(0)) 481 }) 482 }) 483 }) 484 }) 485 }) 486 }) 487 })