github.com/kanishk98/terraform@v1.3.0-dev.0.20220917174235-661ca8088a6a/internal/terraform/context_import_test.go (about) 1 package terraform 2 3 import ( 4 "errors" 5 "strings" 6 "testing" 7 8 "github.com/hashicorp/terraform/internal/addrs" 9 "github.com/hashicorp/terraform/internal/configs/configschema" 10 "github.com/hashicorp/terraform/internal/providers" 11 "github.com/hashicorp/terraform/internal/states" 12 "github.com/zclconf/go-cty/cty" 13 ) 14 15 func TestContextImport_basic(t *testing.T) { 16 p := testProvider("aws") 17 m := testModule(t, "import-provider") 18 ctx := testContext2(t, &ContextOpts{ 19 Providers: map[addrs.Provider]providers.Factory{ 20 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 21 }, 22 }) 23 24 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 25 ImportedResources: []providers.ImportedResource{ 26 { 27 TypeName: "aws_instance", 28 State: cty.ObjectVal(map[string]cty.Value{ 29 "id": cty.StringVal("foo"), 30 }), 31 }, 32 }, 33 } 34 35 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 36 Targets: []*ImportTarget{ 37 { 38 Addr: addrs.RootModuleInstance.ResourceInstance( 39 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 40 ), 41 ID: "bar", 42 }, 43 }, 44 }) 45 if diags.HasErrors() { 46 t.Fatalf("unexpected errors: %s", diags.Err()) 47 } 48 actual := strings.TrimSpace(state.String()) 49 expected := strings.TrimSpace(testImportStr) 50 if actual != expected { 51 t.Fatalf("wrong final state\ngot:\n%s\nwant:\n%s", actual, expected) 52 } 53 } 54 55 // import 1 of count instances in the configuration 56 func TestContextImport_countIndex(t *testing.T) { 57 p := testProvider("aws") 58 m := testModuleInline(t, map[string]string{ 59 "main.tf": ` 60 provider "aws" { 61 foo = "bar" 62 } 63 64 resource "aws_instance" "foo" { 65 count = 2 66 } 67 `}) 68 69 ctx := testContext2(t, &ContextOpts{ 70 Providers: map[addrs.Provider]providers.Factory{ 71 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 72 }, 73 }) 74 75 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 76 ImportedResources: []providers.ImportedResource{ 77 { 78 TypeName: "aws_instance", 79 State: cty.ObjectVal(map[string]cty.Value{ 80 "id": cty.StringVal("foo"), 81 }), 82 }, 83 }, 84 } 85 86 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 87 Targets: []*ImportTarget{ 88 { 89 Addr: addrs.RootModuleInstance.ResourceInstance( 90 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.IntKey(0), 91 ), 92 ID: "bar", 93 }, 94 }, 95 }) 96 if diags.HasErrors() { 97 t.Fatalf("unexpected errors: %s", diags.Err()) 98 } 99 100 actual := strings.TrimSpace(state.String()) 101 expected := strings.TrimSpace(testImportCountIndexStr) 102 if actual != expected { 103 t.Fatalf("bad: \n%s", actual) 104 } 105 } 106 107 func TestContextImport_collision(t *testing.T) { 108 p := testProvider("aws") 109 m := testModule(t, "import-provider") 110 ctx := testContext2(t, &ContextOpts{ 111 Providers: map[addrs.Provider]providers.Factory{ 112 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 113 }, 114 }) 115 116 state := states.BuildState(func(s *states.SyncState) { 117 s.SetResourceInstanceCurrent( 118 addrs.Resource{ 119 Mode: addrs.ManagedResourceMode, 120 Type: "aws_instance", 121 Name: "foo", 122 }.Instance(addrs.NoKey).Absolute(addrs.RootModuleInstance), 123 &states.ResourceInstanceObjectSrc{ 124 AttrsFlat: map[string]string{ 125 "id": "bar", 126 }, 127 Status: states.ObjectReady, 128 }, 129 addrs.AbsProviderConfig{ 130 Provider: addrs.NewDefaultProvider("aws"), 131 Module: addrs.RootModule, 132 }, 133 ) 134 }) 135 136 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 137 ImportedResources: []providers.ImportedResource{ 138 { 139 TypeName: "aws_instance", 140 State: cty.ObjectVal(map[string]cty.Value{ 141 "id": cty.StringVal("foo"), 142 }), 143 }, 144 }, 145 } 146 147 state, diags := ctx.Import(m, state, &ImportOpts{ 148 Targets: []*ImportTarget{ 149 { 150 Addr: addrs.RootModuleInstance.ResourceInstance( 151 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 152 ), 153 ID: "bar", 154 }, 155 }, 156 }) 157 if !diags.HasErrors() { 158 t.Fatalf("succeeded; want an error indicating that the resource already exists in state") 159 } 160 161 actual := strings.TrimSpace(state.String()) 162 expected := `aws_instance.foo: 163 ID = bar 164 provider = provider["registry.terraform.io/hashicorp/aws"]` 165 166 if actual != expected { 167 t.Fatalf("bad: \n%s", actual) 168 } 169 } 170 171 func TestContextImport_missingType(t *testing.T) { 172 p := testProvider("aws") 173 m := testModule(t, "import-provider") 174 175 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 176 ImportedResources: []providers.ImportedResource{ 177 { 178 State: cty.ObjectVal(map[string]cty.Value{ 179 "id": cty.StringVal("foo"), 180 }), 181 }, 182 }, 183 } 184 185 ctx := testContext2(t, &ContextOpts{ 186 Providers: map[addrs.Provider]providers.Factory{ 187 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 188 }, 189 }) 190 191 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 192 Targets: []*ImportTarget{ 193 { 194 Addr: addrs.RootModuleInstance.ResourceInstance( 195 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 196 ), 197 ID: "bar", 198 }, 199 }, 200 }) 201 if !diags.HasErrors() { 202 t.Fatal("should error") 203 } 204 205 actual := strings.TrimSpace(state.String()) 206 expected := "<no state>" 207 if actual != expected { 208 t.Fatalf("bad: \n%s", actual) 209 } 210 } 211 212 func TestContextImport_moduleProvider(t *testing.T) { 213 p := testProvider("aws") 214 215 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 216 ImportedResources: []providers.ImportedResource{ 217 { 218 TypeName: "aws_instance", 219 State: cty.ObjectVal(map[string]cty.Value{ 220 "id": cty.StringVal("foo"), 221 }), 222 }, 223 }, 224 } 225 226 p.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) (resp providers.ConfigureProviderResponse) { 227 foo := req.Config.GetAttr("foo").AsString() 228 if foo != "bar" { 229 resp.Diagnostics = resp.Diagnostics.Append(errors.New("not bar")) 230 } 231 232 return 233 } 234 235 m := testModule(t, "import-provider") 236 ctx := testContext2(t, &ContextOpts{ 237 Providers: map[addrs.Provider]providers.Factory{ 238 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 239 }, 240 }) 241 242 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 243 Targets: []*ImportTarget{ 244 { 245 Addr: addrs.RootModuleInstance.ResourceInstance( 246 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 247 ), 248 ID: "bar", 249 }, 250 }, 251 }) 252 if diags.HasErrors() { 253 t.Fatalf("unexpected errors: %s", diags.Err()) 254 } 255 256 if !p.ConfigureProviderCalled { 257 t.Fatal("didn't configure provider") 258 } 259 260 actual := strings.TrimSpace(state.String()) 261 expected := strings.TrimSpace(testImportStr) 262 if actual != expected { 263 t.Fatalf("expected:\n%s\n\ngot:\n%s", expected, actual) 264 } 265 } 266 267 // Importing into a module requires a provider config in that module. 268 func TestContextImport_providerModule(t *testing.T) { 269 p := testProvider("aws") 270 m := testModule(t, "import-module") 271 ctx := testContext2(t, &ContextOpts{ 272 Providers: map[addrs.Provider]providers.Factory{ 273 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 274 }, 275 }) 276 277 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 278 ImportedResources: []providers.ImportedResource{ 279 { 280 TypeName: "aws_instance", 281 State: cty.ObjectVal(map[string]cty.Value{ 282 "id": cty.StringVal("foo"), 283 }), 284 }, 285 }, 286 } 287 288 p.ConfigureProviderFn = func(req providers.ConfigureProviderRequest) (resp providers.ConfigureProviderResponse) { 289 foo := req.Config.GetAttr("foo").AsString() 290 if foo != "bar" { 291 resp.Diagnostics = resp.Diagnostics.Append(errors.New("not bar")) 292 } 293 294 return 295 } 296 297 _, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 298 Targets: []*ImportTarget{ 299 { 300 Addr: addrs.RootModuleInstance.Child("child", addrs.NoKey).ResourceInstance( 301 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 302 ), 303 ID: "bar", 304 }, 305 }, 306 }) 307 if diags.HasErrors() { 308 t.Fatalf("unexpected errors: %s", diags.Err()) 309 } 310 311 if !p.ConfigureProviderCalled { 312 t.Fatal("didn't configure provider") 313 } 314 } 315 316 // Test that import will interpolate provider configuration and use 317 // that configuration for import. 318 func TestContextImport_providerConfig(t *testing.T) { 319 testCases := map[string]struct { 320 module string 321 value string 322 }{ 323 "variables": { 324 module: "import-provider-vars", 325 value: "bar", 326 }, 327 "locals": { 328 module: "import-provider-locals", 329 value: "baz-bar", 330 }, 331 } 332 for name, test := range testCases { 333 t.Run(name, func(t *testing.T) { 334 p := testProvider("aws") 335 m := testModule(t, test.module) 336 ctx := testContext2(t, &ContextOpts{ 337 Providers: map[addrs.Provider]providers.Factory{ 338 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 339 }, 340 }) 341 342 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 343 ImportedResources: []providers.ImportedResource{ 344 { 345 TypeName: "aws_instance", 346 State: cty.ObjectVal(map[string]cty.Value{ 347 "id": cty.StringVal("foo"), 348 }), 349 }, 350 }, 351 } 352 353 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 354 Targets: []*ImportTarget{ 355 { 356 Addr: addrs.RootModuleInstance.ResourceInstance( 357 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 358 ), 359 ID: "bar", 360 }, 361 }, 362 SetVariables: InputValues{ 363 "foo": &InputValue{ 364 Value: cty.StringVal("bar"), 365 SourceType: ValueFromCaller, 366 }, 367 }, 368 }) 369 if diags.HasErrors() { 370 t.Fatalf("unexpected errors: %s", diags.Err()) 371 } 372 373 if !p.ConfigureProviderCalled { 374 t.Fatal("didn't configure provider") 375 } 376 377 if foo := p.ConfigureProviderRequest.Config.GetAttr("foo").AsString(); foo != test.value { 378 t.Fatalf("bad value %#v; want %#v", foo, test.value) 379 } 380 381 actual := strings.TrimSpace(state.String()) 382 expected := strings.TrimSpace(testImportStr) 383 if actual != expected { 384 t.Fatalf("bad: \n%s", actual) 385 } 386 }) 387 } 388 } 389 390 // Test that provider configs can't reference resources. 391 func TestContextImport_providerConfigResources(t *testing.T) { 392 p := testProvider("aws") 393 pTest := testProvider("test") 394 m := testModule(t, "import-provider-resources") 395 ctx := testContext2(t, &ContextOpts{ 396 Providers: map[addrs.Provider]providers.Factory{ 397 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 398 addrs.NewDefaultProvider("test"): testProviderFuncFixed(pTest), 399 }, 400 }) 401 402 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 403 ImportedResources: []providers.ImportedResource{ 404 { 405 TypeName: "aws_instance", 406 State: cty.ObjectVal(map[string]cty.Value{ 407 "id": cty.StringVal("foo"), 408 }), 409 }, 410 }, 411 } 412 413 _, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 414 Targets: []*ImportTarget{ 415 { 416 Addr: addrs.RootModuleInstance.ResourceInstance( 417 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 418 ), 419 ID: "bar", 420 }, 421 }, 422 }) 423 if !diags.HasErrors() { 424 t.Fatal("should error") 425 } 426 if got, want := diags.Err().Error(), `The configuration for provider["registry.terraform.io/hashicorp/aws"] depends on values that cannot be determined until apply.`; !strings.Contains(got, want) { 427 t.Errorf("wrong error\n got: %s\nwant: %s", got, want) 428 } 429 } 430 431 func TestContextImport_refresh(t *testing.T) { 432 p := testProvider("aws") 433 m := testModule(t, "import-provider") 434 ctx := testContext2(t, &ContextOpts{ 435 Providers: map[addrs.Provider]providers.Factory{ 436 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 437 }, 438 }) 439 440 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 441 ImportedResources: []providers.ImportedResource{ 442 { 443 TypeName: "aws_instance", 444 State: cty.ObjectVal(map[string]cty.Value{ 445 "id": cty.StringVal("foo"), 446 }), 447 }, 448 }, 449 } 450 451 p.ReadResourceFn = nil 452 453 p.ReadResourceResponse = &providers.ReadResourceResponse{ 454 NewState: cty.ObjectVal(map[string]cty.Value{ 455 "id": cty.StringVal("foo"), 456 "foo": cty.StringVal("bar"), 457 }), 458 } 459 460 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 461 Targets: []*ImportTarget{ 462 { 463 Addr: addrs.RootModuleInstance.ResourceInstance( 464 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 465 ), 466 ID: "bar", 467 }, 468 }, 469 }) 470 if diags.HasErrors() { 471 t.Fatalf("unexpected errors: %s", diags.Err()) 472 } 473 474 actual := strings.TrimSpace(state.String()) 475 expected := strings.TrimSpace(testImportRefreshStr) 476 if actual != expected { 477 t.Fatalf("bad: \n%s", actual) 478 } 479 } 480 481 func TestContextImport_refreshNil(t *testing.T) { 482 p := testProvider("aws") 483 m := testModule(t, "import-provider") 484 ctx := testContext2(t, &ContextOpts{ 485 Providers: map[addrs.Provider]providers.Factory{ 486 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 487 }, 488 }) 489 490 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 491 ImportedResources: []providers.ImportedResource{ 492 { 493 TypeName: "aws_instance", 494 State: cty.ObjectVal(map[string]cty.Value{ 495 "id": cty.StringVal("foo"), 496 }), 497 }, 498 }, 499 } 500 501 p.ReadResourceFn = func(req providers.ReadResourceRequest) providers.ReadResourceResponse { 502 return providers.ReadResourceResponse{ 503 NewState: cty.NullVal(cty.DynamicPseudoType), 504 } 505 } 506 507 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 508 Targets: []*ImportTarget{ 509 { 510 Addr: addrs.RootModuleInstance.ResourceInstance( 511 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 512 ), 513 ID: "bar", 514 }, 515 }, 516 }) 517 if !diags.HasErrors() { 518 t.Fatal("should error") 519 } 520 521 actual := strings.TrimSpace(state.String()) 522 expected := "<no state>" 523 if actual != expected { 524 t.Fatalf("bad: \n%s", actual) 525 } 526 } 527 528 func TestContextImport_module(t *testing.T) { 529 p := testProvider("aws") 530 m := testModule(t, "import-module") 531 ctx := testContext2(t, &ContextOpts{ 532 Providers: map[addrs.Provider]providers.Factory{ 533 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 534 }, 535 }) 536 537 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 538 ImportedResources: []providers.ImportedResource{ 539 { 540 TypeName: "aws_instance", 541 State: cty.ObjectVal(map[string]cty.Value{ 542 "id": cty.StringVal("foo"), 543 }), 544 }, 545 }, 546 } 547 548 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 549 Targets: []*ImportTarget{ 550 { 551 Addr: addrs.RootModuleInstance.Child("child", addrs.IntKey(0)).ResourceInstance( 552 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 553 ), 554 ID: "bar", 555 }, 556 }, 557 }) 558 if diags.HasErrors() { 559 t.Fatalf("unexpected errors: %s", diags.Err()) 560 } 561 562 actual := strings.TrimSpace(state.String()) 563 expected := strings.TrimSpace(testImportModuleStr) 564 if actual != expected { 565 t.Fatalf("bad: \n%s", actual) 566 } 567 } 568 569 func TestContextImport_moduleDepth2(t *testing.T) { 570 p := testProvider("aws") 571 m := testModule(t, "import-module") 572 ctx := testContext2(t, &ContextOpts{ 573 Providers: map[addrs.Provider]providers.Factory{ 574 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 575 }, 576 }) 577 578 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 579 ImportedResources: []providers.ImportedResource{ 580 { 581 TypeName: "aws_instance", 582 State: cty.ObjectVal(map[string]cty.Value{ 583 "id": cty.StringVal("foo"), 584 }), 585 }, 586 }, 587 } 588 589 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 590 Targets: []*ImportTarget{ 591 { 592 Addr: addrs.RootModuleInstance.Child("child", addrs.IntKey(0)).Child("nested", addrs.NoKey).ResourceInstance( 593 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 594 ), 595 ID: "baz", 596 }, 597 }, 598 }) 599 if diags.HasErrors() { 600 t.Fatalf("unexpected errors: %s", diags.Err()) 601 } 602 603 actual := strings.TrimSpace(state.String()) 604 expected := strings.TrimSpace(testImportModuleDepth2Str) 605 if actual != expected { 606 t.Fatalf("bad: \n%s", actual) 607 } 608 } 609 610 func TestContextImport_moduleDiff(t *testing.T) { 611 p := testProvider("aws") 612 m := testModule(t, "import-module") 613 ctx := testContext2(t, &ContextOpts{ 614 Providers: map[addrs.Provider]providers.Factory{ 615 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 616 }, 617 }) 618 619 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 620 ImportedResources: []providers.ImportedResource{ 621 { 622 TypeName: "aws_instance", 623 State: cty.ObjectVal(map[string]cty.Value{ 624 "id": cty.StringVal("foo"), 625 }), 626 }, 627 }, 628 } 629 630 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 631 Targets: []*ImportTarget{ 632 { 633 Addr: addrs.RootModuleInstance.Child("child", addrs.IntKey(0)).ResourceInstance( 634 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 635 ), 636 ID: "baz", 637 }, 638 }, 639 }) 640 if diags.HasErrors() { 641 t.Fatalf("unexpected errors: %s", diags.Err()) 642 } 643 644 actual := strings.TrimSpace(state.String()) 645 expected := strings.TrimSpace(testImportModuleStr) 646 if actual != expected { 647 t.Fatalf("\nexpected: %q\ngot: %q\n", expected, actual) 648 } 649 } 650 651 func TestContextImport_multiState(t *testing.T) { 652 p := testProvider("aws") 653 m := testModule(t, "import-provider") 654 655 p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(&ProviderSchema{ 656 Provider: &configschema.Block{ 657 Attributes: map[string]*configschema.Attribute{ 658 "foo": {Type: cty.String, Optional: true}, 659 }, 660 }, 661 ResourceTypes: map[string]*configschema.Block{ 662 "aws_instance": { 663 Attributes: map[string]*configschema.Attribute{ 664 "id": {Type: cty.String, Computed: true}, 665 }, 666 }, 667 "aws_instance_thing": { 668 Attributes: map[string]*configschema.Attribute{ 669 "id": {Type: cty.String, Computed: true}, 670 }, 671 }, 672 }, 673 }) 674 675 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 676 ImportedResources: []providers.ImportedResource{ 677 { 678 TypeName: "aws_instance", 679 State: cty.ObjectVal(map[string]cty.Value{ 680 "id": cty.StringVal("foo"), 681 }), 682 }, 683 { 684 TypeName: "aws_instance_thing", 685 State: cty.ObjectVal(map[string]cty.Value{ 686 "id": cty.StringVal("bar"), 687 }), 688 }, 689 }, 690 } 691 692 ctx := testContext2(t, &ContextOpts{ 693 Providers: map[addrs.Provider]providers.Factory{ 694 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 695 }, 696 }) 697 698 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 699 Targets: []*ImportTarget{ 700 { 701 Addr: addrs.RootModuleInstance.ResourceInstance( 702 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 703 ), 704 ID: "bar", 705 }, 706 }, 707 }) 708 if diags.HasErrors() { 709 t.Fatalf("unexpected errors: %s", diags.Err()) 710 } 711 712 actual := strings.TrimSpace(state.String()) 713 expected := strings.TrimSpace(testImportMultiStr) 714 if actual != expected { 715 t.Fatalf("bad: \n%s", actual) 716 } 717 } 718 719 func TestContextImport_multiStateSame(t *testing.T) { 720 p := testProvider("aws") 721 m := testModule(t, "import-provider") 722 723 p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(&ProviderSchema{ 724 Provider: &configschema.Block{ 725 Attributes: map[string]*configschema.Attribute{ 726 "foo": {Type: cty.String, Optional: true}, 727 }, 728 }, 729 ResourceTypes: map[string]*configschema.Block{ 730 "aws_instance": { 731 Attributes: map[string]*configschema.Attribute{ 732 "id": {Type: cty.String, Computed: true}, 733 }, 734 }, 735 "aws_instance_thing": { 736 Attributes: map[string]*configschema.Attribute{ 737 "id": {Type: cty.String, Computed: true}, 738 }, 739 }, 740 }, 741 }) 742 743 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 744 ImportedResources: []providers.ImportedResource{ 745 { 746 TypeName: "aws_instance", 747 State: cty.ObjectVal(map[string]cty.Value{ 748 "id": cty.StringVal("foo"), 749 }), 750 }, 751 { 752 TypeName: "aws_instance_thing", 753 State: cty.ObjectVal(map[string]cty.Value{ 754 "id": cty.StringVal("bar"), 755 }), 756 }, 757 { 758 TypeName: "aws_instance_thing", 759 State: cty.ObjectVal(map[string]cty.Value{ 760 "id": cty.StringVal("qux"), 761 }), 762 }, 763 }, 764 } 765 766 ctx := testContext2(t, &ContextOpts{ 767 Providers: map[addrs.Provider]providers.Factory{ 768 addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), 769 }, 770 }) 771 772 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 773 Targets: []*ImportTarget{ 774 { 775 Addr: addrs.RootModuleInstance.ResourceInstance( 776 addrs.ManagedResourceMode, "aws_instance", "foo", addrs.NoKey, 777 ), 778 ID: "bar", 779 }, 780 }, 781 }) 782 if diags.HasErrors() { 783 t.Fatalf("unexpected errors: %s", diags.Err()) 784 } 785 786 actual := strings.TrimSpace(state.String()) 787 expected := strings.TrimSpace(testImportMultiSameStr) 788 if actual != expected { 789 t.Fatalf("bad: \n%s", actual) 790 } 791 } 792 793 func TestContextImport_nestedModuleImport(t *testing.T) { 794 p := testProvider("aws") 795 m := testModuleInline(t, map[string]string{ 796 "main.tf": ` 797 locals { 798 xs = toset(["foo"]) 799 } 800 801 module "a" { 802 for_each = local.xs 803 source = "./a" 804 } 805 806 module "b" { 807 for_each = local.xs 808 source = "./b" 809 y = module.a[each.key].y 810 } 811 812 resource "test_resource" "test" { 813 } 814 `, 815 "a/main.tf": ` 816 output "y" { 817 value = "bar" 818 } 819 `, 820 "b/main.tf": ` 821 variable "y" { 822 type = string 823 } 824 825 resource "test_resource" "unused" { 826 value = var.y 827 // missing required, but should not error 828 } 829 `, 830 }) 831 832 p.GetProviderSchemaResponse = getProviderSchemaResponseFromProviderSchema(&ProviderSchema{ 833 Provider: &configschema.Block{ 834 Attributes: map[string]*configschema.Attribute{ 835 "foo": {Type: cty.String, Optional: true}, 836 }, 837 }, 838 ResourceTypes: map[string]*configschema.Block{ 839 "test_resource": { 840 Attributes: map[string]*configschema.Attribute{ 841 "id": {Type: cty.String, Computed: true}, 842 "required": {Type: cty.String, Required: true}, 843 }, 844 }, 845 }, 846 }) 847 848 p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{ 849 ImportedResources: []providers.ImportedResource{ 850 { 851 TypeName: "test_resource", 852 State: cty.ObjectVal(map[string]cty.Value{ 853 "id": cty.StringVal("test"), 854 "required": cty.StringVal("value"), 855 }), 856 }, 857 }, 858 } 859 860 ctx := testContext2(t, &ContextOpts{ 861 Providers: map[addrs.Provider]providers.Factory{ 862 addrs.NewDefaultProvider("test"): testProviderFuncFixed(p), 863 }, 864 }) 865 866 state, diags := ctx.Import(m, states.NewState(), &ImportOpts{ 867 Targets: []*ImportTarget{ 868 { 869 Addr: addrs.RootModuleInstance.ResourceInstance( 870 addrs.ManagedResourceMode, "test_resource", "test", addrs.NoKey, 871 ), 872 ID: "test", 873 }, 874 }, 875 }) 876 if diags.HasErrors() { 877 t.Fatal(diags.ErrWithWarnings()) 878 } 879 880 ri := state.ResourceInstance(mustResourceInstanceAddr("test_resource.test")) 881 expected := `{"id":"test","required":"value"}` 882 if ri == nil || ri.Current == nil { 883 t.Fatal("no state is recorded for resource instance test_resource.test") 884 } 885 if string(ri.Current.AttrsJSON) != expected { 886 t.Fatalf("expected %q, got %q\n", expected, ri.Current.AttrsJSON) 887 } 888 } 889 890 const testImportStr = ` 891 aws_instance.foo: 892 ID = foo 893 provider = provider["registry.terraform.io/hashicorp/aws"] 894 ` 895 896 const testImportCountIndexStr = ` 897 aws_instance.foo.0: 898 ID = foo 899 provider = provider["registry.terraform.io/hashicorp/aws"] 900 ` 901 902 const testImportModuleStr = ` 903 <no state> 904 module.child[0]: 905 aws_instance.foo: 906 ID = foo 907 provider = provider["registry.terraform.io/hashicorp/aws"] 908 ` 909 910 const testImportModuleDepth2Str = ` 911 <no state> 912 module.child[0].nested: 913 aws_instance.foo: 914 ID = foo 915 provider = provider["registry.terraform.io/hashicorp/aws"] 916 ` 917 918 const testImportMultiStr = ` 919 aws_instance.foo: 920 ID = foo 921 provider = provider["registry.terraform.io/hashicorp/aws"] 922 aws_instance_thing.foo: 923 ID = bar 924 provider = provider["registry.terraform.io/hashicorp/aws"] 925 ` 926 927 const testImportMultiSameStr = ` 928 aws_instance.foo: 929 ID = foo 930 provider = provider["registry.terraform.io/hashicorp/aws"] 931 aws_instance_thing.foo: 932 ID = bar 933 provider = provider["registry.terraform.io/hashicorp/aws"] 934 aws_instance_thing.foo-1: 935 ID = qux 936 provider = provider["registry.terraform.io/hashicorp/aws"] 937 ` 938 939 const testImportRefreshStr = ` 940 aws_instance.foo: 941 ID = foo 942 provider = provider["registry.terraform.io/hashicorp/aws"] 943 foo = bar 944 `