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