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