github.com/sleungcy-sap/cli@v7.1.0+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(`staticfile_buildpack\s+\d+.\d+.\d+\s+staticfile\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(`ruby_buildpack\s+\d+.\d+.\d+\s+ruby`))
   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  })