Browse code

reference: Handle combination of tag and digest in AddReference

With the switchover to the unified reference package, AddReference no
longer does the right thing when passed a reference that has both a
digest and a tag. It would put both the digest in the tag in the
reference stored in the repositories.json file, which isn't the right
format, and would mean that neither "docker run" nor docker services
could locate the image. This meant that a simple "docker service create"
command like "docker service create --name foo busybox top" would create
a service that immediately went into a restart loop, because it couldn't
use the image that had been pulled.

Fix AddReference to strip out the tag when both a tag and digest are
specified. We do this because we don't necessarily want to overwrite the
tag - when both a digest and tag are specified, the tag is only
advisory.

Signed-off-by: Aaron Lehmann <aaron.lehmann@docker.com>

Aaron Lehmann authored on 2017/02/10 09:30:46
Showing 1 changed files
... ...
@@ -107,6 +107,20 @@ func (store *store) AddDigest(ref reference.Canonical, id digest.Digest, force b
107 107
 }
108 108
 
109 109
 func (store *store) addReference(ref reference.Named, id digest.Digest, force bool) error {
110
+	// If the reference includes a digest and a tag, we must store only the
111
+	// digest.
112
+	canonical, isCanonical := ref.(reference.Canonical)
113
+	_, isNamedTagged := ref.(reference.NamedTagged)
114
+
115
+	if isCanonical && isNamedTagged {
116
+		trimmed, err := reference.WithDigest(reference.TrimNamed(canonical), canonical.Digest())
117
+		if err != nil {
118
+			// should never happen
119
+			return err
120
+		}
121
+		ref = trimmed
122
+	}
123
+
110 124
 	refName := reference.FamiliarName(ref)
111 125
 	refStr := reference.FamiliarString(ref)
112 126