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