Browse code

Always store the image digest when pulling and pushing an image.

Always attempt to add digest even when tag already exists.
Ensure digest does not currently exist.
When image id is mismatched, output an error log.

Signed-off-by: Daniel Nephin <dnephin@docker.com>
Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
(cherry picked from commit 33984f256b1a281b1130ac7e8edb7bc311750ccf)
Signed-off-by: Tibor Vass <tibor@docker.com>

Derek McGowan authored on 2016/06/28 02:09:57
Showing 4 changed files
... ...
@@ -4,6 +4,7 @@ import (
4 4
 	"fmt"
5 5
 
6 6
 	"github.com/Sirupsen/logrus"
7
+	"github.com/docker/distribution/digest"
7 8
 	"github.com/docker/docker/api"
8 9
 	"github.com/docker/docker/distribution/metadata"
9 10
 	"github.com/docker/docker/distribution/xfer"
... ...
@@ -203,3 +204,22 @@ func ValidateRepoName(name string) error {
203 203
 	}
204 204
 	return nil
205 205
 }
206
+
207
+func addDigestReference(store reference.Store, ref reference.Named, dgst digest.Digest, imageID image.ID) error {
208
+	dgstRef, err := reference.WithDigest(ref, dgst)
209
+	if err != nil {
210
+		return err
211
+	}
212
+
213
+	if oldTagImageID, err := store.Get(dgstRef); err == nil {
214
+		if oldTagImageID != imageID {
215
+			// Updating digests not supported by reference store
216
+			logrus.Errorf("Image ID for digest %s changed from %s to %s, cannot update", dgst.String(), oldTagImageID, imageID)
217
+		}
218
+		return nil
219
+	} else if err != reference.ErrDoesNotExist {
220
+		return err
221
+	}
222
+
223
+	return store.AddDigest(dgstRef, imageID, true)
224
+}
... ...
@@ -393,7 +393,7 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
393 393
 	oldTagImageID, err := p.config.ReferenceStore.Get(ref)
394 394
 	if err == nil {
395 395
 		if oldTagImageID == imageID {
396
-			return false, nil
396
+			return false, addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID)
397 397
 		}
398 398
 	} else if err != reference.ErrDoesNotExist {
399 399
 		return false, err
... ...
@@ -403,10 +403,14 @@ func (p *v2Puller) pullV2Tag(ctx context.Context, ref reference.Named) (tagUpdat
403 403
 		if err = p.config.ReferenceStore.AddDigest(canonical, imageID, true); err != nil {
404 404
 			return false, err
405 405
 		}
406
-	} else if err = p.config.ReferenceStore.AddTag(ref, imageID, true); err != nil {
407
-		return false, err
406
+	} else {
407
+		if err = addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID); err != nil {
408
+			return false, err
409
+		}
410
+		if err = p.config.ReferenceStore.AddTag(ref, imageID, true); err != nil {
411
+			return false, err
412
+		}
408 413
 	}
409
-
410 414
 	return true, nil
411 415
 }
412 416
 
... ...
@@ -200,6 +200,11 @@ func (p *v2Pusher) pushV2Tag(ctx context.Context, ref reference.NamedTagged, ima
200 200
 
201 201
 	manifestDigest := digest.FromBytes(canonicalManifest)
202 202
 	progress.Messagef(p.config.ProgressOutput, "", "%s: digest: %s size: %d", ref.Tag(), manifestDigest, len(canonicalManifest))
203
+
204
+	if err := addDigestReference(p.config.ReferenceStore, ref, manifestDigest, imageID); err != nil {
205
+		return err
206
+	}
207
+
203 208
 	// Signal digest to the trust client so it can sign the
204 209
 	// push, if appropriate.
205 210
 	progress.Aux(p.config.ProgressOutput, PushResult{Tag: ref.Tag(), Digest: manifestDigest, Size: len(canonicalManifest)})
... ...
@@ -287,7 +287,7 @@ func (s *DockerTrustSuite) TestTrustedPush(c *check.C) {
287 287
 	s.trustedCmd(pullCmd)
288 288
 	out, _, err = runCommandWithOutput(pullCmd)
289 289
 	c.Assert(err, check.IsNil, check.Commentf(out))
290
-	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
290
+	c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out))
291 291
 
292 292
 	// Assert that we rotated the snapshot key to the server by checking our local keystore
293 293
 	contents, err := ioutil.ReadDir(filepath.Join(cliconfig.ConfigDir(), "trust/private/tuf_keys", privateRegistryURL, "dockerclitrusted/pushtest"))
... ...
@@ -312,7 +312,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithEnvPasswords(c *check.C) {
312 312
 	s.trustedCmd(pullCmd)
313 313
 	out, _, err = runCommandWithOutput(pullCmd)
314 314
 	c.Assert(err, check.IsNil, check.Commentf(out))
315
-	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
315
+	c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out))
316 316
 }
317 317
 
318 318
 func (s *DockerTrustSuite) TestTrustedPushWithFailingServer(c *check.C) {
... ...
@@ -358,7 +358,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithExistingTag(c *check.C) {
358 358
 	s.trustedCmd(pullCmd)
359 359
 	out, _, err = runCommandWithOutput(pullCmd)
360 360
 	c.Assert(err, check.IsNil, check.Commentf(out))
361
-	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
361
+	c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out))
362 362
 }
363 363
 
364 364
 func (s *DockerTrustSuite) TestTrustedPushWithExistingSignedTag(c *check.C) {
... ...
@@ -492,7 +492,7 @@ func (s *DockerTrustSuite) TestTrustedPushWithReleasesDelegationOnly(c *check.C)
492 492
 	s.trustedCmd(pullCmd)
493 493
 	out, _, err = runCommandWithOutput(pullCmd)
494 494
 	c.Assert(err, check.IsNil, check.Commentf(out))
495
-	c.Assert(string(out), checker.Contains, "Status: Downloaded", check.Commentf(out))
495
+	c.Assert(string(out), checker.Contains, "Status: Image is up to date", check.Commentf(out))
496 496
 }
497 497
 
498 498
 func (s *DockerTrustSuite) TestTrustedPushSignsAllFirstLevelRolesWeHaveKeysFor(c *check.C) {