Skip to content

Commit 6eceacf

Browse files
committed
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.
1 parent e22eb3a commit 6eceacf

File tree

7 files changed

+159
-0
lines changed

7 files changed

+159
-0
lines changed

CHANGELOG.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,11 @@
11
## 0.3.2 (unreleased)
22

3+
FEATURES:
4+
5+
* New command: `packer inspect`. This command tells you the components of
6+
a template. It respects the `-machine-readable` flag as well so you can
7+
parse out components of a template.
8+
39
IMPROVEMENTS:
410

511
* builder/virtualbox: Do not check for VirtualBox as part of template

command/inspect/command.go

Lines changed: 118 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,118 @@
1+
package inspect
2+
3+
import (
4+
"flag"
5+
"fmt"
6+
"github.com/mitchellh/packer/packer"
7+
"log"
8+
"sort"
9+
"strings"
10+
)
11+
12+
type Command struct{}
13+
14+
func (Command) Help() string {
15+
return strings.TrimSpace(helpText)
16+
}
17+
18+
func (c Command) Synopsis() string {
19+
return "see components of a template"
20+
}
21+
22+
func (c Command) Run(env packer.Environment, args []string) int {
23+
flags := flag.NewFlagSet("inspect", flag.ContinueOnError)
24+
flags.Usage = func() { env.Ui().Say(c.Help()) }
25+
if err := flags.Parse(args); err != nil {
26+
return 1
27+
}
28+
29+
args = flags.Args()
30+
if len(args) != 1 {
31+
flags.Usage()
32+
return 1
33+
}
34+
35+
// Read the file into a byte array so that we can parse the template
36+
log.Printf("Reading template: %s", args[0])
37+
tpl, err := packer.ParseTemplateFile(args[0])
38+
if err != nil {
39+
env.Ui().Error(fmt.Sprintf("Failed to parse template: %s", err))
40+
return 1
41+
}
42+
43+
// Convenience...
44+
ui := env.Ui()
45+
46+
// Variables
47+
ui.Say("Variables and their defaults:\n")
48+
if len(tpl.Variables) == 0 {
49+
ui.Say(" <No variables>")
50+
} else {
51+
keys := make([]string, 0, len(tpl.Variables))
52+
max := 0
53+
for k, _ := range tpl.Variables {
54+
keys = append(keys, k)
55+
if len(k) > max {
56+
max = len(k)
57+
}
58+
}
59+
60+
sort.Strings(keys)
61+
62+
for _, k := range keys {
63+
v := tpl.Variables[k]
64+
padding := strings.Repeat(" ", max-len(k))
65+
output := fmt.Sprintf(" %s%s = %s", k, padding, v)
66+
67+
ui.Machine("template-variable", k, v)
68+
ui.Say(output)
69+
}
70+
}
71+
72+
ui.Say("")
73+
74+
// Builders
75+
ui.Say("Builders:\n")
76+
if len(tpl.Builders) == 0 {
77+
ui.Say(" <No builders>")
78+
} else {
79+
keys := make([]string, 0, len(tpl.Builders))
80+
max := 0
81+
for k, _ := range tpl.Builders {
82+
keys = append(keys, k)
83+
if len(k) > max {
84+
max = len(k)
85+
}
86+
}
87+
88+
sort.Strings(keys)
89+
90+
for _, k := range keys {
91+
v := tpl.Builders[k]
92+
padding := strings.Repeat(" ", max-len(k))
93+
output := fmt.Sprintf(" %s%s", k, padding)
94+
if v.Name != v.Type {
95+
output = fmt.Sprintf("%s (%s)", output, v.Type)
96+
}
97+
98+
ui.Machine("template-build", k, v.Type)
99+
ui.Say(output)
100+
101+
}
102+
}
103+
104+
ui.Say("")
105+
106+
// Provisioners
107+
ui.Say("Provisioners:\n")
108+
if len(tpl.Provisioners) == 0 {
109+
ui.Say(" <No provisioners>")
110+
} else {
111+
for _, v := range tpl.Provisioners {
112+
ui.Machine("template-provisioner", v.Type)
113+
ui.Say(fmt.Sprintf(" %s", v.Type))
114+
}
115+
}
116+
117+
return 0
118+
}

command/inspect/command_test.go

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
package inspect
2+
3+
import (
4+
"github.com/mitchellh/packer/packer"
5+
"testing"
6+
)
7+
8+
func TestCommand_Impl(t *testing.T) {
9+
var raw interface{}
10+
raw = new(Command)
11+
if _, ok := raw.(packer.Command); !ok {
12+
t.Fatalf("must be a Command")
13+
}
14+
}

command/inspect/help.go

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
package inspect
2+
3+
const helpText = `
4+
Usage: packer inspect TEMPLATE
5+
6+
Inspects a template, parsing and outputting the components a template
7+
defines. This does not validate the contents of a template (other than
8+
basic syntax by necessity).
9+
`

config.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ const defaultConfig = `
3030
"commands": {
3131
"build": "packer-command-build",
3232
"fix": "packer-command-fix",
33+
"inspect": "packer-command-inspect",
3334
"validate": "packer-command-validate"
3435
},
3536

plugin/command-inspect/main.go

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package main
2+
3+
import (
4+
"github.com/mitchellh/packer/command/inspect"
5+
"github.com/mitchellh/packer/packer/plugin"
6+
)
7+
8+
func main() {
9+
plugin.ServeCommand(new(inspect.Command))
10+
}

plugin/command-inspect/main_test.go

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
package main

0 commit comments

Comments
 (0)