github.com/iaas-resource-provision/iaas-rpc@v1.0.7-0.20211021023331-ed21f798c408/internal/command/jsonstate/state_test.go (about) 1 package jsonstate 2 3 import ( 4 "encoding/json" 5 "reflect" 6 "testing" 7 8 "github.com/google/go-cmp/cmp" 9 "github.com/iaas-resource-provision/iaas-rpc/internal/addrs" 10 "github.com/iaas-resource-provision/iaas-rpc/internal/configs/configschema" 11 "github.com/iaas-resource-provision/iaas-rpc/internal/states" 12 "github.com/iaas-resource-provision/iaas-rpc/internal/terraform" 13 "github.com/zclconf/go-cty/cty" 14 ) 15 16 func TestMarshalOutputs(t *testing.T) { 17 tests := []struct { 18 Outputs map[string]*states.OutputValue 19 Want map[string]output 20 Err bool 21 }{ 22 { 23 nil, 24 nil, 25 false, 26 }, 27 { 28 map[string]*states.OutputValue{ 29 "test": { 30 Sensitive: true, 31 Value: cty.StringVal("sekret"), 32 }, 33 }, 34 map[string]output{ 35 "test": { 36 Sensitive: true, 37 Value: json.RawMessage(`"sekret"`), 38 }, 39 }, 40 false, 41 }, 42 { 43 map[string]*states.OutputValue{ 44 "test": { 45 Sensitive: false, 46 Value: cty.StringVal("not_so_sekret"), 47 }, 48 }, 49 map[string]output{ 50 "test": { 51 Sensitive: false, 52 Value: json.RawMessage(`"not_so_sekret"`), 53 }, 54 }, 55 false, 56 }, 57 } 58 59 for _, test := range tests { 60 got, err := marshalOutputs(test.Outputs) 61 if test.Err { 62 if err == nil { 63 t.Fatal("succeeded; want error") 64 } 65 return 66 } else if err != nil { 67 t.Fatalf("unexpected error: %s", err) 68 } 69 eq := reflect.DeepEqual(got, test.Want) 70 if !eq { 71 // printing the output isn't terribly useful, but it does help indicate which test case failed 72 t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want) 73 } 74 } 75 } 76 77 func TestMarshalAttributeValues(t *testing.T) { 78 tests := []struct { 79 Attr cty.Value 80 Want attributeValues 81 }{ 82 { 83 cty.NilVal, 84 nil, 85 }, 86 { 87 cty.NullVal(cty.String), 88 nil, 89 }, 90 { 91 cty.ObjectVal(map[string]cty.Value{ 92 "foo": cty.StringVal("bar"), 93 }), 94 attributeValues{"foo": json.RawMessage(`"bar"`)}, 95 }, 96 { 97 cty.ObjectVal(map[string]cty.Value{ 98 "foo": cty.NullVal(cty.String), 99 }), 100 attributeValues{"foo": json.RawMessage(`null`)}, 101 }, 102 { 103 cty.ObjectVal(map[string]cty.Value{ 104 "bar": cty.MapVal(map[string]cty.Value{ 105 "hello": cty.StringVal("world"), 106 }), 107 "baz": cty.ListVal([]cty.Value{ 108 cty.StringVal("goodnight"), 109 cty.StringVal("moon"), 110 }), 111 }), 112 attributeValues{ 113 "bar": json.RawMessage(`{"hello":"world"}`), 114 "baz": json.RawMessage(`["goodnight","moon"]`), 115 }, 116 }, 117 // Marked values 118 { 119 cty.ObjectVal(map[string]cty.Value{ 120 "bar": cty.MapVal(map[string]cty.Value{ 121 "hello": cty.StringVal("world"), 122 }), 123 "baz": cty.ListVal([]cty.Value{ 124 cty.StringVal("goodnight"), 125 cty.StringVal("moon").Mark("sensitive"), 126 }), 127 }), 128 attributeValues{ 129 "bar": json.RawMessage(`{"hello":"world"}`), 130 "baz": json.RawMessage(`["goodnight","moon"]`), 131 }, 132 }, 133 } 134 135 for _, test := range tests { 136 got := marshalAttributeValues(test.Attr) 137 eq := reflect.DeepEqual(got, test.Want) 138 if !eq { 139 t.Fatalf("wrong result:\nGot: %#v\nWant: %#v\n", got, test.Want) 140 } 141 } 142 } 143 144 func TestMarshalResources(t *testing.T) { 145 deposedKey := states.NewDeposedKey() 146 tests := map[string]struct { 147 Resources map[string]*states.Resource 148 Schemas *terraform.Schemas 149 Want []resource 150 Err bool 151 }{ 152 "nil": { 153 nil, 154 nil, 155 nil, 156 false, 157 }, 158 "single resource": { 159 map[string]*states.Resource{ 160 "test_thing.baz": { 161 Addr: addrs.AbsResource{ 162 Resource: addrs.Resource{ 163 Mode: addrs.ManagedResourceMode, 164 Type: "test_thing", 165 Name: "bar", 166 }, 167 }, 168 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 169 addrs.NoKey: { 170 Current: &states.ResourceInstanceObjectSrc{ 171 Status: states.ObjectReady, 172 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 173 }, 174 }, 175 }, 176 ProviderConfig: addrs.AbsProviderConfig{ 177 Provider: addrs.NewDefaultProvider("test"), 178 Module: addrs.RootModule, 179 }, 180 }, 181 }, 182 testSchemas(), 183 []resource{ 184 { 185 Address: "test_thing.bar", 186 Mode: "managed", 187 Type: "test_thing", 188 Name: "bar", 189 Index: addrs.InstanceKey(nil), 190 ProviderName: "registry.terraform.io/hashicorp/test", 191 AttributeValues: attributeValues{ 192 "foozles": json.RawMessage(`null`), 193 "woozles": json.RawMessage(`"confuzles"`), 194 }, 195 SensitiveValues: json.RawMessage("{}"), 196 }, 197 }, 198 false, 199 }, 200 "resource with marks": { 201 map[string]*states.Resource{ 202 "test_thing.bar": { 203 Addr: addrs.AbsResource{ 204 Resource: addrs.Resource{ 205 Mode: addrs.ManagedResourceMode, 206 Type: "test_thing", 207 Name: "bar", 208 }, 209 }, 210 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 211 addrs.NoKey: { 212 Current: &states.ResourceInstanceObjectSrc{ 213 Status: states.ObjectReady, 214 AttrsJSON: []byte(`{"foozles":"confuzles"}`), 215 AttrSensitivePaths: []cty.PathValueMarks{{ 216 Path: cty.Path{cty.GetAttrStep{Name: "foozles"}}, 217 Marks: cty.NewValueMarks("sensitive")}, 218 }, 219 }, 220 }, 221 }, 222 ProviderConfig: addrs.AbsProviderConfig{ 223 Provider: addrs.NewDefaultProvider("test"), 224 Module: addrs.RootModule, 225 }, 226 }, 227 }, 228 testSchemas(), 229 []resource{ 230 { 231 Address: "test_thing.bar", 232 Mode: "managed", 233 Type: "test_thing", 234 Name: "bar", 235 Index: addrs.InstanceKey(nil), 236 ProviderName: "registry.terraform.io/hashicorp/test", 237 AttributeValues: attributeValues{ 238 "foozles": json.RawMessage(`"confuzles"`), 239 "woozles": json.RawMessage(`null`), 240 }, 241 SensitiveValues: json.RawMessage(`{"foozles":true}`), 242 }, 243 }, 244 false, 245 }, 246 "single resource wrong schema": { 247 map[string]*states.Resource{ 248 "test_thing.baz": { 249 Addr: addrs.AbsResource{ 250 Resource: addrs.Resource{ 251 Mode: addrs.ManagedResourceMode, 252 Type: "test_thing", 253 Name: "bar", 254 }, 255 }, 256 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 257 addrs.NoKey: { 258 Current: &states.ResourceInstanceObjectSrc{ 259 SchemaVersion: 1, 260 Status: states.ObjectReady, 261 AttrsJSON: []byte(`{"woozles":["confuzles"]}`), 262 }, 263 }, 264 }, 265 ProviderConfig: addrs.AbsProviderConfig{ 266 Provider: addrs.NewDefaultProvider("test"), 267 Module: addrs.RootModule, 268 }, 269 }, 270 }, 271 testSchemas(), 272 nil, 273 true, 274 }, 275 "resource with count": { 276 map[string]*states.Resource{ 277 "test_thing.bar": { 278 Addr: addrs.AbsResource{ 279 Resource: addrs.Resource{ 280 Mode: addrs.ManagedResourceMode, 281 Type: "test_thing", 282 Name: "bar", 283 }, 284 }, 285 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 286 addrs.IntKey(0): { 287 Current: &states.ResourceInstanceObjectSrc{ 288 Status: states.ObjectReady, 289 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 290 }, 291 }, 292 }, 293 ProviderConfig: addrs.AbsProviderConfig{ 294 Provider: addrs.NewDefaultProvider("test"), 295 Module: addrs.RootModule, 296 }, 297 }, 298 }, 299 testSchemas(), 300 []resource{ 301 { 302 Address: "test_thing.bar[0]", 303 Mode: "managed", 304 Type: "test_thing", 305 Name: "bar", 306 Index: addrs.IntKey(0), 307 ProviderName: "registry.terraform.io/hashicorp/test", 308 AttributeValues: attributeValues{ 309 "foozles": json.RawMessage(`null`), 310 "woozles": json.RawMessage(`"confuzles"`), 311 }, 312 SensitiveValues: json.RawMessage("{}"), 313 }, 314 }, 315 false, 316 }, 317 "resource with for_each": { 318 map[string]*states.Resource{ 319 "test_thing.bar": { 320 Addr: addrs.AbsResource{ 321 Resource: addrs.Resource{ 322 Mode: addrs.ManagedResourceMode, 323 Type: "test_thing", 324 Name: "bar", 325 }, 326 }, 327 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 328 addrs.StringKey("rockhopper"): { 329 Current: &states.ResourceInstanceObjectSrc{ 330 Status: states.ObjectReady, 331 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 332 }, 333 }, 334 }, 335 ProviderConfig: addrs.AbsProviderConfig{ 336 Provider: addrs.NewDefaultProvider("test"), 337 Module: addrs.RootModule, 338 }, 339 }, 340 }, 341 testSchemas(), 342 []resource{ 343 { 344 Address: "test_thing.bar[\"rockhopper\"]", 345 Mode: "managed", 346 Type: "test_thing", 347 Name: "bar", 348 Index: addrs.StringKey("rockhopper"), 349 ProviderName: "registry.terraform.io/hashicorp/test", 350 AttributeValues: attributeValues{ 351 "foozles": json.RawMessage(`null`), 352 "woozles": json.RawMessage(`"confuzles"`), 353 }, 354 SensitiveValues: json.RawMessage("{}"), 355 }, 356 }, 357 false, 358 }, 359 "deposed resource": { 360 map[string]*states.Resource{ 361 "test_thing.baz": { 362 Addr: addrs.AbsResource{ 363 Resource: addrs.Resource{ 364 Mode: addrs.ManagedResourceMode, 365 Type: "test_thing", 366 Name: "bar", 367 }, 368 }, 369 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 370 addrs.NoKey: { 371 Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{ 372 states.DeposedKey(deposedKey): { 373 Status: states.ObjectReady, 374 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 375 }, 376 }, 377 }, 378 }, 379 ProviderConfig: addrs.AbsProviderConfig{ 380 Provider: addrs.NewDefaultProvider("test"), 381 Module: addrs.RootModule, 382 }, 383 }, 384 }, 385 testSchemas(), 386 []resource{ 387 { 388 Address: "test_thing.bar", 389 Mode: "managed", 390 Type: "test_thing", 391 Name: "bar", 392 Index: addrs.InstanceKey(nil), 393 ProviderName: "registry.terraform.io/hashicorp/test", 394 DeposedKey: deposedKey.String(), 395 AttributeValues: attributeValues{ 396 "foozles": json.RawMessage(`null`), 397 "woozles": json.RawMessage(`"confuzles"`), 398 }, 399 SensitiveValues: json.RawMessage("{}"), 400 }, 401 }, 402 false, 403 }, 404 "deposed and current resource": { 405 map[string]*states.Resource{ 406 "test_thing.baz": { 407 Addr: addrs.AbsResource{ 408 Resource: addrs.Resource{ 409 Mode: addrs.ManagedResourceMode, 410 Type: "test_thing", 411 Name: "bar", 412 }, 413 }, 414 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 415 addrs.NoKey: { 416 Deposed: map[states.DeposedKey]*states.ResourceInstanceObjectSrc{ 417 states.DeposedKey(deposedKey): { 418 Status: states.ObjectReady, 419 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 420 }, 421 }, 422 Current: &states.ResourceInstanceObjectSrc{ 423 Status: states.ObjectReady, 424 AttrsJSON: []byte(`{"woozles":"confuzles"}`), 425 }, 426 }, 427 }, 428 ProviderConfig: addrs.AbsProviderConfig{ 429 Provider: addrs.NewDefaultProvider("test"), 430 Module: addrs.RootModule, 431 }, 432 }, 433 }, 434 testSchemas(), 435 []resource{ 436 { 437 Address: "test_thing.bar", 438 Mode: "managed", 439 Type: "test_thing", 440 Name: "bar", 441 Index: addrs.InstanceKey(nil), 442 ProviderName: "registry.terraform.io/hashicorp/test", 443 AttributeValues: attributeValues{ 444 "foozles": json.RawMessage(`null`), 445 "woozles": json.RawMessage(`"confuzles"`), 446 }, 447 SensitiveValues: json.RawMessage("{}"), 448 }, 449 { 450 Address: "test_thing.bar", 451 Mode: "managed", 452 Type: "test_thing", 453 Name: "bar", 454 Index: addrs.InstanceKey(nil), 455 ProviderName: "registry.terraform.io/hashicorp/test", 456 DeposedKey: deposedKey.String(), 457 AttributeValues: attributeValues{ 458 "foozles": json.RawMessage(`null`), 459 "woozles": json.RawMessage(`"confuzles"`), 460 }, 461 SensitiveValues: json.RawMessage("{}"), 462 }, 463 }, 464 false, 465 }, 466 "resource with marked map attr": { 467 map[string]*states.Resource{ 468 "test_map_attr.bar": { 469 Addr: addrs.AbsResource{ 470 Resource: addrs.Resource{ 471 Mode: addrs.ManagedResourceMode, 472 Type: "test_map_attr", 473 Name: "bar", 474 }, 475 }, 476 Instances: map[addrs.InstanceKey]*states.ResourceInstance{ 477 addrs.NoKey: { 478 Current: &states.ResourceInstanceObjectSrc{ 479 Status: states.ObjectReady, 480 AttrsJSON: []byte(`{"data":{"woozles":"confuzles"}}`), 481 AttrSensitivePaths: []cty.PathValueMarks{{ 482 Path: cty.Path{cty.GetAttrStep{Name: "data"}}, 483 Marks: cty.NewValueMarks("sensitive")}, 484 }, 485 }, 486 }, 487 }, 488 ProviderConfig: addrs.AbsProviderConfig{ 489 Provider: addrs.NewDefaultProvider("test"), 490 Module: addrs.RootModule, 491 }, 492 }, 493 }, 494 testSchemas(), 495 []resource{ 496 { 497 Address: "test_map_attr.bar", 498 Mode: "managed", 499 Type: "test_map_attr", 500 Name: "bar", 501 Index: addrs.InstanceKey(nil), 502 ProviderName: "registry.terraform.io/hashicorp/test", 503 AttributeValues: attributeValues{ 504 "data": json.RawMessage(`{"woozles":"confuzles"}`), 505 }, 506 SensitiveValues: json.RawMessage(`{"data":true}`), 507 }, 508 }, 509 false, 510 }, 511 } 512 513 for name, test := range tests { 514 t.Run(name, func(t *testing.T) { 515 got, err := marshalResources(test.Resources, addrs.RootModuleInstance, test.Schemas) 516 if test.Err { 517 if err == nil { 518 t.Fatal("succeeded; want error") 519 } 520 return 521 } else if err != nil { 522 t.Fatalf("unexpected error: %s", err) 523 } 524 525 diff := cmp.Diff(got, test.Want) 526 if diff != "" { 527 t.Fatalf("wrong result: %s\n", diff) 528 } 529 530 }) 531 } 532 } 533 534 func TestMarshalModules_basic(t *testing.T) { 535 childModule, _ := addrs.ParseModuleInstanceStr("module.child") 536 subModule, _ := addrs.ParseModuleInstanceStr("module.submodule") 537 testState := states.BuildState(func(s *states.SyncState) { 538 s.SetResourceInstanceCurrent( 539 addrs.Resource{ 540 Mode: addrs.ManagedResourceMode, 541 Type: "test_instance", 542 Name: "foo", 543 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 544 &states.ResourceInstanceObjectSrc{ 545 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 546 Status: states.ObjectReady, 547 }, 548 addrs.AbsProviderConfig{ 549 Provider: addrs.NewDefaultProvider("test"), 550 Module: addrs.RootModule, 551 }, 552 ) 553 s.SetResourceInstanceCurrent( 554 addrs.Resource{ 555 Mode: addrs.ManagedResourceMode, 556 Type: "test_instance", 557 Name: "foo", 558 }.Instance(addrs.NoKey).Absolute(childModule), 559 &states.ResourceInstanceObjectSrc{ 560 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 561 Status: states.ObjectReady, 562 }, 563 addrs.AbsProviderConfig{ 564 Provider: addrs.NewDefaultProvider("test"), 565 Module: childModule.Module(), 566 }, 567 ) 568 s.SetResourceInstanceCurrent( 569 addrs.Resource{ 570 Mode: addrs.ManagedResourceMode, 571 Type: "test_instance", 572 Name: "foo", 573 }.Instance(addrs.NoKey).Absolute(subModule), 574 &states.ResourceInstanceObjectSrc{ 575 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 576 Status: states.ObjectReady, 577 }, 578 addrs.AbsProviderConfig{ 579 Provider: addrs.NewDefaultProvider("test"), 580 Module: subModule.Module(), 581 }, 582 ) 583 }) 584 moduleMap := make(map[string][]addrs.ModuleInstance) 585 moduleMap[""] = []addrs.ModuleInstance{childModule, subModule} 586 587 got, err := marshalModules(testState, testSchemas(), moduleMap[""], moduleMap) 588 589 if err != nil { 590 t.Fatalf("unexpected error: %s", err.Error()) 591 } 592 593 if len(got) != 2 { 594 t.Fatalf("wrong result! got %d modules, expected 2", len(got)) 595 } 596 597 if got[0].Address != "module.child" || got[1].Address != "module.submodule" { 598 t.Fatalf("wrong result! got %#v\n", got) 599 } 600 601 } 602 603 func TestMarshalModules_nested(t *testing.T) { 604 childModule, _ := addrs.ParseModuleInstanceStr("module.child") 605 subModule, _ := addrs.ParseModuleInstanceStr("module.child.module.submodule") 606 testState := states.BuildState(func(s *states.SyncState) { 607 s.SetResourceInstanceCurrent( 608 addrs.Resource{ 609 Mode: addrs.ManagedResourceMode, 610 Type: "test_instance", 611 Name: "foo", 612 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 613 &states.ResourceInstanceObjectSrc{ 614 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 615 Status: states.ObjectReady, 616 }, 617 addrs.AbsProviderConfig{ 618 Provider: addrs.NewDefaultProvider("test"), 619 Module: addrs.RootModule, 620 }, 621 ) 622 s.SetResourceInstanceCurrent( 623 addrs.Resource{ 624 Mode: addrs.ManagedResourceMode, 625 Type: "test_instance", 626 Name: "foo", 627 }.Instance(addrs.NoKey).Absolute(childModule), 628 &states.ResourceInstanceObjectSrc{ 629 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 630 Status: states.ObjectReady, 631 }, 632 addrs.AbsProviderConfig{ 633 Provider: addrs.NewDefaultProvider("test"), 634 Module: childModule.Module(), 635 }, 636 ) 637 s.SetResourceInstanceCurrent( 638 addrs.Resource{ 639 Mode: addrs.ManagedResourceMode, 640 Type: "test_instance", 641 Name: "foo", 642 }.Instance(addrs.NoKey).Absolute(subModule), 643 &states.ResourceInstanceObjectSrc{ 644 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 645 Status: states.ObjectReady, 646 }, 647 addrs.AbsProviderConfig{ 648 Provider: addrs.NewDefaultProvider("test"), 649 Module: subModule.Module(), 650 }, 651 ) 652 }) 653 moduleMap := make(map[string][]addrs.ModuleInstance) 654 moduleMap[""] = []addrs.ModuleInstance{childModule} 655 moduleMap[childModule.String()] = []addrs.ModuleInstance{subModule} 656 657 got, err := marshalModules(testState, testSchemas(), moduleMap[""], moduleMap) 658 659 if err != nil { 660 t.Fatalf("unexpected error: %s", err.Error()) 661 } 662 663 if len(got) != 1 { 664 t.Fatalf("wrong result! got %d modules, expected 1", len(got)) 665 } 666 667 if got[0].Address != "module.child" { 668 t.Fatalf("wrong result! got %#v\n", got) 669 } 670 671 if got[0].ChildModules[0].Address != "module.child.module.submodule" { 672 t.Fatalf("wrong result! got %#v\n", got) 673 } 674 } 675 676 func TestMarshalModules_parent_no_resources(t *testing.T) { 677 subModule, _ := addrs.ParseModuleInstanceStr("module.child.module.submodule") 678 testState := states.BuildState(func(s *states.SyncState) { 679 s.SetResourceInstanceCurrent( 680 addrs.Resource{ 681 Mode: addrs.ManagedResourceMode, 682 Type: "test_instance", 683 Name: "foo", 684 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 685 &states.ResourceInstanceObjectSrc{ 686 AttrsJSON: []byte(`{"id":"bar","foo":"value","bar":"value"}`), 687 Status: states.ObjectReady, 688 }, 689 addrs.AbsProviderConfig{ 690 Provider: addrs.NewDefaultProvider("test"), 691 Module: addrs.RootModule, 692 }, 693 ) 694 s.SetResourceInstanceCurrent( 695 addrs.Resource{ 696 Mode: addrs.ManagedResourceMode, 697 Type: "test_instance", 698 Name: "foo", 699 }.Instance(addrs.NoKey).Absolute(subModule), 700 &states.ResourceInstanceObjectSrc{ 701 AttrsJSON: []byte(`{"id":"foo","foo":"value","bar":"value"}`), 702 Status: states.ObjectReady, 703 }, 704 addrs.AbsProviderConfig{ 705 Provider: addrs.NewDefaultProvider("test"), 706 Module: subModule.Module(), 707 }, 708 ) 709 }) 710 got, err := marshalRootModule(testState, testSchemas()) 711 712 if err != nil { 713 t.Fatalf("unexpected error: %s", err.Error()) 714 } 715 716 if len(got.ChildModules) != 1 { 717 t.Fatalf("wrong result! got %d modules, expected 1", len(got.ChildModules)) 718 } 719 720 if got.ChildModules[0].Address != "module.child" { 721 t.Fatalf("wrong result! got %#v\n", got) 722 } 723 724 if got.ChildModules[0].ChildModules[0].Address != "module.child.module.submodule" { 725 t.Fatalf("wrong result! got %#v\n", got) 726 } 727 } 728 729 func testSchemas() *terraform.Schemas { 730 return &terraform.Schemas{ 731 Providers: map[addrs.Provider]*terraform.ProviderSchema{ 732 addrs.NewDefaultProvider("test"): { 733 ResourceTypes: map[string]*configschema.Block{ 734 "test_thing": { 735 Attributes: map[string]*configschema.Attribute{ 736 "woozles": {Type: cty.String, Optional: true, Computed: true}, 737 "foozles": {Type: cty.String, Optional: true, Sensitive: true}, 738 }, 739 }, 740 "test_instance": { 741 Attributes: map[string]*configschema.Attribute{ 742 "id": {Type: cty.String, Optional: true, Computed: true}, 743 "foo": {Type: cty.String, Optional: true}, 744 "bar": {Type: cty.String, Optional: true}, 745 }, 746 }, 747 "test_map_attr": { 748 Attributes: map[string]*configschema.Attribute{ 749 "data": {Type: cty.Map(cty.String), Optional: true, Computed: true, Sensitive: true}, 750 }, 751 }, 752 }, 753 }, 754 }, 755 } 756 } 757 758 func TestSensitiveAsBool(t *testing.T) { 759 sensitive := "sensitive" 760 tests := []struct { 761 Input cty.Value 762 Want cty.Value 763 }{ 764 { 765 cty.StringVal("hello"), 766 cty.False, 767 }, 768 { 769 cty.NullVal(cty.String), 770 cty.False, 771 }, 772 { 773 cty.StringVal("hello").Mark(sensitive), 774 cty.True, 775 }, 776 { 777 cty.NullVal(cty.String).Mark(sensitive), 778 cty.True, 779 }, 780 781 { 782 cty.NullVal(cty.DynamicPseudoType).Mark(sensitive), 783 cty.True, 784 }, 785 { 786 cty.NullVal(cty.Object(map[string]cty.Type{"test": cty.String})), 787 cty.False, 788 }, 789 { 790 cty.NullVal(cty.Object(map[string]cty.Type{"test": cty.String})).Mark(sensitive), 791 cty.True, 792 }, 793 { 794 cty.DynamicVal, 795 cty.False, 796 }, 797 { 798 cty.DynamicVal.Mark(sensitive), 799 cty.True, 800 }, 801 802 { 803 cty.ListValEmpty(cty.String), 804 cty.EmptyTupleVal, 805 }, 806 { 807 cty.ListValEmpty(cty.String).Mark(sensitive), 808 cty.True, 809 }, 810 { 811 cty.ListVal([]cty.Value{ 812 cty.StringVal("hello"), 813 cty.StringVal("friend").Mark(sensitive), 814 }), 815 cty.TupleVal([]cty.Value{ 816 cty.False, 817 cty.True, 818 }), 819 }, 820 { 821 cty.SetValEmpty(cty.String), 822 cty.EmptyTupleVal, 823 }, 824 { 825 cty.SetValEmpty(cty.String).Mark(sensitive), 826 cty.True, 827 }, 828 { 829 cty.SetVal([]cty.Value{cty.StringVal("hello")}), 830 cty.TupleVal([]cty.Value{cty.False}), 831 }, 832 { 833 cty.SetVal([]cty.Value{cty.StringVal("hello").Mark(sensitive)}), 834 cty.True, 835 }, 836 { 837 cty.EmptyTupleVal.Mark(sensitive), 838 cty.True, 839 }, 840 { 841 cty.TupleVal([]cty.Value{ 842 cty.StringVal("hello"), 843 cty.StringVal("friend").Mark(sensitive), 844 }), 845 cty.TupleVal([]cty.Value{ 846 cty.False, 847 cty.True, 848 }), 849 }, 850 { 851 cty.MapValEmpty(cty.String), 852 cty.EmptyObjectVal, 853 }, 854 { 855 cty.MapValEmpty(cty.String).Mark(sensitive), 856 cty.True, 857 }, 858 { 859 cty.MapVal(map[string]cty.Value{ 860 "greeting": cty.StringVal("hello"), 861 "animal": cty.StringVal("horse"), 862 }), 863 cty.EmptyObjectVal, 864 }, 865 { 866 cty.MapVal(map[string]cty.Value{ 867 "greeting": cty.StringVal("hello"), 868 "animal": cty.StringVal("horse").Mark(sensitive), 869 }), 870 cty.ObjectVal(map[string]cty.Value{ 871 "animal": cty.True, 872 }), 873 }, 874 { 875 cty.MapVal(map[string]cty.Value{ 876 "greeting": cty.StringVal("hello"), 877 "animal": cty.StringVal("horse").Mark(sensitive), 878 }).Mark(sensitive), 879 cty.True, 880 }, 881 { 882 cty.EmptyObjectVal, 883 cty.EmptyObjectVal, 884 }, 885 { 886 cty.ObjectVal(map[string]cty.Value{ 887 "greeting": cty.StringVal("hello"), 888 "animal": cty.StringVal("horse"), 889 }), 890 cty.EmptyObjectVal, 891 }, 892 { 893 cty.ObjectVal(map[string]cty.Value{ 894 "greeting": cty.StringVal("hello"), 895 "animal": cty.StringVal("horse").Mark(sensitive), 896 }), 897 cty.ObjectVal(map[string]cty.Value{ 898 "animal": cty.True, 899 }), 900 }, 901 { 902 cty.ObjectVal(map[string]cty.Value{ 903 "greeting": cty.StringVal("hello"), 904 "animal": cty.StringVal("horse").Mark(sensitive), 905 }).Mark(sensitive), 906 cty.True, 907 }, 908 { 909 cty.ListVal([]cty.Value{ 910 cty.ObjectVal(map[string]cty.Value{ 911 "a": cty.UnknownVal(cty.String), 912 }), 913 cty.ObjectVal(map[string]cty.Value{ 914 "a": cty.StringVal("known").Mark(sensitive), 915 }), 916 }), 917 cty.TupleVal([]cty.Value{ 918 cty.EmptyObjectVal, 919 cty.ObjectVal(map[string]cty.Value{ 920 "a": cty.True, 921 }), 922 }), 923 }, 924 { 925 cty.ListVal([]cty.Value{ 926 cty.MapValEmpty(cty.String), 927 cty.MapVal(map[string]cty.Value{ 928 "a": cty.StringVal("known").Mark(sensitive), 929 }), 930 cty.MapVal(map[string]cty.Value{ 931 "a": cty.UnknownVal(cty.String), 932 }), 933 }), 934 cty.TupleVal([]cty.Value{ 935 cty.EmptyObjectVal, 936 cty.ObjectVal(map[string]cty.Value{ 937 "a": cty.True, 938 }), 939 cty.EmptyObjectVal, 940 }), 941 }, 942 { 943 cty.ObjectVal(map[string]cty.Value{ 944 "list": cty.UnknownVal(cty.List(cty.String)), 945 "set": cty.UnknownVal(cty.Set(cty.Bool)), 946 "tuple": cty.UnknownVal(cty.Tuple([]cty.Type{cty.String, cty.Number})), 947 "map": cty.UnknownVal(cty.Map(cty.String)), 948 "object": cty.UnknownVal(cty.Object(map[string]cty.Type{"a": cty.String})), 949 }), 950 cty.ObjectVal(map[string]cty.Value{ 951 "list": cty.EmptyTupleVal, 952 "set": cty.EmptyTupleVal, 953 "tuple": cty.EmptyTupleVal, 954 "map": cty.EmptyObjectVal, 955 "object": cty.EmptyObjectVal, 956 }), 957 }, 958 } 959 960 for _, test := range tests { 961 got := SensitiveAsBool(test.Input) 962 if !reflect.DeepEqual(got, test.Want) { 963 t.Errorf( 964 "wrong result\ninput: %#v\ngot: %#v\nwant: %#v", 965 test.Input, got, test.Want, 966 ) 967 } 968 } 969 }