github.com/richardbowden/terraform@v0.6.12-0.20160901200758-30ea22c25211/helper/schema/field_reader_config_test.go (about) 1 package schema 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/hashicorp/hil/ast" 8 "github.com/hashicorp/terraform/config" 9 "github.com/hashicorp/terraform/terraform" 10 ) 11 12 func TestConfigFieldReader_impl(t *testing.T) { 13 var _ FieldReader = new(ConfigFieldReader) 14 } 15 16 func TestConfigFieldReader(t *testing.T) { 17 testFieldReader(t, func(s map[string]*Schema) FieldReader { 18 return &ConfigFieldReader{ 19 Schema: s, 20 21 Config: testConfig(t, map[string]interface{}{ 22 "bool": true, 23 "float": 3.1415, 24 "int": 42, 25 "string": "string", 26 27 "list": []interface{}{"foo", "bar"}, 28 29 "listInt": []interface{}{21, 42}, 30 31 "map": map[string]interface{}{ 32 "foo": "bar", 33 "bar": "baz", 34 }, 35 36 "set": []interface{}{10, 50}, 37 "setDeep": []interface{}{ 38 map[string]interface{}{ 39 "index": 10, 40 "value": "foo", 41 }, 42 map[string]interface{}{ 43 "index": 50, 44 "value": "bar", 45 }, 46 }, 47 }), 48 } 49 }) 50 } 51 52 func TestConfigFieldReader_DefaultHandling(t *testing.T) { 53 schema := map[string]*Schema{ 54 "strWithDefault": &Schema{ 55 Type: TypeString, 56 Default: "ImADefault", 57 }, 58 "strWithDefaultFunc": &Schema{ 59 Type: TypeString, 60 DefaultFunc: func() (interface{}, error) { 61 return "FuncDefault", nil 62 }, 63 }, 64 } 65 66 cases := map[string]struct { 67 Addr []string 68 Result FieldReadResult 69 Config *terraform.ResourceConfig 70 Err bool 71 }{ 72 "gets default value when no config set": { 73 []string{"strWithDefault"}, 74 FieldReadResult{ 75 Value: "ImADefault", 76 Exists: true, 77 Computed: false, 78 }, 79 testConfig(t, map[string]interface{}{}), 80 false, 81 }, 82 "config overrides default value": { 83 []string{"strWithDefault"}, 84 FieldReadResult{ 85 Value: "fromConfig", 86 Exists: true, 87 Computed: false, 88 }, 89 testConfig(t, map[string]interface{}{ 90 "strWithDefault": "fromConfig", 91 }), 92 false, 93 }, 94 "gets default from function when no config set": { 95 []string{"strWithDefaultFunc"}, 96 FieldReadResult{ 97 Value: "FuncDefault", 98 Exists: true, 99 Computed: false, 100 }, 101 testConfig(t, map[string]interface{}{}), 102 false, 103 }, 104 "config overrides default function": { 105 []string{"strWithDefaultFunc"}, 106 FieldReadResult{ 107 Value: "fromConfig", 108 Exists: true, 109 Computed: false, 110 }, 111 testConfig(t, map[string]interface{}{ 112 "strWithDefaultFunc": "fromConfig", 113 }), 114 false, 115 }, 116 } 117 118 for name, tc := range cases { 119 r := &ConfigFieldReader{ 120 Schema: schema, 121 Config: tc.Config, 122 } 123 out, err := r.ReadField(tc.Addr) 124 if err != nil != tc.Err { 125 t.Fatalf("%s: err: %s", name, err) 126 } 127 if s, ok := out.Value.(*Set); ok { 128 // If it is a set, convert to a list so its more easily checked. 129 out.Value = s.List() 130 } 131 if !reflect.DeepEqual(tc.Result, out) { 132 t.Fatalf("%s: bad: %#v", name, out) 133 } 134 } 135 } 136 137 func TestConfigFieldReader_ComputedMap(t *testing.T) { 138 schema := map[string]*Schema{ 139 "map": &Schema{ 140 Type: TypeMap, 141 Computed: true, 142 }, 143 } 144 145 cases := map[string]struct { 146 Addr []string 147 Result FieldReadResult 148 Config *terraform.ResourceConfig 149 Err bool 150 }{ 151 "set, normal": { 152 []string{"map"}, 153 FieldReadResult{ 154 Value: map[string]interface{}{ 155 "foo": "bar", 156 }, 157 Exists: true, 158 Computed: false, 159 }, 160 testConfig(t, map[string]interface{}{ 161 "map": map[string]interface{}{ 162 "foo": "bar", 163 }, 164 }), 165 false, 166 }, 167 168 "computed element": { 169 []string{"map"}, 170 FieldReadResult{ 171 Exists: true, 172 Computed: true, 173 }, 174 testConfigInterpolate(t, map[string]interface{}{ 175 "map": map[string]interface{}{ 176 "foo": "${var.foo}", 177 }, 178 }, map[string]ast.Variable{ 179 "var.foo": ast.Variable{ 180 Value: config.UnknownVariableValue, 181 Type: ast.TypeString, 182 }, 183 }), 184 false, 185 }, 186 187 "native map": { 188 []string{"map"}, 189 FieldReadResult{ 190 Value: map[string]interface{}{ 191 "bar": "baz", 192 "baz": "bar", 193 }, 194 Exists: true, 195 Computed: false, 196 }, 197 testConfigInterpolate(t, map[string]interface{}{ 198 "map": "${var.foo}", 199 }, map[string]ast.Variable{ 200 "var.foo": ast.Variable{ 201 Type: ast.TypeMap, 202 Value: map[string]ast.Variable{ 203 "bar": ast.Variable{ 204 Type: ast.TypeString, 205 Value: "baz", 206 }, 207 "baz": ast.Variable{ 208 Type: ast.TypeString, 209 Value: "bar", 210 }, 211 }, 212 }, 213 }), 214 false, 215 }, 216 } 217 218 for name, tc := range cases { 219 r := &ConfigFieldReader{ 220 Schema: schema, 221 Config: tc.Config, 222 } 223 out, err := r.ReadField(tc.Addr) 224 if err != nil != tc.Err { 225 t.Fatalf("%s: err: %s", name, err) 226 } 227 if s, ok := out.Value.(*Set); ok { 228 // If it is a set, convert to the raw map 229 out.Value = s.m 230 if len(s.m) == 0 { 231 out.Value = nil 232 } 233 } 234 if !reflect.DeepEqual(tc.Result, out) { 235 t.Fatalf("%s: bad: %#v", name, out) 236 } 237 } 238 } 239 240 func TestConfigFieldReader_ComputedSet(t *testing.T) { 241 schema := map[string]*Schema{ 242 "strSet": &Schema{ 243 Type: TypeSet, 244 Elem: &Schema{Type: TypeString}, 245 Set: HashString, 246 }, 247 } 248 249 cases := map[string]struct { 250 Addr []string 251 Result FieldReadResult 252 Config *terraform.ResourceConfig 253 Err bool 254 }{ 255 "set, normal": { 256 []string{"strSet"}, 257 FieldReadResult{ 258 Value: map[string]interface{}{ 259 "2356372769": "foo", 260 }, 261 Exists: true, 262 Computed: false, 263 }, 264 testConfig(t, map[string]interface{}{ 265 "strSet": []interface{}{"foo"}, 266 }), 267 false, 268 }, 269 270 "set, computed element": { 271 []string{"strSet"}, 272 FieldReadResult{ 273 Value: nil, 274 Exists: true, 275 Computed: true, 276 }, 277 testConfigInterpolate(t, map[string]interface{}{ 278 "strSet": []interface{}{"${var.foo}"}, 279 }, map[string]ast.Variable{ 280 "var.foo": ast.Variable{ 281 Value: config.UnknownVariableValue, 282 Type: ast.TypeString, 283 }, 284 }), 285 false, 286 }, 287 288 "set, computed element substring": { 289 []string{"strSet"}, 290 FieldReadResult{ 291 Value: nil, 292 Exists: true, 293 Computed: true, 294 }, 295 testConfigInterpolate(t, map[string]interface{}{ 296 "strSet": []interface{}{"${var.foo}/32"}, 297 }, map[string]ast.Variable{ 298 "var.foo": ast.Variable{ 299 Value: config.UnknownVariableValue, 300 Type: ast.TypeString, 301 }, 302 }), 303 false, 304 }, 305 } 306 307 for name, tc := range cases { 308 r := &ConfigFieldReader{ 309 Schema: schema, 310 Config: tc.Config, 311 } 312 out, err := r.ReadField(tc.Addr) 313 if err != nil != tc.Err { 314 t.Fatalf("%s: err: %s", name, err) 315 } 316 if s, ok := out.Value.(*Set); ok { 317 // If it is a set, convert to the raw map 318 out.Value = s.m 319 if len(s.m) == 0 { 320 out.Value = nil 321 } 322 } 323 if !reflect.DeepEqual(tc.Result, out) { 324 t.Fatalf("%s: bad: %#v", name, out) 325 } 326 } 327 } 328 329 func testConfig( 330 t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig { 331 return testConfigInterpolate(t, raw, nil) 332 } 333 334 func testConfigInterpolate( 335 t *testing.T, 336 raw map[string]interface{}, 337 vs map[string]ast.Variable) *terraform.ResourceConfig { 338 339 rc, err := config.NewRawConfig(raw) 340 if err != nil { 341 t.Fatalf("err: %s", err) 342 } 343 if len(vs) > 0 { 344 if err := rc.Interpolate(vs); err != nil { 345 t.Fatalf("err: %s", err) 346 } 347 } 348 349 return terraform.NewResourceConfig(rc) 350 }