diff --git a/terraform/context_apply_test.go b/terraform/context_apply_test.go index 74fcf33bd..0296ef487 100644 --- a/terraform/context_apply_test.go +++ b/terraform/context_apply_test.go @@ -1390,6 +1390,54 @@ func TestContext2Apply_moduleOrphanProvider(t *testing.T) { } } +func TestContext2Apply_moduleOrphanGrandchildProvider(t *testing.T) { + m := testModule(t, "apply-module-orphan-provider-inherit") + p := testProvider("aws") + p.ApplyFn = testApplyFn + p.DiffFn = testDiffFn + + p.ConfigureFn = func(c *ResourceConfig) error { + if _, ok := c.Get("value"); !ok { + return fmt.Errorf("value is not found") + } + + return nil + } + + // Create a state with an orphan module that is nested (grandchild) + state := &State{ + Modules: []*ModuleState{ + &ModuleState{ + Path: []string{"root", "parent", "child"}, + Resources: map[string]*ResourceState{ + "aws_instance.bar": &ResourceState{ + Type: "aws_instance", + Primary: &InstanceState{ + ID: "bar", + }, + }, + }, + }, + }, + } + + ctx := testContext2(t, &ContextOpts{ + Module: m, + State: state, + Providers: map[string]ResourceProviderFactory{ + "aws": testProviderFuncFixed(p), + }, + }) + + if _, err := ctx.Plan(); err != nil { + t.Fatalf("err: %s", err) + } + + if _, err := ctx.Apply(); err != nil { + t.Fatalf("err: %s", err) + } +} + func TestContext2Apply_moduleGrandchildProvider(t *testing.T) { m := testModule(t, "apply-module-grandchild-provider-inherit") p := testProvider("aws") diff --git a/terraform/transform_provider.go b/terraform/transform_provider.go index cbb56dec1..99ea0c3f4 100644 --- a/terraform/transform_provider.go +++ b/terraform/transform_provider.go @@ -523,9 +523,10 @@ func (n *graphNodeProviderFlat) DependableName() []string { func (n *graphNodeProviderFlat) DependentOn() []string { var result []string - // If we're in a module, then depend on our parent's provider - if len(n.PathValue) > 1 { - prefix := modulePrefixStr(n.PathValue[:len(n.PathValue)-1]) + // If we're in a module, then depend on all parent providers. Some of + // these may not exist, hence we depend on all of them. + for i := len(n.PathValue); i > 1; i-- { + prefix := modulePrefixStr(n.PathValue[:i-1]) result = modulePrefixList(n.graphNodeProvider.DependableName(), prefix) }