From 9ab9ef62914ef4d4e15e602ad7fcd008615a32c8 Mon Sep 17 00:00:00 2001 From: Alisdair McDiarmid Date: Tue, 23 Jun 2020 14:08:27 -0400 Subject: [PATCH] command/import: Fix allow-missing-config option We previously intentionally removed support for the allow-missing-config option to terraform import, requiring that all imported resources have matching config. See #24412. However, the option was not removed from the import command, and it is widely used. This commit reintroduces support for importing with a missing configuration by falling back to implying the provider FQN based on the resource type. --- command/import_test.go | 14 +++++------ terraform/context_import_test.go | 34 --------------------------- terraform/transform_import_state.go | 36 +++++++++++++---------------- 3 files changed, 23 insertions(+), 61 deletions(-) diff --git a/command/import_test.go b/command/import_test.go index d70e68504..67277c1ec 100644 --- a/command/import_test.go +++ b/command/import_test.go @@ -601,7 +601,7 @@ func TestImport_providerConfigWithVarFile(t *testing.T) { testStateOutput(t, statePath, testImportStr) } -func TestImport_disallowMissingResourceConfig(t *testing.T) { +func TestImport_allowMissingResourceConfig(t *testing.T) { defer testChdir(t, testFixturePath("import-missing-resource-config"))() statePath := testTempFile(t) @@ -643,15 +643,15 @@ func TestImport_disallowMissingResourceConfig(t *testing.T) { "bar", } - if code := c.Run(args); code != 1 { - t.Fatalf("import succeeded; expected failure") + if code := c.Run(args); code != 0 { + t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String()) } - msg := ui.ErrorWriter.String() - - if want := `Error: Resource test_instance.foo not found in the configuration.`; !strings.Contains(msg, want) { - t.Errorf("incorrect message\nwant substring: %s\ngot:\n%s", want, msg) + if !p.ImportResourceStateCalled { + t.Fatal("ImportResourceState should be called") } + + testStateOutput(t, statePath, testImportStr) } func TestImport_emptyConfig(t *testing.T) { diff --git a/terraform/context_import_test.go b/terraform/context_import_test.go index 938f65a74..2373ed27d 100644 --- a/terraform/context_import_test.go +++ b/terraform/context_import_test.go @@ -49,40 +49,6 @@ func TestContextImport_basic(t *testing.T) { } } -// Importing a resource which does not exist in the configuration results in an error -func TestContextImport_basic_errpr(t *testing.T) { - p := testProvider("aws") - m := testModule(t, "import-provider") - ctx := testContext2(t, &ContextOpts{ - Config: m, - Providers: map[addrs.Provider]providers.Factory{ - addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p), - }, - }) - - p.ImportStateReturn = []*InstanceState{ - &InstanceState{ - ID: "foo", - Ephemeral: EphemeralState{Type: "aws_instance"}, - }, - } - - _, diags := ctx.Import(&ImportOpts{ - Targets: []*ImportTarget{ - &ImportTarget{ - Addr: addrs.RootModuleInstance.ResourceInstance( - addrs.ManagedResourceMode, "aws_instance", "test", addrs.NoKey, - ), - ID: "bar", - }, - }, - }) - - if !diags.HasErrors() { - t.Fatal("should error") - } -} - func TestContextImport_countIndex(t *testing.T) { p := testProvider("aws") m := testModule(t, "import-provider") diff --git a/terraform/transform_import_state.go b/terraform/transform_import_state.go index 682161fba..158bbfe15 100644 --- a/terraform/transform_import_state.go +++ b/terraform/transform_import_state.go @@ -30,27 +30,23 @@ func (t *ImportStateTransformer) Transform(g *Graph) error { return fmt.Errorf("Module %s not found.", target.Addr.Module.Module()) } - // Get the resource config - rsCfg := modCfg.Module.ResourceByAddr(target.Addr.Resource.Resource) - if rsCfg == nil { - return fmt.Errorf("Resource %s not found in the configuration.", target.Addr) - } - - // Get the provider FQN for the resource from the resource configuration - providerFqn := rsCfg.Provider - - // This is only likely to happen in misconfigured tests. - if rsCfg == nil { - return fmt.Errorf("provider for resource %s not found in the configuration.", target.Addr) - } - - // Get the provider local config for the resource - localpCfg := rsCfg.ProviderConfigAddr() - providerAddr := addrs.AbsProviderConfig{ - Provider: providerFqn, - Alias: localpCfg.Alias, - Module: target.Addr.Module.Module(), + Module: target.Addr.Module.Module(), + } + + // Try to find the resource config + rsCfg := modCfg.Module.ResourceByAddr(target.Addr.Resource.Resource) + if rsCfg != nil { + // Get the provider FQN for the resource from the resource configuration + providerAddr.Provider = rsCfg.Provider + + // Get the alias from the resource's provider local config + providerAddr.Alias = rsCfg.ProviderConfigAddr().Alias + } else { + // Resource has no matching config, so use an implied provider + // based on the resource type + rsProviderType := target.Addr.Resource.Resource.ImpliedProvider() + providerAddr.Provider = modCfg.Module.ImpliedProviderForUnqualifiedType(rsProviderType) } node := &graphNodeImportState{