mirror of
https://github.com/opentofu/opentofu.git
synced 2024-12-26 08:51:02 -06:00
addrs: Disallow provider source addresses starting with terraform-
The main motivation here is to produce a helpful error if a user incorrectly uses the terraform-provider- prefix (which we see on provider VCS repositories and plugin executables) as part of the source address. However, this also more broadly blocks "terraform-" as a prefix in anticipation of whatever instinct causes the phenomenon where e.g. Python's PyPI has thousands of packages whose names start with "python-", even though everything on PyPI is for Python by definition. This is definitely not _necessary_, but it's better to be restrictive at first and weaken later as needed.
This commit is contained in:
parent
7909dd318d
commit
0a46ded3e7
@ -324,6 +324,51 @@ func ParseProviderSourceString(str string) (Provider, tfdiags.Diagnostics) {
|
||||
return Provider{}, diags
|
||||
}
|
||||
|
||||
// Due to how plugin executables are named and provider git repositories
|
||||
// are conventionally named, it's a reasonable and
|
||||
// apparently-somewhat-common user error to incorrectly use the
|
||||
// "terraform-provider-" prefix in a provider source address. There is
|
||||
// no good reason for a provider to have the prefix "terraform-" anyway,
|
||||
// so we've made that invalid from the start both so we can give feedback
|
||||
// to provider developers about the terraform- prefix being redundant
|
||||
// and give specialized feedback to folks who incorrectly use the full
|
||||
// terraform-provider- prefix to help them self-correct.
|
||||
const redundantPrefix = "terraform-"
|
||||
const userErrorPrefix = "terraform-provider-"
|
||||
if strings.HasPrefix(ret.Type, redundantPrefix) {
|
||||
if strings.HasPrefix(ret.Type, userErrorPrefix) {
|
||||
// Likely user error. We only return this specialized error if
|
||||
// whatever is after the prefix would otherwise be a
|
||||
// syntactically-valid provider type, so we don't end up advising
|
||||
// the user to try something that would be invalid for another
|
||||
// reason anyway.
|
||||
// (This is mainly just for robustness, because the validation
|
||||
// we already did above should've rejected most/all ways for
|
||||
// the suggestedType to end up invalid here.)
|
||||
suggestedType := ret.Type[len(userErrorPrefix):]
|
||||
if _, err := ParseProviderPart(suggestedType); err == nil {
|
||||
suggestedAddr := ret
|
||||
suggestedAddr.Type = suggestedType
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Invalid provider type",
|
||||
fmt.Sprintf("Provider source %q has a type with the prefix %q, which isn't valid. Although that prefix is often used in the names of version control repositories for Terraform providers, provider source strings should not include it.\n\nDid you mean %q?", ret.ForDisplay(), userErrorPrefix, suggestedAddr.ForDisplay()),
|
||||
))
|
||||
return Provider{}, diags
|
||||
}
|
||||
}
|
||||
// Otherwise, probably instead an incorrectly-named provider, perhaps
|
||||
// arising from a similar instinct to what causes there to be
|
||||
// thousands of Python packages on PyPI with "python-"-prefixed
|
||||
// names.
|
||||
diags = diags.Append(tfdiags.Sourceless(
|
||||
tfdiags.Error,
|
||||
"Invalid provider type",
|
||||
fmt.Sprintf("Provider source %q has a type with the prefix %q, which isn't allowed because it would be redundant to name a Terraform provider with that prefix. If you are the author of this provider, rename it to not include the prefix.", ret, redundantPrefix),
|
||||
))
|
||||
return Provider{}, diags
|
||||
}
|
||||
|
||||
return ret, diags
|
||||
}
|
||||
|
||||
|
@ -379,6 +379,20 @@ func TestParseProviderSourceStr(t *testing.T) {
|
||||
Provider{},
|
||||
true,
|
||||
},
|
||||
|
||||
// We forbid the terraform- prefix both because it's redundant to
|
||||
// include "terraform" in a Terraform provider name and because we use
|
||||
// the longer prefix terraform-provider- to hint for users who might be
|
||||
// accidentally using the git repository name or executable file name
|
||||
// instead of the provider type.
|
||||
"example.com/hashicorp/terraform-provider-bad": {
|
||||
Provider{},
|
||||
true,
|
||||
},
|
||||
"example.com/hashicorp/terraform-bad": {
|
||||
Provider{},
|
||||
true,
|
||||
},
|
||||
}
|
||||
|
||||
for name, test := range tests {
|
||||
|
10
configs/testdata/error-files/provider-source-prefix.tf
vendored
Normal file
10
configs/testdata/error-files/provider-source-prefix.tf
vendored
Normal file
@ -0,0 +1,10 @@
|
||||
terraform {
|
||||
required_providers {
|
||||
usererror = { # ERROR: Invalid provider type
|
||||
source = "foo/terraform-provider-foo"
|
||||
}
|
||||
badname = { # ERROR: Invalid provider type
|
||||
source = "foo/terraform-foo"
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user