Skip to content

Commit 0140f7d

Browse files
author
zhouhao
committed
Increase platform option
Signed-off-by: zhouhao <[email protected]>
1 parent 592aab4 commit 0140f7d

File tree

7 files changed

+104
-71
lines changed

7 files changed

+104
-71
lines changed

cmd/oci-image-tool/create.go

Lines changed: 14 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -29,9 +29,10 @@ var bundleTypes = []string{
2929
}
3030

3131
type bundleCmd struct {
32-
typ string // the type to bundle, can be empty string
33-
ref string
34-
root string
32+
typ string // the type to bundle, can be empty string
33+
ref string
34+
root string
35+
platform []string
3536
}
3637

3738
func createHandle(context *cli.Context) error {
@@ -40,9 +41,10 @@ func createHandle(context *cli.Context) error {
4041
}
4142

4243
v := bundleCmd{
43-
typ: context.String("type"),
44-
ref: context.String("ref"),
45-
root: context.String("rootfs"),
44+
typ: context.String("type"),
45+
ref: context.String("ref"),
46+
root: context.String("rootfs"),
47+
platform: context.StringSlice("platform"),
4648
}
4749

4850
if v.typ == "" {
@@ -56,10 +58,10 @@ func createHandle(context *cli.Context) error {
5658
var err error
5759
switch v.typ {
5860
case image.TypeImageLayout:
59-
err = image.CreateRuntimeBundleLayout(context.Args()[0], context.Args()[1], v.ref, v.root)
61+
err = image.CreateRuntimeBundleLayout(context.Args()[0], context.Args()[1], v.ref, v.root, v.platform)
6062

6163
case image.TypeImage:
62-
err = image.CreateRuntimeBundleFile(context.Args()[0], context.Args()[1], v.ref, v.root)
64+
err = image.CreateRuntimeBundleFile(context.Args()[0], context.Args()[1], v.ref, v.root, v.platform)
6365

6466
default:
6567
err = fmt.Errorf("cannot create %q", v.typ)
@@ -95,5 +97,9 @@ var createCommand = cli.Command{
9597
Value: "rootfs",
9698
Usage: "A directory representing the root filesystem of the container in the OCI runtime bundle. It is strongly recommended to keep the default value.",
9799
},
100+
cli.StringSliceFlag{
101+
Name: "platform",
102+
Usage: "The platform contains os and arch. Filter manifests according to the conditions provided. Only applicable if reftype is index.",
103+
},
98104
},
99105
}

cmd/oci-image-tool/unpack.go

Lines changed: 12 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -29,8 +29,9 @@ var unpackTypes = []string{
2929
}
3030

3131
type unpackCmd struct {
32-
typ string // the type to unpack, can be empty string
33-
ref string
32+
typ string // the type to unpack, can be empty string
33+
ref string
34+
platform []string
3435
}
3536

3637
func unpackHandle(context *cli.Context) error {
@@ -39,8 +40,9 @@ func unpackHandle(context *cli.Context) error {
3940
}
4041

4142
v := unpackCmd{
42-
typ: context.String("type"),
43-
ref: context.String("ref"),
43+
typ: context.String("type"),
44+
ref: context.String("ref"),
45+
platform: context.StringSlice("platform"),
4446
}
4547

4648
if v.typ == "" {
@@ -54,10 +56,10 @@ func unpackHandle(context *cli.Context) error {
5456
var err error
5557
switch v.typ {
5658
case image.TypeImageLayout:
57-
err = image.UnpackLayout(context.Args()[0], context.Args()[1], v.ref)
59+
err = image.UnpackLayout(context.Args()[0], context.Args()[1], v.ref, v.platform)
5860

5961
case image.TypeImage:
60-
err = image.UnpackFile(context.Args()[0], context.Args()[1], v.ref)
62+
err = image.UnpackFile(context.Args()[0], context.Args()[1], v.ref, v.platform)
6163

6264
default:
6365
err = fmt.Errorf("cannot unpack %q", v.typ)
@@ -86,5 +88,9 @@ var unpackCommand = cli.Command{
8688
Value: "v1.0",
8789
Usage: "The ref pointing to the manifest of the OCI image. This must be present in the 'refs' subdirectory of the image.",
8890
},
91+
cli.StringSliceFlag{
92+
Name: "platform",
93+
Usage: "The platform contains os and arch conditions. Filter manifests according to the conditions provided. Only applicable if reftype is index.",
94+
},
8995
},
9096
}

completions/bash/oci-image-tool

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -150,7 +150,7 @@ _oci-image-tool_create() {
150150

151151
case "$cur" in
152152
-*)
153-
COMPREPLY=( $( compgen -W "--type --ref --rootfs --help -h" -- "$cur" ) )
153+
COMPREPLY=( $( compgen -W "--type --ref --rootfs --platform --help -h" -- "$cur" ) )
154154
;;
155155
esac
156156

@@ -166,7 +166,7 @@ _oci-image-tool_unpack() {
166166

167167
case "$cur" in
168168
-*)
169-
COMPREPLY=( $( compgen -W "--type --ref --help -h" -- "$cur" ) )
169+
COMPREPLY=( $( compgen -W "--type --ref --platform --help -h" -- "$cur" ) )
170170
;;
171171
esac
172172

image/image.go

Lines changed: 63 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -115,7 +115,7 @@ func validate(w walker, refs []string, out *log.Logger) error {
115115
}
116116

117117
for _, manifest := range index.Manifests {
118-
m, err := findManifest(w, &(manifest.Descriptor))
118+
m, err := findManifest(w, &manifest)
119119
if err != nil {
120120
return err
121121
}
@@ -136,30 +136,30 @@ func validate(w walker, refs []string, out *log.Logger) error {
136136
// UnpackLayout walks through the file tree given by src and, using the layers
137137
// specified in the manifest pointed to by the given ref, unpacks all layers in
138138
// the given destination directory or returns an error if the unpacking failed.
139-
func UnpackLayout(src, dest, ref string) error {
140-
return unpack(newPathWalker(src), dest, ref)
139+
func UnpackLayout(src, dest, ref string, platform []string) error {
140+
return unpack(newPathWalker(src), dest, ref, platform)
141141
}
142142

143143
// UnpackFile opens the file pointed by tarFileName and calls Unpack on it.
144-
func UnpackFile(tarFileName, dest, ref string) error {
144+
func UnpackFile(tarFileName, dest, ref string, platform []string) error {
145145
f, err := os.Open(tarFileName)
146146
if err != nil {
147147
return errors.Wrap(err, "unable to open file")
148148
}
149149
defer f.Close()
150150

151-
return Unpack(f, dest, ref)
151+
return Unpack(f, dest, ref, platform)
152152
}
153153

154154
// Unpack walks through the tar stream and, using the layers specified in
155155
// the manifest pointed to by the given ref, unpacks all layers in the given
156156
// destination directory or returns an error if the unpacking failed.
157157
// The destination will be created if it does not exist.
158-
func Unpack(r io.ReadSeeker, dest, refName string) error {
159-
return unpack(newTarWalker(r), dest, refName)
158+
func Unpack(r io.ReadSeeker, dest, refName string, platform []string) error {
159+
return unpack(newTarWalker(r), dest, refName, platform)
160160
}
161161

162-
func unpack(w walker, dest, refName string) error {
162+
func unpack(w walker, dest, refName string, platform []string) error {
163163
ref, err := findDescriptor(w, refName)
164164
if err != nil {
165165
return err
@@ -188,28 +188,17 @@ func unpack(w walker, dest, refName string) error {
188188
return err
189189
}
190190

191-
if err := validateIndex(index, w); err != nil {
191+
if err = validateIndex(index, w); err != nil {
192192
return err
193193
}
194194

195-
if len(index.Manifests) == 0 {
196-
fmt.Println("warning: no manifests found")
197-
return nil
195+
manifests, err := filterManifest(w, index.Manifests, platform)
196+
if err != nil {
197+
return err
198198
}
199199

200-
for _, manifest := range index.Manifests {
201-
m, err := findManifest(w, &(manifest.Descriptor))
202-
if err != nil {
203-
return err
204-
}
205-
206-
if err := m.validate(w); err != nil {
207-
return err
208-
}
209-
210-
if err := m.unpack(w, dest); err != nil {
211-
return err
212-
}
200+
for _, m := range manifests {
201+
return m.unpack(w, dest)
213202
}
214203
}
215204

@@ -219,30 +208,30 @@ func unpack(w walker, dest, refName string) error {
219208
// CreateRuntimeBundleLayout walks through the file tree given by src and
220209
// creates an OCI runtime bundle in the given destination dest
221210
// or returns an error if the unpacking failed.
222-
func CreateRuntimeBundleLayout(src, dest, ref, root string) error {
223-
return createRuntimeBundle(newPathWalker(src), dest, ref, root)
211+
func CreateRuntimeBundleLayout(src, dest, ref, root string, platform []string) error {
212+
return createRuntimeBundle(newPathWalker(src), dest, ref, root, platform)
224213
}
225214

226215
// CreateRuntimeBundleFile opens the file pointed by tarFile and calls
227216
// CreateRuntimeBundle.
228-
func CreateRuntimeBundleFile(tarFile, dest, ref, root string) error {
217+
func CreateRuntimeBundleFile(tarFile, dest, ref, root string, platform []string) error {
229218
f, err := os.Open(tarFile)
230219
if err != nil {
231220
return errors.Wrap(err, "unable to open file")
232221
}
233222
defer f.Close()
234223

235-
return createRuntimeBundle(newTarWalker(f), dest, ref, root)
224+
return createRuntimeBundle(newTarWalker(f), dest, ref, root, platform)
236225
}
237226

238227
// CreateRuntimeBundle walks through the given tar stream and
239228
// creates an OCI runtime bundle in the given destination dest
240229
// or returns an error if the unpacking failed.
241-
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string) error {
242-
return createRuntimeBundle(newTarWalker(r), dest, ref, root)
230+
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string, platform []string) error {
231+
return createRuntimeBundle(newTarWalker(r), dest, ref, root, platform)
243232
}
244233

245-
func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
234+
func createRuntimeBundle(w walker, dest, refName, rootfs string, platform []string) error {
246235
ref, err := findDescriptor(w, refName)
247236
if err != nil {
248237
return err
@@ -262,7 +251,7 @@ func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
262251
return err
263252
}
264253

265-
return createRuntimebundle(w, m, dest, rootfs)
254+
return createBundle(w, m, dest, rootfs)
266255
}
267256

268257
if ref.MediaType == validRefMediaTypes[1] {
@@ -271,35 +260,24 @@ func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
271260
return err
272261
}
273262

274-
if err := validateIndex(index, w); err != nil {
263+
if err = validateIndex(index, w); err != nil {
275264
return err
276265
}
277266

278-
if len(index.Manifests) == 0 {
279-
fmt.Println("warning: no manifests found")
280-
return nil
267+
manifests, err := filterManifest(w, index.Manifests, platform)
268+
if err != nil {
269+
return err
281270
}
282271

283-
for _, manifest := range index.Manifests {
284-
m, err := findManifest(w, &(manifest.Descriptor))
285-
if err != nil {
286-
return err
287-
}
288-
289-
if err := m.validate(w); err != nil {
290-
return err
291-
}
292-
293-
if err := createRuntimebundle(w, m, dest, rootfs); err != nil {
294-
return err
295-
}
272+
for _, m := range manifests {
273+
return createBundle(w, m, dest, rootfs)
296274
}
297275
}
298276

299277
return nil
300278
}
301279

302-
func createRuntimebundle(w walker, m *manifest, dest, rootfs string) error {
280+
func createBundle(w walker, m *manifest, dest, rootfs string) error {
303281
c, err := findConfig(w, &m.Config)
304282
if err != nil {
305283
return err
@@ -332,3 +310,37 @@ func createRuntimebundle(w walker, m *manifest, dest, rootfs string) error {
332310

333311
return json.NewEncoder(f).Encode(spec)
334312
}
313+
314+
// filertManifest returns a filtered list of manifests
315+
func filterManifest(w walker, Manifests []v1.Descriptor, platform []string) ([]*manifest, error) {
316+
var manifests []*manifest
317+
318+
if len(Manifests) == 0 {
319+
fmt.Println("warning: no manifests found")
320+
return manifests, nil
321+
}
322+
323+
if len(platform) != 2 {
324+
return manifests, fmt.Errorf("platform must have os and arch")
325+
}
326+
327+
for _, manifest := range Manifests {
328+
m, err := findManifest(w, &manifest)
329+
if err != nil {
330+
return manifests, err
331+
}
332+
333+
if err := m.validate(w); err != nil {
334+
return manifests, err
335+
}
336+
if manifest.Platform.OS == platform[0] && manifest.Platform.Architecture == platform[1] {
337+
manifests = append(manifests, m)
338+
}
339+
}
340+
341+
if len(manifests) == 0 {
342+
return manifests, fmt.Errorf("There is no matching manifest")
343+
}
344+
345+
return manifests, nil
346+
}

image/index.go

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,8 @@ import (
2828
"github.com/pkg/errors"
2929
)
3030

31-
func findIndex(w walker, d *v1.Descriptor) (*v1.ImageIndex, error) {
32-
var index v1.ImageIndex
31+
func findIndex(w walker, d *v1.Descriptor) (*v1.Index, error) {
32+
var index v1.Index
3333

3434
switch err := w.walk(func(path string, info os.FileInfo, r io.Reader) error {
3535
if info.IsDir() || filepath.Clean(path) != indexPath {
@@ -60,9 +60,9 @@ func findIndex(w walker, d *v1.Descriptor) (*v1.ImageIndex, error) {
6060
}
6161
}
6262

63-
func validateIndex(index *v1.ImageIndex, w walker) error {
63+
func validateIndex(index *v1.Index, w walker) error {
6464
for _, manifest := range index.Manifests {
65-
if err := validateDescriptor(&manifest.Descriptor, w, []string{v1.MediaTypeImageManifest}); err != nil {
65+
if err := validateDescriptor(&manifest, w, []string{v1.MediaTypeImageManifest}); err != nil {
6666
return errors.Wrap(err, "manifest validation failed")
6767
}
6868
}

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

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,10 @@ runtime-spec-compatible `dest/config.json`.
2626
**--type**=""
2727
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"
2828

29+
**--platform**=""
30+
The platform contains os and arch. Filter manifests according to the conditions provided.
31+
Only applicable if reftype is index.
32+
2933
# EXAMPLES
3034
```
3135
$ skopeo copy docker://busybox oci:busybox-oci

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

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,11 @@ oci-image-tool unpack \- Unpack an image or image source layout
2020
**--type**=""
2121
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"
2222

23+
**--platform**=""
24+
The platform contains os and arch. Filter manifests according to the conditions provided.
25+
Only applicable if reftype is index.
26+
27+
2328
# EXAMPLES
2429
```
2530
$ skopeo copy docker://busybox oci:busybox-oci

0 commit comments

Comments
 (0)