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