github.com/nimakaviani/cli@v6.37.1-0.20180619223813-e734901a73fa+incompatible/integration/isolated/create_app_manifest_command_test.go (about)

     1  package isolated
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"os"
     7  	"path/filepath"
     8  	"strings"
     9  
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
    11  	"code.cloudfoundry.org/cli/integration/helpers"
    12  	"code.cloudfoundry.org/cli/util/manifest"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  	. "github.com/onsi/gomega/gbytes"
    16  	. "github.com/onsi/gomega/gexec"
    17  	yaml "gopkg.in/yaml.v2"
    18  )
    19  
    20  func createManifest(appName string) (manifest.Manifest, string, error) {
    21  	tmpDir, err := ioutil.TempDir("", "")
    22  	defer os.RemoveAll(tmpDir)
    23  	if err != nil {
    24  		return manifest.Manifest{}, "", err
    25  	}
    26  
    27  	manifestPath := filepath.Join(tmpDir, "manifest.yml")
    28  	Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tmpDir}, "create-app-manifest", appName, "-p", manifestPath)).Should(Exit(0))
    29  
    30  	manifestContents, err := ioutil.ReadFile(manifestPath)
    31  	if err != nil {
    32  		return manifest.Manifest{}, "", err
    33  	}
    34  
    35  	var appsManifest manifest.Manifest
    36  	err = yaml.Unmarshal(manifestContents, &appsManifest)
    37  	if err != nil {
    38  		return manifest.Manifest{}, "", err
    39  	}
    40  
    41  	return appsManifest, string(manifestContents), nil
    42  }
    43  
    44  var _ = Describe("create-app-manifest command", func() {
    45  	var appName string
    46  	var manifestFilePath string
    47  	var tempDir string
    48  
    49  	BeforeEach(func() {
    50  		appName = helpers.NewAppName()
    51  		var err error
    52  		tempDir, err = ioutil.TempDir("", "create-manifest")
    53  		Expect(err).ToNot(HaveOccurred())
    54  
    55  		manifestFilePath = filepath.Join(tempDir, fmt.Sprintf("%s_manifest.yml", appName))
    56  	})
    57  
    58  	AfterEach(func() {
    59  		os.RemoveAll(tempDir)
    60  	})
    61  
    62  	Context("Help", func() {
    63  		It("displays the help information", func() {
    64  			session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", "--help")
    65  			Eventually(session).Should(Say("NAME:"))
    66  			Eventually(session).Should(Say("create-app-manifest - Create an app manifest for an app that has been pushed successfully"))
    67  			Eventually(session).Should(Say("USAGE:"))
    68  			Eventually(session).Should(Say("cf create-app-manifest APP_NAME \\[-p \\/path\\/to\\/<app-name>_manifest\\.yml\\]"))
    69  			Eventually(session).Should(Say(""))
    70  			Eventually(session).Should(Say("OPTIONS:"))
    71  			Eventually(session).Should(Say("-p      Specify a path for file creation. If path not specified, manifest file is created in current working directory."))
    72  			Eventually(session).Should(Say("SEE ALSO:"))
    73  			Eventually(session).Should(Say("apps, push"))
    74  
    75  			Eventually(session).Should(Exit(0))
    76  		})
    77  	})
    78  
    79  	Context("when the environment is not setup correctly", func() {
    80  		It("fails with the appropriate errors", func() {
    81  			helpers.CheckEnvironmentTargetedCorrectly(true, true, ReadOnlyOrg, "create-app-manifest", "some-app-name")
    82  		})
    83  	})
    84  
    85  	Context("when app name not provided", func() {
    86  		It("displays a usage error", func() {
    87  			session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest")
    88  			Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `APP_NAME` was not provided"))
    89  			Eventually(session).Should(Say("USAGE:"))
    90  
    91  			Eventually(session).Should(Exit(1))
    92  		})
    93  	})
    94  
    95  	Context("when the environment is setup correctly", func() {
    96  		var (
    97  			orgName   string
    98  			spaceName string
    99  			userName  string
   100  
   101  			domainName string
   102  		)
   103  
   104  		BeforeEach(func() {
   105  			orgName = helpers.NewOrgName()
   106  			spaceName = helpers.NewSpaceName()
   107  
   108  			helpers.SetupCF(orgName, spaceName)
   109  			userName, _ = helpers.GetCredentials()
   110  			domainName = helpers.DefaultSharedDomain()
   111  		})
   112  
   113  		AfterEach(func() {
   114  			helpers.QuickDeleteOrg(orgName)
   115  		})
   116  
   117  		Context("when the app does not exist", func() {
   118  			It("displays a usage error", func() {
   119  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
   120  				Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   121  				Eventually(session).Should(Say("FAILED"))
   122  				Eventually(session.Err).Should(Say("App %s not found", appName))
   123  
   124  				Eventually(session).Should(Exit(1))
   125  			})
   126  		})
   127  
   128  		Context("when the app exists", func() {
   129  			Context("when the app does not have routes", func() {
   130  				BeforeEach(func() {
   131  					helpers.WithHelloWorldApp(func(appDir string) {
   132  						Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName, "--no-route")).Should(Exit(0))
   133  					})
   134  				})
   135  
   136  				It("creates the manifest with no-route set to true", func() {
   137  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
   138  					Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   139  					Eventually(session).Should(Say("OK"))
   140  					expectedFilePath := helpers.ConvertPathToRegularExpression(fmt.Sprintf(".%s%s_manifest.yml", string(os.PathSeparator), appName))
   141  					Eventually(session).Should(Say("Manifest file created successfully at %s", expectedFilePath))
   142  
   143  					expectedFile := fmt.Sprintf(`applications:
   144  - name: %s
   145    disk_quota: 1G
   146    instances: 1
   147    memory: 32M
   148    no-route: true
   149    stack: cflinuxfs2
   150  `, appName)
   151  
   152  					createdFile, err := ioutil.ReadFile(manifestFilePath)
   153  					Expect(err).ToNot(HaveOccurred())
   154  					Expect(string(createdFile)).To(Equal(expectedFile))
   155  
   156  					Eventually(session).Should(Exit(0))
   157  				})
   158  			})
   159  
   160  			Context("when the app has routes", func() {
   161  				BeforeEach(func() {
   162  					helpers.WithHelloWorldApp(func(appDir string) {
   163  						Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName)).Should(Exit(0))
   164  					})
   165  				})
   166  
   167  				It("creates the manifest", func() {
   168  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName)
   169  					Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   170  					Eventually(session).Should(Say("OK"))
   171  					expectedFilePath := helpers.ConvertPathToRegularExpression(fmt.Sprintf(".%s%s_manifest.yml", string(os.PathSeparator), appName))
   172  					Eventually(session).Should(Say("Manifest file created successfully at %s", expectedFilePath))
   173  
   174  					expectedFile := fmt.Sprintf(`applications:
   175  - name: %s
   176    disk_quota: 1G
   177    instances: 1
   178    memory: 32M
   179    routes:
   180    - route: %s.%s
   181    stack: cflinuxfs2
   182  `, appName, strings.ToLower(appName), domainName)
   183  
   184  					createdFile, err := ioutil.ReadFile(manifestFilePath)
   185  					Expect(err).ToNot(HaveOccurred())
   186  					Expect(string(createdFile)).To(Equal(expectedFile))
   187  
   188  					Eventually(session).Should(Exit(0))
   189  				})
   190  
   191  				Context("when the -p flag is provided", func() {
   192  					Context("when the specified file is a directory", func() {
   193  						It("displays a file creation error", func() {
   194  							session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", tempDir)
   195  							Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   196  							Eventually(session).Should(Say("FAILED"))
   197  							Eventually(session.Err).Should(Say("Error creating manifest file: open %s: is a directory", helpers.ConvertPathToRegularExpression(tempDir)))
   198  
   199  							Eventually(session).Should(Exit(1))
   200  						})
   201  					})
   202  
   203  					Context("when the specified file does not exist", func() {
   204  						var newFile string
   205  
   206  						BeforeEach(func() {
   207  							newFile = filepath.Join(tempDir, "new-file.yml")
   208  						})
   209  
   210  						It("creates the manifest in the file", func() {
   211  							session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", newFile)
   212  							Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   213  							Eventually(session).Should(Say("OK"))
   214  							Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.ConvertPathToRegularExpression(newFile)))
   215  
   216  							expectedFile := fmt.Sprintf(`applications:
   217  - name: %s
   218    disk_quota: 1G
   219    instances: 1
   220    memory: 32M
   221    routes:
   222    - route: %s.%s
   223    stack: cflinuxfs2
   224  `, appName, strings.ToLower(appName), domainName)
   225  
   226  							createdFile, err := ioutil.ReadFile(newFile)
   227  							Expect(err).ToNot(HaveOccurred())
   228  							Expect(string(createdFile)).To(Equal(expectedFile))
   229  
   230  							Eventually(session).Should(Exit(0))
   231  						})
   232  					})
   233  
   234  					Context("when the specified file exists", func() {
   235  						var existingFile string
   236  
   237  						BeforeEach(func() {
   238  							existingFile = filepath.Join(tempDir, "some-file")
   239  							f, err := os.Create(existingFile)
   240  							Expect(err).ToNot(HaveOccurred())
   241  							Expect(f.Close()).To(Succeed())
   242  						})
   243  
   244  						It("overrides the previous file with the new manifest", func() {
   245  							session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-p", existingFile)
   246  							Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   247  							Eventually(session).Should(Say("OK"))
   248  							Eventually(session).Should(Say("Manifest file created successfully at %s", helpers.ConvertPathToRegularExpression(existingFile)))
   249  
   250  							expectedFile := fmt.Sprintf(`applications:
   251  - name: %s
   252    disk_quota: 1G
   253    instances: 1
   254    memory: 32M
   255    routes:
   256    - route: %s.%s
   257    stack: cflinuxfs2
   258  `, appName, strings.ToLower(appName), domainName)
   259  
   260  							createdFile, err := ioutil.ReadFile(existingFile)
   261  							Expect(err).ToNot(HaveOccurred())
   262  							Expect(string(createdFile)).To(Equal(expectedFile))
   263  
   264  							Eventually(session).Should(Exit(0))
   265  						})
   266  					})
   267  				})
   268  			})
   269  		})
   270  
   271  		Context("when app was created with docker image", func() {
   272  
   273  			BeforeEach(func() {
   274  				Eventually(helpers.CF("push", appName, "-o", DockerImage)).Should(Exit())
   275  			})
   276  
   277  			It("creates the manifest", func() {
   278  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-v")
   279  				Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   280  				Eventually(session).Should(Say("OK"))
   281  				expectedFilePath := helpers.ConvertPathToRegularExpression(fmt.Sprintf(".%s%s_manifest.yml", string(os.PathSeparator), appName))
   282  				Eventually(session).Should(Say("Manifest file created successfully at %s", expectedFilePath))
   283  
   284  				expectedFile := fmt.Sprintf(`applications:
   285  - name: %s
   286    disk_quota: 1G
   287    docker:
   288      image: %s
   289    instances: 1
   290    memory: 32M
   291    routes:
   292    - route: %s.%s
   293    stack: cflinuxfs2
   294  `, appName, DockerImage, strings.ToLower(appName), domainName)
   295  
   296  				createdFile, err := ioutil.ReadFile(manifestFilePath)
   297  				Expect(err).ToNot(HaveOccurred())
   298  				Expect(string(createdFile)).To(Equal(expectedFile))
   299  
   300  				Eventually(session).Should(Exit(0))
   301  			})
   302  		})
   303  
   304  		Context("when the API supports docker credentials", func() {
   305  			var oldDockerPassword string
   306  
   307  			BeforeEach(func() {
   308  				helpers.SkipIfVersionLessThan(ccversion.MinVersionDockerCredentialsV2)
   309  
   310  				oldDockerPassword = os.Getenv("CF_DOCKER_PASSWORD")
   311  				Expect(os.Setenv("CF_DOCKER_PASSWORD", "my-docker-password")).To(Succeed())
   312  
   313  				Eventually(helpers.CF("push", appName, "-o", DockerImage, "--docker-username", "some-docker-username")).Should(Exit())
   314  			})
   315  
   316  			AfterEach(func() {
   317  				Expect(os.Setenv("CF_DOCKER_PASSWORD", oldDockerPassword)).To(Succeed())
   318  			})
   319  
   320  			It("creates the manifest", func() {
   321  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: tempDir}, "create-app-manifest", appName, "-v")
   322  				Eventually(session).Should(Say("Creating an app manifest from current settings of app %s in org %s / space %s as %s\\.\\.\\.", appName, orgName, spaceName, userName))
   323  				Eventually(session).Should(Say("OK"))
   324  				expectedFilePath := helpers.ConvertPathToRegularExpression(fmt.Sprintf(".%s%s_manifest.yml", string(os.PathSeparator), appName))
   325  				Eventually(session).Should(Say("Manifest file created successfully at %s", expectedFilePath))
   326  
   327  				expectedFile := fmt.Sprintf(`applications:
   328  - name: %s
   329    disk_quota: 1G
   330    docker:
   331      image: %s
   332      username: some-docker-username
   333    instances: 1
   334    memory: 32M
   335    routes:
   336    - route: %s.%s
   337    stack: cflinuxfs2
   338  `, appName, DockerImage, strings.ToLower(appName), domainName)
   339  
   340  				createdFile, err := ioutil.ReadFile(manifestFilePath)
   341  				Expect(err).ToNot(HaveOccurred())
   342  				Expect(string(createdFile)).To(Equal(expectedFile))
   343  
   344  				Eventually(session).Should(Exit(0))
   345  			})
   346  
   347  		})
   348  
   349  		Context("when app has no hostname", func() {
   350  			var domain helpers.Domain
   351  
   352  			BeforeEach(func() {
   353  				domain = helpers.NewDomain(orgName, helpers.DomainName(""))
   354  				domain.Create()
   355  
   356  				helpers.WithHelloWorldApp(func(appDir string) {
   357  					Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName, "--no-start", "-b", "staticfile_buildpack", "--no-hostname", "-d", domain.Name)).Should(Exit(0))
   358  				})
   359  			})
   360  
   361  			It("contains routes without hostnames", func() {
   362  				appManifest, _, err := createManifest(appName)
   363  				Expect(err).ToNot(HaveOccurred())
   364  
   365  				Expect(appManifest.Applications).To(HaveLen(1))
   366  				Expect(appManifest.Applications[0].Routes).To(HaveLen(1))
   367  				Expect(appManifest.Applications[0].Routes[0]).To(Equal(domain.Name))
   368  			})
   369  		})
   370  
   371  		Context("when the app has a buildpack", func() {
   372  			BeforeEach(func() {
   373  				helpers.WithHelloWorldApp(func(appDir string) {
   374  					Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName, "--no-start", "-b", "staticfile_buildpack")).Should(Exit(0))
   375  				})
   376  			})
   377  
   378  			It("returns a manifest with one buildpack under buildpacks", func() {
   379  				appManifest, rawManifest, err := createManifest(appName)
   380  				Expect(err).ToNot(HaveOccurred())
   381  
   382  				Expect(appManifest.Applications).To(HaveLen(1))
   383  				Expect(appManifest.Applications[0].Buildpacks).To(ConsistOf("staticfile_buildpack"), fmt.Sprintf("Manifest should have a staticfile_buildpack:\n%s\n", rawManifest))
   384  			})
   385  		})
   386  
   387  		Context("when the app has multiple buildpacks", func() {
   388  			BeforeEach(func() {
   389  				helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   390  
   391  				helpers.WithHelloWorldApp(func(appDir string) {
   392  					Eventually(helpers.CustomCF(helpers.CFEnv{WorkingDirectory: appDir}, "push", appName, "--no-start", "-b", "ruby_buildpack", "-b", "staticfile_buildpack")).Should(Exit(0))
   393  				})
   394  			})
   395  
   396  			It("returns a manifest with multiple buildpacks", func() {
   397  				appManifest, rawManifest, err := createManifest(appName)
   398  				Expect(err).ToNot(HaveOccurred())
   399  
   400  				Expect(appManifest.Applications).To(HaveLen(1))
   401  				Expect(appManifest.Applications[0].Buildpacks).To(ConsistOf("ruby_buildpack", "staticfile_buildpack"), fmt.Sprintf("Manifest should have ruby and staticfile:\n%s\n", rawManifest))
   402  			})
   403  		})
   404  	})
   405  })