github.com/tonistiigi/docker@v0.10.1-0.20240229224939-974013b0dc6a/distribution/config.go (about)

     1  package distribution // import "github.com/docker/docker/distribution"
     2  
     3  import (
     4  	"context"
     5  	"encoding/json"
     6  	"io"
     7  	"runtime"
     8  
     9  	"github.com/distribution/reference"
    10  	"github.com/docker/distribution"
    11  	"github.com/docker/distribution/manifest/schema2"
    12  	"github.com/docker/docker/api/types/events"
    13  	"github.com/docker/docker/api/types/registry"
    14  	"github.com/docker/docker/distribution/metadata"
    15  	"github.com/docker/docker/distribution/xfer"
    16  	"github.com/docker/docker/image"
    17  	"github.com/docker/docker/layer"
    18  	"github.com/docker/docker/pkg/progress"
    19  	refstore "github.com/docker/docker/reference"
    20  	registrypkg "github.com/docker/docker/registry"
    21  	"github.com/opencontainers/go-digest"
    22  	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
    23  	"github.com/pkg/errors"
    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 *registry.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 RegistryResolver
    40  	// ImageEventLogger notifies events for a given image
    41  	ImageEventLogger func(id, name string, action events.Action)
    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  }
    51  
    52  // ImagePullConfig stores pull configuration.
    53  type ImagePullConfig struct {
    54  	Config
    55  
    56  	// DownloadManager manages concurrent pulls.
    57  	DownloadManager *xfer.LayerDownloadManager
    58  	// Schema2Types is an optional list of valid schema2 configuration types
    59  	// allowed by the pull operation. If omitted, the default list of accepted
    60  	// types is used.
    61  	Schema2Types []string
    62  	// Platform is the requested platform of the image being pulled
    63  	Platform *ocispec.Platform
    64  }
    65  
    66  // ImagePushConfig stores push configuration.
    67  type ImagePushConfig struct {
    68  	Config
    69  
    70  	// ConfigMediaType is the configuration media type for
    71  	// schema2 manifests.
    72  	ConfigMediaType string
    73  	// LayerStores manages layers.
    74  	LayerStores PushLayerProvider
    75  	// UploadManager dispatches uploads.
    76  	UploadManager *xfer.LayerUploadManager
    77  }
    78  
    79  // RegistryResolver is used for TLS configuration and endpoint lookup.
    80  type RegistryResolver interface {
    81  	LookupPushEndpoints(hostname string) (endpoints []registrypkg.APIEndpoint, err error)
    82  	LookupPullEndpoints(hostname string) (endpoints []registrypkg.APIEndpoint, err error)
    83  	ResolveRepository(name reference.Named) (*registrypkg.RepositoryInfo, error)
    84  }
    85  
    86  // ImageConfigStore handles storing and getting image configurations
    87  // by digest. Allows getting an image configurations rootfs from the
    88  // configuration.
    89  type ImageConfigStore interface {
    90  	Put(context.Context, []byte) (digest.Digest, error)
    91  	Get(context.Context, digest.Digest) ([]byte, error)
    92  }
    93  
    94  // PushLayerProvider provides layers to be pushed by ChainID.
    95  type PushLayerProvider interface {
    96  	Get(layer.ChainID) (PushLayer, error)
    97  }
    98  
    99  // PushLayer is a pushable layer with metadata about the layer
   100  // and access to the content of the layer.
   101  type PushLayer interface {
   102  	ChainID() layer.ChainID
   103  	DiffID() layer.DiffID
   104  	Parent() PushLayer
   105  	Open() (io.ReadCloser, error)
   106  	Size() int64
   107  	MediaType() string
   108  	Release()
   109  }
   110  
   111  type imageConfigStore struct {
   112  	image.Store
   113  }
   114  
   115  // NewImageConfigStoreFromStore returns an ImageConfigStore backed
   116  // by an image.Store for container images.
   117  func NewImageConfigStoreFromStore(is image.Store) ImageConfigStore {
   118  	return &imageConfigStore{
   119  		Store: is,
   120  	}
   121  }
   122  
   123  func (s *imageConfigStore) Put(_ context.Context, c []byte) (digest.Digest, error) {
   124  	id, err := s.Store.Create(c)
   125  	return digest.Digest(id), err
   126  }
   127  
   128  func (s *imageConfigStore) Get(_ context.Context, d digest.Digest) ([]byte, error) {
   129  	img, err := s.Store.Get(image.ID(d))
   130  	if err != nil {
   131  		return nil, err
   132  	}
   133  	return img.RawJSON(), nil
   134  }
   135  
   136  func rootFSFromConfig(c []byte) (*image.RootFS, error) {
   137  	var unmarshalledConfig image.Image
   138  	if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
   139  		return nil, err
   140  	}
   141  	return unmarshalledConfig.RootFS, nil
   142  }
   143  
   144  func platformFromConfig(c []byte) (*ocispec.Platform, error) {
   145  	var unmarshalledConfig image.Image
   146  	if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
   147  		return nil, err
   148  	}
   149  
   150  	os := unmarshalledConfig.OS
   151  	if os == "" {
   152  		os = runtime.GOOS
   153  	}
   154  	if err := image.CheckOS(os); err != nil {
   155  		return nil, errors.Wrapf(err, "image operating system %q cannot be used on this platform", os)
   156  	}
   157  	return &ocispec.Platform{
   158  		OS:           os,
   159  		Architecture: unmarshalledConfig.Architecture,
   160  		Variant:      unmarshalledConfig.Variant,
   161  		OSVersion:    unmarshalledConfig.OSVersion,
   162  	}, nil
   163  }
   164  
   165  type storeLayerProvider struct {
   166  	ls layer.Store
   167  }
   168  
   169  // NewLayerProvidersFromStore returns layer providers backed by
   170  // an instance of LayerStore. Only getting layers as gzipped
   171  // tars is supported.
   172  func NewLayerProvidersFromStore(ls layer.Store) PushLayerProvider {
   173  	return &storeLayerProvider{ls: ls}
   174  }
   175  
   176  func (p *storeLayerProvider) Get(lid layer.ChainID) (PushLayer, error) {
   177  	if lid == "" {
   178  		return &storeLayer{
   179  			Layer: layer.EmptyLayer,
   180  		}, nil
   181  	}
   182  	l, err := p.ls.Get(lid)
   183  	if err != nil {
   184  		return nil, err
   185  	}
   186  
   187  	sl := storeLayer{
   188  		Layer: l,
   189  		ls:    p.ls,
   190  	}
   191  	if d, ok := l.(distribution.Describable); ok {
   192  		return &describableStoreLayer{
   193  			storeLayer:  sl,
   194  			describable: d,
   195  		}, nil
   196  	}
   197  
   198  	return &sl, nil
   199  }
   200  
   201  type storeLayer struct {
   202  	layer.Layer
   203  	ls layer.Store
   204  }
   205  
   206  func (l *storeLayer) Parent() PushLayer {
   207  	p := l.Layer.Parent()
   208  	if p == nil {
   209  		return nil
   210  	}
   211  	sl := storeLayer{
   212  		Layer: p,
   213  		ls:    l.ls,
   214  	}
   215  	if d, ok := p.(distribution.Describable); ok {
   216  		return &describableStoreLayer{
   217  			storeLayer:  sl,
   218  			describable: d,
   219  		}
   220  	}
   221  
   222  	return &sl
   223  }
   224  
   225  func (l *storeLayer) Open() (io.ReadCloser, error) {
   226  	return l.Layer.TarStream()
   227  }
   228  
   229  func (l *storeLayer) Size() int64 {
   230  	return l.Layer.DiffSize()
   231  }
   232  
   233  func (l *storeLayer) MediaType() string {
   234  	// layer store always returns uncompressed tars
   235  	return schema2.MediaTypeUncompressedLayer
   236  }
   237  
   238  func (l *storeLayer) Release() {
   239  	if l.ls != nil {
   240  		layer.ReleaseAndLog(l.ls, l.Layer)
   241  	}
   242  }
   243  
   244  type describableStoreLayer struct {
   245  	storeLayer
   246  	describable distribution.Describable
   247  }
   248  
   249  func (l *describableStoreLayer) Descriptor() distribution.Descriptor {
   250  	return l.describable.Descriptor()
   251  }