mirror of
https://github.com/opentofu/opentofu.git
synced 2025-01-04 13:17:43 -06:00
92f427779d
The formatter in `command/format/state.go`, when formatting a resource with an aliased provider, was looking for a schema with the alias (ie, test.foo), but the schemas are only listed by provider type (test). Update the state formatter to lookup schemas by provider type only. Some of the show tests (and a couple others) were not properly cleaning up the created tmpdirs, so I fixed those. Also, the show tests are using a statefile named `state.tfstate`, but were not passing that path to the show command, so we were getting some false positives (a `show` command that returns `no state` exits 0). Fixes #21462
212 lines
5.8 KiB
Go
212 lines
5.8 KiB
Go
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)
|
|
defer testChdir(t, td)()
|
|
|
|
pluginPath := []string{"a", "b", "c"}
|
|
|
|
m := Meta{}
|
|
if err := m.storePluginPath(pluginPath); err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
restoredPath, err := m.loadPluginPath()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
if !reflect.DeepEqual(pluginPath, restoredPath) {
|
|
t.Fatalf("expected plugin path %#v, got %#v", pluginPath, restoredPath)
|
|
}
|
|
}
|
|
|
|
func TestInternalProviders(t *testing.T) {
|
|
m := Meta{}
|
|
internal := m.internalProviders()
|
|
tfProvider, err := internal[addrs.NewLegacyProvider("terraform")]()
|
|
if err != nil {
|
|
t.Fatal(err)
|
|
}
|
|
|
|
schema := tfProvider.GetSchema()
|
|
_, found := schema.DataSources["terraform_remote_state"]
|
|
if !found {
|
|
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
|
|
}
|