github.com/jghiloni/cli@v6.28.1-0.20170628223758-0ce05fe032a2+incompatible/command/common/install_plugin_from_repo_command_test.go (about) 1 package common_test 2 3 import ( 4 "encoding/json" 5 "errors" 6 "fmt" 7 "math/rand" 8 "os" 9 "runtime" 10 "strconv" 11 12 "code.cloudfoundry.org/cli/actor/pluginaction" 13 "code.cloudfoundry.org/cli/api/plugin/pluginerror" 14 "code.cloudfoundry.org/cli/api/plugin/pluginfakes" 15 "code.cloudfoundry.org/cli/command/commandfakes" 16 . "code.cloudfoundry.org/cli/command/common" 17 "code.cloudfoundry.org/cli/command/common/commonfakes" 18 "code.cloudfoundry.org/cli/command/flag" 19 "code.cloudfoundry.org/cli/command/plugin/shared" 20 "code.cloudfoundry.org/cli/integration/helpers" 21 "code.cloudfoundry.org/cli/util/configv3" 22 "code.cloudfoundry.org/cli/util/ui" 23 . "github.com/onsi/ginkgo" 24 . "github.com/onsi/ginkgo/extensions/table" 25 . "github.com/onsi/gomega" 26 . "github.com/onsi/gomega/gbytes" 27 ) 28 29 var _ = Describe("install-plugin command", func() { 30 var ( 31 cmd InstallPluginCommand 32 testUI *ui.UI 33 input *Buffer 34 fakeConfig *commandfakes.FakeConfig 35 fakeActor *commonfakes.FakeInstallPluginActor 36 fakeProgressBar *pluginfakes.FakeProxyReader 37 executeErr error 38 expectedErr error 39 pluginHome string 40 binaryName string 41 ) 42 43 BeforeEach(func() { 44 input = NewBuffer() 45 testUI = ui.NewTestUI(input, NewBuffer(), NewBuffer()) 46 fakeConfig = new(commandfakes.FakeConfig) 47 fakeActor = new(commonfakes.FakeInstallPluginActor) 48 fakeProgressBar = new(pluginfakes.FakeProxyReader) 49 50 cmd = InstallPluginCommand{ 51 UI: testUI, 52 Config: fakeConfig, 53 Actor: fakeActor, 54 ProgressBar: fakeProgressBar, 55 } 56 57 tmpDirectorySeed := strconv.Itoa(int(rand.Int63())) 58 pluginHome = fmt.Sprintf("some-pluginhome-%s", tmpDirectorySeed) 59 fakeConfig.PluginHomeReturns(pluginHome) 60 binaryName = helpers.PrefixedRandomName("bin") 61 fakeConfig.BinaryNameReturns(binaryName) 62 }) 63 64 AfterEach(func() { 65 os.RemoveAll(pluginHome) 66 }) 67 68 JustBeforeEach(func() { 69 executeErr = cmd.Execute(nil) 70 }) 71 72 Describe("installing from a specific repo", func() { 73 var ( 74 pluginName string 75 pluginURL string 76 repoName string 77 repoURL string 78 ) 79 80 BeforeEach(func() { 81 pluginName = helpers.PrefixedRandomName("plugin") 82 pluginURL = helpers.PrefixedRandomName("http://") 83 repoName = helpers.PrefixedRandomName("repo") 84 repoURL = helpers.PrefixedRandomName("http://") 85 cmd.OptionalArgs.PluginNameOrLocation = flag.Path(pluginName) 86 cmd.RegisteredRepository = repoName 87 }) 88 89 Context("when the repo is not registered", func() { 90 BeforeEach(func() { 91 fakeActor.GetPluginRepositoryReturns(configv3.PluginRepository{}, pluginaction.RepositoryNotRegisteredError{Name: repoName}) 92 }) 93 94 It("returns a RepositoryNotRegisteredError", func() { 95 Expect(executeErr).To(MatchError(shared.RepositoryNotRegisteredError{Name: repoName})) 96 97 Expect(fakeActor.GetPluginRepositoryCallCount()).To(Equal(1)) 98 repositoryNameArg := fakeActor.GetPluginRepositoryArgsForCall(0) 99 Expect(repositoryNameArg).To(Equal(repoName)) 100 }) 101 }) 102 103 Context("when the repository is registered", func() { 104 var platform string 105 106 BeforeEach(func() { 107 platform = helpers.PrefixedRandomName("platform") 108 fakeActor.GetPlatformStringReturns(platform) 109 fakeActor.GetPluginRepositoryReturns(configv3.PluginRepository{Name: repoName, URL: repoURL}, nil) 110 }) 111 112 Context("when getting repository information returns a json syntax error", func() { 113 var jsonErr error 114 BeforeEach(func() { 115 jsonErr = &json.SyntaxError{} 116 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, jsonErr) 117 }) 118 119 It("returns a JSONSyntaxError", func() { 120 Expect(executeErr).To(MatchError(shared.JSONSyntaxError{Err: jsonErr})) 121 }) 122 }) 123 124 Context("when getting the repository information errors", func() { 125 Context("with a generic error", func() { 126 var expectedErr error 127 128 BeforeEach(func() { 129 expectedErr = errors.New("some-client-error") 130 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, pluginaction.FetchingPluginInfoFromRepositoryError{ 131 RepositoryName: "some-repo", 132 Err: expectedErr, 133 }) 134 }) 135 136 It("returns the wrapped client(request/http status) error", func() { 137 Expect(executeErr).To(MatchError(expectedErr)) 138 }) 139 }) 140 141 Context("with a RawHTTPStatusError error", func() { 142 var returnedErr pluginerror.RawHTTPStatusError 143 144 BeforeEach(func() { 145 returnedErr = pluginerror.RawHTTPStatusError{Status: "some-status"} 146 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, pluginaction.FetchingPluginInfoFromRepositoryError{ 147 RepositoryName: "some-repo", 148 Err: returnedErr, 149 }) 150 }) 151 152 It("returns the wrapped client(request/http status) error", func() { 153 Expect(executeErr).To(MatchError(shared.DownloadPluginHTTPError{Message: returnedErr.Status})) 154 }) 155 }) 156 }) 157 158 Context("when the plugin can't be found in the repository", func() { 159 BeforeEach(func() { 160 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, pluginaction.PluginNotFoundInAnyRepositoryError{PluginName: pluginName}) 161 }) 162 163 It("returns the PluginNotFoundInRepositoryError", func() { 164 Expect(executeErr).To(MatchError(shared.PluginNotFoundInRepositoryError{BinaryName: binaryName, PluginName: pluginName, RepositoryName: repoName})) 165 166 Expect(fakeActor.GetPlatformStringCallCount()).To(Equal(1)) 167 platformGOOS, platformGOARCH := fakeActor.GetPlatformStringArgsForCall(0) 168 Expect(platformGOOS).To(Equal(runtime.GOOS)) 169 Expect(platformGOARCH).To(Equal(runtime.GOARCH)) 170 171 Expect(fakeActor.GetPluginInfoFromRepositoriesForPlatformCallCount()).To(Equal(1)) 172 pluginNameArg, pluginRepositoriesArg, pluginPlatform := fakeActor.GetPluginInfoFromRepositoriesForPlatformArgsForCall(0) 173 Expect(pluginNameArg).To(Equal(pluginName)) 174 Expect(pluginRepositoriesArg).To(Equal([]configv3.PluginRepository{{Name: repoName, URL: repoURL}})) 175 Expect(pluginPlatform).To(Equal(platform)) 176 }) 177 }) 178 179 Context("when a compatible binary can't be found in the repository", func() { 180 BeforeEach(func() { 181 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, pluginaction.NoCompatibleBinaryError{}) 182 }) 183 184 It("returns the NoCompatibleBinaryError", func() { 185 Expect(executeErr).To(MatchError(shared.NoCompatibleBinaryError{})) 186 }) 187 }) 188 189 Context("when the plugin is found", func() { 190 var ( 191 checksum string 192 downloadedVersionString string 193 ) 194 195 BeforeEach(func() { 196 checksum = helpers.PrefixedRandomName("checksum") 197 downloadedVersionString = helpers.PrefixedRandomName("version") 198 199 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{Name: pluginName, Version: downloadedVersionString, URL: pluginURL, Checksum: checksum}, []string{repoName}, nil) 200 }) 201 202 Context("when the -f argument is given", func() { 203 BeforeEach(func() { 204 cmd.Force = true 205 }) 206 207 Context("when the plugin is already installed", func() { 208 BeforeEach(func() { 209 fakeConfig.GetPluginReturns(configv3.Plugin{ 210 Name: pluginName, 211 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 2}, 212 }, true) 213 fakeActor.IsPluginInstalledReturns(true) 214 }) 215 216 Context("when getting the binary errors", func() { 217 BeforeEach(func() { 218 expectedErr = errors.New("some-error") 219 fakeActor.DownloadExecutableBinaryFromURLReturns("", expectedErr) 220 }) 221 222 It("returns the error", func() { 223 Expect(executeErr).To(MatchError(expectedErr)) 224 225 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 226 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 227 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 228 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 229 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 230 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 231 232 Expect(testUI.Out).ToNot(Say("downloaded")) 233 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(0)) 234 235 Expect(fakeConfig.GetPluginCallCount()).To(Equal(1)) 236 Expect(fakeConfig.GetPluginArgsForCall(0)).To(Equal(pluginName)) 237 238 Expect(fakeActor.GetPlatformStringCallCount()).To(Equal(1)) 239 platformGOOS, platformGOARCH := fakeActor.GetPlatformStringArgsForCall(0) 240 Expect(platformGOOS).To(Equal(runtime.GOOS)) 241 Expect(platformGOARCH).To(Equal(runtime.GOARCH)) 242 243 Expect(fakeActor.GetPluginInfoFromRepositoriesForPlatformCallCount()).To(Equal(1)) 244 pluginNameArg, pluginRepositoriesArg, pluginPlatform := fakeActor.GetPluginInfoFromRepositoriesForPlatformArgsForCall(0) 245 Expect(pluginNameArg).To(Equal(pluginName)) 246 Expect(pluginRepositoriesArg).To(Equal([]configv3.PluginRepository{{Name: repoName, URL: repoURL}})) 247 Expect(pluginPlatform).To(Equal(platform)) 248 249 Expect(fakeActor.DownloadExecutableBinaryFromURLCallCount()).To(Equal(1)) 250 urlArg, dirArg, proxyReader := fakeActor.DownloadExecutableBinaryFromURLArgsForCall(0) 251 Expect(urlArg).To(Equal(pluginURL)) 252 Expect(dirArg).To(ContainSubstring("temp")) 253 Expect(proxyReader).To(Equal(fakeProgressBar)) 254 }) 255 }) 256 257 Context("when getting the binary succeeds", func() { 258 var execPath string 259 260 BeforeEach(func() { 261 execPath = helpers.PrefixedRandomName("some-path") 262 fakeActor.DownloadExecutableBinaryFromURLReturns(execPath, nil) 263 }) 264 265 Context("when the checksum fails", func() { 266 BeforeEach(func() { 267 fakeActor.ValidateFileChecksumReturns(false) 268 }) 269 270 It("returns the checksum error", func() { 271 Expect(executeErr).To(MatchError(InvalidChecksumError{})) 272 273 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 274 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 275 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 276 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 277 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 278 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 279 Expect(testUI.Out).ToNot(Say("Installing plugin")) 280 281 Expect(fakeActor.ValidateFileChecksumCallCount()).To(Equal(1)) 282 pathArg, checksumArg := fakeActor.ValidateFileChecksumArgsForCall(0) 283 Expect(pathArg).To(Equal(execPath)) 284 Expect(checksumArg).To(Equal(checksum)) 285 }) 286 }) 287 288 Context("when the checksum succeeds", func() { 289 BeforeEach(func() { 290 fakeActor.ValidateFileChecksumReturns(true) 291 }) 292 293 Context("when creating an executable copy errors", func() { 294 BeforeEach(func() { 295 fakeActor.CreateExecutableCopyReturns("", errors.New("some-error")) 296 }) 297 298 It("returns the error", func() { 299 Expect(executeErr).To(MatchError(errors.New("some-error"))) 300 Expect(testUI.Out).ToNot(Say("Installing plugin")) 301 302 Expect(fakeActor.CreateExecutableCopyCallCount()).To(Equal(1)) 303 pathArg, tempDirArg := fakeActor.CreateExecutableCopyArgsForCall(0) 304 Expect(pathArg).To(Equal(execPath)) 305 Expect(tempDirArg).To(ContainSubstring("temp")) 306 }) 307 }) 308 309 Context("when creating an exectuable copy succeeds", func() { 310 BeforeEach(func() { 311 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 312 }) 313 314 Context("when validating the new plugin errors", func() { 315 BeforeEach(func() { 316 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{}, pluginaction.PluginInvalidError{}) 317 }) 318 319 It("returns the error", func() { 320 Expect(executeErr).To(MatchError(shared.PluginInvalidError{})) 321 Expect(testUI.Out).ToNot(Say("Installing plugin")) 322 323 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(1)) 324 _, commandsArg, tempDirArg := fakeActor.GetAndValidatePluginArgsForCall(0) 325 Expect(commandsArg).To(Equal(Commands)) 326 Expect(tempDirArg).To(Equal("copy-path")) 327 }) 328 }) 329 330 Context("when validating the new plugin succeeds", func() { 331 var ( 332 pluginVersion configv3.PluginVersion 333 pluginVersionRegex string 334 ) 335 336 BeforeEach(func() { 337 major := rand.Int() 338 minor := rand.Int() 339 build := rand.Int() 340 pluginVersion = configv3.PluginVersion{Major: major, Minor: minor, Build: build} 341 pluginVersionRegex = fmt.Sprintf("%d\\.%d\\.%d", major, minor, build) 342 343 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 344 Name: pluginName, 345 Version: pluginVersion, 346 }, nil) 347 }) 348 349 Context("when uninstalling the existing errors", func() { 350 BeforeEach(func() { 351 expectedErr = errors.New("uninstall plugin error") 352 fakeActor.UninstallPluginReturns(expectedErr) 353 }) 354 355 It("returns the error", func() { 356 Expect(executeErr).To(MatchError(expectedErr)) 357 358 Expect(testUI.Out).To(Say("Uninstalling existing plugin\\.\\.\\.")) 359 Expect(testUI.Out).ToNot(Say("Plugin %s successfully uninstalled\\.", pluginName)) 360 361 Expect(fakeActor.UninstallPluginCallCount()).To(Equal(1)) 362 _, pluginNameArg := fakeActor.UninstallPluginArgsForCall(0) 363 Expect(pluginNameArg).To(Equal(pluginName)) 364 }) 365 }) 366 367 Context("when uninstalling the existing plugin succeeds", func() { 368 Context("when installing the new plugin errors", func() { 369 BeforeEach(func() { 370 expectedErr = errors.New("install plugin error") 371 fakeActor.InstallPluginFromPathReturns(expectedErr) 372 }) 373 374 It("returns the error", func() { 375 Expect(executeErr).To(MatchError(expectedErr)) 376 377 Expect(testUI.Out).To(Say("Plugin %s successfully uninstalled\\.", pluginName)) 378 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 379 Expect(testUI.Out).ToNot(Say("successfully installed")) 380 381 Expect(fakeActor.InstallPluginFromPathCallCount()).To(Equal(1)) 382 pathArg, pluginArg := fakeActor.InstallPluginFromPathArgsForCall(0) 383 Expect(pathArg).To(Equal("copy-path")) 384 Expect(pluginArg).To(Equal(configv3.Plugin{ 385 Name: pluginName, 386 Version: pluginVersion, 387 })) 388 }) 389 }) 390 391 Context("when installing the new plugin succeeds", func() { 392 It("uninstalls the existing plugin and installs the new one", func() { 393 Expect(executeErr).ToNot(HaveOccurred()) 394 395 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 396 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 397 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 398 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 399 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 400 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 401 Expect(testUI.Out).To(Say("Uninstalling existing plugin\\.\\.\\.")) 402 Expect(testUI.Out).To(Say("OK")) 403 Expect(testUI.Out).To(Say("Plugin %s successfully uninstalled\\.", pluginName)) 404 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 405 Expect(testUI.Out).To(Say("OK")) 406 Expect(testUI.Out).To(Say("%s %s successfully installed\\.", pluginName, pluginVersionRegex)) 407 }) 408 }) 409 }) 410 }) 411 }) 412 }) 413 }) 414 }) 415 416 Context("when the plugin is NOT already installed", func() { 417 Context("when getting the binary errors", func() { 418 BeforeEach(func() { 419 expectedErr = errors.New("some-error") 420 fakeActor.DownloadExecutableBinaryFromURLReturns("", expectedErr) 421 }) 422 423 It("returns the error", func() { 424 Expect(executeErr).To(MatchError(expectedErr)) 425 426 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 427 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 428 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 429 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 430 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 431 432 Expect(testUI.Out).ToNot(Say("downloaded")) 433 Expect(fakeActor.GetAndValidatePluginCallCount()).To(Equal(0)) 434 }) 435 }) 436 437 Context("when getting the binary succeeds", func() { 438 BeforeEach(func() { 439 fakeActor.DownloadExecutableBinaryFromURLReturns("some-path", nil) 440 }) 441 442 Context("when the checksum fails", func() { 443 BeforeEach(func() { 444 fakeActor.ValidateFileChecksumReturns(false) 445 }) 446 447 It("returns the checksum error", func() { 448 Expect(executeErr).To(MatchError(InvalidChecksumError{})) 449 450 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 451 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 452 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 453 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 454 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 455 Expect(testUI.Out).ToNot(Say("Installing plugin")) 456 }) 457 }) 458 459 Context("when the checksum succeeds", func() { 460 BeforeEach(func() { 461 fakeActor.ValidateFileChecksumReturns(true) 462 }) 463 464 Context("when creating an executable copy errors", func() { 465 BeforeEach(func() { 466 fakeActor.CreateExecutableCopyReturns("", errors.New("some-error")) 467 }) 468 469 It("returns the error", func() { 470 Expect(executeErr).To(MatchError(errors.New("some-error"))) 471 Expect(testUI.Out).ToNot(Say("Installing plugin")) 472 }) 473 }) 474 475 Context("when creating an executable copy succeeds", func() { 476 BeforeEach(func() { 477 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 478 }) 479 480 Context("when validating the plugin errors", func() { 481 BeforeEach(func() { 482 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{}, pluginaction.PluginInvalidError{}) 483 }) 484 485 It("returns the error", func() { 486 Expect(executeErr).To(MatchError(shared.PluginInvalidError{})) 487 Expect(testUI.Out).ToNot(Say("Installing plugin")) 488 }) 489 }) 490 491 Context("when validating the plugin succeeds", func() { 492 BeforeEach(func() { 493 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 494 Name: pluginName, 495 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 3}, 496 }, nil) 497 }) 498 499 Context("when installing the plugin errors", func() { 500 BeforeEach(func() { 501 expectedErr = errors.New("install plugin error") 502 fakeActor.InstallPluginFromPathReturns(expectedErr) 503 }) 504 505 It("returns the error", func() { 506 Expect(executeErr).To(MatchError(expectedErr)) 507 508 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 509 Expect(testUI.Out).ToNot(Say("successfully installed")) 510 }) 511 }) 512 513 Context("when installing the plugin succeeds", func() { 514 It("uninstalls the existing plugin and installs the new one", func() { 515 Expect(executeErr).ToNot(HaveOccurred()) 516 517 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 518 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 519 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 520 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 521 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 522 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 523 Expect(testUI.Out).To(Say("OK")) 524 Expect(testUI.Out).To(Say("%s 1\\.2\\.3 successfully installed", pluginName)) 525 }) 526 }) 527 }) 528 }) 529 }) 530 }) 531 }) 532 }) 533 534 Context("when the -f argument is not given (user is prompted for confirmation)", func() { 535 BeforeEach(func() { 536 fakeActor.ValidateFileChecksumReturns(true) 537 }) 538 539 Context("when the plugin is already installed", func() { 540 BeforeEach(func() { 541 fakeConfig.GetPluginReturns(configv3.Plugin{ 542 Name: pluginName, 543 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 2}, 544 }, true) 545 fakeActor.IsPluginInstalledReturns(true) 546 }) 547 548 Context("when the user chooses no", func() { 549 BeforeEach(func() { 550 input.Write([]byte("n\n")) 551 }) 552 553 It("cancels plugin installation", func() { 554 Expect(executeErr).ToNot(HaveOccurred()) 555 556 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 557 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 558 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 559 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 560 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 561 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 562 Expect(testUI.Out).To(Say("Plugin installation cancelled\\.")) 563 }) 564 }) 565 566 Context("when the user chooses the default", func() { 567 BeforeEach(func() { 568 input.Write([]byte("\n")) 569 }) 570 571 It("cancels plugin installation", func() { 572 Expect(executeErr).ToNot(HaveOccurred()) 573 574 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 575 Expect(testUI.Out).To(Say("Plugin installation cancelled\\.")) 576 }) 577 }) 578 579 Context("when the user input is invalid", func() { 580 BeforeEach(func() { 581 input.Write([]byte("e\n")) 582 }) 583 584 It("returns an error", func() { 585 Expect(executeErr).To(HaveOccurred()) 586 587 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 588 Expect(testUI.Out).ToNot(Say("Plugin installation cancelled\\.")) 589 Expect(testUI.Out).ToNot(Say("Installing plugin")) 590 }) 591 }) 592 593 Context("when the user chooses yes", func() { 594 BeforeEach(func() { 595 input.Write([]byte("y\n")) 596 fakeActor.DownloadExecutableBinaryFromURLReturns("some-path", nil) 597 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 598 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 599 Name: pluginName, 600 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 3}, 601 }, nil) 602 }) 603 604 It("installs the plugin", func() { 605 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 606 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 607 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 608 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 609 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 610 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 611 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 612 Expect(testUI.Out).To(Say("Uninstalling existing plugin\\.\\.\\.")) 613 Expect(testUI.Out).To(Say("OK")) 614 Expect(testUI.Out).To(Say("Plugin %s successfully uninstalled\\.", pluginName)) 615 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 616 Expect(testUI.Out).To(Say("OK")) 617 Expect(testUI.Out).To(Say("%s 1\\.2\\.3 successfully installed", pluginName)) 618 }) 619 }) 620 }) 621 622 Context("when the plugin is NOT already installed", func() { 623 Context("when the user chooses no", func() { 624 BeforeEach(func() { 625 input.Write([]byte("n\n")) 626 }) 627 628 It("cancels plugin installation", func() { 629 Expect(executeErr).ToNot(HaveOccurred()) 630 631 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 632 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 633 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 634 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 635 Expect(testUI.Out).To(Say("Do you want to install the plugin %s\\? \\[yN\\]", pluginName)) 636 Expect(testUI.Out).To(Say("Plugin installation cancelled\\.")) 637 }) 638 }) 639 640 Context("when the user chooses the default", func() { 641 BeforeEach(func() { 642 input.Write([]byte("\n")) 643 }) 644 645 It("cancels plugin installation", func() { 646 Expect(executeErr).ToNot(HaveOccurred()) 647 648 Expect(testUI.Out).To(Say("Do you want to install the plugin %s\\? \\[yN\\]", pluginName)) 649 Expect(testUI.Out).To(Say("Plugin installation cancelled\\.")) 650 }) 651 }) 652 653 Context("when the user input is invalid", func() { 654 BeforeEach(func() { 655 input.Write([]byte("e\n")) 656 }) 657 658 It("returns an error", func() { 659 Expect(executeErr).To(HaveOccurred()) 660 661 Expect(testUI.Out).To(Say("Do you want to install the plugin %s\\? \\[yN\\]", pluginName)) 662 Expect(testUI.Out).ToNot(Say("Plugin installation cancelled\\.")) 663 Expect(testUI.Out).ToNot(Say("Installing plugin")) 664 }) 665 }) 666 667 Context("when the user chooses yes", func() { 668 var execPath string 669 670 BeforeEach(func() { 671 input.Write([]byte("y\n")) 672 execPath = helpers.PrefixedRandomName("some-path") 673 fakeActor.DownloadExecutableBinaryFromURLReturns(execPath, nil) 674 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 675 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 676 Name: pluginName, 677 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 3}, 678 }, nil) 679 }) 680 681 It("installs the plugin", func() { 682 Expect(executeErr).ToNot(HaveOccurred()) 683 684 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 685 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 686 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 687 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 688 Expect(testUI.Out).To(Say("Do you want to install the plugin %s\\? \\[yN\\]", pluginName)) 689 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 690 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 691 Expect(testUI.Out).To(Say("OK")) 692 Expect(testUI.Out).To(Say("%s 1\\.2\\.3 successfully installed", pluginName)) 693 }) 694 }) 695 }) 696 }) 697 }) 698 }) 699 }) 700 701 Describe("installing from any registered repo", func() { 702 var ( 703 pluginName string 704 pluginURL string 705 repoName string 706 repoURL string 707 repo2Name string 708 repo2URL string 709 repo3Name string 710 repo3URL string 711 platform string 712 ) 713 714 BeforeEach(func() { 715 pluginName = helpers.PrefixedRandomName("plugin") 716 pluginURL = helpers.PrefixedRandomName("http://") 717 repoName = helpers.PrefixedRandomName("repoA") 718 repoURL = helpers.PrefixedRandomName("http://") 719 repo2Name = helpers.PrefixedRandomName("repoB") 720 repo2URL = helpers.PrefixedRandomName("http://") 721 repo3Name = helpers.PrefixedRandomName("repoC") 722 repo3URL = helpers.PrefixedRandomName("http://") 723 cmd.OptionalArgs.PluginNameOrLocation = flag.Path(pluginName) 724 725 platform = helpers.PrefixedRandomName("platform") 726 fakeActor.GetPlatformStringReturns(platform) 727 }) 728 729 Context("when there are no registered repos", func() { 730 BeforeEach(func() { 731 fakeConfig.PluginRepositoriesReturns([]configv3.PluginRepository{}) 732 }) 733 734 It("returns PluginNotFoundOnDiskOrInAnyRepositoryError", func() { 735 Expect(executeErr).To(MatchError(shared.PluginNotFoundOnDiskOrInAnyRepositoryError{PluginName: pluginName, BinaryName: binaryName})) 736 }) 737 }) 738 739 Context("when there is one registered repo", func() { 740 BeforeEach(func() { 741 fakeConfig.PluginRepositoriesReturns([]configv3.PluginRepository{{Name: repoName, URL: repoURL}}) 742 }) 743 744 Context("when there is an error getting the plugin", func() { 745 BeforeEach(func() { 746 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, errors.New("some-error")) 747 }) 748 749 It("returns the error", func() { 750 Expect(executeErr).To(MatchError(errors.New("some-error"))) 751 }) 752 }) 753 754 Context("when the plugin is not found", func() { 755 BeforeEach(func() { 756 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, pluginaction.PluginNotFoundInAnyRepositoryError{PluginName: pluginName}) 757 }) 758 759 It("returns the plugin not found error", func() { 760 Expect(executeErr).To(MatchError(shared.PluginNotFoundOnDiskOrInAnyRepositoryError{PluginName: pluginName, BinaryName: binaryName})) 761 }) 762 }) 763 764 Context("when the plugin is found", func() { 765 var ( 766 checksum string 767 downloadedVersionString string 768 execPath string 769 ) 770 771 BeforeEach(func() { 772 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{Name: pluginName, Version: downloadedVersionString, URL: pluginURL, Checksum: checksum}, []string{repoName}, nil) 773 774 fakeConfig.GetPluginReturns(configv3.Plugin{ 775 Name: pluginName, 776 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 2}, 777 }, true) 778 fakeActor.IsPluginInstalledReturns(true) 779 780 execPath = helpers.PrefixedRandomName("some-path") 781 fakeActor.DownloadExecutableBinaryFromURLReturns(execPath, nil) 782 }) 783 784 Context("when the -f flag is provided, the plugin has already been installed, getting the binary succeeds, validating the checksum succeeds, creating an executable copy succeeds, validating the new plugin succeeds, uninstalling the existing plugin succeeds, and installing the plugin is succeeds", func() { 785 var ( 786 pluginVersion configv3.PluginVersion 787 pluginVersionRegex string 788 ) 789 790 BeforeEach(func() { 791 cmd.Force = true 792 793 fakeActor.ValidateFileChecksumReturns(true) 794 checksum = helpers.PrefixedRandomName("checksum") 795 796 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 797 798 major := rand.Int() 799 minor := rand.Int() 800 build := rand.Int() 801 pluginVersion = configv3.PluginVersion{Major: major, Minor: minor, Build: build} 802 pluginVersionRegex = fmt.Sprintf("%d\\.%d\\.%d", major, minor, build) 803 804 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 805 Name: pluginName, 806 Version: pluginVersion, 807 }, nil) 808 }) 809 810 It("uninstalls the existing plugin and installs the new one", func() { 811 Expect(executeErr).ToNot(HaveOccurred()) 812 813 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 814 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 815 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 816 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 817 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 818 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 819 Expect(testUI.Out).To(Say("Uninstalling existing plugin\\.\\.\\.")) 820 Expect(testUI.Out).To(Say("OK")) 821 Expect(testUI.Out).To(Say("Plugin %s successfully uninstalled\\.", pluginName)) 822 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 823 Expect(testUI.Out).To(Say("OK")) 824 Expect(testUI.Out).To(Say("%s %s successfully installed\\.", pluginName, pluginVersionRegex)) 825 }) 826 }) 827 828 Context("when the -f flag is not provided, the plugin has already been installed, getting the binary succeeds, but validating the checksum fails", func() { 829 BeforeEach(func() { 830 fakeActor.DownloadExecutableBinaryFromURLReturns("some-path", nil) 831 }) 832 833 Context("when the checksum fails", func() { 834 BeforeEach(func() { 835 cmd.Force = false 836 fakeActor.ValidateFileChecksumReturns(false) 837 input.Write([]byte("y\n")) 838 }) 839 840 It("returns the checksum error", func() { 841 Expect(executeErr).To(MatchError(InvalidChecksumError{})) 842 843 Expect(testUI.Out).To(Say("Searching %s for plugin %s\\.\\.\\.", repoName, pluginName)) 844 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repoName)) 845 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 846 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 847 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 848 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 849 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repoName)) 850 }) 851 }) 852 }) 853 }) 854 }) 855 856 Context("when there are many registered repos", func() { 857 BeforeEach(func() { 858 fakeConfig.PluginRepositoriesReturns([]configv3.PluginRepository{{Name: repoName, URL: repoURL}, {Name: repo2Name, URL: repo2URL}, {Name: repo3Name, URL: repo3URL}}) 859 }) 860 861 Context("when getting the repository information errors", func() { 862 DescribeTable("properly propagates errors", 863 func(clientErr error, expectedErr error) { 864 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns( 865 pluginaction.PluginInfo{}, 866 nil, 867 clientErr) 868 869 executeErr = cmd.Execute(nil) 870 871 Expect(executeErr).To(MatchError(expectedErr)) 872 }, 873 874 Entry("when the error is a RawHTTPStatusError", 875 pluginaction.FetchingPluginInfoFromRepositoryError{ 876 RepositoryName: "some-repo", 877 Err: pluginerror.RawHTTPStatusError{Status: "some-status"}, 878 }, 879 shared.FetchingPluginInfoFromRepositoriesError{Message: "some-status", RepositoryName: "some-repo"}, 880 ), 881 882 Entry("when the error is a SSLValidationHostnameError", 883 pluginaction.FetchingPluginInfoFromRepositoryError{ 884 RepositoryName: "some-repo", 885 Err: pluginerror.SSLValidationHostnameError{Message: "some-status"}, 886 }, 887 888 shared.FetchingPluginInfoFromRepositoriesError{Message: "Hostname does not match SSL Certificate (some-status)", RepositoryName: "some-repo"}, 889 ), 890 891 Entry("when the error is an UnverifiedServerError", 892 pluginaction.FetchingPluginInfoFromRepositoryError{ 893 RepositoryName: "some-repo", 894 Err: pluginerror.UnverifiedServerError{URL: "some-url"}, 895 }, 896 shared.FetchingPluginInfoFromRepositoriesError{Message: "x509: certificate signed by unknown authority", RepositoryName: "some-repo"}, 897 ), 898 899 Entry("when the error is generic", 900 pluginaction.FetchingPluginInfoFromRepositoryError{ 901 RepositoryName: "some-repo", 902 Err: errors.New("generic-error"), 903 }, 904 errors.New("generic-error"), 905 ), 906 ) 907 }) 908 909 Context("when the plugin can't be found in any repos", func() { 910 BeforeEach(func() { 911 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{}, nil, pluginaction.PluginNotFoundInAnyRepositoryError{PluginName: pluginName}) 912 }) 913 914 It("returns PluginNotFoundOnDiskOrInAnyRepositoryError", func() { 915 Expect(executeErr).To(MatchError(shared.PluginNotFoundOnDiskOrInAnyRepositoryError{PluginName: pluginName, BinaryName: binaryName})) 916 }) 917 }) 918 919 Context("when the plugin is found in one repo", func() { 920 var ( 921 checksum string 922 downloadedVersionString string 923 execPath string 924 ) 925 926 BeforeEach(func() { 927 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{Name: pluginName, Version: downloadedVersionString, URL: pluginURL, Checksum: checksum}, []string{repo2Name}, nil) 928 929 fakeConfig.GetPluginReturns(configv3.Plugin{ 930 Name: pluginName, 931 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 2}, 932 }, true) 933 fakeActor.IsPluginInstalledReturns(true) 934 935 execPath = helpers.PrefixedRandomName("some-path") 936 }) 937 938 Context("when the -f flag is provided, the plugin has already been installed, getting the binary succeeds, validating the checksum succeeds, creating an executable copy succeeds, validating the new plugin succeeds, uninstalling the existing plugin succeeds, and installing the plugin is succeeds", func() { 939 var pluginVersion configv3.PluginVersion 940 941 BeforeEach(func() { 942 cmd.Force = true 943 944 fakeActor.DownloadExecutableBinaryFromURLReturns(execPath, nil) 945 946 fakeActor.ValidateFileChecksumReturns(true) 947 checksum = helpers.PrefixedRandomName("checksum") 948 949 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 950 951 major := rand.Int() 952 minor := rand.Int() 953 build := rand.Int() 954 pluginVersion = configv3.PluginVersion{Major: major, Minor: minor, Build: build} 955 956 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 957 Name: pluginName, 958 Version: pluginVersion, 959 }, nil) 960 }) 961 962 It("uninstalls the existing plugin and installs the new one", func() { 963 Expect(executeErr).ToNot(HaveOccurred()) 964 965 Expect(testUI.Out).To(Say("Searching %s, %s, %s for plugin %s\\.\\.\\.", repoName, repo2Name, repo3Name, pluginName)) 966 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repo2Name)) 967 }) 968 }) 969 970 Context("when the -f flag is not provided, the plugin has already been installed, getting the binary succeeds fails", func() { 971 972 BeforeEach(func() { 973 cmd.Force = false 974 fakeActor.DownloadExecutableBinaryFromURLReturns("", errors.New("some-error")) 975 input.Write([]byte("y\n")) 976 }) 977 978 It("returns the checksum error", func() { 979 Expect(executeErr).To(MatchError(errors.New("some-error"))) 980 981 Expect(testUI.Out).To(Say("Searching %s, %s, %s for plugin %s\\.\\.\\.", repoName, repo2Name, repo3Name, pluginName)) 982 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s", pluginName, downloadedVersionString, repo2Name)) 983 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 984 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 985 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 986 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 987 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repo2Name)) 988 }) 989 }) 990 }) 991 992 Context("when the plugin is found in multiple repos", func() { 993 var ( 994 checksum string 995 downloadedVersionString string 996 execPath string 997 ) 998 999 BeforeEach(func() { 1000 downloadedVersionString = helpers.PrefixedRandomName("version") 1001 1002 fakeActor.GetPluginInfoFromRepositoriesForPlatformReturns(pluginaction.PluginInfo{Name: pluginName, Version: downloadedVersionString, URL: pluginURL, Checksum: checksum}, []string{repo2Name, repo3Name}, nil) 1003 1004 fakeConfig.GetPluginReturns(configv3.Plugin{ 1005 Name: pluginName, 1006 Version: configv3.PluginVersion{Major: 1, Minor: 2, Build: 2}, 1007 }, true) 1008 fakeActor.IsPluginInstalledReturns(true) 1009 1010 execPath = helpers.PrefixedRandomName("some-path") 1011 fakeActor.DownloadExecutableBinaryFromURLReturns(execPath, nil) 1012 }) 1013 1014 Context("when the -f flag is provided, the plugin has already been installed, getting the binary succeeds, validating the checksum succeeds, creating an executable copy succeeds, validating the new plugin succeeds, uninstalling the existing plugin succeeds, and installing the plugin is succeeds", func() { 1015 var ( 1016 pluginVersion configv3.PluginVersion 1017 pluginVersionRegex string 1018 ) 1019 1020 BeforeEach(func() { 1021 cmd.Force = true 1022 1023 fakeActor.ValidateFileChecksumReturns(true) 1024 checksum = helpers.PrefixedRandomName("checksum") 1025 1026 fakeActor.CreateExecutableCopyReturns("copy-path", nil) 1027 1028 major := rand.Int() 1029 minor := rand.Int() 1030 build := rand.Int() 1031 pluginVersion = configv3.PluginVersion{Major: major, Minor: minor, Build: build} 1032 pluginVersionRegex = fmt.Sprintf("%d\\.%d\\.%d", major, minor, build) 1033 1034 fakeActor.GetAndValidatePluginReturns(configv3.Plugin{ 1035 Name: pluginName, 1036 Version: pluginVersion, 1037 }, nil) 1038 }) 1039 1040 It("uninstalls the existing plugin and installs the new one", func() { 1041 Expect(executeErr).ToNot(HaveOccurred()) 1042 1043 Expect(testUI.Out).To(Say("Searching %s, %s, %s for plugin %s\\.\\.\\.", repoName, repo2Name, repo3Name, pluginName)) 1044 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s, %s", pluginName, downloadedVersionString, repo2Name, repo3Name)) 1045 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 1046 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 1047 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 1048 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repo2Name)) 1049 Expect(testUI.Out).To(Say("Uninstalling existing plugin\\.\\.\\.")) 1050 Expect(testUI.Out).To(Say("OK")) 1051 Expect(testUI.Out).To(Say("Plugin %s successfully uninstalled\\.", pluginName)) 1052 Expect(testUI.Out).To(Say("Installing plugin %s\\.\\.\\.", pluginName)) 1053 Expect(testUI.Out).To(Say("OK")) 1054 Expect(testUI.Out).To(Say("%s %s successfully installed\\.", pluginName, pluginVersionRegex)) 1055 }) 1056 }) 1057 1058 Context("when the -f flag is not provided, the plugin has already been installed, getting the binary succeeds, validating the checksum succeeds, but creating an executable copy fails", func() { 1059 1060 BeforeEach(func() { 1061 cmd.Force = false 1062 fakeActor.ValidateFileChecksumReturns(true) 1063 checksum = helpers.PrefixedRandomName("checksum") 1064 1065 fakeActor.CreateExecutableCopyReturns("", errors.New("some-error")) 1066 input.Write([]byte("y\n")) 1067 }) 1068 1069 It("returns the error", func() { 1070 Expect(executeErr).To(MatchError(errors.New("some-error"))) 1071 1072 Expect(testUI.Out).To(Say("Searching %s, %s, %s for plugin %s\\.\\.\\.", repoName, repo2Name, repo3Name, pluginName)) 1073 Expect(testUI.Out).To(Say("Plugin %s %s found in: %s, %s", pluginName, downloadedVersionString, repo2Name, repo3Name)) 1074 Expect(testUI.Out).To(Say("Plugin %s 1\\.2\\.2 is already installed\\.", pluginName)) 1075 Expect(testUI.Out).To(Say("Attention: Plugins are binaries written by potentially untrusted authors\\.")) 1076 Expect(testUI.Out).To(Say("Install and use plugins at your own risk\\.")) 1077 Expect(testUI.Out).To(Say("Do you want to uninstall the existing plugin and install %s %s\\? \\[yN\\]", pluginName, downloadedVersionString)) 1078 Expect(testUI.Out).To(Say("Starting download of plugin binary from repository %s\\.\\.\\.", repo2Name)) 1079 }) 1080 }) 1081 }) 1082 }) 1083 }) 1084 })