Check for multi-values maps in output too

A map value read from a config file will be the default
`[]map[string]interface{}` type decoded from HCL. Since this type can't
be applied to a variable, it's likely that it was a simple map. If
there's a single map value, we can pull that out of the slice during
Eval.
This commit is contained in:
James Bardin 2016-10-07 15:00:50 -04:00
parent 9fc50a76c3
commit 48c8afaa11
2 changed files with 69 additions and 0 deletions

View File

@ -98,6 +98,19 @@ func (n *EvalWriteOutput) Eval(ctx EvalContext) (interface{}, error) {
Sensitive: n.Sensitive,
Value: valueTyped,
}
case []map[string]interface{}:
// an HCL map is multi-valued, so if this was read out of a config the
// map may still be in a slice.
if len(valueTyped) == 1 {
mod.Outputs[n.Name] = &OutputState{
Type: "map",
Sensitive: n.Sensitive,
Value: valueTyped[0],
}
break
}
return nil, fmt.Errorf("output %s type (%T) with %d values not valid for type map",
n.Name, valueTyped, len(valueTyped))
default:
return nil, fmt.Errorf("output %s is not a valid type (%T)\n", n.Name, valueTyped)
}

View File

@ -0,0 +1,56 @@
package terraform
import (
"sync"
"testing"
)
func TestEvalWriteMapOutput(t *testing.T) {
ctx := new(MockEvalContext)
ctx.StateState = NewState()
ctx.StateLock = new(sync.RWMutex)
cases := []struct {
name string
cfg *ResourceConfig
err bool
}{
{
// Eval should recognize a single map in a slice, and collapse it
// into the map value
"single-map",
&ResourceConfig{
Config: map[string]interface{}{
"value": []map[string]interface{}{
map[string]interface{}{"a": "b"},
},
},
},
false,
},
{
// we can't apply a multi-valued map to a variable, so this should error
"multi-map",
&ResourceConfig{
Config: map[string]interface{}{
"value": []map[string]interface{}{
map[string]interface{}{"a": "b"},
map[string]interface{}{"c": "d"},
},
},
},
true,
},
}
for _, tc := range cases {
evalNode := &EvalWriteOutput{Name: tc.name}
ctx.InterpolateConfigResult = tc.cfg
t.Run(tc.name, func(t *testing.T) {
_, err := evalNode.Eval(ctx)
if err != nil && !tc.err {
t.Fatal(err)
}
})
}
}