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>
| ... | ... |
@@ -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. |