github.com/docker/docker@v299999999.0.0-20200612211812-aaf470eca7b5+incompatible/distribution/config.go (about)

     1  package distribution // import "github.com/docker/docker/distribution"
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"fmt"
     7  	"io"
     8  	"runtime"
     9  
    10  	"github.com/docker/distribution"
    11  	"github.com/docker/distribution/manifest/schema2"
    12  	"github.com/docker/docker/api/types"
    13  	"github.com/docker/docker/distribution/metadata"
    14  	"github.com/docker/docker/distribution/xfer"
    15  	"github.com/docker/docker/image"
    16  	"github.com/docker/docker/layer"
    17  	"github.com/docker/docker/pkg/progress"
    18  	"github.com/docker/docker/pkg/system"
    19  	refstore "github.com/docker/docker/reference"
    20  	"github.com/docker/docker/registry"
    21  	"github.com/docker/libtrust"
    22  	digest "github.com/opencontainers/go-digest"
    23  	specs "github.com/opencontainers/image-spec/specs-go/v1"
    24  )
    25  
    26  // Config stores configuration for communicating
    27  // with a registry.
    28  type Config struct {
    29  	// MetaHeaders stores HTTP headers with metadata about the image
    30  	MetaHeaders map[string][]string
    31  	// AuthConfig holds authentication credentials for authenticating with
    32  	// the registry.
    33  	AuthConfig *types.AuthConfig
    34  	// ProgressOutput is the interface for showing the status of the pull
    35  	// operation.
    36  	ProgressOutput progress.Output
    37  	// RegistryService is the registry service to use for TLS configuration
    38  	// and endpoint lookup.
    39  	RegistryService registry.Service
    40  	// ImageEventLogger notifies events for a given image
    41  	ImageEventLogger func(id, name, action string)
    42  	// MetadataStore is the storage backend for distribution-specific
    43  	// metadata.
    44  	MetadataStore metadata.Store
    45  	// ImageStore manages images.
    46  	ImageStore ImageConfigStore
    47  	// ReferenceStore manages tags. This value is optional, when excluded
    48  	// content will not be tagged.
    49  	ReferenceStore refstore.Store
    50  	// RequireSchema2 ensures that only schema2 manifests are used.
    51  	RequireSchema2 bool
    52  }
    53  
    54  // ImagePullConfig stores pull configuration.
    55  type ImagePullConfig struct {
    56  	Config
    57  
    58  	// DownloadManager manages concurrent pulls.
    59  	DownloadManager RootFSDownloadManager
    60  	// Schema2Types is the valid schema2 configuration types allowed
    61  	// by the pull operation.
    62  	Schema2Types []string
    63  	// Platform is the requested platform of the image being pulled
    64  	Platform *specs.Platform
    65  }
    66  
    67  // ImagePushConfig stores push configuration.
    68  type ImagePushConfig struct {
    69  	Config
    70  
    71  	// ConfigMediaType is the configuration media type for
    72  	// schema2 manifests.
    73  	ConfigMediaType string
    74  	// LayerStores (indexed by operating system) manages layers.
    75  	LayerStores map[string]PushLayerProvider
    76  	// TrustKey is the private key for legacy signatures. This is typically
    77  	// an ephemeral key, since these signatures are no longer verified.
    78  	TrustKey libtrust.PrivateKey
    79  	// UploadManager dispatches uploads.
    80  	UploadManager *xfer.LayerUploadManager
    81  }
    82  
    83  // ImageConfigStore handles storing and getting image configurations
    84  // by digest. Allows getting an image configurations rootfs from the
    85  // configuration.
    86  type ImageConfigStore interface {
    87  	Put([]byte) (digest.Digest, error)
    88  	Get(digest.Digest) ([]byte, error)
    89  	RootFSFromConfig([]byte) (*image.RootFS, error)
    90  	PlatformFromConfig([]byte) (*specs.Platform, error)
    91  }
    92  
    93  // PushLayerProvider provides layers to be pushed by ChainID.
    94  type PushLayerProvider interface {
    95  	Get(layer.ChainID) (PushLayer, error)
    96  }
    97  
    98  // PushLayer is a pushable layer with metadata about the layer
    99  // and access to the content of the layer.
   100  type PushLayer interface {
   101  	ChainID() layer.ChainID
   102  	DiffID() layer.DiffID
   103  	Parent() PushLayer
   104  	Open() (io.ReadCloser, error)
   105  	Size() (int64, error)
   106  	MediaType() string
   107  	Release()
   108  }
   109  
   110  // RootFSDownloadManager handles downloading of the rootfs
   111  type RootFSDownloadManager interface {
   112  	// Download downloads the layers into the given initial rootfs and
   113  	// returns the final rootfs.
   114  	// Given progress output to track download progress
   115  	// Returns function to release download resources
   116  	Download(ctx context.Context, initialRootFS image.RootFS, os string, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error)
   117  }
   118  
   119  type imageConfigStore struct {
   120  	image.Store
   121  }
   122  
   123  // NewImageConfigStoreFromStore returns an ImageConfigStore backed
   124  // by an image.Store for container images.
   125  func NewImageConfigStoreFromStore(is image.Store) ImageConfigStore {
   126  	return &imageConfigStore{
   127  		Store: is,
   128  	}
   129  }
   130  
   131  func (s *imageConfigStore) Put(c []byte) (digest.Digest, error) {
   132  	id, err := s.Store.Create(c)
   133  	return digest.Digest(id), err
   134  }
   135  
   136  func (s *imageConfigStore) Get(d digest.Digest) ([]byte, error) {
   137  	img, err := s.Store.Get(image.IDFromDigest(d))
   138  	if err != nil {
   139  		return nil, err
   140  	}
   141  	return img.RawJSON(), nil
   142  }
   143  
   144  func (s *imageConfigStore) RootFSFromConfig(c []byte) (*image.RootFS, error) {
   145  	var unmarshalledConfig image.Image
   146  	if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
   147  		return nil, err
   148  	}
   149  	return unmarshalledConfig.RootFS, nil
   150  }
   151  
   152  func (s *imageConfigStore) PlatformFromConfig(c []byte) (*specs.Platform, error) {
   153  	var unmarshalledConfig image.Image
   154  	if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
   155  		return nil, err
   156  	}
   157  
   158  	// fail immediately on Windows when downloading a non-Windows image
   159  	// and vice versa. Exception on Windows if Linux Containers are enabled.
   160  	if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" && !system.LCOWSupported() {
   161  		return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
   162  	} else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" {
   163  		return nil, fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
   164  	}
   165  
   166  	os := unmarshalledConfig.OS
   167  	if os == "" {
   168  		os = runtime.GOOS
   169  	}
   170  	if !system.IsOSSupported(os) {
   171  		return nil, system.ErrNotSupportedOperatingSystem
   172  	}
   173  	return &specs.Platform{OS: os, Architecture: unmarshalledConfig.Architecture, Variant: unmarshalledConfig.Variant, OSVersion: unmarshalledConfig.OSVersion}, nil
   174  }
   175  
   176  type storeLayerProvider struct {
   177  	ls layer.Store
   178  }
   179  
   180  // NewLayerProvidersFromStores returns layer providers backed by
   181  // an instance of LayerStore. Only getting layers as gzipped
   182  // tars is supported.
   183  func NewLayerProvidersFromStores(lss map[string]layer.Store) map[string]PushLayerProvider {
   184  	plps := make(map[string]PushLayerProvider)
   185  	for os, ls := range lss {
   186  		plps[os] = &storeLayerProvider{ls: ls}
   187  	}
   188  	return plps
   189  }
   190  
   191  func (p *storeLayerProvider) Get(lid layer.ChainID) (PushLayer, error) {
   192  	if lid == "" {
   193  		return &storeLayer{
   194  			Layer: layer.EmptyLayer,
   195  		}, nil
   196  	}
   197  	l, err := p.ls.Get(lid)
   198  	if err != nil {
   199  		return nil, err
   200  	}
   201  
   202  	sl := storeLayer{
   203  		Layer: l,
   204  		ls:    p.ls,
   205  	}
   206  	if d, ok := l.(distribution.Describable); ok {
   207  		return &describableStoreLayer{
   208  			storeLayer:  sl,
   209  			describable: d,
   210  		}, nil
   211  	}
   212  
   213  	return &sl, nil
   214  }
   215  
   216  type storeLayer struct {
   217  	layer.Layer
   218  	ls layer.Store
   219  }
   220  
   221  func (l *storeLayer) Parent() PushLayer {
   222  	p := l.Layer.Parent()
   223  	if p == nil {
   224  		return nil
   225  	}
   226  	sl := storeLayer{
   227  		Layer: p,
   228  		ls:    l.ls,
   229  	}
   230  	if d, ok := p.(distribution.Describable); ok {
   231  		return &describableStoreLayer{
   232  			storeLayer:  sl,
   233  			describable: d,
   234  		}
   235  	}
   236  
   237  	return &sl
   238  }
   239  
   240  func (l *storeLayer) Open() (io.ReadCloser, error) {
   241  	return l.Layer.TarStream()
   242  }
   243  
   244  func (l *storeLayer) Size() (int64, error) {
   245  	return l.Layer.DiffSize()
   246  }
   247  
   248  func (l *storeLayer) MediaType() string {
   249  	// layer store always returns uncompressed tars
   250  	return schema2.MediaTypeUncompressedLayer
   251  }
   252  
   253  func (l *storeLayer) Release() {
   254  	if l.ls != nil {
   255  		layer.ReleaseAndLog(l.ls, l.Layer)
   256  	}
   257  }
   258  
   259  type describableStoreLayer struct {
   260  	storeLayer
   261  	describable distribution.Describable
   262  }
   263  
   264  func (l *describableStoreLayer) Descriptor() distribution.Descriptor {
   265  	return l.describable.Descriptor()
   266  }