Browse Source

Update graph to use digest type

Update get and set functions to use digests.
Update push code to use the digest type instead of string

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)
Derek McGowan 10 years ago
parent
commit
c0b4421819
3 changed files with 43 additions and 49 deletions
  1. 16 8
      graph/graph.go
  2. 15 24
      graph/manifest_test.go
  3. 12 17
      graph/push.go

+ 16 - 8
graph/graph.go

@@ -4,6 +4,7 @@ import (
 	"compress/gzip"
 	"crypto/sha256"
 	"encoding/json"
+	"errors"
 	"fmt"
 	"io"
 	"io/ioutil"
@@ -36,6 +37,13 @@ type Graph struct {
 	driver  graphdriver.Driver
 }
 
+var (
+	// ErrDigestNotSet is used when request the digest for a layer
+	// but the layer has no digest value or content to compute the
+	// the digest.
+	ErrDigestNotSet = errors.New("digest is not set for layer")
+)
+
 // NewGraph instantiates a new graph at the given root path in the filesystem.
 // `root` will be created if it doesn't exist.
 func NewGraph(root string, driver graphdriver.Driver) (*Graph, error) {
@@ -507,26 +515,26 @@ func (graph *Graph) saveSize(root string, size int) error {
 	return nil
 }
 
-// SetCheckSum sets the checksum for the image layer to the provided value.
-func (graph *Graph) SetCheckSum(id, checksum string) error {
+// SetDigest sets the digest for the image layer to the provided value.
+func (graph *Graph) SetDigest(id string, dgst digest.Digest) error {
 	root := graph.imageRoot(id)
-	if err := ioutil.WriteFile(filepath.Join(root, "checksum"), []byte(checksum), 0600); err != nil {
-		return fmt.Errorf("Error storing checksum in %s/checksum: %s", root, err)
+	if err := ioutil.WriteFile(filepath.Join(root, "checksum"), []byte(dgst.String()), 0600); err != nil {
+		return fmt.Errorf("Error storing digest in %s/checksum: %s", root, err)
 	}
 	return nil
 }
 
-// GetCheckSum gets the checksum for the provide image layer id.
-func (graph *Graph) GetCheckSum(id string) (string, error) {
+// GetDigest gets the digest for the provide image layer id.
+func (graph *Graph) GetDigest(id string) (digest.Digest, error) {
 	root := graph.imageRoot(id)
 	cs, err := ioutil.ReadFile(filepath.Join(root, "checksum"))
 	if err != nil {
 		if os.IsNotExist(err) {
-			return "", nil
+			return "", ErrDigestNotSet
 		}
 		return "", err
 	}
-	return string(cs), err
+	return digest.ParseDigest(string(cs))
 }
 
 // RawJSON returns the JSON representation for an image as a byte array.

+ 15 - 24
graph/manifest_test.go

@@ -3,14 +3,11 @@ package graph
 import (
 	"encoding/json"
 	"fmt"
-	"io"
-	"io/ioutil"
 	"os"
 	"testing"
 
 	"github.com/docker/distribution/digest"
 	"github.com/docker/docker/image"
-	"github.com/docker/docker/pkg/tarsum"
 	"github.com/docker/docker/registry"
 	"github.com/docker/docker/runconfig"
 	"github.com/docker/docker/utils"
@@ -72,11 +69,8 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
 			}
 		}
 
-		checksum, err := s.graph.GetCheckSum(layer.ID)
-		if err != nil {
-			return nil, fmt.Errorf("Error getting image checksum: %s", err)
-		}
-		if tarsum.VersionLabelForChecksum(checksum) != tarsum.Version1.String() {
+		dgst, err := s.graph.GetDigest(layer.ID)
+		if err == ErrDigestNotSet {
 			archive, err := s.graph.TarLayer(layer)
 			if err != nil {
 				return nil, err
@@ -84,20 +78,17 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
 
 			defer archive.Close()
 
-			tarSum, err := tarsum.NewTarSum(archive, true, tarsum.Version1)
+			dgst, err = digest.FromReader(archive)
 			if err != nil {
 				return nil, err
 			}
-			if _, err := io.Copy(ioutil.Discard, tarSum); err != nil {
-				return nil, err
-			}
-
-			checksum = tarSum.Sum(nil)
 
 			// Save checksum value
-			if err := s.graph.SetCheckSum(layer.ID, checksum); err != nil {
+			if err := s.graph.SetDigest(layer.ID, dgst); err != nil {
 				return nil, err
 			}
+		} else if err != nil {
+			return nil, fmt.Errorf("Error getting image checksum: %s", err)
 		}
 
 		jsonData, err := s.graph.RawJSON(layer.ID)
@@ -105,7 +96,7 @@ func (s *TagStore) newManifest(localName, remoteName, tag string) ([]byte, error
 			return nil, fmt.Errorf("Cannot retrieve the path for {%s}: %s", layer.ID, err)
 		}
 
-		manifest.FSLayers = append(manifest.FSLayers, &registry.FSLayer{BlobSum: checksum})
+		manifest.FSLayers = append(manifest.FSLayers, &registry.FSLayer{BlobSum: dgst.String()})
 
 		layersSeen[layer.ID] = true
 
@@ -141,10 +132,10 @@ func TestManifestTarsumCache(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if cs, err := store.graph.GetCheckSum(testManifestImageID); err != nil {
-		t.Fatal(err)
-	} else if cs != "" {
+	if _, err := store.graph.GetDigest(testManifestImageID); err == nil {
 		t.Fatalf("Non-empty checksum file after register")
+	} else if err != ErrDigestNotSet {
+		t.Fatal(err)
 	}
 
 	// Generate manifest
@@ -153,7 +144,7 @@ func TestManifestTarsumCache(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	manifestChecksum, err := store.graph.GetCheckSum(testManifestImageID)
+	manifestChecksum, err := store.graph.GetDigest(testManifestImageID)
 	if err != nil {
 		t.Fatal(err)
 	}
@@ -167,7 +158,7 @@ func TestManifestTarsumCache(t *testing.T) {
 		t.Fatalf("Unexpected number of layers, expecting 1: %d", len(manifest.FSLayers))
 	}
 
-	if manifest.FSLayers[0].BlobSum != manifestChecksum {
+	if manifest.FSLayers[0].BlobSum != manifestChecksum.String() {
 		t.Fatalf("Unexpected blob sum, expecting %q, got %q", manifestChecksum, manifest.FSLayers[0].BlobSum)
 	}
 
@@ -207,10 +198,10 @@ func TestManifestDigestCheck(t *testing.T) {
 		t.Fatal(err)
 	}
 
-	if cs, err := store.graph.GetCheckSum(testManifestImageID); err != nil {
-		t.Fatal(err)
-	} else if cs != "" {
+	if _, err := store.graph.GetDigest(testManifestImageID); err == nil {
 		t.Fatalf("Non-empty checksum file after register")
+	} else if err != ErrDigestNotSet {
+		t.Fatal(err)
 	}
 
 	// Generate manifest

+ 12 - 17
graph/push.go

@@ -375,18 +375,13 @@ func (s *TagStore) pushV2Repository(r *registry.Session, localRepo Repository, o
 				return fmt.Errorf("cannot retrieve the path for %s: %s", layer.ID, err)
 			}
 
-			checksum, err := s.graph.GetCheckSum(layer.ID)
-			if err != nil {
-				return fmt.Errorf("error getting image checksum: %s", err)
-			}
-
 			var exists bool
-			if len(checksum) > 0 {
-				dgst, err := digest.ParseDigest(checksum)
-				if err != nil {
-					return fmt.Errorf("Invalid checksum %s: %s", checksum, err)
+			dgst, err := s.graph.GetDigest(layer.ID)
+			if err != nil {
+				if err != ErrDigestNotSet {
+					return fmt.Errorf("error getting image checksum: %s", err)
 				}
-
+			} else {
 				// Call mount blob
 				exists, err = r.HeadV2ImageBlob(endpoint, repoInfo.RemoteName, dgst, auth)
 				if err != nil {
@@ -395,19 +390,19 @@ func (s *TagStore) pushV2Repository(r *registry.Session, localRepo Repository, o
 				}
 			}
 			if !exists {
-				if cs, err := s.pushV2Image(r, layer, endpoint, repoInfo.RemoteName, sf, out, auth); err != nil {
+				if pushDigest, err := s.pushV2Image(r, layer, endpoint, repoInfo.RemoteName, sf, out, auth); err != nil {
 					return err
-				} else if cs != checksum {
+				} else if pushDigest != dgst {
 					// Cache new checksum
-					if err := s.graph.SetCheckSum(layer.ID, cs); err != nil {
+					if err := s.graph.SetDigest(layer.ID, pushDigest); err != nil {
 						return err
 					}
-					checksum = cs
+					dgst = pushDigest
 				}
 			} else {
 				out.Write(sf.FormatProgress(stringid.TruncateID(layer.ID), "Image already exists", nil))
 			}
-			m.FSLayers[i] = &registry.FSLayer{BlobSum: checksum}
+			m.FSLayers[i] = &registry.FSLayer{BlobSum: dgst.String()}
 			m.History[i] = &registry.ManifestHistory{V1Compatibility: string(jsonData)}
 		}
 
@@ -447,7 +442,7 @@ func (s *TagStore) pushV2Repository(r *registry.Session, localRepo Repository, o
 }
 
 // PushV2Image pushes the image content to the v2 registry, first buffering the contents to disk
-func (s *TagStore) pushV2Image(r *registry.Session, img *image.Image, endpoint *registry.Endpoint, imageName string, sf *streamformatter.StreamFormatter, out io.Writer, auth *registry.RequestAuthorization) (string, error) {
+func (s *TagStore) pushV2Image(r *registry.Session, img *image.Image, endpoint *registry.Endpoint, imageName string, sf *streamformatter.StreamFormatter, out io.Writer, auth *registry.RequestAuthorization) (digest.Digest, error) {
 	out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), "Buffering to Disk", nil))
 
 	image, err := s.graph.Get(img.ID)
@@ -488,7 +483,7 @@ func (s *TagStore) pushV2Image(r *registry.Session, img *image.Image, endpoint *
 		return "", err
 	}
 	out.Write(sf.FormatProgress(stringid.TruncateID(img.ID), "Image successfully pushed", nil))
-	return dgst.String(), nil
+	return dgst, nil
 }
 
 // FIXME: Allow to interrupt current push when new push of same image is done.