command/inspect: Inspect a templates contents

This command prints out the components of a template, and most
importantly respects the machine-readable flag so that you can
programmatically inspect a template's contents without manually parsing
the JSON.
This commit is contained in:
Mitchell Hashimoto 2013-08-13 09:36:40 -07:00
parent a17c939042
commit 30f9358edc
7 changed files with 159 additions and 0 deletions

View File

@ -1,5 +1,11 @@
## 0.3.2 (unreleased)
FEATURES:
* New command: `packer inspect`. This command tells you the components of
a template. It respects the `-machine-readable` flag as well so you can
parse out components of a template.
IMPROVEMENTS:
* builder/virtualbox: Do not check for VirtualBox as part of template

118
command/inspect/command.go Normal file
View File

@ -0,0 +1,118 @@
package inspect
import (
"flag"
"fmt"
"github.com/mitchellh/packer/packer"
"log"
"sort"
"strings"
)
type Command struct{}
func (Command) Help() string {
return strings.TrimSpace(helpText)
}
func (c Command) Synopsis() string {
return "see components of a template"
}
func (c Command) Run(env packer.Environment, args []string) int {
flags := flag.NewFlagSet("inspect", flag.ContinueOnError)
flags.Usage = func() { env.Ui().Say(c.Help()) }
if err := flags.Parse(args); err != nil {
return 1
}
args = flags.Args()
if len(args) != 1 {
flags.Usage()
return 1
}
// Read the file into a byte array so that we can parse the template
log.Printf("Reading template: %s", args[0])
tpl, err := packer.ParseTemplateFile(args[0])
if err != nil {
env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
return 1
}
// Convenience...
ui := env.Ui()
// Variables
ui.Say("Variables and their defaults:\n")
if len(tpl.Variables) == 0 {
ui.Say(" <No variables>")
} else {
keys := make([]string, 0, len(tpl.Variables))
max := 0
for k, _ := range tpl.Variables {
keys = append(keys, k)
if len(k) > max {
max = len(k)
}
}
sort.Strings(keys)
for _, k := range keys {
v := tpl.Variables[k]
padding := strings.Repeat(" ", max-len(k))
output := fmt.Sprintf(" %s%s = %s", k, padding, v)
ui.Machine("template-variable", k, v)
ui.Say(output)
}
}
ui.Say("")
// Builders
ui.Say("Builders:\n")
if len(tpl.Builders) == 0 {
ui.Say(" <No builders>")
} else {
keys := make([]string, 0, len(tpl.Builders))
max := 0
for k, _ := range tpl.Builders {
keys = append(keys, k)
if len(k) > max {
max = len(k)
}
}
sort.Strings(keys)
for _, k := range keys {
v := tpl.Builders[k]
padding := strings.Repeat(" ", max-len(k))
output := fmt.Sprintf(" %s%s", k, padding)
if v.Name != v.Type {
output = fmt.Sprintf("%s (%s)", output, v.Type)
}
ui.Machine("template-build", k, v.Type)
ui.Say(output)
}
}
ui.Say("")
// Provisioners
ui.Say("Provisioners:\n")
if len(tpl.Provisioners) == 0 {
ui.Say(" <No provisioners>")
} else {
for _, v := range tpl.Provisioners {
ui.Machine("template-provisioner", v.Type)
ui.Say(fmt.Sprintf(" %s", v.Type))
}
}
return 0
}

View File

@ -0,0 +1,14 @@
package inspect
import (
"github.com/mitchellh/packer/packer"
"testing"
)
func TestCommand_Impl(t *testing.T) {
var raw interface{}
raw = new(Command)
if _, ok := raw.(packer.Command); !ok {
t.Fatalf("must be a Command")
}
}

9
command/inspect/help.go Normal file
View File

@ -0,0 +1,9 @@
package inspect
const helpText = `
Usage: packer inspect TEMPLATE
Inspects a template, parsing and outputting the components a template
defines. This does not validate the contents of a template (other than
basic syntax by necessity).
`

View File

@ -30,6 +30,7 @@ const defaultConfig = `
"commands": {
"build": "packer-command-build",
"fix": "packer-command-fix",
"inspect": "packer-command-inspect",
"validate": "packer-command-validate"
},

View File

@ -0,0 +1,10 @@
package main
import (
"github.com/mitchellh/packer/command/inspect"
"github.com/mitchellh/packer/packer/plugin"
)
func main() {
plugin.ServeCommand(new(inspect.Command))
}

View File

@ -0,0 +1 @@
package main