pull.go 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293
  1. package image
  2. import (
  3. "errors"
  4. "fmt"
  5. "strings"
  6. "golang.org/x/net/context"
  7. "github.com/docker/docker/cli"
  8. "github.com/docker/docker/cli/command"
  9. "github.com/docker/docker/reference"
  10. "github.com/docker/docker/registry"
  11. "github.com/spf13/cobra"
  12. )
  13. type pullOptions struct {
  14. remote string
  15. all bool
  16. }
  17. // NewPullCommand creates a new `docker pull` command
  18. func NewPullCommand(dockerCli *command.DockerCli) *cobra.Command {
  19. var opts pullOptions
  20. cmd := &cobra.Command{
  21. Use: "pull [OPTIONS] NAME[:TAG|@DIGEST]",
  22. Short: "Pull an image or a repository from a registry",
  23. Args: cli.ExactArgs(1),
  24. RunE: func(cmd *cobra.Command, args []string) error {
  25. opts.remote = args[0]
  26. return runPull(dockerCli, opts)
  27. },
  28. }
  29. flags := cmd.Flags()
  30. flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository")
  31. command.AddTrustedFlags(flags, true)
  32. return cmd
  33. }
  34. func runPull(dockerCli *command.DockerCli, opts pullOptions) error {
  35. distributionRef, err := reference.ParseNamed(opts.remote)
  36. if err != nil {
  37. return err
  38. }
  39. if opts.all && !reference.IsNameOnly(distributionRef) {
  40. return errors.New("tag can't be used with --all-tags/-a")
  41. }
  42. if !opts.all && reference.IsNameOnly(distributionRef) {
  43. distributionRef = reference.WithDefaultTag(distributionRef)
  44. fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", reference.DefaultTag)
  45. }
  46. var tag string
  47. switch x := distributionRef.(type) {
  48. case reference.Canonical:
  49. tag = x.Digest().String()
  50. case reference.NamedTagged:
  51. tag = x.Tag()
  52. }
  53. registryRef := registry.ParseReference(tag)
  54. // Resolve the Repository name from fqn to RepositoryInfo
  55. repoInfo, err := registry.ParseRepositoryInfo(distributionRef)
  56. if err != nil {
  57. return err
  58. }
  59. ctx := context.Background()
  60. authConfig := command.ResolveAuthConfig(ctx, dockerCli, repoInfo.Index)
  61. requestPrivilege := command.RegistryAuthenticationPrivilegedFunc(dockerCli, repoInfo.Index, "pull")
  62. if command.IsTrusted() && !registryRef.HasDigest() {
  63. // Check if tag is digest
  64. err = trustedPull(ctx, dockerCli, repoInfo, registryRef, authConfig, requestPrivilege)
  65. } else {
  66. err = imagePullPrivileged(ctx, dockerCli, authConfig, distributionRef.String(), requestPrivilege, opts.all)
  67. }
  68. if err != nil {
  69. if strings.Contains(err.Error(), "target is a plugin") {
  70. return errors.New(err.Error() + " - Use `docker plugin install`")
  71. }
  72. return err
  73. }
  74. return nil
  75. }