Skip to content

Commit

Permalink
Check for duplicate types in required_providers
Browse files Browse the repository at this point in the history
Adding multiple local names for the same provider type in
required_providers was not prevented, which can lead to ambiguous
behavior in Terraform. Providers are always indexed by the providers
fully qualified name, so duplicate local names cannot be differentiated.
  • Loading branch information
jbardin committed Jun 9, 2022
1 parent 2f1a8bb commit 7ac37eb
Show file tree
Hide file tree
Showing 3 changed files with 42 additions and 0 deletions.
6 changes: 6 additions & 0 deletions internal/configs/config_test.go
Expand Up @@ -158,6 +158,12 @@ func TestConfigProviderRequirements(t *testing.T) {
}
}

func TestConfigProviderRequirementsDuplicate(t *testing.T) {
_, diags := testNestedModuleConfigFromDir(t, "testdata/duplicate-local-name")
assertDiagnosticCount(t, diags, 1)
assertDiagnosticSummary(t, diags, "Duplicate required provider")
}

func TestConfigProviderRequirementsShallow(t *testing.T) {
cfg, diags := testNestedModuleConfigFromDir(t, "testdata/provider-reqs")
// TODO: Version Constraint Deprecation.
Expand Down
26 changes: 26 additions & 0 deletions internal/configs/provider_validation.go
Expand Up @@ -82,7 +82,33 @@ func validateProviderConfigs(parentCall *ModuleCall, cfg *Config, noProviderConf
}

if mod.ProviderRequirements != nil {

// Track all known local types too to ensure we don't have duplicated
// with different local names.
localTypes := map[string]bool{}

for _, req := range mod.ProviderRequirements.RequiredProviders {
if localTypes[req.Type.String()] {
// find the last declaration to give a better error
prevDecl := ""
for localName, typ := range localNames {
if typ.Equals(req.Type) {
prevDecl = localName
}
}

diags = append(diags, &hcl.Diagnostic{
Severity: hcl.DiagError,
Summary: "Duplicate required provider",
Detail: fmt.Sprintf(
"Provider %s with the local name %q was previously required as %q. A provider can only be required once within required_providers.",
req.Type.ForDisplay(), req.Name, prevDecl,
),
Subject: &req.DeclRange,
})
}
localTypes[req.Type.String()] = true

localNames[req.Name] = req.Type
for _, alias := range req.Aliases {
addr := addrs.AbsProviderConfig{
Expand Down
10 changes: 10 additions & 0 deletions internal/configs/testdata/duplicate-local-name/main.tf
@@ -0,0 +1,10 @@
terraform {
required_providers {
test = {
source = "hashicorp/test"
}
dupe = {
source = "hashicorp/test"
}
}
}

0 comments on commit 7ac37eb

Please sign in to comment.