2017-05-04 13:03:57 -05:00
|
|
|
package command
|
|
|
|
|
|
|
|
import (
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2017-06-15 14:23:16 -05:00
|
|
|
"reflect"
|
|
|
|
"testing"
|
2017-05-04 13:03:57 -05:00
|
|
|
|
|
|
|
"github.com/hashicorp/terraform/plugin/discovery"
|
2017-11-03 13:36:31 -05:00
|
|
|
"github.com/hashicorp/terraform/terraform"
|
2017-05-04 13:03:57 -05:00
|
|
|
)
|
|
|
|
|
2017-11-03 13:36:31 -05:00
|
|
|
func TestMultiVersionProviderResolver(t *testing.T) {
|
|
|
|
available := make(discovery.PluginMetaSet)
|
|
|
|
available.Add(discovery.PluginMeta{
|
|
|
|
Name: "plugin",
|
|
|
|
Version: "1.0.0",
|
|
|
|
Path: "test-fixtures/empty-file",
|
|
|
|
})
|
|
|
|
|
|
|
|
resolver := &multiVersionProviderResolver{
|
|
|
|
Internal: map[string]terraform.ResourceProviderFactory{
|
|
|
|
"internal": func() (terraform.ResourceProvider, error) {
|
|
|
|
return &terraform.MockResourceProvider{
|
|
|
|
ResourcesReturn: []terraform.ResourceType{
|
|
|
|
{
|
|
|
|
Name: "internal_foo",
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}, nil
|
|
|
|
},
|
|
|
|
},
|
|
|
|
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["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["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")
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
|
2017-06-15 14:23:16 -05:00
|
|
|
func TestPluginPath(t *testing.T) {
|
2018-03-28 12:08:38 -05:00
|
|
|
td := testTempDir(t)
|
2017-06-15 14:23:16 -05:00
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-11-03 13:36:31 -05:00
|
|
|
func TestInternalProviders(t *testing.T) {
|
|
|
|
m := Meta{}
|
|
|
|
internal := m.internalProviders()
|
|
|
|
tfProvider, err := internal["terraform"]()
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
dataSources := tfProvider.DataSources()
|
|
|
|
found := false
|
|
|
|
for _, ds := range dataSources {
|
|
|
|
if ds.Name == "terraform_remote_state" {
|
|
|
|
found = true
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if !found {
|
|
|
|
t.Errorf("didn't find terraform_remote_state in internal \"terraform\" provider")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-12 20:22:47 -05:00
|
|
|
// mockProviderInstaller is a discovery.PluginInstaller implementation that
|
|
|
|
// is a mock for discovery.ProviderInstaller.
|
|
|
|
type mockProviderInstaller struct {
|
2017-05-04 13:03:57 -05:00
|
|
|
// 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
|
2017-06-12 20:22:47 -05:00
|
|
|
|
|
|
|
Dir string
|
|
|
|
PurgeUnusedCalled bool
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|
|
|
|
|
2017-06-12 20:22:47 -05:00
|
|
|
func (i *mockProviderInstaller) FileName(provider, version string) string {
|
2017-06-09 15:24:25 -05:00
|
|
|
return fmt.Sprintf("terraform-provider-%s_v%s_x4", provider, version)
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|
|
|
|
|
2017-06-12 20:22:47 -05:00
|
|
|
func (i *mockProviderInstaller) Get(provider string, req discovery.Constraints) (discovery.PluginMeta, error) {
|
|
|
|
noMeta := discovery.PluginMeta{}
|
|
|
|
versions := i.Providers[provider]
|
2017-05-04 13:03:57 -05:00
|
|
|
if len(versions) == 0 {
|
2017-06-12 20:22:47 -05:00
|
|
|
return noMeta, fmt.Errorf("provider %q not found", provider)
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|
|
|
|
|
2017-06-12 20:22:47 -05:00
|
|
|
err := os.MkdirAll(i.Dir, 0755)
|
2017-05-04 13:03:57 -05:00
|
|
|
if err != nil {
|
2017-06-12 20:22:47 -05:00
|
|
|
return noMeta, fmt.Errorf("error creating plugins directory: %s", err)
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
for _, v := range versions {
|
|
|
|
version, err := discovery.VersionStr(v).Parse()
|
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
|
2017-05-04 17:53:02 -05:00
|
|
|
if req.Allows(version) {
|
2017-05-04 13:03:57 -05:00
|
|
|
// provider filename
|
2017-06-12 20:22:47 -05:00
|
|
|
name := i.FileName(provider, v)
|
|
|
|
path := filepath.Join(i.Dir, name)
|
2017-05-04 13:03:57 -05:00
|
|
|
f, err := os.Create(path)
|
|
|
|
if err != nil {
|
2017-06-12 20:22:47 -05:00
|
|
|
return noMeta, fmt.Errorf("error fetching provider: %s", err)
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|
|
|
|
f.Close()
|
2017-06-12 20:22:47 -05:00
|
|
|
return discovery.PluginMeta{
|
|
|
|
Name: provider,
|
|
|
|
Version: discovery.VersionStr(v),
|
|
|
|
Path: path,
|
|
|
|
}, nil
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-12 20:22:47 -05:00
|
|
|
return noMeta, 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, error)
|
|
|
|
|
|
|
|
func (cb callbackPluginInstaller) Get(provider string, req discovery.Constraints) (discovery.PluginMeta, error) {
|
|
|
|
return cb(provider, req)
|
|
|
|
}
|
|
|
|
|
|
|
|
func (cb callbackPluginInstaller) PurgeUnused(map[string]discovery.PluginMeta) (discovery.PluginMetaSet, error) {
|
|
|
|
// does nothing
|
|
|
|
return make(discovery.PluginMetaSet), nil
|
2017-05-04 13:03:57 -05:00
|
|
|
}
|