/
twoplatform.go
117 lines (100 loc) · 3.05 KB
/
twoplatform.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
package specialimage
import (
"os"
"path/filepath"
"github.com/containerd/containerd/platforms"
"github.com/distribution/reference"
"github.com/opencontainers/go-digest"
"github.com/opencontainers/image-spec/specs-go"
ocispec "github.com/opencontainers/image-spec/specs-go/v1"
)
func TwoPlatform(dir string) (*ocispec.Index, error) {
const imageRef = "twoplatform:latest"
layer1Desc, err := writeLayerWithOneFile(dir, "bash", []byte("layer1"))
if err != nil {
return nil, err
}
layer2Desc, err := writeLayerWithOneFile(dir, "bash", []byte("layer2"))
if err != nil {
return nil, err
}
config1Desc, err := writeJsonBlob(dir, ocispec.MediaTypeImageConfig, ocispec.Image{
Platform: platforms.MustParse("linux/amd64"),
Config: ocispec.ImageConfig{
Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
},
RootFS: ocispec.RootFS{
Type: "layers",
DiffIDs: []digest.Digest{layer1Desc.Digest},
},
})
if err != nil {
return nil, err
}
manifest1Desc, err := writeJsonBlob(dir, ocispec.MediaTypeImageManifest, ocispec.Manifest{
MediaType: ocispec.MediaTypeImageManifest,
Config: config1Desc,
Layers: []ocispec.Descriptor{layer1Desc},
})
if err != nil {
return nil, err
}
config2Desc, err := writeJsonBlob(dir, ocispec.MediaTypeImageConfig, ocispec.Image{
Platform: platforms.MustParse("linux/arm64"),
Config: ocispec.ImageConfig{
Env: []string{"PATH=/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin"},
},
RootFS: ocispec.RootFS{
Type: "layers",
DiffIDs: []digest.Digest{layer1Desc.Digest},
},
})
if err != nil {
return nil, err
}
manifest2Desc, err := writeJsonBlob(dir, ocispec.MediaTypeImageManifest, ocispec.Manifest{
MediaType: ocispec.MediaTypeImageManifest,
Config: config2Desc,
Layers: []ocispec.Descriptor{layer2Desc},
})
if err != nil {
return nil, err
}
index := ocispec.Index{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: ocispec.MediaTypeImageIndex,
Manifests: []ocispec.Descriptor{manifest1Desc, manifest2Desc},
}
ref, err := reference.ParseNormalizedNamed(imageRef)
if err != nil {
return nil, err
}
return multiPlatformImage(dir, ref, index)
}
func multiPlatformImage(dir string, ref reference.Named, target ocispec.Index) (*ocispec.Index, error) {
targetDesc, err := writeJsonBlob(dir, ocispec.MediaTypeImageIndex, target)
if err != nil {
return nil, err
}
if ref != nil {
targetDesc.Annotations = map[string]string{
"io.containerd.image.name": ref.String(),
}
if tagged, ok := ref.(reference.Tagged); ok {
targetDesc.Annotations[ocispec.AnnotationRefName] = tagged.Tag()
}
}
index := ocispec.Index{
Versioned: specs.Versioned{SchemaVersion: 2},
MediaType: ocispec.MediaTypeImageIndex,
Manifests: []ocispec.Descriptor{targetDesc},
}
if err := writeJson(index, filepath.Join(dir, "index.json")); err != nil {
return nil, err
}
err = os.WriteFile(filepath.Join(dir, "oci-layout"), []byte(`{"imageLayoutVersion": "1.0.0"}`), 0o644)
if err != nil {
return nil, err
}
return &index, nil
}