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>
This commit is contained in:
Tonis Tiigi 2016-03-07 10:56:24 -08:00
parent bc730f3d99
commit 16e4c4e481
5 changed files with 55 additions and 26 deletions

View File

@ -92,21 +92,22 @@ func (cli *DockerCli) createContainer(config *container.Config, hostConfig *cont
defer containerIDFile.Close() defer containerIDFile.Close()
} }
ref, err := reference.ParseNamed(config.Image) var trustedRef reference.Canonical
_, ref, err := reference.ParseIDOrReference(config.Image)
if err != nil { if err != nil {
return nil, err return nil, err
} }
ref = reference.WithDefaultTag(ref) if ref != nil {
ref = reference.WithDefaultTag(ref)
var trustedRef reference.Canonical if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() {
var err error
if ref, ok := ref.(reference.NamedTagged); ok && isTrusted() { trustedRef, err = cli.trustedReference(ref)
var err error if err != nil {
trustedRef, err = cli.trustedReference(ref) return nil, err
if err != nil { }
return nil, err config.Image = trustedRef.String()
} }
config.Image = trustedRef.String()
} }
//create the container //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 image not found try to pull it
if err != nil { 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()) 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 // we don't want to write to stdout anything apart from container.ID

View File

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

View File

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

View File

@ -450,3 +450,11 @@ func (s *DockerSuite) TestCreateWithInvalidLogOpts(c *check.C) {
out, _ = dockerCmd(c, "ps", "-a") out, _ = dockerCmd(c, "ps", "-a")
c.Assert(out, checker.Not(checker.Contains), name) 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)
}

View File

@ -155,6 +155,19 @@ func IsNameOnly(ref Named) bool {
return true 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. // splitHostname splits a repository name to hostname and remotename string.
// If no valid hostname is found, the default hostname is used. Repository name // If no valid hostname is found, the default hostname is used. Repository name
// needs to be already validated before. // needs to be already validated before.