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