diff --git a/terraform/eval_variable.go b/terraform/eval_variable.go index 47bd2ea2b67f..b39a4d198fc9 100644 --- a/terraform/eval_variable.go +++ b/terraform/eval_variable.go @@ -114,7 +114,6 @@ type EvalVariableBlock struct { VariableValues map[string]interface{} } -// TODO: test func (n *EvalVariableBlock) Eval(ctx EvalContext) (interface{}, error) { // Clear out the existing mapping for k, _ := range n.VariableValues { @@ -174,9 +173,15 @@ func (n *EvalVariableBlock) setUnknownVariableValueForPath(path string) error { // Otherwise find the correct point in the tree and then set to unknown var current interface{} = n.VariableValues[pathComponents[0]] for i := 1; i < len(pathComponents); i++ { - switch current.(type) { - case []interface{}, []map[string]interface{}: - tCurrent := current.([]interface{}) + switch tCurrent := current.(type) { + case []interface{}: + index, err := strconv.Atoi(pathComponents[i]) + if err != nil { + return fmt.Errorf("Cannot convert %s to slice index in path %s", + pathComponents[i], path) + } + current = tCurrent[index] + case []map[string]interface{}: index, err := strconv.Atoi(pathComponents[i]) if err != nil { return fmt.Errorf("Cannot convert %s to slice index in path %s", @@ -184,7 +189,6 @@ func (n *EvalVariableBlock) setUnknownVariableValueForPath(path string) error { } current = tCurrent[index] case map[string]interface{}: - tCurrent := current.(map[string]interface{}) if val, hasVal := tCurrent[pathComponents[i]]; hasVal { current = val continue diff --git a/terraform/eval_variable_test.go b/terraform/eval_variable_test.go index 05fc2b850cd9..eb7ff92a3116 100644 --- a/terraform/eval_variable_test.go +++ b/terraform/eval_variable_test.go @@ -3,6 +3,8 @@ package terraform import ( "reflect" "testing" + + "github.com/hashicorp/terraform/config" ) func TestCoerceMapVariable(t *testing.T) { @@ -140,3 +142,78 @@ func TestCoerceMapVariable(t *testing.T) { } } } + +func TestEvalVariableBlock(t *testing.T) { + rc, err := config.NewRawConfig(map[string]interface{}{ + "known": "foo", + "known_list": []interface{}{"foo"}, + "known_map": map[string]interface{}{ + "foo": "foo", + }, + "known_list_of_maps": []map[string]interface{}{ + map[string]interface{}{ + "foo": "foo", + }, + }, + "computed_map": map[string]interface{}{}, + "computed_list_of_maps": []map[string]interface{}{ + map[string]interface{}{}, + }, + // No computed_list right now, because that isn't currently supported: + // EvalVariableBlock assumes the final step of the path will always + // be a map. + }) + if err != nil { + t.Fatalf("config.NewRawConfig failed: %s", err) + } + + cfg := NewResourceConfig(rc) + cfg.ComputedKeys = []string{ + "computed", + "computed_map.foo", + "computed_list_of_maps.0.foo", + } + + n := &EvalVariableBlock{ + VariableValues: map[string]interface{}{ + // Should be cleared out on Eval + "should_be_deleted": true, + }, + Config: &cfg, + } + + ctx := &MockEvalContext{} + val, err := n.Eval(ctx) + if err != nil { + t.Fatalf("n.Eval failed: %s", err) + } + if val != nil { + t.Fatalf("n.Eval returned non-nil result: %#v", val) + } + + got := n.VariableValues + want := map[string]interface{}{ + "known": "foo", + "known_list": []interface{}{"foo"}, + "known_map": map[string]interface{}{ + "foo": "foo", + }, + "known_list_of_maps": []interface{}{ + map[string]interface{}{ + "foo": "foo", + }, + }, + "computed": config.UnknownVariableValue, + "computed_map": map[string]interface{}{ + "foo": config.UnknownVariableValue, + }, + "computed_list_of_maps": []interface{}{ + map[string]interface{}{ + "foo": config.UnknownVariableValue, + }, + }, + } + if !reflect.DeepEqual(got, want) { + t.Errorf("Incorrect variables\ngot: %#v\nwant: %#v", got, want) + } +}