Skip to content

Commit

Permalink
don't evaluate providers in overridden modules
Browse files Browse the repository at this point in the history
While we don't normally encounter providers within modules, they are
technically still supported, and could exist within a module which has
been overridden for testing. Since the module is not being evaluated, we
cannot safely evaluate the provider config as variables will not exist
within that module.
  • Loading branch information
jbardin committed May 2, 2024
1 parent bf0a6ed commit 582c729
Show file tree
Hide file tree
Showing 2 changed files with 65 additions and 1 deletion.
47 changes: 47 additions & 0 deletions internal/terraform/context_apply_overrides_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -638,6 +638,43 @@ resource "test_instance" "resource" {
output "id" {
value = test_instance.resource[0].id
}
`,
},
overrides: mocking.OverridesForTesting(nil, func(overrides addrs.Map[addrs.Targetable, *configs.Override]) {
overrides.Put(mustModuleInstance("module.test"), &configs.Override{
Values: cty.ObjectVal(map[string]cty.Value{
"id": cty.StringVal("h3ll0"),
}),
})
}),
outputs: cty.EmptyObjectVal,
},
"legacy provider config inside overridden module": {
configs: map[string]string{
"main.tf": `
module "test" {
source = "./child"
}
`,
"child/main.tf": `
module "grandchild" {
source = "../grandchild"
}
output "id" {
value = "child"
}
`,
"grandchild/main.tf": `
variable "in" {
default = "test_value"
}
provider "test" {
value = var.in
}
resource "test_instance" "resource" {
}
`,
},
overrides: mocking.OverridesForTesting(nil, func(overrides addrs.Map[addrs.Targetable, *configs.Override]) {
Expand Down Expand Up @@ -720,6 +757,16 @@ output "id" {
// functionality, in that they should stop the provider from being executed.
var underlyingOverridesProvider = &testing_provider.MockProvider{
GetProviderSchemaResponse: &providers.GetProviderSchemaResponse{
Provider: providers.Schema{
Block: &configschema.Block{
Attributes: map[string]*configschema.Attribute{
"value": {
Type: cty.String,
Optional: true,
},
},
},
},
ResourceTypes: map[string]providers.Schema{
"test_instance": {
Block: &configschema.Block{
Expand Down
19 changes: 18 additions & 1 deletion internal/terraform/graph.go
Original file line number Diff line number Diff line change
Expand Up @@ -64,9 +64,11 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
}
}()

haveOverrides := !ctx.Overrides().Empty()

// If the graph node is overridable, we'll check our overrides to see
// if we need to apply any overrides to the node.
if overridable, ok := v.(GraphNodeOverridable); ok && !ctx.Overrides().Empty() {
if overridable, ok := v.(GraphNodeOverridable); ok && haveOverrides {
// It'd be nice if we could just pass the overrides directly into
// the nodes, but the way the AbstractNodeResource is created is
// complicated and it's not easy to make sure that every
Expand All @@ -80,6 +82,21 @@ func (g *Graph) walk(walker GraphWalker) tfdiags.Diagnostics {
}
}

if provider, ok := v.(GraphNodeProvider); ok && haveOverrides {
// If we find a legacy provider within an overridden module, we
// can't evaluate the config so we have to skip it. We do this here
// for the similar reasons as the resource overrides above, and to
// keep all the override logic together.
addr := provider.ProviderAddr()
// UnkeyedInstanceShim is used by legacy provider configs within a
// module to return an instance of that module, since they can never
// exist within an expanded instance.
if ctx.Overrides().IsOverridden(addr.Module.UnkeyedInstanceShim()) {
log.Printf("[DEBUG] skipping provider %s found within overridden module", addr)
return
}
}

// vertexCtx is the context that we use when evaluating. This
// is normally the global context but can be overridden
// with either a GraphNodeModuleInstance, GraphNodePartialExpandedModule,
Expand Down

0 comments on commit 582c729

Please sign in to comment.