From 553d48d618411feaa6ae947a61f7fd9c9153e68e Mon Sep 17 00:00:00 2001 From: Stephen J Day Date: Wed, 11 Feb 2015 16:49:49 -0800 Subject: [PATCH] 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 --- docs/handlers/app.go | 4 +- docs/handlers/context.go | 4 +- docs/handlers/images.go | 3 +- docs/handlers/layer.go | 4 +- docs/handlers/layerupload.go | 8 +- docs/storage/cloudfrontlayerhandler.go | 3 +- docs/storage/delegatelayerhandler.go | 5 +- docs/storage/filereader.go | 35 ++++---- docs/storage/layer.go | 90 --------------------- docs/storage/layer_test.go | 7 +- docs/storage/layerhandler.go | 3 +- docs/storage/layerreader.go | 8 +- docs/storage/layerstore.go | 17 ++-- docs/storage/layerupload.go | 11 +-- docs/storage/manifeststore.go | 5 +- docs/storage/notifications/bridge.go | 25 +++--- docs/storage/notifications/listener.go | 38 ++++----- docs/storage/notifications/listener_test.go | 15 ++-- docs/storage/registry.go | 9 ++- docs/storage/services.go | 84 ------------------- 20 files changed, 113 insertions(+), 265 deletions(-) delete mode 100644 docs/storage/layer.go delete mode 100644 docs/storage/services.go diff --git a/docs/handlers/app.go b/docs/handlers/app.go index 7a36309b..bc0c46aa 100644 --- a/docs/handlers/app.go +++ b/docs/handlers/app.go @@ -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. diff --git a/docs/handlers/context.go b/docs/handlers/context.go index 0d3f44cc..ee02a53a 100644 --- a/docs/handlers/context.go +++ b/docs/handlers/context.go @@ -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 diff --git a/docs/handlers/images.go b/docs/handlers/images.go index e41f3682..0e58984b 100644 --- a/docs/handlers/images.go +++ b/docs/handlers/images.go @@ -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) diff --git a/docs/handlers/layer.go b/docs/handlers/layer.go index 105c2964..69c3df7c 100644 --- a/docs/handlers/layer.go +++ b/docs/handlers/layer.go @@ -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: diff --git a/docs/handlers/layerupload.go b/docs/handlers/layerupload.go index 237644ea..fa854449 100644 --- a/docs/handlers/layerupload.go +++ b/docs/handlers/layerupload.go @@ -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: diff --git a/docs/storage/cloudfrontlayerhandler.go b/docs/storage/cloudfrontlayerhandler.go index f887895c..82bc313d 100644 --- a/docs/storage/cloudfrontlayerhandler.go +++ b/docs/storage/cloudfrontlayerhandler.go @@ -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 diff --git a/docs/storage/delegatelayerhandler.go b/docs/storage/delegatelayerhandler.go index 01354023..62b08b22 100644 --- a/docs/storage/delegatelayerhandler.go +++ b/docs/storage/delegatelayerhandler.go @@ -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 { diff --git a/docs/storage/filereader.go b/docs/storage/filereader.go index 4cb2b331..b70b1fb2 100644 --- a/docs/storage/filereader.go +++ b/docs/storage/filereader.go @@ -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 +} diff --git a/docs/storage/layer.go b/docs/storage/layer.go deleted file mode 100644 index 5e12f43e..00000000 --- a/docs/storage/layer.go +++ /dev/null @@ -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) -} diff --git a/docs/storage/layer_test.go b/docs/storage/layer_test.go index 48982993..ec0186db 100644 --- a/docs/storage/layer_test.go +++ b/docs/storage/layer_test.go @@ -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) diff --git a/docs/storage/layerhandler.go b/docs/storage/layerhandler.go index 5bcfeddd..b03bc250 100644 --- a/docs/storage/layerhandler.go +++ b/docs/storage/layerhandler.go @@ -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 diff --git a/docs/storage/layerreader.go b/docs/storage/layerreader.go index 4510dd7d..c539b769 100644 --- a/docs/storage/layerreader.go +++ b/docs/storage/layerreader.go @@ -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) +} diff --git a/docs/storage/layerstore.go b/docs/storage/layerstore.go index e4760b4e..1769eb43 100644 --- a/docs/storage/layerstore.go +++ b/docs/storage/layerstore.go @@ -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 } diff --git a/docs/storage/layerupload.go b/docs/storage/layerupload.go index e6cf21a9..fe3a0721 100644 --- a/docs/storage/layerupload.go +++ b/docs/storage/layerupload.go @@ -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 :. -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"), } diff --git a/docs/storage/manifeststore.go b/docs/storage/manifeststore.go index 1f798dde..99802905 100644 --- a/docs/storage/manifeststore.go +++ b/docs/storage/manifeststore.go @@ -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}) } } diff --git a/docs/storage/notifications/bridge.go b/docs/storage/notifications/bridge.go index 217ee5bd..9954e7c7 100644 --- a/docs/storage/notifications/bridge.go +++ b/docs/storage/notifications/bridge.go @@ -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() diff --git a/docs/storage/notifications/listener.go b/docs/storage/notifications/listener.go index 99a06f02..b55fe326 100644 --- a/docs/storage/notifications/listener.go +++ b/docs/storage/notifications/listener.go @@ -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 { diff --git a/docs/storage/notifications/listener_test.go b/docs/storage/notifications/listener_test.go index b8d6a31e..0f91a6a3 100644 --- a/docs/storage/notifications/listener_test.go +++ b/docs/storage/notifications/listener_test.go @@ -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 diff --git a/docs/storage/registry.go b/docs/storage/registry.go index c4ca2f80..2983751a 100644 --- a/docs/storage/registry.go +++ b/docs/storage/registry.go @@ -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, } diff --git a/docs/storage/services.go b/docs/storage/services.go deleted file mode 100644 index 7e6ac476..00000000 --- a/docs/storage/services.go +++ /dev/null @@ -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) -}