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