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