github.com/Hashicorp/terraform@v0.11.12-beta1/helper/schema/field_reader_diff_test.go (about) 1 package schema 2 3 import ( 4 "reflect" 5 "testing" 6 7 "github.com/hashicorp/terraform/terraform" 8 ) 9 10 func TestDiffFieldReader_impl(t *testing.T) { 11 var _ FieldReader = new(DiffFieldReader) 12 } 13 14 func TestDiffFieldReader_NestedSetUpdate(t *testing.T) { 15 hashFn := func(a interface{}) int { 16 m := a.(map[string]interface{}) 17 return m["val"].(int) 18 } 19 20 schema := map[string]*Schema{ 21 "list_of_sets_1": &Schema{ 22 Type: TypeList, 23 Elem: &Resource{ 24 Schema: map[string]*Schema{ 25 "nested_set": &Schema{ 26 Type: TypeSet, 27 Elem: &Resource{ 28 Schema: map[string]*Schema{ 29 "val": &Schema{ 30 Type: TypeInt, 31 }, 32 }, 33 }, 34 Set: hashFn, 35 }, 36 }, 37 }, 38 }, 39 "list_of_sets_2": &Schema{ 40 Type: TypeList, 41 Elem: &Resource{ 42 Schema: map[string]*Schema{ 43 "nested_set": &Schema{ 44 Type: TypeSet, 45 Elem: &Resource{ 46 Schema: map[string]*Schema{ 47 "val": &Schema{ 48 Type: TypeInt, 49 }, 50 }, 51 }, 52 Set: hashFn, 53 }, 54 }, 55 }, 56 }, 57 } 58 59 r := &DiffFieldReader{ 60 Schema: schema, 61 Diff: &terraform.InstanceDiff{ 62 Attributes: map[string]*terraform.ResourceAttrDiff{ 63 "list_of_sets_1.0.nested_set.1.val": &terraform.ResourceAttrDiff{ 64 Old: "1", 65 New: "0", 66 NewRemoved: true, 67 }, 68 "list_of_sets_1.0.nested_set.2.val": &terraform.ResourceAttrDiff{ 69 New: "2", 70 }, 71 }, 72 }, 73 } 74 75 r.Source = &MultiLevelFieldReader{ 76 Readers: map[string]FieldReader{ 77 "diff": r, 78 "set": &MapFieldReader{Schema: schema}, 79 "state": &MapFieldReader{ 80 Map: &BasicMapReader{ 81 "list_of_sets_1.#": "1", 82 "list_of_sets_1.0.nested_set.#": "1", 83 "list_of_sets_1.0.nested_set.1.val": "1", 84 "list_of_sets_2.#": "1", 85 "list_of_sets_2.0.nested_set.#": "1", 86 "list_of_sets_2.0.nested_set.1.val": "1", 87 }, 88 Schema: schema, 89 }, 90 }, 91 Levels: []string{"state", "config"}, 92 } 93 94 out, err := r.ReadField([]string{"list_of_sets_2"}) 95 if err != nil { 96 t.Fatalf("err: %v", err) 97 } 98 99 s := &Set{F: hashFn} 100 s.Add(map[string]interface{}{"val": 1}) 101 expected := s.List() 102 103 l := out.Value.([]interface{}) 104 i := l[0].(map[string]interface{}) 105 actual := i["nested_set"].(*Set).List() 106 107 if !reflect.DeepEqual(expected, actual) { 108 t.Fatalf("bad: NestedSetUpdate\n\nexpected: %#v\n\ngot: %#v\n\n", expected, actual) 109 } 110 } 111 112 // https://github.com/hashicorp/terraform/issues/914 113 func TestDiffFieldReader_MapHandling(t *testing.T) { 114 schema := map[string]*Schema{ 115 "tags": &Schema{ 116 Type: TypeMap, 117 }, 118 } 119 r := &DiffFieldReader{ 120 Schema: schema, 121 Diff: &terraform.InstanceDiff{ 122 Attributes: map[string]*terraform.ResourceAttrDiff{ 123 "tags.%": &terraform.ResourceAttrDiff{ 124 Old: "1", 125 New: "2", 126 }, 127 "tags.baz": &terraform.ResourceAttrDiff{ 128 Old: "", 129 New: "qux", 130 }, 131 }, 132 }, 133 Source: &MapFieldReader{ 134 Schema: schema, 135 Map: BasicMapReader(map[string]string{ 136 "tags.%": "1", 137 "tags.foo": "bar", 138 }), 139 }, 140 } 141 142 result, err := r.ReadField([]string{"tags"}) 143 if err != nil { 144 t.Fatalf("ReadField failed: %#v", err) 145 } 146 147 expected := map[string]interface{}{ 148 "foo": "bar", 149 "baz": "qux", 150 } 151 152 if !reflect.DeepEqual(expected, result.Value) { 153 t.Fatalf("bad: DiffHandling\n\nexpected: %#v\n\ngot: %#v\n\n", expected, result.Value) 154 } 155 } 156 157 func TestDiffFieldReader_extra(t *testing.T) { 158 schema := map[string]*Schema{ 159 "stringComputed": &Schema{Type: TypeString}, 160 161 "listMap": &Schema{ 162 Type: TypeList, 163 Elem: &Schema{ 164 Type: TypeMap, 165 }, 166 }, 167 168 "mapRemove": &Schema{Type: TypeMap}, 169 170 "setChange": &Schema{ 171 Type: TypeSet, 172 Optional: true, 173 Elem: &Resource{ 174 Schema: map[string]*Schema{ 175 "index": &Schema{ 176 Type: TypeInt, 177 Required: true, 178 }, 179 180 "value": &Schema{ 181 Type: TypeString, 182 Required: true, 183 }, 184 }, 185 }, 186 Set: func(a interface{}) int { 187 m := a.(map[string]interface{}) 188 return m["index"].(int) 189 }, 190 }, 191 192 "setEmpty": &Schema{ 193 Type: TypeSet, 194 Optional: true, 195 Elem: &Resource{ 196 Schema: map[string]*Schema{ 197 "index": &Schema{ 198 Type: TypeInt, 199 Required: true, 200 }, 201 202 "value": &Schema{ 203 Type: TypeString, 204 Required: true, 205 }, 206 }, 207 }, 208 Set: func(a interface{}) int { 209 m := a.(map[string]interface{}) 210 return m["index"].(int) 211 }, 212 }, 213 } 214 215 r := &DiffFieldReader{ 216 Schema: schema, 217 Diff: &terraform.InstanceDiff{ 218 Attributes: map[string]*terraform.ResourceAttrDiff{ 219 "stringComputed": &terraform.ResourceAttrDiff{ 220 Old: "foo", 221 New: "bar", 222 NewComputed: true, 223 }, 224 225 "listMap.0.bar": &terraform.ResourceAttrDiff{ 226 NewRemoved: true, 227 }, 228 229 "mapRemove.bar": &terraform.ResourceAttrDiff{ 230 NewRemoved: true, 231 }, 232 233 "setChange.10.value": &terraform.ResourceAttrDiff{ 234 Old: "50", 235 New: "80", 236 }, 237 238 "setEmpty.#": &terraform.ResourceAttrDiff{ 239 Old: "2", 240 New: "0", 241 }, 242 }, 243 }, 244 245 Source: &MapFieldReader{ 246 Schema: schema, 247 Map: BasicMapReader(map[string]string{ 248 "listMap.#": "2", 249 "listMap.0.foo": "bar", 250 "listMap.0.bar": "baz", 251 "listMap.1.baz": "baz", 252 253 "mapRemove.foo": "bar", 254 "mapRemove.bar": "bar", 255 256 "setChange.#": "1", 257 "setChange.10.index": "10", 258 "setChange.10.value": "50", 259 260 "setEmpty.#": "2", 261 "setEmpty.10.index": "10", 262 "setEmpty.10.value": "50", 263 "setEmpty.20.index": "20", 264 "setEmpty.20.value": "50", 265 }), 266 }, 267 } 268 269 cases := map[string]struct { 270 Addr []string 271 Result FieldReadResult 272 Err bool 273 }{ 274 "stringComputed": { 275 []string{"stringComputed"}, 276 FieldReadResult{ 277 Value: "", 278 Exists: true, 279 Computed: true, 280 }, 281 false, 282 }, 283 284 "listMapRemoval": { 285 []string{"listMap"}, 286 FieldReadResult{ 287 Value: []interface{}{ 288 map[string]interface{}{ 289 "foo": "bar", 290 }, 291 map[string]interface{}{ 292 "baz": "baz", 293 }, 294 }, 295 Exists: true, 296 }, 297 false, 298 }, 299 300 "mapRemove": { 301 []string{"mapRemove"}, 302 FieldReadResult{ 303 Value: map[string]interface{}{ 304 "foo": "bar", 305 }, 306 Exists: true, 307 Computed: false, 308 }, 309 false, 310 }, 311 312 "setChange": { 313 []string{"setChange"}, 314 FieldReadResult{ 315 Value: []interface{}{ 316 map[string]interface{}{ 317 "index": 10, 318 "value": "80", 319 }, 320 }, 321 Exists: true, 322 }, 323 false, 324 }, 325 326 "setEmpty": { 327 []string{"setEmpty"}, 328 FieldReadResult{ 329 Value: []interface{}{}, 330 Exists: true, 331 }, 332 false, 333 }, 334 } 335 336 for name, tc := range cases { 337 out, err := r.ReadField(tc.Addr) 338 if err != nil != tc.Err { 339 t.Fatalf("%s: err: %s", name, err) 340 } 341 if s, ok := out.Value.(*Set); ok { 342 // If it is a set, convert to a list so its more easily checked. 343 out.Value = s.List() 344 } 345 if !reflect.DeepEqual(tc.Result, out) { 346 t.Fatalf("%s: bad: %#v", name, out) 347 } 348 } 349 } 350 351 func TestDiffFieldReader(t *testing.T) { 352 testFieldReader(t, func(s map[string]*Schema) FieldReader { 353 return &DiffFieldReader{ 354 Schema: s, 355 Diff: &terraform.InstanceDiff{ 356 Attributes: map[string]*terraform.ResourceAttrDiff{ 357 "bool": &terraform.ResourceAttrDiff{ 358 Old: "", 359 New: "true", 360 }, 361 362 "int": &terraform.ResourceAttrDiff{ 363 Old: "", 364 New: "42", 365 }, 366 367 "float": &terraform.ResourceAttrDiff{ 368 Old: "", 369 New: "3.1415", 370 }, 371 372 "string": &terraform.ResourceAttrDiff{ 373 Old: "", 374 New: "string", 375 }, 376 377 "stringComputed": &terraform.ResourceAttrDiff{ 378 Old: "foo", 379 New: "bar", 380 NewComputed: true, 381 }, 382 383 "list.#": &terraform.ResourceAttrDiff{ 384 Old: "0", 385 New: "2", 386 }, 387 388 "list.0": &terraform.ResourceAttrDiff{ 389 Old: "", 390 New: "foo", 391 }, 392 393 "list.1": &terraform.ResourceAttrDiff{ 394 Old: "", 395 New: "bar", 396 }, 397 398 "listInt.#": &terraform.ResourceAttrDiff{ 399 Old: "0", 400 New: "2", 401 }, 402 403 "listInt.0": &terraform.ResourceAttrDiff{ 404 Old: "", 405 New: "21", 406 }, 407 408 "listInt.1": &terraform.ResourceAttrDiff{ 409 Old: "", 410 New: "42", 411 }, 412 413 "map.foo": &terraform.ResourceAttrDiff{ 414 Old: "", 415 New: "bar", 416 }, 417 418 "map.bar": &terraform.ResourceAttrDiff{ 419 Old: "", 420 New: "baz", 421 }, 422 423 "mapInt.%": &terraform.ResourceAttrDiff{ 424 Old: "", 425 New: "2", 426 }, 427 "mapInt.one": &terraform.ResourceAttrDiff{ 428 Old: "", 429 New: "1", 430 }, 431 "mapInt.two": &terraform.ResourceAttrDiff{ 432 Old: "", 433 New: "2", 434 }, 435 436 "mapIntNestedSchema.%": &terraform.ResourceAttrDiff{ 437 Old: "", 438 New: "2", 439 }, 440 "mapIntNestedSchema.one": &terraform.ResourceAttrDiff{ 441 Old: "", 442 New: "1", 443 }, 444 "mapIntNestedSchema.two": &terraform.ResourceAttrDiff{ 445 Old: "", 446 New: "2", 447 }, 448 449 "mapFloat.%": &terraform.ResourceAttrDiff{ 450 Old: "", 451 New: "1", 452 }, 453 "mapFloat.oneDotTwo": &terraform.ResourceAttrDiff{ 454 Old: "", 455 New: "1.2", 456 }, 457 458 "mapBool.%": &terraform.ResourceAttrDiff{ 459 Old: "", 460 New: "2", 461 }, 462 "mapBool.True": &terraform.ResourceAttrDiff{ 463 Old: "", 464 New: "true", 465 }, 466 "mapBool.False": &terraform.ResourceAttrDiff{ 467 Old: "", 468 New: "false", 469 }, 470 471 "set.#": &terraform.ResourceAttrDiff{ 472 Old: "0", 473 New: "2", 474 }, 475 476 "set.10": &terraform.ResourceAttrDiff{ 477 Old: "", 478 New: "10", 479 }, 480 481 "set.50": &terraform.ResourceAttrDiff{ 482 Old: "", 483 New: "50", 484 }, 485 486 "setDeep.#": &terraform.ResourceAttrDiff{ 487 Old: "0", 488 New: "2", 489 }, 490 491 "setDeep.10.index": &terraform.ResourceAttrDiff{ 492 Old: "", 493 New: "10", 494 }, 495 496 "setDeep.10.value": &terraform.ResourceAttrDiff{ 497 Old: "", 498 New: "foo", 499 }, 500 501 "setDeep.50.index": &terraform.ResourceAttrDiff{ 502 Old: "", 503 New: "50", 504 }, 505 506 "setDeep.50.value": &terraform.ResourceAttrDiff{ 507 Old: "", 508 New: "bar", 509 }, 510 }, 511 }, 512 513 Source: &MapFieldReader{ 514 Schema: s, 515 Map: BasicMapReader(map[string]string{ 516 "listMap.#": "2", 517 "listMap.0.foo": "bar", 518 "listMap.0.bar": "baz", 519 "listMap.1.baz": "baz", 520 }), 521 }, 522 } 523 }) 524 }