mirror of
				https://github.com/moby/moby.git
				synced 2022-11-09 12:21:53 -05:00 
			
		
		
		
	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…
	
	Add table
		Add a link
		
	
		Reference in a new issue