diff --git a/command/init.go b/command/init.go index 2f93c1b4e..c76c7175a 100644 --- a/command/init.go +++ b/command/init.go @@ -612,6 +612,18 @@ func (c *InitCommand) getProviders(config *configs.Config, state *states.State, "https://www.terraform.io/docs/plugins/signing.html")) } }, + HashPackageFailure: func(provider addrs.Provider, version getproviders.Version, err error) { + diags = diags.Append(tfdiags.Sourceless( + tfdiags.Error, + "Failed to validate installed provider", + fmt.Sprintf( + "Validating provider %s v%s failed: %s", + provider.ForDisplay(), + version, + err, + ), + )) + }, } mode := providercache.InstallNewProvidersOnly diff --git a/command/init_test.go b/command/init_test.go index 86a5466f9..61744f0b3 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -951,6 +951,67 @@ func TestInit_getProviderSource(t *testing.T) { } } +func TestInit_getProviderInvalidPackage(t *testing.T) { + // Create a temporary working directory that is empty + td := tempDir(t) + copy.CopyDir(testFixturePath("init-get-provider-invalid-package"), td) + defer os.RemoveAll(td) + defer testChdir(t, td)() + + overrides := metaOverridesForProvider(testProvider()) + ui := new(cli.MockUi) + + // create a provider source which allows installing an invalid package + addr := addrs.MustParseProviderSourceString("invalid/package") + version := getproviders.MustParseVersion("1.0.0") + meta, close, err := getproviders.FakeInstallablePackageMeta( + addr, + version, + getproviders.VersionList{getproviders.MustParseVersion("5.0")}, + getproviders.CurrentPlatform, + "terraform-package", // should be "terraform-provider-package" + ) + defer close() + if err != nil { + t.Fatalf("failed to prepare fake package for %s %s: %s", addr.ForDisplay(), version, err) + } + providerSource := getproviders.NewMockSource([]getproviders.PackageMeta{meta}, nil) + + m := Meta{ + testingOverrides: overrides, + Ui: ui, + ProviderSource: providerSource, + } + + c := &InitCommand{ + Meta: m, + } + + args := []string{ + "-backend=false", // should be possible to install plugins without backend init + } + if code := c.Run(args); code != 1 { + t.Fatalf("got exit status %d; want 1\nstderr:\n%s\n\nstdout:\n%s", code, ui.ErrorWriter.String(), ui.OutputWriter.String()) + } + + // invalid provider should be installed + packagePath := fmt.Sprintf(".terraform/plugins/registry.terraform.io/invalid/package/1.0.0/%s/terraform-package", getproviders.CurrentPlatform) + if _, err := os.Stat(packagePath); os.IsNotExist(err) { + t.Fatal("provider 'invalid/package' not downloaded") + } + + wantErrors := []string{ + "Failed to validate installed provider", + "could not find executable file starting with terraform-provider-package", + } + got := ui.ErrorWriter.String() + for _, wantError := range wantErrors { + if !strings.Contains(got, wantError) { + t.Fatalf("missing error:\nwant: %q\n got: %q", wantError, got) + } + } +} + func TestInit_getProviderDetectedLegacy(t *testing.T) { // Create a temporary working directory that is empty td := tempDir(t) diff --git a/command/testdata/init-get-provider-invalid-package/main.tf b/command/testdata/init-get-provider-invalid-package/main.tf new file mode 100644 index 000000000..5f93ef7fc --- /dev/null +++ b/command/testdata/init-get-provider-invalid-package/main.tf @@ -0,0 +1,8 @@ +terraform { + required_providers { + package = { + source = "invalid/package" + version = "1.0.0" + } + } +}