Signed-off-by: Vincent Demeester <vincent@sbr.pm>
| 18 | 17 |
new file mode 100644 |
| ... | ... |
@@ -0,0 +1,86 @@ |
| 0 |
+package image |
|
| 1 |
+ |
|
| 2 |
+import ( |
|
| 3 |
+ "errors" |
|
| 4 |
+ "fmt" |
|
| 5 |
+ |
|
| 6 |
+ "golang.org/x/net/context" |
|
| 7 |
+ |
|
| 8 |
+ "github.com/docker/docker/api/client" |
|
| 9 |
+ "github.com/docker/docker/cli" |
|
| 10 |
+ "github.com/docker/docker/reference" |
|
| 11 |
+ "github.com/docker/docker/registry" |
|
| 12 |
+ "github.com/spf13/cobra" |
|
| 13 |
+) |
|
| 14 |
+ |
|
| 15 |
+type pullOptions struct {
|
|
| 16 |
+ remote string |
|
| 17 |
+ all bool |
|
| 18 |
+} |
|
| 19 |
+ |
|
| 20 |
+// NewPullCommand creates a new `docker pull` command |
|
| 21 |
+func NewPullCommand(dockerCli *client.DockerCli) *cobra.Command {
|
|
| 22 |
+ var opts pullOptions |
|
| 23 |
+ |
|
| 24 |
+ cmd := &cobra.Command{
|
|
| 25 |
+ Use: "pull [OPTIONS] NAME[:TAG|@DIGEST]", |
|
| 26 |
+ Short: "Pull an image or a repository from a registry", |
|
| 27 |
+ Args: cli.ExactArgs(1), |
|
| 28 |
+ RunE: func(cmd *cobra.Command, args []string) error {
|
|
| 29 |
+ opts.remote = args[0] |
|
| 30 |
+ return runPull(dockerCli, opts) |
|
| 31 |
+ }, |
|
| 32 |
+ } |
|
| 33 |
+ |
|
| 34 |
+ flags := cmd.Flags() |
|
| 35 |
+ |
|
| 36 |
+ flags.BoolVarP(&opts.all, "all-tags", "a", false, "Download all tagged images in the repository") |
|
| 37 |
+ client.AddTrustedFlags(flags, true) |
|
| 38 |
+ |
|
| 39 |
+ return cmd |
|
| 40 |
+} |
|
| 41 |
+ |
|
| 42 |
+func runPull(dockerCli *client.DockerCli, opts pullOptions) error {
|
|
| 43 |
+ |
|
| 44 |
+ distributionRef, err := reference.ParseNamed(opts.remote) |
|
| 45 |
+ if err != nil {
|
|
| 46 |
+ return err |
|
| 47 |
+ } |
|
| 48 |
+ if opts.all && !reference.IsNameOnly(distributionRef) {
|
|
| 49 |
+ return errors.New("tag can't be used with --all-tags/-a")
|
|
| 50 |
+ } |
|
| 51 |
+ |
|
| 52 |
+ if !opts.all && reference.IsNameOnly(distributionRef) {
|
|
| 53 |
+ distributionRef = reference.WithDefaultTag(distributionRef) |
|
| 54 |
+ fmt.Fprintf(dockerCli.Out(), "Using default tag: %s\n", reference.DefaultTag) |
|
| 55 |
+ } |
|
| 56 |
+ |
|
| 57 |
+ var tag string |
|
| 58 |
+ switch x := distributionRef.(type) {
|
|
| 59 |
+ case reference.Canonical: |
|
| 60 |
+ tag = x.Digest().String() |
|
| 61 |
+ case reference.NamedTagged: |
|
| 62 |
+ tag = x.Tag() |
|
| 63 |
+ } |
|
| 64 |
+ |
|
| 65 |
+ registryRef := registry.ParseReference(tag) |
|
| 66 |
+ |
|
| 67 |
+ // Resolve the Repository name from fqn to RepositoryInfo |
|
| 68 |
+ repoInfo, err := registry.ParseRepositoryInfo(distributionRef) |
|
| 69 |
+ if err != nil {
|
|
| 70 |
+ return err |
|
| 71 |
+ } |
|
| 72 |
+ |
|
| 73 |
+ ctx := context.Background() |
|
| 74 |
+ |
|
| 75 |
+ authConfig := dockerCli.ResolveAuthConfig(ctx, repoInfo.Index) |
|
| 76 |
+ requestPrivilege := dockerCli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "pull") |
|
| 77 |
+ |
|
| 78 |
+ if client.IsTrusted() && !registryRef.HasDigest() {
|
|
| 79 |
+ // Check if tag is digest |
|
| 80 |
+ return dockerCli.TrustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege) |
|
| 81 |
+ } |
|
| 82 |
+ |
|
| 83 |
+ return dockerCli.ImagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, opts.all) |
|
| 84 |
+ |
|
| 85 |
+} |
| ... | ... |
@@ -1,74 +1,14 @@ |
| 1 | 1 |
package client |
| 2 | 2 |
|
| 3 | 3 |
import ( |
| 4 |
- "errors" |
|
| 5 |
- "fmt" |
|
| 6 |
- |
|
| 7 | 4 |
"golang.org/x/net/context" |
| 8 | 5 |
|
| 9 |
- Cli "github.com/docker/docker/cli" |
|
| 10 | 6 |
"github.com/docker/docker/pkg/jsonmessage" |
| 11 |
- flag "github.com/docker/docker/pkg/mflag" |
|
| 12 |
- "github.com/docker/docker/reference" |
|
| 13 |
- "github.com/docker/docker/registry" |
|
| 14 | 7 |
"github.com/docker/engine-api/types" |
| 15 | 8 |
) |
| 16 | 9 |
|
| 17 |
-// CmdPull pulls an image or a repository from the registry. |
|
| 18 |
-// |
|
| 19 |
-// Usage: docker pull [OPTIONS] IMAGENAME[:TAG|@DIGEST] |
|
| 20 |
-func (cli *DockerCli) CmdPull(args ...string) error {
|
|
| 21 |
- cmd := Cli.Subcmd("pull", []string{"NAME[:TAG|@DIGEST]"}, Cli.DockerCommands["pull"].Description, true)
|
|
| 22 |
- allTags := cmd.Bool([]string{"a", "-all-tags"}, false, "Download all tagged images in the repository")
|
|
| 23 |
- addTrustedFlags(cmd, true) |
|
| 24 |
- cmd.Require(flag.Exact, 1) |
|
| 25 |
- |
|
| 26 |
- cmd.ParseFlags(args, true) |
|
| 27 |
- remote := cmd.Arg(0) |
|
| 28 |
- |
|
| 29 |
- distributionRef, err := reference.ParseNamed(remote) |
|
| 30 |
- if err != nil {
|
|
| 31 |
- return err |
|
| 32 |
- } |
|
| 33 |
- if *allTags && !reference.IsNameOnly(distributionRef) {
|
|
| 34 |
- return errors.New("tag can't be used with --all-tags/-a")
|
|
| 35 |
- } |
|
| 36 |
- |
|
| 37 |
- if !*allTags && reference.IsNameOnly(distributionRef) {
|
|
| 38 |
- distributionRef = reference.WithDefaultTag(distributionRef) |
|
| 39 |
- fmt.Fprintf(cli.out, "Using default tag: %s\n", reference.DefaultTag) |
|
| 40 |
- } |
|
| 41 |
- |
|
| 42 |
- var tag string |
|
| 43 |
- switch x := distributionRef.(type) {
|
|
| 44 |
- case reference.Canonical: |
|
| 45 |
- tag = x.Digest().String() |
|
| 46 |
- case reference.NamedTagged: |
|
| 47 |
- tag = x.Tag() |
|
| 48 |
- } |
|
| 49 |
- |
|
| 50 |
- registryRef := registry.ParseReference(tag) |
|
| 51 |
- |
|
| 52 |
- // Resolve the Repository name from fqn to RepositoryInfo |
|
| 53 |
- repoInfo, err := registry.ParseRepositoryInfo(distributionRef) |
|
| 54 |
- if err != nil {
|
|
| 55 |
- return err |
|
| 56 |
- } |
|
| 57 |
- |
|
| 58 |
- ctx := context.Background() |
|
| 59 |
- |
|
| 60 |
- authConfig := cli.ResolveAuthConfig(ctx, repoInfo.Index) |
|
| 61 |
- requestPrivilege := cli.RegistryAuthenticationPrivilegedFunc(repoInfo.Index, "pull") |
|
| 62 |
- |
|
| 63 |
- if IsTrusted() && !registryRef.HasDigest() {
|
|
| 64 |
- // Check if tag is digest |
|
| 65 |
- return cli.trustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege) |
|
| 66 |
- } |
|
| 67 |
- |
|
| 68 |
- return cli.imagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, *allTags) |
|
| 69 |
-} |
|
| 70 |
- |
|
| 71 |
-func (cli *DockerCli) imagePullPrivileged(ctx context.Context, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {
|
|
| 10 |
+// ImagePullPrivileged pulls the image and displays it to the output |
|
| 11 |
+func (cli *DockerCli) ImagePullPrivileged(ctx context.Context, authConfig types.AuthConfig, ref string, requestPrivilege types.RequestPrivilegeFunc, all bool) error {
|
|
| 72 | 12 |
|
| 73 | 13 |
encodedAuth, err := EncodeAuthToBase64(authConfig) |
| 74 | 14 |
if err != nil {
|
| ... | ... |
@@ -51,7 +51,7 @@ func addTrustedFlags(fs *flag.FlagSet, verify bool) {
|
| 51 | 51 |
fs.BoolVar(&untrusted, []string{"-disable-content-trust"}, !trusted, message)
|
| 52 | 52 |
} |
| 53 | 53 |
|
| 54 |
-// AddTrustedFlags adds the trust flags to a FlagSet |
|
| 54 |
+// AddTrustedFlags adds content trust flags to the current command flagset |
|
| 55 | 55 |
func AddTrustedFlags(fs *pflag.FlagSet, verify bool) {
|
| 56 | 56 |
trusted, message := setupTrustedFlag(verify) |
| 57 | 57 |
fs.BoolVar(&untrusted, "disable-content-trust", !trusted, message) |
| ... | ... |
@@ -314,7 +314,8 @@ func notaryError(repoName string, err error) error {
|
| 314 | 314 |
return err |
| 315 | 315 |
} |
| 316 | 316 |
|
| 317 |
-func (cli *DockerCli) trustedPull(ctx context.Context, repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
|
|
| 317 |
+// TrustedPull handles content trust pulling of an image |
|
| 318 |
+func (cli *DockerCli) TrustedPull(ctx context.Context, repoInfo *registry.RepositoryInfo, ref registry.Reference, authConfig types.AuthConfig, requestPrivilege types.RequestPrivilegeFunc) error {
|
|
| 318 | 319 |
var refs []target |
| 319 | 320 |
|
| 320 | 321 |
notaryRepo, err := cli.getNotaryRepository(repoInfo, authConfig, "pull") |
| ... | ... |
@@ -376,7 +377,7 @@ func (cli *DockerCli) trustedPull(ctx context.Context, repoInfo *registry.Reposi |
| 376 | 376 |
if err != nil {
|
| 377 | 377 |
return err |
| 378 | 378 |
} |
| 379 |
- if err := cli.imagePullPrivileged(ctx, authConfig, ref.String(), requestPrivilege, false); err != nil {
|
|
| 379 |
+ if err := cli.ImagePullPrivileged(ctx, authConfig, ref.String(), requestPrivilege, false); err != nil {
|
|
| 380 | 380 |
return err |
| 381 | 381 |
} |
| 382 | 382 |
|
| ... | ... |
@@ -59,6 +59,7 @@ func NewCobraAdaptor(clientFlags *cliflags.ClientFlags) CobraAdaptor {
|
| 59 | 59 |
image.NewLoadCommand(dockerCli), |
| 60 | 60 |
image.NewRemoveCommand(dockerCli), |
| 61 | 61 |
image.NewSaveCommand(dockerCli), |
| 62 |
+ image.NewPullCommand(dockerCli), |
|
| 62 | 63 |
image.NewSearchCommand(dockerCli), |
| 63 | 64 |
image.NewImportCommand(dockerCli), |
| 64 | 65 |
image.NewTagCommand(dockerCli), |
| ... | ... |
@@ -16,7 +16,6 @@ var DockerCommandUsage = []Command{
|
| 16 | 16 |
{"login", "Log in to a Docker registry"},
|
| 17 | 17 |
{"logout", "Log out from a Docker registry"},
|
| 18 | 18 |
{"ps", "List containers"},
|
| 19 |
- {"pull", "Pull an image or a repository from a registry"},
|
|
| 20 | 19 |
{"push", "Push an image or a repository to a registry"},
|
| 21 | 20 |
{"update", "Update configuration of one or more containers"},
|
| 22 | 21 |
} |