github.com/arunkumar7540/cli@v6.45.0+incompatible/integration/v6/global/create_buildpack_command_test.go (about)

     1  package global
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"log"
     7  	"net/http"
     8  	"os"
     9  	"regexp"
    10  
    11  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
    12  	"code.cloudfoundry.org/cli/integration/helpers"
    13  	. "github.com/onsi/ginkgo"
    14  	. "github.com/onsi/gomega"
    15  	. "github.com/onsi/gomega/gbytes"
    16  	. "github.com/onsi/gomega/gexec"
    17  	. "github.com/onsi/gomega/ghttp"
    18  )
    19  
    20  var _ = Describe("create buildpack command", func() {
    21  	var (
    22  		buildpackName string
    23  		username      string
    24  	)
    25  
    26  	BeforeEach(func() {
    27  		buildpackName = helpers.NewBuildpackName()
    28  	})
    29  
    30  	Describe("help", func() {
    31  		When("--help flag is set", func() {
    32  			It("Displays command usage to output", func() {
    33  				session := helpers.CF("create-buildpack", "--help")
    34  				Eventually(session).Should(Say("NAME:"))
    35  				Eventually(session).Should(Say("create-buildpack - Create a buildpack"))
    36  				Eventually(session).Should(Say("USAGE:"))
    37  				Eventually(session).Should(Say(`cf create-buildpack BUILDPACK PATH POSITION \[--enable|--disable\]`))
    38  				Eventually(session).Should(Say("TIP:"))
    39  				Eventually(session).Should(Say("Path should be a zip file, a url to a zip file, or a local directory. Position is a positive integer, sets priority, and is sorted from lowest to highest."))
    40  				Eventually(session).Should(Say("OPTIONS:"))
    41  				Eventually(session).Should(Say(`--disable\s+Disable the buildpack from being used for staging`))
    42  				Eventually(session).Should(Say(`--enable\s+Enable the buildpack to be used for staging`))
    43  				Eventually(session).Should(Say("SEE ALSO:"))
    44  				Eventually(session).Should(Say("buildpacks, push"))
    45  				Eventually(session).Should(Exit(0))
    46  			})
    47  		})
    48  	})
    49  
    50  	When("the environment is not setup correctly", func() {
    51  		It("fails with the appropriate errors", func() {
    52  			path, err := os.Getwd()
    53  			Expect(err).ToNot(HaveOccurred())
    54  
    55  			helpers.CheckEnvironmentTargetedCorrectly(false, false, ReadOnlyOrg, "create-buildpack", "fake-buildpack", path, "1")
    56  		})
    57  	})
    58  
    59  	When("the user is logged in", func() {
    60  		BeforeEach(func() {
    61  			helpers.LoginCF()
    62  			username, _ = helpers.GetCredentials()
    63  		})
    64  
    65  		When("uploading from a directory", func() {
    66  			var buildpackDir string
    67  
    68  			AfterEach(func() {
    69  				err := os.RemoveAll(buildpackDir)
    70  				Expect(err).ToNot(HaveOccurred())
    71  			})
    72  
    73  			When("zipping the directory errors", func() {
    74  				BeforeEach(func() {
    75  					buildpackDir = "some/nonexistent/dir"
    76  				})
    77  
    78  				It("returns an error", func() {
    79  					session := helpers.CF("create-buildpack", buildpackName, buildpackDir, "1")
    80  					Eventually(session.Err).Should(Say("Incorrect Usage: The specified path 'some/nonexistent/dir' does not exist."))
    81  					Eventually(session).Should(Say("USAGE:"))
    82  					Eventually(session).Should(Exit(1))
    83  				})
    84  			})
    85  
    86  			When("zipping the directory succeeds", func() {
    87  				BeforeEach(func() {
    88  					var err error
    89  					buildpackDir, err = ioutil.TempDir("", "buildpackdir-")
    90  					Expect(err).ToNot(HaveOccurred())
    91  					file, err := ioutil.TempFile(buildpackDir, "myfile-")
    92  					defer file.Close()
    93  					Expect(err).ToNot(HaveOccurred())
    94  				})
    95  
    96  				It("successfully uploads a buildpack", func() {
    97  					session := helpers.CF("create-buildpack", buildpackName, buildpackDir, "1")
    98  					Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
    99  					Eventually(session).Should(Say("OK"))
   100  					Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   101  					Eventually(session).Should(Say("Done uploading"))
   102  					Eventually(session).Should(Say("OK"))
   103  					Eventually(session).Should(Exit(0))
   104  				})
   105  			})
   106  
   107  			When("the specified directory is empty", func() {
   108  				BeforeEach(func() {
   109  					var err error
   110  					buildpackDir, err = ioutil.TempDir("", "empty-")
   111  					Expect(err).ToNot(HaveOccurred())
   112  				})
   113  
   114  				It("fails and reports that the directory is empty", func() {
   115  					session := helpers.CF("create-buildpack", buildpackName, buildpackDir, "1")
   116  					Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   117  					Eventually(session.Err).Should(Say("The specified path '%s' cannot be an empty directory.", regexp.QuoteMeta(buildpackDir)))
   118  					Eventually(session).Should(Say("FAILED"))
   119  					Eventually(session).Should(Exit(1))
   120  				})
   121  			})
   122  		})
   123  
   124  		When("uploading from a zip", func() {
   125  			var stacks []string
   126  
   127  			BeforeEach(func() {
   128  				stacks = helpers.EnsureMinimumNumberOfStacks(2)
   129  			})
   130  
   131  			When("specifying a valid path", func() {
   132  				When("the new buildpack is unique", func() {
   133  					When("the new buildpack has a nil stack", func() {
   134  						It("successfully uploads a buildpack", func() {
   135  							helpers.BuildpackWithoutStack(func(buildpackPath string) {
   136  								session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   137  								Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   138  								Eventually(session).Should(Say("OK"))
   139  								Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   140  								Eventually(session).Should(Say("Done uploading"))
   141  								Eventually(session).Should(Say("OK"))
   142  								Eventually(session).Should(Exit(0))
   143  							})
   144  
   145  							session := helpers.CF("buildpacks")
   146  							Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   147  								Name: buildpackName, Position: "1"})))
   148  							Eventually(session).Should(Exit(0))
   149  						})
   150  					})
   151  
   152  					When("the new buildpack has a valid stack", func() {
   153  						BeforeEach(func() {
   154  							helpers.SkipIfVersionLessThan(ccversion.MinVersionBuildpackStackAssociationV2)
   155  						})
   156  
   157  						It("successfully uploads a buildpack", func() {
   158  							helpers.BuildpackWithStack(func(buildpackPath string) {
   159  								session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   160  								Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   161  								Eventually(session).Should(Say("OK"))
   162  								Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   163  								Eventually(session).Should(Say("Done uploading"))
   164  								Eventually(session).Should(Say("OK"))
   165  								Eventually(session).Should(Exit(0))
   166  							}, stacks[0])
   167  
   168  							session := helpers.CF("buildpacks")
   169  							Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   170  								Name: buildpackName, Stack: stacks[0], Position: "1",
   171  							})))
   172  							Eventually(session).Should(Exit(0))
   173  						})
   174  					})
   175  				})
   176  
   177  				When("the new buildpack has an invalid stack", func() {
   178  					BeforeEach(func() {
   179  						helpers.SkipIfVersionLessThan(ccversion.MinVersionBuildpackStackAssociationV2)
   180  					})
   181  
   182  					It("returns the appropriate error", func() {
   183  						helpers.BuildpackWithStack(func(buildpackPath string) {
   184  							session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   185  							Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   186  							Eventually(session).Should(Say("OK"))
   187  							Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   188  							Eventually(session.Err).Should(Say(`Uploaded buildpack stack \(fake-stack\) does not exist`))
   189  							Eventually(session).Should(Exit(1))
   190  						}, "fake-stack")
   191  					})
   192  				})
   193  
   194  				When("a buildpack with the same name exists", func() {
   195  					var (
   196  						existingBuildpack string
   197  					)
   198  
   199  					BeforeEach(func() {
   200  						existingBuildpack = buildpackName
   201  					})
   202  
   203  					When("the new buildpack has a nil stack", func() {
   204  						BeforeEach(func() {
   205  							helpers.SkipIfVersionLessThan(ccversion.MinVersionBuildpackStackAssociationV2)
   206  						})
   207  
   208  						When("the existing buildpack does not have a nil stack", func() {
   209  							BeforeEach(func() {
   210  								helpers.BuildpackWithStack(func(buildpackPath string) {
   211  									session := helpers.CF("create-buildpack", existingBuildpack, buildpackPath, "5")
   212  									Eventually(session).Should(Exit(0))
   213  								}, stacks[0])
   214  							})
   215  
   216  							It("successfully uploads a buildpack", func() {
   217  								helpers.BuildpackWithStack(func(buildpackPath string) {
   218  									session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   219  									Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   220  									Eventually(session).Should(Say("OK"))
   221  									Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   222  									Eventually(session).Should(Exit(0))
   223  								}, stacks[0])
   224  
   225  								session := helpers.CF("buildpacks")
   226  								Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   227  									Name: buildpackName, Position: "1"})))
   228  								Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   229  									Name: existingBuildpack, Stack: stacks[0], Position: "6"})))
   230  								Eventually(session).Should(Exit(0))
   231  							})
   232  						})
   233  
   234  						When("the existing buildpack has a nil stack", func() {
   235  							BeforeEach(func() {
   236  								helpers.BuildpackWithoutStack(func(buildpackPath string) {
   237  									session := helpers.CF("create-buildpack", existingBuildpack, buildpackPath, "5")
   238  									Eventually(session).Should(Exit(0))
   239  								})
   240  							})
   241  
   242  							It("prints a warning but exits 0", func() {
   243  								helpers.BuildpackWithoutStack(func(buildpackPath string) {
   244  									session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   245  									Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   246  									Eventually(session.Err).Should(Say("Buildpack %s already exists without a stack", buildpackName))
   247  									Eventually(session).Should(Exit(0))
   248  								})
   249  
   250  								session := helpers.CF("buildpacks")
   251  								Eventually(session).Should(Say(`%s\s+5`, existingBuildpack))
   252  								Eventually(session).Should(Exit(0))
   253  							})
   254  						})
   255  					})
   256  
   257  					When("the new buildpack has a non-nil stack", func() {
   258  						BeforeEach(func() {
   259  							helpers.SkipIfVersionLessThan(ccversion.MinVersionBuildpackStackAssociationV2)
   260  						})
   261  
   262  						When("the existing buildpack has a different non-nil stack", func() {
   263  							BeforeEach(func() {
   264  								helpers.BuildpackWithStack(func(buildpackPath string) {
   265  									session := helpers.CF("create-buildpack", existingBuildpack, buildpackPath, "5")
   266  									Eventually(session).Should(Exit(0))
   267  								}, stacks[1])
   268  							})
   269  
   270  							It("successfully uploads a buildpack", func() {
   271  								helpers.BuildpackWithStack(func(buildpackPath string) {
   272  									session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   273  									Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   274  									Eventually(session).Should(Say("OK"))
   275  									Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   276  									Eventually(session).Should(Say("Done uploading"))
   277  									Eventually(session).Should(Say("OK"))
   278  									Eventually(session).Should(Exit(0))
   279  								}, stacks[0])
   280  
   281  								session := helpers.CF("buildpacks")
   282  								Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   283  									Name: buildpackName, Stack: stacks[0]})))
   284  								Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   285  									Name: existingBuildpack, Stack: stacks[1]})))
   286  								Eventually(session).Should(Exit(0))
   287  							})
   288  						})
   289  
   290  						When("the existing buildpack has a nil stack", func() {
   291  							BeforeEach(func() {
   292  								helpers.BuildpackWithoutStack(func(buildpackPath string) {
   293  									session := helpers.CF("create-buildpack", existingBuildpack, buildpackPath, "5")
   294  									Eventually(session).Should(Exit(0))
   295  								})
   296  							})
   297  
   298  							It("prints a warning and tip but exits 0", func() {
   299  								helpers.BuildpackWithStack(func(buildpackPath string) {
   300  									session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   301  									Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   302  									Eventually(session.Err).Should(Say("Buildpack %s already exists without a stack", buildpackName))
   303  									Eventually(session).Should(Say("TIP: use 'cf buildpacks' and 'cf delete-buildpack' to delete buildpack %s without a stack", buildpackName))
   304  									Eventually(session).Should(Exit(0))
   305  								}, stacks[0])
   306  							})
   307  						})
   308  
   309  						When("the existing buildpack has the same non-nil stack", func() {
   310  							BeforeEach(func() {
   311  								helpers.BuildpackWithStack(func(buildpackPath string) {
   312  									session := helpers.CF("create-buildpack", existingBuildpack, buildpackPath, "5")
   313  									Eventually(session).Should(Exit(0))
   314  								}, stacks[0])
   315  							})
   316  
   317  							It("prints a warning but doesn't exit 1", func() {
   318  								helpers.BuildpackWithStack(func(buildpackPath string) {
   319  									session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   320  									Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   321  									Eventually(session.Err).Should(Say("The buildpack name %s is already in use for the stack %s", buildpackName, stacks[0]))
   322  									Eventually(session).Should(Say("TIP: use 'cf update-buildpack' to update this buildpack"))
   323  									Eventually(session).Should(Exit(0))
   324  								}, stacks[0])
   325  							})
   326  						})
   327  					})
   328  
   329  					When("the API doesn't support stack association", func() {
   330  						BeforeEach(func() {
   331  							helpers.SkipIfVersionAtLeast(ccversion.MinVersionBuildpackStackAssociationV2)
   332  
   333  							helpers.BuildpackWithoutStack(func(buildpackPath string) {
   334  								session := helpers.CF("create-buildpack", existingBuildpack, buildpackPath, "5")
   335  								Eventually(session).Should(Exit(0))
   336  							})
   337  						})
   338  
   339  						It("prints a warning but doesn't exit 1", func() {
   340  							helpers.BuildpackWithoutStack(func(buildpackPath string) {
   341  								session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   342  								Eventually(session.Err).Should(Say("Buildpack %s already exists", buildpackName))
   343  								Eventually(session).Should(Say("TIP: use 'cf update-buildpack' to update this buildpack"))
   344  								Eventually(session).Should(Exit(0))
   345  							})
   346  						})
   347  					})
   348  				})
   349  			})
   350  
   351  			When("specifying an invalid path", func() {
   352  				It("returns the appropriate error", func() {
   353  					session := helpers.CF("create-buildpack", buildpackName, "bogus-path", "1")
   354  
   355  					Eventually(session.Err).Should(Say("Incorrect Usage: The specified path 'bogus-path' does not exist"))
   356  					Eventually(session).Should(Say("USAGE:"))
   357  					Eventually(session).Should(Exit(1))
   358  				})
   359  			})
   360  		})
   361  
   362  		When("uploading from a URL", func() {
   363  			var buildpackURL string
   364  
   365  			When("specifying a valid URL", func() {
   366  				BeforeEach(func() {
   367  					buildpackURL = "https://github.com/cloudfoundry/binary-buildpack/releases/download/v1.0.21/binary-buildpack-v1.0.21.zip"
   368  				})
   369  
   370  				It("successfully uploads a buildpack", func() {
   371  					session := helpers.CF("create-buildpack", buildpackName, buildpackURL, "1")
   372  					Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   373  					Eventually(session).Should(Say("OK"))
   374  					Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   375  					Eventually(session).Should(Say("Done uploading"))
   376  					Eventually(session).Should(Say("OK"))
   377  					Eventually(session).Should(Exit(0))
   378  				})
   379  			})
   380  
   381  			When("a 4xx or 5xx HTTP response status is encountered", func() {
   382  				var server *Server
   383  
   384  				BeforeEach(func() {
   385  					server = NewServer()
   386  					// Suppresses ginkgo server logs
   387  					server.HTTPTestServer.Config.ErrorLog = log.New(&bytes.Buffer{}, "", 0)
   388  					server.AppendHandlers(
   389  						CombineHandlers(
   390  							VerifyRequest(http.MethodGet, "/"),
   391  							RespondWith(http.StatusNotFound, nil),
   392  						),
   393  					)
   394  				})
   395  
   396  				AfterEach(func() {
   397  					server.Close()
   398  				})
   399  
   400  				It("displays an appropriate error", func() {
   401  					session := helpers.CF("create-buildpack", buildpackName, server.URL(), "10")
   402  					Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   403  					Eventually(session.Err).Should(Say("Download attempt failed; server returned 404 Not Found"))
   404  					Eventually(session.Err).Should(Say(`Unable to install; buildpack is not available from the given URL\.`))
   405  					Eventually(session).Should(Say("FAILED"))
   406  					Eventually(session).Should(Exit(1))
   407  				})
   408  			})
   409  
   410  			When("specifying an invalid URL", func() {
   411  				BeforeEach(func() {
   412  					buildpackURL = "http://not-a-real-url"
   413  				})
   414  
   415  				It("returns the appropriate error", func() {
   416  					session := helpers.CF("create-buildpack", buildpackName, buildpackURL, "1")
   417  					Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   418  					Eventually(session.Err).Should(Say("Get %s: dial tcp: lookup", buildpackURL))
   419  					Eventually(session).Should(Say("FAILED"))
   420  					Eventually(session).Should(Exit(1))
   421  				})
   422  			})
   423  		})
   424  
   425  		When("specifying the position flag", func() {
   426  			When("position is positive integer", func() {
   427  				It("successfully uploads buildpack in correct position", func() {
   428  					helpers.BuildpackWithoutStack(func(buildpackPath string) {
   429  						session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "3")
   430  						Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   431  						Eventually(session).Should(Say("OK"))
   432  						Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   433  						Eventually(session).Should(Say("Done uploading"))
   434  						Eventually(session).Should(Say("OK"))
   435  						Eventually(session).Should(Exit(0))
   436  					})
   437  
   438  					session := helpers.CF("buildpacks")
   439  					Eventually(session).Should(Say(`%s\s+3`, buildpackName))
   440  					Eventually(session).Should(Exit(0))
   441  				})
   442  			})
   443  		})
   444  
   445  		When("using the enable/disable flags", func() {
   446  			When("specifying disable flag", func() {
   447  				It("disables buildpack", func() {
   448  					helpers.BuildpackWithoutStack(func(buildpackPath string) {
   449  						session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1", "--disable")
   450  						Eventually(session).Should(Say(`Creating buildpack %s as %s\.\.\.`, buildpackName, username))
   451  						Eventually(session).Should(Say("OK"))
   452  						Eventually(session).Should(Say(`Uploading buildpack %s as %s\.\.\.`, buildpackName, username))
   453  						Eventually(session).Should(Say("Done uploading"))
   454  						Eventually(session).Should(Say("OK"))
   455  						Eventually(session).Should(Exit(0))
   456  					})
   457  
   458  					session := helpers.CF("buildpacks")
   459  					Eventually(session).Should(Say(`%s\s+1\s+false`, buildpackName))
   460  					Eventually(session).Should(Exit(0))
   461  				})
   462  			})
   463  
   464  			When("specifying both enable and disable flags", func() {
   465  				It("returns the appropriate error", func() {
   466  					helpers.BuildpackWithoutStack(func(buildpackPath string) {
   467  						session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1", "--enable", "--disable")
   468  						Eventually(session).Should(Say("FAILED"))
   469  						Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: --enable, --disable"))
   470  						Eventually(session).Should(Exit(1))
   471  					})
   472  				})
   473  			})
   474  		})
   475  	})
   476  })