diff --git a/.gitignore b/.gitignore index 772132c4..8c72f3ee 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ -skopeo -skopeo.1 -layers-* +!cmd/skopeo/ +/skopeo +/skopeo.1 +/layers-* diff --git a/cmd/skopeo/inspect.go b/cmd/skopeo/inspect.go new file mode 100644 index 00000000..6cf426f6 --- /dev/null +++ b/cmd/skopeo/inspect.go @@ -0,0 +1,70 @@ +package main + +import ( + "encoding/json" + "fmt" + "strings" + + "github.com/Sirupsen/logrus" + "github.com/codegangsta/cli" + "github.com/projectatomic/skopeo" + pkgInspect "github.com/projectatomic/skopeo/docker/inspect" + "github.com/projectatomic/skopeo/types" +) + +var inspectCmd = cli.Command{ + Name: "inspect", + Usage: "inspect images on a registry", + ArgsUsage: ``, + Flags: []cli.Flag{ + cli.BoolFlag{ + Name: "raw", + Usage: "output raw manifest", + }, + }, + Action: func(c *cli.Context) { + if c.Bool("raw") { + img, err := skopeo.ParseImage(c.Args().First()) + if err != nil { + logrus.Fatal(err) + } + // TODO(runcom): this is not falling back to v1 + // TODO(runcom): hardcoded schema 2 version 1 + b, err := img.RawManifest("2-1") + if err != nil { + logrus.Fatal(err) + } + fmt.Println(string(b)) + return + } + // get the Image interface before inspecting...utils.go parseImage + imgInspect, err := inspect(c) + if err != nil { + logrus.Fatal(err) + } + out, err := json.Marshal(imgInspect) + if err != nil { + logrus.Fatal(err) + } + fmt.Println(string(out)) + }, +} + +func inspect(c *cli.Context) (types.ImageManifest, error) { + var ( + imgInspect types.ImageManifest + err error + name = c.Args().First() + ) + + switch { + case strings.HasPrefix(name, types.DockerPrefix): + imgInspect, err = pkgInspect.GetData(c, strings.Replace(name, "docker://", "", -1)) + if err != nil { + return nil, err + } + default: + return nil, fmt.Errorf("%s image is invalid, please use 'docker://'", name) + } + return imgInspect, nil +} diff --git a/cmd/skopeo/layers.go b/cmd/skopeo/layers.go new file mode 100644 index 00000000..5031052d --- /dev/null +++ b/cmd/skopeo/layers.go @@ -0,0 +1,23 @@ +package main + +import ( + "github.com/Sirupsen/logrus" + "github.com/codegangsta/cli" + "github.com/projectatomic/skopeo" +) + +// TODO(runcom): document args and usage +var layersCmd = cli.Command{ + Name: "layers", + Usage: "get images layers", + ArgsUsage: ``, + Action: func(context *cli.Context) { + img, err := skopeo.ParseImage(context.Args().First()) + if err != nil { + logrus.Fatal(err) + } + if err := img.Layers(context.Args().Tail()...); err != nil { + logrus.Fatal(err) + } + }, +} diff --git a/cmd/skopeo/main.go b/cmd/skopeo/main.go new file mode 100644 index 00000000..ca92f864 --- /dev/null +++ b/cmd/skopeo/main.go @@ -0,0 +1,58 @@ +package main + +import ( + "fmt" + "os" + + "github.com/Sirupsen/logrus" + "github.com/codegangsta/cli" + "github.com/docker/docker/cliconfig" + "github.com/projectatomic/skopeo" +) + +func main() { + app := cli.NewApp() + app.Name = "skopeo" + if skopeo.GitCommit != "" { + app.Version = fmt.Sprintf("%s commit: %s", skopeo.Version, skopeo.GitCommit) + } else { + app.Version = skopeo.Version + } + app.Usage = "interact with registries" + // TODO(runcom) + //app.EnableBashCompletion = true + app.Flags = []cli.Flag{ + cli.BoolFlag{ + Name: "debug", + Usage: "enable debug output", + }, + cli.StringFlag{ + Name: "username", + Value: "", + Usage: "registry username", + }, + cli.StringFlag{ + Name: "password", + Value: "", + Usage: "registry password", + }, + cli.StringFlag{ + Name: "docker-cfg", + Value: cliconfig.ConfigDir(), + Usage: "Docker's cli config for auth", + }, + } + app.Before = func(c *cli.Context) error { + if c.GlobalBool("debug") { + logrus.SetLevel(logrus.DebugLevel) + } + return nil + } + app.Commands = []cli.Command{ + inspectCmd, + layersCmd, + } + if err := app.Run(os.Args); err != nil { + logrus.Fatal(err) + } +}