registry/storage/services.go
Stephen J Day 83d62628fc Refactor storage to use new backend layout
This change refactors the storage backend to use the new path layout. To
facilitate this, manifest storage has been separated into a revision store and
tag store, supported by a more general blob store. The blob store is a hybrid
object, effectively providing both small object access, keyed by content
address, as well as methods that can be used to manage and traverse links to
underlying blobs. This covers common operations used in the revision store and
tag store, such as linking and traversal. The blob store can also be updated to
better support layer reading but this refactoring has been left for another
day.

The revision store and tag store support the manifest store's compound view of
data. These underlying stores provide facilities for richer access models, such
as content-addressable access and a richer tagging model. The highlight of this
change is the ability to sign a manifest from different hosts and have the
registry merge and serve those signatures as part of the manifest package.

Various other items, such as the delegate layer handler, were updated to more
directly use the blob store or other mechanism to fit with the changes.

Signed-off-by: Stephen J Day <stephen.day@docker.com>
2015-01-15 10:32:18 -08:00

103 lines
3 KiB
Go

package storage
import (
"github.com/docker/distribution/digest"
"github.com/docker/distribution/manifest"
"github.com/docker/distribution/storagedriver"
)
// Services provides various services with application-level operations for
// use across backend storage drivers.
type Services struct {
driver storagedriver.StorageDriver
pathMapper *pathMapper
}
// NewServices creates a new Services object to access docker objects stored
// in the underlying driver.
func NewServices(driver storagedriver.StorageDriver) *Services {
return &Services{
driver: driver,
// TODO(sday): This should be configurable.
pathMapper: defaultPathMapper,
}
}
// 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 (ss *Services) Layers() LayerService {
return &layerStore{
driver: ss.driver,
blobStore: &blobStore{
driver: ss.driver,
pm: ss.pathMapper,
},
pathMapper: ss.pathMapper,
}
}
// 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 (ss *Services) Manifests() ManifestService {
// TODO(stevvooe): Lose this kludge. An intermediary object is clearly
// missing here. This initialization is a mess.
bs := &blobStore{
driver: ss.driver,
pm: ss.pathMapper,
}
return &manifestStore{
driver: ss.driver,
pathMapper: ss.pathMapper,
revisionStore: &revisionStore{
driver: ss.driver,
pathMapper: ss.pathMapper,
blobStore: bs,
},
tagStore: &tagStore{
driver: ss.driver,
blobStore: bs,
pathMapper: ss.pathMapper,
},
blobStore: bs,
layerService: ss.Layers()}
}
// ManifestService provides operations on image manifests.
type ManifestService interface {
// Tags lists the tags under the named repository.
Tags(name string) ([]string, error)
// Exists returns true if the manifest exists.
Exists(name, tag string) (bool, error)
// Get retrieves the named manifest, if it exists.
Get(name, tag string) (*manifest.SignedManifest, error)
// Put creates or updates the named manifest.
Put(name, tag string, manifest *manifest.SignedManifest) error
// Delete removes the named manifest, if it exists.
Delete(name, tag string) error
}
// LayerService provides operations on layer files in a backend storage.
type LayerService interface {
// Exists returns true if the layer exists.
Exists(name string, digest digest.Digest) (bool, error)
// Fetch the layer identifed by TarSum.
Fetch(name string, digest digest.Digest) (Layer, error)
// Upload begins a layer upload to repository identified by name,
// returning a handle.
Upload(name string) (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(name, uuid string) (LayerUpload, error)
}