distribution/config.go
4f0d95fa
 package distribution // import "github.com/docker/docker/distribution"
3c7676a0
 
 import (
7d62e40f
 	"context"
3c7676a0
 	"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"
fe5b34ba
 	"github.com/docker/docker/pkg/system"
3a127939
 	refstore "github.com/docker/docker/reference"
3c7676a0
 	"github.com/docker/docker/registry"
99cd23ce
 	"github.com/docker/libtrust"
7a855799
 	"github.com/opencontainers/go-digest"
83908836
 	specs "github.com/opencontainers/image-spec/specs-go/v1"
3c7676a0
 )
 
 // 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.
3a127939
 	ReferenceStore refstore.Store
3c7676a0
 	// 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
337ba71f
 	// Platform is the requested platform of the image being pulled
 	Platform *specs.Platform
3c7676a0
 }
 
 // ImagePushConfig stores push configuration.
 type ImagePushConfig struct {
 	Config
 
 	// ConfigMediaType is the configuration media type for
 	// schema2 manifests.
 	ConfigMediaType string
afd305c4
 	// LayerStores (indexed by operating system) manages layers.
 	LayerStores map[string]PushLayerProvider
99cd23ce
 	// TrustKey is the private key for legacy signatures. This is typically
 	// an ephemeral key, since these signatures are no longer verified.
 	TrustKey libtrust.PrivateKey
3c7676a0
 	// 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)
83908836
 	RootFSFromConfig([]byte) (*image.RootFS, error)
 	PlatformFromConfig([]byte) (*specs.Platform, error)
3c7676a0
 }
 
 // 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
ce8e529e
 	Download(ctx context.Context, initialRootFS image.RootFS, os string, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error)
3c7676a0
 }
 
 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
 }
 
83908836
 func (s *imageConfigStore) RootFSFromConfig(c []byte) (*image.RootFS, error) {
3c7676a0
 	var unmarshalledConfig image.Image
 	if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
83908836
 		return nil, err
 	}
 	return unmarshalledConfig.RootFS, nil
 }
 
 func (s *imageConfigStore) PlatformFromConfig(c []byte) (*specs.Platform, error) {
 	var unmarshalledConfig image.Image
 	if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
 		return nil, err
3c7676a0
 	}
 
d5530406
 	// fail immediately on Windows when downloading a non-Windows image
fe5b34ba
 	// and vice versa. Exception on Windows if Linux Containers are enabled.
 	if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" && !system.LCOWSupported() {
83908836
 		return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
d5530406
 	} else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" {
83908836
 		return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
3c7676a0
 	}
 
ce8e529e
 	os := unmarshalledConfig.OS
 	if os == "" {
 		os = runtime.GOOS
42c5c1a9
 	}
0cba7740
 	if !system.IsOSSupported(os) {
83908836
 		return nil, system.ErrNotSupportedOperatingSystem
0cba7740
 	}
337ba71f
 	return &specs.Platform{OS: os, Architecture: unmarshalledConfig.Architecture, OSVersion: unmarshalledConfig.OSVersion}, nil
3c7676a0
 }
 
 type storeLayerProvider struct {
 	ls layer.Store
 }
 
afd305c4
 // NewLayerProvidersFromStores returns layer providers backed by
3c7676a0
 // an instance of LayerStore. Only getting layers as gzipped
 // tars is supported.
afd305c4
 func NewLayerProvidersFromStores(lss map[string]layer.Store) map[string]PushLayerProvider {
 	plps := make(map[string]PushLayerProvider)
 	for os, ls := range lss {
 		plps[os] = &storeLayerProvider{ls: ls}
3c7676a0
 	}
afd305c4
 	return plps
3c7676a0
 }
 
 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
 	}
d14b7212
 	sl := storeLayer{
3c7676a0
 		Layer: p,
 		ls:    l.ls,
 	}
d14b7212
 	if d, ok := p.(distribution.Describable); ok {
 		return &describableStoreLayer{
 			storeLayer:  sl,
 			describable: d,
 		}
 	}
 
 	return &sl
3c7676a0
 }
 
 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()
 }