Add a warning when multiple likely forks of a provider are detected (#1009)

Signed-off-by: Christian Mesh <christianmesh1@gmail.com>
This commit is contained in:
Christian Mesh 2023-12-14 12:21:16 -05:00 committed by GitHub
parent 99e51a166d
commit 78464f251a
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
5 changed files with 111 additions and 0 deletions

View File

@ -33,6 +33,7 @@ ENHANCEMENTS:
* state: Provider addresses in the statefile referring to registry.terraform.io will be treated as referring to registry.opentofu.org unless the full provider address is specified in the config or `OPENTOFU_STATEFILE_PROVIDER_ADDRESS_TRANSLATION` is set to `0`. ([#773](https://github.com/opentofu/opentofu/pull/773))
* The default provider namespace has been changed from "hasicorp" to "opentofu". This only impacts providers that do not explicitly have a namespace set, ex "aws" vs "hasicorp/aws". This change should be transparent and not require action to be taken by users.
* init: Ensured that the `tofu init` command has consistent spelling of the word `initialization` in its output. ([#855](https://github.com/opentofu/opentofu/pull/855/files))
* init: A warning is now emitted when two providers who share the same name are detected. This can help prevent misconfigurations when switching a project to use a fork of a provider. ([#1009](https://github.com/opentofu/opentofu/pull/1009))
BUG FIXES:

View File

@ -546,7 +546,13 @@ func (c *InitCommand) getProviders(ctx context.Context, config *configs.Config,
reqs = reqs.Merge(stateReqs)
}
potentialProviderConflicts := make(map[string][]string)
for providerAddr := range reqs {
if providerAddr.Namespace == "hashicorp" || providerAddr.Namespace == "opentofu" {
potentialProviderConflicts[providerAddr.Type] = append(potentialProviderConflicts[providerAddr.Type], providerAddr.ForDisplay())
}
if providerAddr.IsLegacy() {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Error,
@ -559,6 +565,20 @@ func (c *InitCommand) getProviders(ctx context.Context, config *configs.Config,
}
}
for name, addrs := range potentialProviderConflicts {
if len(addrs) > 1 {
diags = diags.Append(tfdiags.Sourceless(
tfdiags.Warning,
"Potential provider misconfiguration",
fmt.Sprintf(
"OpenTofu has detected multiple providers of type %s (%s) which may be a misconfiguration.\n\nIf this is intentional you can ignore this warning",
name,
strings.Join(addrs, ", "),
),
))
}
}
previousLocks, moreDiags := c.lockedDependencies()
diags = diags.Append(moreDiags)

View File

@ -1631,6 +1631,71 @@ func TestInit_getProviderDetectedLegacy(t *testing.T) {
}
}
func TestInit_getProviderDetectedDuplicate(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()
testCopyDir(t, testFixturePath("init-get-provider-detected-duplicate"), td)
defer testChdir(t, td)()
// We need to construct a multisource with a mock source and a registry
// source: the mock source will return ErrRegistryProviderNotKnown for an
// unknown provider, and the registry source will allow us to look up the
// appropriate namespace if possible.
providerSource, psClose := newMockProviderSource(t, map[string][]string{
"hashicorp/foo": {"1.2.3"},
"opentofu/foo": {"1.2.3"},
"hashicorp/bar": {"1.2.3"},
})
defer psClose()
registrySource, rsClose := testRegistrySource(t)
defer rsClose()
multiSource := getproviders.MultiSource{
{Source: providerSource},
{Source: registrySource},
}
ui := new(cli.MockUi)
view, _ := testView(t)
m := Meta{
Ui: ui,
View: view,
ProviderSource: multiSource,
}
c := &InitCommand{
Meta: m,
}
args := []string{
"-backend=false", // should be possible to install plugins without backend init
}
if code := c.Run(args); code != 0 {
t.Fatalf("expected error, got output: \n%s\n%s", ui.OutputWriter.String(), ui.ErrorWriter.String())
}
// error output is the main focus of this test
errOutput := ui.ErrorWriter.String()
errors := []string{
"Warning: Potential provider misconfiguration",
"OpenTofu has detected multiple providers of type foo",
"If this is intentional you can ignore this warning",
}
unexpected := []string{
"OpenTofu has detected multiple providers of type bar",
}
for _, want := range errors {
if !strings.Contains(errOutput, want) {
t.Fatalf("expected error %q: %s", want, errOutput)
}
}
for _, unwanted := range unexpected {
if strings.Contains(errOutput, unwanted) {
t.Fatalf("unexpected error %q: %s", unwanted, errOutput)
}
}
}
func TestInit_providerSource(t *testing.T) {
// Create a temporary working directory that is empty
td := t.TempDir()

View File

@ -0,0 +1,10 @@
terraform {
required_providers {
dupechild = {
source = "hashicorp/bar"
}
}
}
// This will try to install hashicorp/foo
provider foo {}

View File

@ -0,0 +1,15 @@
terraform {
required_providers {
foo = {
// This will conflict with the child modules hashicorp/foo
source = "opentofu/foo"
}
dupe = {
// This should not conflict with the child modules hashicorp/bar
source = "bar"
}
}
}
module "some-baz-stuff" {
source = "./child"
}