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:
parent
3e3854ed65
commit
9fc50a76c3
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
|
|
Loading…
Reference in New Issue