Tizen_4.0 base
[platform/upstream/docker-engine.git] / distribution / config.go
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/ioutils"
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         "github.com/opencontainers/go-digest"
23         "golang.org/x/net/context"
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 to ensure it can be validated
64         // when the host platform supports multiple image operating systems.
65         Platform string
66 }
67
68 // ImagePushConfig stores push configuration.
69 type ImagePushConfig struct {
70         Config
71
72         // ConfigMediaType is the configuration media type for
73         // schema2 manifests.
74         ConfigMediaType string
75         // LayerStore manages layers.
76         LayerStore PushLayerProvider
77         // TrustKey is the private key for legacy signatures. This is typically
78         // an ephemeral key, since these signatures are no longer verified.
79         TrustKey libtrust.PrivateKey
80         // UploadManager dispatches uploads.
81         UploadManager *xfer.LayerUploadManager
82 }
83
84 // ImageConfigStore handles storing and getting image configurations
85 // by digest. Allows getting an image configurations rootfs from the
86 // configuration.
87 type ImageConfigStore interface {
88         Put([]byte) (digest.Digest, error)
89         Get(digest.Digest) ([]byte, error)
90         GetTarSeekStream(digest.Digest) (ioutils.ReadSeekCloser, error)
91         RootFSAndPlatformFromConfig([]byte) (*image.RootFS, layer.Platform, 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, error)
107         MediaType() string
108         Release()
109 }
110
111 // RootFSDownloadManager handles downloading of the rootfs
112 type RootFSDownloadManager interface {
113         // Download downloads the layers into the given initial rootfs and
114         // returns the final rootfs.
115         // Given progress output to track download progress
116         // Returns function to release download resources
117         Download(ctx context.Context, initialRootFS image.RootFS, platform layer.Platform, layers []xfer.DownloadDescriptor, progressOutput progress.Output) (image.RootFS, func(), error)
118 }
119
120 type imageConfigStore struct {
121         image.Store
122         deltaStore image.Store
123 }
124
125 // NewImageConfigStoreFromStore returns an ImageConfigStore backed
126 // by an image.Store for container images.
127 func NewImageConfigStoreFromStore(is, deltaImageStore image.Store) ImageConfigStore {
128         return &imageConfigStore{
129                 Store: is,
130                 deltaStore: deltaImageStore,
131         }
132 }
133
134 func (s *imageConfigStore) Put(c []byte) (digest.Digest, error) {
135         id, err := s.Store.Create(c)
136         return digest.Digest(id), err
137 }
138
139 func (s *imageConfigStore) Get(d digest.Digest) ([]byte, error) {
140         img, err := s.Store.Get(image.IDFromDigest(d))
141         if err != nil {
142                 return nil, err
143         }
144         return img.RawJSON(), nil
145 }
146
147 func (s *imageConfigStore) GetTarSeekStream(d digest.Digest) (ioutils.ReadSeekCloser, error) {
148         stream, err := s.Store.GetTarSeekStream(image.IDFromDigest(d))
149         if err != nil && s.deltaStore != nil {
150                 return s.deltaStore.GetTarSeekStream(image.IDFromDigest(d))
151         }
152         return stream, err
153 }
154
155 func (s *imageConfigStore) RootFSAndPlatformFromConfig(c []byte) (*image.RootFS, layer.Platform, error) {
156         var unmarshalledConfig image.Image
157         if err := json.Unmarshal(c, &unmarshalledConfig); err != nil {
158                 return nil, "", err
159         }
160
161         // fail immediately on Windows when downloading a non-Windows image
162         // and vice versa. Exception on Windows if Linux Containers are enabled.
163         if runtime.GOOS == "windows" && unmarshalledConfig.OS == "linux" && !system.LCOWSupported() {
164                 return nil, "", fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
165         } else if runtime.GOOS != "windows" && unmarshalledConfig.OS == "windows" {
166                 return nil, "", fmt.Errorf("image operating system %q cannot be used on this platform", unmarshalledConfig.OS)
167         }
168
169         platform := ""
170         if runtime.GOOS == "windows" {
171                 platform = unmarshalledConfig.OS
172         }
173         return unmarshalledConfig.RootFS, layer.Platform(platform), nil
174 }
175
176 type storeLayerProvider struct {
177         ls layer.Store
178 }
179
180 // NewLayerProviderFromStore returns a layer provider backed by
181 // an instance of LayerStore. Only getting layers as gzipped
182 // tars is supported.
183 func NewLayerProviderFromStore(ls layer.Store) PushLayerProvider {
184         return &storeLayerProvider{
185                 ls: ls,
186         }
187 }
188
189 func (p *storeLayerProvider) Get(lid layer.ChainID) (PushLayer, error) {
190         if lid == "" {
191                 return &storeLayer{
192                         Layer: layer.EmptyLayer,
193                 }, nil
194         }
195         l, err := p.ls.Get(lid)
196         if err != nil {
197                 return nil, err
198         }
199
200         sl := storeLayer{
201                 Layer: l,
202                 ls:    p.ls,
203         }
204         if d, ok := l.(distribution.Describable); ok {
205                 return &describableStoreLayer{
206                         storeLayer:  sl,
207                         describable: d,
208                 }, nil
209         }
210
211         return &sl, nil
212 }
213
214 type storeLayer struct {
215         layer.Layer
216         ls layer.Store
217 }
218
219 func (l *storeLayer) Parent() PushLayer {
220         p := l.Layer.Parent()
221         if p == nil {
222                 return nil
223         }
224         sl := storeLayer{
225                 Layer: p,
226                 ls:    l.ls,
227         }
228         if d, ok := p.(distribution.Describable); ok {
229                 return &describableStoreLayer{
230                         storeLayer:  sl,
231                         describable: d,
232                 }
233         }
234
235         return &sl
236 }
237
238 func (l *storeLayer) Open() (io.ReadCloser, error) {
239         return l.Layer.TarStream()
240 }
241
242 func (l *storeLayer) Size() (int64, error) {
243         return l.Layer.DiffSize()
244 }
245
246 func (l *storeLayer) MediaType() string {
247         // layer store always returns uncompressed tars
248         return schema2.MediaTypeUncompressedLayer
249 }
250
251 func (l *storeLayer) Release() {
252         if l.ls != nil {
253                 layer.ReleaseAndLog(l.ls, l.Layer)
254         }
255 }
256
257 type describableStoreLayer struct {
258         storeLayer
259         describable distribution.Describable
260 }
261
262 func (l *describableStoreLayer) Descriptor() distribution.Descriptor {
263         return l.describable.Descriptor()
264 }