upgrade.go 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889
  1. package plugin
  2. import (
  3. "context"
  4. "fmt"
  5. "strings"
  6. "github.com/docker/distribution/reference"
  7. "github.com/docker/docker/cli"
  8. "github.com/docker/docker/cli/command"
  9. "github.com/docker/docker/pkg/jsonmessage"
  10. "github.com/pkg/errors"
  11. "github.com/spf13/cobra"
  12. )
  13. func newUpgradeCommand(dockerCli *command.DockerCli) *cobra.Command {
  14. var options pluginOptions
  15. cmd := &cobra.Command{
  16. Use: "upgrade [OPTIONS] PLUGIN [REMOTE]",
  17. Short: "Upgrade an existing plugin",
  18. Args: cli.RequiresRangeArgs(1, 2),
  19. RunE: func(cmd *cobra.Command, args []string) error {
  20. options.localName = args[0]
  21. if len(args) == 2 {
  22. options.remote = args[1]
  23. }
  24. return runUpgrade(dockerCli, options)
  25. },
  26. }
  27. flags := cmd.Flags()
  28. loadPullFlags(&options, flags)
  29. flags.BoolVar(&options.skipRemoteCheck, "skip-remote-check", false, "Do not check if specified remote plugin matches existing plugin image")
  30. return cmd
  31. }
  32. func runUpgrade(dockerCli *command.DockerCli, opts pluginOptions) error {
  33. ctx := context.Background()
  34. p, _, err := dockerCli.Client().PluginInspectWithRaw(ctx, opts.localName)
  35. if err != nil {
  36. return fmt.Errorf("error reading plugin data: %v", err)
  37. }
  38. if p.Enabled {
  39. return fmt.Errorf("the plugin must be disabled before upgrading")
  40. }
  41. opts.localName = p.Name
  42. if opts.remote == "" {
  43. opts.remote = p.PluginReference
  44. }
  45. remote, err := reference.ParseNormalizedNamed(opts.remote)
  46. if err != nil {
  47. return errors.Wrap(err, "error parsing remote upgrade image reference")
  48. }
  49. remote = reference.TagNameOnly(remote)
  50. old, err := reference.ParseNormalizedNamed(p.PluginReference)
  51. if err != nil {
  52. return errors.Wrap(err, "error parsing current image reference")
  53. }
  54. old = reference.TagNameOnly(old)
  55. fmt.Fprintf(dockerCli.Out(), "Upgrading plugin %s from %s to %s\n", p.Name, reference.FamiliarString(old), reference.FamiliarString(remote))
  56. if !opts.skipRemoteCheck && remote.String() != old.String() {
  57. if !command.PromptForConfirmation(dockerCli.In(), dockerCli.Out(), "Plugin images do not match, are you sure?") {
  58. return errors.New("canceling upgrade request")
  59. }
  60. }
  61. options, err := buildPullConfig(ctx, dockerCli, opts, "plugin upgrade")
  62. if err != nil {
  63. return err
  64. }
  65. responseBody, err := dockerCli.Client().PluginUpgrade(ctx, opts.localName, options)
  66. if err != nil {
  67. if strings.Contains(err.Error(), "target is image") {
  68. return errors.New(err.Error() + " - Use `docker image pull`")
  69. }
  70. return err
  71. }
  72. defer responseBody.Close()
  73. if err := jsonmessage.DisplayJSONMessagesToStream(responseBody, dockerCli.Out(), nil); err != nil {
  74. return err
  75. }
  76. fmt.Fprintf(dockerCli.Out(), "Upgraded plugin %s to %s\n", opts.localName, opts.remote) // todo: return proper values from the API for this result
  77. return nil
  78. }