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