From 142d62798e382b41963530a8e2761a9a4ce288f1 Mon Sep 17 00:00:00 2001 From: Derek McGowan Date: Thu, 9 Apr 2015 19:21:33 -0700 Subject: [PATCH] Rename top level registry interface to namespace Registry is intended to be used as a repository service than an abstract collection of repositories. Namespace better describes a collection of repositories retrievable by name. The registry service serves any repository in the global scope. Signed-off-by: Derek McGowan (github: dmcgowan) --- docs/configuration.md | 2 +- docs/glossary.md | 11 +++++++-- registry.go | 27 ++++++++++++++++++++-- registry/handlers/app.go | 4 ++-- registry/middleware/registry/middleware.go | 4 ++-- registry/storage/manifeststore_test.go | 2 +- registry/storage/registry.go | 8 ++++++- 7 files changed, 47 insertions(+), 11 deletions(-) diff --git a/docs/configuration.md b/docs/configuration.md index cb76b231d..933474b20 100644 --- a/docs/configuration.md +++ b/docs/configuration.md @@ -283,7 +283,7 @@ For more information about Token based authentication configuration, see the [sp ## middleware -The middleware option is **optional** and allows middlewares to be injected at named hook points. A requirement of all middlewares is that they implement the same interface as the object they're wrapping. This means a registry middleware must implement the `distribution.Registry` interface, repository middleware must implement `distribution.Respository`, and storage middleware must implement `driver.StorageDriver`. +The middleware option is **optional** and allows middlewares to be injected at named hook points. A requirement of all middlewares is that they implement the same interface as the object they're wrapping. This means a registry middleware must implement the `distribution.Namespace` interface, repository middleware must implement `distribution.Respository`, and storage middleware must implement `driver.StorageDriver`. Currently only one middleware, cloudfront, a storage middleware, is included in the registry. diff --git a/docs/glossary.md b/docs/glossary.md index 15184567e..95c8ec9e5 100644 --- a/docs/glossary.md +++ b/docs/glossary.md @@ -23,7 +23,7 @@ see the [glossary in the full documentation set](http://docs.docker.com/referenc
Describes a collection layers that make up an image.
Registry
-
A registry is a collection of repositories.
+
A registry is a service which serves repositories.
Repository
@@ -33,4 +33,11 @@ see the [glossary in the full documentation set](http://docs.docker.com/referenc
Tag
Tag provides a common name to an image.
- \ No newline at end of file + +
Namespace
+
A namespace is a collection of repositories with a common name prefix. The + namespace with an empty common prefix is considered the Global Namespace.
+ +
Scope
+
A common repository name prefix.
+ diff --git a/registry.go b/registry.go index 52b4f8d35..374d8ca59 100644 --- a/registry.go +++ b/registry.go @@ -10,8 +10,31 @@ import ( "golang.org/x/net/context" ) -// Registry represents a collection of repositories, addressable by name. -type Registry interface { +// Scope defines the set of items that match a namespace. +type Scope interface { + // Contains returns true if the name belongs to the namespace. + Contains(name string) bool +} + +type fullScope struct{} + +func (f fullScope) Contains(string) bool { + return true +} + +// GlobalScope represents the full namespace scope which contains +// all other scopes. +var GlobalScope = Scope(fullScope{}) + +// Namespace represents a collection of repositories, addressable by name. +// Generally, a namespace is backed by a set of one or more services, +// providing facilities such as registry access, trust, and indexing. +type Namespace interface { + // Scope describes the names that can be used with this Namespace. The + // global namespace will have a scope that matches all names. The scope + // effectively provides an identity for the namespace. + Scope() Scope + // Repository should return a reference to the named repository. The // registry may or may not have the repository but should always return a // reference. diff --git a/registry/handlers/app.go b/registry/handlers/app.go index fac93382f..657ed2db3 100644 --- a/registry/handlers/app.go +++ b/registry/handlers/app.go @@ -40,7 +40,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 distribution.Registry // registry is the primary registry backend for the app instance. + registry distribution.Namespace // registry is the primary registry backend for the app instance. accessController auth.AccessController // main access controller for application // events contains notification related configuration. @@ -541,7 +541,7 @@ func appendAccessRecords(records []auth.Access, method string, repo string) []au } // applyRegistryMiddleware wraps a registry instance with the configured middlewares -func applyRegistryMiddleware(registry distribution.Registry, middlewares []configuration.Middleware) (distribution.Registry, error) { +func applyRegistryMiddleware(registry distribution.Namespace, middlewares []configuration.Middleware) (distribution.Namespace, error) { for _, mw := range middlewares { rmw, err := registrymiddleware.Get(mw.Name, mw.Options, registry) if err != nil { diff --git a/registry/middleware/registry/middleware.go b/registry/middleware/registry/middleware.go index d3e88810d..048603b87 100644 --- a/registry/middleware/registry/middleware.go +++ b/registry/middleware/registry/middleware.go @@ -8,7 +8,7 @@ import ( // InitFunc is the type of a RegistryMiddleware factory function and is // used to register the constructor for different RegistryMiddleware backends. -type InitFunc func(registry distribution.Registry, options map[string]interface{}) (distribution.Registry, error) +type InitFunc func(registry distribution.Namespace, options map[string]interface{}) (distribution.Namespace, error) var middlewares map[string]InitFunc @@ -28,7 +28,7 @@ func Register(name string, initFunc InitFunc) error { } // Get constructs a RegistryMiddleware with the given options using the named backend. -func Get(name string, options map[string]interface{}, registry distribution.Registry) (distribution.Registry, error) { +func Get(name string, options map[string]interface{}, registry distribution.Namespace) (distribution.Namespace, error) { if middlewares != nil { if initFunc, exists := middlewares[name]; exists { return initFunc(registry, options) diff --git a/registry/storage/manifeststore_test.go b/registry/storage/manifeststore_test.go index fe75868b7..a70789d36 100644 --- a/registry/storage/manifeststore_test.go +++ b/registry/storage/manifeststore_test.go @@ -21,7 +21,7 @@ import ( type manifestStoreTestEnv struct { ctx context.Context driver driver.StorageDriver - registry distribution.Registry + registry distribution.Namespace repository distribution.Repository name string tag string diff --git a/registry/storage/registry.go b/registry/storage/registry.go index 9ad43acb7..1126db457 100644 --- a/registry/storage/registry.go +++ b/registry/storage/registry.go @@ -20,7 +20,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, layerInfoCache cache.LayerInfoCache) distribution.Registry { +func NewRegistryWithDriver(driver storagedriver.StorageDriver, layerInfoCache cache.LayerInfoCache) distribution.Namespace { bs := &blobStore{ driver: driver, pm: defaultPathMapper, @@ -36,6 +36,12 @@ func NewRegistryWithDriver(driver storagedriver.StorageDriver, layerInfoCache ca } } +// Scope returns the namespace scope for a registry. The registry +// will only serve repositories contained within this scope. +func (reg *registry) Scope() distribution.Scope { + return distribution.GlobalScope +} + // 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.