github.com/wikibal01/hashicorp-terraform@v0.11.12-beta1/terraform/eval_variable_test.go (about) 1 package terraform 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/hashicorp/terraform/config" 8 ) 9 10 func TestCoerceMapVariable(t *testing.T) { 11 cases := map[string]struct { 12 Input *EvalCoerceMapVariable 13 ExpectVars map[string]interface{} 14 }{ 15 "a valid map is untouched": { 16 Input: &EvalCoerceMapVariable{ 17 Variables: map[string]interface{}{ 18 "amap": map[string]interface{}{"foo": "bar"}, 19 }, 20 ModulePath: []string{"root"}, 21 ModuleTree: testModuleInline(t, map[string]string{ 22 "main.tf": ` 23 variable "amap" { 24 type = "map" 25 } 26 `, 27 }), 28 }, 29 ExpectVars: map[string]interface{}{ 30 "amap": map[string]interface{}{"foo": "bar"}, 31 }, 32 }, 33 "a list w/ a single map element is coerced": { 34 Input: &EvalCoerceMapVariable{ 35 Variables: map[string]interface{}{ 36 "amap": []interface{}{ 37 map[string]interface{}{"foo": "bar"}, 38 }, 39 }, 40 ModulePath: []string{"root"}, 41 ModuleTree: testModuleInline(t, map[string]string{ 42 "main.tf": ` 43 variable "amap" { 44 type = "map" 45 } 46 `, 47 }), 48 }, 49 ExpectVars: map[string]interface{}{ 50 "amap": map[string]interface{}{"foo": "bar"}, 51 }, 52 }, 53 "a list w/ more than one map element is untouched": { 54 Input: &EvalCoerceMapVariable{ 55 Variables: map[string]interface{}{ 56 "amap": []interface{}{ 57 map[string]interface{}{"foo": "bar"}, 58 map[string]interface{}{"baz": "qux"}, 59 }, 60 }, 61 ModulePath: []string{"root"}, 62 ModuleTree: testModuleInline(t, map[string]string{ 63 "main.tf": ` 64 variable "amap" { 65 type = "map" 66 } 67 `, 68 }), 69 }, 70 ExpectVars: map[string]interface{}{ 71 "amap": []interface{}{ 72 map[string]interface{}{"foo": "bar"}, 73 map[string]interface{}{"baz": "qux"}, 74 }, 75 }, 76 }, 77 "list coercion also works in a module": { 78 Input: &EvalCoerceMapVariable{ 79 Variables: map[string]interface{}{ 80 "amap": []interface{}{ 81 map[string]interface{}{"foo": "bar"}, 82 }, 83 }, 84 ModulePath: []string{"root", "middle", "bottom"}, 85 ModuleTree: testModuleInline(t, map[string]string{ 86 "top.tf": ` 87 module "middle" { 88 source = "./middle" 89 } 90 `, 91 "middle/mid.tf": ` 92 module "bottom" { 93 source = "./bottom" 94 amap { 95 foo = "bar" 96 } 97 } 98 `, 99 "middle/bottom/bot.tf": ` 100 variable "amap" { 101 type = "map" 102 } 103 `, 104 }), 105 }, 106 ExpectVars: map[string]interface{}{ 107 "amap": map[string]interface{}{"foo": "bar"}, 108 }, 109 }, 110 "coercion only occurs when target var is a map": { 111 Input: &EvalCoerceMapVariable{ 112 Variables: map[string]interface{}{ 113 "alist": []interface{}{ 114 map[string]interface{}{"foo": "bar"}, 115 }, 116 }, 117 ModulePath: []string{"root"}, 118 ModuleTree: testModuleInline(t, map[string]string{ 119 "main.tf": ` 120 variable "alist" { 121 type = "list" 122 } 123 `, 124 }), 125 }, 126 ExpectVars: map[string]interface{}{ 127 "alist": []interface{}{ 128 map[string]interface{}{"foo": "bar"}, 129 }, 130 }, 131 }, 132 } 133 134 for tn, tc := range cases { 135 _, err := tc.Input.Eval(&MockEvalContext{}) 136 if err != nil { 137 t.Fatalf("%s: Unexpected err: %s", tn, err) 138 } 139 if !reflect.DeepEqual(tc.Input.Variables, tc.ExpectVars) { 140 t.Fatalf("%s: Expected variables:\n\n%#v\n\nGot:\n\n%#v", 141 tn, tc.ExpectVars, tc.Input.Variables) 142 } 143 } 144 } 145 146 func TestEvalVariableBlock(t *testing.T) { 147 rc, err := config.NewRawConfig(map[string]interface{}{ 148 "known": "foo", 149 "known_list": []interface{}{"foo"}, 150 "known_map": map[string]interface{}{ 151 "foo": "foo", 152 }, 153 "known_list_of_maps": []map[string]interface{}{ 154 map[string]interface{}{ 155 "foo": "foo", 156 }, 157 }, 158 "computed_map": map[string]interface{}{}, 159 "computed_list_of_maps": []map[string]interface{}{ 160 map[string]interface{}{}, 161 }, 162 // No computed_list right now, because that isn't currently supported: 163 // EvalVariableBlock assumes the final step of the path will always 164 // be a map. 165 }) 166 if err != nil { 167 t.Fatalf("config.NewRawConfig failed: %s", err) 168 } 169 170 cfg := NewResourceConfig(rc) 171 cfg.ComputedKeys = []string{ 172 "computed", 173 "computed_map.foo", 174 "computed_list_of_maps.0.foo", 175 } 176 177 n := &EvalVariableBlock{ 178 VariableValues: map[string]interface{}{ 179 // Should be cleared out on Eval 180 "should_be_deleted": true, 181 }, 182 Config: &cfg, 183 } 184 185 ctx := &MockEvalContext{} 186 val, err := n.Eval(ctx) 187 if err != nil { 188 t.Fatalf("n.Eval failed: %s", err) 189 } 190 if val != nil { 191 t.Fatalf("n.Eval returned non-nil result: %#v", val) 192 } 193 194 got := n.VariableValues 195 want := map[string]interface{}{ 196 "known": "foo", 197 "known_list": []interface{}{"foo"}, 198 "known_map": map[string]interface{}{ 199 "foo": "foo", 200 }, 201 "known_list_of_maps": []interface{}{ 202 map[string]interface{}{ 203 "foo": "foo", 204 }, 205 }, 206 "computed": config.UnknownVariableValue, 207 "computed_map": map[string]interface{}{ 208 "foo": config.UnknownVariableValue, 209 }, 210 "computed_list_of_maps": []interface{}{ 211 map[string]interface{}{ 212 "foo": config.UnknownVariableValue, 213 }, 214 }, 215 } 216 if !reflect.DeepEqual(got, want) { 217 t.Errorf("Incorrect variables\ngot: %#v\nwant: %#v", got, want) 218 } 219 }