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