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 }