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