github.com/hashicorp/terraform-plugin-sdk@v1.17.2/helper/resource/testing_new_test.go (about) 1 package resource 2 3 import ( 4 "encoding/json" 5 "fmt" 6 "strings" 7 "testing" 8 9 "github.com/go-test/deep" 10 tfjson "github.com/hashicorp/terraform-json" 11 "github.com/hashicorp/terraform-plugin-sdk/terraform" 12 ) 13 14 func TestShimState(t *testing.T) { 15 type expectedError struct { 16 Prefix string 17 } 18 19 testCases := []struct { 20 Name string 21 RawState string 22 ExpectedState *terraform.State 23 ExpectedErr *expectedError 24 }{ 25 { 26 "empty", 27 `{ 28 "format_version": "0.1" 29 }`, 30 &terraform.State{ 31 Version: 3, 32 Modules: []*terraform.ModuleState{ 33 { 34 Path: []string{"root"}, 35 Outputs: map[string]*terraform.OutputState{}, 36 Resources: map[string]*terraform.ResourceState{}, 37 Dependencies: []string{}, 38 }, 39 }, 40 }, 41 nil, 42 }, 43 { 44 "simple outputs", 45 `{ 46 "format_version": "0.1", 47 "terraform_version": "0.12.18", 48 "values": { 49 "outputs": { 50 "bool": { 51 "sensitive": false, 52 "value": true 53 }, 54 "int": { 55 "sensitive": false, 56 "value": 42 57 }, 58 "float": { 59 "sensitive": false, 60 "value": 1.4 61 }, 62 "string": { 63 "sensitive": false, 64 "value": "test" 65 } 66 }, 67 "root_module": {} 68 } 69 }`, 70 &terraform.State{ 71 Version: 3, 72 TFVersion: "0.12.18", 73 Modules: []*terraform.ModuleState{ 74 { 75 Path: []string{"root"}, 76 Outputs: map[string]*terraform.OutputState{ 77 "bool": { 78 Type: "string", 79 Value: "true", 80 Sensitive: false, 81 }, 82 "int": { 83 Type: "string", 84 Value: "42", 85 Sensitive: false, 86 }, 87 "float": { 88 Type: "string", 89 Value: "1.4", 90 Sensitive: false, 91 }, 92 "string": { 93 Type: "string", 94 Value: "test", 95 Sensitive: false, 96 }, 97 }, 98 Resources: map[string]*terraform.ResourceState{}, 99 Dependencies: []string{}, 100 }, 101 }, 102 }, 103 nil, 104 }, 105 { 106 "complex outputs", 107 `{ 108 "format_version": "0.1", 109 "terraform_version": "0.12.18", 110 "values": { 111 "outputs": { 112 "empty_list": { 113 "sensitive": false, 114 "value": [] 115 }, 116 "list_of_strings": { 117 "sensitive": false, 118 "value": ["first", "second", "third"] 119 }, 120 "map_of_strings": { 121 "sensitive": false, 122 "value": { 123 "hello": "world", 124 "foo": "bar" 125 } 126 }, 127 "list_of_int": { 128 "sensitive": false, 129 "value": [1, 4, 9] 130 }, 131 "list_of_float": { 132 "sensitive": false, 133 "value": [1.2, 4.2, 9.8] 134 }, 135 "list_of_bool": { 136 "sensitive": false, 137 "value": [true, false, true] 138 } 139 }, 140 "root_module": {} 141 } 142 }`, 143 &terraform.State{ 144 Version: 3, 145 TFVersion: "0.12.18", 146 Modules: []*terraform.ModuleState{ 147 { 148 Path: []string{"root"}, 149 Outputs: map[string]*terraform.OutputState{ 150 "empty_list": { 151 Type: "list", 152 Value: []interface{}{}, 153 Sensitive: false, 154 }, 155 "list_of_strings": { 156 Type: "list", 157 Value: []interface{}{ 158 "first", "second", "third", 159 }, 160 Sensitive: false, 161 }, 162 "map_of_strings": { 163 Type: "map", 164 Value: map[string]interface{}{ 165 "hello": "world", 166 "foo": "bar", 167 }, 168 Sensitive: false, 169 }, 170 "list_of_int": { 171 Type: "list", 172 Value: []interface{}{ 173 json.Number("1"), 174 json.Number("4"), 175 json.Number("9"), 176 }, 177 Sensitive: false, 178 }, 179 "list_of_float": { 180 Type: "list", 181 Value: []interface{}{ 182 json.Number("1.2"), 183 json.Number("4.2"), 184 json.Number("9.8"), 185 }, 186 Sensitive: false, 187 }, 188 "list_of_bool": { 189 Type: "list", 190 Value: []interface{}{ 191 true, false, true, 192 }, 193 Sensitive: false, 194 }, 195 }, 196 Resources: map[string]*terraform.ResourceState{}, 197 Dependencies: []string{}, 198 }, 199 }, 200 }, 201 nil, 202 }, 203 { 204 "output with slice of slices", 205 `{ 206 "format_version": "0.1", 207 "terraform_version": "0.12.18", 208 "values": { 209 "outputs": { 210 "list_of_lists": { 211 "sensitive": false, 212 "value": [ 213 ["one", "two"], 214 ["blue", "green", "red"] 215 ] 216 } 217 }, 218 "root_module": {} 219 } 220 }`, 221 &terraform.State{ 222 Version: 3, 223 TFVersion: "0.12.18", 224 Modules: []*terraform.ModuleState{ 225 { 226 Path: []string{"root"}, 227 Outputs: map[string]*terraform.OutputState{ 228 "list_of_lists": { 229 Type: "list", 230 Value: []interface{}{ 231 []interface{}{"one", "two"}, 232 []interface{}{"blue", "green", "red"}, 233 }, 234 Sensitive: false, 235 }, 236 }, 237 Resources: map[string]*terraform.ResourceState{}, 238 Dependencies: []string{}, 239 }, 240 }, 241 }, 242 nil, 243 }, 244 { 245 "output with slice of maps", 246 `{ 247 "format_version": "0.1", 248 "terraform_version": "0.12.18", 249 "values": { 250 "outputs": { 251 "list_of_maps": { 252 "sensitive": false, 253 "value": [ 254 { 255 "rule": "allow", 256 "port": 443, 257 "allow_bool": true 258 }, 259 { 260 "rule": "deny", 261 "port": 80, 262 "allow_bool": false 263 } 264 ] 265 } 266 }, 267 "root_module": {} 268 } 269 }`, 270 &terraform.State{ 271 Version: 3, 272 TFVersion: "0.12.18", 273 Modules: []*terraform.ModuleState{ 274 { 275 Path: []string{"root"}, 276 Outputs: map[string]*terraform.OutputState{ 277 "list_of_maps": { 278 Type: "list", 279 Value: []interface{}{ 280 map[string]interface{}{ 281 "allow_bool": true, 282 "port": json.Number("443"), 283 "rule": "allow", 284 }, 285 map[string]interface{}{ 286 "allow_bool": false, 287 "port": json.Number("80"), 288 "rule": "deny", 289 }, 290 }, 291 Sensitive: false, 292 }, 293 }, 294 Resources: map[string]*terraform.ResourceState{}, 295 Dependencies: []string{}, 296 }, 297 }, 298 }, 299 nil, 300 }, 301 { 302 "output with nested map", 303 `{ 304 "format_version": "0.1", 305 "terraform_version": "0.12.18", 306 "values": { 307 "outputs": { 308 "map_of_maps": { 309 "sensitive": false, 310 "value": { 311 "hello": { 312 "whole": "world" 313 }, 314 "foo": "bar" 315 } 316 } 317 }, 318 "root_module": {} 319 } 320 }`, 321 &terraform.State{ 322 Version: 3, 323 TFVersion: "0.12.18", 324 Modules: []*terraform.ModuleState{ 325 { 326 Path: []string{"root"}, 327 Outputs: map[string]*terraform.OutputState{ 328 "map_of_maps": { 329 Type: "map", 330 Value: map[string]interface{}{ 331 "hello": map[string]interface{}{ 332 "whole": "world", 333 }, 334 "foo": "bar", 335 }, 336 Sensitive: false, 337 }, 338 }, 339 Resources: map[string]*terraform.ResourceState{}, 340 Dependencies: []string{}, 341 }, 342 }, 343 }, 344 nil, 345 }, 346 { 347 "invalid address", 348 `{ 349 "format_version": "0.1", 350 "values": { 351 "root_module": { 352 "address": "blah" 353 } 354 } 355 }`, 356 nil, 357 &expectedError{Prefix: "Invalid module instance address"}, 358 }, 359 { 360 "resource with primitive attributes", 361 `{ 362 "format_version": "0.1", 363 "terraform_version": "0.12.18", 364 "values": { 365 "outputs": {}, 366 "root_module": { 367 "resources": [ 368 { 369 "address": "cloud_vpc.main", 370 "mode": "managed", 371 "type": "cloud_vpc", 372 "name": "main", 373 "provider_name": "cloud", 374 "schema_version": 1, 375 "values": { 376 "id": "123999", 377 "string_field": "hello world", 378 "bool_field_1": false, 379 "bool_field_2": true, 380 "null_field": null, 381 "empty_string": "", 382 "number_field": 42 383 } 384 } 385 ] 386 } 387 } 388 }`, 389 &terraform.State{ 390 Version: 3, 391 TFVersion: "0.12.18", 392 Modules: []*terraform.ModuleState{ 393 { 394 Path: []string{"root"}, 395 Outputs: map[string]*terraform.OutputState{}, 396 Resources: map[string]*terraform.ResourceState{ 397 "cloud_vpc.main": { 398 Type: "cloud_vpc", 399 Provider: "cloud", 400 Primary: &terraform.InstanceState{ 401 ID: "123999", 402 Meta: map[string]interface{}{ 403 "schema_version": 1, 404 }, 405 Attributes: map[string]string{ 406 "%": "7", 407 "id": "123999", 408 409 "bool_field_2": "true", 410 "string_field": "hello world", 411 "bool_field_1": "false", 412 "empty_string": "", 413 "number_field": "42", 414 }, 415 }, 416 }, 417 }, 418 Dependencies: []string{}, 419 }, 420 }, 421 }, 422 nil, 423 }, 424 { 425 "resource with nested slice", 426 `{ 427 "format_version": "0.1", 428 "terraform_version": "0.12.18", 429 "values": { 430 "outputs": {}, 431 "root_module": { 432 "resources": [ 433 { 434 "address": "cloud_vpc.main", 435 "mode": "managed", 436 "type": "cloud_vpc", 437 "name": "main", 438 "provider_name": "cloud", 439 "schema_version": 1, 440 "values": { 441 "id": "123999", 442 "list_of_lists": [ 443 ["one", "two", "three"], 444 ["red", "green", "blue"], 445 ["black", "white"] 446 ], 447 "list_of_maps": [ 448 { 449 "action": "allow", 450 "port": 443, 451 "allow_bool": true 452 }, 453 { 454 "action": "deny", 455 "port": 80, 456 "allow_bool": false 457 } 458 ] 459 } 460 } 461 ] 462 } 463 } 464 }`, 465 &terraform.State{ 466 Version: 3, 467 TFVersion: "0.12.18", 468 Modules: []*terraform.ModuleState{ 469 { 470 Path: []string{"root"}, 471 Outputs: map[string]*terraform.OutputState{}, 472 Resources: map[string]*terraform.ResourceState{ 473 "cloud_vpc.main": { 474 Type: "cloud_vpc", 475 Provider: "cloud", 476 Primary: &terraform.InstanceState{ 477 ID: "123999", 478 Meta: map[string]interface{}{ 479 "schema_version": 1, 480 }, 481 Attributes: map[string]string{ 482 "%": "3", 483 "id": "123999", 484 485 "list_of_lists.#": "3", 486 "list_of_lists.0.#": "3", 487 "list_of_lists.0.0": "one", 488 "list_of_lists.0.1": "two", 489 "list_of_lists.0.2": "three", 490 "list_of_lists.1.#": "3", 491 "list_of_lists.1.0": "red", 492 "list_of_lists.1.1": "green", 493 "list_of_lists.1.2": "blue", 494 "list_of_lists.2.#": "2", 495 "list_of_lists.2.0": "black", 496 "list_of_lists.2.1": "white", 497 498 "list_of_maps.#": "2", 499 "list_of_maps.0.%": "3", 500 "list_of_maps.0.action": "allow", 501 "list_of_maps.0.allow_bool": "true", 502 "list_of_maps.0.port": "443", 503 "list_of_maps.1.%": "3", 504 "list_of_maps.1.action": "deny", 505 "list_of_maps.1.allow_bool": "false", 506 "list_of_maps.1.port": "80", 507 }, 508 }, 509 }, 510 }, 511 Dependencies: []string{}, 512 }, 513 }, 514 }, 515 nil, 516 }, 517 { 518 "resource with nested map", 519 `{ 520 "format_version": "0.1", 521 "terraform_version": "0.12.18", 522 "values": { 523 "outputs": {}, 524 "root_module": { 525 "resources": [ 526 { 527 "address": "cloud_vpc.main", 528 "mode": "managed", 529 "type": "cloud_vpc", 530 "name": "main", 531 "provider_name": "cloud", 532 "schema_version": 1, 533 "values": { 534 "id": "123999", 535 "map_of_maps": { 536 "parent": { 537 "inner": "value" 538 }, 539 "second": { 540 "inner2": "value2" 541 } 542 }, 543 "map_of_lists": { 544 "parent": { 545 "inner": ["one", "two"] 546 }, 547 "second": { 548 "inner2": [1, 4, 9] 549 } 550 }, 551 "map_of_list_of_maps": { 552 "parent": [ 553 { 554 "action": "allow", 555 "port": 443, 556 "allow_bool": true 557 }, 558 { 559 "action": "deny", 560 "port": 80, 561 "allow_bool": false 562 } 563 ] 564 } 565 } 566 } 567 ] 568 } 569 } 570 }`, 571 &terraform.State{ 572 Version: 3, 573 TFVersion: "0.12.18", 574 Modules: []*terraform.ModuleState{ 575 { 576 Path: []string{"root"}, 577 Outputs: map[string]*terraform.OutputState{}, 578 Resources: map[string]*terraform.ResourceState{ 579 "cloud_vpc.main": { 580 Type: "cloud_vpc", 581 Provider: "cloud", 582 Primary: &terraform.InstanceState{ 583 ID: "123999", 584 Meta: map[string]interface{}{ 585 "schema_version": 1, 586 }, 587 Attributes: map[string]string{ 588 "%": "4", 589 "id": "123999", 590 591 "map_of_maps.%": "2", 592 "map_of_maps.parent.%": "1", 593 "map_of_maps.parent.inner": "value", 594 "map_of_maps.second.%": "1", 595 "map_of_maps.second.inner2": "value2", 596 597 "map_of_lists.%": "2", 598 "map_of_lists.parent.%": "1", 599 "map_of_lists.parent.inner.#": "2", 600 "map_of_lists.parent.inner.0": "one", 601 "map_of_lists.parent.inner.1": "two", 602 "map_of_lists.second.%": "1", 603 "map_of_lists.second.inner2.#": "3", 604 "map_of_lists.second.inner2.0": "1", 605 "map_of_lists.second.inner2.1": "4", 606 "map_of_lists.second.inner2.2": "9", 607 608 "map_of_list_of_maps.%": "1", 609 "map_of_list_of_maps.parent.#": "2", 610 "map_of_list_of_maps.parent.0.%": "3", 611 "map_of_list_of_maps.parent.0.action": "allow", 612 "map_of_list_of_maps.parent.0.allow_bool": "true", 613 "map_of_list_of_maps.parent.0.port": "443", 614 "map_of_list_of_maps.parent.1.%": "3", 615 "map_of_list_of_maps.parent.1.action": "deny", 616 "map_of_list_of_maps.parent.1.allow_bool": "false", 617 "map_of_list_of_maps.parent.1.port": "80", 618 }, 619 }, 620 }, 621 }, 622 Dependencies: []string{}, 623 }, 624 }, 625 }, 626 nil, 627 }, 628 { 629 "data source", 630 `{ 631 "format_version": "0.1", 632 "terraform_version": "0.12.18", 633 "values": { 634 "outputs": {}, 635 "root_module": { 636 "resources": [ 637 { 638 "address": "data.cloud_vpc.main", 639 "mode": "data", 640 "type": "cloud_vpc", 641 "name": "main", 642 "provider_name": "cloud", 643 "schema_version": 0, 644 "values": { 645 "id": "123999", 646 "string_field": "hello world", 647 "bool_field_1": false, 648 "bool_field_2": true, 649 "null_field": null, 650 "empty_string": "", 651 "number_field": 42 652 } 653 } 654 ] 655 } 656 } 657 }`, 658 &terraform.State{ 659 Version: 3, 660 TFVersion: "0.12.18", 661 Modules: []*terraform.ModuleState{ 662 { 663 Path: []string{"root"}, 664 Outputs: map[string]*terraform.OutputState{}, 665 Resources: map[string]*terraform.ResourceState{ 666 "data.cloud_vpc.main": { 667 Type: "cloud_vpc", 668 Provider: "cloud", 669 Primary: &terraform.InstanceState{ 670 ID: "123999", 671 Meta: map[string]interface{}{ 672 "schema_version": 0, 673 }, 674 Attributes: map[string]string{ 675 "%": "7", 676 "id": "123999", 677 678 "bool_field_2": "true", 679 "string_field": "hello world", 680 "bool_field_1": "false", 681 "empty_string": "", 682 "number_field": "42", 683 }, 684 }, 685 }, 686 }, 687 Dependencies: []string{}, 688 }, 689 }, 690 }, 691 nil, 692 }, 693 { 694 "resource with complex attributes", 695 `{ 696 "format_version": "0.1", 697 "terraform_version": "0.12.18", 698 "values": { 699 "outputs": {}, 700 "root_module": { 701 "resources": [ 702 { 703 "address": "cloud_vpc.main", 704 "mode": "managed", 705 "type": "cloud_vpc", 706 "name": "main", 707 "provider_name": "cloud", 708 "schema_version": 1, 709 "values": { 710 "id": "123999", 711 "map_field": { 712 "key": "val", 713 "foo": "bar" 714 }, 715 "list_of_string": ["first", "second"], 716 "list_of_numbers": [1,2,3,4], 717 "list_of_bool": [true, false, true] 718 } 719 } 720 ] 721 } 722 } 723 }`, 724 &terraform.State{ 725 Version: 3, 726 TFVersion: "0.12.18", 727 Modules: []*terraform.ModuleState{ 728 { 729 Path: []string{"root"}, 730 Outputs: map[string]*terraform.OutputState{}, 731 Resources: map[string]*terraform.ResourceState{ 732 "cloud_vpc.main": { 733 Type: "cloud_vpc", 734 Provider: "cloud", 735 Primary: &terraform.InstanceState{ 736 ID: "123999", 737 Meta: map[string]interface{}{ 738 "schema_version": 1, 739 }, 740 Attributes: map[string]string{ 741 "%": "5", 742 "id": "123999", 743 744 "map_field.%": "2", 745 "map_field.key": "val", 746 "map_field.foo": "bar", 747 748 "list_of_string.#": "2", 749 "list_of_string.0": "first", 750 "list_of_string.1": "second", 751 752 "list_of_numbers.#": "4", 753 "list_of_numbers.0": "1", 754 "list_of_numbers.1": "2", 755 "list_of_numbers.2": "3", 756 "list_of_numbers.3": "4", 757 758 "list_of_bool.#": "3", 759 "list_of_bool.0": "true", 760 "list_of_bool.1": "false", 761 "list_of_bool.2": "true", 762 }, 763 }, 764 }, 765 }, 766 Dependencies: []string{}, 767 }, 768 }, 769 }, 770 nil, 771 }, 772 { 773 "indexed resource", 774 `{ 775 "format_version": "0.1", 776 "terraform_version": "0.12.18", 777 "values": { 778 "outputs": {}, 779 "root_module": { 780 "resources": [ 781 { 782 "address": "cloud_vpc.main", 783 "index": 0, 784 "mode": "managed", 785 "type": "cloud_vpc", 786 "name": "main", 787 "provider_name": "cloud", 788 "schema_version": 1, 789 "values": { 790 "id": "11111" 791 } 792 }, 793 { 794 "address": "cloud_vpc.main", 795 "index": 1, 796 "mode": "managed", 797 "type": "cloud_vpc", 798 "name": "main", 799 "provider_name": "cloud", 800 "schema_version": 1, 801 "values": { 802 "id": "22222" 803 } 804 } 805 ] 806 } 807 } 808 }`, 809 &terraform.State{ 810 Version: 3, 811 TFVersion: "0.12.18", 812 Modules: []*terraform.ModuleState{ 813 { 814 Path: []string{"root"}, 815 Outputs: map[string]*terraform.OutputState{}, 816 Resources: map[string]*terraform.ResourceState{ 817 "cloud_vpc.main.0": { 818 Type: "cloud_vpc", 819 Provider: "cloud", 820 Primary: &terraform.InstanceState{ 821 ID: "11111", 822 Meta: map[string]interface{}{ 823 "schema_version": 1, 824 }, 825 Attributes: map[string]string{ 826 "%": "1", 827 "id": "11111", 828 }, 829 }, 830 }, 831 "cloud_vpc.main.1": { 832 Type: "cloud_vpc", 833 Provider: "cloud", 834 Primary: &terraform.InstanceState{ 835 ID: "22222", 836 Meta: map[string]interface{}{ 837 "schema_version": 1, 838 }, 839 Attributes: map[string]string{ 840 "%": "1", 841 "id": "22222", 842 }, 843 }, 844 }, 845 }, 846 Dependencies: []string{}, 847 }, 848 }, 849 }, 850 nil, 851 }, 852 { 853 "indexed data source", 854 `{ 855 "format_version": "0.1", 856 "terraform_version": "0.12.18", 857 "values": { 858 "outputs": {}, 859 "root_module": { 860 "resources": [ 861 { 862 "address": "data.cloud_vpc.main", 863 "index": 0, 864 "mode": "data", 865 "type": "cloud_vpc", 866 "name": "main", 867 "provider_name": "cloud", 868 "schema_version": 0, 869 "values": { 870 "id": "11111" 871 } 872 }, 873 { 874 "address": "data.cloud_vpc.main", 875 "index": 1, 876 "mode": "data", 877 "type": "cloud_vpc", 878 "name": "main", 879 "provider_name": "cloud", 880 "schema_version": 0, 881 "values": { 882 "id": "22222" 883 } 884 } 885 ] 886 } 887 } 888 }`, 889 &terraform.State{ 890 Version: 3, 891 TFVersion: "0.12.18", 892 Modules: []*terraform.ModuleState{ 893 { 894 Path: []string{"root"}, 895 Outputs: map[string]*terraform.OutputState{}, 896 Resources: map[string]*terraform.ResourceState{ 897 "data.cloud_vpc.main.0": { 898 Type: "cloud_vpc", 899 Provider: "cloud", 900 Primary: &terraform.InstanceState{ 901 ID: "11111", 902 Meta: map[string]interface{}{ 903 "schema_version": 0, 904 }, 905 Attributes: map[string]string{ 906 "%": "1", 907 "id": "11111", 908 }, 909 }, 910 }, 911 "data.cloud_vpc.main.1": { 912 Type: "cloud_vpc", 913 Provider: "cloud", 914 Primary: &terraform.InstanceState{ 915 ID: "22222", 916 Meta: map[string]interface{}{ 917 "schema_version": 0, 918 }, 919 Attributes: map[string]string{ 920 "%": "1", 921 "id": "22222", 922 }, 923 }, 924 }, 925 }, 926 Dependencies: []string{}, 927 }, 928 }, 929 }, 930 nil, 931 }, 932 { 933 "for_each", 934 `{ 935 "format_version": "0.1", 936 "terraform_version": "0.12.18", 937 "values": { 938 "outputs": {}, 939 "root_module": { 940 "resources": [ 941 { 942 "address": "cloud_vpc.main", 943 "index": "one", 944 "mode": "managed", 945 "type": "cloud_vpc", 946 "name": "main", 947 "provider_name": "cloud", 948 "schema_version": 1, 949 "values": { 950 "id": "11111" 951 } 952 }, 953 { 954 "address": "cloud_vpc.main", 955 "index": "two", 956 "mode": "managed", 957 "type": "cloud_vpc", 958 "name": "main", 959 "provider_name": "cloud", 960 "schema_version": 1, 961 "values": { 962 "id": "22222" 963 } 964 } 965 ] 966 } 967 } 968 }`, 969 nil, 970 &expectedError{Prefix: "unexpected index type (string)"}, 971 }, 972 { 973 "depends on", 974 `{ 975 "format_version": "0.1", 976 "terraform_version": "0.12.18", 977 "values": { 978 "outputs": {}, 979 "root_module": { 980 "resources": [ 981 { 982 "address": "cloud_vpc.primary", 983 "mode": "managed", 984 "type": "cloud_vpc", 985 "name": "primary", 986 "provider_name": "cloud", 987 "values": { 988 "id": "11111" 989 } 990 }, 991 { 992 "address": "cloud_vpc.secondary", 993 "mode": "managed", 994 "type": "cloud_vpc", 995 "name": "secondary", 996 "provider_name": "cloud", 997 "values": { 998 "id": "22222" 999 }, 1000 "depends_on": [ 1001 "cloud_vpc.primary" 1002 ] 1003 } 1004 ] 1005 } 1006 } 1007 }`, 1008 &terraform.State{ 1009 Version: 3, 1010 TFVersion: "0.12.18", 1011 Modules: []*terraform.ModuleState{ 1012 { 1013 Path: []string{"root"}, 1014 Outputs: map[string]*terraform.OutputState{}, 1015 Resources: map[string]*terraform.ResourceState{ 1016 "cloud_vpc.primary": { 1017 Type: "cloud_vpc", 1018 Provider: "cloud", 1019 Primary: &terraform.InstanceState{ 1020 ID: "11111", 1021 Meta: map[string]interface{}{ 1022 "schema_version": 0, 1023 }, 1024 Attributes: map[string]string{ 1025 "%": "1", 1026 "id": "11111", 1027 }, 1028 }, 1029 }, 1030 "cloud_vpc.secondary": { 1031 Type: "cloud_vpc", 1032 Provider: "cloud", 1033 Primary: &terraform.InstanceState{ 1034 ID: "22222", 1035 Meta: map[string]interface{}{ 1036 "schema_version": 0, 1037 }, 1038 Attributes: map[string]string{ 1039 "%": "1", 1040 "id": "22222", 1041 }, 1042 }, 1043 Dependencies: []string{ 1044 "cloud_vpc.primary", 1045 }, 1046 }, 1047 }, 1048 Dependencies: []string{}, 1049 }, 1050 }, 1051 }, 1052 nil, 1053 }, 1054 { 1055 "child modules", 1056 `{ 1057 "format_version": "0.1", 1058 "terraform_version": "0.12.18", 1059 "values": { 1060 "root_module": { 1061 "child_modules": [ 1062 { 1063 "resources": [ 1064 { 1065 "address": "cloud_vpc.primary", 1066 "mode": "managed", 1067 "type": "cloud_vpc", 1068 "name": "primary", 1069 "provider_name": "cloud", 1070 "values": { 1071 "id": "11111" 1072 } 1073 } 1074 ] 1075 } 1076 ] 1077 } 1078 } 1079 }`, 1080 nil, 1081 &expectedError{Prefix: "Modules are not supported."}, 1082 }, 1083 } 1084 1085 for i, tc := range testCases { 1086 t.Run(fmt.Sprintf("%d-%s", i, tc.Name), func(t *testing.T) { 1087 var rawState tfjson.State 1088 rawState.UseJSONNumber(true) 1089 1090 err := unmarshalJSON([]byte(tc.RawState), &rawState) 1091 if err != nil { 1092 t.Fatal(err) 1093 } 1094 1095 shimmedState, err := shimStateFromJson(&rawState) 1096 if tc.ExpectedErr != nil { 1097 if err == nil { 1098 t.Fatalf("Expected error with prefix: %q\nGot no error.", 1099 tc.ExpectedErr.Prefix) 1100 } 1101 if strings.HasPrefix(err.Error(), tc.ExpectedErr.Prefix) { 1102 return 1103 } 1104 t.Fatalf("Error mismatch.\nExpected prefix: %q\nGot: %q\n", 1105 tc.ExpectedErr.Prefix, err.Error()) 1106 } 1107 if err != nil { 1108 t.Fatal(err) 1109 } 1110 1111 // Lineage is randomly generated, so we wipe it to make comparing easier 1112 shimmedState.Lineage = "" 1113 1114 if diff := deep.Equal(tc.ExpectedState, shimmedState); diff != nil { 1115 t.Fatalf("state mismatch:\n%s", strings.Join(diff, "\n")) 1116 } 1117 }) 1118 } 1119 }