Skip to content

Commit 10e8442

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

File tree

7 files changed

+119
-60
lines changed

7 files changed

+119
-60
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: 89 additions & 34 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,7 @@ const (
4039
"architecture": "amd64",
4140
"os": "linux",
4241
"config": {
43-
"User": "alice",
42+
"User": "",
4443
"ExposedPorts": {
4544
"8080/tcp": {}
4645
},
@@ -90,36 +89,59 @@ const (
9089
)
9190

9291
var (
92+
refTag = []string{
93+
"latest",
94+
"v1.0",
95+
}
96+
97+
indexJSON = `{
98+
"schemaVersion": 2,
99+
"manifests": [
100+
{
101+
"mediaType": "application/vnd.oci.image.index.v1+json",
102+
"size": <index_size>,
103+
"digest": "<index_digest>",
104+
"annotations": {
105+
"org.opencontainers.ref.name": "v1.0"
106+
}
107+
},
108+
{
109+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
110+
"size": <manifest_size>,
111+
"digest": "<manifest_digest>",
112+
"platform": {
113+
"architecture": "ppc64le",
114+
"os": "linux"
115+
},
116+
"annotations": {
117+
"org.opencontainers.ref.name": "latest"
118+
}
119+
}
120+
],
121+
"annotations": {
122+
"com.example.index.revision": "r124356"
123+
}
124+
}
125+
`
93126
indexStr = `{
94127
"schemaVersion": 2,
95128
"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-
},
104129
{
105130
"mediaType": "application/vnd.oci.image.manifest.v1+json",
106131
"size": <manifest_size>,
107132
"digest": "<manifest_digest>",
108133
"platform": {
109134
"architecture": "ppc64le",
110135
"os": "linux"
111-
},
112-
"annotations": {
113-
"org.opencontainers.ref.name": "latest"
114136
}
115137
},
116138
{
117-
"mediaType": "application/xml",
139+
"mediaType": "application/vnd.oci.image.manifest.v1+json",
118140
"size": <manifest_size>,
119141
"digest": "<manifest_digest>",
120-
"annotations": {
121-
"org.freedesktop.specifications.metainfo.version": "1.0",
122-
"org.freedesktop.specifications.metainfo.type": "AppStream"
142+
"platform": {
143+
"architecture": "amd64",
144+
"os": "linux"
123145
}
124146
}
125147
],
@@ -156,12 +178,14 @@ type tarContent struct {
156178
}
157179

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

167191
func TestValidateLayout(t *testing.T) {
@@ -172,11 +196,13 @@ func TestValidateLayout(t *testing.T) {
172196
defer os.RemoveAll(root)
173197

174198
il := imageLayout{
175-
rootDir: root,
176-
layout: layoutStr,
177-
ref: refTag,
178-
manifest: manifestStr,
179-
config: configStr,
199+
rootDir: root,
200+
layout: layoutStr,
201+
ref: refTag,
202+
manifest: manifestStr,
203+
index: indexStr,
204+
indexjson: indexJSON,
205+
config: configStr,
180206
tarList: []tarContent{
181207
{&tar.Header{Name: "test", Size: 4, Mode: 0600}, []byte("test")},
182208
},
@@ -188,7 +214,7 @@ func TestValidateLayout(t *testing.T) {
188214
t.Fatal(err)
189215
}
190216

191-
err = ValidateLayout(root, []string{refTag}, nil)
217+
err = ValidateLayout(root, refTag, nil)
192218
if err != nil {
193219
t.Fatal(err)
194220
}
@@ -226,8 +252,22 @@ func createImageLayoutBundle(il imageLayout) error {
226252
if err != nil {
227253
return err
228254
}
255+
il.index = strings.Replace(il.index, "<manifest_digest>", string(desc.Digest), -1)
256+
il.index = strings.Replace(il.index, "<manifest_size>", strconv.FormatInt(desc.Size, 10), -1)
257+
258+
il.indexjson = strings.Replace(il.indexjson, "<manifest_digest>", string(desc.Digest), -1)
259+
il.indexjson = strings.Replace(il.indexjson, "<manifest_size>", strconv.FormatInt(desc.Size, 10), -1)
260+
261+
// create index blob file
262+
desc, err = createIndexFile(il.rootDir, il.index)
263+
if err != nil {
264+
return err
265+
}
266+
il.indexjson = strings.Replace(il.indexjson, "<index_digest>", string(desc.Digest), -1)
267+
il.indexjson = strings.Replace(il.indexjson, "<index_size>", strconv.FormatInt(desc.Size, 10), -1)
229268

230-
return createIndexFile(il.rootDir, desc)
269+
// create index.json file
270+
return createIndexJSON(il.rootDir, il.indexjson)
231271
}
232272

233273
func createLayoutFile(root string) error {
@@ -241,19 +281,34 @@ func createLayoutFile(root string) error {
241281
return err
242282
}
243283

244-
func createIndexFile(root string, mft v1.Descriptor) error {
284+
func createIndexJSON(root string, str string) error {
245285
indexpath := filepath.Join(root, "index.json")
246286
f, err := os.Create(indexpath)
247287
if err != nil {
248288
return err
249289
}
250290
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)))
291+
_, err = io.Copy(f, bytes.NewBuffer([]byte(str)))
292+
254293
return err
255294
}
256295

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

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

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -21,10 +21,10 @@ oci-image-tool unpack \- Unpack an image or image source layout
2121
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"
2222

2323
**--platform**=""
24-
The platform contains os and arch. Filter manifests according to the conditions provided.
24+
Specify the os and architecture of the manifest, format is OS:Architecture.
25+
e.g. --platform linux:amd64
2526
Only applicable if reftype is index.
2627

27-
2828
# EXAMPLES
2929
```
3030
$ skopeo copy docker://busybox oci:busybox-oci

0 commit comments

Comments
 (0)