Browse code

LCOW: Adds platform to the layer store

Signed-off-by: John Howard <jhoward@microsoft.com>

John Howard authored on 2017/04/26 01:37:29
Showing 10 changed files
... ...
@@ -26,6 +26,7 @@ type mockLayer struct {
26 26
 	diffID    layer.DiffID
27 27
 	chainID   layer.ChainID
28 28
 	parent    layer.Layer
29
+	platform  layer.Platform
29 30
 }
30 31
 
31 32
 func (ml *mockLayer) TarStream() (io.ReadCloser, error) {
... ...
@@ -56,6 +57,10 @@ func (ml *mockLayer) DiffSize() (size int64, err error) {
56 56
 	return 0, nil
57 57
 }
58 58
 
59
+func (ml *mockLayer) Platform() layer.Platform {
60
+	return ml.platform
61
+}
62
+
59 63
 func (ml *mockLayer) Metadata() (map[string]string, error) {
60 64
 	return make(map[string]string), nil
61 65
 }
... ...
@@ -55,6 +55,10 @@ func (el *emptyLayer) Metadata() (map[string]string, error) {
55 55
 	return make(map[string]string), nil
56 56
 }
57 57
 
58
+func (el *emptyLayer) Platform() Platform {
59
+	return ""
60
+}
61
+
58 62
 // IsEmpty returns true if the layer is an EmptyLayer
59 63
 func IsEmpty(diffID DiffID) bool {
60 64
 	return diffID == DigestSHA256EmptyTar
61 65
new file mode 100644
... ...
@@ -0,0 +1,13 @@
0
+// +build !windows
1
+
2
+package layer
3
+
4
+// SetPlatform writes the "platform" file to the layer filestore
5
+func (fm *fileMetadataTransaction) SetPlatform(platform Platform) error {
6
+	return nil
7
+}
8
+
9
+// GetPlatform reads the "platform" file from the layer filestore
10
+func (fms *fileMetadataStore) GetPlatform(layer ChainID) (Platform, error) {
11
+	return "", nil
12
+}
0 13
new file mode 100644
... ...
@@ -0,0 +1,35 @@
0
+package layer
1
+
2
+import (
3
+	"fmt"
4
+	"io/ioutil"
5
+	"os"
6
+	"strings"
7
+)
8
+
9
+// SetPlatform writes the "platform" file to the layer filestore
10
+func (fm *fileMetadataTransaction) SetPlatform(platform Platform) error {
11
+	if platform == "" {
12
+		return nil
13
+	}
14
+	return fm.ws.WriteFile("platform", []byte(platform), 0644)
15
+}
16
+
17
+// GetPlatform reads the "platform" file from the layer filestore
18
+func (fms *fileMetadataStore) GetPlatform(layer ChainID) (Platform, error) {
19
+	contentBytes, err := ioutil.ReadFile(fms.getLayerFilename(layer, "platform"))
20
+	if err != nil {
21
+		// For backwards compatibility, the platform file may not exist. Default to "windows" if missing.
22
+		if os.IsNotExist(err) {
23
+			return "windows", nil
24
+		}
25
+		return "", err
26
+	}
27
+	content := strings.TrimSpace(string(contentBytes))
28
+
29
+	if content != "windows" && content != "linux" {
30
+		return "", fmt.Errorf("invalid platform value: %s", content)
31
+	}
32
+
33
+	return Platform(content), nil
34
+}
... ...
@@ -64,6 +64,14 @@ func (id ChainID) String() string {
64 64
 	return string(id)
65 65
 }
66 66
 
67
+// Platform is the platform of a layer
68
+type Platform string
69
+
70
+// String returns a string rendition of layers target platform
71
+func (id Platform) String() string {
72
+	return string(id)
73
+}
74
+
67 75
 // DiffID is the hash of an individual layer tar.
68 76
 type DiffID digest.Digest
69 77
 
... ...
@@ -99,6 +107,9 @@ type Layer interface {
99 99
 	// Parent returns the next layer in the layer chain.
100 100
 	Parent() Layer
101 101
 
102
+	// Platform returns the platform of the layer
103
+	Platform() Platform
104
+
102 105
 	// Size returns the size of the entire layer chain. The size
103 106
 	// is calculated from the total size of all files in the layers.
104 107
 	Size() (int64, error)
... ...
@@ -208,6 +219,7 @@ type MetadataTransaction interface {
208 208
 	SetDiffID(DiffID) error
209 209
 	SetCacheID(string) error
210 210
 	SetDescriptor(distribution.Descriptor) error
211
+	SetPlatform(Platform) error
211 212
 	TarSplitWriter(compressInput bool) (io.WriteCloser, error)
212 213
 
213 214
 	Commit(ChainID) error
... ...
@@ -228,6 +240,7 @@ type MetadataStore interface {
228 228
 	GetDiffID(ChainID) (DiffID, error)
229 229
 	GetCacheID(ChainID) (string, error)
230 230
 	GetDescriptor(ChainID) (distribution.Descriptor, error)
231
+	GetPlatform(ChainID) (Platform, error)
231 232
 	TarSplitReader(ChainID) (io.ReadCloser, error)
232 233
 
233 234
 	SetMountID(string, string) error
... ...
@@ -144,6 +144,11 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
144 144
 		return nil, fmt.Errorf("failed to get descriptor for %s: %s", layer, err)
145 145
 	}
146 146
 
147
+	platform, err := ls.store.GetPlatform(layer)
148
+	if err != nil {
149
+		return nil, fmt.Errorf("failed to get platform for %s: %s", layer, err)
150
+	}
151
+
147 152
 	cl = &roLayer{
148 153
 		chainID:    layer,
149 154
 		diffID:     diff,
... ...
@@ -152,6 +157,7 @@ func (ls *layerStore) loadLayer(layer ChainID) (*roLayer, error) {
152 152
 		layerStore: ls,
153 153
 		references: map[Layer]struct{}{},
154 154
 		descriptor: descriptor,
155
+		platform:   platform,
155 156
 	}
156 157
 
157 158
 	if parent != "" {
... ...
@@ -16,6 +16,7 @@ type roLayer struct {
16 16
 	size       int64
17 17
 	layerStore *layerStore
18 18
 	descriptor distribution.Descriptor
19
+	platform   Platform
19 20
 
20 21
 	referenceCount int
21 22
 	references     map[Layer]struct{}
... ...
@@ -142,6 +143,9 @@ func storeLayer(tx MetadataTransaction, layer *roLayer) error {
142 142
 			return err
143 143
 		}
144 144
 	}
145
+	if err := tx.SetPlatform(layer.platform); err != nil {
146
+		return err
147
+	}
145 148
 
146 149
 	return nil
147 150
 }
148 151
new file mode 100644
... ...
@@ -0,0 +1,7 @@
0
+// +build !windows
1
+
2
+package layer
3
+
4
+func (rl *roLayer) Platform() Platform {
5
+	return ""
6
+}
... ...
@@ -7,3 +7,10 @@ var _ distribution.Describable = &roLayer{}
7 7
 func (rl *roLayer) Descriptor() distribution.Descriptor {
8 8
 	return rl.descriptor
9 9
 }
10
+
11
+func (rl *roLayer) Platform() Platform {
12
+	if rl.platform == "" {
13
+		return "windows"
14
+	}
15
+	return rl.platform
16
+}
... ...
@@ -433,6 +433,10 @@ func (l *mockLayer) DiffSize() (int64, error) {
433 433
 	return 0, nil
434 434
 }
435 435
 
436
+func (l *mockLayer) Platform() layer.Platform {
437
+	return ""
438
+}
439
+
436 440
 func (l *mockLayer) Metadata() (map[string]string, error) {
437 441
 	return nil, nil
438 442
 }