Commit 638e1911 authored by Mitchell Hashimoto's avatar Mitchell Hashimoto

packer: Parse provisioners out of template

parent 06b0cebd
......@@ -23,6 +23,7 @@ type Template struct {
Name string
Builders map[string]rawBuilderConfig
Hooks map[string][]string
Provisioners []rawProvisionerConfig
}
// The rawBuilderConfig struct represents a raw, unprocessed builder
......@@ -34,6 +35,14 @@ type rawBuilderConfig struct {
rawConfig interface{}
}
// rawProvisionerConfig represents a raw, unprocessed provisioner configuration.
// It contains the type of the provisioner as well as the raw configuration
// that is handed to the provisioner for it to process.
type rawProvisionerConfig struct {
pType string
rawConfig interface{}
}
// ParseTemplate takes a byte slice and parses a Template from it, returning
// the template and possibly errors while loading the template. The error
// could potentially be a MultiError, representing multiple errors. Knowing
......@@ -50,6 +59,7 @@ func ParseTemplate(data []byte) (t *Template, err error) {
t.Name = rawTpl.Name
t.Builders = make(map[string]rawBuilderConfig)
t.Hooks = rawTpl.Hooks
t.Provisioners = make([]rawProvisionerConfig, len(rawTpl.Provisioners))
errors := make([]error, 0)
......@@ -94,6 +104,26 @@ func ParseTemplate(data []byte) (t *Template, err error) {
}
}
// Gather all the provisioners
for i, v := range rawTpl.Provisioners {
rawType, ok := v["type"]
if !ok {
errors = append(errors, fmt.Errorf("provisioner %d: missing 'type'", i+1))
continue
}
typeName, ok := rawType.(string)
if !ok {
errors = append(errors, fmt.Errorf("provisioner %d: type must be a string", i+1))
continue
}
t.Provisioners[i] = rawProvisionerConfig{
typeName,
v,
}
}
// If there were errors, we put it into a MultiError and return
if len(errors) > 0 {
err = &MultiError{errors}
......
......@@ -165,6 +165,57 @@ func TestParseTemplate_Hooks(t *testing.T) {
assert.Equal(hooks, []string{"foo", "bar"}, "hooks should be correct")
}
func TestParseTemplate_ProvisionerWithoutType(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
data := `
{
"name": "my-image",
"provisioners": [{}]
}
`
_, err := ParseTemplate([]byte(data))
assert.NotNil(err, "should have error")
}
func TestParseTemplate_ProvisionerWithNonStringType(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
data := `
{
"name": "my-image",
"provisioners": [{
"type": 42
}]
}
`
_, err := ParseTemplate([]byte(data))
assert.NotNil(err, "should have error")
}
func TestParseTemplate_Provisioners(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
data := `
{
"name": "my-image",
"provisioners": [
{
"type": "shell"
}
]
}
`
result, err := ParseTemplate([]byte(data))
assert.Nil(err, "should not error")
assert.NotNil(result, "template should not be nil")
assert.Length(result.Provisioners, 1, "should have one provisioner")
assert.Equal(result.Provisioners[0].pType, "shell", "provisioner should be shell")
}
func TestTemplate_BuildNames(t *testing.T) {
assert := asserts.NewTestingAsserts(t, true)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment