github.com/mook-as/cf-cli@v7.0.0-beta.28.0.20200120190804-b91c115fae48+incompatible/command/v7/update_buildpack_command_test.go (about)

     1  package v7_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"code.cloudfoundry.org/cli/actor/v7action"
     7  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccerror"
     8  	"code.cloudfoundry.org/cli/command/v7/v7fakes"
     9  	"code.cloudfoundry.org/cli/types"
    10  
    11  	"code.cloudfoundry.org/cli/command/translatableerror"
    12  
    13  	"code.cloudfoundry.org/cli/actor/actionerror"
    14  	"code.cloudfoundry.org/cli/command/commandfakes"
    15  	"code.cloudfoundry.org/cli/command/flag"
    16  	. "code.cloudfoundry.org/cli/command/v7"
    17  	"code.cloudfoundry.org/cli/util/configv3"
    18  	"code.cloudfoundry.org/cli/util/ui"
    19  	. "github.com/onsi/ginkgo"
    20  	. "github.com/onsi/gomega"
    21  	. "github.com/onsi/gomega/gbytes"
    22  )
    23  
    24  var _ = Describe("UpdateBuildpackCommand", func() {
    25  	var (
    26  		cmd             UpdateBuildpackCommand
    27  		fakeSharedActor *commandfakes.FakeSharedActor
    28  		testUI          *ui.UI
    29  		input           *Buffer
    30  		fakeActor       *v7fakes.FakeUpdateBuildpackActor
    31  		fakeConfig      *commandfakes.FakeConfig
    32  		buildpackGUID   = "buildpack-guid"
    33  		buildpackName   = "some-bp"
    34  		binaryName      = "faceman"
    35  
    36  		executeErr  error
    37  		expectedErr error
    38  	)
    39  
    40  	BeforeEach(func() {
    41  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    42  		input = NewBuffer()
    43  		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
    44  		fakeActor = new(v7fakes.FakeUpdateBuildpackActor)
    45  		fakeConfig = new(commandfakes.FakeConfig)
    46  		buildpackGUID = "some guid"
    47  
    48  		cmd = UpdateBuildpackCommand{
    49  			RequiredArgs: flag.BuildpackName{Buildpack: buildpackName},
    50  			UI:           testUI,
    51  			SharedActor:  fakeSharedActor,
    52  			Actor:        fakeActor,
    53  			Config:       fakeConfig,
    54  		}
    55  	})
    56  
    57  	JustBeforeEach(func() {
    58  		executeErr = cmd.Execute(nil)
    59  	})
    60  
    61  	Describe("invalid flag combinations", func() {
    62  		When("the --lock and --unlock flags are provided", func() {
    63  			BeforeEach(func() {
    64  				cmd.Lock = true
    65  				cmd.Unlock = true
    66  			})
    67  
    68  			It("returns an ArgumentCombinationError", func() {
    69  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
    70  					Args: []string{"--lock", "--unlock"},
    71  				}))
    72  			})
    73  		})
    74  
    75  		When("the --enable and --disable flags are provided", func() {
    76  			BeforeEach(func() {
    77  				cmd.Enable = true
    78  				cmd.Disable = true
    79  			})
    80  
    81  			It("returns an ArgumentCombinationError", func() {
    82  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
    83  					Args: []string{"--enable", "--disable"},
    84  				}))
    85  			})
    86  		})
    87  
    88  		When("the --path and --lock flags are provided", func() {
    89  			BeforeEach(func() {
    90  				cmd.Lock = true
    91  				cmd.Path = "asdf"
    92  			})
    93  
    94  			It("returns an ArgumentCombinationError", func() {
    95  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
    96  					Args: []string{"--path", "--lock"},
    97  				}))
    98  			})
    99  		})
   100  
   101  		When("the --path and --assign-stack flags are provided", func() {
   102  			BeforeEach(func() {
   103  				cmd.Path = "asdf"
   104  				cmd.NewStack = "some-new-stack"
   105  			})
   106  
   107  			It("returns an ArgumentCombinationError", func() {
   108  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
   109  					Args: []string{"--path", "--assign-stack"},
   110  				}))
   111  			})
   112  		})
   113  
   114  		When("the --stack and --assign-stack flags are provided", func() {
   115  			BeforeEach(func() {
   116  				cmd.CurrentStack = "current-stack"
   117  				cmd.NewStack = "some-new-stack"
   118  			})
   119  
   120  			It("returns an ArgumentCombinationError", func() {
   121  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
   122  					Args: []string{"--stack", "--assign-stack"},
   123  				}))
   124  			})
   125  		})
   126  	})
   127  
   128  	When("the environment is not set up correctly", func() {
   129  		BeforeEach(func() {
   130  			fakeSharedActor.CheckTargetReturns(actionerror.NotLoggedInError{BinaryName: binaryName})
   131  		})
   132  
   133  		It("returns an error", func() {
   134  			Expect(executeErr).To(MatchError(actionerror.NotLoggedInError{BinaryName: binaryName}))
   135  
   136  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
   137  			checkTargetedOrg, checkTargetedSpace := fakeSharedActor.CheckTargetArgsForCall(0)
   138  			Expect(checkTargetedOrg).To(BeFalse())
   139  			Expect(checkTargetedSpace).To(BeFalse())
   140  		})
   141  	})
   142  
   143  	When("the environment is setup correctly", func() {
   144  		When("getting the current user fails", func() {
   145  			BeforeEach(func() {
   146  				expectedErr = errors.New("some-error that happened")
   147  				fakeConfig.CurrentUserReturns(configv3.User{}, expectedErr)
   148  			})
   149  
   150  			It("returns the error", func() {
   151  				Expect(executeErr).To(MatchError(expectedErr))
   152  			})
   153  		})
   154  
   155  		When("getting the current user succeeds", func() {
   156  			var userName string
   157  
   158  			BeforeEach(func() {
   159  				userName = "some-user"
   160  				fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil)
   161  			})
   162  
   163  			When("preparing buildpack bits causes an error", func() {
   164  				var emptyDirectoryError error
   165  				BeforeEach(func() {
   166  					emptyDirectoryError = actionerror.EmptyBuildpackDirectoryError{Path: "some-directory"}
   167  					fakeActor.PrepareBuildpackBitsReturns("", emptyDirectoryError)
   168  					cmd.Path = "some empty directory"
   169  				})
   170  
   171  				It("exits without updating if the path points to an empty directory", func() {
   172  					Expect(executeErr).To(MatchError(emptyDirectoryError))
   173  					Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(0))
   174  				})
   175  			})
   176  
   177  			When("updating the buildpack fails", func() {
   178  				BeforeEach(func() {
   179  					cmd.Path = "path/to/buildpack"
   180  					fakeActor.PrepareBuildpackBitsReturns("path/to/prepared/bits", nil)
   181  					expectedErr = errors.New("update-error")
   182  					fakeActor.UpdateBuildpackByNameAndStackReturns(
   183  						v7action.Buildpack{},
   184  						v7action.Warnings{"update-bp-warning1", "update-bp-warning2"},
   185  						expectedErr,
   186  					)
   187  				})
   188  
   189  				It("returns the error and prints any warnings", func() {
   190  					Expect(testUI.Err).To(Say("update-bp-warning1"))
   191  					Expect(testUI.Err).To(Say("update-bp-warning2"))
   192  					Expect(executeErr).To(MatchError(expectedErr))
   193  					Expect(fakeActor.UploadBuildpackCallCount()).To(Equal(0))
   194  				})
   195  			})
   196  
   197  			When("the --lock flag is provided", func() {
   198  				BeforeEach(func() {
   199  					cmd.Lock = true
   200  				})
   201  
   202  				It("sets the locked value to true when updating the buildpack", func() {
   203  					Expect(executeErr).ToNot(HaveOccurred())
   204  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   205  					Expect(buildpack.Locked.IsSet).To(Equal(true))
   206  					Expect(buildpack.Locked.Value).To(Equal(true))
   207  				})
   208  			})
   209  
   210  			When("the --unlock flag is provided", func() {
   211  				BeforeEach(func() {
   212  					cmd.Unlock = true
   213  				})
   214  
   215  				It("sets the locked value to false when updating the buildpack", func() {
   216  					Expect(executeErr).ToNot(HaveOccurred())
   217  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   218  					Expect(buildpack.Locked.IsSet).To(Equal(true))
   219  					Expect(buildpack.Locked.Value).To(Equal(false))
   220  				})
   221  			})
   222  
   223  			When("the --enable flag is provided", func() {
   224  				BeforeEach(func() {
   225  					cmd.Enable = true
   226  				})
   227  
   228  				It("sets the enabled value to true when updating the buildpack", func() {
   229  					Expect(executeErr).ToNot(HaveOccurred())
   230  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   231  					Expect(buildpack.Enabled.IsSet).To(Equal(true))
   232  					Expect(buildpack.Enabled.Value).To(Equal(true))
   233  				})
   234  			})
   235  
   236  			When("the --disable flag is provided", func() {
   237  				BeforeEach(func() {
   238  					cmd.Disable = true
   239  				})
   240  
   241  				It("sets the enabled value to false when updating the buildpack", func() {
   242  					Expect(executeErr).ToNot(HaveOccurred())
   243  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   244  					Expect(buildpack.Enabled.IsSet).To(Equal(true))
   245  					Expect(buildpack.Enabled.Value).To(Equal(false))
   246  				})
   247  			})
   248  
   249  			When("the --index flag is provided", func() {
   250  				BeforeEach(func() {
   251  					cmd.Position = types.NullInt{IsSet: true, Value: 99}
   252  				})
   253  
   254  				It("sets the new buildpack order when updating the buildpack", func() {
   255  					Expect(executeErr).ToNot(HaveOccurred())
   256  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   257  					Expect(buildpack.Position.IsSet).To(Equal(true))
   258  					Expect(buildpack.Position.Value).To(Equal(99))
   259  				})
   260  			})
   261  
   262  			When("the --assign-stack flag is provided", func() {
   263  				BeforeEach(func() {
   264  					cmd.NewStack = "some-new-stack"
   265  				})
   266  
   267  				It("sets the new stack on the buildpack", func() {
   268  					Expect(executeErr).ToNot(HaveOccurred())
   269  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   270  					Expect(testUI.Out).ToNot(Say("Updating buildpack %s", buildpackName))
   271  					Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, buildpackName, userName))
   272  					Expect(buildpack.Stack).To(Equal("some-new-stack"))
   273  				})
   274  
   275  				Context("and the --index flag is provided", func() {
   276  					BeforeEach(func() {
   277  						cmd.Position = types.NullInt{IsSet: true, Value: 3}
   278  					})
   279  
   280  					It("sets the new stack and updates the priority of the buildpack", func() {
   281  						Expect(executeErr).ToNot(HaveOccurred())
   282  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, buildpackName, userName))
   283  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", buildpackName, cmd.NewStack))
   284  						Expect(testUI.Out).To(Say("OK"))
   285  					})
   286  				})
   287  
   288  				Context("and the --lock flag is provided", func() {
   289  					BeforeEach(func() {
   290  						cmd.Lock = true
   291  					})
   292  
   293  					It("sets the new stack and locks the buildpack", func() {
   294  						Expect(executeErr).ToNot(HaveOccurred())
   295  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, buildpackName, userName))
   296  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", buildpackName, cmd.NewStack))
   297  						Expect(testUI.Out).To(Say("OK"))
   298  					})
   299  				})
   300  
   301  				Context("and the --unlock flag is provided", func() {
   302  					BeforeEach(func() {
   303  						cmd.Unlock = true
   304  					})
   305  
   306  					It("sets the new stack and unlocks the buildpack", func() {
   307  						Expect(executeErr).ToNot(HaveOccurred())
   308  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, buildpackName, userName))
   309  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", buildpackName, cmd.NewStack))
   310  						Expect(testUI.Out).To(Say("OK"))
   311  					})
   312  				})
   313  
   314  				Context("and the --enable flag is provided", func() {
   315  					BeforeEach(func() {
   316  						cmd.Enable = true
   317  					})
   318  
   319  					It("sets the new stack and enables the buildpack", func() {
   320  						Expect(executeErr).ToNot(HaveOccurred())
   321  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, buildpackName, userName))
   322  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", buildpackName, cmd.NewStack))
   323  						Expect(testUI.Out).To(Say("OK"))
   324  					})
   325  				})
   326  
   327  				Context("and the --disable flag is provided", func() {
   328  					BeforeEach(func() {
   329  						cmd.Disable = true
   330  					})
   331  
   332  					It("sets the new stack and disables the buildpack", func() {
   333  						Expect(executeErr).ToNot(HaveOccurred())
   334  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, buildpackName, userName))
   335  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", buildpackName, cmd.NewStack))
   336  						Expect(testUI.Out).To(Say("OK"))
   337  					})
   338  				})
   339  
   340  			})
   341  
   342  			When("the --rename flag is provided", func() {
   343  				BeforeEach(func() {
   344  					cmd.NewName = "new-buildpack-name"
   345  				})
   346  
   347  				It("sets the new name on the buildpack", func() {
   348  					Expect(executeErr).ToNot(HaveOccurred())
   349  					_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   350  					Expect(buildpack.Name).To(Equal("new-buildpack-name"))
   351  
   352  					Expect(testUI.Out).ToNot(Say("Updating buildpack %s", buildpackName))
   353  					Expect(testUI.Out).To(Say(
   354  						"Renaming buildpack %s to %s as %s...", buildpackName, cmd.NewName, userName))
   355  					Expect(testUI.Out).To(Say("OK"))
   356  				})
   357  
   358  				Context("and the --assign-stack flag is provided", func() {
   359  					BeforeEach(func() {
   360  						cmd.NewStack = "new-stack"
   361  					})
   362  
   363  					It("sets the new name/stack on the buildpack and refers to the new name going forward", func() {
   364  						Expect(executeErr).ToNot(HaveOccurred())
   365  						_, _, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   366  						Expect(buildpack.Name).To(Equal("new-buildpack-name"))
   367  						Expect(buildpack.Stack).To(Equal("new-stack"))
   368  
   369  						Expect(testUI.Out).To(Say(
   370  							"Renaming buildpack %s to %s as %s...", buildpackName, cmd.NewName, userName))
   371  
   372  						Expect(testUI.Out).To(Say(
   373  							"Assigning stack %s to %s as %s", cmd.NewStack, cmd.NewName, userName))
   374  
   375  						Expect(testUI.Out).ToNot(Say("Updating buildpack %s", buildpackName))
   376  
   377  						Expect(testUI.Out).To(Say("OK"))
   378  					})
   379  				})
   380  			})
   381  
   382  			When("updating the buildpack succeeds", func() {
   383  				BeforeEach(func() {
   384  					fakeActor.UpdateBuildpackByNameAndStackReturns(
   385  						v7action.Buildpack{GUID: buildpackGUID},
   386  						v7action.Warnings{"update-bp-warning1", "update-bp-warning2"},
   387  						nil,
   388  					)
   389  				})
   390  
   391  				When("no arguments are specified", func() {
   392  					It("makes the actor call to update the buildpack", func() {
   393  						Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(1))
   394  						_, newStack, buildpack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   395  						Expect(buildpack.Name).To(Equal(""))
   396  						Expect(buildpack.Stack).To(Equal(""))
   397  						Expect(buildpack.Position.IsSet).To(BeFalse())
   398  						Expect(buildpack.Locked.IsSet).To(BeFalse())
   399  						Expect(buildpack.Enabled.IsSet).To(BeFalse())
   400  						Expect(newStack).To(Equal(""))
   401  
   402  						Expect(testUI.Err).To(Say("update-bp-warning1"))
   403  						Expect(testUI.Err).To(Say("update-bp-warning2"))
   404  						Expect(testUI.Out).To(Say("Updating buildpack %s as %s...", buildpackName, userName))
   405  						Expect(testUI.Out).To(Say("OK"))
   406  					})
   407  				})
   408  
   409  				When("a path is specified", func() {
   410  					BeforeEach(func() {
   411  						cmd.Path = "some path"
   412  					})
   413  
   414  					It("makes the call to update the buildpack", func() {
   415  						Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(1))
   416  						buildpackNameArg, _, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   417  						Expect(buildpackNameArg).To(Equal(buildpackName))
   418  
   419  						Expect(testUI.Err).To(Say("update-bp-warning1"))
   420  						Expect(testUI.Err).To(Say("update-bp-warning2"))
   421  						Expect(testUI.Out).To(Say("Updating buildpack %s as %s...", buildpackName, userName))
   422  						Expect(testUI.Out).To(Say("OK"))
   423  					})
   424  
   425  					When("preparing the bits succeeds", func() {
   426  						buildpackBitsPath := "some path on the file system"
   427  						BeforeEach(func() {
   428  							fakeActor.PrepareBuildpackBitsReturns(buildpackBitsPath, nil)
   429  						})
   430  
   431  						It("uploads the new buildpack bits", func() {
   432  							Expect(testUI.Out).To(Say("Uploading buildpack some-bp as some-user..."))
   433  							Expect(fakeActor.UploadBuildpackCallCount()).To(Equal(1))
   434  							buildpackGUIDUsed, pathUsed, _ := fakeActor.UploadBuildpackArgsForCall(0)
   435  							Expect(buildpackGUIDUsed).To(Equal(buildpackGUID))
   436  							Expect(pathUsed).To(Equal(buildpackBitsPath))
   437  						})
   438  
   439  						When("uploading the buildpack fails", func() {
   440  
   441  							When("the client returns invalid auth token", func() {
   442  								BeforeEach(func() {
   443  									fakeActor.UploadBuildpackReturns("", v7action.Warnings{"some-create-bp-with-auth-warning"}, ccerror.InvalidAuthTokenError{Message: "token expired"})
   444  								})
   445  
   446  								It("alerts the user and retries the upload", func() {
   447  									Expect(testUI.Err).To(Say("Failed to upload buildpack due to auth token expiration, retrying..."))
   448  									Expect(fakeActor.UploadBuildpackCallCount()).To(Equal(2))
   449  								})
   450  							})
   451  
   452  							When("a non token error occurs", func() {
   453  								BeforeEach(func() {
   454  									expectedErr = errors.New("upload error")
   455  									fakeActor.UploadBuildpackReturns("", v7action.Warnings{"upload-warning1", "upload-warning2"}, expectedErr)
   456  								})
   457  
   458  								It("returns all warnings and an error", func() {
   459  									Expect(testUI.Err).To(Say("update-bp-warning1"))
   460  									Expect(testUI.Err).To(Say("update-bp-warning2"))
   461  									Expect(testUI.Err).To(Say("upload-warning1"))
   462  									Expect(testUI.Err).To(Say("upload-warning2"))
   463  									Expect(executeErr).To(MatchError(expectedErr))
   464  								})
   465  							})
   466  						})
   467  
   468  						When("uploading the buildpack succeeds", func() {
   469  							BeforeEach(func() {
   470  								fakeActor.UploadBuildpackReturns(
   471  									"example.com/job/url/",
   472  									v7action.Warnings{"upload-warning1", "upload-warning2"},
   473  									nil,
   474  								)
   475  							})
   476  
   477  							When("polling the buildpack job fails", func() {
   478  								BeforeEach(func() {
   479  									expectedErr = ccerror.JobTimeoutError{JobGUID: "job-guid"}
   480  									fakeActor.PollUploadBuildpackJobReturns(
   481  										v7action.Warnings{"poll-warning1", "poll-warning2"},
   482  										expectedErr,
   483  									)
   484  								})
   485  
   486  								It("returns all warnings and an error", func() {
   487  									Expect(testUI.Err).To(Say("update-bp-warning1"))
   488  									Expect(testUI.Err).To(Say("update-bp-warning2"))
   489  									Expect(testUI.Err).To(Say("poll-warning1"))
   490  									Expect(testUI.Err).To(Say("poll-warning2"))
   491  									Expect(executeErr).To(MatchError(expectedErr))
   492  								})
   493  							})
   494  
   495  							When("polling the buildpack job succeeds", func() {
   496  								BeforeEach(func() {
   497  									fakeActor.PollUploadBuildpackJobReturns(
   498  										v7action.Warnings{"poll-warning1", "poll-warning2"},
   499  										nil,
   500  									)
   501  								})
   502  
   503  								It("displays success test and any warnings", func() {
   504  									Expect(testUI.Out).To(Say(`Uploading buildpack %s`, buildpackName))
   505  									Expect(testUI.Err).To(Say("upload-warning1"))
   506  									Expect(testUI.Err).To(Say("upload-warning2"))
   507  									Expect(testUI.Out).To(Say("OK"))
   508  
   509  									Expect(testUI.Out).To(Say(`Processing uploaded buildpack %s\.\.\.`, buildpackName))
   510  									Expect(testUI.Err).To(Say("poll-warning1"))
   511  									Expect(testUI.Err).To(Say("poll-warning2"))
   512  									Expect(testUI.Out).To(Say("OK"))
   513  								})
   514  							})
   515  						})
   516  					})
   517  				})
   518  			})
   519  		})
   520  	})
   521  })