From d40085f3743a34f0b9aace3faa01e5c5ac5f3eda Mon Sep 17 00:00:00 2001 From: Martin Atkins Date: Tue, 31 Mar 2020 14:02:40 -0700 Subject: [PATCH] command: Make the tests compile again They still aren't passing, but this is just enough updating to make the test program compile successfully after the refactoring related to provider installation. They are now using the mock provider source offered by the getproviders package, which is similar but not totally identical to the idea of mocking the entire installer as these tests used to do, and so many of them need further adjustment to still be testing what they intended to test under this new architecture. Subsequent commits will gradually repair the failing tests. --- command/import_test.go | 38 ++-- command/init_test.go | 367 ++++++++++++++----------------- command/internal_plugin_test.go | 4 +- command/plugins_test.go | 169 +------------- command/providers_schema_test.go | 12 +- command/show_test.go | 24 +- 6 files changed, 207 insertions(+), 407 deletions(-) diff --git a/command/import_test.go b/command/import_test.go index 199c6d99d..888b98c03 100644 --- a/command/import_test.go +++ b/command/import_test.go @@ -14,7 +14,6 @@ import ( "github.com/hashicorp/terraform/configs/configschema" "github.com/hashicorp/terraform/helper/copy" - "github.com/hashicorp/terraform/plugin/discovery" "github.com/hashicorp/terraform/providers" "github.com/hashicorp/terraform/terraform" "github.com/hashicorp/terraform/tfdiags" @@ -160,22 +159,21 @@ func TestImport_remoteState(t *testing.T) { statePath := "imported.tfstate" + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + // init our backend ui := cli.NewMockUi() m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } ic := &InitCommand{ Meta: m, - providerInstaller: &mockProviderInstaller{ - Providers: map[string][]string{ - "test": []string{"1.2.3"}, - }, - - Dir: m.pluginDir(), - }, } // (Using log here rather than t.Log so that these messages interleave with other trace logs) @@ -267,22 +265,21 @@ func TestImport_initializationErrorShouldUnlock(t *testing.T) { statePath := "imported.tfstate" + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + // init our backend ui := cli.NewMockUi() m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } ic := &InitCommand{ Meta: m, - providerInstaller: &mockProviderInstaller{ - Providers: map[string][]string{ - "test": []string{"1.2.3"}, - }, - - Dir: m.pluginDir(), - }, } // (Using log here rather than t.Log so that these messages interleave with other trace logs) @@ -853,10 +850,16 @@ func TestImport_pluginDir(t *testing.T) { t.Fatal(err) } + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + ui := new(cli.MockUi) c := &ImportCommand{ Meta: Meta{ - Ui: ui, + Ui: ui, + ProviderSource: providerSource, }, } @@ -873,9 +876,6 @@ func TestImport_pluginDir(t *testing.T) { pluginPath: []string{"./plugins"}, Ui: initUi, }, - providerInstaller: &discovery.ProviderInstaller{ - PluginProtocolVersion: discovery.PluginInstallProtocolVersion, - }, } if code := initCmd.Run(nil); code != 0 { t.Fatal(initUi.ErrorWriter.String()) diff --git a/command/init_test.go b/command/init_test.go index 227d2e98f..e880403ee 100644 --- a/command/init_test.go +++ b/command/init_test.go @@ -7,12 +7,11 @@ import ( "log" "os" "path/filepath" - "reflect" - "runtime" - "sort" "strings" "testing" + "github.com/davecgh/go-spew/spew" + "github.com/google/go-cmp/cmp" "github.com/mitchellh/cli" "github.com/zclconf/go-cty/cty" @@ -20,12 +19,12 @@ import ( "github.com/hashicorp/terraform/backend/local" "github.com/hashicorp/terraform/configs" "github.com/hashicorp/terraform/helper/copy" - "github.com/hashicorp/terraform/plugin/discovery" + "github.com/hashicorp/terraform/internal/getproviders" + "github.com/hashicorp/terraform/internal/providercache" "github.com/hashicorp/terraform/state" "github.com/hashicorp/terraform/states" "github.com/hashicorp/terraform/states/statemgr" "github.com/hashicorp/terraform/terraform" - "github.com/hashicorp/terraform/tfdiags" ) func TestInit_empty(t *testing.T) { @@ -779,26 +778,23 @@ func TestInit_getProvider(t *testing.T) { overrides := metaOverridesForProvider(testProvider()) ui := new(cli.MockUi) + providerSource, close := newMockProviderSource(t, map[string][]string{ + // looking for an exact version + "exact": []string{"1.2.3"}, + // config requires >= 2.3.3 + "greater-than": []string{"2.3.4", "2.3.3", "2.3.0"}, + // config specifies + "between": []string{"3.4.5", "2.3.4", "1.2.3"}, + }) + defer close() m := Meta{ testingOverrides: overrides, Ui: ui, - } - installer := &mockProviderInstaller{ - Providers: map[string][]string{ - // looking for an exact version - "exact": []string{"1.2.3"}, - // config requires >= 2.3.3 - "greater-than": []string{"2.3.4", "2.3.3", "2.3.0"}, - // config specifies - "between": []string{"3.4.5", "2.3.4", "1.2.3"}, - }, - - Dir: m.pluginDir(), + ProviderSource: providerSource, } c := &InitCommand{ - Meta: m, - providerInstaller: installer, + Meta: m, } args := []string{ @@ -808,20 +804,16 @@ func TestInit_getProvider(t *testing.T) { t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) } - if !installer.PurgeUnusedCalled { - t.Errorf("init didn't purge providers, but should have") - } - // check that we got the providers for our config - exactPath := filepath.Join(c.pluginDir(), installer.FileName("exact", "1.2.3")) + exactPath := fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/exact/1.2.3/%s", getproviders.CurrentPlatform) if _, err := os.Stat(exactPath); os.IsNotExist(err) { t.Fatal("provider 'exact' not downloaded") } - greaterThanPath := filepath.Join(c.pluginDir(), installer.FileName("greater-than", "2.3.4")) + greaterThanPath := fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/greater-than/2.3.4/%s", getproviders.CurrentPlatform) if _, err := os.Stat(greaterThanPath); os.IsNotExist(err) { t.Fatal("provider 'greater-than' not downloaded") } - betweenPath := filepath.Join(c.pluginDir(), installer.FileName("between", "2.3.4")) + betweenPath := fmt.Sprintf(".terraform/plugins/registry.terraform.io/hashicorp/between/2.3.4/%s", getproviders.CurrentPlatform) if _, err := os.Stat(betweenPath); os.IsNotExist(err) { t.Fatal("provider 'between' not downloaded") } @@ -842,8 +834,7 @@ func TestInit_getProvider(t *testing.T) { ui := new(cli.MockUi) m.Ui = ui c := &InitCommand{ - Meta: m, - providerInstaller: installer, + Meta: m, } if code := c.Run(nil); code == 0 { @@ -867,15 +858,19 @@ func TestInit_findVendoredProviders(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + // An empty provider source + providerSource, close := newMockProviderSource(t, nil) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } c := &InitCommand{ - Meta: m, - providerInstaller: &mockProviderInstaller{}, + Meta: m, } // make our plugin paths @@ -909,49 +904,6 @@ func TestInit_findVendoredProviders(t *testing.T) { } } -// make sure we can locate providers defined in the legacy rc file -func TestInit_rcProviders(t *testing.T) { - // Create a temporary working directory that is empty - td := tempDir(t) - - configDirName := "init-legacy-rc" - copy.CopyDir(testFixturePath(configDirName), filepath.Join(td, configDirName)) - defer os.RemoveAll(td) - defer testChdir(t, td)() - - pluginDir := filepath.Join(td, "custom") - pluginPath := filepath.Join(pluginDir, "terraform-provider-legacy") - - ui := new(cli.MockUi) - m := Meta{ - Ui: ui, - PluginOverrides: &PluginOverrides{ - Providers: map[string]string{ - "legacy": pluginPath, - }, - }, - } - - c := &InitCommand{ - Meta: m, - providerInstaller: &mockProviderInstaller{}, - } - - // make our plugin paths - if err := os.MkdirAll(pluginDir, 0755); err != nil { - t.Fatal(err) - } - - if err := ioutil.WriteFile(pluginPath, []byte("test bin"), 0755); err != nil { - t.Fatal(err) - } - - args := []string{configDirName} - if code := c.Run(args); code != 0 { - t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) - } -} - func TestInit_providerSource(t *testing.T) { // Create a temporary working directory that is empty td := tempDir(t) @@ -961,15 +913,19 @@ func TestInit_providerSource(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + // An empty provider source + providerSource, close := newMockProviderSource(t, nil) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } c := &InitCommand{ - Meta: m, - providerInstaller: &mockProviderInstaller{}, + Meta: m, } // make our plugin paths @@ -1009,48 +965,40 @@ func TestInit_getUpgradePlugins(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + providerSource, close := newMockProviderSource(t, map[string][]string{ + // looking for an exact version + "exact": []string{"1.2.3"}, + // config requires >= 2.3.3 + "greater-than": []string{"2.3.4", "2.3.3", "2.3.0"}, + // config specifies + "between": []string{"3.4.5", "2.3.4", "1.2.3"}, + }) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, - } - - installer := &mockProviderInstaller{ - Providers: map[string][]string{ - // looking for an exact version - "exact": []string{"1.2.3"}, - // config requires >= 2.3.3 - "greater-than": []string{"2.3.4", "2.3.3", "2.3.0"}, - // config specifies - "between": []string{"3.4.5", "2.3.4", "1.2.3"}, - }, - - Dir: m.pluginDir(), + ProviderSource: providerSource, } err := os.MkdirAll(m.pluginDir(), os.ModePerm) if err != nil { t.Fatal(err) } - exactUnwanted := filepath.Join(m.pluginDir(), installer.FileName("exact", "0.0.1")) + 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 := filepath.Join(m.pluginDir(), installer.FileName("greater-than", "2.3.3")) + 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) } - betweenOverride := installer.FileName("between", "2.3.4") // intentionally directly in cwd, and should override auto-install - err = ioutil.WriteFile(betweenOverride, []byte{}, os.ModePerm) - if err != nil { - t.Fatal(err) - } c := &InitCommand{ - Meta: m, - providerInstaller: installer, + Meta: m, } args := []string{ @@ -1060,36 +1008,27 @@ func TestInit_getUpgradePlugins(t *testing.T) { t.Fatalf("command did not complete successfully:\n%s", ui.ErrorWriter.String()) } - files, err := ioutil.ReadDir(m.pluginDir()) - if err != nil { - t.Fatal(err) - } + cacheDir := m.providerLocalCacheDir() + gotPackages := cacheDir.AllAvailablePackages() + wantPackages := []*providercache.CachedProvider{} - if !installer.PurgeUnusedCalled { - t.Errorf("init -upgrade didn't purge providers, but should have") - } + /* + wantFilenames := []string{ + "lock.json", - gotFilenames := make([]string, len(files)) - for i, info := range files { - gotFilenames[i] = info.Name() - } - sort.Strings(gotFilenames) + // no "between" because the file in cwd overrides it - wantFilenames := []string{ - "lock.json", + // 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", + } + */ - // 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", - } - - if !reflect.DeepEqual(gotFilenames, wantFilenames) { - t.Errorf("wrong directory contents after upgrade\ngot: %#v\nwant: %#v", gotFilenames, wantFilenames) + if diff := cmp.Diff(wantPackages, gotPackages); diff != "" { + t.Errorf("wrong cache directory contents after upgrade\n%s", diff) } } @@ -1101,28 +1040,25 @@ func TestInit_getProviderMissing(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + providerSource, close := newMockProviderSource(t, map[string][]string{ + // looking for exact version 1.2.3 + "exact": []string{"1.2.4"}, + // config requires >= 2.3.3 + "greater-than": []string{"2.3.4", "2.3.3", "2.3.0"}, + // config specifies + "between": []string{"3.4.5", "2.3.4", "1.2.3"}, + }) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, - } - - installer := &mockProviderInstaller{ - Providers: map[string][]string{ - // looking for exact version 1.2.3 - "exact": []string{"1.2.4"}, - // config requires >= 2.3.3 - "greater-than": []string{"2.3.4", "2.3.3", "2.3.0"}, - // config specifies - "between": []string{"3.4.5", "2.3.4", "1.2.3"}, - }, - - Dir: m.pluginDir(), + ProviderSource: providerSource, } c := &InitCommand{ - Meta: m, - providerInstaller: installer, + Meta: m, } args := []string{} @@ -1135,40 +1071,6 @@ func TestInit_getProviderMissing(t *testing.T) { } } -func TestInit_getProviderHaveLegacyVersion(t *testing.T) { - // Create a temporary working directory that is empty - td := tempDir(t) - copy.CopyDir(testFixturePath("init-providers-lock"), td) - defer os.RemoveAll(td) - defer testChdir(t, td)() - - if err := ioutil.WriteFile("terraform-provider-test", []byte("provider bin"), 0755); err != nil { - t.Fatal(err) - } - - // provider test has a version constraint in the config, which should - // trigger the getProvider error below. - ui := new(cli.MockUi) - c := &InitCommand{ - Meta: Meta{ - testingOverrides: metaOverridesForProvider(testProvider()), - Ui: ui, - }, - providerInstaller: callbackPluginInstaller(func(provider string, req discovery.Constraints) (discovery.PluginMeta, tfdiags.Diagnostics, error) { - return discovery.PluginMeta{}, tfdiags.Diagnostics{}, fmt.Errorf("EXPECTED PROVIDER ERROR %s", provider) - }), - } - - args := []string{} - if code := c.Run(args); code == 0 { - t.Fatalf("expceted error, got output: \n%s", ui.OutputWriter.String()) - } - - if !strings.Contains(ui.ErrorWriter.String(), "EXPECTED PROVIDER ERROR test") { - t.Fatalf("unexpected error output: %s", ui.ErrorWriter) - } -} - func TestInit_checkRequiredVersion(t *testing.T) { // Create a temporary working directory that is empty td := tempDir(t) @@ -1197,23 +1099,20 @@ func TestInit_providerLockFile(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, - } - - installer := &mockProviderInstaller{ - Providers: map[string][]string{ - "test": []string{"1.2.3"}, - }, - - Dir: m.pluginDir(), + ProviderSource: providerSource, } c := &InitCommand{ - Meta: m, - providerInstaller: installer, + Meta: m, } args := []string{} @@ -1221,22 +1120,23 @@ func TestInit_providerLockFile(t *testing.T) { t.Fatalf("bad: \n%s", ui.ErrorWriter.String()) } - providersLockFile := fmt.Sprintf( - ".terraform/plugins/%s_%s/lock.json", - runtime.GOOS, runtime.GOARCH, - ) - buf, err := ioutil.ReadFile(providersLockFile) + selectionsFile := ".terraform/plugins/selections.json" + buf, err := ioutil.ReadFile(selectionsFile) if err != nil { - t.Fatalf("failed to read providers lock file %s: %s", providersLockFile, err) + t.Fatalf("failed to read provider selections file %s: %s", selectionsFile, err) } - // The hash in here is for the empty files that mockGetProvider produces + // The hash in here is for the fake package that newMockProviderSource produces + // (so it'll change if newMockProviderSource starts producing different contents) wantLockFile := strings.TrimSpace(` { - "test": "e3b0c44298fc1c149afbf4c8996fb92427ae41e4649b934ca495991b7852b855" + "registry.terraform.io/hashicorp/test": { + "hash": "h1:4RzJudhcE4CkEwtVNRqdMKumSXu6bj8fkFTbPaX5G14=", + "version": "1.2.3" + } } `) if string(buf) != wantLockFile { - t.Errorf("wrong provider lock file contents\ngot: %s\nwant: %s", buf, wantLockFile) + t.Errorf("wrong provider selections file contents\ngot: %s\nwant: %s", buf, wantLockFile) } } @@ -1245,13 +1145,17 @@ func TestInit_pluginDirReset(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + // An empty provider source + providerSource, close := newMockProviderSource(t, nil) + defer close() + ui := new(cli.MockUi) c := &InitCommand{ Meta: Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, }, - providerInstaller: &mockProviderInstaller{}, } // make our vendor paths @@ -1282,8 +1186,8 @@ func TestInit_pluginDirReset(t *testing.T) { Meta: Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, // still empty }, - providerInstaller: &mockProviderInstaller{}, } // make sure we remove the plugin-dir record @@ -1309,15 +1213,19 @@ func TestInit_pluginDirProviders(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + // An empty provider source + providerSource, close := newMockProviderSource(t, nil) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } c := &InitCommand{ - Meta: m, - providerInstaller: &mockProviderInstaller{}, + Meta: m, } // make our vendor paths @@ -1357,18 +1265,19 @@ func TestInit_pluginDirProvidersDoesNotGet(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + // An empty provider source + providerSource, close := newMockProviderSource(t, nil) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } c := &InitCommand{ Meta: m, - providerInstaller: callbackPluginInstaller(func(provider string, req discovery.Constraints) (discovery.PluginMeta, tfdiags.Diagnostics, error) { - t.Fatalf("plugin installer should not have been called for %q", provider) - return discovery.PluginMeta{}, tfdiags.Diagnostics{}, nil - }), } // make our vendor paths @@ -1398,6 +1307,10 @@ func TestInit_pluginDirProvidersDoesNotGet(t *testing.T) { // should have been an error t.Fatalf("bad: \n%s", ui.OutputWriter) } + + if calls := providerSource.CallLog(); len(calls) > 0 { + t.Errorf("unexpected provider source calls (want none)\n%s", spew.Sdump(calls)) + } } // Verify that plugin-dir doesn't prevent discovery of internal providers @@ -1407,10 +1320,15 @@ func TestInit_pluginWithInternal(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + // An empty provider source + providerSource, close := newMockProviderSource(t, nil) + defer close() + ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(testProvider()), Ui: ui, + ProviderSource: providerSource, } c := &InitCommand{ @@ -1455,3 +1373,54 @@ func TestInit_syntaxErrorUpgradeHint(t *testing.T) { t.Fatalf("wrong output\ngot:\n%s\n\nwant: message containing %q", got, want) } } + +// newMockProviderSource is a helper to succinctly construct a mock provider +// source that contains a set of packages matching the given provider versions +// that are available for installation (from temporary local files). +// +// The caller must call the returned close callback once the source is no +// longer needed, at which point it will clean up all of the temporary files +// and the packages in the source will no longer be available for installation. +// +// For ease of use in the common case, this function just treats all of the +// provider given names as "default" providers under +// registry.terraform.io/hashicorp . If you need more control over the +// provider addresses, construct a getproviders.MockSource directly instead. +// +// This function also registers providers as belonging to the current platform, +// to ensure that they will be available to a provider installer operating in +// its default configuration. +// +// In case of any errors while constructing the source, this function will +// abort the current test using the given testing.T. Therefore a caller can +// assume that if this function returns then the result is valid and ready +// to use. +func newMockProviderSource(t *testing.T, availableProviderVersions map[string][]string) (source *getproviders.MockSource, close func()) { + t.Helper() + var packages []getproviders.PackageMeta + var closes []func() + close = func() { + for _, f := range closes { + f() + } + } + for name, versions := range availableProviderVersions { + addr := addrs.NewDefaultProvider(name) + for _, versionStr := range versions { + version, err := getproviders.ParseVersion(versionStr) + if err != nil { + close() + 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) + if err != nil { + close() + t.Fatalf("failed to prepare fake package for %s %s: %s", name, versionStr, err) + } + closes = append(closes, close) + packages = append(packages, meta) + } + } + + return getproviders.NewMockSource(packages), close +} diff --git a/command/internal_plugin_test.go b/command/internal_plugin_test.go index 832ec6b15..bcfb97826 100644 --- a/command/internal_plugin_test.go +++ b/command/internal_plugin_test.go @@ -2,8 +2,6 @@ package command import ( "testing" - - "github.com/hashicorp/terraform/addrs" ) func TestInternalPlugin_InternalProviders(t *testing.T) { @@ -11,7 +9,7 @@ func TestInternalPlugin_InternalProviders(t *testing.T) { providers := m.internalProviders() // terraform is the only provider moved back to internal for _, name := range []string{"terraform"} { - pf, ok := providers[addrs.NewLegacyProvider(name)] + pf, ok := providers[name] if !ok { t.Errorf("Expected to find %s in InternalProviders", name) } diff --git a/command/plugins_test.go b/command/plugins_test.go index 19eaf5964..379cc5bc5 100644 --- a/command/plugins_test.go +++ b/command/plugins_test.go @@ -1,102 +1,11 @@ package command import ( - "fmt" "os" - "path/filepath" "reflect" "testing" - - "github.com/hashicorp/terraform/addrs" - "github.com/hashicorp/terraform/configs/configschema" - "github.com/hashicorp/terraform/plugin/discovery" - "github.com/hashicorp/terraform/providers" - "github.com/hashicorp/terraform/terraform" - "github.com/hashicorp/terraform/tfdiags" ) -func TestMultiVersionProviderResolver(t *testing.T) { - available := make(discovery.PluginMetaSet) - available.Add(discovery.PluginMeta{ - Name: "plugin", - Version: "1.0.0", - Path: "testdata/empty-file", - }) - - resolver := &multiVersionProviderResolver{ - Internal: map[addrs.Provider]providers.Factory{ - addrs.NewLegacyProvider("internal"): providers.FactoryFixed( - &terraform.MockProvider{ - GetSchemaReturn: &terraform.ProviderSchema{ - ResourceTypes: map[string]*configschema.Block{ - "internal_foo": {}, - }, - }, - }, - ), - }, - Available: available, - } - - t.Run("plugin matches", func(t *testing.T) { - reqd := discovery.PluginRequirements{ - "plugin": &discovery.PluginConstraints{ - Versions: discovery.ConstraintStr("1.0.0").MustParse(), - }, - } - got, err := resolver.ResolveProviders(reqd) - if err != nil { - t.Fatalf("unexpected error: %s", err) - } - if ct := len(got); ct != 1 { - t.Errorf("wrong number of results %d; want 1", ct) - } - if _, exists := got[addrs.NewLegacyProvider("plugin")]; !exists { - t.Errorf("provider \"plugin\" not in result") - } - }) - t.Run("plugin doesn't match", func(t *testing.T) { - reqd := discovery.PluginRequirements{ - "plugin": &discovery.PluginConstraints{ - Versions: discovery.ConstraintStr("2.0.0").MustParse(), - }, - } - _, err := resolver.ResolveProviders(reqd) - if err == nil { - t.Errorf("resolved successfully, but want error") - } - }) - t.Run("internal matches", func(t *testing.T) { - reqd := discovery.PluginRequirements{ - "internal": &discovery.PluginConstraints{ - Versions: discovery.AllVersions, - }, - } - got, err := resolver.ResolveProviders(reqd) - if err != nil { - t.Fatalf("unexpected error: %s", err) - } - if ct := len(got); ct != 1 { - t.Errorf("wrong number of results %d; want 1", ct) - } - if _, exists := got[addrs.NewLegacyProvider("internal")]; !exists { - t.Errorf("provider \"internal\" not in result") - } - }) - t.Run("internal with version constraint", func(t *testing.T) { - // Version constraints are not permitted for internal providers - reqd := discovery.PluginRequirements{ - "internal": &discovery.PluginConstraints{ - Versions: discovery.ConstraintStr("2.0.0").MustParse(), - }, - } - _, err := resolver.ResolveProviders(reqd) - if err == nil { - t.Errorf("resolved successfully, but want error") - } - }) -} - func TestPluginPath(t *testing.T) { td := testTempDir(t) defer os.RemoveAll(td) @@ -122,7 +31,7 @@ func TestPluginPath(t *testing.T) { func TestInternalProviders(t *testing.T) { m := Meta{} internal := m.internalProviders() - tfProvider, err := internal[addrs.NewLegacyProvider("terraform")]() + tfProvider, err := internal["terraform"]() if err != nil { t.Fatal(err) } @@ -133,79 +42,3 @@ func TestInternalProviders(t *testing.T) { t.Errorf("didn't find terraform_remote_state in internal \"terraform\" provider") } } - -// mockProviderInstaller is a discovery.PluginInstaller implementation that -// is a mock for discovery.ProviderInstaller. -type mockProviderInstaller struct { - // A map of provider names to available versions. - // The tests expect the versions to be in order from newest to oldest. - Providers map[string][]string - - Dir string - PurgeUnusedCalled bool -} - -func (i *mockProviderInstaller) FileName(provider, version string) string { - return fmt.Sprintf("terraform-provider-%s_v%s_x4", provider, version) -} - -func (i *mockProviderInstaller) Get(provider addrs.Provider, req discovery.Constraints) (discovery.PluginMeta, tfdiags.Diagnostics, error) { - var diags tfdiags.Diagnostics - noMeta := discovery.PluginMeta{} - versions := i.Providers[provider.Type] - if len(versions) == 0 { - return noMeta, diags, fmt.Errorf("provider %q not found", provider) - } - - err := os.MkdirAll(i.Dir, 0755) - if err != nil { - return noMeta, diags, fmt.Errorf("error creating plugins directory: %s", err) - } - - for _, v := range versions { - version, err := discovery.VersionStr(v).Parse() - if err != nil { - panic(err) - } - - if req.Allows(version) { - // provider filename - name := i.FileName(provider.Type, v) - path := filepath.Join(i.Dir, name) - f, err := os.Create(path) - if err != nil { - return noMeta, diags, fmt.Errorf("error fetching provider: %s", err) - } - f.Close() - return discovery.PluginMeta{ - Name: provider.Type, - Version: discovery.VersionStr(v), - Path: path, - }, diags, nil - } - } - - return noMeta, diags, fmt.Errorf("no suitable version for provider %q found with constraints %s", provider, req) -} - -func (i *mockProviderInstaller) PurgeUnused(map[string]discovery.PluginMeta) (discovery.PluginMetaSet, error) { - i.PurgeUnusedCalled = true - ret := make(discovery.PluginMetaSet) - ret.Add(discovery.PluginMeta{ - Name: "test", - Version: "0.0.0", - Path: "mock-test", - }) - return ret, nil -} - -type callbackPluginInstaller func(provider string, req discovery.Constraints) (discovery.PluginMeta, tfdiags.Diagnostics, error) - -func (cb callbackPluginInstaller) Get(provider addrs.Provider, req discovery.Constraints) (discovery.PluginMeta, tfdiags.Diagnostics, error) { - return cb(provider.Type, req) -} - -func (cb callbackPluginInstaller) PurgeUnused(map[string]discovery.PluginMeta) (discovery.PluginMetaSet, error) { - // does nothing - return make(discovery.PluginMetaSet), nil -} diff --git a/command/providers_schema_test.go b/command/providers_schema_test.go index b556bf876..1b600aeb0 100644 --- a/command/providers_schema_test.go +++ b/command/providers_schema_test.go @@ -49,22 +49,22 @@ func TestProvidersSchema_output(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + p := showFixtureProvider() ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(p), Ui: ui, + ProviderSource: providerSource, } // `terrafrom init` ic := &InitCommand{ Meta: m, - providerInstaller: &mockProviderInstaller{ - Providers: map[string][]string{ - "test": []string{"1.2.3"}, - }, - Dir: m.pluginDir(), - }, } if code := ic.Run([]string{}); code != 0 { t.Fatalf("init failed\n%s", ui.ErrorWriter) diff --git a/command/show_test.go b/command/show_test.go index 2e81933f4..f1a637221 100644 --- a/command/show_test.go +++ b/command/show_test.go @@ -250,22 +250,22 @@ func TestShow_json_output(t *testing.T) { expectError := strings.Contains(entry.Name(), "error") + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + p := showFixtureProvider() ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(p), Ui: ui, + ProviderSource: providerSource, } // init ic := &InitCommand{ Meta: m, - providerInstaller: &mockProviderInstaller{ - Providers: map[string][]string{ - "test": []string{"1.2.3"}, - }, - Dir: m.pluginDir(), - }, } if code := ic.Run([]string{}); code != 0 { if expectError { @@ -347,22 +347,22 @@ func TestShow_json_output_state(t *testing.T) { defer os.RemoveAll(td) defer testChdir(t, td)() + providerSource, close := newMockProviderSource(t, map[string][]string{ + "test": []string{"1.2.3"}, + }) + defer close() + p := showFixtureProvider() ui := new(cli.MockUi) m := Meta{ testingOverrides: metaOverridesForProvider(p), Ui: ui, + ProviderSource: providerSource, } // init ic := &InitCommand{ Meta: m, - providerInstaller: &mockProviderInstaller{ - Providers: map[string][]string{ - "test": []string{"1.2.3"}, - }, - Dir: m.pluginDir(), - }, } if code := ic.Run([]string{}); code != 0 { t.Fatalf("init failed\n%s", ui.ErrorWriter)