Get rid of the list when parsing HCL maps for vars

When we parse a map from HCL, it's decoded into a list of maps because
HCL allows declaring a key multiple times to implicitly add it to a
list.  Since there's no terraform variable configuration that supports
this structure, we can always flatten a []map[string]interface{} value
to a map[string]interface{} and remove any type rrors trying to apply
that value.
This commit is contained in:
James Bardin 2016-10-06 19:40:04 -04:00
parent 3e3854ed65
commit 9fc50a76c3
2 changed files with 51 additions and 10 deletions

View File

@ -111,6 +111,10 @@ func loadKVFile(rawPath string) (map[string]interface{}, error) {
"Decoding errors are usually caused by an invalid format.",
err)
}
err = flattenMultiMaps(result)
if err != nil {
return nil, err
}
return result, nil
}
@ -185,10 +189,34 @@ func parseVarFlagAsHCL(input string) (string, interface{}, error) {
return "", nil, fmt.Errorf("Cannot parse value for variable %s (%q) as valid HCL. Only one value may be specified.", probablyName, input)
}
for k, v := range decoded {
return k, v, nil
err = flattenMultiMaps(decoded)
if err != nil {
return probablyName, "", err
}
// Should be unreachable
return "", nil, fmt.Errorf("No value for variable: %s", input)
var k string
var v interface{}
for k, v = range decoded {
break
}
return k, v, nil
}
// Variables don't support any type that can be configured via multiple
// declarations of the same HCL map, so any instances of
// []map[string]interface{} are either a single map that can be flattened, or
// are invalid config.
func flattenMultiMaps(m map[string]interface{}) error {
for k, v := range m {
switch v := v.(type) {
case []map[string]interface{}:
switch {
case len(v) > 1:
return fmt.Errorf("multiple map declarations not supported for variables")
case len(v) == 1:
m[k] = v[0]
}
}
}
return nil
}

View File

@ -2,10 +2,11 @@ package command
import (
"flag"
"github.com/davecgh/go-spew/spew"
"io/ioutil"
"reflect"
"testing"
"github.com/davecgh/go-spew/spew"
)
func TestFlagStringKV_impl(t *testing.T) {
@ -118,11 +119,9 @@ func TestFlagTypedKV(t *testing.T) {
{
`key={"hello" = "world", "foo" = "bar"}`,
map[string]interface{}{
"key": []map[string]interface{}{
map[string]interface{}{
"hello": "world",
"foo": "bar",
},
"key": map[string]interface{}{
"hello": "world",
"foo": "bar",
},
},
false,
@ -169,6 +168,10 @@ func TestFlagKVFile(t *testing.T) {
inputLibucl := `
foo = "bar"
`
inputMap := `
foo = {
k = "v"
}`
inputJson := `{
"foo": "bar"}`
@ -195,6 +198,16 @@ foo = "bar"
map[string]interface{}{"map.key": "foo"},
false,
},
{
inputMap,
map[string]interface{}{
"foo": map[string]interface{}{
"k": "v",
},
},
false,
},
}
path := testTempFile(t)