command/init: Fix TestInit_getUpgradePlugins

This test now requires a bit of a different approach because it was
previously directly constructing a cache directory but we now use a
different directory layout.

Rather than manually constructing the new heirarchical directory layout
(which would've required a lot more inline code), this introduces a helper
function installFakeProviderPackages that installs a fake provider package
directly into the local cache directory associated with a Meta object,
with the correct directory layout.
This commit is contained in:
Martin Atkins 2020-03-31 16:48:37 -07:00
parent c4fb22863c
commit 14701b8300
1 changed files with 147 additions and 32 deletions

View File

@ -1,6 +1,7 @@
package command
import (
"context"
"encoding/json"
"fmt"
"io/ioutil"
@ -970,7 +971,7 @@ func TestInit_getUpgradePlugins(t *testing.T) {
"exact": []string{"1.2.3"},
// config requires >= 2.3.3
"greater-than": []string{"2.3.4", "2.3.3", "2.3.0"},
// config specifies
// config specifies > 1.0.0 , < 3.0.0
"between": []string{"3.4.5", "2.3.4", "1.2.3"},
})
defer close()
@ -982,20 +983,10 @@ func TestInit_getUpgradePlugins(t *testing.T) {
ProviderSource: providerSource,
}
err := os.MkdirAll(m.pluginDir(), os.ModePerm)
if err != nil {
t.Fatal(err)
}
exactUnwanted := fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/exact/0.0.1/%s", getproviders.CurrentPlatform)
err = ioutil.WriteFile(exactUnwanted, []byte{}, os.ModePerm)
if err != nil {
t.Fatal(err)
}
greaterThanUnwanted := fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/greater-than/2.3.3/%s", getproviders.CurrentPlatform)
err = ioutil.WriteFile(greaterThanUnwanted, []byte{}, os.ModePerm)
if err != nil {
t.Fatal(err)
}
installFakeProviderPackages(t, &m, map[string][]string{
"exact": []string{"0.0.1"},
"greater-than": []string{"2.3.3"},
})
c := &InitCommand{
Meta: m,
@ -1008,29 +999,100 @@ func TestInit_getUpgradePlugins(t *testing.T) {
t.Fatalf("command did not complete successfully:\n%s", ui.ErrorWriter.String())
}
packageInstPath := func(name string, version string, exe bool) string {
platform := getproviders.CurrentPlatform
if exe {
p := fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/%s/%s/%s/terraform-provider-%s_%s", name, version, platform, name, version)
if platform.OS == "windows" {
p += ".exe"
}
return p
}
return fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/%s/%s/%s", name, version, platform)
}
cacheDir := m.providerLocalCacheDir()
gotPackages := cacheDir.AllAvailablePackages()
wantPackages := []*providercache.CachedProvider{}
/*
wantFilenames := []string{
"lock.json",
// no "between" because the file in cwd overrides it
// The mock PurgeUnused doesn't actually purge anything, so the dir
// includes both our old and new versions.
"terraform-provider-exact_v0.0.1_x4",
"terraform-provider-exact_v1.2.3_x4",
"terraform-provider-greater-than_v2.3.3_x4",
"terraform-provider-greater-than_v2.3.4_x4",
}
*/
wantPackages := map[addrs.Provider][]providercache.CachedProvider{
// "between" wasn't previously installed at all, so we installed
// the newest available version that matched the version constraints.
addrs.NewDefaultProvider("between"): {
{
Provider: addrs.NewDefaultProvider("between"),
Version: getproviders.MustParseVersion("2.3.4"),
PackageDir: packageInstPath("between", "2.3.4", false),
ExecutableFile: packageInstPath("between", "2.3.4", true),
},
},
// 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: packageInstPath("exact", "1.2.3", false),
ExecutableFile: packageInstPath("exact", "1.2.3", true),
},
// Previous version is still there, but not selected
{
Provider: addrs.NewDefaultProvider("exact"),
Version: getproviders.MustParseVersion("0.0.1"),
PackageDir: packageInstPath("exact", "0.0.1", false),
ExecutableFile: packageInstPath("exact", "0.0.1", true),
},
},
// The existing version of "greater-than" _did_ match the constraints,
// but a newer version was available and the user specified
// -upgrade and so we upgraded it anyway.
addrs.NewDefaultProvider("greater-than"): {
{
Provider: addrs.NewDefaultProvider("greater-than"),
Version: getproviders.MustParseVersion("2.3.4"),
PackageDir: packageInstPath("greater-than", "2.3.4", false),
ExecutableFile: packageInstPath("greater-than", "2.3.4", true),
},
// Previous version is still there, but not selected
{
Provider: addrs.NewDefaultProvider("greater-than"),
Version: getproviders.MustParseVersion("2.3.3"),
PackageDir: packageInstPath("greater-than", "2.3.3", false),
ExecutableFile: packageInstPath("greater-than", "2.3.3", true),
},
},
}
if diff := cmp.Diff(wantPackages, gotPackages); diff != "" {
t.Errorf("wrong cache directory contents after upgrade\n%s", diff)
}
inst := m.providerInstaller()
gotSelected, err := inst.SelectedPackages()
if err != nil {
t.Fatalf("failed to get selected packages from installer: %s", err)
}
wantSelected := map[addrs.Provider]*providercache.CachedProvider{
addrs.NewDefaultProvider("between"): {
Provider: addrs.NewDefaultProvider("between"),
Version: getproviders.MustParseVersion("2.3.4"),
PackageDir: packageInstPath("between", "2.3.4", false),
ExecutableFile: packageInstPath("between", "2.3.4", true),
},
addrs.NewDefaultProvider("exact"): {
Provider: addrs.NewDefaultProvider("exact"),
Version: getproviders.MustParseVersion("1.2.3"),
PackageDir: packageInstPath("exact", "1.2.3", false),
ExecutableFile: packageInstPath("exact", "1.2.3", true),
},
addrs.NewDefaultProvider("greater-than"): {
Provider: addrs.NewDefaultProvider("greater-than"),
Version: getproviders.MustParseVersion("2.3.4"),
PackageDir: packageInstPath("greater-than", "2.3.4", false),
ExecutableFile: packageInstPath("greater-than", "2.3.4", true),
},
}
if diff := cmp.Diff(wantSelected, gotSelected); diff != "" {
t.Errorf("wrong version selections after upgrade\n%s", diff)
}
}
func TestInit_getProviderMissing(t *testing.T) {
@ -1424,3 +1486,56 @@ func newMockProviderSource(t *testing.T, availableProviderVersions map[string][]
return getproviders.NewMockSource(packages), close
}
// installFakeProviderPackage installs a fake package for the given provider
// names (interpreted as a "default" provider address) and versions into the
// local plugin cache for the given "meta".
//
// Any test using this must be using testChdir or some similar mechanism to
// make sure that it isn't writing directly into a test fixture or source
// directory within the codebase.
//
// If a requested package cannot be installed for some reason, this function
// will abort the test using the given testing.T. Therefore if this function
// returns the caller can assume that the requested providers have been
// installed.
func installFakeProviderPackages(t *testing.T, meta *Meta, providerVersions map[string][]string) {
t.Helper()
// It can be hard to spot the mistake of forgetting to run testChdir before
// modifying the working directory, so we'll use a simple heuristic here
// to try to detect that mistake and make a noisy error about it instead.
wd, err := os.Getwd()
if err == nil {
wd = filepath.Clean(wd)
// If the directory we're in is named "command" or if we're under a
// directory named "testdata" then we'll assume a mistake and generate
// an error. This will cause the test to fail but won't block it from
// running.
if filepath.Base(wd) == "command" || filepath.Base(wd) == "testdata" || strings.Contains(filepath.ToSlash(wd), "/testdata/") {
t.Errorf("installFakeProviderPackage may be used only by tests that switch to a temporary working directory, e.g. using testChdir")
}
}
cacheDir := meta.providerLocalCacheDir()
for name, versions := range providerVersions {
addr := addrs.NewDefaultProvider(name)
for _, versionStr := range versions {
version, err := getproviders.ParseVersion(versionStr)
if err != nil {
t.Fatalf("failed to parse %q as a version number for %q: %s", versionStr, name, err)
}
meta, close, err := getproviders.FakeInstallablePackageMeta(addr, version, getproviders.CurrentPlatform)
// We're going to install all these fake packages before we return,
// so we don't need to preserve them afterwards.
defer close()
if err != nil {
t.Fatalf("failed to prepare fake package for %s %s: %s", name, versionStr, err)
}
err = cacheDir.InstallPackage(context.Background(), meta)
if err != nil {
t.Fatalf("failed to install fake package for %s %s: %s", name, versionStr, err)
}
}
}
}