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)
This commit is contained in:
parent
bb50a4159b
commit
c0b4421819
3 changed files with 43 additions and 49 deletions
|
@ -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.
|
||||
|
|
|
@ -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, ®istry.FSLayer{BlobSum: checksum})
|
||||
manifest.FSLayers = append(manifest.FSLayers, ®istry.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
|
||||
|
|
|
@ -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] = ®istry.FSLayer{BlobSum: checksum}
|
||||
m.FSLayers[i] = ®istry.FSLayer{BlobSum: dgst.String()}
|
||||
m.History[i] = ®istry.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.
|
||||
|
|
Loading…
Reference in a new issue