From 1423c5e01935372d9f069e158f11a0f1b43df221 Mon Sep 17 00:00:00 2001 From: zhouhao Date: Tue, 6 Dec 2016 17:05:07 +0800 Subject: [PATCH] merging of subcommands Signed-off-by: zhouhao --- .gitignore | 4 +- .travis.yml | 2 +- Makefile | 58 +++--- cmd/oci-create-runtime-bundle/main.go | 152 -------------- cmd/oci-image-tool/create.go | 104 ++++++++++ cmd/oci-image-tool/main.go | 60 ++++++ cmd/oci-image-tool/unpack.go | 93 +++++++++ cmd/oci-image-tool/validate.go | 145 +++++++++++++ cmd/oci-image-validate/main.go | 192 ------------------ cmd/oci-unpack/main.go | 144 ------------- .../oci-image-tool-create.1.md | 14 +- .../oci-image-tool-unpack.1.md | 14 +- .../oci-image-tool-validate.1.md | 14 +- man/oci-image-tool.1.md | 43 ++++ 14 files changed, 498 insertions(+), 541 deletions(-) delete mode 100644 cmd/oci-create-runtime-bundle/main.go create mode 100644 cmd/oci-image-tool/create.go create mode 100644 cmd/oci-image-tool/main.go create mode 100644 cmd/oci-image-tool/unpack.go create mode 100644 cmd/oci-image-tool/validate.go delete mode 100644 cmd/oci-image-validate/main.go delete mode 100644 cmd/oci-unpack/main.go rename cmd/oci-create-runtime-bundle/oci-create-runtime-bundle.1.md => man/oci-image-tool-create.1.md (60%) rename cmd/oci-unpack/oci-unpack.1.md => man/oci-image-tool-unpack.1.md (64%) rename cmd/oci-image-validate/oci-image-validate.1.md => man/oci-image-tool-validate.1.md (58%) create mode 100644 man/oci-image-tool.1.md diff --git a/.gitignore b/.gitignore index 83397be..128ade0 100644 --- a/.gitignore +++ b/.gitignore @@ -1,5 +1,3 @@ -/oci-create-runtime-bundle -/oci-unpack -/oci-image-validate +/oci-image-tool *.1 diff --git a/.travis.yml b/.travis.yml index 48eecfb..52f77aa 100644 --- a/.travis.yml +++ b/.travis.yml @@ -21,4 +21,4 @@ script: - make lint - make check-license - make test - - make tools + - make tool diff --git a/Makefile b/Makefile index 54918f3..5e15555 100644 --- a/Makefile +++ b/Makefile @@ -1,25 +1,19 @@ GO15VENDOREXPERIMENT=1 export GO15VENDOREXPERIMENT +PREFIX ?= $(DESTDIR)/usr +BINDIR ?= $(DESTDIR)/usr/bin -COMMIT=$(shell git rev-parse HEAD 2> /dev/null || true) - -EPOCH_TEST_COMMIT ?= v0.2.0 -TOOLS := \ - oci-create-runtime-bundle \ - oci-image-validate \ - oci-unpack -MAN := $(TOOLS:%=%.1) default: all help: @echo "Usage: make " @echo - @echo " * 'all' - Build the oci tools and manual pages" + @echo " * 'all' - Build the oci tool and manual pages" + @echo " * 'tool' - Build the oci tool" @echo " * 'install' - Install binaries and manual pages" - @echo " * 'install.tools' - Install tools needed for building this project" - @echo " * 'uninstall' - Remove the oci tools and manual pages" - @echo " * 'tools' - Build the oci image tools binaries" + @echo " * 'install.tools' - Install tool needed for building this project" + @echo " * 'uninstall' - Remove the oci tool and manual pages" @echo " * 'man' - Build the oci image manual pages" @echo " * 'check-license' - Check license headers in source files" @echo " * 'lint' - Execute the source code linter" @@ -31,25 +25,33 @@ check-license: @echo "checking license headers" @./.tool/check-license -tools: $(TOOLS) +.PHONY: tool +tool: + go build -o oci-image-tool ./cmd/oci-image-tool -man: $(MAN) -all: $(TOOLS) $(MAN) +all: tool man -$(TOOLS): oci-%: - go build -ldflags "-X main.gitCommit=${COMMIT}" ./cmd/$@ +.PHONY: man +man: + go-md2man -in "man/oci-image-tool.1.md" -out "oci-image-tool.1" + go-md2man -in "man/oci-image-tool-create.1.md" -out "oci-image-tool-create.1" + go-md2man -in "man/oci-image-tool-unpack.1.md" -out "oci-image-tool-unpack.1" + go-md2man -in "man/oci-image-tool-validate.1.md" -out "oci-image-tool-validate.1" -.SECONDEXPANSION: -$(MAN): %.1: cmd/$$*/$$*.1.md - go-md2man -in "$<" -out "$@" -install: $(TOOLS) $(MAN) - install -m 755 $(TOOLS) /usr/local/bin/ - install -m 644 $(MAN) /usr/local/share/man/man1 +install: man + install -d -m 755 $(BINDIR) + install -m 755 oci-image-tool $(BINDIR) + install -d -m 755 $(PREFIX)/share/man/man1 + install -m 644 *.1 $(PREFIX)/share/man/man1 + install -d -m 755 $(PREFIX)/share/bash-completion/completions + install -m 644 completions/bash/oci-image-tool $(PREFIX)/share/bash-completion/completionsn -uninstall: clean - rm -f $(MAN:%=/usr/local/share/man/man1/%) $(TOOLS:%=/usr/local/bin/%) +uninstall: + rm -f $(BINDIR)/oci-image-tool + rm -f $(PREFIX)/share/man/man1/oci-image-tool*.1 + rm -f $(PREFIX)/share/bash-completion/completions/oci-image-tool lint: @echo "checking lint" @@ -58,6 +60,7 @@ lint: test: go test -race -cover $(shell go list ./... | grep -v /vendor/) + ## this uses https://github.com/Masterminds/glide and https://github.com/sgotti/glide-vc update-deps: @which glide > /dev/null 2>/dev/null || (echo "ERROR: glide not found. Consider 'make install.tools' target" && false) @@ -98,12 +101,11 @@ install.tools: .install.gitvalidation .install.glide .install.glide-vc .install. go get github.com/cpuguy83/go-md2man clean: - rm -rf *~ $(OUTPUT_DIRNAME) $(TOOLS) $(MAN) + rm -rf oci-image-tool *.1 .PHONY: \ all \ - tools \ - $(TOOLS) \ + tool \ man \ install \ uninstall \ diff --git a/cmd/oci-create-runtime-bundle/main.go b/cmd/oci-create-runtime-bundle/main.go deleted file mode 100644 index e1a15fc..0000000 --- a/cmd/oci-create-runtime-bundle/main.go +++ /dev/null @@ -1,152 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "log" - "os" - "strings" - - specs "github.com/opencontainers/image-spec/specs-go" - "github.com/opencontainers/image-tools/image" - "github.com/opencontainers/image-tools/version" - "github.com/spf13/cobra" -) - -// gitCommit will be the hash that the binary was built from -// and will be populated by the Makefile -var gitCommit = "" - -// supported bundle types -var bundleTypes = []string{ - image.TypeImageLayout, - image.TypeImage, -} - -type bundleCmd struct { - stdout *log.Logger - stderr *log.Logger - typ string // the type to bundle, can be empty string - ref string - root string - version bool -} - -func main() { - stdout := log.New(os.Stdout, "", 0) - stderr := log.New(os.Stderr, "", 0) - - cmd := newBundleCmd(stdout, stderr) - if err := cmd.Execute(); err != nil { - stderr.Println(err) - os.Exit(1) - } -} - -func newBundleCmd(stdout, stderr *log.Logger) *cobra.Command { - v := &bundleCmd{ - stdout: stdout, - stderr: stderr, - } - - cmd := &cobra.Command{ - Use: "oci-create-runtime-bundle [src] [dest]", - Short: "Create an OCI image runtime bundle", - Long: `Creates an OCI image runtime bundle at the destination directory [dest] from an OCI image present at [src].`, - Run: v.Run, - } - - cmd.Flags().StringVar( - &v.typ, "type", "", - fmt.Sprintf( - `Type of the file to unpack. If unset, oci-create-runtime-bundle will try to auto-detect the type. One of "%s"`, - strings.Join(bundleTypes, ","), - ), - ) - - cmd.Flags().StringVar( - &v.ref, "ref", "v1.0", - `The ref pointing to the manifest of the OCI image. This must be present in the "refs" subdirectory of the image.`, - ) - - cmd.Flags().StringVar( - &v.root, "rootfs", "rootfs", - `A directory representing the root filesystem of the container in the OCI runtime bundle. -It is strongly recommended to keep the default value.`, - ) - - cmd.Flags().BoolVarP( - &v.version, "version", "v", false, - `Print version information and exit`, - ) - - origHelp := cmd.HelpFunc() - - cmd.SetHelpFunc(func(c *cobra.Command, args []string) { - origHelp(c, args) - stdout.Println("\nMore information:") - stdout.Printf("\treferences\t%s\n", image.SpecURL) - stdout.Printf("\tbug report\t%s\n", image.IssuesURL) - }) - - return cmd -} - -func (v *bundleCmd) Run(cmd *cobra.Command, args []string) { - if v.version { - v.stdout.Printf("commit: %s", gitCommit) - v.stdout.Printf("version: %s", version.Version) - v.stdout.Printf("spec: %s", specs.Version) - os.Exit(0) - - } - if len(args) != 2 { - v.stderr.Print("both src and dest must be provided") - if err := cmd.Usage(); err != nil { - v.stderr.Println(err) - } - os.Exit(1) - } - - if v.typ == "" { - typ, err := image.Autodetect(args[0]) - if err != nil { - v.stderr.Printf("%q: autodetection failed: %v", args[0], err) - os.Exit(1) - } - v.typ = typ - } - - var err error - switch v.typ { - case image.TypeImageLayout: - err = image.CreateRuntimeBundleLayout(args[0], args[1], v.ref, v.root) - - case image.TypeImage: - err = image.CreateRuntimeBundle(args[0], args[1], v.ref, v.root) - - default: - err = fmt.Errorf("cannot create %q", v.typ) - - } - - if err != nil { - v.stderr.Printf("creating failed: %v", err) - os.Exit(1) - } - - os.Exit(0) -} diff --git a/cmd/oci-image-tool/create.go b/cmd/oci-image-tool/create.go new file mode 100644 index 0000000..ced7cce --- /dev/null +++ b/cmd/oci-image-tool/create.go @@ -0,0 +1,104 @@ +// Copyright 2016 The Linux Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "strings" + + "github.com/opencontainers/image-tools/image" + "github.com/urfave/cli" +) + +// supported bundle types +var bundleTypes = []string{ + image.TypeImageLayout, + image.TypeImage, +} + +type bundleCmd struct { + typ string // the type to bundle, can be empty string + ref string + root string +} + +func createHandle(context *cli.Context) error { + if len(context.Args()) != 2 { + return fmt.Errorf("both src and dest must be provided") + } + + var v bundleCmd + if context.IsSet("type") { + v.typ = context.String("type") + } + if context.IsSet("ref") { + v.ref = context.String("ref") + } + if context.IsSet("rootfs") { + v.root = context.String("roofs") + } + + if v.typ == "" { + typ, err := image.Autodetect(context.Args()[0]) + if err != nil { + return fmt.Errorf("%q: autodetection failed: %v", context.Args()[0], err) + } + v.typ = typ + } + + var err error + switch v.typ { + case image.TypeImageLayout: + err = image.CreateRuntimeBundleLayout(context.Args()[0], context.Args()[1], v.ref, v.root) + + case image.TypeImage: + err = image.CreateRuntimeBundle(context.Args()[0], context.Args()[1], v.ref, v.root) + + default: + err = fmt.Errorf("cannot create %q", v.typ) + + } + + if err != nil { + fmt.Printf("creating failed: %v\n", err) + } + + return err +} + +var createCommand = cli.Command{ + Name: "create", + Usage: "Create an OCI image runtime bundle", + Action: createHandle, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "type", + Usage: fmt.Sprintf( + `Type of the file to unpack. If unset, oci-image-tool-validate will try to auto-detect the type. One of "%s".`, + strings.Join(bundleTypes, ","), + ), + }, + cli.StringFlag{ + Name: "ref", + 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.StringFlag{ + Name: "rootfs", + 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.", + }, + }, +} diff --git a/cmd/oci-image-tool/main.go b/cmd/oci-image-tool/main.go new file mode 100644 index 0000000..e91d59a --- /dev/null +++ b/cmd/oci-image-tool/main.go @@ -0,0 +1,60 @@ +// Copyright 2016 The Linux Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "os" + + "github.com/Sirupsen/logrus" + "github.com/opencontainers/image-tools/version" + "github.com/urfave/cli" +) + +// gitCommit will be the hash that the binary was built from +// and will be populated by the Makefile +var gitCommit = "" + +func main() { + app := cli.NewApp() + app.Name = "oci-image-tool" + if gitCommit != "" { + app.Version = fmt.Sprintf("%s commit: %s", version.Version, gitCommit) + } else { + app.Version = version.Version + } + app.Usage = "OCI (Open Container Initiative) image tools" + app.Flags = []cli.Flag{ + cli.BoolFlag{ + Name: "debug", + Usage: "enable debug output", + }, + } + app.Before = func(c *cli.Context) error { + if c.GlobalBool("debug") { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + } + app.Commands = []cli.Command{ + validateCommand, + unpackCommand, + createCommand, + } + + if err := app.Run(os.Args); err != nil { + logrus.Fatal(err) + } +} diff --git a/cmd/oci-image-tool/unpack.go b/cmd/oci-image-tool/unpack.go new file mode 100644 index 0000000..76f9a68 --- /dev/null +++ b/cmd/oci-image-tool/unpack.go @@ -0,0 +1,93 @@ +// Copyright 2016 The Linux Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "strings" + + "github.com/opencontainers/image-tools/image" + "github.com/urfave/cli" +) + +// supported unpack types +var unpackTypes = []string{ + image.TypeImageLayout, + image.TypeImage, +} + +type unpackCmd struct { + typ string // the type to unpack, can be empty string + ref string +} + +func unpackHandle(context *cli.Context) error { + if len(context.Args()) != 2 { + return fmt.Errorf("both src and dest must be provided") + } + + var v unpackCmd + if context.IsSet("type") { + v.typ = context.String("type") + } + if context.IsSet("ref") { + v.ref = context.String("ref") + } + + if v.typ == "" { + typ, err := image.Autodetect(context.Args()[0]) + if err != nil { + return fmt.Errorf("%q: autodetection failed: %v", context.Args()[0], err) + } + v.typ = typ + } + + var err error + switch v.typ { + case image.TypeImageLayout: + err = image.UnpackLayout(context.Args()[0], context.Args()[1], v.ref) + + case image.TypeImage: + err = image.Unpack(context.Args()[0], context.Args()[1], v.ref) + + default: + err = fmt.Errorf("cannot unpack %q", v.typ) + } + + if err != nil { + fmt.Printf("unpacking failed: %v\n", err) + } + return err +} + +var unpackCommand = cli.Command{ + Name: "unpack", + Usage: "Unpack an image or image source layout", + Action: unpackHandle, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "type", + Usage: fmt.Sprintf( + `Type of the file to unpack. If unset, oci-image-tool-validate will try to auto-detect the type. One of "%s".`, + strings.Join(unpackTypes, ","), + ), + }, + cli.StringFlag{ + Name: "ref", + 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.", + }, + }, +} diff --git a/cmd/oci-image-tool/validate.go b/cmd/oci-image-tool/validate.go new file mode 100644 index 0000000..ed0895e --- /dev/null +++ b/cmd/oci-image-tool/validate.go @@ -0,0 +1,145 @@ +// Copyright 2016 The Linux Foundation +// +// Licensed under the Apache License, Version 2.0 (the "License"); +// you may not use this file except in compliance with the License. +// You may obtain a copy of the License at +// +// http://www.apache.org/licenses/LICENSE-2.0 +// +// Unless required by applicable law or agreed to in writing, software +// distributed under the License is distributed on an "AS IS" BASIS, +// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +// See the License for the specific language governing permissions and +// limitations under the License. + +package main + +import ( + "fmt" + "log" + "os" + "strings" + + "github.com/opencontainers/image-spec/schema" + "github.com/opencontainers/image-tools/image" + "github.com/pkg/errors" + "github.com/urfave/cli" +) + +// supported validation types +var validateTypes = []string{ + image.TypeImageLayout, + image.TypeImage, + image.TypeManifest, + image.TypeImageIndex, + image.TypeConfig, +} + +type validateCmd struct { + stdout *log.Logger + typ string // the type to validate, can be empty string + refs []string +} + +var v validateCmd + +func validateHandler(context *cli.Context) error { + if len(context.Args()) < 1 { + return fmt.Errorf("no files specified") + } + + if context.IsSet("type") { + v.typ = context.String("type") + } + + if context.IsSet("ref") { + v.refs = context.StringSlice("ref") + } + + var errs []string + for _, arg := range context.Args() { + err := validatePath(arg) + + if err == nil { + fmt.Printf("%s: OK\n", arg) + continue + } + + if verr, ok := errors.Cause(err).(schema.ValidationError); ok { + errs = append(errs, fmt.Sprintf("%v", verr.Errs)) + } else if serr, ok := errors.Cause(err).(*schema.SyntaxError); ok { + errs = append(errs, fmt.Sprintf("%s:%d:%d: validation failed: %v", arg, serr.Line, serr.Col, err)) + continue + } else { + errs = append(errs, fmt.Sprintf("%s: validation failed: %v", arg, err)) + continue + } + + } + + if len(errs) > 0 { + return fmt.Errorf("%d errors detected: \n%s", len(errs), strings.Join(errs, "\n")) + } + fmt.Println("Validation succeeded") + return nil +} + +func validatePath(name string) error { + var ( + err error + typ = v.typ + ) + + if typ == "" { + if typ, err = image.Autodetect(name); err != nil { + return errors.Wrap(err, "unable to determine type") + } + } + + switch typ { + case image.TypeImageLayout: + return image.ValidateLayout(name, v.refs, v.stdout) + case image.TypeImage: + return image.Validate(name, v.refs, v.stdout) + } + + if len(v.refs) != 0 { + fmt.Printf("WARNING: type %q does not support refs, which are only appropriate if type is image or imageLayout.\n", typ) + } + + f, err := os.Open(name) + if err != nil { + return errors.Wrap(err, "unable to open file") + } + defer f.Close() + + switch typ { + case image.TypeManifest: + return schema.ValidatorMediaTypeManifest.Validate(f) + case image.TypeImageIndex: + return schema.ValidatorMediaTypeImageIndex.Validate(f) + case image.TypeConfig: + return schema.ValidatorMediaTypeImageConfig.Validate(f) + } + + return fmt.Errorf("type %q unimplemented", typ) +} + +var validateCommand = cli.Command{ + Name: "validate", + Usage: "Validate one or more image files", + Action: validateHandler, + Flags: []cli.Flag{ + cli.StringFlag{ + Name: "type", + Usage: fmt.Sprintf( + `Type of the file to validate. If unset, oci-image-tool-validate will try to auto-detect the type. One of "%s".`, + strings.Join(validateTypes, ","), + ), + }, + cli.StringSliceFlag{ + Name: "ref", + Usage: "A set of refs pointing to the manifests to be validated. Each reference must be present in the refs subdirectory of the image. Only applicable if type is image or imageLayout.", + }, + }, +} diff --git a/cmd/oci-image-validate/main.go b/cmd/oci-image-validate/main.go deleted file mode 100644 index 373f197..0000000 --- a/cmd/oci-image-validate/main.go +++ /dev/null @@ -1,192 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "log" - "os" - "strings" - - "github.com/opencontainers/image-spec/schema" - specs "github.com/opencontainers/image-spec/specs-go" - "github.com/opencontainers/image-tools/image" - "github.com/opencontainers/image-tools/version" - "github.com/pkg/errors" - "github.com/spf13/cobra" -) - -// gitCommit will be the hash that the binary was built from -// and will be populated by the Makefile -var gitCommit = "" - -// supported validation types -var validateTypes = []string{ - image.TypeImageLayout, - image.TypeImage, - image.TypeManifest, - image.TypeImageIndex, - image.TypeConfig, -} - -type validateCmd struct { - stdout *log.Logger - stderr *log.Logger - typ string // the type to validate, can be empty string - refs []string - version bool -} - -func main() { - stdout := log.New(os.Stdout, "", 0) - stderr := log.New(os.Stderr, "", 0) - - cmd := newValidateCmd(stdout, stderr) - if err := cmd.Execute(); err != nil { - stderr.Println(err) - os.Exit(1) - } -} - -func newValidateCmd(stdout, stderr *log.Logger) *cobra.Command { - v := &validateCmd{ - stdout: stdout, - stderr: stderr, - } - - cmd := &cobra.Command{ - Use: "oci-image-validate FILE...", - Short: "Validate one or more image files", - Run: v.Run, - } - - cmd.Flags().StringVar( - &v.typ, "type", "", - fmt.Sprintf( - `Type of the file to validate. If unset, oci-image-validate will try to auto-detect the type. One of "%s".`, - strings.Join(validateTypes, ","), - ), - ) - - cmd.Flags().StringSliceVar( - &v.refs, "ref", nil, - `A set of refs pointing to the manifests to be validated. Each reference must be present in the "refs" subdirectory of the image. Only applicable if type is image or imageLayout.`, - ) - - cmd.Flags().BoolVarP( - &v.version, "version", "v", false, - `Print version information and exit`, - ) - - origHelp := cmd.HelpFunc() - - cmd.SetHelpFunc(func(c *cobra.Command, args []string) { - origHelp(c, args) - stdout.Println("\nMore information:") - stdout.Printf("\treferences\t%s\n", image.SpecURL) - stdout.Printf("\tbug report\t%s\n", image.IssuesURL) - }) - - return cmd -} - -func (v *validateCmd) Run(cmd *cobra.Command, args []string) { - if v.version { - v.stdout.Printf("commit: %s", gitCommit) - v.stdout.Printf("version: %s", version.Version) - v.stdout.Printf("spec: %s", specs.Version) - os.Exit(0) - } - - if len(args) < 1 { - v.stderr.Printf("no files specified") - if err := cmd.Usage(); err != nil { - v.stderr.Println(err) - } - os.Exit(1) - } - - var exitcode int - for _, arg := range args { - err := v.validatePath(arg) - - if err == nil { - v.stdout.Printf("%s: OK", arg) - continue - } - - var errs []error - if verr, ok := errors.Cause(err).(schema.ValidationError); ok { - errs = verr.Errs - } else if serr, ok := errors.Cause(err).(*schema.SyntaxError); ok { - v.stderr.Printf("%s:%d:%d: validation failed: %v", arg, serr.Line, serr.Col, err) - exitcode = 1 - continue - } else { - v.stderr.Printf("%s: validation failed: %v", arg, err) - exitcode = 1 - continue - } - - for _, err := range errs { - v.stderr.Printf("%s: validation failed: %v", arg, err) - } - - exitcode = 1 - } - - os.Exit(exitcode) -} - -func (v *validateCmd) validatePath(name string) error { - var ( - err error - typ = v.typ - ) - - if typ == "" { - if typ, err = image.Autodetect(name); err != nil { - return errors.Wrap(err, "unable to determine type") - } - } - - switch typ { - case image.TypeImageLayout: - return image.ValidateLayout(name, v.refs, v.stdout) - case image.TypeImage: - return image.Validate(name, v.refs, v.stdout) - } - - if len(v.refs) != 0 { - fmt.Printf("WARNING: type %q does not support refs, which are only appropriate if type is image or imageLayout.\n", typ) - } - - f, err := os.Open(name) - if err != nil { - return errors.Wrap(err, "unable to open file") - } - defer f.Close() - - switch typ { - case image.TypeManifest: - return schema.ValidatorMediaTypeManifest.Validate(f) - case image.TypeImageIndex: - return schema.ValidatorMediaTypeImageIndex.Validate(f) - case image.TypeConfig: - return schema.ValidatorMediaTypeImageConfig.Validate(f) - } - - return fmt.Errorf("type %q unimplemented", typ) -} diff --git a/cmd/oci-unpack/main.go b/cmd/oci-unpack/main.go deleted file mode 100644 index b82361f..0000000 --- a/cmd/oci-unpack/main.go +++ /dev/null @@ -1,144 +0,0 @@ -// Copyright 2016 The Linux Foundation -// -// Licensed under the Apache License, Version 2.0 (the "License"); -// you may not use this file except in compliance with the License. -// You may obtain a copy of the License at -// -// http://www.apache.org/licenses/LICENSE-2.0 -// -// Unless required by applicable law or agreed to in writing, software -// distributed under the License is distributed on an "AS IS" BASIS, -// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. -// See the License for the specific language governing permissions and -// limitations under the License. - -package main - -import ( - "fmt" - "log" - "os" - "strings" - - specs "github.com/opencontainers/image-spec/specs-go" - "github.com/opencontainers/image-tools/image" - "github.com/opencontainers/image-tools/version" - "github.com/spf13/cobra" -) - -// gitCommit will be the hash that the binary was built from -// and will be populated by the Makefile -var gitCommit = "" - -// supported unpack types -var unpackTypes = []string{ - image.TypeImageLayout, - image.TypeImage, -} - -type unpackCmd struct { - stdout *log.Logger - stderr *log.Logger - typ string // the type to unpack, can be empty string - ref string - version bool -} - -func main() { - stdout := log.New(os.Stdout, "", 0) - stderr := log.New(os.Stderr, "", 0) - - cmd := newUnpackCmd(stdout, stderr) - if err := cmd.Execute(); err != nil { - stderr.Println(err) - os.Exit(1) - } -} - -func newUnpackCmd(stdout, stderr *log.Logger) *cobra.Command { - v := &unpackCmd{ - stdout: stdout, - stderr: stderr, - } - - cmd := &cobra.Command{ - Use: "unpack [src] [dest]", - Short: "Unpack an image or image source layout", - Long: `Unpack the OCI image .tar file or OCI image layout directory present at [src] to the destination directory [dest].`, - Run: v.Run, - } - - cmd.Flags().StringVar( - &v.typ, "type", "", - fmt.Sprintf( - `Type of the file to unpack. If unset, oci-unpack will try to auto-detect the type. One of "%s"`, - strings.Join(unpackTypes, ","), - ), - ) - - cmd.Flags().StringVar( - &v.ref, "ref", "v1.0", - `The ref pointing to the manifest to be unpacked. This must be present in the "refs" subdirectory of the image.`, - ) - - cmd.Flags().BoolVarP( - &v.version, "version", "v", false, - `Print version information and exit`, - ) - - origHelp := cmd.HelpFunc() - - cmd.SetHelpFunc(func(c *cobra.Command, args []string) { - origHelp(c, args) - stdout.Println("\nMore information:") - stdout.Printf("\treferences\t%s\n", image.SpecURL) - stdout.Printf("\tbug report\t%s\n", image.IssuesURL) - }) - - return cmd -} - -func (v *unpackCmd) Run(cmd *cobra.Command, args []string) { - if v.version { - v.stdout.Printf("commit: %s", gitCommit) - v.stdout.Printf("version: %s", version.Version) - v.stdout.Printf("spec: %s", specs.Version) - os.Exit(0) - } - - if len(args) != 2 { - v.stderr.Print("both src and dest must be provided") - if err := cmd.Usage(); err != nil { - v.stderr.Println(err) - } - os.Exit(1) - } - - if v.typ == "" { - typ, err := image.Autodetect(args[0]) - if err != nil { - v.stderr.Printf("%q: autodetection failed: %v", args[0], err) - os.Exit(1) - } - v.typ = typ - } - - var err error - switch v.typ { - case image.TypeImageLayout: - err = image.UnpackLayout(args[0], args[1], v.ref) - - case image.TypeImage: - err = image.Unpack(args[0], args[1], v.ref) - - default: - err = fmt.Errorf("cannot unpack %q", v.typ) - } - - if err != nil { - v.stderr.Printf("unpacking failed: %v", err) - os.Exit(1) - } - - os.Exit(0) -} diff --git a/cmd/oci-create-runtime-bundle/oci-create-runtime-bundle.1.md b/man/oci-image-tool-create.1.md similarity index 60% rename from cmd/oci-create-runtime-bundle/oci-create-runtime-bundle.1.md rename to man/oci-image-tool-create.1.md index 0c25fd9..99ebe41 100644 --- a/cmd/oci-create-runtime-bundle/oci-create-runtime-bundle.1.md +++ b/man/oci-image-tool-create.1.md @@ -2,19 +2,19 @@ % OCI Community % JULY 2016 # NAME -oci-create-runtime-bundle \- Create an OCI runtime bundle +oci-image-tool-create \- Create an OCI runtime bundle # SYNOPSIS -**oci-create-runtime-bundle** [src] [dest] [flags] -**oci-create-runtime-bundle** [--help|-v|--version] +**oci-image-tool create** [src] [dest] [OPTIONS] +**oci-image-tool create** [--help|-v|--version] # DESCRIPTION -`oci-create-runtime-bundle` validates an application/vnd.oci.image.manifest.v1+json and unpacks its layered filesystem to `dest/rootfs`, although the target directory is configurable with `--rootfs`. See **oci-unpack**(1) for more details on this process. +`oci-image-tool create` validates an application/vnd.oci.image.manifest.v1+json and unpacks its layered filesystem to `dest/rootfs`, although the target directory is configurable with `--rootfs`. See **oci-image-tool unpack**(1) for more details on this process. Also translates the referenced config from application/vnd.oci.image.config.v1+json to a runtime-spec-compatible `dest/config.json`. -# FLAGS +# OPTIONS **--help** Print usage statement @@ -25,7 +25,7 @@ runtime-spec-compatible `dest/config.json`. A directory representing the root filesystem of the container in the OCI runtime bundle. It is strongly recommended to keep the default value. (default "rootfs") **--type**="" - Type of the file to unpack. If unset, oci-create-runtime-bundle will try to auto-detect the type. One of "imageLayout,image" + Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image" **-v**, **--version** Print version information and exit. @@ -34,7 +34,7 @@ runtime-spec-compatible `dest/config.json`. ``` $ skopeo copy docker://busybox oci:busybox-oci $ mkdir busybox-bundle -$ oci-create-runtime-bundle --ref latest busybox-oci busybox-bundle +$ oci-image-tool create --ref latest busybox-oci busybox-bundle $ cd busybox-bundle && sudo runc run busybox [...] ``` diff --git a/cmd/oci-unpack/oci-unpack.1.md b/man/oci-image-tool-unpack.1.md similarity index 64% rename from cmd/oci-unpack/oci-unpack.1.md rename to man/oci-image-tool-unpack.1.md index fcbbd92..e5d28e8 100644 --- a/cmd/oci-unpack/oci-unpack.1.md +++ b/man/oci-image-tool-unpack.1.md @@ -2,16 +2,16 @@ % OCI Community % JULY 2016 # NAME -oci-unpack \- Unpack an image or image source layout +oci-image-tool unpack \- Unpack an image or image source layout # SYNOPSIS -**oci-unpack** [src] [dest] [flags] -**oci-unpack** [--help|-v|--version] +**oci-image-tool unpack** [src] [dest] [OPTIONS] +**oci-image-tool unpack** [--help|-v|--version] # DESCRIPTION -`oci-unpack` validates an application/vnd.oci.image.manifest.v1+json and unpacks its layered filesystem to `dest`. +`oci-image-tool unpack` validates an application/vnd.oci.image.manifest.v1+json and unpacks its layered filesystem to `dest`. -# FLAGS +# OPTIONS **--help** Print usage statement @@ -19,7 +19,7 @@ oci-unpack \- Unpack an image or image source layout The ref pointing to the manifest to be unpacked. This must be present in the "refs" subdirectory of the image. (default "v1.0") **--type**="" - Type of the file to unpack. If unset, oci-unpack will try to auto-detect the type. One of "imageLayout,image" + Type of the file to unpack. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image" **-v**, **--version** Print version information and exit. @@ -28,7 +28,7 @@ oci-unpack \- Unpack an image or image source layout ``` $ skopeo copy docker://busybox oci:busybox-oci $ mkdir busybox-bundle -$ oci-unpack --ref latest busybox-oci busybox-bundle +$ oci-image-tool unpack --ref latest busybox-oci busybox-bundle $ tree busybox-bundle busybox-bundle ├── bin diff --git a/cmd/oci-image-validate/oci-image-validate.1.md b/man/oci-image-tool-validate.1.md similarity index 58% rename from cmd/oci-image-validate/oci-image-validate.1.md rename to man/oci-image-tool-validate.1.md index c2e1efa..ccde692 100644 --- a/cmd/oci-image-validate/oci-image-validate.1.md +++ b/man/oci-image-tool-validate.1.md @@ -2,17 +2,17 @@ % OCI Community % JULY 2016 # NAME -oci-image-validate \- Validate one or more image files +oci-image-tool validate \- Validate one or more image files # SYNOPSIS -**oci-image-validate** FILE... [flags] -**oci-image-validate** [--help|-v|--version] +**oci-image-tool validate** FILE... [OPTIONS] +**oci-image-tool validate** [--help|-v|--version] # DESCRIPTION -`oci-image-validate` validates the given file(s) against the OCI image specification. +`oci-image-tool validate` validates the given file(s) against the OCI image specification. -# FLAGS +# OPTIONS **--help** Print usage statement @@ -23,7 +23,7 @@ oci-image-validate \- Validate one or more image files Only applicable if type is image or imageLayout. **--type**="" - Type of the file to validate. If unset, oci-image-validate will try to auto-detect the type. One of "imageLayout,image,manifest,imageIndex,config" + Type of the file to validate. If unset, oci-image-tool will try to auto-detect the type. One of "imageLayout,image,manifest,imageIndex,config" **-v**, **--version** Print version information and exit. @@ -31,7 +31,7 @@ oci-image-validate \- Validate one or more image files # EXAMPLES ``` $ skopeo copy docker://busybox oci:busybox-oci -$ oci-image-validate --type imageLayout --ref latest busybox-oci +$ oci-image-tool validate --type imageLayout --ref latest busybox-oci busybox-oci: OK ``` diff --git a/man/oci-image-tool.1.md b/man/oci-image-tool.1.md new file mode 100644 index 0000000..1dcecb4 --- /dev/null +++ b/man/oci-image-tool.1.md @@ -0,0 +1,43 @@ +% OCI(1) OCI-IMAGE-TOOL User Manuals +% OCI Community +% JULY 2016 +# NAME +oci-image-tool \- OCI (Open Container Initiative) image tools + +# SYNOPSIS +**oci-image-tool** [OPTIONS] COMMAND [arg...] + +**oci-image-tool** [--help|-v|--version] + +# DESCRIPTION +oci-image-tool is a collection of tools for working with the [OCI image specification](https://github.com/opencontainers/image-spec). + + +# OPTIONS +**--help** + Print usage statement. + +**--debug** + Enable debug output + +**-v**, **--version** + Print version information. + +# COMMANDS +**validate** + Validate the given file(s) against the OCI image specification + See **oci-image-tool-validate**(1) for full documentation on the **validate** command. + +**unpack** + Unpack the file which against the OCI image specification into a bundle directory. + See **oci-image-tool-unpack**(1) for full documentation on the **unpack** command. + +**create** + Create an OCI runtime bundle + See **oci-image-tool-create**(1) for full documentation on the **create** command. + +# SEE ALSO +**oci-image-tool-validate**(1), **oci-image-tool-unpack**(1), **oci-image-tool-create**(1) + +# HISTORY +Sept 2016, Originally compiled by Antonio Murdaca (runcom at redhat dot com)