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