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