github.com/jenspinney/cli@v6.42.1-0.20190207184520-7450c600020e+incompatible/command/v6/update_buildpack_command_test.go (about)

     1  package v6_test
     2  
     3  import (
     4  	"errors"
     5  
     6  	"code.cloudfoundry.org/cli/command/translatableerror"
     7  
     8  	"code.cloudfoundry.org/cli/api/cloudcontroller/ccversion"
     9  
    10  	"code.cloudfoundry.org/cli/actor/actionerror"
    11  	"code.cloudfoundry.org/cli/actor/v2action"
    12  	"code.cloudfoundry.org/cli/command/commandfakes"
    13  	"code.cloudfoundry.org/cli/command/flag"
    14  	. "code.cloudfoundry.org/cli/command/v6"
    15  	"code.cloudfoundry.org/cli/command/v6/v6fakes"
    16  	"code.cloudfoundry.org/cli/types"
    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       *v6fakes.FakeUpdateBuildpackActor
    31  		fakeConfig      *commandfakes.FakeConfig
    32  		args            flag.BuildpackName
    33  		buildpackGUID   string
    34  
    35  		executeErr  error
    36  		expectedErr error
    37  	)
    38  
    39  	BeforeEach(func() {
    40  		fakeSharedActor = new(commandfakes.FakeSharedActor)
    41  		input = NewBuffer()
    42  		testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer())
    43  		fakeActor = new(v6fakes.FakeUpdateBuildpackActor)
    44  		fakeConfig = new(commandfakes.FakeConfig)
    45  		args.Buildpack = "some-bp"
    46  		buildpackGUID = "some guid"
    47  
    48  		cmd = UpdateBuildpackCommand{
    49  			RequiredArgs: args,
    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 -p and --lock flags are provided", func() {
    76  			BeforeEach(func() {
    77  				cmd.Lock = true
    78  				cmd.Path = "asdf"
    79  			})
    80  
    81  			It("returns an ArgumentCombinationError", func() {
    82  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
    83  					Args: []string{"-p", "--lock"},
    84  				}))
    85  			})
    86  		})
    87  
    88  		When("the -p and --unlock flags are provided", func() {
    89  			BeforeEach(func() {
    90  				cmd.Path = "asdf"
    91  				cmd.Unlock = true
    92  			})
    93  
    94  			It("returns an ArgumentCombinationError", func() {
    95  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
    96  					Args: []string{"-p", "--unlock"},
    97  				}))
    98  			})
    99  		})
   100  
   101  		When("the -p 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{"-p", "--assign-stack"},
   110  				}))
   111  			})
   112  		})
   113  
   114  		When("the -s 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{"-s", "--assign-stack"},
   123  				}))
   124  			})
   125  		})
   126  
   127  		When("the --enable and --disable flags are provided", func() {
   128  			BeforeEach(func() {
   129  				cmd.Enable = true
   130  				cmd.Disable = true
   131  			})
   132  
   133  			It("returns an ArgumentCombinationError", func() {
   134  				Expect(executeErr).To(MatchError(translatableerror.ArgumentCombinationError{
   135  					Args: []string{"--enable", "--disable"},
   136  				}))
   137  			})
   138  		})
   139  	})
   140  
   141  	When("an error is encountered checking if the environment is setup correctly", func() {
   142  		BeforeEach(func() {
   143  			expectedErr = actionerror.NotLoggedInError{BinaryName: "some name"}
   144  			fakeSharedActor.CheckTargetReturns(expectedErr)
   145  		})
   146  
   147  		It("returns an error", func() {
   148  			Expect(executeErr).To(MatchError(expectedErr))
   149  			Expect(fakeSharedActor.CheckTargetCallCount()).To(Equal(1))
   150  			checkTargetedOrgArg, checkTargetedSpaceArg := fakeSharedActor.CheckTargetArgsForCall(0)
   151  			Expect(checkTargetedOrgArg).To(BeFalse())
   152  			Expect(checkTargetedSpaceArg).To(BeFalse())
   153  		})
   154  	})
   155  
   156  	When("the environment is setup correctly", func() {
   157  		When("getting the current user fails", func() {
   158  			BeforeEach(func() {
   159  				expectedErr = errors.New("some-error that happened")
   160  				fakeConfig.CurrentUserReturns(configv3.User{}, expectedErr)
   161  			})
   162  
   163  			It("returns the error", func() {
   164  				Expect(executeErr).To(MatchError(expectedErr))
   165  			})
   166  		})
   167  
   168  		When("getting the current user succeeds", func() {
   169  			var userName string
   170  
   171  			BeforeEach(func() {
   172  				userName = "some-user"
   173  				fakeConfig.CurrentUserReturns(configv3.User{Name: userName}, nil)
   174  			})
   175  
   176  			When("the path specified is an empty directory", func() {
   177  				var emptyDirectoryError error
   178  				BeforeEach(func() {
   179  					emptyDirectoryError = actionerror.EmptyBuildpackDirectoryError{Path: "some-directory"}
   180  					fakeActor.PrepareBuildpackBitsReturns("", emptyDirectoryError)
   181  					cmd.Path = "some empty directory"
   182  				})
   183  
   184  				It("exits without updating if the path points to an empty directory", func() {
   185  					Expect(executeErr).To(MatchError(emptyDirectoryError))
   186  					Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(0))
   187  				})
   188  			})
   189  
   190  			When("updating the buildpack fails", func() {
   191  				BeforeEach(func() {
   192  					expectedErr = errors.New("update-error")
   193  					fakeActor.UpdateBuildpackByNameAndStackReturns(
   194  						"",
   195  						v2action.Warnings{"update-bp-warning1", "update-bp-warning2"},
   196  						expectedErr,
   197  					)
   198  				})
   199  
   200  				It("returns the error and prints any warnings", func() {
   201  					Expect(testUI.Err).To(Say("update-bp-warning1"))
   202  					Expect(testUI.Err).To(Say("update-bp-warning2"))
   203  					Expect(executeErr).To(MatchError(expectedErr))
   204  				})
   205  			})
   206  
   207  			When("the --lock flag is provided", func() {
   208  				BeforeEach(func() {
   209  					cmd.Lock = true
   210  				})
   211  
   212  				It("sets the locked value to true when updating the buildpack", func() {
   213  					Expect(executeErr).ToNot(HaveOccurred())
   214  					_, _, _, locked, _, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   215  					Expect(locked.IsSet).To(Equal(true))
   216  					Expect(locked.Value).To(Equal(true))
   217  				})
   218  			})
   219  
   220  			When("the --unlock flag is provided", func() {
   221  				BeforeEach(func() {
   222  					cmd.Unlock = true
   223  				})
   224  
   225  				It("sets the locked value to false when updating the buildpack", func() {
   226  					Expect(executeErr).ToNot(HaveOccurred())
   227  					_, _, _, locked, _, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   228  					Expect(locked.IsSet).To(Equal(true))
   229  					Expect(locked.Value).To(Equal(false))
   230  				})
   231  			})
   232  
   233  			When("the --enable flag is provided", func() {
   234  				BeforeEach(func() {
   235  					cmd.Enable = true
   236  				})
   237  
   238  				It("sets the enabled value to true when updating the buildpack", func() {
   239  					Expect(executeErr).ToNot(HaveOccurred())
   240  					_, _, _, _, enabled, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   241  					Expect(enabled.IsSet).To(Equal(true))
   242  					Expect(enabled.Value).To(Equal(true))
   243  				})
   244  			})
   245  
   246  			When("the --disable flag is provided", func() {
   247  				BeforeEach(func() {
   248  					cmd.Disable = true
   249  				})
   250  
   251  				It("sets the enabled value to false when updating the buildpack", func() {
   252  					Expect(executeErr).ToNot(HaveOccurred())
   253  					_, _, _, _, enabled, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   254  					Expect(enabled.IsSet).To(Equal(true))
   255  					Expect(enabled.Value).To(Equal(false))
   256  				})
   257  			})
   258  
   259  			When("the -i flag is provided", func() {
   260  				BeforeEach(func() {
   261  					cmd.Order = types.NullInt{IsSet: true, Value: 99}
   262  				})
   263  
   264  				It("sets the new buildpack order when updating the buildpack", func() {
   265  					Expect(executeErr).ToNot(HaveOccurred())
   266  					_, _, order, _, _, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   267  					Expect(order.IsSet).To(Equal(true))
   268  					Expect(order.Value).To(Equal(99))
   269  				})
   270  			})
   271  
   272  			When("the --assign-stack flag is provided", func() {
   273  				BeforeEach(func() {
   274  					cmd.NewStack = "some-new-stack"
   275  					fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionBuildpackStackAssociationV2)
   276  				})
   277  
   278  				It("sets the new stack on the buildpack", func() {
   279  					Expect(executeErr).ToNot(HaveOccurred())
   280  					_, _, _, _, _, newStack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   281  					Expect(testUI.Out).ToNot(Say("Updating buildpack %s", args.Buildpack))
   282  					Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, args.Buildpack, userName))
   283  					Expect(newStack).To(Equal("some-new-stack"))
   284  				})
   285  
   286  				Context("and the -i flag is provided", func() {
   287  					BeforeEach(func() {
   288  						cmd.Order = types.NullInt{IsSet: true, Value: 99}
   289  					})
   290  
   291  					It("sets the new stack and updates the priority of the buildpack", func() {
   292  						Expect(executeErr).ToNot(HaveOccurred())
   293  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, args.Buildpack, userName))
   294  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", args.Buildpack, cmd.NewStack))
   295  						Expect(testUI.Out).To(Say("OK"))
   296  					})
   297  				})
   298  
   299  				Context("and the --lock flag is provided", func() {
   300  					BeforeEach(func() {
   301  						cmd.Lock = true
   302  					})
   303  
   304  					It("sets the new stack and locks the buildpack", func() {
   305  						Expect(executeErr).ToNot(HaveOccurred())
   306  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, args.Buildpack, userName))
   307  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", args.Buildpack, cmd.NewStack))
   308  						Expect(testUI.Out).To(Say("OK"))
   309  					})
   310  				})
   311  
   312  				Context("and the --unlock flag is provided", func() {
   313  					BeforeEach(func() {
   314  						cmd.Unlock = true
   315  					})
   316  
   317  					It("sets the new stack and unlocks the buildpack", func() {
   318  						Expect(executeErr).ToNot(HaveOccurred())
   319  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, args.Buildpack, userName))
   320  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", args.Buildpack, cmd.NewStack))
   321  						Expect(testUI.Out).To(Say("OK"))
   322  					})
   323  				})
   324  
   325  				Context("and the --enable flag is provided", func() {
   326  					BeforeEach(func() {
   327  						cmd.Enable = true
   328  					})
   329  
   330  					It("sets the new stack and enables the buildpack", func() {
   331  						Expect(executeErr).ToNot(HaveOccurred())
   332  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, args.Buildpack, userName))
   333  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", args.Buildpack, cmd.NewStack))
   334  						Expect(testUI.Out).To(Say("OK"))
   335  					})
   336  				})
   337  
   338  				Context("and the --disable flag is provided", func() {
   339  					BeforeEach(func() {
   340  						cmd.Disable = true
   341  					})
   342  
   343  					It("sets the new stack and disables the buildpack", func() {
   344  						Expect(executeErr).ToNot(HaveOccurred())
   345  						Expect(testUI.Out).To(Say("Assigning stack %s to %s as %s...", cmd.NewStack, args.Buildpack, userName))
   346  						Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s...", args.Buildpack, cmd.NewStack))
   347  						Expect(testUI.Out).To(Say("OK"))
   348  					})
   349  				})
   350  			})
   351  
   352  			When("updating the buildpack succeeds", func() {
   353  				BeforeEach(func() {
   354  					fakeActor.UpdateBuildpackByNameAndStackReturns(
   355  						buildpackGUID,
   356  						v2action.Warnings{"update-bp-warning1", "update-bp-warning2"},
   357  						nil,
   358  					)
   359  				})
   360  
   361  				When("no arguments are specified", func() {
   362  					It("makes the actor call to update the buildpack", func() {
   363  						Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(1))
   364  						name, currentStack, order, locked, enabled, newStack := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   365  						Expect(name).To(Equal(args.Buildpack))
   366  						Expect(currentStack).To(Equal(""))
   367  						Expect(order.IsSet).To(BeFalse())
   368  						Expect(locked.IsSet).To(BeFalse())
   369  						Expect(enabled.IsSet).To(BeFalse())
   370  						Expect(newStack).To(Equal(""))
   371  
   372  						Expect(testUI.Err).To(Say("update-bp-warning1"))
   373  						Expect(testUI.Err).To(Say("update-bp-warning2"))
   374  						Expect(testUI.Out).To(Say("Updating buildpack %s as %s...", args.Buildpack, userName))
   375  						Expect(testUI.Out).To(Say("OK"))
   376  					})
   377  				})
   378  
   379  				When("a stack association is specified", func() {
   380  					BeforeEach(func() {
   381  						cmd.CurrentStack = "some-stack"
   382  					})
   383  
   384  					When("The API does not support stack associations", func() {
   385  						BeforeEach(func() {
   386  							fakeActor.CloudControllerAPIVersionReturns(ccversion.MinSupportedV2ClientVersion)
   387  						})
   388  
   389  						It("returns an error about not supporting the stack association flag", func() {
   390  							Expect(executeErr).To(MatchError(translatableerror.MinimumCFAPIVersionNotMetError{
   391  								Command:        "Option '-s'",
   392  								CurrentVersion: ccversion.MinSupportedV2ClientVersion,
   393  								MinimumVersion: ccversion.MinVersionBuildpackStackAssociationV2,
   394  							}))
   395  						})
   396  					})
   397  
   398  					When("the API supports stack associations", func() {
   399  						BeforeEach(func() {
   400  							fakeActor.CloudControllerAPIVersionReturns(ccversion.MinVersionBuildpackStackAssociationV2)
   401  						})
   402  
   403  						It("attempts to retrieve buildpack by name and stack", func() {
   404  							Expect(executeErr).ToNot(HaveOccurred())
   405  							Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(1))
   406  
   407  							Expect(testUI.Err).To(Say("update-bp-warning1"))
   408  							Expect(testUI.Err).To(Say("update-bp-warning2"))
   409  							Expect(testUI.Out).To(Say("Updating buildpack %s with stack %s as %s...", args.Buildpack, cmd.CurrentStack, userName))
   410  							Expect(testUI.Out).To(Say("OK"))
   411  						})
   412  					})
   413  				})
   414  
   415  				When("a path is specified", func() {
   416  					BeforeEach(func() {
   417  						cmd.Path = flag.PathWithExistenceCheckOrURL("some path")
   418  					})
   419  
   420  					It("makes the actor call to update the buildpack", func() {
   421  						Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(1))
   422  						name, _, _, _, _, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   423  						Expect(name).To(Equal(args.Buildpack))
   424  
   425  						Expect(testUI.Err).To(Say("update-bp-warning1"))
   426  						Expect(testUI.Err).To(Say("update-bp-warning2"))
   427  						Expect(testUI.Out).To(Say("Updating buildpack %s as %s...", args.Buildpack, userName))
   428  						Expect(testUI.Out).To(Say("OK"))
   429  					})
   430  
   431  					When("preparing the bits fails", func() {
   432  						BeforeEach(func() {
   433  							expectedErr = errors.New("prepare error")
   434  							fakeActor.PrepareBuildpackBitsReturns("", expectedErr)
   435  						})
   436  
   437  						It("returns an error", func() {
   438  							Expect(executeErr).To(MatchError(expectedErr))
   439  						})
   440  					})
   441  
   442  					When("preparing the bits succeeds", func() {
   443  						buildpackBitsPath := "some path on the file system"
   444  						BeforeEach(func() {
   445  							fakeActor.PrepareBuildpackBitsReturns(buildpackBitsPath, nil)
   446  						})
   447  
   448  						It("uploads the new buildpack bits", func() {
   449  							Expect(testUI.Out).To(Say("Uploading buildpack some-bp as some-user..."))
   450  							Expect(fakeActor.UploadBuildpackCallCount()).To(Equal(1))
   451  							buildpackGUIDUsed, pathUsed, _ := fakeActor.UploadBuildpackArgsForCall(0)
   452  							Expect(buildpackGUIDUsed).To(Equal(buildpackGUID))
   453  							Expect(pathUsed).To(Equal(buildpackBitsPath))
   454  						})
   455  
   456  						When("uploading the buildpack fails", func() {
   457  							BeforeEach(func() {
   458  								expectedErr = errors.New("upload error")
   459  								fakeActor.UploadBuildpackReturns(v2action.Warnings{"upload-warning1", "upload-warning2"}, expectedErr)
   460  							})
   461  
   462  							It("returns warnings and an error", func() {
   463  								Expect(testUI.Err).To(Say("upload-warning1"))
   464  								Expect(testUI.Err).To(Say("upload-warning2"))
   465  								Expect(executeErr).To(MatchError(expectedErr))
   466  							})
   467  						})
   468  
   469  						When("uploading the buildpack succeeds", func() {
   470  							BeforeEach(func() {
   471  								fakeActor.UploadBuildpackReturns(v2action.Warnings{"upload-warning1", "upload-warning2"}, nil)
   472  							})
   473  							It("displays success test and any warnings", func() {
   474  								Expect(testUI.Err).To(Say("upload-warning1"))
   475  								Expect(testUI.Err).To(Say("upload-warning2"))
   476  								Expect(testUI.Out).To(Say("OK"))
   477  							})
   478  						})
   479  					})
   480  				})
   481  
   482  				When("an order is specified", func() {
   483  					BeforeEach(func() {
   484  						cmd.Order = types.NullInt{Value: 3, IsSet: true}
   485  					})
   486  
   487  					It("makes the actor call to update the buildpack", func() {
   488  						Expect(fakeActor.UpdateBuildpackByNameAndStackCallCount()).To(Equal(1))
   489  						name, _, order, _, _, _ := fakeActor.UpdateBuildpackByNameAndStackArgsForCall(0)
   490  						Expect(name).To(Equal(args.Buildpack))
   491  						Expect(order.IsSet).To(BeTrue())
   492  						Expect(order.Value).To(Equal(3))
   493  
   494  						Expect(testUI.Err).To(Say("update-bp-warning1"))
   495  						Expect(testUI.Err).To(Say("update-bp-warning2"))
   496  						Expect(testUI.Out).To(Say("Updating buildpack %s as %s...", args.Buildpack, userName))
   497  						Expect(testUI.Out).To(Say("OK"))
   498  					})
   499  				})
   500  			})
   501  		})
   502  	})
   503  })