Move layer interface definitions to distribution package
After consideration, it has been decided that the interfaces defined in the storage package provide a good base for interacting with various registry instances. Whether interacting with a remote API or a local, on-disk registry, these types have proved flexible. By moving them here, they can become the central components of interacting with distribution components. Signed-off-by: Stephen J Day <stephen.day@docker.com>master
							parent
							
								
									5a0f1ceeef
								
							
						
					
					
						commit
						553d48d618
					
				| 
						 | 
				
			
			@ -7,8 +7,10 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
 | 
			
		||||
	"code.google.com/p/go-uuid/uuid"
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	"github.com/docker/distribution/configuration"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/notifications"
 | 
			
		||||
	"github.com/docker/distribution/registry/api/v2"
 | 
			
		||||
	"github.com/docker/distribution/registry/auth"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
| 
						 | 
				
			
			@ -32,7 +34,7 @@ type App struct {
 | 
			
		|||
 | 
			
		||||
	router           *mux.Router                 // main application router, configured with dispatchers
 | 
			
		||||
	driver           storagedriver.StorageDriver // driver maintains the app global storage driver instance.
 | 
			
		||||
	registry         storage.Registry            // registry is the primary registry backend for the app instance.
 | 
			
		||||
	registry         distribution.Registry       // registry is the primary registry backend for the app instance.
 | 
			
		||||
	accessController auth.AccessController       // main access controller for application
 | 
			
		||||
 | 
			
		||||
	// events contains notification related configuration.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,10 +4,10 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/registry/api/v2"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -21,7 +21,7 @@ type Context struct {
 | 
			
		|||
 | 
			
		||||
	// Repository is the repository for the current request. All requests
 | 
			
		||||
	// should be scoped to a single repository. This field may be nil.
 | 
			
		||||
	Repository storage.Repository
 | 
			
		||||
	Repository distribution.Repository
 | 
			
		||||
 | 
			
		||||
	// Errors is a collection of errors encountered during the request to be
 | 
			
		||||
	// returned to the client API. If errors are added to the collection, the
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
| 
						 | 
				
			
			@ -72,7 +73,7 @@ func (imh *imageManifestHandler) PutImageManifest(w http.ResponseWriter, r *http
 | 
			
		|||
		case storage.ErrManifestVerification:
 | 
			
		||||
			for _, verificationError := range err {
 | 
			
		||||
				switch verificationError := verificationError.(type) {
 | 
			
		||||
				case storage.ErrUnknownLayer:
 | 
			
		||||
				case distribution.ErrUnknownLayer:
 | 
			
		||||
					imh.Errors.Push(v2.ErrorCodeBlobUnknown, verificationError.FSLayer)
 | 
			
		||||
				case storage.ErrManifestUnverified:
 | 
			
		||||
					imh.Errors.Push(v2.ErrorCodeManifestUnverified)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,10 +3,10 @@ package handlers
 | 
			
		|||
import (
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/registry/api/v2"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
	"github.com/gorilla/handlers"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -54,7 +54,7 @@ func (lh *layerHandler) GetLayer(w http.ResponseWriter, r *http.Request) {
 | 
			
		|||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		switch err := err.(type) {
 | 
			
		||||
		case storage.ErrUnknownLayer:
 | 
			
		||||
		case distribution.ErrUnknownLayer:
 | 
			
		||||
			w.WriteHeader(http.StatusNotFound)
 | 
			
		||||
			lh.Errors.Push(v2.ErrorCodeBlobUnknown, err.FSLayer)
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,10 +7,10 @@ import (
 | 
			
		|||
	"net/url"
 | 
			
		||||
	"os"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/registry/api/v2"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
	"github.com/gorilla/handlers"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ func layerUploadDispatcher(ctx *Context, r *http.Request) http.Handler {
 | 
			
		|||
		upload, err := layers.Resume(luh.UUID)
 | 
			
		||||
		if err != nil {
 | 
			
		||||
			ctxu.GetLogger(ctx).Errorf("error resolving upload: %v", err)
 | 
			
		||||
			if err == storage.ErrLayerUploadUnknown {
 | 
			
		||||
			if err == distribution.ErrLayerUploadUnknown {
 | 
			
		||||
				return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
			
		||||
					w.WriteHeader(http.StatusNotFound)
 | 
			
		||||
					luh.Errors.Push(v2.ErrorCodeBlobUploadUnknown, err)
 | 
			
		||||
| 
						 | 
				
			
			@ -114,7 +114,7 @@ type layerUploadHandler struct {
 | 
			
		|||
	// UUID identifies the upload instance for the current request.
 | 
			
		||||
	UUID string
 | 
			
		||||
 | 
			
		||||
	Upload storage.LayerUpload
 | 
			
		||||
	Upload distribution.LayerUpload
 | 
			
		||||
 | 
			
		||||
	State layerUploadState
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -196,7 +196,7 @@ func (luh *layerUploadHandler) PutLayerUploadComplete(w http.ResponseWriter, r *
 | 
			
		|||
	layer, err := luh.Upload.Finish(dgst)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		switch err := err.(type) {
 | 
			
		||||
		case storage.ErrLayerInvalidDigest:
 | 
			
		||||
		case distribution.ErrLayerInvalidDigest:
 | 
			
		||||
			w.WriteHeader(http.StatusBadRequest)
 | 
			
		||||
			luh.Errors.Push(v2.ErrorCodeDigestInvalid, err)
 | 
			
		||||
		default:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -10,6 +10,7 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/AdRoll/goamz/cloudfront"
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	storagedriver "github.com/docker/distribution/registry/storage/driver"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -95,7 +96,7 @@ func newCloudFrontLayerHandler(storageDriver storagedriver.StorageDriver, option
 | 
			
		|||
 | 
			
		||||
// Resolve returns an http.Handler which can serve the contents of the given
 | 
			
		||||
// Layer, or an error if not supported by the storagedriver.
 | 
			
		||||
func (lh *cloudFrontLayerHandler) Resolve(layer Layer) (http.Handler, error) {
 | 
			
		||||
func (lh *cloudFrontLayerHandler) Resolve(layer distribution.Layer) (http.Handler, error) {
 | 
			
		||||
	layerURLStr, err := lh.delegateLayerHandler.urlFor(layer, nil)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	storagedriver "github.com/docker/distribution/registry/storage/driver"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -40,7 +41,7 @@ func newDelegateLayerHandler(storageDriver storagedriver.StorageDriver, options
 | 
			
		|||
 | 
			
		||||
// Resolve returns an http.Handler which can serve the contents of the given
 | 
			
		||||
// Layer, or an error if not supported by the storagedriver.
 | 
			
		||||
func (lh *delegateLayerHandler) Resolve(layer Layer) (http.Handler, error) {
 | 
			
		||||
func (lh *delegateLayerHandler) Resolve(layer distribution.Layer) (http.Handler, error) {
 | 
			
		||||
	// TODO(bbland): This is just a sanity check to ensure that the
 | 
			
		||||
	// storagedriver supports url generation. It would be nice if we didn't have
 | 
			
		||||
	// to do this twice for non-GET requests.
 | 
			
		||||
| 
						 | 
				
			
			@ -64,7 +65,7 @@ func (lh *delegateLayerHandler) Resolve(layer Layer) (http.Handler, error) {
 | 
			
		|||
 | 
			
		||||
// urlFor returns a download URL for the given layer, or the empty string if
 | 
			
		||||
// unsupported.
 | 
			
		||||
func (lh *delegateLayerHandler) urlFor(layer Layer, options map[string]interface{}) (string, error) {
 | 
			
		||||
func (lh *delegateLayerHandler) urlFor(layer distribution.Layer, options map[string]interface{}) (string, error) {
 | 
			
		||||
	// Crack open the layer to get at the layerStore
 | 
			
		||||
	layerRd, ok := layer.(*layerReader)
 | 
			
		||||
	if !ok {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -125,23 +125,8 @@ func (fr *fileReader) Seek(offset int64, whence int) (int64, error) {
 | 
			
		|||
	return fr.offset, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close the layer. Should be called when the resource is no longer needed.
 | 
			
		||||
func (fr *fileReader) Close() error {
 | 
			
		||||
	if fr.err != nil {
 | 
			
		||||
		return fr.err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fr.err = ErrLayerClosed
 | 
			
		||||
 | 
			
		||||
	// close and release reader chain
 | 
			
		||||
	if fr.rc != nil {
 | 
			
		||||
		fr.rc.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fr.rc = nil
 | 
			
		||||
	fr.brd = nil
 | 
			
		||||
 | 
			
		||||
	return fr.err
 | 
			
		||||
	return fr.closeWithErr(fmt.Errorf("fileReader: closed"))
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// reader prepares the current reader at the lrs offset, ensuring its buffered
 | 
			
		||||
| 
						 | 
				
			
			@ -199,3 +184,21 @@ func (fr *fileReader) reset() {
 | 
			
		|||
		fr.rc = nil
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (fr *fileReader) closeWithErr(err error) error {
 | 
			
		||||
	if fr.err != nil {
 | 
			
		||||
		return fr.err
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fr.err = err
 | 
			
		||||
 | 
			
		||||
	// close and release reader chain
 | 
			
		||||
	if fr.rc != nil {
 | 
			
		||||
		fr.rc.Close()
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	fr.rc = nil
 | 
			
		||||
	fr.brd = nil
 | 
			
		||||
 | 
			
		||||
	return fr.err
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,90 +0,0 @@
 | 
			
		|||
package storage
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"fmt"
 | 
			
		||||
	"io"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// Layer provides a readable and seekable layer object. Typically,
 | 
			
		||||
// implementations are *not* goroutine safe.
 | 
			
		||||
type Layer interface {
 | 
			
		||||
	// http.ServeContent requires an efficient implementation of
 | 
			
		||||
	// ReadSeeker.Seek(0, os.SEEK_END).
 | 
			
		||||
	io.ReadSeeker
 | 
			
		||||
	io.Closer
 | 
			
		||||
 | 
			
		||||
	// Name returns the repository under which this layer is linked.
 | 
			
		||||
	Name() string // TODO(stevvooe): struggling with nomenclature: should this be "repo" or "name"?
 | 
			
		||||
 | 
			
		||||
	// Digest returns the unique digest of the blob, which is the tarsum for
 | 
			
		||||
	// layers.
 | 
			
		||||
	Digest() digest.Digest
 | 
			
		||||
 | 
			
		||||
	// CreatedAt returns the time this layer was created.
 | 
			
		||||
	CreatedAt() time.Time
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LayerUpload provides a handle for working with in-progress uploads.
 | 
			
		||||
// Instances can be obtained from the LayerService.Upload and
 | 
			
		||||
// LayerService.Resume.
 | 
			
		||||
type LayerUpload interface {
 | 
			
		||||
	io.WriteSeeker
 | 
			
		||||
	io.ReaderFrom
 | 
			
		||||
	io.Closer
 | 
			
		||||
 | 
			
		||||
	// Name of the repository under which the layer will be linked.
 | 
			
		||||
	Name() string
 | 
			
		||||
 | 
			
		||||
	// UUID returns the identifier for this upload.
 | 
			
		||||
	UUID() string
 | 
			
		||||
 | 
			
		||||
	// StartedAt returns the time this layer upload was started.
 | 
			
		||||
	StartedAt() time.Time
 | 
			
		||||
 | 
			
		||||
	// Finish marks the upload as completed, returning a valid handle to the
 | 
			
		||||
	// uploaded layer. The digest is validated against the contents of the
 | 
			
		||||
	// uploaded layer.
 | 
			
		||||
	Finish(digest digest.Digest) (Layer, error)
 | 
			
		||||
 | 
			
		||||
	// Cancel the layer upload process.
 | 
			
		||||
	Cancel() error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var (
 | 
			
		||||
	// ErrLayerExists returned when layer already exists
 | 
			
		||||
	ErrLayerExists = fmt.Errorf("layer exists")
 | 
			
		||||
 | 
			
		||||
	// ErrLayerTarSumVersionUnsupported when tarsum is unsupported version.
 | 
			
		||||
	ErrLayerTarSumVersionUnsupported = fmt.Errorf("unsupported tarsum version")
 | 
			
		||||
 | 
			
		||||
	// ErrLayerUploadUnknown returned when upload is not found.
 | 
			
		||||
	ErrLayerUploadUnknown = fmt.Errorf("layer upload unknown")
 | 
			
		||||
 | 
			
		||||
	// ErrLayerClosed returned when an operation is attempted on a closed
 | 
			
		||||
	// Layer or LayerUpload.
 | 
			
		||||
	ErrLayerClosed = fmt.Errorf("layer closed")
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ErrUnknownLayer returned when layer cannot be found.
 | 
			
		||||
type ErrUnknownLayer struct {
 | 
			
		||||
	FSLayer manifest.FSLayer
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrUnknownLayer) Error() string {
 | 
			
		||||
	return fmt.Sprintf("unknown layer %v", err.FSLayer.BlobSum)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ErrLayerInvalidDigest returned when tarsum check fails.
 | 
			
		||||
type ErrLayerInvalidDigest struct {
 | 
			
		||||
	Digest digest.Digest
 | 
			
		||||
	Reason error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (err ErrLayerInvalidDigest) Error() string {
 | 
			
		||||
	return fmt.Sprintf("invalid digest for referenced layer: %v, %v",
 | 
			
		||||
		err.Digest, err.Reason)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			@ -9,6 +9,7 @@ import (
 | 
			
		|||
	"os"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	storagedriver "github.com/docker/distribution/registry/storage/driver"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage/driver/inmemory"
 | 
			
		||||
| 
						 | 
				
			
			@ -53,7 +54,7 @@ func TestSimpleLayerUpload(t *testing.T) {
 | 
			
		|||
 | 
			
		||||
	// Do a resume, get unknown upload
 | 
			
		||||
	layerUpload, err = ls.Resume(layerUpload.UUID())
 | 
			
		||||
	if err != ErrLayerUploadUnknown {
 | 
			
		||||
	if err != distribution.ErrLayerUploadUnknown {
 | 
			
		||||
		t.Fatalf("unexpected error resuming upload, should be unkown: %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -102,7 +103,7 @@ func TestSimpleLayerUpload(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	// After finishing an upload, it should no longer exist.
 | 
			
		||||
	if _, err := ls.Resume(layerUpload.UUID()); err != ErrLayerUploadUnknown {
 | 
			
		||||
	if _, err := ls.Resume(layerUpload.UUID()); err != distribution.ErrLayerUploadUnknown {
 | 
			
		||||
		t.Fatalf("expected layer upload to be unknown, got %v", err)
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -165,7 +166,7 @@ func TestSimpleLayerRead(t *testing.T) {
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	switch err.(type) {
 | 
			
		||||
	case ErrUnknownLayer:
 | 
			
		||||
	case distribution.ErrUnknownLayer:
 | 
			
		||||
		err = nil
 | 
			
		||||
	default:
 | 
			
		||||
		t.Fatalf("unexpected error fetching non-existent layer: %v", err)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"net/http"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	storagedriver "github.com/docker/distribution/registry/storage/driver"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -13,7 +14,7 @@ type LayerHandler interface {
 | 
			
		|||
	// Layer if possible, or nil and an error when unsupported. This may
 | 
			
		||||
	// directly serve the contents of the layer or issue a redirect to another
 | 
			
		||||
	// URL hosting the content.
 | 
			
		||||
	Resolve(layer Layer) (http.Handler, error)
 | 
			
		||||
	Resolve(layer distribution.Layer) (http.Handler, error)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LayerHandlerInitFunc is the type of a LayerHandler factory function and is
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -3,6 +3,7 @@ package storage
 | 
			
		|||
import (
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -15,7 +16,7 @@ type layerReader struct {
 | 
			
		|||
	digest digest.Digest
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ Layer = &layerReader{}
 | 
			
		||||
var _ distribution.Layer = &layerReader{}
 | 
			
		||||
 | 
			
		||||
func (lrs *layerReader) Name() string {
 | 
			
		||||
	return lrs.name
 | 
			
		||||
| 
						 | 
				
			
			@ -28,3 +29,8 @@ func (lrs *layerReader) Digest() digest.Digest {
 | 
			
		|||
func (lrs *layerReader) CreatedAt() time.Time {
 | 
			
		||||
	return lrs.modtime
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Close the layer. Should be called when the resource is no longer needed.
 | 
			
		||||
func (lrs *layerReader) Close() error {
 | 
			
		||||
	return lrs.closeWithErr(distribution.ErrLayerClosed)
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
 | 
			
		||||
	"code.google.com/p/go-uuid/uuid"
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
| 
						 | 
				
			
			@ -23,7 +24,7 @@ func (ls *layerStore) Exists(digest digest.Digest) (bool, error) {
 | 
			
		|||
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		switch err.(type) {
 | 
			
		||||
		case ErrUnknownLayer:
 | 
			
		||||
		case distribution.ErrUnknownLayer:
 | 
			
		||||
			return false, nil
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -33,7 +34,7 @@ func (ls *layerStore) Exists(digest digest.Digest) (bool, error) {
 | 
			
		|||
	return true, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (ls *layerStore) Fetch(dgst digest.Digest) (Layer, error) {
 | 
			
		||||
func (ls *layerStore) Fetch(dgst digest.Digest) (distribution.Layer, error) {
 | 
			
		||||
	ctxu.GetLogger(ls.repository.ctx).Debug("(*layerStore).Fetch")
 | 
			
		||||
	bp, err := ls.path(dgst)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -55,7 +56,7 @@ func (ls *layerStore) Fetch(dgst digest.Digest) (Layer, error) {
 | 
			
		|||
// Upload begins a layer upload, returning a handle. If the layer upload
 | 
			
		||||
// is already in progress or the layer has already been uploaded, this
 | 
			
		||||
// will return an error.
 | 
			
		||||
func (ls *layerStore) Upload() (LayerUpload, error) {
 | 
			
		||||
func (ls *layerStore) Upload() (distribution.LayerUpload, error) {
 | 
			
		||||
	ctxu.GetLogger(ls.repository.ctx).Debug("(*layerStore).Upload")
 | 
			
		||||
 | 
			
		||||
	// NOTE(stevvooe): Consider the issues with allowing concurrent upload of
 | 
			
		||||
| 
						 | 
				
			
			@ -93,7 +94,7 @@ func (ls *layerStore) Upload() (LayerUpload, error) {
 | 
			
		|||
 | 
			
		||||
// Resume continues an in progress layer upload, returning the current
 | 
			
		||||
// state of the upload.
 | 
			
		||||
func (ls *layerStore) Resume(uuid string) (LayerUpload, error) {
 | 
			
		||||
func (ls *layerStore) Resume(uuid string) (distribution.LayerUpload, error) {
 | 
			
		||||
	ctxu.GetLogger(ls.repository.ctx).Debug("(*layerStore).Resume")
 | 
			
		||||
	startedAtPath, err := ls.repository.registry.pm.path(uploadStartedAtPathSpec{
 | 
			
		||||
		name: ls.repository.Name(),
 | 
			
		||||
| 
						 | 
				
			
			@ -108,7 +109,7 @@ func (ls *layerStore) Resume(uuid string) (LayerUpload, error) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		switch err := err.(type) {
 | 
			
		||||
		case storagedriver.PathNotFoundError:
 | 
			
		||||
			return nil, ErrLayerUploadUnknown
 | 
			
		||||
			return nil, distribution.ErrLayerUploadUnknown
 | 
			
		||||
		default:
 | 
			
		||||
			return nil, err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			@ -132,7 +133,7 @@ func (ls *layerStore) Resume(uuid string) (LayerUpload, error) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
// newLayerUpload allocates a new upload controller with the given state.
 | 
			
		||||
func (ls *layerStore) newLayerUpload(uuid, path string, startedAt time.Time) (LayerUpload, error) {
 | 
			
		||||
func (ls *layerStore) newLayerUpload(uuid, path string, startedAt time.Time) (distribution.LayerUpload, error) {
 | 
			
		||||
	fw, err := newFileWriter(ls.repository.driver, path)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return nil, err
 | 
			
		||||
| 
						 | 
				
			
			@ -158,7 +159,9 @@ func (ls *layerStore) path(dgst digest.Digest) (string, error) {
 | 
			
		|||
	if err != nil {
 | 
			
		||||
		switch err := err.(type) {
 | 
			
		||||
		case storagedriver.PathNotFoundError:
 | 
			
		||||
			return "", ErrUnknownLayer{manifest.FSLayer{BlobSum: dgst}}
 | 
			
		||||
			return "", distribution.ErrUnknownLayer{
 | 
			
		||||
				FSLayer: manifest.FSLayer{BlobSum: dgst},
 | 
			
		||||
			}
 | 
			
		||||
		default:
 | 
			
		||||
			return "", err
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -7,6 +7,7 @@ import (
 | 
			
		|||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	storagedriver "github.com/docker/distribution/registry/storage/driver"
 | 
			
		||||
| 
						 | 
				
			
			@ -24,7 +25,7 @@ type layerUploadController struct {
 | 
			
		|||
	fileWriter
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ LayerUpload = &layerUploadController{}
 | 
			
		||||
var _ distribution.LayerUpload = &layerUploadController{}
 | 
			
		||||
 | 
			
		||||
// Name of the repository under which the layer will be linked.
 | 
			
		||||
func (luc *layerUploadController) Name() string {
 | 
			
		||||
| 
						 | 
				
			
			@ -44,7 +45,7 @@ func (luc *layerUploadController) StartedAt() time.Time {
 | 
			
		|||
// uploaded layer. The final size and checksum are validated against the
 | 
			
		||||
// contents of the uploaded layer. The checksum should be provided in the
 | 
			
		||||
// format <algorithm>:<hex digest>.
 | 
			
		||||
func (luc *layerUploadController) Finish(digest digest.Digest) (Layer, error) {
 | 
			
		||||
func (luc *layerUploadController) Finish(digest digest.Digest) (distribution.Layer, error) {
 | 
			
		||||
	ctxu.GetLogger(luc.layerStore.repository.ctx).Debug("(*layerUploadController).Finish")
 | 
			
		||||
	canonical, err := luc.validateLayer(digest)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -93,9 +94,9 @@ func (luc *layerUploadController) validateLayer(dgst digest.Digest) (digest.Dige
 | 
			
		|||
	case tarsum.Version1:
 | 
			
		||||
	default:
 | 
			
		||||
		// version 0 and dev, for now.
 | 
			
		||||
		return "", ErrLayerInvalidDigest{
 | 
			
		||||
		return "", distribution.ErrLayerInvalidDigest{
 | 
			
		||||
			Digest: dgst,
 | 
			
		||||
			Reason: ErrLayerTarSumVersionUnsupported,
 | 
			
		||||
			Reason: distribution.ErrLayerTarSumVersionUnsupported,
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -124,7 +125,7 @@ func (luc *layerUploadController) validateLayer(dgst digest.Digest) (digest.Dige
 | 
			
		|||
	}
 | 
			
		||||
 | 
			
		||||
	if !digestVerifier.Verified() {
 | 
			
		||||
		return "", ErrLayerInvalidDigest{
 | 
			
		||||
		return "", distribution.ErrLayerInvalidDigest{
 | 
			
		||||
			Digest: dgst,
 | 
			
		||||
			Reason: fmt.Errorf("content does not match digest"),
 | 
			
		||||
		}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,6 +4,7 @@ import (
 | 
			
		|||
	"fmt"
 | 
			
		||||
	"strings"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	ctxu "github.com/docker/distribution/context"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
| 
						 | 
				
			
			@ -71,7 +72,7 @@ type manifestStore struct {
 | 
			
		|||
	tagStore      *tagStore
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
var _ ManifestService = &manifestStore{}
 | 
			
		||||
var _ distribution.ManifestService = &manifestStore{}
 | 
			
		||||
 | 
			
		||||
// func (ms *manifestStore) Repository() Repository {
 | 
			
		||||
// 	return ms.repository
 | 
			
		||||
| 
						 | 
				
			
			@ -177,7 +178,7 @@ func (ms *manifestStore) verifyManifest(tag string, mnfst *manifest.SignedManife
 | 
			
		|||
		}
 | 
			
		||||
 | 
			
		||||
		if !exists {
 | 
			
		||||
			errs = append(errs, ErrUnknownLayer{FSLayer: fsLayer})
 | 
			
		||||
			errs = append(errs, distribution.ErrUnknownLayer{FSLayer: fsLayer})
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -4,11 +4,10 @@ import (
 | 
			
		|||
	"net/http"
 | 
			
		||||
	"time"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
 | 
			
		||||
	"code.google.com/p/go-uuid/uuid"
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
type bridge struct {
 | 
			
		||||
| 
						 | 
				
			
			@ -53,31 +52,31 @@ func NewRequestRecord(id string, r *http.Request) RequestRecord {
 | 
			
		|||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) ManifestPushed(repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (b *bridge) ManifestPushed(repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	return b.createManifestEventAndWrite(EventActionPush, repo, sm)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) ManifestPulled(repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (b *bridge) ManifestPulled(repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	return b.createManifestEventAndWrite(EventActionPull, repo, sm)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) ManifestDeleted(repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (b *bridge) ManifestDeleted(repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	return b.createManifestEventAndWrite(EventActionDelete, repo, sm)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) LayerPushed(repo storage.Repository, layer storage.Layer) error {
 | 
			
		||||
func (b *bridge) LayerPushed(repo distribution.Repository, layer distribution.Layer) error {
 | 
			
		||||
	return b.createLayerEventAndWrite(EventActionPush, repo, layer.Digest())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) LayerPulled(repo storage.Repository, layer storage.Layer) error {
 | 
			
		||||
func (b *bridge) LayerPulled(repo distribution.Repository, layer distribution.Layer) error {
 | 
			
		||||
	return b.createLayerEventAndWrite(EventActionPull, repo, layer.Digest())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) LayerDeleted(repo storage.Repository, layer storage.Layer) error {
 | 
			
		||||
func (b *bridge) LayerDeleted(repo distribution.Repository, layer distribution.Layer) error {
 | 
			
		||||
	return b.createLayerEventAndWrite(EventActionDelete, repo, layer.Digest())
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) createManifestEventAndWrite(action string, repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (b *bridge) createManifestEventAndWrite(action string, repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	event, err := b.createManifestEvent(action, repo, sm)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -86,7 +85,7 @@ func (b *bridge) createManifestEventAndWrite(action string, repo storage.Reposit
 | 
			
		|||
	return b.sink.Write(*event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) createManifestEvent(action string, repo storage.Repository, sm *manifest.SignedManifest) (*Event, error) {
 | 
			
		||||
func (b *bridge) createManifestEvent(action string, repo distribution.Repository, sm *manifest.SignedManifest) (*Event, error) {
 | 
			
		||||
	event := b.createEvent(action)
 | 
			
		||||
	event.Target.Type = EventTargetTypeManifest
 | 
			
		||||
	event.Target.Name = repo.Name()
 | 
			
		||||
| 
						 | 
				
			
			@ -112,7 +111,7 @@ func (b *bridge) createManifestEvent(action string, repo storage.Repository, sm
 | 
			
		|||
	return event, nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) createLayerEventAndWrite(action string, repo storage.Repository, dgst digest.Digest) error {
 | 
			
		||||
func (b *bridge) createLayerEventAndWrite(action string, repo distribution.Repository, dgst digest.Digest) error {
 | 
			
		||||
	event, err := b.createLayerEvent(action, repo, dgst)
 | 
			
		||||
	if err != nil {
 | 
			
		||||
		return err
 | 
			
		||||
| 
						 | 
				
			
			@ -121,7 +120,7 @@ func (b *bridge) createLayerEventAndWrite(action string, repo storage.Repository
 | 
			
		|||
	return b.sink.Write(*event)
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (b *bridge) createLayerEvent(action string, repo storage.Repository, dgst digest.Digest) (*Event, error) {
 | 
			
		||||
func (b *bridge) createLayerEvent(action string, repo distribution.Repository, dgst digest.Digest) (*Event, error) {
 | 
			
		||||
	event := b.createEvent(action)
 | 
			
		||||
	event.Target.Type = EventTargetTypeBlob
 | 
			
		||||
	event.Target.Name = repo.Name()
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -2,31 +2,31 @@ package notifications
 | 
			
		|||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/Sirupsen/logrus"
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// ManifestListener describes a set of methods for listening to events related to manifests.
 | 
			
		||||
type ManifestListener interface {
 | 
			
		||||
	ManifestPushed(repo storage.Repository, sm *manifest.SignedManifest) error
 | 
			
		||||
	ManifestPulled(repo storage.Repository, sm *manifest.SignedManifest) error
 | 
			
		||||
	ManifestPushed(repo distribution.Repository, sm *manifest.SignedManifest) error
 | 
			
		||||
	ManifestPulled(repo distribution.Repository, sm *manifest.SignedManifest) error
 | 
			
		||||
 | 
			
		||||
	// TODO(stevvooe): Please note that delete support is still a little shaky
 | 
			
		||||
	// and we'll need to propagate these in the future.
 | 
			
		||||
 | 
			
		||||
	ManifestDeleted(repo storage.Repository, sm *manifest.SignedManifest) error
 | 
			
		||||
	ManifestDeleted(repo distribution.Repository, sm *manifest.SignedManifest) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LayerListener describes a listener that can respond to layer related events.
 | 
			
		||||
type LayerListener interface {
 | 
			
		||||
	LayerPushed(repo storage.Repository, layer storage.Layer) error
 | 
			
		||||
	LayerPulled(repo storage.Repository, layer storage.Layer) error
 | 
			
		||||
	LayerPushed(repo distribution.Repository, layer distribution.Layer) error
 | 
			
		||||
	LayerPulled(repo distribution.Repository, layer distribution.Layer) error
 | 
			
		||||
 | 
			
		||||
	// TODO(stevvooe): Please note that delete support is still a little shaky
 | 
			
		||||
	// and we'll need to propagate these in the future.
 | 
			
		||||
 | 
			
		||||
	LayerDeleted(repo storage.Repository, layer storage.Layer) error
 | 
			
		||||
	LayerDeleted(repo distribution.Repository, layer distribution.Layer) error
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Listener combines all repository events into a single interface.
 | 
			
		||||
| 
						 | 
				
			
			@ -36,26 +36,26 @@ type Listener interface {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
type repositoryListener struct {
 | 
			
		||||
	storage.Repository
 | 
			
		||||
	distribution.Repository
 | 
			
		||||
	listener Listener
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Listen dispatches events on the repository to the listener.
 | 
			
		||||
func Listen(repo storage.Repository, listener Listener) storage.Repository {
 | 
			
		||||
func Listen(repo distribution.Repository, listener Listener) distribution.Repository {
 | 
			
		||||
	return &repositoryListener{
 | 
			
		||||
		Repository: repo,
 | 
			
		||||
		listener:   listener,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (rl *repositoryListener) Manifests() storage.ManifestService {
 | 
			
		||||
func (rl *repositoryListener) Manifests() distribution.ManifestService {
 | 
			
		||||
	return &manifestServiceListener{
 | 
			
		||||
		ManifestService: rl.Repository.Manifests(),
 | 
			
		||||
		parent:          rl,
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (rl *repositoryListener) Layers() storage.LayerService {
 | 
			
		||||
func (rl *repositoryListener) Layers() distribution.LayerService {
 | 
			
		||||
	return &layerServiceListener{
 | 
			
		||||
		LayerService: rl.Repository.Layers(),
 | 
			
		||||
		parent:       rl,
 | 
			
		||||
| 
						 | 
				
			
			@ -63,7 +63,7 @@ func (rl *repositoryListener) Layers() storage.LayerService {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
type manifestServiceListener struct {
 | 
			
		||||
	storage.ManifestService
 | 
			
		||||
	distribution.ManifestService
 | 
			
		||||
	parent *repositoryListener
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -91,11 +91,11 @@ func (msl *manifestServiceListener) Put(tag string, sm *manifest.SignedManifest)
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
type layerServiceListener struct {
 | 
			
		||||
	storage.LayerService
 | 
			
		||||
	distribution.LayerService
 | 
			
		||||
	parent *repositoryListener
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lsl *layerServiceListener) Fetch(dgst digest.Digest) (storage.Layer, error) {
 | 
			
		||||
func (lsl *layerServiceListener) Fetch(dgst digest.Digest) (distribution.Layer, error) {
 | 
			
		||||
	layer, err := lsl.LayerService.Fetch(dgst)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if err := lsl.parent.listener.LayerPulled(lsl.parent.Repository, layer); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			@ -106,17 +106,17 @@ func (lsl *layerServiceListener) Fetch(dgst digest.Digest) (storage.Layer, error
 | 
			
		|||
	return layer, err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lsl *layerServiceListener) Upload() (storage.LayerUpload, error) {
 | 
			
		||||
func (lsl *layerServiceListener) Upload() (distribution.LayerUpload, error) {
 | 
			
		||||
	lu, err := lsl.LayerService.Upload()
 | 
			
		||||
	return lsl.decorateUpload(lu), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lsl *layerServiceListener) Resume(uuid string) (storage.LayerUpload, error) {
 | 
			
		||||
func (lsl *layerServiceListener) Resume(uuid string) (distribution.LayerUpload, error) {
 | 
			
		||||
	lu, err := lsl.LayerService.Resume(uuid)
 | 
			
		||||
	return lsl.decorateUpload(lu), err
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lsl *layerServiceListener) decorateUpload(lu storage.LayerUpload) storage.LayerUpload {
 | 
			
		||||
func (lsl *layerServiceListener) decorateUpload(lu distribution.LayerUpload) distribution.LayerUpload {
 | 
			
		||||
	return &layerUploadListener{
 | 
			
		||||
		LayerUpload: lu,
 | 
			
		||||
		parent:      lsl,
 | 
			
		||||
| 
						 | 
				
			
			@ -124,11 +124,11 @@ func (lsl *layerServiceListener) decorateUpload(lu storage.LayerUpload) storage.
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
type layerUploadListener struct {
 | 
			
		||||
	storage.LayerUpload
 | 
			
		||||
	distribution.LayerUpload
 | 
			
		||||
	parent *layerServiceListener
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (lul *layerUploadListener) Finish(dgst digest.Digest) (storage.Layer, error) {
 | 
			
		||||
func (lul *layerUploadListener) Finish(dgst digest.Digest) (distribution.Layer, error) {
 | 
			
		||||
	layer, err := lul.LayerUpload.Finish(dgst)
 | 
			
		||||
	if err == nil {
 | 
			
		||||
		if err := lul.parent.parent.listener.LayerPushed(lul.parent.parent.Repository, layer); err != nil {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -5,6 +5,7 @@ import (
 | 
			
		|||
	"reflect"
 | 
			
		||||
	"testing"
 | 
			
		||||
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
	"github.com/docker/distribution/registry/storage"
 | 
			
		||||
| 
						 | 
				
			
			@ -44,40 +45,40 @@ type testListener struct {
 | 
			
		|||
	ops map[string]int
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tl *testListener) ManifestPushed(repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (tl *testListener) ManifestPushed(repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	tl.ops["manifest:push"]++
 | 
			
		||||
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tl *testListener) ManifestPulled(repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (tl *testListener) ManifestPulled(repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	tl.ops["manifest:pull"]++
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tl *testListener) ManifestDeleted(repo storage.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
func (tl *testListener) ManifestDeleted(repo distribution.Repository, sm *manifest.SignedManifest) error {
 | 
			
		||||
	tl.ops["manifest:delete"]++
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tl *testListener) LayerPushed(repo storage.Repository, layer storage.Layer) error {
 | 
			
		||||
func (tl *testListener) LayerPushed(repo distribution.Repository, layer distribution.Layer) error {
 | 
			
		||||
	tl.ops["layer:push"]++
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tl *testListener) LayerPulled(repo storage.Repository, layer storage.Layer) error {
 | 
			
		||||
func (tl *testListener) LayerPulled(repo distribution.Repository, layer distribution.Layer) error {
 | 
			
		||||
	tl.ops["layer:pull"]++
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
func (tl *testListener) LayerDeleted(repo storage.Repository, layer storage.Layer) error {
 | 
			
		||||
func (tl *testListener) LayerDeleted(repo distribution.Repository, layer distribution.Layer) error {
 | 
			
		||||
	tl.ops["layer:delete"]++
 | 
			
		||||
	return nil
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// checkExerciseRegistry takes the registry through all of its operations,
 | 
			
		||||
// carrying out generic checks.
 | 
			
		||||
func checkExerciseRepository(t *testing.T, repository storage.Repository) {
 | 
			
		||||
func checkExerciseRepository(t *testing.T, repository distribution.Repository) {
 | 
			
		||||
	// TODO(stevvooe): This would be a nice testutil function. Basically, it
 | 
			
		||||
	// takes the registry through a common set of operations. This could be
 | 
			
		||||
	// used to make cross-cutting updates by changing internals that affect
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,6 +1,7 @@
 | 
			
		|||
package storage
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/docker/distribution"
 | 
			
		||||
	storagedriver "github.com/docker/distribution/registry/storage/driver"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
| 
						 | 
				
			
			@ -16,7 +17,7 @@ type registry struct {
 | 
			
		|||
// NewRegistryWithDriver creates a new registry instance from the provided
 | 
			
		||||
// driver. The resulting registry may be shared by multiple goroutines but is
 | 
			
		||||
// cheap to allocate.
 | 
			
		||||
func NewRegistryWithDriver(driver storagedriver.StorageDriver) Registry {
 | 
			
		||||
func NewRegistryWithDriver(driver storagedriver.StorageDriver) distribution.Registry {
 | 
			
		||||
	bs := &blobStore{}
 | 
			
		||||
 | 
			
		||||
	reg := ®istry{
 | 
			
		||||
| 
						 | 
				
			
			@ -35,7 +36,7 @@ func NewRegistryWithDriver(driver storagedriver.StorageDriver) Registry {
 | 
			
		|||
// Repository returns an instance of the repository tied to the registry.
 | 
			
		||||
// Instances should not be shared between goroutines but are cheap to
 | 
			
		||||
// allocate. In general, they should be request scoped.
 | 
			
		||||
func (reg *registry) Repository(ctx context.Context, name string) Repository {
 | 
			
		||||
func (reg *registry) Repository(ctx context.Context, name string) distribution.Repository {
 | 
			
		||||
	return &repository{
 | 
			
		||||
		ctx:      ctx,
 | 
			
		||||
		registry: reg,
 | 
			
		||||
| 
						 | 
				
			
			@ -58,7 +59,7 @@ func (repo *repository) Name() string {
 | 
			
		|||
// Manifests returns an instance of ManifestService. Instantiation is cheap and
 | 
			
		||||
// may be context sensitive in the future. The instance should be used similar
 | 
			
		||||
// to a request local.
 | 
			
		||||
func (repo *repository) Manifests() ManifestService {
 | 
			
		||||
func (repo *repository) Manifests() distribution.ManifestService {
 | 
			
		||||
	return &manifestStore{
 | 
			
		||||
		repository: repo,
 | 
			
		||||
		revisionStore: &revisionStore{
 | 
			
		||||
| 
						 | 
				
			
			@ -73,7 +74,7 @@ func (repo *repository) Manifests() ManifestService {
 | 
			
		|||
// Layers returns an instance of the LayerService. Instantiation is cheap and
 | 
			
		||||
// may be context sensitive in the future. The instance should be used similar
 | 
			
		||||
// to a request local.
 | 
			
		||||
func (repo *repository) Layers() LayerService {
 | 
			
		||||
func (repo *repository) Layers() distribution.LayerService {
 | 
			
		||||
	return &layerStore{
 | 
			
		||||
		repository: repo,
 | 
			
		||||
	}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,84 +0,0 @@
 | 
			
		|||
package storage
 | 
			
		||||
 | 
			
		||||
import (
 | 
			
		||||
	"github.com/docker/distribution/digest"
 | 
			
		||||
	"github.com/docker/distribution/manifest"
 | 
			
		||||
	"golang.org/x/net/context"
 | 
			
		||||
)
 | 
			
		||||
 | 
			
		||||
// TODO(stevvooe): These types need to be moved out of the storage package.
 | 
			
		||||
 | 
			
		||||
// Registry represents a collection of repositories, addressable by name.
 | 
			
		||||
type Registry interface {
 | 
			
		||||
	// Repository should return a reference to the named repository. The
 | 
			
		||||
	// registry may or may not have the repository but should always return a
 | 
			
		||||
	// reference.
 | 
			
		||||
	Repository(ctx context.Context, name string) Repository
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// Repository is a named collection of manifests and layers.
 | 
			
		||||
type Repository interface {
 | 
			
		||||
	// Name returns the name of the repository.
 | 
			
		||||
	Name() string
 | 
			
		||||
 | 
			
		||||
	// Manifests returns a reference to this repository's manifest service.
 | 
			
		||||
	Manifests() ManifestService
 | 
			
		||||
 | 
			
		||||
	// Layers returns a reference to this repository's layers service.
 | 
			
		||||
	Layers() LayerService
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// ManifestService provides operations on image manifests.
 | 
			
		||||
type ManifestService interface {
 | 
			
		||||
	// Tags lists the tags under the named repository.
 | 
			
		||||
	Tags() ([]string, error)
 | 
			
		||||
 | 
			
		||||
	// Exists returns true if the manifest exists.
 | 
			
		||||
	Exists(tag string) (bool, error)
 | 
			
		||||
 | 
			
		||||
	// Get retrieves the named manifest, if it exists.
 | 
			
		||||
	Get(tag string) (*manifest.SignedManifest, error)
 | 
			
		||||
 | 
			
		||||
	// Put creates or updates the named manifest.
 | 
			
		||||
	// Put(tag string, manifest *manifest.SignedManifest) (digest.Digest, error)
 | 
			
		||||
	Put(tag string, manifest *manifest.SignedManifest) error
 | 
			
		||||
 | 
			
		||||
	// Delete removes the named manifest, if it exists.
 | 
			
		||||
	Delete(tag string) error
 | 
			
		||||
 | 
			
		||||
	// TODO(stevvooe): There are several changes that need to be done to this
 | 
			
		||||
	// interface:
 | 
			
		||||
	//
 | 
			
		||||
	//	1. Get(tag string) should be GetByTag(tag string)
 | 
			
		||||
	//	2. Put(tag string, manifest *manifest.SignedManifest) should be
 | 
			
		||||
	//       Put(manifest *manifest.SignedManifest). The method can read the
 | 
			
		||||
	//       tag on manifest to automatically tag it in the repository.
 | 
			
		||||
	//	3. Need a GetByDigest(dgst digest.Digest) method.
 | 
			
		||||
	//	4. Allow explicit tagging with Tag(digest digest.Digest, tag string)
 | 
			
		||||
	//	5. Support reading tags with a re-entrant reader to avoid large
 | 
			
		||||
	//       allocations in the registry.
 | 
			
		||||
	//	6. Long-term: Provide All() method that lets one scroll through all of
 | 
			
		||||
	//       the manifest entries.
 | 
			
		||||
	//	7. Long-term: break out concept of signing from manifests. This is
 | 
			
		||||
	//       really a part of the distribution sprint.
 | 
			
		||||
	//	8. Long-term: Manifest should be an interface. This code shouldn't
 | 
			
		||||
	//       really be concerned with the storage format.
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
// LayerService provides operations on layer files in a backend storage.
 | 
			
		||||
type LayerService interface {
 | 
			
		||||
	// Exists returns true if the layer exists.
 | 
			
		||||
	Exists(digest digest.Digest) (bool, error)
 | 
			
		||||
 | 
			
		||||
	// Fetch the layer identifed by TarSum.
 | 
			
		||||
	Fetch(digest digest.Digest) (Layer, error)
 | 
			
		||||
 | 
			
		||||
	// Upload begins a layer upload to repository identified by name,
 | 
			
		||||
	// returning a handle.
 | 
			
		||||
	Upload() (LayerUpload, error)
 | 
			
		||||
 | 
			
		||||
	// Resume continues an in progress layer upload, returning a handle to the
 | 
			
		||||
	// upload. The caller should seek to the latest desired upload location
 | 
			
		||||
	// before proceeding.
 | 
			
		||||
	Resume(uuid string) (LayerUpload, error)
 | 
			
		||||
}
 | 
			
		||||
		Loading…
	
		Reference in New Issue