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