diff --git a/command/init_test.go b/command/init_test.go index 9fdc29ba0..a44054665 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -1060,26 +1060,23 @@ func TestInit_providerSource(t *testing.T) { wantPackages := map[addrs.Provider][]providercache.CachedProvider{ addrs.NewDefaultProvider("test"): { { - Provider: addrs.NewDefaultProvider("test"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("test", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("test", "1.2.3", true), + Provider: addrs.NewDefaultProvider("test"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("test", "1.2.3", false), }, }, addrs.NewDefaultProvider("test-beta"): { { - Provider: addrs.NewDefaultProvider("test-beta"), - Version: getproviders.MustParseVersion("1.2.4"), - PackageDir: expectedPackageInstallPath("test-beta", "1.2.4", false), - ExecutableFile: expectedPackageInstallPath("test-beta", "1.2.4", true), + Provider: addrs.NewDefaultProvider("test-beta"), + Version: getproviders.MustParseVersion("1.2.4"), + PackageDir: expectedPackageInstallPath("test-beta", "1.2.4", false), }, }, addrs.NewDefaultProvider("source"): { { - Provider: addrs.NewDefaultProvider("source"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("source", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("source", "1.2.3", true), + Provider: addrs.NewDefaultProvider("source"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("source", "1.2.3", false), }, }, } @@ -1094,22 +1091,19 @@ func TestInit_providerSource(t *testing.T) { } wantSelected := map[addrs.Provider]*providercache.CachedProvider{ addrs.NewDefaultProvider("test-beta"): { - Provider: addrs.NewDefaultProvider("test-beta"), - Version: getproviders.MustParseVersion("1.2.4"), - PackageDir: expectedPackageInstallPath("test-beta", "1.2.4", false), - ExecutableFile: expectedPackageInstallPath("test-beta", "1.2.4", true), + Provider: addrs.NewDefaultProvider("test-beta"), + Version: getproviders.MustParseVersion("1.2.4"), + PackageDir: expectedPackageInstallPath("test-beta", "1.2.4", false), }, addrs.NewDefaultProvider("test"): { - Provider: addrs.NewDefaultProvider("test"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("test", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("test", "1.2.3", true), + Provider: addrs.NewDefaultProvider("test"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("test", "1.2.3", false), }, addrs.NewDefaultProvider("source"): { - Provider: addrs.NewDefaultProvider("source"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("source", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("source", "1.2.3", true), + Provider: addrs.NewDefaultProvider("source"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("source", "1.2.3", false), }, } if diff := cmp.Diff(wantSelected, gotSelected); diff != "" { @@ -1169,27 +1163,24 @@ func TestInit_getUpgradePlugins(t *testing.T) { // the newest available version that matched the version constraints. addrs.NewDefaultProvider("between"): { { - Provider: addrs.NewDefaultProvider("between"), - Version: getproviders.MustParseVersion("2.3.4"), - PackageDir: expectedPackageInstallPath("between", "2.3.4", false), - ExecutableFile: expectedPackageInstallPath("between", "2.3.4", true), + Provider: addrs.NewDefaultProvider("between"), + Version: getproviders.MustParseVersion("2.3.4"), + PackageDir: expectedPackageInstallPath("between", "2.3.4", false), }, }, // The existing version of "exact" did not match the version constraints, // so we installed what the configuration selected as well. addrs.NewDefaultProvider("exact"): { { - Provider: addrs.NewDefaultProvider("exact"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("exact", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("exact", "1.2.3", true), + Provider: addrs.NewDefaultProvider("exact"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("exact", "1.2.3", false), }, // Previous version is still there, but not selected { - Provider: addrs.NewDefaultProvider("exact"), - Version: getproviders.MustParseVersion("0.0.1"), - PackageDir: expectedPackageInstallPath("exact", "0.0.1", false), - ExecutableFile: expectedPackageInstallPath("exact", "0.0.1", true), + Provider: addrs.NewDefaultProvider("exact"), + Version: getproviders.MustParseVersion("0.0.1"), + PackageDir: expectedPackageInstallPath("exact", "0.0.1", false), }, }, // The existing version of "greater-than" _did_ match the constraints, @@ -1197,17 +1188,15 @@ func TestInit_getUpgradePlugins(t *testing.T) { // -upgrade and so we upgraded it anyway. addrs.NewDefaultProvider("greater-than"): { { - Provider: addrs.NewDefaultProvider("greater-than"), - Version: getproviders.MustParseVersion("2.3.4"), - PackageDir: expectedPackageInstallPath("greater-than", "2.3.4", false), - ExecutableFile: expectedPackageInstallPath("greater-than", "2.3.4", true), + Provider: addrs.NewDefaultProvider("greater-than"), + Version: getproviders.MustParseVersion("2.3.4"), + PackageDir: expectedPackageInstallPath("greater-than", "2.3.4", false), }, // Previous version is still there, but not selected { - Provider: addrs.NewDefaultProvider("greater-than"), - Version: getproviders.MustParseVersion("2.3.3"), - PackageDir: expectedPackageInstallPath("greater-than", "2.3.3", false), - ExecutableFile: expectedPackageInstallPath("greater-than", "2.3.3", true), + Provider: addrs.NewDefaultProvider("greater-than"), + Version: getproviders.MustParseVersion("2.3.3"), + PackageDir: expectedPackageInstallPath("greater-than", "2.3.3", false), }, }, } @@ -1222,22 +1211,19 @@ func TestInit_getUpgradePlugins(t *testing.T) { } wantSelected := map[addrs.Provider]*providercache.CachedProvider{ addrs.NewDefaultProvider("between"): { - Provider: addrs.NewDefaultProvider("between"), - Version: getproviders.MustParseVersion("2.3.4"), - PackageDir: expectedPackageInstallPath("between", "2.3.4", false), - ExecutableFile: expectedPackageInstallPath("between", "2.3.4", true), + Provider: addrs.NewDefaultProvider("between"), + Version: getproviders.MustParseVersion("2.3.4"), + PackageDir: expectedPackageInstallPath("between", "2.3.4", false), }, addrs.NewDefaultProvider("exact"): { - Provider: addrs.NewDefaultProvider("exact"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("exact", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("exact", "1.2.3", true), + Provider: addrs.NewDefaultProvider("exact"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("exact", "1.2.3", false), }, addrs.NewDefaultProvider("greater-than"): { - Provider: addrs.NewDefaultProvider("greater-than"), - Version: getproviders.MustParseVersion("2.3.4"), - PackageDir: expectedPackageInstallPath("greater-than", "2.3.4", false), - ExecutableFile: expectedPackageInstallPath("greater-than", "2.3.4", true), + Provider: addrs.NewDefaultProvider("greater-than"), + Version: getproviders.MustParseVersion("2.3.4"), + PackageDir: expectedPackageInstallPath("greater-than", "2.3.4", false), }, } if diff := cmp.Diff(wantSelected, gotSelected); diff != "" { @@ -1480,22 +1466,19 @@ func TestInit_pluginDirProviders(t *testing.T) { } wantSelected := map[addrs.Provider]*providercache.CachedProvider{ addrs.NewDefaultProvider("between"): { - Provider: addrs.NewDefaultProvider("between"), - Version: getproviders.MustParseVersion("2.3.4"), - PackageDir: expectedPackageInstallPath("between", "2.3.4", false), - ExecutableFile: expectedPackageInstallPath("between", "2.3.4", true), + Provider: addrs.NewDefaultProvider("between"), + Version: getproviders.MustParseVersion("2.3.4"), + PackageDir: expectedPackageInstallPath("between", "2.3.4", false), }, addrs.NewDefaultProvider("exact"): { - Provider: addrs.NewDefaultProvider("exact"), - Version: getproviders.MustParseVersion("1.2.3"), - PackageDir: expectedPackageInstallPath("exact", "1.2.3", false), - ExecutableFile: expectedPackageInstallPath("exact", "1.2.3", true), + Provider: addrs.NewDefaultProvider("exact"), + Version: getproviders.MustParseVersion("1.2.3"), + PackageDir: expectedPackageInstallPath("exact", "1.2.3", false), }, addrs.NewDefaultProvider("greater-than"): { - Provider: addrs.NewDefaultProvider("greater-than"), - Version: getproviders.MustParseVersion("2.3.4"), - PackageDir: expectedPackageInstallPath("greater-than", "2.3.4", false), - ExecutableFile: expectedPackageInstallPath("greater-than", "2.3.4", true), + Provider: addrs.NewDefaultProvider("greater-than"), + Version: getproviders.MustParseVersion("2.3.4"), + PackageDir: expectedPackageInstallPath("greater-than", "2.3.4", false), }, } if diff := cmp.Diff(wantSelected, gotSelected); diff != "" { diff --git a/command/meta_providers.go b/command/meta_providers.go index 896553d2a..548868ee7 100644 --- a/command/meta_providers.go +++ b/command/meta_providers.go @@ -209,12 +209,17 @@ func providerFactory(meta *providercache.CachedProvider) providers.Factory { Output: os.Stderr, }) + execFile, err := meta.ExecutableFile() + if err != nil { + return nil, err + } + config := &plugin.ClientConfig{ HandshakeConfig: tfplugin.Handshake, Logger: logger, AllowedProtocols: []plugin.Protocol{plugin.ProtocolGRPC}, Managed: true, - Cmd: exec.Command(meta.ExecutableFile), + Cmd: exec.Command(execFile), AutoMTLS: enableProviderAutoMTLS, VersionedPlugins: tfplugin.VersionedPlugins, } diff --git a/internal/providercache/cached_provider.go b/internal/providercache/cached_provider.go index 55e8fd52d..25c864c00 100644 --- a/internal/providercache/cached_provider.go +++ b/internal/providercache/cached_provider.go @@ -1,6 +1,11 @@ package providercache import ( + "fmt" + "io/ioutil" + "path/filepath" + "strings" + "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/internal/getproviders" ) @@ -20,16 +25,6 @@ type CachedProvider struct { // both slashes and backslashes as long as the separators are consistent // within a particular path string. PackageDir string - - // ExecutableFile is the local filesystem path to the main plugin executable - // for the provider, which is always a file within the directory given - // in PackageDir. - // - // The path always uses slashes as path separators, even on Windows, so - // that the results are consistent between platforms. Windows accepts - // both slashes and backslashes as long as the separators are consistent - // within a particular path string. - ExecutableFile string } // PackageLocation returns the package directory given in the PackageDir field @@ -77,3 +72,70 @@ func (cp *CachedProvider) MatchesHash(want string) (bool, error) { func (cp *CachedProvider) HashV1() (string, error) { return getproviders.PackageHashV1(cp.PackageLocation()) } + +// ExecutableFile inspects the cached provider's unpacked package directory for +// something that looks like it's intended to be the executable file for the +// plugin. +// +// This is a bit messy and heuristic-y because historically Terraform used the +// filename itself for local filesystem discovery, allowing some variance in +// the filenames to capture extra metadata, whereas now we're using the +// directory structure leading to the executable instead but need to remain +// compatible with the executable names bundled into existing provider packages. +// +// It will return an error if it can't find a file following the expected +// convention in the given directory. +// +// If found, the path always uses slashes as path separators, even on Windows, +// so that the results are consistent between platforms. Windows accepts both +// slashes and backslashes as long as the separators are consistent within a +// particular path string. +func (cp *CachedProvider) ExecutableFile() (string, error) { + infos, err := ioutil.ReadDir(cp.PackageDir) + if err != nil { + // If the directory itself doesn't exist or isn't readable then we + // can't access an executable in it. + return "", fmt.Errorf("could not read package directory: %s", err) + } + + // For a provider named e.g. tf.example.com/awesomecorp/happycloud, we + // expect an executable file whose name starts with + // "terraform-provider-happycloud", followed by zero or more additional + // characters. If there _are_ additional characters then the first one + // must be an underscore or a period, like in thse examples: + // - terraform-provider-happycloud_v1.0.0 + // - terraform-provider-happycloud.exe + // + // We don't require the version in the filename to match because the + // executable's name is no longer authoritative, but packages of "official" + // providers may continue to use versioned executable names for backward + // compatibility with Terraform 0.12. + // + // We also presume that providers packaged for Windows will include the + // necessary .exe extension on their filenames but do not explicitly check + // for that. If there's a provider package for Windows that has a file + // without that suffix then it will be detected as an executable but then + // we'll presumably fail later trying to run it. + wantPrefix := "terraform-provider-" + cp.Provider.Type + + // We'll visit all of the directory entries and take the first (in + // name-lexical order) that looks like a plausible provider executable + // name. A package with multiple files meeting these criteria is degenerate + // but we will tolerate it by ignoring the subsequent entries. + for _, info := range infos { + if info.IsDir() { + continue // A directory can never be an executable + } + name := info.Name() + if !strings.HasPrefix(name, wantPrefix) { + continue + } + remainder := name[len(wantPrefix):] + if len(remainder) > 0 && (remainder[0] != '_' && remainder[0] != '.') { + continue // subsequent characters must be delimited by _ or . + } + return filepath.ToSlash(filepath.Join(cp.PackageDir, name)), nil + } + + return "", fmt.Errorf("could not find executable file starting with %s", wantPrefix) +} diff --git a/internal/providercache/cached_provider_test.go b/internal/providercache/cached_provider_test.go index 8d366e637..84315cbcc 100644 --- a/internal/providercache/cached_provider_test.go +++ b/internal/providercache/cached_provider_test.go @@ -15,8 +15,7 @@ func TestCachedProviderHash(t *testing.T) { ), Version: getproviders.MustParseVersion("2.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/darwin_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/darwin_amd64/terraform-provider-null", + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/darwin_amd64", } want := "h1:qjsREM4DqEWECD43FcPqddZ9oxCG+IaMTxvWPciS05g=" @@ -46,8 +45,7 @@ func TestCachedProviderHash(t *testing.T) { ), Version: getproviders.MustParseVersion("2.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64/terraform-provider-null", + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", } gotMatches, err = cp2.MatchesHash(want) if err != nil { @@ -58,3 +56,58 @@ func TestCachedProviderHash(t *testing.T) { } } + +func TestExecutableFile(t *testing.T) { + testCases := map[string]struct { + cp *CachedProvider + file string + err string + }{ + "linux": { + cp: &CachedProvider{ + Provider: addrs.NewProvider(addrs.DefaultRegistryHost, "hashicorp", "null"), + Version: getproviders.MustParseVersion("2.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/linux_amd64", + }, + file: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/linux_amd64/terraform-provider-null", + }, + "windows": { + cp: &CachedProvider{ + Provider: addrs.NewProvider(addrs.DefaultRegistryHost, "hashicorp", "null"), + Version: getproviders.MustParseVersion("2.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", + }, + file: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64/terraform-provider-null.exe", + }, + "missing-executable": { + cp: &CachedProvider{ + Provider: addrs.NewProvider(addrs.DefaultRegistryHost, "missing", "executable"), + Version: getproviders.MustParseVersion("2.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/missing/executable/2.0.0/linux_amd64", + }, + err: "could not find executable file starting with terraform-provider-executable", + }, + "missing-dir": { + cp: &CachedProvider{ + Provider: addrs.NewProvider(addrs.DefaultRegistryHost, "missing", "packagedir"), + Version: getproviders.MustParseVersion("2.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/missing/packagedir/2.0.0/linux_amd64", + }, + err: "could not read package directory: open testdata/cachedir/registry.terraform.io/missing/packagedir/2.0.0/linux_amd64: no such file or directory", + }, + } + + for name, tc := range testCases { + t.Run(name, func(t *testing.T) { + file, err := tc.cp.ExecutableFile() + if file != tc.file { + t.Errorf("wrong file\n got: %q\nwant: %q", file, tc.file) + } + if err == nil && tc.err != "" { + t.Fatalf("no error returned, want: %q", tc.err) + } else if err != nil && err.Error() != tc.err { + t.Errorf("wrong error\n got: %q\nwant: %q", err, tc.err) + } + }) + } +} diff --git a/internal/providercache/dir.go b/internal/providercache/dir.go index 72688f92e..576af7ef4 100644 --- a/internal/providercache/dir.go +++ b/internal/providercache/dir.go @@ -1,11 +1,9 @@ package providercache import ( - "io/ioutil" "log" "path/filepath" "sort" - "strings" "github.com/hashicorp/terraform/addrs" "github.com/hashicorp/terraform/internal/getproviders" @@ -165,20 +163,12 @@ func (d *Dir) fillMetaCache() error { } packageDir := filepath.Clean(string(meta.Location.(getproviders.PackageLocalDir))) - execFile := findProviderExecutableInLocalPackage(meta) - if execFile == "" { - // If the package doesn't contain a suitable executable then - // it isn't considered to be part of our cache. - log.Printf("[TRACE] providercache.fillMetaCache: ignoring %s because it is does not seem to contain a suitable plugin executable", meta.Location) - continue - } log.Printf("[TRACE] providercache.fillMetaCache: including %s as a candidate package for %s %s", meta.Location, providerAddr, meta.Version) data[providerAddr] = append(data[providerAddr], CachedProvider{ - Provider: providerAddr, - Version: meta.Version, - PackageDir: filepath.ToSlash(packageDir), - ExecutableFile: filepath.ToSlash(execFile), + Provider: providerAddr, + Version: meta.Version, + PackageDir: filepath.ToSlash(packageDir), }) } } @@ -200,75 +190,3 @@ func (d *Dir) fillMetaCache() error { d.metaCache = data return nil } - -// This is a helper function to peep into the unpacked directory associated -// with the given package meta and find something that looks like it's intended -// to be the executable file for the plugin. -// -// This is a bit messy and heuristic-y because historically Terraform used the -// filename itself for local filesystem discovery, allowing some variance in -// the filenames to capture extra metadata, whereas now we're using the -// directory structure leading to the executable instead but need to remain -// compatible with the executable names bundled into existing provider packages. -// -// It will return a zero-length string if it can't find a file following -// the expected convention in the given directory. -func findProviderExecutableInLocalPackage(meta getproviders.PackageMeta) string { - packageDir, ok := meta.Location.(getproviders.PackageLocalDir) - if !ok { - // This should never happen because the providercache package only - // uses the local unpacked directory layout. If anything else ends - // up in here then we'll indicate that no executable is available, - // because all other locations require a fetch/unpack step first. - return "" - } - - infos, err := ioutil.ReadDir(string(packageDir)) - if err != nil { - // If the directory itself doesn't exist or isn't readable then we - // can't access an executable in it. - return "" - } - - // For a provider named e.g. tf.example.com/awesomecorp/happycloud, we - // expect an executable file whose name starts with - // "terraform-provider-happycloud", followed by zero or more additional - // characters. If there _are_ additional characters then the first one - // must be an underscore or a period, like in thse examples: - // - terraform-provider-happycloud_v1.0.0 - // - terraform-provider-happycloud.exe - // - // We don't require the version in the filename to match because the - // executable's name is no longer authoritative, but packages of "official" - // providers may continue to use versioned executable names for backward - // compatibility with Terraform 0.12. - // - // We also presume that providers packaged for Windows will include the - // necessary .exe extension on their filenames but do not explicitly check - // for that. If there's a provider package for Windows that has a file - // without that suffix then it will be detected as an executable but then - // we'll presumably fail later trying to run it. - wantPrefix := "terraform-provider-" + meta.Provider.Type - - // We'll visit all of the directory entries and take the first (in - // name-lexical order) that looks like a plausible provider executable - // name. A package with multiple files meeting these criteria is degenerate - // but we will tolerate it by ignoring the subsequent entries. - for _, info := range infos { - if info.IsDir() { - continue // A directory can never be an executable - } - name := info.Name() - if !strings.HasPrefix(name, wantPrefix) { - continue - } - remainder := name[len(wantPrefix):] - if len(remainder) > 0 && (remainder[0] != '_' && remainder[0] != '.') { - continue // subsequent characters must be delimited by _ - } - return filepath.Join(string(packageDir), name) - } - - // If we fall out here then nothing has matched. - return "" -} diff --git a/internal/providercache/dir_modify_test.go b/internal/providercache/dir_modify_test.go index b55961b5b..9d1c8ce56 100644 --- a/internal/providercache/dir_modify_test.go +++ b/internal/providercache/dir_modify_test.go @@ -58,8 +58,7 @@ func TestInstallPackage(t *testing.T) { Version: versions.MustParseVersion("2.1.0"), - PackageDir: tmpDirPath + "/registry.terraform.io/hashicorp/null/2.1.0/linux_amd64", - ExecutableFile: tmpDirPath + "/registry.terraform.io/hashicorp/null/2.1.0/linux_amd64/terraform-provider-null", + PackageDir: tmpDirPath + "/registry.terraform.io/hashicorp/null/2.1.0/linux_amd64", }, }, } @@ -101,8 +100,7 @@ func TestLinkFromOtherCache(t *testing.T) { // still packed and thus not considered to be a cache member. Version: versions.MustParseVersion("2.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64/terraform-provider-null.exe", + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", }, }, } @@ -138,8 +136,7 @@ func TestLinkFromOtherCache(t *testing.T) { // still packed and thus not considered to be a cache member. Version: versions.MustParseVersion("2.0.0"), - PackageDir: tmpDirPath + "/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", - ExecutableFile: tmpDirPath + "/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64/terraform-provider-null.exe", + PackageDir: tmpDirPath + "/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", }, }, } diff --git a/internal/providercache/dir_test.go b/internal/providercache/dir_test.go index b59d4c75a..ada5c83fd 100644 --- a/internal/providercache/dir_test.go +++ b/internal/providercache/dir_test.go @@ -37,6 +37,9 @@ func TestDirReading(t *testing.T) { addrs.DefaultRegistryHost, "bloop", "nonexist", ) legacyProvider := addrs.NewLegacyProvider("legacy") + missingExecutableProvider := addrs.NewProvider( + addrs.DefaultRegistryHost, "missing", "executable", + ) t.Run("ProviderLatestVersion", func(t *testing.T) { t.Run("exists", func(t *testing.T) { @@ -50,8 +53,7 @@ func TestDirReading(t *testing.T) { // still packed and thus not considered to be a cache member. Version: versions.MustParseVersion("2.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64/terraform-provider-null.exe", + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", } if diff := cmp.Diff(want, got); diff != "" { @@ -91,8 +93,7 @@ func TestDirReading(t *testing.T) { Provider: nullProvider, Version: versions.MustParseVersion("2.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64/terraform-provider-null.exe", + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/windows_amd64", } if diff := cmp.Diff(want, got); diff != "" { @@ -141,34 +142,37 @@ func TestDirReading(t *testing.T) { want := map[addrs.Provider][]CachedProvider{ legacyProvider: { { - Provider: legacyProvider, - Version: versions.MustParseVersion("1.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/-/legacy/1.0.0/linux_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/-/legacy/1.0.0/linux_amd64/terraform-provider-legacy", + Provider: legacyProvider, + Version: versions.MustParseVersion("1.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/-/legacy/1.0.0/linux_amd64", }, }, nullProvider: { { - Provider: nullProvider, - Version: versions.MustParseVersion("2.0.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/linux_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/linux_amd64/terraform-provider-null", + Provider: nullProvider, + Version: versions.MustParseVersion("2.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/null/2.0.0/linux_amd64", }, }, randomProvider: { { - Provider: randomProvider, - Version: versions.MustParseVersion("1.2.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/random/1.2.0/linux_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/random/1.2.0/linux_amd64/terraform-provider-random", + Provider: randomProvider, + Version: versions.MustParseVersion("1.2.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/random/1.2.0/linux_amd64", }, }, randomBetaProvider: { { - Provider: randomBetaProvider, - Version: versions.MustParseVersion("1.2.0"), - PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/random-beta/1.2.0/linux_amd64", - ExecutableFile: "testdata/cachedir/registry.terraform.io/hashicorp/random-beta/1.2.0/linux_amd64/terraform-provider-random-beta", + Provider: randomBetaProvider, + Version: versions.MustParseVersion("1.2.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/hashicorp/random-beta/1.2.0/linux_amd64", + }, + }, + missingExecutableProvider: { + { + Provider: missingExecutableProvider, + Version: versions.MustParseVersion("2.0.0"), + PackageDir: "testdata/cachedir/registry.terraform.io/missing/executable/2.0.0/linux_amd64", }, }, } diff --git a/internal/providercache/testdata/cachedir/registry.terraform.io/missing/executable/2.0.0/linux_amd64/executable b/internal/providercache/testdata/cachedir/registry.terraform.io/missing/executable/2.0.0/linux_amd64/executable new file mode 100755 index 000000000..f7a5e529a --- /dev/null +++ b/internal/providercache/testdata/cachedir/registry.terraform.io/missing/executable/2.0.0/linux_amd64/executable @@ -0,0 +1 @@ +This file represents a misnamed provider executable.