github.com/hugorut/terraform@v1.1.3/src/terraform/context_import_test.go (about)

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