Merge pull request #886 from yifan-gu/img_cat

rkt/image: Add cat-manifest to print the image manifest to stdout.
This commit is contained in:
Yifan Gu
2015-05-12 23:27:10 -07:00
4 changed files with 222 additions and 4 deletions
+63 -4
View File
@@ -34,9 +34,10 @@ var (
}
helpFlags flag.FlagSet
globalUsageTemplate *template.Template
commandUsageTemplate *template.Template
templFuncs = template.FuncMap{
globalUsageTemplate *template.Template
commandUsageTemplate *template.Template
subCommandUsageTemplate *template.Template
templFuncs = template.FuncMap{
"descToLines": func(s string) []string {
// trim leading/trailing whitespace and split into slice of lines
return strings.Split(strings.Trim(s, "\n\t "), "\n")
@@ -86,6 +87,20 @@ DESCRIPTION:
{{printOption .Name .DefValue .Usage}}{{end}}
{{end}}For help on global options run "{{.Executable}} help"
`[1:]))
subCommandUsageTemplate = template.Must(template.New("subcommand_usage").Funcs(templFuncs).Parse(`
NAME:
{{printf "\t%s %s - %s" .CmdName .SubCmd.Name .SubCmd.Summary}}
USAGE:
{{printf "\t%s %s %s %s" .Executable .CmdName .SubCmd.Name .SubCmd.Usage}}
DESCRIPTION:
{{range $line := descToLines .SubCmd.Description}}{{printf "\t%s" $line}}
{{end}}
{{if .SubCmdFlags}}OPTIONS:{{range .SubCmdFlags}}
{{printOption .Name .DefValue .Usage}}{{end}}
{{end}}
`[1:]))
}
@@ -95,7 +110,17 @@ func runHelp(args []string) (exit int) {
return
}
if err := printCommandUsageByName(args[0]); err != nil {
if len(args) == 1 {
if err := printCommandUsageByName(args[0]); err != nil {
printGlobalUsage()
stderr("\nHelp error: %v\n", err)
return 1
}
return
}
// Help for sub-commands.
if err := printSubCommandUsageByName(args[0], args[1], subCommands[args[0]]); err != nil {
printGlobalUsage()
stderr("\nHelp error: %v\n", err)
return 1
@@ -151,3 +176,37 @@ func printCommandUsageByName(name string) error {
return nil
}
func printSubCommandUsage(cmdName string, subCmd *Command) {
subCommandUsageTemplate.Execute(tabOut, struct {
Executable string
CmdName string
SubCmd *Command
SubCmdFlags []*flag.Flag
}{
cliName,
cmdName,
subCmd,
getFlags(subCmd.Flags),
})
tabOut.Flush()
}
func printSubCommandUsageByName(name, subName string, subCommands []*Command) error {
var cmd *Command
for _, c := range subCommands {
if c.Name == subName {
cmd = c
break
}
}
if cmd == nil {
return fmt.Errorf("unrecognized sub-command: %s", subName)
}
printSubCommandUsage(name, cmd)
return nil
}
+65
View File
@@ -0,0 +1,65 @@
// Copyright 2015 The rkt Authors
//
// 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 (
"flag"
"os"
)
var (
cmdImage = &Command{
Name: "image",
Summary: "Operate on an image in the local store",
Usage: "SUBCOMMAND IMAGE [args...]",
Description: `SUBCOMMAND could be "cat-manifest". IMAGE should be a string referencing an image; either a hash, local file on disk, or URL.
They will be checked in that order and the first match will be used.`,
Run: runImage,
Flags: &imageFlags,
}
imageFlags flag.FlagSet
)
func init() {
commands = append(commands, cmdImage)
}
func runImage(args []string) (exit int) {
if len(args) < 1 {
printCommandUsageByName("image")
return 1
}
var subCmd *Command
subArgs := args[1:]
// determine which Command should be run
for _, c := range subCommands["image"] {
if c.Name == args[0] {
subCmd = c
if err := c.Flags.Parse(subArgs); err != nil {
stderr("%v", err)
os.Exit(2)
}
break
}
}
if subCmd == nil {
stderr("image: unknown subcommand: %q", args[0])
os.Exit(2)
}
return subCmd.Run(subArgs[subCmd.Flags.NFlag():])
}
+93
View File
@@ -0,0 +1,93 @@
// Copyright 2015 The rkt Authors
//
// 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 (
"encoding/json"
"flag"
"github.com/coreos/rkt/store"
)
var (
cmdImageCatManifest = &Command{
Name: "cat-manifest",
Summary: "Inspect and print the image manifest",
Usage: "IMAGE",
Description: `IMAGE should be a string referencing an image; either a hash, local file on disk, or URL.
They will be checked in that order and the first match will be used.`,
Run: runImageCatManifest,
Flags: &imageCatManifestFlag,
}
imageCatManifestFlag flag.FlagSet
flagPrettyPrint bool
)
func init() {
subCommands["image"] = append(subCommands["image"], cmdImageCatManifest)
imageCatManifestFlag.BoolVar(&flagPrettyPrint, "pretty-print", false, "apply indent to format the output")
}
func runImageCatManifest(args []string) (exit int) {
if len(args) != 1 {
printSubCommandUsageByName("image", "cat-manifest", subCommands["image"])
return 1
}
s, err := store.NewStore(globalFlags.Dir)
if err != nil {
stderr("image cat-manifest: cannot open store: %v\n", err)
return 1
}
ks := getKeystore()
fn := &finder{
imageActionData: imageActionData{
s: s,
ks: ks,
insecureSkipVerify: true,
debug: globalFlags.Debug,
},
local: true,
withDeps: false,
}
h, err := fn.findImage(args[0], "", true)
if err != nil {
stderr("image cat-manifest: cannot find image: %v\n", err)
return 1
}
manifest, err := fn.s.GetImageManifest(h.String())
if err != nil {
stderr("image cat-manifest: cannot get image manifest: %v\n", err)
return 1
}
var b []byte
if flagPrettyPrint {
b, err = json.MarshalIndent(manifest, "", "\t")
} else {
b, err = json.Marshal(manifest)
}
if err != nil {
stderr("image cat-manifest: cannot read the image manifest: %v\n", err)
return 1
}
stdout(string(b))
return 0
}
+1
View File
@@ -40,6 +40,7 @@ var (
globalFlagset = flag.NewFlagSet(cliName, flag.ExitOnError)
tabOut *tabwriter.Writer
commands []*Command // Commands should register themselves by appending
subCommands = make(map[string][]*Command)
globalFlags = struct {
Dir string
SystemConfigDir string