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