2015-01-17 03:24:07 +01:00
|
|
|
package storage
|
|
|
|
|
2015-02-09 23:44:58 +01:00
|
|
|
import (
|
2015-02-12 01:49:49 +01:00
|
|
|
"github.com/docker/distribution"
|
2015-02-13 22:59:50 +01:00
|
|
|
"github.com/docker/distribution/registry/api/v2"
|
2015-04-02 01:41:33 +02:00
|
|
|
"github.com/docker/distribution/registry/storage/cache"
|
2015-02-11 03:14:23 +01:00
|
|
|
storagedriver "github.com/docker/distribution/registry/storage/driver"
|
2015-02-09 23:44:58 +01:00
|
|
|
"golang.org/x/net/context"
|
|
|
|
)
|
2015-01-17 03:24:07 +01:00
|
|
|
|
|
|
|
// registry is the top-level implementation of Registry for use in the storage
|
|
|
|
// package. All instances should descend from this object.
|
|
|
|
type registry struct {
|
2015-04-02 01:41:33 +02:00
|
|
|
driver storagedriver.StorageDriver
|
|
|
|
pm *pathMapper
|
|
|
|
blobStore *blobStore
|
|
|
|
layerInfoCache cache.LayerInfoCache
|
2015-01-17 03:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// NewRegistryWithDriver creates a new registry instance from the provided
|
|
|
|
// driver. The resulting registry may be shared by multiple goroutines but is
|
|
|
|
// cheap to allocate.
|
2015-04-02 01:41:33 +02:00
|
|
|
func NewRegistryWithDriver(driver storagedriver.StorageDriver, layerInfoCache cache.LayerInfoCache) distribution.Registry {
|
|
|
|
bs := &blobStore{
|
|
|
|
driver: driver,
|
|
|
|
pm: defaultPathMapper,
|
|
|
|
}
|
2015-01-17 03:24:07 +01:00
|
|
|
|
2015-04-02 01:41:33 +02:00
|
|
|
return ®istry{
|
2015-01-17 03:24:07 +01:00
|
|
|
driver: driver,
|
|
|
|
blobStore: bs,
|
|
|
|
|
|
|
|
// TODO(sday): This should be configurable.
|
2015-04-02 01:41:33 +02:00
|
|
|
pm: defaultPathMapper,
|
|
|
|
layerInfoCache: layerInfoCache,
|
2015-01-17 03:24:07 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2015-02-13 22:59:50 +01:00
|
|
|
func (reg *registry) Repository(ctx context.Context, name string) (distribution.Repository, error) {
|
|
|
|
if err := v2.ValidateRespositoryName(name); err != nil {
|
|
|
|
return nil, distribution.ErrRepositoryNameInvalid{
|
|
|
|
Name: name,
|
|
|
|
Reason: err,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2015-01-17 03:24:07 +01:00
|
|
|
return &repository{
|
2015-02-09 23:44:58 +01:00
|
|
|
ctx: ctx,
|
2015-01-17 03:24:07 +01:00
|
|
|
registry: reg,
|
|
|
|
name: name,
|
2015-02-13 22:59:50 +01:00
|
|
|
}, nil
|
2015-01-17 03:24:07 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
// repository provides name-scoped access to various services.
|
|
|
|
type repository struct {
|
|
|
|
*registry
|
2015-02-09 23:44:58 +01:00
|
|
|
ctx context.Context
|
2015-01-17 03:24:07 +01:00
|
|
|
name string
|
|
|
|
}
|
|
|
|
|
|
|
|
// Name returns the name of the repository.
|
|
|
|
func (repo *repository) Name() string {
|
|
|
|
return repo.name
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2015-02-12 01:49:49 +01:00
|
|
|
func (repo *repository) Manifests() distribution.ManifestService {
|
2015-01-17 03:24:07 +01:00
|
|
|
return &manifestStore{
|
|
|
|
repository: repo,
|
|
|
|
revisionStore: &revisionStore{
|
|
|
|
repository: repo,
|
|
|
|
},
|
|
|
|
tagStore: &tagStore{
|
|
|
|
repository: repo,
|
|
|
|
},
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
// 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.
|
2015-02-12 01:49:49 +01:00
|
|
|
func (repo *repository) Layers() distribution.LayerService {
|
2015-04-02 01:41:33 +02:00
|
|
|
ls := &layerStore{
|
2015-01-17 03:24:07 +01:00
|
|
|
repository: repo,
|
|
|
|
}
|
2015-04-02 01:41:33 +02:00
|
|
|
|
|
|
|
if repo.registry.layerInfoCache != nil {
|
|
|
|
// TODO(stevvooe): This is not the best place to setup a cache. We would
|
|
|
|
// really like to decouple the cache from the backend but also have the
|
|
|
|
// manifeset service use the layer service cache. For now, we can simply
|
|
|
|
// integrate the cache directly. The main issue is that we have layer
|
|
|
|
// access and layer data coupled in a single object. Work is already under
|
|
|
|
// way to decouple this.
|
|
|
|
|
|
|
|
return &cachedLayerService{
|
|
|
|
LayerService: ls,
|
|
|
|
repository: repo,
|
|
|
|
ctx: repo.ctx,
|
|
|
|
driver: repo.driver,
|
|
|
|
blobStore: repo.blobStore,
|
|
|
|
cache: repo.registry.layerInfoCache,
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return ls
|
2015-01-17 03:24:07 +01:00
|
|
|
}
|
2015-03-04 21:32:22 +01:00
|
|
|
|
|
|
|
func (repo *repository) Signatures() distribution.SignatureService {
|
|
|
|
return &signatureStore{
|
|
|
|
repository: repo,
|
|
|
|
}
|
|
|
|
}
|