github.com/bpineau/terraform@v0.8.0-rc1.0.20161126184705-a8886012d185/helper/schema/field_reader_config_test.go (about) 1 package schema 2 3 import ( 4 "bytes" 5 "fmt" 6 "reflect" 7 "testing" 8 9 "github.com/hashicorp/hil/ast" 10 "github.com/hashicorp/terraform/config" 11 "github.com/hashicorp/terraform/helper/hashcode" 12 "github.com/hashicorp/terraform/terraform" 13 ) 14 15 func TestConfigFieldReader_impl(t *testing.T) { 16 var _ FieldReader = new(ConfigFieldReader) 17 } 18 19 func TestConfigFieldReader(t *testing.T) { 20 testFieldReader(t, func(s map[string]*Schema) FieldReader { 21 return &ConfigFieldReader{ 22 Schema: s, 23 24 Config: testConfig(t, map[string]interface{}{ 25 "bool": true, 26 "float": 3.1415, 27 "int": 42, 28 "string": "string", 29 30 "list": []interface{}{"foo", "bar"}, 31 32 "listInt": []interface{}{21, 42}, 33 34 "map": map[string]interface{}{ 35 "foo": "bar", 36 "bar": "baz", 37 }, 38 "mapInt": map[string]interface{}{ 39 "one": "1", 40 "two": "2", 41 }, 42 "mapFloat": map[string]interface{}{ 43 "oneDotTwo": "1.2", 44 }, 45 "mapBool": map[string]interface{}{ 46 "True": "true", 47 "False": "false", 48 }, 49 50 "set": []interface{}{10, 50}, 51 "setDeep": []interface{}{ 52 map[string]interface{}{ 53 "index": 10, 54 "value": "foo", 55 }, 56 map[string]interface{}{ 57 "index": 50, 58 "value": "bar", 59 }, 60 }, 61 }), 62 } 63 }) 64 } 65 66 // This contains custom table tests for our ConfigFieldReader 67 func TestConfigFieldReader_custom(t *testing.T) { 68 schema := map[string]*Schema{ 69 "bool": &Schema{ 70 Type: TypeBool, 71 }, 72 } 73 74 cases := map[string]struct { 75 Addr []string 76 Result FieldReadResult 77 Config *terraform.ResourceConfig 78 Err bool 79 }{ 80 "basic": { 81 []string{"bool"}, 82 FieldReadResult{ 83 Value: true, 84 Exists: true, 85 }, 86 testConfig(t, map[string]interface{}{ 87 "bool": true, 88 }), 89 false, 90 }, 91 92 "computed": { 93 []string{"bool"}, 94 FieldReadResult{ 95 Exists: true, 96 Computed: true, 97 }, 98 testConfigInterpolate(t, map[string]interface{}{ 99 "bool": "${var.foo}", 100 }, map[string]ast.Variable{ 101 "var.foo": ast.Variable{ 102 Value: config.UnknownVariableValue, 103 Type: ast.TypeString, 104 }, 105 }), 106 false, 107 }, 108 } 109 110 for name, tc := range cases { 111 t.Run(name, func(t *testing.T) { 112 r := &ConfigFieldReader{ 113 Schema: schema, 114 Config: tc.Config, 115 } 116 out, err := r.ReadField(tc.Addr) 117 if err != nil != tc.Err { 118 t.Fatalf("%s: err: %s", name, err) 119 } 120 if s, ok := out.Value.(*Set); ok { 121 // If it is a set, convert to a list so its more easily checked. 122 out.Value = s.List() 123 } 124 if !reflect.DeepEqual(tc.Result, out) { 125 t.Fatalf("%s: bad: %#v", name, out) 126 } 127 }) 128 } 129 } 130 131 func TestConfigFieldReader_DefaultHandling(t *testing.T) { 132 schema := map[string]*Schema{ 133 "strWithDefault": &Schema{ 134 Type: TypeString, 135 Default: "ImADefault", 136 }, 137 "strWithDefaultFunc": &Schema{ 138 Type: TypeString, 139 DefaultFunc: func() (interface{}, error) { 140 return "FuncDefault", nil 141 }, 142 }, 143 } 144 145 cases := map[string]struct { 146 Addr []string 147 Result FieldReadResult 148 Config *terraform.ResourceConfig 149 Err bool 150 }{ 151 "gets default value when no config set": { 152 []string{"strWithDefault"}, 153 FieldReadResult{ 154 Value: "ImADefault", 155 Exists: true, 156 Computed: false, 157 }, 158 testConfig(t, map[string]interface{}{}), 159 false, 160 }, 161 "config overrides default value": { 162 []string{"strWithDefault"}, 163 FieldReadResult{ 164 Value: "fromConfig", 165 Exists: true, 166 Computed: false, 167 }, 168 testConfig(t, map[string]interface{}{ 169 "strWithDefault": "fromConfig", 170 }), 171 false, 172 }, 173 "gets default from function when no config set": { 174 []string{"strWithDefaultFunc"}, 175 FieldReadResult{ 176 Value: "FuncDefault", 177 Exists: true, 178 Computed: false, 179 }, 180 testConfig(t, map[string]interface{}{}), 181 false, 182 }, 183 "config overrides default function": { 184 []string{"strWithDefaultFunc"}, 185 FieldReadResult{ 186 Value: "fromConfig", 187 Exists: true, 188 Computed: false, 189 }, 190 testConfig(t, map[string]interface{}{ 191 "strWithDefaultFunc": "fromConfig", 192 }), 193 false, 194 }, 195 } 196 197 for name, tc := range cases { 198 r := &ConfigFieldReader{ 199 Schema: schema, 200 Config: tc.Config, 201 } 202 out, err := r.ReadField(tc.Addr) 203 if err != nil != tc.Err { 204 t.Fatalf("%s: err: %s", name, err) 205 } 206 if s, ok := out.Value.(*Set); ok { 207 // If it is a set, convert to a list so its more easily checked. 208 out.Value = s.List() 209 } 210 if !reflect.DeepEqual(tc.Result, out) { 211 t.Fatalf("%s: bad: %#v", name, out) 212 } 213 } 214 } 215 216 func TestConfigFieldReader_ComputedMap(t *testing.T) { 217 schema := map[string]*Schema{ 218 "map": &Schema{ 219 Type: TypeMap, 220 Computed: true, 221 }, 222 } 223 224 cases := map[string]struct { 225 Addr []string 226 Result FieldReadResult 227 Config *terraform.ResourceConfig 228 Err bool 229 }{ 230 "set, normal": { 231 []string{"map"}, 232 FieldReadResult{ 233 Value: map[string]interface{}{ 234 "foo": "bar", 235 }, 236 Exists: true, 237 Computed: false, 238 }, 239 testConfig(t, map[string]interface{}{ 240 "map": map[string]interface{}{ 241 "foo": "bar", 242 }, 243 }), 244 false, 245 }, 246 247 "computed element": { 248 []string{"map"}, 249 FieldReadResult{ 250 Exists: true, 251 Computed: true, 252 }, 253 testConfigInterpolate(t, map[string]interface{}{ 254 "map": map[string]interface{}{ 255 "foo": "${var.foo}", 256 }, 257 }, map[string]ast.Variable{ 258 "var.foo": ast.Variable{ 259 Value: config.UnknownVariableValue, 260 Type: ast.TypeString, 261 }, 262 }), 263 false, 264 }, 265 266 "native map": { 267 []string{"map"}, 268 FieldReadResult{ 269 Value: map[string]interface{}{ 270 "bar": "baz", 271 "baz": "bar", 272 }, 273 Exists: true, 274 Computed: false, 275 }, 276 testConfigInterpolate(t, map[string]interface{}{ 277 "map": "${var.foo}", 278 }, map[string]ast.Variable{ 279 "var.foo": ast.Variable{ 280 Type: ast.TypeMap, 281 Value: map[string]ast.Variable{ 282 "bar": ast.Variable{ 283 Type: ast.TypeString, 284 Value: "baz", 285 }, 286 "baz": ast.Variable{ 287 Type: ast.TypeString, 288 Value: "bar", 289 }, 290 }, 291 }, 292 }), 293 false, 294 }, 295 } 296 297 for name, tc := range cases { 298 r := &ConfigFieldReader{ 299 Schema: schema, 300 Config: tc.Config, 301 } 302 out, err := r.ReadField(tc.Addr) 303 if err != nil != tc.Err { 304 t.Fatalf("%s: err: %s", name, err) 305 } 306 if s, ok := out.Value.(*Set); ok { 307 // If it is a set, convert to the raw map 308 out.Value = s.m 309 if len(s.m) == 0 { 310 out.Value = nil 311 } 312 } 313 if !reflect.DeepEqual(tc.Result, out) { 314 t.Fatalf("%s: bad: %#v", name, out) 315 } 316 } 317 } 318 319 func TestConfigFieldReader_ComputedSet(t *testing.T) { 320 schema := map[string]*Schema{ 321 "strSet": &Schema{ 322 Type: TypeSet, 323 Elem: &Schema{Type: TypeString}, 324 Set: HashString, 325 }, 326 } 327 328 cases := map[string]struct { 329 Addr []string 330 Result FieldReadResult 331 Config *terraform.ResourceConfig 332 Err bool 333 }{ 334 "set, normal": { 335 []string{"strSet"}, 336 FieldReadResult{ 337 Value: map[string]interface{}{ 338 "2356372769": "foo", 339 }, 340 Exists: true, 341 Computed: false, 342 }, 343 testConfig(t, map[string]interface{}{ 344 "strSet": []interface{}{"foo"}, 345 }), 346 false, 347 }, 348 349 "set, computed element": { 350 []string{"strSet"}, 351 FieldReadResult{ 352 Value: nil, 353 Exists: true, 354 Computed: true, 355 }, 356 testConfigInterpolate(t, map[string]interface{}{ 357 "strSet": []interface{}{"${var.foo}"}, 358 }, map[string]ast.Variable{ 359 "var.foo": ast.Variable{ 360 Value: config.UnknownVariableValue, 361 Type: ast.TypeUnknown, 362 }, 363 }), 364 false, 365 }, 366 367 "set, computed element substring": { 368 []string{"strSet"}, 369 FieldReadResult{ 370 Value: nil, 371 Exists: true, 372 Computed: true, 373 }, 374 testConfigInterpolate(t, map[string]interface{}{ 375 "strSet": []interface{}{"${var.foo}/32"}, 376 }, map[string]ast.Variable{ 377 "var.foo": ast.Variable{ 378 Value: config.UnknownVariableValue, 379 Type: ast.TypeUnknown, 380 }, 381 }), 382 false, 383 }, 384 } 385 386 for name, tc := range cases { 387 r := &ConfigFieldReader{ 388 Schema: schema, 389 Config: tc.Config, 390 } 391 out, err := r.ReadField(tc.Addr) 392 if err != nil != tc.Err { 393 t.Fatalf("%s: err: %s", name, err) 394 } 395 if s, ok := out.Value.(*Set); ok { 396 // If it is a set, convert to the raw map 397 out.Value = s.m 398 if len(s.m) == 0 { 399 out.Value = nil 400 } 401 } 402 if !reflect.DeepEqual(tc.Result, out) { 403 t.Fatalf("%s: bad: %#v", name, out) 404 } 405 } 406 } 407 408 func TestConfigFieldReader_computedComplexSet(t *testing.T) { 409 hashfunc := func(v interface{}) int { 410 var buf bytes.Buffer 411 m := v.(map[string]interface{}) 412 buf.WriteString(fmt.Sprintf("%s-", m["name"].(string))) 413 buf.WriteString(fmt.Sprintf("%s-", m["vhd_uri"].(string))) 414 return hashcode.String(buf.String()) 415 } 416 417 schema := map[string]*Schema{ 418 "set": &Schema{ 419 Type: TypeSet, 420 Elem: &Resource{ 421 Schema: map[string]*Schema{ 422 "name": { 423 Type: TypeString, 424 Required: true, 425 }, 426 427 "vhd_uri": { 428 Type: TypeString, 429 Required: true, 430 }, 431 }, 432 }, 433 Set: hashfunc, 434 }, 435 } 436 437 cases := map[string]struct { 438 Addr []string 439 Result FieldReadResult 440 Config *terraform.ResourceConfig 441 Err bool 442 }{ 443 "set, normal": { 444 []string{"set"}, 445 FieldReadResult{ 446 Value: map[string]interface{}{ 447 "532860136": map[string]interface{}{ 448 "name": "myosdisk1", 449 "vhd_uri": "bar", 450 }, 451 }, 452 Exists: true, 453 Computed: false, 454 }, 455 testConfig(t, map[string]interface{}{ 456 "set": []interface{}{ 457 map[string]interface{}{ 458 "name": "myosdisk1", 459 "vhd_uri": "bar", 460 }, 461 }, 462 }), 463 false, 464 }, 465 466 "set, computed element": { 467 []string{"set"}, 468 FieldReadResult{ 469 Value: map[string]interface{}{ 470 "~3596295623": map[string]interface{}{ 471 "name": "myosdisk1", 472 "vhd_uri": "${var.foo}/bar", 473 }, 474 }, 475 Exists: true, 476 Computed: false, 477 }, 478 testConfigInterpolate(t, map[string]interface{}{ 479 "set": []interface{}{ 480 map[string]interface{}{ 481 "name": "myosdisk1", 482 "vhd_uri": "${var.foo}/bar", 483 }, 484 }, 485 }, map[string]ast.Variable{ 486 "var.foo": ast.Variable{ 487 Value: config.UnknownVariableValue, 488 Type: ast.TypeUnknown, 489 }, 490 }), 491 false, 492 }, 493 494 "set, computed element single": { 495 []string{"set", "~3596295623", "vhd_uri"}, 496 FieldReadResult{ 497 Value: "${var.foo}/bar", 498 Exists: true, 499 Computed: true, 500 }, 501 testConfigInterpolate(t, map[string]interface{}{ 502 "set": []interface{}{ 503 map[string]interface{}{ 504 "name": "myosdisk1", 505 "vhd_uri": "${var.foo}/bar", 506 }, 507 }, 508 }, map[string]ast.Variable{ 509 "var.foo": ast.Variable{ 510 Value: config.UnknownVariableValue, 511 Type: ast.TypeUnknown, 512 }, 513 }), 514 false, 515 }, 516 } 517 518 for name, tc := range cases { 519 r := &ConfigFieldReader{ 520 Schema: schema, 521 Config: tc.Config, 522 } 523 out, err := r.ReadField(tc.Addr) 524 if err != nil != tc.Err { 525 t.Fatalf("%s: err: %s", name, err) 526 } 527 if s, ok := out.Value.(*Set); ok { 528 // If it is a set, convert to the raw map 529 out.Value = s.m 530 if len(s.m) == 0 { 531 out.Value = nil 532 } 533 } 534 if !reflect.DeepEqual(tc.Result, out) { 535 t.Fatalf("%s: bad: %#v", name, out) 536 } 537 } 538 } 539 540 func testConfig( 541 t *testing.T, raw map[string]interface{}) *terraform.ResourceConfig { 542 return testConfigInterpolate(t, raw, nil) 543 } 544 545 func testConfigInterpolate( 546 t *testing.T, 547 raw map[string]interface{}, 548 vs map[string]ast.Variable) *terraform.ResourceConfig { 549 550 rc, err := config.NewRawConfig(raw) 551 if err != nil { 552 t.Fatalf("err: %s", err) 553 } 554 if len(vs) > 0 { 555 if err := rc.Interpolate(vs); err != nil { 556 t.Fatalf("err: %s", err) 557 } 558 } 559 560 return terraform.NewResourceConfig(rc) 561 }