Error if unknown root level key in template [GH-180]
This commit is contained in:
parent
3b4ef72e47
commit
0e9c0edade
|
@ -5,6 +5,7 @@ import (
|
|||
"encoding/json"
|
||||
"fmt"
|
||||
"github.com/mitchellh/mapstructure"
|
||||
"sort"
|
||||
)
|
||||
|
||||
// The rawTemplate struct represents the structure of a template read
|
||||
|
@ -15,7 +16,7 @@ type rawTemplate struct {
|
|||
Builders []map[string]interface{}
|
||||
Hooks map[string][]string
|
||||
Provisioners []map[string]interface{}
|
||||
PostProcessors []interface{} `json:"post-processors"`
|
||||
PostProcessors []interface{} `mapstructure:"post-processors"`
|
||||
}
|
||||
|
||||
// The Template struct represents a parsed template, parsed into the most
|
||||
|
@ -63,8 +64,8 @@ type rawProvisionerConfig struct {
|
|||
// and checking for this can be useful, if you wish to format it in a certain
|
||||
// way.
|
||||
func ParseTemplate(data []byte) (t *Template, err error) {
|
||||
var rawTpl rawTemplate
|
||||
err = json.Unmarshal(data, &rawTpl)
|
||||
var rawTplInterface interface{}
|
||||
err = json.Unmarshal(data, &rawTplInterface)
|
||||
if err != nil {
|
||||
syntaxErr, ok := err.(*json.SyntaxError)
|
||||
if !ok {
|
||||
|
@ -92,14 +93,41 @@ func ParseTemplate(data []byte) (t *Template, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
// Decode the raw template interface into the actual rawTemplate
|
||||
// structure, checking for any extranneous keys along the way.
|
||||
var md mapstructure.Metadata
|
||||
var rawTpl rawTemplate
|
||||
decoderConfig := &mapstructure.DecoderConfig{
|
||||
Metadata: &md,
|
||||
Result: &rawTpl,
|
||||
}
|
||||
|
||||
decoder, err := mapstructure.NewDecoder(decoderConfig)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
err = decoder.Decode(rawTplInterface)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
|
||||
errors := make([]error, 0)
|
||||
|
||||
if len(md.Unused) > 0 {
|
||||
sort.Strings(md.Unused)
|
||||
for _, unused := range md.Unused {
|
||||
errors = append(
|
||||
errors, fmt.Errorf("Unknown root level key in template: '%s'", unused))
|
||||
}
|
||||
}
|
||||
|
||||
t = &Template{}
|
||||
t.Builders = make(map[string]rawBuilderConfig)
|
||||
t.Hooks = rawTpl.Hooks
|
||||
t.PostProcessors = make([][]rawPostProcessorConfig, len(rawTpl.PostProcessors))
|
||||
t.Provisioners = make([]rawProvisionerConfig, len(rawTpl.Provisioners))
|
||||
|
||||
errors := make([]error, 0)
|
||||
|
||||
// Gather all the builders
|
||||
for i, v := range rawTpl.Builders {
|
||||
var raw rawBuilderConfig
|
||||
|
@ -203,6 +231,7 @@ func ParseTemplate(data []byte) (t *Template, err error) {
|
|||
// If there were errors, we put it into a MultiError and return
|
||||
if len(errors) > 0 {
|
||||
err = &MultiError{errors}
|
||||
t = nil
|
||||
return
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,23 @@ func TestParseTemplate_Invalid(t *testing.T) {
|
|||
assert.Nil(result, "should have no result")
|
||||
}
|
||||
|
||||
func TestParseTemplate_InvalidKeys(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
// Note there is an extra comma below for a purposeful
|
||||
// syntax error in the JSON.
|
||||
data := `
|
||||
{
|
||||
"builders": [{"type": "foo"}],
|
||||
"what is this": ""
|
||||
}
|
||||
`
|
||||
|
||||
result, err := ParseTemplate([]byte(data))
|
||||
assert.NotNil(err, "should have an error")
|
||||
assert.Nil(result, "should have no result")
|
||||
}
|
||||
|
||||
func TestParseTemplate_BuilderWithoutType(t *testing.T) {
|
||||
assert := asserts.NewTestingAsserts(t, true)
|
||||
|
||||
|
|
Loading…
Reference in New Issue