diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 99f2d805b7d7..d643991590da 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -443,6 +443,45 @@ func TestContext2Apply_destroySkipsCBD(t *testing.T) { } } +func TestContext2Apply_destroyModuleVarProviderConfig(t *testing.T) { + m := testModule(t, "apply-destroy-mod-var-provider-config") + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: []string{"root", "child"}, + Resources: map[string]*ResourceState{ + "aws_instance.foo": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "foo", + }, + }, + }, + }, + }, + } + ctx := testContext2(t, &ContextOpts{ + Module: m, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + State: state, + Destroy: true, + }) + + if _, err := ctx.Plan(); err != nil { + t.Fatalf("err: %s", err) + } + + _, err := ctx.Apply() + if err != nil { + t.Fatalf("err: %s", err) + } +} + // https://github.com/hashicorp/terraform/issues/2892 func TestContext2Apply_destroyCrossProviders(t *testing.T) { m := testModule(t, "apply-destroy-cross-providers") diff --git a/terraform/graph_config_node_variable.go b/terraform/graph_config_node_variable.go index 1f17471e8ec1..0a86c4881502 100644 --- a/terraform/graph_config_node_variable.go +++ b/terraform/graph_config_node_variable.go @@ -234,3 +234,24 @@ func (n *GraphNodeConfigVariableFlat) Path() []string { return nil } + +func (n *GraphNodeConfigVariableFlat) Noop(opts *NoopOpts) bool { + // First look for provider nodes that depend on this variable downstream + modDiff := opts.Diff.ModuleByPath(n.ModulePath) + if modDiff != nil && modDiff.Destroy { + ds, err := opts.Graph.Descendents(n) + if err != nil { + log.Printf("[ERROR] Error looking up descendents of %s: %s", n.Name(), err) + } else { + for _, d := range ds.List() { + if _, ok := d.(GraphNodeProvider); ok { + log.Printf("[DEBUG] This variable is depended on by a provider, can't be a noop.") + return false + } + } + } + } + + // Then fall back to existing impl + return n.GraphNodeConfigVariable.Noop(opts) +} diff --git a/terraform/test-fixtures/apply-destroy-mod-var-provider-config/child/child.tf b/terraform/test-fixtures/apply-destroy-mod-var-provider-config/child/child.tf new file mode 100644 index 000000000000..6544cf6cb45f --- /dev/null +++ b/terraform/test-fixtures/apply-destroy-mod-var-provider-config/child/child.tf @@ -0,0 +1,7 @@ +variable "input" {} + +provider "aws" { + region = "us-east-${var.input}" +} + +resource "aws_instance" "foo" { } diff --git a/terraform/test-fixtures/apply-destroy-mod-var-provider-config/main.tf b/terraform/test-fixtures/apply-destroy-mod-var-provider-config/main.tf new file mode 100644 index 000000000000..1e2dfb3521df --- /dev/null +++ b/terraform/test-fixtures/apply-destroy-mod-var-provider-config/main.tf @@ -0,0 +1,4 @@ +module "child" { + source = "./child" + input = "1" +}