github.com/randomtask1155/cli@v6.41.1-0.20181227003417-a98eed78cbde+incompatible/integration/v6/push/buildpack_test.go (about)

     1  package push
     2  
     3  import (
     4  	"fmt"
     5  	"io/ioutil"
     6  	"math/rand"
     7  	"os"
     8  	"path/filepath"
     9  
    10  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
    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("push with different buildpack values", func() {
    19  	var (
    20  		appName string
    21  	)
    22  
    23  	BeforeEach(func() {
    24  		appName = helpers.NewAppName()
    25  	})
    26  
    27  	When("the buildpack flag is provided", func() {
    28  		When("only one buildpack is provided", func() {
    29  			BeforeEach(func() {
    30  				helpers.WithHelloWorldApp(func(dir string) {
    31  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
    32  						PushCommandName, appName,
    33  						"-b", "binary_buildpack",
    34  						"--no-start",
    35  					)
    36  
    37  					Eventually(session).Should(Say(`(?m)\s+buildpacks:\s+\+\s+binary_buildpack`))
    38  					Eventually(session).Should(Exit(0))
    39  				})
    40  			})
    41  
    42  			It("pushing a staticfile app with a null buildpack sets buildpack to auto-detected (staticfile)", func() {
    43  				helpers.WithHelloWorldApp(func(dir string) {
    44  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
    45  						PushCommandName, appName,
    46  						"-b", "null",
    47  					)
    48  					Eventually(session).Should(Say(`(?m)\s+buildpacks:\s+-\s+binary_buildpack`))
    49  					Eventually(session).Should(Say(`buildpacks?:\s+staticfile`))
    50  					Eventually(session).Should(Exit(0))
    51  				})
    52  			})
    53  
    54  			It("pushing a staticfile app with a default buildpack sets buildpack to auto-detected (staticfile)", func() {
    55  				helpers.WithHelloWorldApp(func(dir string) {
    56  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
    57  						PushCommandName, appName,
    58  						"-b", "default",
    59  					)
    60  					Eventually(session).Should(Say(`(?m)\s+buildpacks:\s+-\s+binary_buildpack`))
    61  					Eventually(session).Should(Say(`buildpacks?:\s+staticfile`))
    62  					Eventually(session).Should(Exit(0))
    63  				})
    64  			})
    65  		})
    66  
    67  		When("multiple instances of buildpack are provided", func() {
    68  			BeforeEach(func() {
    69  				helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
    70  			})
    71  
    72  			When("the buildpacks do not use the default stack", func() {
    73  				var (
    74  					buildpacks      []string
    75  					nonDefaultStack string
    76  				)
    77  
    78  				BeforeEach(func() {
    79  					helpers.SkipIfVersionLessThan(ccversion.MinVersionBuildpackStackAssociationV2)
    80  					nonDefaultStack = helpers.CreateStack()
    81  					buildpacks = []string{helpers.NewBuildpackName(), helpers.NewBuildpackName()}
    82  					for _, buildpack := range buildpacks {
    83  						helpers.SetupBuildpackWithStack(buildpack, nonDefaultStack)
    84  					}
    85  				})
    86  
    87  				When("a stack is provided", func() {
    88  					It("pushes the app successfully with multiple buildpacks using the stack specified", func() {
    89  						helpers.WithProcfileApp(func(dir string) {
    90  							tempfile := filepath.Join(dir, "index.html")
    91  							err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666)
    92  							Expect(err).ToNot(HaveOccurred())
    93  
    94  							session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
    95  								PushCommandName, appName,
    96  								"-b", buildpacks[0], "-b", buildpacks[1], "-s", nonDefaultStack, "--no-start",
    97  							)
    98  							Eventually(session).Should(Exit(0))
    99  						})
   100  
   101  						session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   102  
   103  						Eventually(session).Should(Say(`\s+"buildpacks":\s+`))
   104  						Eventually(session).Should(Say(`\s+"%s"`, buildpacks[0]))
   105  						Eventually(session).Should(Say(`\s+"%s"`, buildpacks[1]))
   106  						Eventually(session).Should(Say(`"stack":\s+"%s"`, nonDefaultStack))
   107  						Eventually(session).Should(Exit(0))
   108  					})
   109  				})
   110  			})
   111  
   112  			When("the app does NOT have existing buildpack configurations", func() {
   113  				It("pushes the app successfully with multiple buildpacks", func() {
   114  					helpers.WithProcfileApp(func(dir string) {
   115  						tempfile := filepath.Join(dir, "index.html")
   116  						err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666)
   117  						Expect(err).ToNot(HaveOccurred())
   118  
   119  						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   120  							PushCommandName, appName,
   121  							"-b", "staticfile_buildpack", "-b", "ruby_buildpack", "--no-start",
   122  						)
   123  						Eventually(session).Should(Exit(0))
   124  					})
   125  
   126  					session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   127  
   128  					Eventually(session).Should(Say(`\s+"buildpacks":\s+`))
   129  					Eventually(session).Should(Say(`\s+"staticfile_buildpack"`))
   130  					Eventually(session).Should(Say(`\s+"ruby_buildpack"`))
   131  					Eventually(session).Should(Exit(0))
   132  				})
   133  			})
   134  
   135  			When("the app has existing buildpacks", func() {
   136  				It("pushes the app successfully and overrides the existing buildpacks", func() {
   137  					helpers.WithHelloWorldApp(func(dir string) {
   138  						helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   139  							"applications": []map[string]interface{}{
   140  								{
   141  									"name": appName,
   142  									"buildpacks": []string{
   143  										"ruby_buildpack",
   144  										"staticfile_buildpack",
   145  									},
   146  								},
   147  							},
   148  						})
   149  						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   150  							PushCommandName, appName,
   151  							"-b", "php_buildpack", "-b", "go_buildpack", "--no-start",
   152  						)
   153  						Eventually(session).Should(Exit(0))
   154  					})
   155  
   156  					session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   157  
   158  					Eventually(session).Should(Say(`\s+"buildpacks":\s+`))
   159  					Eventually(session).Should(Say(`php_buildpack`))
   160  					Eventually(session).Should(Say(`go_buildpack`))
   161  					Eventually(session).Should(Exit(0))
   162  				})
   163  			})
   164  
   165  			When("the app has existing `buildpack`", func() {
   166  				It("pushes the app successfully and overrides the existing buildpacks", func() {
   167  					helpers.WithHelloWorldApp(func(dir string) {
   168  						helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   169  							"applications": []map[string]interface{}{
   170  								{
   171  									"name":      appName,
   172  									"buildpack": "staticfile_buildpack",
   173  								},
   174  							},
   175  						})
   176  						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   177  							PushCommandName, appName,
   178  							"-b", "php_buildpack", "-b", "go_buildpack", "--no-start",
   179  						)
   180  						Eventually(session).Should(Exit(0))
   181  					})
   182  
   183  					session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   184  
   185  					Eventually(session).Should(Say(`\s+"buildpacks":\s+`))
   186  					Eventually(session).Should(Say(`php_buildpack`))
   187  					Eventually(session).Should(Say(`go_buildpack`))
   188  					Eventually(session).Should(Exit(0))
   189  				})
   190  			})
   191  
   192  			When("one of the buildpacks provided is null or default", func() {
   193  				It("fails and prints an error", func() {
   194  					helpers.WithProcfileApp(func(dir string) {
   195  						tempfile := filepath.Join(dir, "index.html")
   196  						err := ioutil.WriteFile(tempfile, []byte(fmt.Sprintf("hello world %d", rand.Int())), 0666)
   197  						Expect(err).ToNot(HaveOccurred())
   198  
   199  						session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   200  							PushCommandName, appName,
   201  							"-b", "staticfile_buildpack", "-b", "null", "--no-start",
   202  						)
   203  						Eventually(session).Should(Exit(1))
   204  						Eventually(session.Err).Should(Say("Multiple buildpacks flags cannot have null/default option."))
   205  					})
   206  				})
   207  			})
   208  		})
   209  	})
   210  
   211  	When("buildpack is provided via manifest", func() {
   212  		It("sets buildpack and returns a warning", func() {
   213  			helpers.WithHelloWorldApp(func(dir string) {
   214  				helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   215  					"applications": []map[string]interface{}{
   216  						{
   217  							"name":      appName,
   218  							"buildpack": "staticfile_buildpack",
   219  						},
   220  					},
   221  				})
   222  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "no-start")
   223  				Eventually(session).Should(Say(`(?m)\s+buildpacks:\s+\+\s+staticfile_buildpack`))
   224  				Eventually(session.Err).Should(Say(`Deprecation warning: Use of 'buildpack'`))
   225  				Eventually(session).Should(Exit(0))
   226  			})
   227  		})
   228  	})
   229  
   230  	When("buildpacks (plural) is provided via manifest", func() {
   231  		When("mutiple buildpacks are specified", func() {
   232  			BeforeEach(func() {
   233  				helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   234  			})
   235  
   236  			It("sets all buildpacks correctly for the pushed app", func() {
   237  				helpers.WithHelloWorldApp(func(dir string) {
   238  					helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   239  						"applications": []map[string]interface{}{
   240  							{
   241  								"name": appName,
   242  								"buildpacks": []string{
   243  									"https://github.com/cloudfoundry/ruby-buildpack",
   244  									"https://github.com/cloudfoundry/staticfile-buildpack",
   245  								},
   246  							},
   247  						},
   248  					})
   249  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
   250  					Eventually(session).Should(Exit(0))
   251  				})
   252  
   253  				session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   254  
   255  				Eventually(session).Should(Say(`https://github.com/cloudfoundry/ruby-buildpack"`))
   256  				Eventually(session).Should(Say(`https://github.com/cloudfoundry/staticfile-buildpack"`))
   257  				Eventually(session).Should(Exit(0))
   258  			})
   259  		})
   260  
   261  		When("only one buildpack is specified", func() {
   262  			BeforeEach(func() {
   263  				helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   264  			})
   265  
   266  			It("sets only one buildpack for the pushed app", func() {
   267  				helpers.WithHelloWorldApp(func(dir string) {
   268  					helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   269  						"applications": []map[string]interface{}{
   270  							{
   271  								"name": appName,
   272  								"buildpacks": []string{
   273  									"https://github.com/cloudfoundry/staticfile-buildpack",
   274  								},
   275  							},
   276  						},
   277  					})
   278  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
   279  					Eventually(session).Should(Exit(0))
   280  				})
   281  
   282  				session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   283  
   284  				// TODO: fix during app command rework to actually test that the second buildpack does not exist
   285  				Eventually(session).Should(Say(`https://github.com/cloudfoundry/staticfile-buildpack"`))
   286  				Eventually(session).Should(Exit(0))
   287  			})
   288  		})
   289  
   290  		When("empty list of buildpacks is specified", func() {
   291  			BeforeEach(func() {
   292  				helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   293  			})
   294  
   295  			It("autodetects the buildpack", func() {
   296  				helpers.WithHelloWorldApp(func(dir string) {
   297  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "-b", "staticfile_buildpack", "--no-start")
   298  					Eventually(session).Should(Exit(0))
   299  
   300  					helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   301  						"applications": []map[string]interface{}{
   302  							{
   303  								"name":       appName,
   304  								"buildpacks": []string{},
   305  							},
   306  						},
   307  					})
   308  					session = helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
   309  					Eventually(session).Should(Exit(0))
   310  				})
   311  
   312  				By("displaying an empty buildpacks field")
   313  				session := helpers.CF("curl", fmt.Sprintf("v3/apps/%s", helpers.AppGUID(appName)))
   314  
   315  				Eventually(session).Should(Say(`"buildpacks": \[\]`))
   316  				Eventually(session).Should(Exit(0))
   317  			})
   318  		})
   319  
   320  		When("an empty string is specified", func() {
   321  			It("rasises an error", func() {
   322  				helpers.WithHelloWorldApp(func(dir string) {
   323  					helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   324  						"applications": []map[string]interface{}{
   325  							{
   326  								"name":       appName,
   327  								"buildpacks": nil,
   328  							},
   329  						},
   330  					})
   331  					session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
   332  					Eventually(session).Should(Exit(1))
   333  					Eventually(session.Err).Should(Say("Buildpacks property cannot be an empty string."))
   334  				})
   335  			})
   336  		})
   337  	})
   338  
   339  	When("both buildpack and buildpacks are provided via manifest", func() {
   340  		It("returns an error", func() {
   341  			helpers.WithHelloWorldApp(func(dir string) {
   342  				helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   343  					"applications": []map[string]interface{}{
   344  						{
   345  							"name":      appName,
   346  							"buildpack": "ruby_buildpack",
   347  							"buildpacks": []string{
   348  								"https://github.com/cloudfoundry/staticfile-buildpack",
   349  							},
   350  						},
   351  					},
   352  				})
   353  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
   354  
   355  				Eventually(session).Should(Exit(1))
   356  				Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: buildpack, buildpacks", appName))
   357  			})
   358  		})
   359  	})
   360  
   361  	When("both buildpacks and docker are provided via manfest", func() {
   362  		It("returns an error", func() {
   363  			helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   364  			helpers.WithHelloWorldApp(func(dir string) {
   365  				helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   366  					"applications": []map[string]interface{}{
   367  						{
   368  							"name": appName,
   369  							"docker": map[string]interface{}{
   370  								"image": PublicDockerImage,
   371  							},
   372  							"buildpacks": []string{
   373  								"https://github.com/cloudfoundry/staticfile-buildpack",
   374  							},
   375  						},
   376  					},
   377  				})
   378  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName)
   379  
   380  				Eventually(session).Should(Exit(1))
   381  				Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: docker, buildpacks", appName))
   382  			})
   383  		})
   384  	})
   385  
   386  	When("both buildpacks and docker are provided via flags", func() {
   387  		It("returns an error", func() {
   388  			helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   389  			helpers.WithHelloWorldApp(func(dir string) {
   390  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   391  					PushCommandName, appName, "-o", PublicDockerImage, "-b", "ruby_buildpack", "-b", "staticfile_buildpack",
   392  				)
   393  
   394  				Eventually(session).Should(Exit(1))
   395  				Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -b, --docker-image, -o"))
   396  			})
   397  		})
   398  	})
   399  
   400  	When("buildpack is provided via manifest and droplet is provided via flags", func() {
   401  		var tempDroplet string
   402  
   403  		BeforeEach(func() {
   404  			f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-")
   405  			Expect(err).ToNot(HaveOccurred())
   406  			Expect(f.Close()).ToNot(HaveOccurred())
   407  
   408  			tempDroplet = f.Name()
   409  		})
   410  
   411  		AfterEach(func() {
   412  			Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred())
   413  		})
   414  
   415  		It("returns an error", func() {
   416  			helpers.WithHelloWorldApp(func(dir string) {
   417  				helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   418  					"applications": []map[string]interface{}{
   419  						{
   420  							"name":      appName,
   421  							"buildpack": "https://github.com/cloudfoundry/staticfile-buildpack",
   422  						},
   423  					},
   424  				})
   425  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "--droplet", tempDroplet)
   426  
   427  				Eventually(session).Should(Exit(1))
   428  				Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpack", appName))
   429  			})
   430  		})
   431  	})
   432  
   433  	When("buildpacks is provided via manifest and droplet is provided via flags", func() {
   434  		var tempDroplet string
   435  
   436  		BeforeEach(func() {
   437  			helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   438  			f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-")
   439  			Expect(err).ToNot(HaveOccurred())
   440  			Expect(f.Close()).ToNot(HaveOccurred())
   441  
   442  			tempDroplet = f.Name()
   443  		})
   444  
   445  		AfterEach(func() {
   446  			Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred())
   447  		})
   448  
   449  		It("returns an error", func() {
   450  			helpers.WithHelloWorldApp(func(dir string) {
   451  				helpers.WriteManifest(filepath.Join(dir, "manifest.yml"), map[string]interface{}{
   452  					"applications": []map[string]interface{}{
   453  						{
   454  							"name": appName,
   455  							"buildpacks": []string{
   456  								"https://github.com/cloudfoundry/staticfile-buildpack",
   457  							},
   458  						},
   459  					},
   460  				})
   461  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir}, PushCommandName, appName, "--droplet", tempDroplet)
   462  
   463  				Eventually(session).Should(Exit(1))
   464  				Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpacks", appName))
   465  			})
   466  		})
   467  	})
   468  
   469  	When("both buildpack and droplet are provided via flags", func() {
   470  		var tempDroplet string
   471  
   472  		BeforeEach(func() {
   473  			f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-")
   474  			Expect(err).ToNot(HaveOccurred())
   475  			Expect(f.Close()).ToNot(HaveOccurred())
   476  
   477  			tempDroplet = f.Name()
   478  		})
   479  
   480  		AfterEach(func() {
   481  			Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred())
   482  		})
   483  
   484  		It("returns an error", func() {
   485  			helpers.WithHelloWorldApp(func(dir string) {
   486  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   487  					PushCommandName, appName, "--droplet", tempDroplet, "-b", "staticfile_buildpack",
   488  				)
   489  
   490  				Eventually(session).Should(Exit(1))
   491  				Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpack", appName))
   492  			})
   493  		})
   494  	})
   495  
   496  	When("both buildpacks and droplet are provided via flags", func() {
   497  		var tempDroplet string
   498  
   499  		BeforeEach(func() {
   500  			helpers.SkipIfVersionLessThan(ccversion.MinVersionManifestBuildpacksV3)
   501  			f, err := ioutil.TempFile("", "INT-push-buildpack-droplet-")
   502  			Expect(err).ToNot(HaveOccurred())
   503  			Expect(f.Close()).ToNot(HaveOccurred())
   504  
   505  			tempDroplet = f.Name()
   506  		})
   507  
   508  		AfterEach(func() {
   509  			Expect(os.RemoveAll(tempDroplet)).ToNot(HaveOccurred())
   510  		})
   511  
   512  		It("returns an error", func() {
   513  			helpers.WithHelloWorldApp(func(dir string) {
   514  				session := helpers.CustomCF(helpers.CFEnv{WorkingDirectory: dir},
   515  					PushCommandName, appName, "--droplet", tempDroplet, "-b", "ruby_buildpack", "-b", "staticfile_buildpack",
   516  				)
   517  
   518  				Eventually(session).Should(Exit(1))
   519  				Eventually(session.Err).Should(Say("Application %s cannot use the combination of properties: droplet, buildpacks", appName))
   520  			})
   521  		})
   522  	})
   523  })