Переглянути джерело

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 9 роки тому
батько
коміт
16e4c4e481

+ 12 - 11
api/client/create.go

@@ -92,21 +92,22 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
 		defer containerIDFile.Close()
 	}
 
-	ref, err := reference.ParseNamed(config.Image)
+	var trustedRef reference.Canonical
+	_, ref, err := reference.ParseIDOrReference(config.Image)
 	if err != nil {
 		return nil, err
 	}
-	ref = reference.WithDefaultTag(ref)
-
-	var trustedRef reference.Canonical
+	if ref != nil {
+		ref = reference.WithDefaultTag(ref)
 
-	if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
-		var err error
-		trustedRef, err = cli.trustedReference(ref)
-		if err != nil {
-			return nil, err
+		if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
+			var err error
+			trustedRef, err = cli.trustedReference(ref)
+			if err != nil {
+				return nil, err
+			}
+			config.Image = trustedRef.String()
 		}
-		config.Image = trustedRef.String()
 	}
 
 	//create the container
@@ -114,7 +115,7 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
 
 	//if image not found try to pull it
 	if err != nil {
-		if client.IsErrImageNotFound(err) {
+		if client.IsErrImageNotFound(err) && ref != nil {
 			fmt.Fprintf(cli.err, "Unable to find image '%s' locally\n", ref.String())
 
 			// we don't want to write to stdout anything apart from container.ID

+ 13 - 14
daemon/daemon.go

@@ -20,7 +20,6 @@ import (
 	"time"
 
 	"github.com/Sirupsen/logrus"
-	"github.com/docker/distribution/digest"
 	"github.com/docker/docker/api"
 	"github.com/docker/docker/builder"
 	"github.com/docker/docker/container"
@@ -1267,25 +1266,25 @@ func (daemon *Daemon) ImageHistory(name string) ([]*types.ImageHistory, error) {
 // GetImageID returns an image ID corresponding to the image referred to by
 // refOrID.
 func (daemon *Daemon) GetImageID(refOrID string) (image.ID, error) {
-	// Treat as an ID
-	if id, err := digest.ParseDigest(refOrID); err == nil {
+	id, ref, err := reference.ParseIDOrReference(refOrID)
+	if err != nil {
+		return "", err
+	}
+	if id != "" {
 		if _, err := daemon.imageStore.Get(image.ID(id)); err != nil {
 			return "", ErrImageDoesNotExist{refOrID}
 		}
 		return image.ID(id), nil
 	}
 
-	// Treat it as a possible tag or digest reference
-	if ref, err := reference.ParseNamed(refOrID); err == nil {
-		if id, err := daemon.referenceStore.Get(ref); err == nil {
-			return id, nil
-		}
-		if tagged, ok := ref.(reference.NamedTagged); ok {
-			if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil {
-				for _, namedRef := range daemon.referenceStore.References(id) {
-					if namedRef.Name() == ref.Name() {
-						return id, nil
-					}
+	if id, err := daemon.referenceStore.Get(ref); err == nil {
+		return id, nil
+	}
+	if tagged, ok := ref.(reference.NamedTagged); ok {
+		if id, err := daemon.imageStore.Search(tagged.Tag()); err == nil {
+			for _, namedRef := range daemon.referenceStore.References(id) {
+				if namedRef.Name() == ref.Name() {
+					return id, nil
 				}
 			}
 		}

+ 9 - 1
image/tarexport/save.go

@@ -70,10 +70,18 @@ func (l *tarexporter) parseNames(names []string) (map[image.ID]*imageDescriptor,
 	}
 
 	for _, name := range names {
-		ref, err := reference.ParseNamed(name)
+		id, ref, err := reference.ParseIDOrReference(name)
 		if err != nil {
 			return nil, err
 		}
+		if id != "" {
+			_, err := l.is.Get(image.ID(id))
+			if err != nil {
+				return nil, err
+			}
+			addAssoc(image.ID(id), nil)
+			continue
+		}
 		if ref.Name() == string(digest.Canonical) {
 			imgID, err := l.is.Search(name)
 			if err != nil {

+ 8 - 0
integration-cli/docker_cli_create_test.go

@@ -450,3 +450,11 @@ func (s *DockerSuite) TestCreateWithInvalidLogOpts(c *check.C) {
 	out, _ = dockerCmd(c, "ps", "-a")
 	c.Assert(out, checker.Not(checker.Contains), name)
 }
+
+// #20972
+func (s *DockerSuite) TestCreate64ByteHexID(c *check.C) {
+	out := inspectField(c, "busybox", "Id")
+	imageID := strings.TrimPrefix(strings.TrimSpace(string(out)), "sha256:")
+
+	dockerCmd(c, "create", imageID)
+}

+ 13 - 0
reference/reference.go

@@ -155,6 +155,19 @@ func IsNameOnly(ref Named) bool {
 	return true
 }
 
+// ParseIDOrReference parses string for a image ID or a reference. ID can be
+// without a default prefix.
+func ParseIDOrReference(idOrRef string) (digest.Digest, Named, error) {
+	if err := v1.ValidateID(idOrRef); err == nil {
+		idOrRef = "sha256:" + idOrRef
+	}
+	if dgst, err := digest.ParseDigest(idOrRef); err == nil {
+		return dgst, nil, nil
+	}
+	ref, err := ParseNamed(idOrRef)
+	return "", ref, err
+}
+
 // splitHostname splits a repository name to hostname and remotename string.
 // If no valid hostname is found, the default hostname is used. Repository name
 // needs to be already validated before.