Browse code

Fix docker run for 64 byte hex ID

Fixes #20972

Also makes sure there is no check to registry if
no image is found for the prefixed IDs.

Signed-off-by: Tonis Tiigi <tonistiigi@gmail.com>

Tonis Tiigi authored on 2016/03/08 03:56:24
Showing 5 changed files
... ...
@@ -92,21 +92,22 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
92 92
 		defer containerIDFile.Close()
93 93
 	}
94 94
 
95
-	ref, err := reference.ParseNamed(config.Image)
95
+	var trustedRef reference.Canonical
96
+	_, ref, err := reference.ParseIDOrReference(config.Image)
96 97
 	if err != nil {
97 98
 		return nil, err
98 99
 	}
99
-	ref = reference.WithDefaultTag(ref)
100
-
101
-	var trustedRef reference.Canonical
100
+	if ref != nil {
101
+		ref = reference.WithDefaultTag(ref)
102 102
 
103
-	if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
104
-		var err error
105
-		trustedRef, err = cli.trustedReference(ref)
106
-		if err != nil {
107
-			return nil, err
103
+		if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
104
+			var err error
105
+			trustedRef, err = cli.trustedReference(ref)
106
+			if err != nil {
107
+				return nil, err
108
+			}
109
+			config.Image = trustedRef.String()
108 110
 		}
109
-		config.Image = trustedRef.String()
110 111
 	}
111 112
 
112 113
 	//create the container
... ...
@@ -114,7 +115,7 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
114 114
 
115 115
 	//if image not found try to pull it
116 116
 	if err != nil {
117
-		if client.IsErrImageNotFound(err) {
117
+		if client.IsErrImageNotFound(err) && ref != nil {
118 118
 			fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String())
119 119
 
120 120
 			// we don't want to write to stdout anything apart from container.ID
... ...
@@ -20,7 +20,6 @@ import (
20 20
 	"time"
21 21
 
22 22
 	"github.com/Sirupsen/logrus"
23
-	"github.com/docker/distribution/digest"
24 23
 	"github.com/docker/docker/api"
25 24
 	"github.com/docker/docker/builder"
26 25
 	"github.com/docker/docker/container"
... ...
@@ -1267,25 +1266,25 @@ func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) {
1267 1267
 // GetImageID returns an image ID corresponding to the image referred to by
1268 1268
 // refOrID.
1269 1269
 func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) {
1270
-	// Treat as an ID
1271
-	if id, err := digest.ParseDigest(refOrID); err == nil {
1270
+	id, ref, err := reference.ParseIDOrReference(refOrID)
1271
+	if err != nil {
1272
+		return "", err
1273
+	}
1274
+	if id != "" {
1272 1275
 		if _, err := daemon.imageStore.Get(image.ID(id)); err != nil {
1273 1276
 			return "", ErrImageDoesNotExist{refOrID}
1274 1277
 		}
1275 1278
 		return image.ID(id), nil
1276 1279
 	}
1277 1280
 
1278
-	// Treat it as a possible tag or digest reference
1279
-	if ref, err := reference.ParseNamed(refOrID); err == nil {
1280
-		if id, err := daemon.referenceStore.Get(ref); err == nil {
1281
-			return id, nil
1282
-		}
1283
-		if tagged, ok := ref.(reference.NamedTagged); ok {
1284
-			if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil {
1285
-				for _, namedRef := range daemon.referenceStore.References(id) {
1286
-					if namedRef.Name() == ref.Name() {
1287
-						return id, nil
1288
-					}
1281
+	if id, err := daemon.referenceStore.Get(ref); err == nil {
1282
+		return id, nil
1283
+	}
1284
+	if tagged, ok := ref.(reference.NamedTagged); ok {
1285
+		if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil {
1286
+			for _, namedRef := range daemon.referenceStore.References(id) {
1287
+				if namedRef.Name() == ref.Name() {
1288
+					return id, nil
1289 1289
 				}
1290 1290
 			}
1291 1291
 		}
... ...
@@ -70,10 +70,18 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
70 70
 	}
71 71
 
72 72
 	for _, name := range names {
73
-		ref, err := reference.ParseNamed(name)
73
+		id, ref, err := reference.ParseIDOrReference(name)
74 74
 		if err != nil {
75 75
 			return nil, err
76 76
 		}
77
+		if id != "" {
78
+			_, err := l.is.Get(image.ID(id))
79
+			if err != nil {
80
+				return nil, err
81
+			}
82
+			addAssoc(image.ID(id), nil)
83
+			continue
84
+		}
77 85
 		if ref.Name() == string(digest.Canonical) {
78 86
 			imgID, err := l.is.Search(name)
79 87
 			if err != nil {
... ...
@@ -450,3 +450,11 @@ func (s *DockerSuite) TestCreateWithInvalidLogOpts(c *check.C) {
450 450
 	out, _ = dockerCmd(c, "ps", "-a")
451 451
 	c.Assert(out, checker.Not(checker.Contains), name)
452 452
 }
453
+
454
+// #20972
455
+func (s *DockerSuite) TestCreate64ByteHexID(c *check.C) {
456
+	out := inspectField(c, "busybox", "Id")
457
+	imageID := strings.TrimPrefix(strings.TrimSpace(string(out)), "sha256:")
458
+
459
+	dockerCmd(c, "create", imageID)
460
+}
... ...
@@ -155,6 +155,19 @@ func IsNameOnly(ref Named) bool {
155 155
 	return true
156 156
 }
157 157
 
158
+// ParseIDOrReference parses string for a image ID or a reference. ID can be
159
+// without a default prefix.
160
+func ParseIDOrReference(idOrRef string) (digest.Digest, Named, error) {
161
+	if err := v1.ValidateID(idOrRef); err == nil {
162
+		idOrRef = "sha256:" + idOrRef
163
+	}
164
+	if dgst, err := digest.ParseDigest(idOrRef); err == nil {
165
+		return dgst, nil, nil
166
+	}
167
+	ref, err := ParseNamed(idOrRef)
168
+	return "", ref, err
169
+}
170
+
158 171
 // splitHostname splits a repository name to hostname and remotename string.
159 172
 // If no valid hostname is found, the default hostname is used. Repository name
160 173
 // needs to be already validated before.