Skip to content

Commit 4273961

Browse files
author
zhouhao
committed
add test to index
Signed-off-by: zhouhao <[email protected]>
1 parent 0dd2b19 commit 4273961

File tree

7 files changed

+120
-62
lines changed

7 files changed

+120
-62
lines changed

cmd/oci-image-tool/create.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@ type bundleCmd struct {
3232
typ string // the type to bundle, can be empty string
3333
ref string
3434
root string
35-
platform []string
35+
platform string
3636
}
3737

3838
func createHandle(context *cli.Context) error {
@@ -44,7 +44,7 @@ func createHandle(context *cli.Context) error {
4444
typ: context.String("type"),
4545
ref: context.String("ref"),
4646
root: context.String("rootfs"),
47-
platform: context.StringSlice("platform"),
47+
platform: context.String("platform"),
4848
}
4949

5050
if v.typ == "" {
@@ -97,9 +97,9 @@ var createCommand = cli.Command{
9797
Value: "rootfs",
9898
Usage: "A directory representing the root filesystem of the container in the OCI runtime bundle. It is strongly recommended to keep the default value.",
9999
},
100-
cli.StringSliceFlag{
100+
cli.StringFlag{
101101
Name: "platform",
102-
Usage: "The platform contains os and arch. Filter manifests according to the conditions provided. Only applicable if reftype is index.",
102+
Usage: "Specify the os and architecture of the manifest, format is OS:Architecture. Only applicable if reftype is index.",
103103
},
104104
},
105105
}

cmd/oci-image-tool/unpack.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@ var unpackTypes = []string{
3131
type unpackCmd struct {
3232
typ string // the type to unpack, can be empty string
3333
ref string
34-
platform []string
34+
platform string
3535
}
3636

3737
func unpackHandle(context *cli.Context) error {
@@ -42,7 +42,7 @@ func unpackHandle(context *cli.Context) error {
4242
v := unpackCmd{
4343
typ: context.String("type"),
4444
ref: context.String("ref"),
45-
platform: context.StringSlice("platform"),
45+
platform: context.String("platform"),
4646
}
4747

4848
if v.typ == "" {
@@ -88,9 +88,9 @@ var unpackCommand = cli.Command{
8888
Value: "v1.0",
8989
Usage: "The ref pointing to the manifest of the OCI image. This must be present in the 'refs' subdirectory of the image.",
9090
},
91-
cli.StringSliceFlag{
91+
cli.StringFlag{
9292
Name: "platform",
93-
Usage: "The platform contains os and arch conditions. Filter manifests according to the conditions provided. Only applicable if reftype is index.",
93+
Usage: "Specify the os and architecture of the manifest, format is OS:Architecture. Only applicable if reftype is index.",
9494
},
9595
},
9696
}

image/image.go

Lines changed: 16 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ import (
2121
"log"
2222
"os"
2323
"path/filepath"
24+
"strings"
2425

2526
"github.com/opencontainers/image-spec/specs-go/v1"
2627
"github.com/pkg/errors"
@@ -136,12 +137,12 @@ func validate(w walker, refs []string, out *log.Logger) error {
136137
// UnpackLayout walks through the file tree given by src and, using the layers
137138
// specified in the manifest pointed to by the given ref, unpacks all layers in
138139
// the given destination directory or returns an error if the unpacking failed.
139-
func UnpackLayout(src, dest, ref string, platform []string) error {
140+
func UnpackLayout(src, dest, ref string, platform string) error {
140141
return unpack(newPathWalker(src), dest, ref, platform)
141142
}
142143

143144
// UnpackFile opens the file pointed by tarFileName and calls Unpack on it.
144-
func UnpackFile(tarFileName, dest, ref string, platform []string) error {
145+
func UnpackFile(tarFileName, dest, ref string, platform string) error {
145146
f, err := os.Open(tarFileName)
146147
if err != nil {
147148
return errors.Wrap(err, "unable to open file")
@@ -155,11 +156,11 @@ func UnpackFile(tarFileName, dest, ref string, platform []string) error {
155156
// the manifest pointed to by the given ref, unpacks all layers in the given
156157
// destination directory or returns an error if the unpacking failed.
157158
// The destination will be created if it does not exist.
158-
func Unpack(r io.ReadSeeker, dest, refName string, platform []string) error {
159+
func Unpack(r io.ReadSeeker, dest, refName string, platform string) error {
159160
return unpack(newTarWalker(r), dest, refName, platform)
160161
}
161162

162-
func unpack(w walker, dest, refName string, platform []string) error {
163+
func unpack(w walker, dest, refName string, platform string) error {
163164
ref, err := findDescriptor(w, refName)
164165
if err != nil {
165166
return err
@@ -208,13 +209,13 @@ func unpack(w walker, dest, refName string, platform []string) error {
208209
// CreateRuntimeBundleLayout walks through the file tree given by src and
209210
// creates an OCI runtime bundle in the given destination dest
210211
// or returns an error if the unpacking failed.
211-
func CreateRuntimeBundleLayout(src, dest, ref, root string, platform []string) error {
212+
func CreateRuntimeBundleLayout(src, dest, ref, root string, platform string) error {
212213
return createRuntimeBundle(newPathWalker(src), dest, ref, root, platform)
213214
}
214215

215216
// CreateRuntimeBundleFile opens the file pointed by tarFile and calls
216217
// CreateRuntimeBundle.
217-
func CreateRuntimeBundleFile(tarFile, dest, ref, root string, platform []string) error {
218+
func CreateRuntimeBundleFile(tarFile, dest, ref, root string, platform string) error {
218219
f, err := os.Open(tarFile)
219220
if err != nil {
220221
return errors.Wrap(err, "unable to open file")
@@ -227,11 +228,11 @@ func CreateRuntimeBundleFile(tarFile, dest, ref, root string, platform []string)
227228
// CreateRuntimeBundle walks through the given tar stream and
228229
// creates an OCI runtime bundle in the given destination dest
229230
// or returns an error if the unpacking failed.
230-
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string, platform []string) error {
231+
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string, platform string) error {
231232
return createRuntimeBundle(newTarWalker(r), dest, ref, root, platform)
232233
}
233234

234-
func createRuntimeBundle(w walker, dest, refName, rootfs string, platform []string) error {
235+
func createRuntimeBundle(w walker, dest, refName, rootfs string, platform string) error {
235236
ref, err := findDescriptor(w, refName)
236237
if err != nil {
237238
return err
@@ -312,18 +313,19 @@ func createBundle(w walker, m *manifest, dest, rootfs string) error {
312313
}
313314

314315
// filertManifest returns a filtered list of manifests
315-
func filterManifest(w walker, Manifests []v1.Descriptor, platform []string) ([]*manifest, error) {
316+
func filterManifest(w walker, Manifests []v1.Descriptor, platform string) ([]*manifest, error) {
316317
var manifests []*manifest
317318

319+
argsParts := strings.Split(platform, ":")
320+
if len(argsParts) != 2 {
321+
return manifests, fmt.Errorf("platform must have os and arch when reftype is index")
322+
}
323+
318324
if len(Manifests) == 0 {
319325
fmt.Println("warning: no manifests found")
320326
return manifests, nil
321327
}
322328

323-
if len(platform) != 2 {
324-
return manifests, fmt.Errorf("platform must have os and arch")
325-
}
326-
327329
for _, manifest := range Manifests {
328330
m, err := findManifest(w, &manifest)
329331
if err != nil {
@@ -333,7 +335,7 @@ func filterManifest(w walker, Manifests []v1.Descriptor, platform []string) ([]*
333335
if err := m.validate(w); err != nil {
334336
return manifests, err
335337
}
336-
if manifest.Platform.OS == platform[0] && manifest.Platform.Architecture == platform[1] {
338+
if strings.EqualFold(manifest.Platform.OS, argsParts[0]) && strings.EqualFold(manifest.Platform.Architecture, argsParts[1]) {
337339
manifests = append(manifests, m)
338340
}
339341
}

image/image_test.go

Lines changed: 90 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,6 @@ import (
3131
)
3232

3333
const (
34-
refTag = "latest"
3534
layoutStr = `{"imageLayoutVersion": "1.0.0"}`
3635

3736
configStr = `{
@@ -40,7 +39,6 @@ const (
4039
"architecture": "amd64",
4140
"os": "linux",
4241
"config": {
43-
"User": "alice",
4442
"ExposedPorts": {
4543
"8080/tcp": {}
4644
},
@@ -90,36 +88,59 @@ const (
9088
)
9189

9290
var (
91+
refTag = []string{
92+
"latest",
93+
"v1.0",
94+
}
95+
96+
indexJSON = `{
97+
"schemaVersion": 2,
98+
"manifests": [
99+
{
100+
"mediaType": "application/vnd.oci.image.index.v1+json",
101+
"size": <index_size>,
102+
"digest": "<index_digest>",
103+
"annotations": {
104+
"org.opencontainers.ref.name": "v1.0"
105+
}
106+
},
107+
{
108+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
109+
"size": <manifest_size>,
110+
"digest": "<manifest_digest>",
111+
"platform": {
112+
"architecture": "ppc64le",
113+
"os": "linux"
114+
},
115+
"annotations": {
116+
"org.opencontainers.ref.name": "latest"
117+
}
118+
}
119+
],
120+
"annotations": {
121+
"com.example.index.revision": "r124356"
122+
}
123+
}
124+
`
93125
indexStr = `{
94126
"schemaVersion": 2,
95127
"manifests": [
96-
{
97-
"mediaType": "application/vnd.oci.image.index.v1+json",
98-
"size": <manifest_size>,
99-
"digest": "<manifest_digest>",
100-
"annotations": {
101-
"org.opencontainers.ref.name": "v1.0"
102-
}
103-
},
104128
{
105129
"mediaType": "application/vnd.oci.image.manifest.v1+json",
106130
"size": <manifest_size>,
107131
"digest": "<manifest_digest>",
108132
"platform": {
109133
"architecture": "ppc64le",
110134
"os": "linux"
111-
},
112-
"annotations": {
113-
"org.opencontainers.ref.name": "latest"
114135
}
115136
},
116137
{
117-
"mediaType": "application/xml",
138+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
118139
"size": <manifest_size>,
119140
"digest": "<manifest_digest>",
120-
"annotations": {
121-
"org.freedesktop.specifications.metainfo.version": "1.0",
122-
"org.freedesktop.specifications.metainfo.type": "AppStream"
141+
"platform": {
142+
"architecture": "amd64",
143+
"os": "linux"
123144
}
124145
}
125146
],
@@ -129,10 +150,10 @@ var (
129150
}
130151
`
131152
manifestStr = `{
132-
"annotations": {
153+
"annotations": {
133154
"org.freedesktop.specifications.metainfo.version": "1.0",
134155
"org.freedesktop.specifications.metainfo.type": "AppStream"
135-
},
156+
},
136157
"config": {
137158
"digest": "<config_digest>",
138159
"mediaType": "application/vnd.oci.image.config.v1+json",
@@ -156,12 +177,14 @@ type tarContent struct {
156177
}
157178

158179
type imageLayout struct {
159-
rootDir string
160-
layout string
161-
ref string
162-
manifest string
163-
config string
164-
tarList []tarContent
180+
rootDir string
181+
layout string
182+
ref []string
183+
manifest string
184+
index string
185+
config string
186+
indexjson string
187+
tarList []tarContent
165188
}
166189

167190
func TestValidateLayout(t *testing.T) {
@@ -172,11 +195,13 @@ func TestValidateLayout(t *testing.T) {
172195
defer os.RemoveAll(root)
173196

174197
il := imageLayout{
175-
rootDir: root,
176-
layout: layoutStr,
177-
ref: refTag,
178-
manifest: manifestStr,
179-
config: configStr,
198+
rootDir: root,
199+
layout: layoutStr,
200+
ref: refTag,
201+
manifest: manifestStr,
202+
index: indexStr,
203+
indexjson: indexJSON,
204+
config: configStr,
180205
tarList: []tarContent{
181206
{&tar.Header{Name: "test", Size: 4, Mode: 0600}, []byte("test")},
182207
},
@@ -188,7 +213,7 @@ func TestValidateLayout(t *testing.T) {
188213
t.Fatal(err)
189214
}
190215

191-
err = ValidateLayout(root, []string{refTag}, nil)
216+
err = ValidateLayout(root, refTag, nil)
192217
if err != nil {
193218
t.Fatal(err)
194219
}
@@ -226,8 +251,22 @@ func createImageLayoutBundle(il imageLayout) error {
226251
if err != nil {
227252
return err
228253
}
254+
il.index = strings.Replace(il.index, "<manifest_digest>", string(desc.Digest), -1)
255+
il.index = strings.Replace(il.index, "<manifest_size>", strconv.FormatInt(desc.Size, 10), -1)
256+
257+
il.indexjson = strings.Replace(il.indexjson, "<manifest_digest>", string(desc.Digest), -1)
258+
il.indexjson = strings.Replace(il.indexjson, "<manifest_size>", strconv.FormatInt(desc.Size, 10), -1)
259+
260+
// create index blob file
261+
desc, err = createIndexFile(il.rootDir, il.index)
262+
if err != nil {
263+
return err
264+
}
265+
il.indexjson = strings.Replace(il.indexjson, "<index_digest>", string(desc.Digest), -1)
266+
il.indexjson = strings.Replace(il.indexjson, "<index_size>", strconv.FormatInt(desc.Size, 10), -1)
229267

230-
return createIndexFile(il.rootDir, desc)
268+
// create index.json file
269+
return createIndexJSON(il.rootDir, il.indexjson)
231270
}
232271

233272
func createLayoutFile(root string) error {
@@ -241,19 +280,34 @@ func createLayoutFile(root string) error {
241280
return err
242281
}
243282

244-
func createIndexFile(root string, mft v1.Descriptor) error {
283+
func createIndexJSON(root string, str string) error {
245284
indexpath := filepath.Join(root, "index.json")
246285
f, err := os.Create(indexpath)
247286
if err != nil {
248287
return err
249288
}
250289
defer f.Close()
251-
indexStr = strings.Replace(indexStr, "<manifest_digest>", string(mft.Digest), -1)
252-
indexStr = strings.Replace(indexStr, "<manifest_size>", strconv.FormatInt(mft.Size, 10), -1)
253-
_, err = io.Copy(f, bytes.NewBuffer([]byte(indexStr)))
290+
_, err = io.Copy(f, bytes.NewBuffer([]byte(str)))
291+
254292
return err
255293
}
256294

295+
func createIndexFile(root, str string) (v1.Descriptor, error) {
296+
name := filepath.Join(root, "blobs", "sha256", "test-index")
297+
f, err := os.Create(name)
298+
if err != nil {
299+
return v1.Descriptor{}, err
300+
}
301+
defer f.Close()
302+
303+
_, err = io.Copy(f, bytes.NewBuffer([]byte(str)))
304+
if err != nil {
305+
return v1.Descriptor{}, err
306+
}
307+
308+
return createHashedBlob(name)
309+
}
310+
257311
func createManifestFile(root, str string) (v1.Descriptor, error) {
258312
name := filepath.Join(root, "blobs", "sha256", "test-manifest")
259313
f, err := os.Create(name)

image/index.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -30,9 +30,10 @@ import (
3030

3131
func findIndex(w walker, d *v1.Descriptor) (*v1.Index, error) {
3232
var index v1.Index
33+
ipath := filepath.Join("blobs", string(d.Digest.Algorithm()), d.Digest.Hex())
3334

3435
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
35-
if info.IsDir() || filepath.Clean(path) != indexPath {
36+
if info.IsDir() || filepath.Clean(path) != ipath {
3637
return nil
3738
}
3839

man/oci-image-tool-create.1.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,8 @@ runtime-spec-compatible `dest/config.json`.
2727
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"
2828

2929
**--platform**=""
30-
The platform contains os and arch. Filter manifests according to the conditions provided.
30+
Specify the os and architecture of the manifest, format is OS:Architecture.
31+
e.g. --platform linux:amd64
3132
Only applicable if reftype is index.
3233

3334
# EXAMPLES

0 commit comments

Comments
 (0)