Browse code

Make `docker pull` detect plugin content and error out.

Signed-off-by: Anusha Ragunathan <anusha@docker.com>

Anusha Ragunathan authored on 2016/08/11 04:04:42
Showing 5 changed files
... ...
@@ -3,6 +3,7 @@ package image
3 3
 import (
4 4
 	"errors"
5 5
 	"fmt"
6
+	"strings"
6 7
 
7 8
 	"golang.org/x/net/context"
8 9
 
... ...
@@ -77,9 +78,16 @@ func runPull(dockerCli *client.DockerCli, opts pullOptions) error {
77 77
 
78 78
 	if client.IsTrusted() && !registryRef.HasDigest() {
79 79
 		// Check if tag is digest
80
-		return dockerCli.TrustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege)
80
+		err = dockerCli.TrustedPull(ctx, repoInfo, registryRef, authConfig, requestPrivilege)
81
+	} else {
82
+		err = dockerCli.ImagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, opts.all)
83
+	}
84
+	if err != nil {
85
+		if strings.Contains(err.Error(), "target is a plugin") {
86
+			return errors.New(err.Error() + " - Use `docker plugin install`")
87
+		}
88
+		return err
81 89
 	}
82 90
 
83
-	return dockerCli.ImagePullPrivileged(ctx, authConfig, distributionRef.String(), requestPrivilege, opts.all)
84
-
91
+	return nil
85 92
 }
... ...
@@ -32,7 +32,11 @@ import (
32 32
 	"golang.org/x/net/context"
33 33
 )
34 34
 
35
-var errRootFSMismatch = errors.New("layers from manifest don't match image configuration")
35
+var (
36
+	errRootFSMismatch  = errors.New("layers from manifest don't match image configuration")
37
+	errMediaTypePlugin = errors.New("target is a plugin")
38
+	errRootFSInvalid   = errors.New("invalid rootfs in image configuration")
39
+)
36 40
 
37 41
 // ImageConfigPullError is an error pulling the image config blob
38 42
 // (only applies to schema2).
... ...
@@ -356,6 +360,12 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
356 356
 		return false, fmt.Errorf("image manifest does not exist for tag or digest %q", tagOrDigest)
357 357
 	}
358 358
 
359
+	if m, ok := manifest.(*schema2.DeserializedManifest); ok {
360
+		if m.Manifest.Config.MediaType == schema2.MediaTypePluginConfig {
361
+			return false, errMediaTypePlugin
362
+		}
363
+	}
364
+
359 365
 	// If manSvc.Get succeeded, we can be confident that the registry on
360 366
 	// the other side speaks the v2 protocol.
361 367
 	p.confirmedV2 = true
... ...
@@ -574,6 +584,10 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
574 574
 		}
575 575
 	}
576 576
 
577
+	if unmarshalledConfig.RootFS == nil {
578
+		return "", "", errRootFSInvalid
579
+	}
580
+
577 581
 	// The DiffIDs returned in rootFS MUST match those in the config.
578 582
 	// Otherwise the image config could be referencing layers that aren't
579 583
 	// included in the manifest.
... ...
@@ -143,7 +143,7 @@ func Pull(name string, rs registry.Service, metaheader http.Header, authConfig *
143 143
 		logrus.Debugf("pull.go: error in json.Unmarshal(): %v", err)
144 144
 		return nil, err
145 145
 	}
146
-	if m.Config.MediaType != MediaTypeConfig {
146
+	if m.Config.MediaType != schema2.MediaTypePluginConfig {
147 147
 		return nil, ErrUnsupportedMediaType
148 148
 	}
149 149
 
... ...
@@ -79,9 +79,9 @@ func Push(name string, rs registry.Service, metaHeader http.Header, authConfig *
79 79
 			return "", err
80 80
 		}
81 81
 		f.Close()
82
-		mt := MediaTypeLayer
82
+		mt := schema2.MediaTypeLayer
83 83
 		if i == 0 {
84
-			mt = MediaTypeConfig
84
+			mt = schema2.MediaTypePluginConfig
85 85
 		}
86 86
 		// Commit completes the write process to the BlobService.
87 87
 		// The descriptor arg to Commit is called the "provisional" descriptor and
... ...
@@ -10,10 +10,5 @@ var ErrUnsupportedRegistry = errors.New("only V2 repositories are supported for
10 10
 // ErrUnsupportedMediaType indicates we are pulling content that's not a plugin
11 11
 var ErrUnsupportedMediaType = errors.New("content is not a plugin")
12 12
 
13
-// Plugin related media types
14
-const (
15
-	MediaTypeManifest = "application/vnd.docker.distribution.manifest.v2+json"
16
-	MediaTypeConfig   = "application/vnd.docker.plugin.v0+json"
17
-	MediaTypeLayer    = "application/vnd.docker.image.rootfs.diff.tar.gzip"
18
-	DefaultTag        = "latest"
19
-)
13
+// DefaultTag is the default tag for plugins
14
+const DefaultTag = "latest"