Browse code

Use describable interfaces

Replace use of foreign sources with descriptors and describable

Signed-off-by: Derek McGowan <derek@mcgstyle.net> (github: dmcgowan)

Derek McGowan authored on 2016/06/07 09:49:34
Showing 16 changed files
... ...
@@ -133,7 +133,7 @@ type v2LayerDescriptor struct {
133 133
 	V2MetadataService *metadata.V2MetadataService
134 134
 	tmpFile           *os.File
135 135
 	verifier          digest.Verifier
136
-	foreignSrc        *distribution.Descriptor
136
+	src               distribution.Descriptor
137 137
 }
138 138
 
139 139
 func (ld *v2LayerDescriptor) Key() string {
... ...
@@ -511,14 +511,7 @@ func (p *v2Puller) pullSchema2(ctx context.Context, ref reference.Named, mfst *s
511 511
 			repo:              p.repo,
512 512
 			repoInfo:          p.repoInfo,
513 513
 			V2MetadataService: p.V2MetadataService,
514
-		}
515
-
516
-		if d.MediaType == schema2.MediaTypeForeignLayer && len(d.URLs) > 0 {
517
-			if !layer.ForeignSourceSupported() {
518
-				return "", "", errors.New("foreign layers are not supported on this OS")
519
-			}
520
-
521
-			layerDescriptor.foreignSrc = &d
514
+			src:               d,
522 515
 		}
523 516
 
524 517
 		descriptors = append(descriptors, layerDescriptor)
... ...
@@ -11,9 +11,9 @@ import (
11 11
 	"github.com/docker/distribution"
12 12
 	"github.com/docker/distribution/context"
13 13
 	"github.com/docker/distribution/manifest/schema1"
14
+	"github.com/docker/distribution/manifest/schema2"
14 15
 	"github.com/docker/distribution/registry/client/transport"
15 16
 	"github.com/docker/docker/image"
16
-	"github.com/docker/docker/layer"
17 17
 )
18 18
 
19 19
 func detectBaseLayer(is image.Store, m *schema1.Manifest, rootFS *image.RootFS) error {
... ...
@@ -35,14 +35,17 @@ func detectBaseLayer(is image.Store, m *schema1.Manifest, rootFS *image.RootFS)
35 35
 	return fmt.Errorf("Invalid base layer %q", v1img.Parent)
36 36
 }
37 37
 
38
-var _ layer.ForeignSourcer = &v2LayerDescriptor{}
38
+var _ distribution.Describable = &v2LayerDescriptor{}
39 39
 
40
-func (ld *v2LayerDescriptor) ForeignSource() *distribution.Descriptor {
41
-	return ld.foreignSrc
40
+func (ld *v2LayerDescriptor) Descriptor() distribution.Descriptor {
41
+	if ld.src.MediaType == schema2.MediaTypeForeignLayer && len(ld.src.URLs) > 0 {
42
+		return ld.src
43
+	}
44
+	return distribution.Descriptor{}
42 45
 }
43 46
 
44 47
 func (ld *v2LayerDescriptor) open(ctx context.Context) (distribution.ReadSeekCloser, error) {
45
-	if ld.foreignSrc == nil {
48
+	if len(ld.src.URLs) == 0 {
46 49
 		blobs := ld.repo.Blobs(ctx)
47 50
 		return blobs.Open(ctx, ld.digest)
48 51
 	}
... ...
@@ -53,7 +56,7 @@ func (ld *v2LayerDescriptor) open(ctx context.Context) (distribution.ReadSeekClo
53 53
 	)
54 54
 
55 55
 	// Find the first URL that results in a 200 result code.
56
-	for _, url := range ld.foreignSrc.URLs {
56
+	for _, url := range ld.src.URLs {
57 57
 		rsc = transport.NewHTTPReadSeeker(http.DefaultClient, url, nil)
58 58
 		_, err = rsc.Seek(0, os.SEEK_SET)
59 59
 		if err == nil {
... ...
@@ -240,10 +240,10 @@ func (pd *v2PushDescriptor) DiffID() layer.DiffID {
240 240
 }
241 241
 
242 242
 func (pd *v2PushDescriptor) Upload(ctx context.Context, progressOutput progress.Output) (distribution.Descriptor, error) {
243
-	if fs, ok := pd.layer.(layer.ForeignSourcer); ok {
244
-		if d := fs.ForeignSource(); d != nil {
243
+	if fs, ok := pd.layer.(distribution.Describable); ok {
244
+		if d := fs.Descriptor(); len(d.URLs) > 0 {
245 245
 			progress.Update(progressOutput, pd.ID(), "Skipped foreign layer")
246
-			return *d, nil
246
+			return d, nil
247 247
 		}
248 248
 	}
249 249
 
... ...
@@ -319,11 +319,15 @@ func (ldm *LayerDownloadManager) makeDownloadFunc(descriptor DownloadDescriptor,
319 319
 				return
320 320
 			}
321 321
 
322
-			var src *distribution.Descriptor
323
-			if fs, ok := descriptor.(layer.ForeignSourcer); ok {
324
-				src = fs.ForeignSource()
322
+			var src distribution.Descriptor
323
+			if fs, ok := descriptor.(distribution.Describable); ok {
324
+				src = fs.Descriptor()
325
+			}
326
+			if ds, ok := d.layerStore.(layer.DescribableStore); ok {
327
+				d.layer, err = ds.RegisterWithDescriptor(inflatedLayerData, parentLayer, src)
328
+			} else {
329
+				d.layer, err = d.layerStore.Register(inflatedLayerData, parentLayer)
325 330
 			}
326
-			d.layer, err = d.layerStore.RegisterForeign(inflatedLayerData, parentLayer, src)
327 331
 			if err != nil {
328 332
 				select {
329 333
 				case <-d.Transfer.Context().Done():
... ...
@@ -414,11 +418,15 @@ func (ldm *LayerDownloadManager) makeDownloadFuncFromDownload(descriptor Downloa
414 414
 			}
415 415
 			defer layerReader.Close()
416 416
 
417
-			var src *distribution.Descriptor
418
-			if fs, ok := l.(layer.ForeignSourcer); ok {
419
-				src = fs.ForeignSource()
417
+			var src distribution.Descriptor
418
+			if fs, ok := l.(distribution.Describable); ok {
419
+				src = fs.Descriptor()
420
+			}
421
+			if ds, ok := d.layerStore.(layer.DescribableStore); ok {
422
+				d.layer, err = ds.RegisterWithDescriptor(layerReader, parentLayer, src)
423
+			} else {
424
+				d.layer, err = d.layerStore.Register(layerReader, parentLayer)
420 425
 			}
421
-			d.layer, err = d.layerStore.RegisterForeign(layerReader, parentLayer, src)
422 426
 			if err != nil {
423 427
 				d.err = fmt.Errorf("failed to register layer: %v", err)
424 428
 				return
... ...
@@ -72,10 +72,10 @@ func createChainIDFromParent(parent layer.ChainID, dgsts ...layer.DiffID) layer.
72 72
 }
73 73
 
74 74
 func (ls *mockLayerStore) Register(reader io.Reader, parentID layer.ChainID) (layer.Layer, error) {
75
-	return ls.RegisterForeign(reader, parentID, nil)
75
+	return ls.RegisterWithDescriptor(reader, parentID, distribution.Descriptor{})
76 76
 }
77 77
 
78
-func (ls *mockLayerStore) RegisterForeign(reader io.Reader, parentID layer.ChainID, _ *distribution.Descriptor) (layer.Layer, error) {
78
+func (ls *mockLayerStore) RegisterWithDescriptor(reader io.Reader, parentID layer.ChainID, _ distribution.Descriptor) (layer.Layer, error) {
79 79
 	var (
80 80
 		parent layer.Layer
81 81
 		err    error
... ...
@@ -64,10 +64,6 @@ func (l *tarexporter) Load(inTar io.ReadCloser, outStream io.Writer, quiet bool)
64 64
 	var parentLinks []parentLink
65 65
 
66 66
 	for _, m := range manifest {
67
-		if m.LayerSources != nil && !layer.ForeignSourceSupported() {
68
-			return fmt.Errorf("invalid manifest, foreign layers not supported on this operating system")
69
-		}
70
-
71 67
 		configPath, err := safePath(tmpDir, m.Config)
72 68
 		if err != nil {
73 69
 			return err
... ...
@@ -156,7 +152,7 @@ func (l *tarexporter) setParentID(id, parentID image.ID) error {
156 156
 	return l.is.SetParent(id, parentID)
157 157
 }
158 158
 
159
-func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string, foreignSrc *distribution.Descriptor, progressOutput progress.Output) (layer.Layer, error) {
159
+func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string, foreignSrc distribution.Descriptor, progressOutput progress.Output) (layer.Layer, error) {
160 160
 	rawTar, err := os.Open(filename)
161 161
 	if err != nil {
162 162
 		logrus.Debugf("Error reading embedded tar: %v", err)
... ...
@@ -179,9 +175,17 @@ func (l *tarexporter) loadLayer(filename string, rootFS image.RootFS, id string,
179 179
 
180 180
 		progressReader := progress.NewProgressReader(inflatedLayerData, progressOutput, fileInfo.Size(), stringid.TruncateID(id), "Loading layer")
181 181
 
182
-		return l.ls.RegisterForeign(progressReader, rootFS.ChainID(), foreignSrc)
182
+		if ds, ok := l.ls.(layer.DescribableStore); ok {
183
+			return ds.RegisterWithDescriptor(progressReader, rootFS.ChainID(), foreignSrc)
184
+		}
185
+		return l.ls.Register(progressReader, rootFS.ChainID())
186
+
187
+	}
188
+
189
+	if ds, ok := l.ls.(layer.DescribableStore); ok {
190
+		return ds.RegisterWithDescriptor(inflatedLayerData, rootFS.ChainID(), foreignSrc)
183 191
 	}
184
-	return l.ls.RegisterForeign(inflatedLayerData, rootFS.ChainID(), foreignSrc)
192
+	return l.ls.Register(inflatedLayerData, rootFS.ChainID())
185 193
 }
186 194
 
187 195
 func (l *tarexporter) setLoadedTag(ref reference.NamedTagged, imgID image.ID, outStream io.Writer) error {
... ...
@@ -303,7 +307,7 @@ func (l *tarexporter) legacyLoadImage(oldID, sourceDir string, loadedMap map[str
303 303
 	if err != nil {
304 304
 		return err
305 305
 	}
306
-	newLayer, err := l.loadLayer(layerPath, *rootFS, oldID, nil, progressOutput)
306
+	newLayer, err := l.loadLayer(layerPath, *rootFS, oldID, distribution.Descriptor{}, progressOutput)
307 307
 	if err != nil {
308 308
 		return err
309 309
 	}
... ...
@@ -216,7 +216,7 @@ func (s *saveSession) save(outStream io.Writer) error {
216 216
 	return nil
217 217
 }
218 218
 
219
-func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]*distribution.Descriptor, error) {
219
+func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]distribution.Descriptor, error) {
220 220
 	img, err := s.is.Get(id)
221 221
 	if err != nil {
222 222
 		return nil, err
... ...
@@ -228,7 +228,7 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]*distribution.Des
228 228
 
229 229
 	var parent digest.Digest
230 230
 	var layers []string
231
-	var foreignSrcs map[layer.DiffID]*distribution.Descriptor
231
+	var foreignSrcs map[layer.DiffID]distribution.Descriptor
232 232
 	for i := range img.RootFS.DiffIDs {
233 233
 		v1Img := image.V1Image{}
234 234
 		if i == len(img.RootFS.DiffIDs)-1 {
... ...
@@ -252,9 +252,9 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]*distribution.Des
252 252
 		}
253 253
 		layers = append(layers, v1Img.ID)
254 254
 		parent = v1ID
255
-		if src != nil {
255
+		if src.Digest != "" {
256 256
 			if foreignSrcs == nil {
257
-				foreignSrcs = make(map[layer.DiffID]*distribution.Descriptor)
257
+				foreignSrcs = make(map[layer.DiffID]distribution.Descriptor)
258 258
 			}
259 259
 			foreignSrcs[img.RootFS.DiffIDs[i]] = src
260 260
 		}
... ...
@@ -272,65 +272,65 @@ func (s *saveSession) saveImage(id image.ID) (map[layer.DiffID]*distribution.Des
272 272
 	return foreignSrcs, nil
273 273
 }
274 274
 
275
-func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, createdTime time.Time) (*distribution.Descriptor, error) {
275
+func (s *saveSession) saveLayer(id layer.ChainID, legacyImg image.V1Image, createdTime time.Time) (distribution.Descriptor, error) {
276 276
 	if _, exists := s.savedLayers[legacyImg.ID]; exists {
277
-		return nil, nil
277
+		return distribution.Descriptor{}, nil
278 278
 	}
279 279
 
280 280
 	outDir := filepath.Join(s.outDir, legacyImg.ID)
281 281
 	if err := os.Mkdir(outDir, 0755); err != nil {
282
-		return nil, err
282
+		return distribution.Descriptor{}, err
283 283
 	}
284 284
 
285 285
 	// todo: why is this version file here?
286 286
 	if err := ioutil.WriteFile(filepath.Join(outDir, legacyVersionFileName), []byte("1.0"), 0644); err != nil {
287
-		return nil, err
287
+		return distribution.Descriptor{}, err
288 288
 	}
289 289
 
290 290
 	imageConfig, err := json.Marshal(legacyImg)
291 291
 	if err != nil {
292
-		return nil, err
292
+		return distribution.Descriptor{}, err
293 293
 	}
294 294
 
295 295
 	if err := ioutil.WriteFile(filepath.Join(outDir, legacyConfigFileName), imageConfig, 0644); err != nil {
296
-		return nil, err
296
+		return distribution.Descriptor{}, err
297 297
 	}
298 298
 
299 299
 	// serialize filesystem
300 300
 	tarFile, err := os.Create(filepath.Join(outDir, legacyLayerFileName))
301 301
 	if err != nil {
302
-		return nil, err
302
+		return distribution.Descriptor{}, err
303 303
 	}
304 304
 	defer tarFile.Close()
305 305
 
306 306
 	l, err := s.ls.Get(id)
307 307
 	if err != nil {
308
-		return nil, err
308
+		return distribution.Descriptor{}, err
309 309
 	}
310 310
 	defer layer.ReleaseAndLog(s.ls, l)
311 311
 
312 312
 	arch, err := l.TarStream()
313 313
 	if err != nil {
314
-		return nil, err
314
+		return distribution.Descriptor{}, err
315 315
 	}
316 316
 	defer arch.Close()
317 317
 
318 318
 	if _, err := io.Copy(tarFile, arch); err != nil {
319
-		return nil, err
319
+		return distribution.Descriptor{}, err
320 320
 	}
321 321
 
322 322
 	for _, fname := range []string{"", legacyVersionFileName, legacyConfigFileName, legacyLayerFileName} {
323 323
 		// todo: maybe save layer created timestamp?
324 324
 		if err := system.Chtimes(filepath.Join(outDir, fname), createdTime, createdTime); err != nil {
325
-			return nil, err
325
+			return distribution.Descriptor{}, err
326 326
 		}
327 327
 	}
328 328
 
329 329
 	s.savedLayers[legacyImg.ID] = struct{}{}
330 330
 
331
-	var src *distribution.Descriptor
332
-	if fs, ok := l.(layer.ForeignSourcer); ok {
333
-		src = fs.ForeignSource()
331
+	var src distribution.Descriptor
332
+	if fs, ok := l.(distribution.Describable); ok {
333
+		src = fs.Descriptor()
334 334
 	}
335 335
 	return src, nil
336 336
 }
... ...
@@ -19,8 +19,8 @@ type manifestItem struct {
19 19
 	Config       string
20 20
 	RepoTags     []string
21 21
 	Layers       []string
22
-	Parent       image.ID                                  `json:",omitempty"`
23
-	LayerSources map[layer.DiffID]*distribution.Descriptor `json:",omitempty"`
22
+	Parent       image.ID                                 `json:",omitempty"`
23
+	LayerSources map[layer.DiffID]distribution.Descriptor `json:",omitempty"`
24 24
 }
25 25
 
26 26
 type tarexporter struct {
... ...
@@ -26,9 +26,6 @@ var (
26 26
 		// digest.SHA384, // Currently not used
27 27
 		// digest.SHA512, // Currently not used
28 28
 	}
29
-
30
-	// ErrNoForeignSource is returned when no foreign source is set for a layer.
31
-	ErrNoForeignSource = errors.New("layer does not have a foreign source")
32 29
 )
33 30
 
34 31
 type fileMetadataStore struct {
... ...
@@ -103,7 +100,7 @@ func (fm *fileMetadataTransaction) SetCacheID(cacheID string) error {
103 103
 	return ioutil.WriteFile(filepath.Join(fm.root, "cache-id"), []byte(cacheID), 0644)
104 104
 }
105 105
 
106
-func (fm *fileMetadataTransaction) SetForeignSource(ref distribution.Descriptor) error {
106
+func (fm *fileMetadataTransaction) SetDescriptor(ref distribution.Descriptor) error {
107 107
 	jsonRef, err := json.Marshal(ref)
108 108
 	if err != nil {
109 109
 		return err
... ...
@@ -204,11 +201,12 @@ func (fms *fileMetadataStore) GetCacheID(layer ChainID) (string, error) {
204 204
 	return content, nil
205 205
 }
206 206
 
207
-func (fms *fileMetadataStore) GetForeignSource(layer ChainID) (distribution.Descriptor, error) {
207
+func (fms *fileMetadataStore) GetDescriptor(layer ChainID) (distribution.Descriptor, error) {
208 208
 	content, err := ioutil.ReadFile(fms.getLayerFilename(layer, "descriptor.json"))
209 209
 	if err != nil {
210 210
 		if os.IsNotExist(err) {
211
-			return distribution.Descriptor{}, ErrNoForeignSource
211
+			// only return empty descriptor to represent what is stored
212
+			return distribution.Descriptor{}, nil
212 213
 		}
213 214
 		return distribution.Descriptor{}, err
214 215
 	}
... ...
@@ -108,14 +108,6 @@ type Layer interface {
108 108
 	Metadata() (map[string]string, error)
109 109
 }
110 110
 
111
-// ForeignSourcer is an interface used to describe the source of layers
112
-// and objects representing layers, when the source is a foreign URL.
113
-type ForeignSourcer interface {
114
-	// ForeignSource returns the descriptor for this layer if it is
115
-	// a foreign layer, or nil for ordinary layers.
116
-	ForeignSource() *distribution.Descriptor
117
-}
118
-
119 111
 // RWLayer represents a layer which is
120 112
 // read and writable
121 113
 type RWLayer interface {
... ...
@@ -177,7 +169,6 @@ type MountInit func(root string) error
177 177
 // read-only and read-write layers.
178 178
 type Store interface {
179 179
 	Register(io.Reader, ChainID) (Layer, error)
180
-	RegisterForeign(io.Reader, ChainID, *distribution.Descriptor) (Layer, error)
181 180
 	Get(ChainID) (Layer, error)
182 181
 	Release(Layer) ([]Metadata, error)
183 182
 
... ...
@@ -191,6 +182,12 @@ type Store interface {
191 191
 	DriverName() string
192 192
 }
193 193
 
194
+// DescribableStore represents a layer store capable of storing
195
+// descriptors for layers.
196
+type DescribableStore interface {
197
+	RegisterWithDescriptor(io.Reader, ChainID, distribution.Descriptor) (Layer, error)
198
+}
199
+
194 200
 // MetadataTransaction represents functions for setting layer metadata
195 201
 // with a single transaction.
196 202
 type MetadataTransaction interface {
... ...
@@ -198,7 +195,7 @@ type MetadataTransaction interface {
198 198
 	SetParent(parent ChainID) error
199 199
 	SetDiffID(DiffID) error
200 200
 	SetCacheID(string) error
201
-	SetForeignSource(distribution.Descriptor) error
201
+	SetDescriptor(distribution.Descriptor) error
202 202
 	TarSplitWriter(compressInput bool) (io.WriteCloser, error)
203 203
 
204 204
 	Commit(ChainID) error
... ...
@@ -218,7 +215,7 @@ type MetadataStore interface {
218 218
 	GetParent(ChainID) (ChainID, error)
219 219
 	GetDiffID(ChainID) (DiffID, error)
220 220
 	GetCacheID(ChainID) (string, error)
221
-	GetForeignSource(ChainID) (distribution.Descriptor, error)
221
+	GetDescriptor(ChainID) (distribution.Descriptor, error)
222 222
 	TarSplitReader(ChainID) (io.ReadCloser, error)
223 223
 
224 224
 	SetMountID(string, string) error
... ...
@@ -129,6 +129,11 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
129 129
 		return nil, fmt.Errorf("failed to get parent for %s: %s", layer, err)
130 130
 	}
131 131
 
132
+	descriptor, err := ls.store.GetDescriptor(layer)
133
+	if err != nil {
134
+		return nil, fmt.Errorf("failed to get descriptor for %s: %s", layer, err)
135
+	}
136
+
132 137
 	cl = &roLayer{
133 138
 		chainID:    layer,
134 139
 		diffID:     diff,
... ...
@@ -136,13 +141,7 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
136 136
 		cacheID:    cacheID,
137 137
 		layerStore: ls,
138 138
 		references: map[Layer]struct{}{},
139
-	}
140
-
141
-	foreignSrc, err := ls.store.GetForeignSource(layer)
142
-	if err == nil {
143
-		cl.foreignSrc = &foreignSrc
144
-	} else if err != ErrNoForeignSource {
145
-		return nil, fmt.Errorf("failed to get foreign reference for %s: %s", layer, err)
139
+		descriptor: descriptor,
146 140
 	}
147 141
 
148 142
 	if parent != "" {
... ...
@@ -236,10 +235,10 @@ func (ls *layerStore) applyTar(tx MetadataTransaction, ts io.Reader, parent stri
236 236
 }
237 237
 
238 238
 func (ls *layerStore) Register(ts io.Reader, parent ChainID) (Layer, error) {
239
-	return ls.RegisterForeign(ts, parent, nil)
239
+	return ls.registerWithDescriptor(ts, parent, distribution.Descriptor{})
240 240
 }
241 241
 
242
-func (ls *layerStore) RegisterForeign(ts io.Reader, parent ChainID, foreignSrc *distribution.Descriptor) (Layer, error) {
242
+func (ls *layerStore) registerWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) {
243 243
 	// err is used to hold the error which will always trigger
244 244
 	// cleanup of creates sources but may not be an error returned
245 245
 	// to the caller (already exists).
... ...
@@ -270,10 +269,10 @@ func (ls *layerStore) RegisterForeign(ts io.Reader, parent ChainID, foreignSrc *
270 270
 	layer := &roLayer{
271 271
 		parent:         p,
272 272
 		cacheID:        stringid.GenerateRandomID(),
273
-		foreignSrc:     foreignSrc,
274 273
 		referenceCount: 1,
275 274
 		layerStore:     ls,
276 275
 		references:     map[Layer]struct{}{},
276
+		descriptor:     descriptor,
277 277
 	}
278 278
 
279 279
 	if err = ls.driver.Create(layer.cacheID, pid, "", nil); err != nil {
280 280
new file mode 100644
... ...
@@ -0,0 +1,11 @@
0
+package layer
1
+
2
+import (
3
+	"io"
4
+
5
+	"github.com/docker/distribution"
6
+)
7
+
8
+func (ls *layerStore) RegisterWithDescriptor(ts io.Reader, parent ChainID, descriptor distribution.Descriptor) (Layer, error) {
9
+	return ls.registerWithDescriptor(ts, parent, descriptor)
10
+}
... ...
@@ -7,9 +7,3 @@ import "github.com/docker/docker/pkg/stringid"
7 7
 func (ls *layerStore) mountID(name string) string {
8 8
 	return stringid.GenerateRandomID()
9 9
 }
10
-
11
-// ForeignSourceSupported returns whether layers downloaded from foreign sources are
12
-// supported in this daemon.
13
-func ForeignSourceSupported() bool {
14
-	return false
15
-}
... ...
@@ -96,9 +96,3 @@ func (ls *layerStore) mountID(name string) string {
96 96
 func (ls *layerStore) GraphDriver() graphdriver.Driver {
97 97
 	return ls.driver
98 98
 }
99
-
100
-// ForeignSourceSupported returns whether layers downloaded from foreign sources are
101
-// supported in this daemon.
102
-func ForeignSourceSupported() bool {
103
-	return true
104
-}
... ...
@@ -15,7 +15,7 @@ type roLayer struct {
15 15
 	cacheID    string
16 16
 	size       int64
17 17
 	layerStore *layerStore
18
-	foreignSrc *distribution.Descriptor
18
+	descriptor distribution.Descriptor
19 19
 
20 20
 	referenceCount int
21 21
 	references     map[Layer]struct{}
... ...
@@ -120,13 +120,14 @@ func storeLayer(tx MetadataTransaction, layer *roLayer) error {
120 120
 	if err := tx.SetCacheID(layer.cacheID); err != nil {
121 121
 		return err
122 122
 	}
123
-	if layer.parent != nil {
124
-		if err := tx.SetParent(layer.parent.chainID); err != nil {
123
+	// Do not store empty descriptors
124
+	if layer.descriptor.Digest != "" {
125
+		if err := tx.SetDescriptor(layer.descriptor); err != nil {
125 126
 			return err
126 127
 		}
127 128
 	}
128
-	if layer.foreignSrc != nil {
129
-		if err := tx.SetForeignSource(*layer.foreignSrc); err != nil {
129
+	if layer.parent != nil {
130
+		if err := tx.SetParent(layer.parent.chainID); err != nil {
130 131
 			return err
131 132
 		}
132 133
 	}
... ...
@@ -2,8 +2,8 @@ package layer
2 2
 
3 3
 import "github.com/docker/distribution"
4 4
 
5
-var _ ForeignSourcer = &roLayer{}
5
+var _ distribution.Describable = &roLayer{}
6 6
 
7
-func (rl *roLayer) ForeignSource() *distribution.Descriptor {
8
-	return rl.foreignSrc
7
+func (rl *roLayer) Descriptor() distribution.Descriptor {
8
+	return rl.descriptor
9 9
 }