github.com/wanddynosios/cli@v7.1.0+incompatible/integration/v6/global/update_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/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  	. "github.com/onsi/gomega/ghttp"
    17  )
    18  
    19  var _ = Describe("update-buildpack command", func() {
    20  	var (
    21  		buildpackName string
    22  		username      string
    23  	)
    24  
    25  	BeforeEach(func() {
    26  		buildpackName = helpers.NewBuildpackName()
    27  		username, _ = helpers.GetCredentials()
    28  	})
    29  
    30  	When("--help flag is set", func() {
    31  		It("Displays command usage to output", func() {
    32  			session := helpers.CF("update-buildpack", "--help")
    33  			Eventually(session).Should(Say("NAME:"))
    34  			Eventually(session).Should(Say("update-buildpack - Update a buildpack"))
    35  			Eventually(session).Should(Say("USAGE:"))
    36  			Eventually(session).Should(Say(regexp.QuoteMeta(`cf update-buildpack BUILDPACK [-p PATH | -s STACK | --assign-stack NEW_STACK] [-i POSITION] [--enable|--disable] [--lock|--unlock]`)))
    37  			Eventually(session).Should(Say("TIP:"))
    38  			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.\n\n"))
    39  			Eventually(session).Should(Say("Use '--assign-stack' with caution. Associating a buildpack with a stack that it does not support may result in undefined behavior. Additionally, changing this association once made may require a local copy of the buildpack.\n\n"))
    40  			Eventually(session).Should(Say("OPTIONS:"))
    41  			Eventually(session).Should(Say(`--assign-stack\s+Assign a stack to a buildpack that does not have a stack association`))
    42  			Eventually(session).Should(Say(`--disable\s+Disable the buildpack from being used for staging`))
    43  			Eventually(session).Should(Say(`--enable\s+Enable the buildpack to be used for staging`))
    44  			Eventually(session).Should(Say(`-i\s+The order in which the buildpacks are checked during buildpack auto-detection`))
    45  			Eventually(session).Should(Say(`--lock\s+Lock the buildpack to prevent updates`))
    46  			Eventually(session).Should(Say(`-p\s+Path to directory or zip file`))
    47  			Eventually(session).Should(Say(`--unlock\s+Unlock the buildpack to enable updates`))
    48  			Eventually(session).Should(Say(`-s\s+Specify stack to disambiguate buildpacks with the same name`))
    49  			Eventually(session).Should(Say("SEE ALSO:"))
    50  			Eventually(session).Should(Say("buildpacks, create-buildpack, delete-buildpack, rename-buildpack"))
    51  			Eventually(session).Should(Exit(0))
    52  		})
    53  	})
    54  
    55  	When("the environment is not setup correctly", func() {
    56  		It("fails with the appropriate errors", func() {
    57  			helpers.CheckEnvironmentTargetedCorrectly(false, false, ReadOnlyOrg, "update-buildpack", "fake-buildpack")
    58  		})
    59  	})
    60  
    61  	When("the user is logged in", func() {
    62  		BeforeEach(func() {
    63  			helpers.LoginCF()
    64  		})
    65  
    66  		AfterEach(func() {
    67  			helpers.DeleteBuildpackIfOnOldCCAPI(buildpackName)
    68  		})
    69  
    70  		When("the buildpack is not provided", func() {
    71  			It("returns a buildpack argument not provided error", func() {
    72  				session := helpers.CF("update-buildpack", "-p", ".")
    73  
    74  				Eventually(session.Err).Should(Say("Incorrect Usage: the required argument `BUILDPACK` was not provided"))
    75  				Eventually(session).Should(Exit(1))
    76  			})
    77  		})
    78  
    79  		When("the buildpack name is provided", func() {
    80  			When("the buildpack does not exist", func() {
    81  				It("returns a buildpack not found error", func() {
    82  					session := helpers.CF("update-buildpack", buildpackName)
    83  					Eventually(session.Err).Should(Say("Buildpack '%s' not found", buildpackName))
    84  					Eventually(session).Should(Say("FAILED"))
    85  					Eventually(session).Should(Exit(1))
    86  				})
    87  			})
    88  
    89  			Describe("stack association", func() {
    90  				var stacks []string
    91  				var stacksBefore []string
    92  
    93  				BeforeEach(func() {
    94  					stacksBefore = helpers.FetchStacks()
    95  					stacks = helpers.EnsureMinimumNumberOfStacks(2)
    96  				})
    97  				AfterEach(func() {
    98  					for i := len(stacksBefore); i < len(stacks); i++ {
    99  						helpers.DeleteStack(stacks[i])
   100  					}
   101  				})
   102  
   103  				When("multiple buildpacks with the same name exist in enabled and unlocked state, and one has nil stack", func() {
   104  					BeforeEach(func() {
   105  						helpers.BuildpackWithStack(func(buildpackArchive string) {
   106  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "99")
   107  							Eventually(createSession).Should(Exit(0))
   108  						}, stacks[0])
   109  
   110  						helpers.BuildpackWithoutStack(func(buildpackArchive string) {
   111  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "100")
   112  							Eventually(createSession).Should(Exit(0))
   113  						})
   114  
   115  						listSession := helpers.CF("buildpacks")
   116  						Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   117  							Name: buildpackName, Stack: stacks[0]})))
   118  						Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{Name: buildpackName})))
   119  						Eventually(listSession).Should(Exit(0))
   120  					})
   121  					AfterEach(func() {
   122  						Eventually(helpers.CF("delete-buildpack", buildpackName, "-s", stacks[0], "-f")).Should(Exit(0))
   123  						Eventually(helpers.CF("delete-buildpack", buildpackName, "-f")).Should(Exit(0))
   124  					})
   125  
   126  					When("no stack association is specified", func() {
   127  						It("acts on the buildpack with the nil stack", func() {
   128  							session := helpers.CF("update-buildpack", buildpackName)
   129  
   130  							Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   131  							Eventually(session).Should(Say("OK"))
   132  							Eventually(session).Should(Exit(0))
   133  						})
   134  					})
   135  
   136  					When("the user specifies a stack association not matching any of the existing buildpacks with this name", func() {
   137  						It("reports that it couldn't find the buildpack", func() {
   138  							nonexistentStack := "some-incorrect-stack-name"
   139  							session := helpers.CF("update-buildpack", buildpackName, "-s", nonexistentStack)
   140  
   141  							Eventually(session.Err).Should(Say("Buildpack '%s' with stack '%s' not found", buildpackName, nonexistentStack))
   142  							Eventually(session).Should(Say("FAILED"))
   143  							Eventually(session).Should(Exit(1))
   144  						})
   145  					})
   146  
   147  					When("the user specifies a stack association matching one of the existing buildpacks with this name", func() {
   148  						It("finds the buildpack with the stack specified (and not the buildpack with the nil stack)", func() {
   149  							session := helpers.CF("update-buildpack", buildpackName, "-s", stacks[0])
   150  
   151  							Eventually(session).Should(Say("Updating buildpack %s with stack %s as %s...",
   152  								buildpackName, stacks[0], username,
   153  							))
   154  							Eventually(session).Should(Say("OK"))
   155  							Eventually(session).Should(Exit(0))
   156  						})
   157  					})
   158  
   159  					When("the user creates a new buildpack with the same name and a different stack and tries to update to it", func() {
   160  						AfterEach(func() {
   161  							Eventually(helpers.CF("delete-buildpack", buildpackName, "-s", stacks[1], "-f")).Should(Exit(0))
   162  						})
   163  
   164  						It("complains that the stack on the new archive differs from the current buildpacks", func() {
   165  							helpers.BuildpackWithStack(func(buildpackArchive string) {
   166  								createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "99")
   167  								Eventually(createSession).Should(Exit(0))
   168  
   169  								session := helpers.CF("update-buildpack", buildpackName, "-s", stacks[0], "-p", buildpackArchive)
   170  								Eventually(session).Should(Say("Updating buildpack %s with stack %s as %s...",
   171  									buildpackName, stacks[0], username))
   172  								Eventually(session.Err).Should(Say("Uploaded buildpack stack \\(%s\\) does not match %s", stacks[1], stacks[0]))
   173  								Eventually(session).Should(Say("FAILED"))
   174  								Eventually(session).Should(Exit(1))
   175  							}, stacks[1])
   176  						})
   177  					})
   178  
   179  					When("the initial buildpack has no stack", func() {
   180  
   181  						When("and the user creates a new stackful buildpack, an update is ok", func() {
   182  							var (
   183  								stacklessBuildpackName string
   184  								stacks                 []string
   185  								stacksBefore           []string
   186  							)
   187  
   188  							BeforeEach(func() {
   189  								stacklessBuildpackName = helpers.NewBuildpackName()
   190  								stacksBefore = helpers.FetchStacks()
   191  								stacks = helpers.EnsureMinimumNumberOfStacks(2)
   192  							})
   193  							AfterEach(func() {
   194  								Eventually(helpers.CF("delete-buildpack", stacklessBuildpackName, "-f")).Should(Exit(0))
   195  								for i := len(stacksBefore); i < len(stacks); i++ {
   196  									helpers.DeleteStack(stacks[i])
   197  								}
   198  								helpers.DeleteBuildpackIfOnOldCCAPI(stacklessBuildpackName)
   199  							})
   200  
   201  							It("updates the buildpack with the new stack", func() {
   202  								helpers.BuildpackWithoutStack(func(buildpackPath string) {
   203  									session := helpers.CF("create-buildpack", stacklessBuildpackName, buildpackPath, "1")
   204  									Eventually(session).Should(Exit(0))
   205  
   206  									helpers.BuildpackWithStack(func(newBuildpackPath string) {
   207  										session = helpers.CF("update-buildpack", stacklessBuildpackName, "-p", newBuildpackPath)
   208  										Eventually(session).Should(Exit(0))
   209  									}, stacks[1])
   210  								})
   211  							})
   212  						})
   213  					})
   214  				})
   215  
   216  				When("multiple buildpacks with the same name exist in enabled and unlocked state, and all have stacks", func() {
   217  					BeforeEach(func() {
   218  						helpers.BuildpackWithStack(func(buildpackArchive string) {
   219  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "98")
   220  							Eventually(createSession).Should(Exit(0))
   221  						}, stacks[0])
   222  
   223  						helpers.BuildpackWithStack(func(buildpackArchive string) {
   224  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "99")
   225  							Eventually(createSession).Should(Exit(0))
   226  						}, stacks[1])
   227  
   228  						listSession := helpers.CF("buildpacks")
   229  						Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   230  							Name: buildpackName, Stack: stacks[0]})))
   231  						Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   232  							Name: buildpackName, Stack: stacks[1]})))
   233  						Eventually(listSession).Should(Exit(0))
   234  					})
   235  					AfterEach(func() {
   236  						Eventually(helpers.CF("delete-buildpack", buildpackName, "-f", "-s", stacks[0])).Should(Exit(0))
   237  						Eventually(helpers.CF("delete-buildpack", buildpackName, "-f", "-s", stacks[1])).Should(Exit(0))
   238  					})
   239  
   240  					When("no stack association is specified", func() {
   241  						It("displays an error saying that multiple buildpacks were found", func() {
   242  							session := helpers.CF("update-buildpack", buildpackName)
   243  
   244  							Eventually(session.Err).Should(Say(`Multiple buildpacks named %s found\. Specify a stack name by using a '-s' flag\.`, buildpackName))
   245  							Eventually(session).Should(Say("FAILED"))
   246  							Eventually(session).Should(Exit(1))
   247  						})
   248  					})
   249  
   250  					When("--assign-stack is given", func() {
   251  						It("displays an error and exits", func() {
   252  							session := helpers.CF("update-buildpack", buildpackName, "--assign-stack", stacks[0])
   253  
   254  							Eventually(session.Err).Should(Say(`Buildpack %s already exists with a stack association`, buildpackName))
   255  							Eventually(session.Err).Should(Say(`TIP: Use 'cf buildpacks' to view buildpack and stack associations`))
   256  							Eventually(session).Should(Say("FAILED"))
   257  							Eventually(session).Should(Exit(1))
   258  						})
   259  					})
   260  
   261  					When("the user specifies a stack association not matching any of the existing buildpacks with this name", func() {
   262  						It("reports that it couldn't find the buildpack", func() {
   263  							nonexistentStack := "some-incorrect-stack-name"
   264  							session := helpers.CF("update-buildpack", buildpackName, "-s", nonexistentStack)
   265  
   266  							Eventually(session.Err).Should(Say("Buildpack '%s' with stack '%s' not found", buildpackName, nonexistentStack))
   267  							Eventually(session).Should(Say("FAILED"))
   268  							Eventually(session).Should(Exit(1))
   269  						})
   270  					})
   271  
   272  					When("the user specifies a stack association matching one of the existing buildpacks with this name", func() {
   273  						It("finds the buildpack with the stack specified (and not the buildpack with the nil stack)", func() {
   274  							session := helpers.CF("update-buildpack", buildpackName, "-s", stacks[0])
   275  
   276  							Eventually(session).Should(Say("Updating buildpack %s with stack %s as %s...",
   277  								buildpackName, stacks[0], username,
   278  							))
   279  							Eventually(session).Should(Say("OK"))
   280  							Eventually(session).Should(Exit(0))
   281  						})
   282  					})
   283  				})
   284  
   285  				When("one buildpack with the given name exists in enabled and unlocked state with a stack association", func() {
   286  					BeforeEach(func() {
   287  						helpers.BuildpackWithStack(func(buildpackArchive string) {
   288  							createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "99")
   289  							Eventually(createSession).Should(Exit(0))
   290  						}, stacks[0])
   291  
   292  						listSession := helpers.CF("buildpacks")
   293  						Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   294  							Name: buildpackName, Stack: stacks[0]})))
   295  						Eventually(listSession).Should(Exit(0))
   296  					})
   297  					AfterEach(func() {
   298  						Eventually(helpers.CF("delete-buildpack", buildpackName, "-f", "-s", stacks[0])).Should(Exit(0))
   299  					})
   300  
   301  					When("no stack association is specified", func() {
   302  						It("updates the only buildpack with that name", func() {
   303  							session := helpers.CF("update-buildpack", buildpackName)
   304  
   305  							Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   306  							Eventually(session).Should(Say("OK"))
   307  							Eventually(session).Should(Exit(0))
   308  						})
   309  					})
   310  
   311  					When("the user specifies a stack association not matching any of the existing buildpacks with this name", func() {
   312  						It("reports that it couldn't find the buildpack", func() {
   313  							nonexistentStack := "some-incorrect-stack-name"
   314  							session := helpers.CF("update-buildpack", buildpackName, "-s", nonexistentStack)
   315  
   316  							Eventually(session.Err).Should(Say("Buildpack '%s' with stack '%s' not found", buildpackName, nonexistentStack))
   317  							Eventually(session).Should(Say("FAILED"))
   318  							Eventually(session).Should(Exit(1))
   319  						})
   320  					})
   321  
   322  					When("the user specifies a stack association matching one of the existing buildpacks with this name", func() {
   323  						It("finds the buildpack with the stack specified (and not the buildpack with the nil stack)", func() {
   324  							session := helpers.CF("update-buildpack", buildpackName, "-s", stacks[0])
   325  
   326  							Eventually(session).Should(Say("Updating buildpack %s with stack %s as %s...",
   327  								buildpackName, stacks[0], username,
   328  							))
   329  							Eventually(session).Should(Say("OK"))
   330  							Eventually(session).Should(Exit(0))
   331  						})
   332  					})
   333  				})
   334  			})
   335  
   336  			When("one buildpack with given name exists in enabled and unlocked state with no stack association", func() {
   337  				BeforeEach(func() {
   338  					helpers.BuildpackWithoutStack(func(buildpackArchive string) {
   339  						createSession := helpers.CF("create-buildpack", buildpackName, buildpackArchive, "99")
   340  						Eventually(createSession).Should(Exit(0))
   341  					})
   342  
   343  					listSession := helpers.CF("buildpacks")
   344  					Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{Name: buildpackName})))
   345  					Eventually(listSession).Should(Exit(0))
   346  				})
   347  				AfterEach(func() {
   348  					Eventually(helpers.CF("delete-buildpack", buildpackName, "-f")).Should(Exit(0))
   349  				})
   350  
   351  				When("only a name is provided", func() {
   352  					It("prints a success message", func() {
   353  						session := helpers.CF("update-buildpack", buildpackName)
   354  
   355  						Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   356  						Eventually(session).Should(Say("OK"))
   357  						Eventually(session).Should(Exit(0))
   358  					})
   359  				})
   360  
   361  				When("the -s flag is provided", func() {
   362  					var (
   363  						stackName string
   364  						session   *Session
   365  					)
   366  
   367  					JustBeforeEach(func() {
   368  						stackName = "some-stack"
   369  						session = helpers.CF("update-buildpack", buildpackName, "-s", stackName)
   370  					})
   371  
   372  					It("returns a buildpack with stack not found error", func() {
   373  						Eventually(session.Err).Should(Say("Buildpack '%s' with stack '%s' not found", buildpackName, stackName))
   374  						Eventually(session).Should(Say("FAILED"))
   375  						Eventually(session).Should(Exit(1))
   376  					})
   377  				})
   378  
   379  				When("the -p flag is provided", func() {
   380  					var (
   381  						buildpackPath string
   382  						session       *Session
   383  					)
   384  
   385  					JustBeforeEach(func() {
   386  						session = helpers.CF("update-buildpack", buildpackName, "-p", buildpackPath)
   387  					})
   388  
   389  					When("the path is local", func() {
   390  						When("the buildpack path exists", func() {
   391  							When("the buildpack path is an empty directory", func() {
   392  								BeforeEach(func() {
   393  									var err error
   394  									buildpackPath, err = ioutil.TempDir("", "create-buildpack-test-")
   395  									Expect(err).ToNot(HaveOccurred())
   396  								})
   397  
   398  								AfterEach(func() {
   399  									err := os.RemoveAll(buildpackPath)
   400  									Expect(err).ToNot(HaveOccurred())
   401  								})
   402  
   403  								It("prints an error message", func() {
   404  									Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   405  									Eventually(session.Err).Should(Say("The specified path '%s' cannot be an empty directory.", regexp.QuoteMeta(buildpackPath)))
   406  									Eventually(session).Should(Exit(1))
   407  								})
   408  							})
   409  
   410  							When("uploading from a directory", func() {
   411  								BeforeEach(func() {
   412  									var err error
   413  									buildpackPath, err = ioutil.TempDir("", "create-buildpack-test-")
   414  									Expect(err).ToNot(HaveOccurred())
   415  									file, err := ioutil.TempFile(buildpackPath, "")
   416  									defer file.Close() // nolint
   417  									Expect(err).ToNot(HaveOccurred())
   418  								})
   419  
   420  								AfterEach(func() {
   421  									err := os.RemoveAll(buildpackPath)
   422  									Expect(err).ToNot(HaveOccurred())
   423  								})
   424  
   425  								It("updates the buildpack with the given bits", func() {
   426  									Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   427  									Eventually(session).Should(Say("OK"))
   428  									Eventually(session).Should(Exit(0))
   429  								})
   430  							})
   431  
   432  							When("uploading from a zip", func() {
   433  								BeforeEach(func() {
   434  									buildpackPath = helpers.MakeBuildpackArchive("")
   435  								})
   436  
   437  								AfterEach(func() {
   438  									err := os.Remove(buildpackPath)
   439  									Expect(err).NotTo(HaveOccurred())
   440  								})
   441  
   442  								It("updates the buildpack with the given bits", func() {
   443  									Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   444  									Eventually(session).Should(Say("OK"))
   445  									Eventually(session).Should(Exit(0))
   446  								})
   447  							})
   448  						})
   449  
   450  						When("the buildpack path does not exist", func() {
   451  							BeforeEach(func() {
   452  								buildpackPath = "this-is-a-bogus-path"
   453  							})
   454  
   455  							It("returns a buildpack does not exist error", func() {
   456  								Eventually(session.Err).Should(Say("Incorrect Usage: The specified path 'this-is-a-bogus-path' does not exist."))
   457  								Eventually(session).Should(Exit(1))
   458  							})
   459  						})
   460  					})
   461  
   462  					When("path is a URL", func() {
   463  						When("specifying a valid URL", func() {
   464  							BeforeEach(func() {
   465  								buildpackPath = "https://github.com/cloudfoundry/binary-buildpack/releases/download/v1.0.21/binary-buildpack-v1.0.21.zip"
   466  							})
   467  
   468  							It("successfully uploads a buildpack", func() {
   469  								Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   470  								Eventually(session).Should(Say("OK"))
   471  								Eventually(session).Should(Say("Uploading buildpack %s as %s...", buildpackName, username))
   472  								Eventually(session).Should(Say("OK"))
   473  								Eventually(session).Should(Exit(0))
   474  							})
   475  						})
   476  
   477  						When("a 4xx or 5xx HTTP response status is encountered", func() {
   478  							var server *Server
   479  
   480  							BeforeEach(func() {
   481  								server = NewServer()
   482  								// Suppresses ginkgo server logs
   483  								server.HTTPTestServer.Config.ErrorLog = log.New(&bytes.Buffer{}, "", 0)
   484  								server.AppendHandlers(
   485  									CombineHandlers(
   486  										VerifyRequest(http.MethodGet, "/"),
   487  										RespondWith(http.StatusNotFound, nil),
   488  									),
   489  								)
   490  								buildpackPath = server.URL()
   491  							})
   492  
   493  							AfterEach(func() {
   494  								server.Close()
   495  							})
   496  
   497  							It("displays an appropriate error", func() {
   498  								Eventually(session.Err).Should(Say("Download attempt failed; server returned 404 Not Found"))
   499  								Eventually(session.Err).Should(Say(`Unable to install; buildpack is not available from the given URL\.`))
   500  								Eventually(session).Should(Say("FAILED"))
   501  								Eventually(session).Should(Exit(1))
   502  							})
   503  						})
   504  
   505  						When("specifying an invalid URL", func() {
   506  							BeforeEach(func() {
   507  								buildpackPath = "http://not-a-real-url"
   508  							})
   509  
   510  							It("returns the appropriate error", func() {
   511  								Eventually(session.Err).Should(Say("Get %s: dial tcp: lookup", buildpackPath))
   512  								Eventually(session).Should(Say("FAILED"))
   513  								Eventually(session).Should(Exit(1))
   514  							})
   515  						})
   516  					})
   517  				})
   518  
   519  				When("the -i flag is provided", func() {
   520  					var (
   521  						buildpackPosition string
   522  						session           *Session
   523  					)
   524  
   525  					JustBeforeEach(func() {
   526  						session = helpers.CF("update-buildpack", buildpackName, "-i", buildpackPosition)
   527  					})
   528  
   529  					When("position is a negative integer", func() {
   530  						BeforeEach(func() {
   531  							buildpackPosition = "-3"
   532  						})
   533  
   534  						It("successfully uploads buildpack as the first position", func() {
   535  							Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   536  							Eventually(session).Should(Say("OK"))
   537  							Eventually(session).Should(Exit(0))
   538  
   539  							listSession := helpers.CF("buildpacks")
   540  							Eventually(listSession).Should(Say(`%s\s+1\s`, buildpackName))
   541  							Eventually(listSession).Should(Exit(0))
   542  						})
   543  					})
   544  
   545  					When("position is positive integer", func() {
   546  						BeforeEach(func() {
   547  							buildpackPosition = "3"
   548  						})
   549  
   550  						It("successfully uploads buildpack in the provided position", func() {
   551  							Eventually(session).Should(Exit(0))
   552  
   553  							listSession := helpers.CF("buildpacks")
   554  							Eventually(listSession).Should(Say(`%s\s+3\s`, buildpackName))
   555  							Eventually(listSession).Should(Exit(0))
   556  						})
   557  					})
   558  				})
   559  
   560  				When("the --assign-stack flag is provided", func() {
   561  					var (
   562  						stacks []string
   563  					)
   564  
   565  					When("the user assigns a stack that exists on the system", func() {
   566  						BeforeEach(func() {
   567  							stacks = helpers.EnsureMinimumNumberOfStacks(2)
   568  						})
   569  
   570  						It("successfully assigns the stack to the buildpack", func() {
   571  							session := helpers.CF("update-buildpack", buildpackName, "--assign-stack", stacks[0])
   572  
   573  							Eventually(session).Should(Say("Assigning stack %s to %s as %s...", stacks[0], buildpackName, username))
   574  							Eventually(session).Should(Say("OK"))
   575  							Eventually(session).Should(Exit(0))
   576  
   577  							listSession := helpers.CF("buildpacks")
   578  							Eventually(listSession).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   579  								Name: buildpackName, Stack: stacks[0]})))
   580  							Eventually(listSession).Should(Exit(0))
   581  						})
   582  
   583  						When("the buildpack already has a stack associated to it", func() {
   584  							BeforeEach(func() {
   585  								assignStackSession := helpers.CF("update-buildpack", buildpackName, "--assign-stack", stacks[0])
   586  								Eventually(assignStackSession).Should(Exit(0))
   587  							})
   588  
   589  							It("displays an error that the buildpack already has a stack association", func() {
   590  								session := helpers.CF("update-buildpack", buildpackName, "--assign-stack", stacks[1])
   591  								Eventually(session.Err).Should(Say("Buildpack %s already exists with a stack association", buildpackName))
   592  								Eventually(session).Should(Say("FAILED"))
   593  								Eventually(session).Should(Exit(1))
   594  							})
   595  						})
   596  					})
   597  
   598  					When("the user assigns a stack that does NOT exist on the system", func() {
   599  						It("displays an error that the stack isn't found", func() {
   600  							session := helpers.CF("update-buildpack", buildpackName, "--assign-stack", "nonexistent-stack")
   601  							Eventually(session.Err).Should(Say("Stack 'nonexistent-stack' not found"))
   602  							Eventually(session).Should(Say("FAILED"))
   603  							Eventually(session).Should(Exit(1))
   604  						})
   605  					})
   606  				})
   607  
   608  				When("the --lock is provided", func() {
   609  					It("locks the buildpack", func() {
   610  						session := helpers.CF("update-buildpack", buildpackName, "--lock")
   611  						Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   612  						Eventually(session).Should(Say("OK"))
   613  						Eventually(session).Should(Exit(0))
   614  
   615  						session = helpers.CF("buildpacks")
   616  						Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{
   617  							Name:   buildpackName,
   618  							Locked: "true",
   619  						})))
   620  						Eventually(session).Should(Exit(0))
   621  					})
   622  				})
   623  
   624  				When("the --disable is provided", func() {
   625  					It("disables buildpack", func() {
   626  						session := helpers.CF("update-buildpack", buildpackName, "--disable")
   627  						Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   628  						Eventually(session).Should(Say("OK"))
   629  						Eventually(session).Should(Exit(0))
   630  
   631  						session = helpers.CF("buildpacks")
   632  						Eventually(session).Should(Say(`%s\s+\d+\s+false`, buildpackName))
   633  						Eventually(session).Should(Exit(0))
   634  					})
   635  				})
   636  
   637  				Describe("flag combinations", func() {
   638  					When("specifying both enable and disable flags", func() {
   639  						It("returns the appropriate error", func() {
   640  							session := helpers.CF("update-buildpack", buildpackName, "--enable", "--disable")
   641  							Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: --enable, --disable"))
   642  							Eventually(session).Should(Say("FAILED"))
   643  							Eventually(session).Should(Exit(1))
   644  						})
   645  					})
   646  
   647  					When("specifying both lock and unlock flags", func() {
   648  						It("returns the appropriate error", func() {
   649  							session := helpers.CF("update-buildpack", buildpackName, "--lock", "--unlock")
   650  							Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: --lock, --unlock"))
   651  							Eventually(session).Should(Say("FAILED"))
   652  							Eventually(session).Should(Exit(1))
   653  						})
   654  					})
   655  
   656  					When("specifying --lock and -p", func() {
   657  						It("returns the an error saying that those flags cannot be used together", func() {
   658  							session := helpers.CF("update-buildpack", buildpackName, "--lock", "-p", "http://google.com")
   659  							Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -p, --lock"))
   660  							Eventually(session).Should(Say("FAILED"))
   661  							Eventually(session).Should(Exit(1))
   662  						})
   663  					})
   664  
   665  					When("specifying --unlock and -p", func() {
   666  						It("returns the an error saying that those flags cannot be used together", func() {
   667  							session := helpers.CF("update-buildpack", buildpackName, "--unlock", "-p", "http://google.com")
   668  							Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -p, --unlock"))
   669  							Eventually(session).Should(Say("FAILED"))
   670  							Eventually(session).Should(Exit(1))
   671  						})
   672  					})
   673  
   674  					When("specifying -s and --assign-stack", func() {
   675  						It("returns the an error saying that those flags cannot be used together", func() {
   676  							session := helpers.CF("update-buildpack", buildpackName, "-s", "old-stack", "--assign-stack", "some-new-stack")
   677  							Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -s, --assign-stack"))
   678  							Eventually(session).Should(Say("FAILED"))
   679  							Eventually(session).Should(Exit(1))
   680  						})
   681  					})
   682  
   683  					When("specifying -p and --assign-stack", func() {
   684  						It("returns the an error saying that those flags cannot be used together", func() {
   685  							session := helpers.CF("update-buildpack", buildpackName, "-p", "http://google.com", "--assign-stack", "some-new-stack")
   686  							Eventually(session.Err).Should(Say("Incorrect Usage: The following arguments cannot be used together: -p, --assign-stack"))
   687  							Eventually(session).Should(Say("FAILED"))
   688  							Eventually(session).Should(Exit(1))
   689  						})
   690  					})
   691  
   692  					When("specifying -i and --assign-stack", func() {
   693  						It("displays text that the stack is being assigned and the buildpack is being updated", func() {
   694  							stacks := helpers.EnsureMinimumNumberOfStacks(1)
   695  							newStack := stacks[0]
   696  							session := helpers.CF("update-buildpack", buildpackName, "-i", "99", "--assign-stack", newStack)
   697  							Eventually(session).Should(Say("Assigning stack %s to %s as %s...", newStack, buildpackName, username))
   698  							Eventually(session).Should(Say("Updating buildpack %s with stack %s...", buildpackName, newStack))
   699  							Eventually(session).Should(Say("OK"))
   700  							Eventually(session).Should(Exit(0))
   701  						})
   702  					})
   703  				})
   704  			})
   705  
   706  			When("the buildpack exists and is disabled", func() {
   707  				BeforeEach(func() {
   708  					helpers.BuildpackWithoutStack(func(buildpackPath string) {
   709  						session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1", "--disable")
   710  						Eventually(session).Should(Exit(0))
   711  					})
   712  				})
   713  
   714  				When("specifying enable flag", func() {
   715  					It("enables buildpack", func() {
   716  						session := helpers.CF("update-buildpack", buildpackName, "--enable")
   717  						Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   718  						Eventually(session).Should(Say("OK"))
   719  						Eventually(session).Should(Exit(0))
   720  
   721  						session = helpers.CF("buildpacks")
   722  						Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{Name: buildpackName})))
   723  						Eventually(session).Should(Exit(0))
   724  					})
   725  				})
   726  			})
   727  
   728  			When("the buildpack exists and is locked", func() {
   729  				var buildpackURL string
   730  
   731  				BeforeEach(func() {
   732  					helpers.BuildpackWithoutStack(func(buildpackPath string) {
   733  						session := helpers.CF("create-buildpack", buildpackName, buildpackPath, "1")
   734  						Eventually(session).Should(Exit(0))
   735  						session = helpers.CF("update-buildpack", buildpackName, "--lock")
   736  						Eventually(session).Should(Exit(0))
   737  					})
   738  					buildpackURL = "https://github.com/cloudfoundry/binary-buildpack/releases/download/v1.0.21/binary-buildpack-v1.0.21.zip"
   739  				})
   740  
   741  				Context("specifying -p argument", func() {
   742  					It("fails to update buildpack", func() {
   743  						session := helpers.CF("update-buildpack", buildpackName, "-p", buildpackURL)
   744  						Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   745  						Eventually(session).Should(Say("FAILED"))
   746  						Eventually(session.Err).Should(Say("The buildpack is locked"))
   747  						Eventually(session).Should(Exit(1))
   748  					})
   749  				})
   750  
   751  				Context("specifying unlock flag", func() {
   752  					It("unlocks the buildpack", func() {
   753  						session := helpers.CF("update-buildpack", buildpackName, "--unlock")
   754  						Eventually(session).Should(Say("Updating buildpack %s as %s...", buildpackName, username))
   755  						Eventually(session).Should(Say("OK"))
   756  						Eventually(session).Should(Exit(0))
   757  
   758  						session = helpers.CF("buildpacks")
   759  						Eventually(session).Should(Say(helpers.BuildpacksOutputRegex(helpers.BuildpackFields{Name: buildpackName})))
   760  						Eventually(session).Should(Exit(0))
   761  					})
   762  				})
   763  			})
   764  		})
   765  	})
   766  })