Skip to content

Commit 77e6b62

Browse files
authored
Merge pull request #31283 from hashicorp/jbardin/plan-import
Use plan graph for importing resources
2 parents a5f307b + 142ce15 commit 77e6b62

20 files changed

+167
-396
lines changed

internal/command/import.go

Lines changed: 1 addition & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,6 @@ func (c *ImportCommand) Run(args []string) int {
4545
cmdFlags.StringVar(&configPath, "config", pwd, "path")
4646
cmdFlags.BoolVar(&c.Meta.stateLock, "lock", true, "lock state")
4747
cmdFlags.DurationVar(&c.Meta.stateLockTimeout, "lock-timeout", 0, "lock timeout")
48-
cmdFlags.BoolVar(&c.Meta.allowMissingConfig, "allow-missing-config", false, "allow missing config")
4948
cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
5049
if err := cmdFlags.Parse(args); err != nil {
5150
return 1
@@ -135,7 +134,7 @@ func (c *ImportCommand) Run(args []string) int {
135134
break
136135
}
137136
}
138-
if !c.Meta.allowMissingConfig && rc == nil {
137+
if rc == nil {
139138
modulePath := addr.Module.String()
140139
if modulePath == "" {
141140
modulePath = "the root module"
@@ -262,10 +261,6 @@ func (c *ImportCommand) Run(args []string) int {
262261

263262
c.Ui.Output(c.Colorize().Color("[reset][green]\n" + importCommandSuccessMsg))
264263

265-
if c.Meta.allowMissingConfig && rc == nil {
266-
c.Ui.Output(c.Colorize().Color("[reset][yellow]\n" + importCommandAllowMissingResourceMsg))
267-
}
268-
269264
c.showDiagnostics(diags)
270265
if diags.HasErrors() {
271266
return 1
@@ -310,8 +305,6 @@ Options:
310305
If no config files are present, they must be provided
311306
via the input prompts or env vars.
312307
313-
-allow-missing-config Allow import when no resource configuration block exists.
314-
315308
-input=false Disable interactive input prompts.
316309
317310
-lock=false Don't hold a state lock during the operation. This is
@@ -361,12 +354,3 @@ const importCommandSuccessMsg = `Import successful!
361354
The resources that were imported are shown above. These resources are now in
362355
your Terraform state and will henceforth be managed by Terraform.
363356
`
364-
365-
const importCommandAllowMissingResourceMsg = `Import does not generate resource configuration, you must create a resource
366-
configuration block that matches the current or desired state manually.
367-
368-
If there is no matching resource configuration block for the imported
369-
resource, Terraform will delete the resource on the next "terraform apply".
370-
It is recommended that you run "terraform plan" to verify that the
371-
configuration is correct and complete.
372-
`

internal/command/import_test.go

Lines changed: 0 additions & 57 deletions
Original file line numberDiff line numberDiff line change
@@ -644,63 +644,6 @@ func TestImport_providerConfigWithVarFile(t *testing.T) {
644644
testStateOutput(t, statePath, testImportStr)
645645
}
646646

647-
func TestImport_allowMissingResourceConfig(t *testing.T) {
648-
defer testChdir(t, testFixturePath("import-missing-resource-config"))()
649-
650-
statePath := testTempFile(t)
651-
652-
p := testProvider()
653-
ui := new(cli.MockUi)
654-
view, _ := testView(t)
655-
c := &ImportCommand{
656-
Meta: Meta{
657-
testingOverrides: metaOverridesForProvider(p),
658-
Ui: ui,
659-
View: view,
660-
},
661-
}
662-
663-
p.ImportResourceStateFn = nil
664-
p.ImportResourceStateResponse = &providers.ImportResourceStateResponse{
665-
ImportedResources: []providers.ImportedResource{
666-
{
667-
TypeName: "test_instance",
668-
State: cty.ObjectVal(map[string]cty.Value{
669-
"id": cty.StringVal("yay"),
670-
}),
671-
},
672-
},
673-
}
674-
p.GetProviderSchemaResponse = &providers.GetProviderSchemaResponse{
675-
ResourceTypes: map[string]providers.Schema{
676-
"test_instance": {
677-
Block: &configschema.Block{
678-
Attributes: map[string]*configschema.Attribute{
679-
"id": {Type: cty.String, Optional: true, Computed: true},
680-
},
681-
},
682-
},
683-
},
684-
}
685-
686-
args := []string{
687-
"-state", statePath,
688-
"-allow-missing-config",
689-
"test_instance.foo",
690-
"bar",
691-
}
692-
693-
if code := c.Run(args); code != 0 {
694-
t.Fatalf("bad: %d\n\n%s", code, ui.ErrorWriter.String())
695-
}
696-
697-
if !p.ImportResourceStateCalled {
698-
t.Fatal("ImportResourceState should be called")
699-
}
700-
701-
testStateOutput(t, statePath, testImportStr)
702-
}
703-
704647
func TestImport_emptyConfig(t *testing.T) {
705648
defer testChdir(t, testFixturePath("empty"))()
706649

internal/command/meta.go

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -231,9 +231,6 @@ type Meta struct {
231231
migrateState bool
232232
compactWarnings bool
233233

234-
// Used with the import command to allow import of state when no matching config exists.
235-
allowMissingConfig bool
236-
237234
// Used with commands which write state to allow users to write remote
238235
// state even if the remote and local Terraform versions don't match.
239236
ignoreRemoteVersion bool

internal/command/meta_backend_migrate_test.go

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,6 @@
11
package command
22

33
import (
4-
"fmt"
54
"testing"
65
)
76

@@ -37,7 +36,7 @@ func TestBackendMigrate_promptMultiStatePattern(t *testing.T) {
3736
},
3837
}
3938
for name, tc := range cases {
40-
fmt.Println("Test: ", name)
39+
t.Log("Test: ", name)
4140
m := testMetaBackend(t, nil)
4241
input := map[string]string{}
4342
cleanup := testInputMap(t, input)

internal/terraform/context_import.go

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,11 +56,13 @@ func (c *Context) Import(config *configs.Config, prevRunState *states.State, opt
5656
variables := opts.SetVariables
5757

5858
// Initialize our graph builder
59-
builder := &ImportGraphBuilder{
59+
builder := &PlanGraphBuilder{
6060
ImportTargets: opts.Targets,
6161
Config: config,
62+
State: state,
6263
RootVariableValues: variables,
6364
Plugins: c.plugins,
65+
Operation: walkImport,
6466
}
6567

6668
// Build the graph

internal/terraform/context_import_test.go

Lines changed: 22 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -52,9 +52,20 @@ func TestContextImport_basic(t *testing.T) {
5252
}
5353
}
5454

55+
// import 1 of count instances in the configuration
5556
func TestContextImport_countIndex(t *testing.T) {
5657
p := testProvider("aws")
57-
m := testModule(t, "import-provider")
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+
5869
ctx := testContext2(t, &ContextOpts{
5970
Providers: map[addrs.Provider]providers.Factory{
6071
addrs.NewDefaultProvider("aws"): testProviderFuncFixed(p),
@@ -779,7 +790,7 @@ func TestContextImport_multiStateSame(t *testing.T) {
779790
}
780791
}
781792

782-
func TestContextImport_noConfigModuleImport(t *testing.T) {
793+
func TestContextImport_nestedModuleImport(t *testing.T) {
783794
p := testProvider("aws")
784795
m := testModuleInline(t, map[string]string{
785796
"main.tf": `
@@ -797,6 +808,9 @@ module "b" {
797808
source = "./b"
798809
y = module.a[each.key].y
799810
}
811+
812+
resource "test_resource" "test" {
813+
}
800814
`,
801815
"a/main.tf": `
802816
output "y" {
@@ -810,6 +824,7 @@ variable "y" {
810824
811825
resource "test_resource" "unused" {
812826
value = var.y
827+
// missing required, but should not error
813828
}
814829
`,
815830
})
@@ -823,7 +838,8 @@ resource "test_resource" "unused" {
823838
ResourceTypes: map[string]*configschema.Block{
824839
"test_resource": {
825840
Attributes: map[string]*configschema.Attribute{
826-
"id": {Type: cty.String, Computed: true},
841+
"id": {Type: cty.String, Computed: true},
842+
"required": {Type: cty.String, Required: true},
827843
},
828844
},
829845
},
@@ -834,17 +850,8 @@ resource "test_resource" "unused" {
834850
{
835851
TypeName: "test_resource",
836852
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"),
853+
"id": cty.StringVal("test"),
854+
"required": cty.StringVal("value"),
848855
}),
849856
},
850857
},
@@ -871,7 +878,7 @@ resource "test_resource" "unused" {
871878
}
872879

873880
ri := state.ResourceInstance(mustResourceInstanceAddr("test_resource.test"))
874-
expected := `{"id":"test"}`
881+
expected := `{"id":"test","required":"value"}`
875882
if ri == nil || ri.Current == nil {
876883
t.Fatal("no state is recorded for resource instance test_resource.test")
877884
}

internal/terraform/context_plan.go

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -560,6 +560,7 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State,
560560
Targets: opts.Targets,
561561
ForceReplace: opts.ForceReplace,
562562
skipRefresh: opts.SkipRefresh,
563+
Operation: walkPlan,
563564
}).Build(addrs.RootModuleInstance)
564565
return graph, walkPlan, diags
565566
case plans.RefreshOnlyMode:
@@ -571,16 +572,18 @@ func (c *Context) planGraph(config *configs.Config, prevRunState *states.State,
571572
Targets: opts.Targets,
572573
skipRefresh: opts.SkipRefresh,
573574
skipPlanChanges: true, // this activates "refresh only" mode.
575+
Operation: walkPlan,
574576
}).Build(addrs.RootModuleInstance)
575577
return graph, walkPlan, diags
576578
case plans.DestroyMode:
577-
graph, diags := DestroyPlanGraphBuilder(&PlanGraphBuilder{
579+
graph, diags := (&PlanGraphBuilder{
578580
Config: config,
579581
State: prevRunState,
580582
RootVariableValues: opts.SetVariables,
581583
Plugins: c.plugins,
582584
Targets: opts.Targets,
583585
skipRefresh: opts.SkipRefresh,
586+
Operation: walkPlanDestroy,
584587
}).Build(addrs.RootModuleInstance)
585588
return graph, walkPlanDestroy, diags
586589
default:

internal/terraform/context_validate.go

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,11 +55,12 @@ func (c *Context) Validate(config *configs.Config) tfdiags.Diagnostics {
5555
}
5656
}
5757

58-
graph, moreDiags := ValidateGraphBuilder(&PlanGraphBuilder{
58+
graph, moreDiags := (&PlanGraphBuilder{
5959
Config: config,
6060
Plugins: c.plugins,
6161
State: states.NewState(),
6262
RootVariableValues: varValues,
63+
Operation: walkValidate,
6364
}).Build(addrs.RootModuleInstance)
6465
diags = diags.Append(moreDiags)
6566
if moreDiags.HasErrors() {

internal/terraform/context_walk.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -73,7 +73,7 @@ func (c *Context) graphWalker(operation walkOperation, opts *graphWalkOpts) *Con
7373
refreshState = states.NewState().SyncWrapper()
7474
prevRunState = states.NewState().SyncWrapper()
7575

76-
case walkPlan, walkPlanDestroy:
76+
case walkPlan, walkPlanDestroy, walkImport:
7777
state = inputState.DeepCopy().SyncWrapper()
7878
refreshState = inputState.DeepCopy().SyncWrapper()
7979
prevRunState = inputState.DeepCopy().SyncWrapper()

internal/terraform/graph_builder_destroy_plan.go

Lines changed: 0 additions & 17 deletions
This file was deleted.

0 commit comments

Comments
 (0)