123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244 |
- package distribution
- import (
- "encoding/json"
- "fmt"
- "io"
- "runtime"
- "github.com/docker/distribution"
- "github.com/docker/distribution/manifest/schema2"
- "github.com/docker/docker/api/types"
- "github.com/docker/docker/distribution/metadata"
- "github.com/docker/docker/distribution/xfer"
- "github.com/docker/docker/image"
- "github.com/docker/docker/layer"
- "github.com/docker/docker/pkg/progress"
- refstore "github.com/docker/docker/reference"
- "github.com/docker/docker/registry"
- "github.com/docker/libtrust"
- "github.com/opencontainers/go-digest"
- "golang.org/x/net/context"
- )
- // Config stores configuration for communicating
- // with a registry.
- type Config struct {
- // MetaHeaders stores HTTP headers with metadata about the image
- MetaHeaders map[string][]string
- // AuthConfig holds authentication credentials for authenticating with
- // the registry.
- AuthConfig *types.AuthConfig
- // ProgressOutput is the interface for showing the status of the pull
- // operation.
- ProgressOutput progress.Output
- // RegistryService is the registry service to use for TLS configuration
- // and endpoint lookup.
- RegistryService registry.Service
- // ImageEventLogger notifies events for a given image
- ImageEventLogger func(id, name, action string)
- // MetadataStore is the storage backend for distribution-specific
- // metadata.
- MetadataStore metadata.Store
- // ImageStore manages images.
- ImageStore ImageConfigStore
- // ReferenceStore manages tags. This value is optional, when excluded
- // content will not be tagged.
- ReferenceStore refstore.Store
- // RequireSchema2 ensures that only schema2 manifests are used.
- RequireSchema2 bool
- }
- // ImagePullConfig stores pull configuration.
- type ImagePullConfig struct {
- Config
- // DownloadManager manages concurrent pulls.
- DownloadManager RootFSDownloadManager
- // Schema2Types is the valid schema2 configuration types allowed
- // by the pull operation.
- Schema2Types []string
- }
- // ImagePushConfig stores push configuration.
- type ImagePushConfig struct {
- Config
- // ConfigMediaType is the configuration media type for
- // schema2 manifests.
- ConfigMediaType string
- // LayerStore manages layers.
- LayerStore PushLayerProvider
- // TrustKey is the private key for legacy signatures. This is typically
- // an ephemeral key, since these signatures are no longer verified.
- TrustKey libtrust.PrivateKey
- // UploadManager dispatches uploads.
- UploadManager *xfer.LayerUploadManager
- }
- // ImageConfigStore handles storing and getting image configurations
- // by digest. Allows getting an image configurations rootfs from the
- // configuration.
- type ImageConfigStore interface {
- Put([]byte) (digest.Digest, error)
- Get(digest.Digest) ([]byte, error)
- RootFSFromConfig([]byte) (*image.RootFS, error)
- }
- // PushLayerProvider provides layers to be pushed by ChainID.
- type PushLayerProvider interface {
- Get(layer.ChainID) (PushLayer, error)
- }
- // PushLayer is a pushable layer with metadata about the layer
- // and access to the content of the layer.
- type PushLayer interface {
- ChainID() layer.ChainID
- DiffID() layer.DiffID
- Parent() PushLayer
- Open() (io.ReadCloser, error)
- Size() (int64, error)
- MediaType() string
- Release()
- }
- // RootFSDownloadManager handles downloading of the rootfs
- type RootFSDownloadManager interface {
- // Download downloads the layers into the given initial rootfs and
- // returns the final rootfs.
- // Given progress output to track download progress
- // Returns function to release download resources
- Download(ctx context.Context, initialRootFS image.RootFS, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error)
- }
- type imageConfigStore struct {
- image.Store
- }
- // NewImageConfigStoreFromStore returns an ImageConfigStore backed
- // by an image.Store for container images.
- func NewImageConfigStoreFromStore(is image.Store) ImageConfigStore {
- return &imageConfigStore{
- Store: is,
- }
- }
- func (s *imageConfigStore) Put(c []byte) (digest.Digest, error) {
- id, err := s.Store.Create(c)
- return digest.Digest(id), err
- }
- func (s *imageConfigStore) Get(d digest.Digest) ([]byte, error) {
- img, err := s.Store.Get(image.IDFromDigest(d))
- if err != nil {
- return nil, err
- }
- return img.RawJSON(), nil
- }
- func (s *imageConfigStore) RootFSFromConfig(c []byte) (*image.RootFS, error) {
- var unmarshalledConfig image.Image
- if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
- return nil, err
- }
- // fail immediately on Windows when downloading a non-Windows image
- // and vice versa
- if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" {
- return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
- } else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" {
- return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
- }
- return unmarshalledConfig.RootFS, nil
- }
- type storeLayerProvider struct {
- ls layer.Store
- }
- // NewLayerProviderFromStore returns a layer provider backed by
- // an instance of LayerStore. Only getting layers as gzipped
- // tars is supported.
- func NewLayerProviderFromStore(ls layer.Store) PushLayerProvider {
- return &storeLayerProvider{
- ls: ls,
- }
- }
- func (p *storeLayerProvider) Get(lid layer.ChainID) (PushLayer, error) {
- if lid == "" {
- return &storeLayer{
- Layer: layer.EmptyLayer,
- }, nil
- }
- l, err := p.ls.Get(lid)
- if err != nil {
- return nil, err
- }
- sl := storeLayer{
- Layer: l,
- ls: p.ls,
- }
- if d, ok := l.(distribution.Describable); ok {
- return &describableStoreLayer{
- storeLayer: sl,
- describable: d,
- }, nil
- }
- return &sl, nil
- }
- type storeLayer struct {
- layer.Layer
- ls layer.Store
- }
- func (l *storeLayer) Parent() PushLayer {
- p := l.Layer.Parent()
- if p == nil {
- return nil
- }
- sl := storeLayer{
- Layer: p,
- ls: l.ls,
- }
- if d, ok := p.(distribution.Describable); ok {
- return &describableStoreLayer{
- storeLayer: sl,
- describable: d,
- }
- }
- return &sl
- }
- func (l *storeLayer) Open() (io.ReadCloser, error) {
- return l.Layer.TarStream()
- }
- func (l *storeLayer) Size() (int64, error) {
- return l.Layer.DiffSize()
- }
- func (l *storeLayer) MediaType() string {
- // layer store always returns uncompressed tars
- return schema2.MediaTypeUncompressedLayer
- }
- func (l *storeLayer) Release() {
- if l.ls != nil {
- layer.ReleaseAndLog(l.ls, l.Layer)
- }
- }
- type describableStoreLayer struct {
- storeLayer
- describable distribution.Describable
- }
- func (l *describableStoreLayer) Descriptor() distribution.Descriptor {
- return l.describable.Descriptor()
- }
|