Skip to content

Commit

Permalink
Increase platform option
Browse files Browse the repository at this point in the history
Signed-off-by: zhouhao <zhouhao@cn.fujitsu.com>
  • Loading branch information
zhouhao committed Jul 14, 2017
1 parent 592aab4 commit 0140f7d
Show file tree
Hide file tree
Showing 7 changed files with 104 additions and 71 deletions.
22 changes: 14 additions & 8 deletions cmd/oci-image-tool/create.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,9 +29,10 @@ var bundleTypes = []string{
}

type bundleCmd struct {
typ string // the type to bundle, can be empty string
ref string
root string
typ string // the type to bundle, can be empty string
ref string
root string
platform []string
}

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

v := bundleCmd{
typ: context.String("type"),
ref: context.String("ref"),
root: context.String("rootfs"),
typ: context.String("type"),
ref: context.String("ref"),
root: context.String("rootfs"),
platform: context.StringSlice("platform"),
}

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

case image.TypeImage:
err = image.CreateRuntimeBundleFile(context.Args()[0], context.Args()[1], v.ref, v.root)
err = image.CreateRuntimeBundleFile(context.Args()[0], context.Args()[1], v.ref, v.root, v.platform)

default:
err = fmt.Errorf("cannot create %q", v.typ)
Expand Down Expand Up @@ -95,5 +97,9 @@ var createCommand = cli.Command{
Value: "rootfs",
Usage: "A directory representing the root filesystem of the container in the OCI runtime bundle. It is strongly recommended to keep the default value.",
},
cli.StringSliceFlag{
Name: "platform",
Usage: "The platform contains os and arch. Filter manifests according to the conditions provided. Only applicable if reftype is index.",
},
},
}
18 changes: 12 additions & 6 deletions cmd/oci-image-tool/unpack.go
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,9 @@ var unpackTypes = []string{
}

type unpackCmd struct {
typ string // the type to unpack, can be empty string
ref string
typ string // the type to unpack, can be empty string
ref string
platform []string
}

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

v := unpackCmd{
typ: context.String("type"),
ref: context.String("ref"),
typ: context.String("type"),
ref: context.String("ref"),
platform: context.StringSlice("platform"),
}

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

case image.TypeImage:
err = image.UnpackFile(context.Args()[0], context.Args()[1], v.ref)
err = image.UnpackFile(context.Args()[0], context.Args()[1], v.ref, v.platform)

default:
err = fmt.Errorf("cannot unpack %q", v.typ)
Expand Down Expand Up @@ -86,5 +88,9 @@ var unpackCommand = cli.Command{
Value: "v1.0",
Usage: "The ref pointing to the manifest of the OCI image. This must be present in the 'refs' subdirectory of the image.",
},
cli.StringSliceFlag{
Name: "platform",
Usage: "The platform contains os and arch conditions. Filter manifests according to the conditions provided. Only applicable if reftype is index.",
},
},
}
4 changes: 2 additions & 2 deletions completions/bash/oci-image-tool
Original file line number Diff line number Diff line change
Expand Up @@ -150,7 +150,7 @@ _oci-image-tool_create() {

case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--type --ref --rootfs --help -h" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--type --ref --rootfs --platform --help -h" -- "$cur" ) )
;;
esac

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

case "$cur" in
-*)
COMPREPLY=( $( compgen -W "--type --ref --help -h" -- "$cur" ) )
COMPREPLY=( $( compgen -W "--type --ref --platform --help -h" -- "$cur" ) )
;;
esac

Expand Down
114 changes: 63 additions & 51 deletions image/image.go
Original file line number Diff line number Diff line change
Expand Up @@ -115,7 +115,7 @@ func validate(w walker, refs []string, out *log.Logger) error {
}

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

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

return Unpack(f, dest, ref)
return Unpack(f, dest, ref, platform)
}

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

func unpack(w walker, dest, refName string) error {
func unpack(w walker, dest, refName string, platform []string) error {
ref, err := findDescriptor(w, refName)
if err != nil {
return err
Expand Down Expand Up @@ -188,28 +188,17 @@ func unpack(w walker, dest, refName string) error {
return err
}

if err := validateIndex(index, w); err != nil {
if err = validateIndex(index, w); err != nil {
return err
}

if len(index.Manifests) == 0 {
fmt.Println("warning: no manifests found")
return nil
manifests, err := filterManifest(w, index.Manifests, platform)
if err != nil {
return err
}

for _, manifest := range index.Manifests {
m, err := findManifest(w, &(manifest.Descriptor))
if err != nil {
return err
}

if err := m.validate(w); err != nil {
return err
}

if err := m.unpack(w, dest); err != nil {
return err
}
for _, m := range manifests {
return m.unpack(w, dest)
}
}

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

// CreateRuntimeBundleFile opens the file pointed by tarFile and calls
// CreateRuntimeBundle.
func CreateRuntimeBundleFile(tarFile, dest, ref, root string) error {
func CreateRuntimeBundleFile(tarFile, dest, ref, root string, platform []string) error {
f, err := os.Open(tarFile)
if err != nil {
return errors.Wrap(err, "unable to open file")
}
defer f.Close()

return createRuntimeBundle(newTarWalker(f), dest, ref, root)
return createRuntimeBundle(newTarWalker(f), dest, ref, root, platform)
}

// CreateRuntimeBundle walks through the given tar stream and
// creates an OCI runtime bundle in the given destination dest
// or returns an error if the unpacking failed.
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string) error {
return createRuntimeBundle(newTarWalker(r), dest, ref, root)
func CreateRuntimeBundle(r io.ReadSeeker, dest, ref, root string, platform []string) error {
return createRuntimeBundle(newTarWalker(r), dest, ref, root, platform)
}

func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
func createRuntimeBundle(w walker, dest, refName, rootfs string, platform []string) error {
ref, err := findDescriptor(w, refName)
if err != nil {
return err
Expand All @@ -262,7 +251,7 @@ func createRuntimeBundle(w walker, dest, refName, rootfs string) error {
return err
}

return createRuntimebundle(w, m, dest, rootfs)
return createBundle(w, m, dest, rootfs)
}

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

if err := validateIndex(index, w); err != nil {
if err = validateIndex(index, w); err != nil {
return err
}

if len(index.Manifests) == 0 {
fmt.Println("warning: no manifests found")
return nil
manifests, err := filterManifest(w, index.Manifests, platform)
if err != nil {
return err
}

for _, manifest := range index.Manifests {
m, err := findManifest(w, &(manifest.Descriptor))
if err != nil {
return err
}

if err := m.validate(w); err != nil {
return err
}

if err := createRuntimebundle(w, m, dest, rootfs); err != nil {
return err
}
for _, m := range manifests {
return createBundle(w, m, dest, rootfs)
}
}

return nil
}

func createRuntimebundle(w walker, m *manifest, dest, rootfs string) error {
func createBundle(w walker, m *manifest, dest, rootfs string) error {
c, err := findConfig(w, &m.Config)
if err != nil {
return err
Expand Down Expand Up @@ -332,3 +310,37 @@ func createRuntimebundle(w walker, m *manifest, dest, rootfs string) error {

return json.NewEncoder(f).Encode(spec)
}

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

if len(Manifests) == 0 {
fmt.Println("warning: no manifests found")
return manifests, nil
}

if len(platform) != 2 {
return manifests, fmt.Errorf("platform must have os and arch")
}

for _, manifest := range Manifests {
m, err := findManifest(w, &manifest)
if err != nil {
return manifests, err
}

if err := m.validate(w); err != nil {
return manifests, err
}
if manifest.Platform.OS == platform[0] && manifest.Platform.Architecture == platform[1] {
manifests = append(manifests, m)
}
}

if len(manifests) == 0 {
return manifests, fmt.Errorf("There is no matching manifest")
}

return manifests, nil
}
8 changes: 4 additions & 4 deletions image/index.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,8 +28,8 @@ import (
"github.com/pkg/errors"
)

func findIndex(w walker, d *v1.Descriptor) (*v1.ImageIndex, error) {
var index v1.ImageIndex
func findIndex(w walker, d *v1.Descriptor) (*v1.Index, error) {
var index v1.Index

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

func validateIndex(index *v1.ImageIndex, w walker) error {
func validateIndex(index *v1.Index, w walker) error {
for _, manifest := range index.Manifests {
if err := validateDescriptor(&manifest.Descriptor, w, []string{v1.MediaTypeImageManifest}); err != nil {
if err := validateDescriptor(&manifest, w, []string{v1.MediaTypeImageManifest}); err != nil {
return errors.Wrap(err, "manifest validation failed")
}
}
Expand Down
4 changes: 4 additions & 0 deletions man/oci-image-tool-create.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,10 @@ runtime-spec-compatible `dest/config.json`.
**--type**=""
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"

**--platform**=""
The platform contains os and arch. Filter manifests according to the conditions provided.
Only applicable if reftype is index.

# EXAMPLES
```
$ skopeo copy docker://busybox oci:busybox-oci
Expand Down
5 changes: 5 additions & 0 deletions man/oci-image-tool-unpack.1.md
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ oci-image-tool unpack \- Unpack an image or image source layout
**--type**=""
Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image"

**--platform**=""
The platform contains os and arch. Filter manifests according to the conditions provided.
Only applicable if reftype is index.


# EXAMPLES
```
$ skopeo copy docker://busybox oci:busybox-oci
Expand Down

0 comments on commit 0140f7d

Please sign in to comment.