github.com/LukasHeimann/cloudfoundrycli/v8@v8.4.4/command/v7/update_buildpack_command_test.go (about)

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