github.com/LorbusChris/terraform@v0.11.12-beta1/command/plugins_test.go (about)

     1  package command
     2  
     3  import (
     4  	"fmt"
     5  	"os"
     6  	"path/filepath"
     7  	"reflect"
     8  	"testing"
     9  
    10  	"github.com/hashicorp/terraform/plugin/discovery"
    11  	"github.com/hashicorp/terraform/terraform"
    12  )
    13  
    14  func TestMultiVersionProviderResolver(t *testing.T) {
    15  	available := make(discovery.PluginMetaSet)
    16  	available.Add(discovery.PluginMeta{
    17  		Name:    "plugin",
    18  		Version: "1.0.0",
    19  		Path:    "test-fixtures/empty-file",
    20  	})
    21  
    22  	resolver := &multiVersionProviderResolver{
    23  		Internal: map[string]terraform.ResourceProviderFactory{
    24  			"internal": func() (terraform.ResourceProvider, error) {
    25  				return &terraform.MockResourceProvider{
    26  					ResourcesReturn: []terraform.ResourceType{
    27  						{
    28  							Name: "internal_foo",
    29  						},
    30  					},
    31  				}, nil
    32  			},
    33  		},
    34  		Available: available,
    35  	}
    36  
    37  	t.Run("plugin matches", func(t *testing.T) {
    38  		reqd := discovery.PluginRequirements{
    39  			"plugin": &discovery.PluginConstraints{
    40  				Versions: discovery.ConstraintStr("1.0.0").MustParse(),
    41  			},
    42  		}
    43  		got, err := resolver.ResolveProviders(reqd)
    44  		if err != nil {
    45  			t.Fatalf("unexpected error: %s", err)
    46  		}
    47  		if ct := len(got); ct != 1 {
    48  			t.Errorf("wrong number of results %d; want 1", ct)
    49  		}
    50  		if _, exists := got["plugin"]; !exists {
    51  			t.Errorf("provider \"plugin\" not in result")
    52  		}
    53  	})
    54  	t.Run("plugin doesn't match", func(t *testing.T) {
    55  		reqd := discovery.PluginRequirements{
    56  			"plugin": &discovery.PluginConstraints{
    57  				Versions: discovery.ConstraintStr("2.0.0").MustParse(),
    58  			},
    59  		}
    60  		_, err := resolver.ResolveProviders(reqd)
    61  		if err == nil {
    62  			t.Errorf("resolved successfully, but want error")
    63  		}
    64  	})
    65  	t.Run("internal matches", func(t *testing.T) {
    66  		reqd := discovery.PluginRequirements{
    67  			"internal": &discovery.PluginConstraints{
    68  				Versions: discovery.AllVersions,
    69  			},
    70  		}
    71  		got, err := resolver.ResolveProviders(reqd)
    72  		if err != nil {
    73  			t.Fatalf("unexpected error: %s", err)
    74  		}
    75  		if ct := len(got); ct != 1 {
    76  			t.Errorf("wrong number of results %d; want 1", ct)
    77  		}
    78  		if _, exists := got["internal"]; !exists {
    79  			t.Errorf("provider \"internal\" not in result")
    80  		}
    81  	})
    82  	t.Run("internal with version constraint", func(t *testing.T) {
    83  		// Version constraints are not permitted for internal providers
    84  		reqd := discovery.PluginRequirements{
    85  			"internal": &discovery.PluginConstraints{
    86  				Versions: discovery.ConstraintStr("2.0.0").MustParse(),
    87  			},
    88  		}
    89  		_, err := resolver.ResolveProviders(reqd)
    90  		if err == nil {
    91  			t.Errorf("resolved successfully, but want error")
    92  		}
    93  	})
    94  }
    95  
    96  func TestPluginPath(t *testing.T) {
    97  	td := testTempDir(t)
    98  	defer testChdir(t, td)()
    99  
   100  	pluginPath := []string{"a", "b", "c"}
   101  
   102  	m := Meta{}
   103  	if err := m.storePluginPath(pluginPath); err != nil {
   104  		t.Fatal(err)
   105  	}
   106  
   107  	restoredPath, err := m.loadPluginPath()
   108  	if err != nil {
   109  		t.Fatal(err)
   110  	}
   111  
   112  	if !reflect.DeepEqual(pluginPath, restoredPath) {
   113  		t.Fatalf("expected plugin path %#v, got %#v", pluginPath, restoredPath)
   114  	}
   115  }
   116  
   117  func TestInternalProviders(t *testing.T) {
   118  	m := Meta{}
   119  	internal := m.internalProviders()
   120  	tfProvider, err := internal["terraform"]()
   121  	if err != nil {
   122  		t.Fatal(err)
   123  	}
   124  
   125  	dataSources := tfProvider.DataSources()
   126  	found := false
   127  	for _, ds := range dataSources {
   128  		if ds.Name == "terraform_remote_state" {
   129  			found = true
   130  		}
   131  	}
   132  	if !found {
   133  		t.Errorf("didn't find terraform_remote_state in internal \"terraform\" provider")
   134  	}
   135  }
   136  
   137  // mockProviderInstaller is a discovery.PluginInstaller implementation that
   138  // is a mock for discovery.ProviderInstaller.
   139  type mockProviderInstaller struct {
   140  	// A map of provider names to available versions.
   141  	// The tests expect the versions to be in order from newest to oldest.
   142  	Providers map[string][]string
   143  
   144  	Dir               string
   145  	PurgeUnusedCalled bool
   146  }
   147  
   148  func (i *mockProviderInstaller) FileName(provider, version string) string {
   149  	return fmt.Sprintf("terraform-provider-%s_v%s_x4", provider, version)
   150  }
   151  
   152  func (i *mockProviderInstaller) Get(provider string, req discovery.Constraints) (discovery.PluginMeta, error) {
   153  	noMeta := discovery.PluginMeta{}
   154  	versions := i.Providers[provider]
   155  	if len(versions) == 0 {
   156  		return noMeta, fmt.Errorf("provider %q not found", provider)
   157  	}
   158  
   159  	err := os.MkdirAll(i.Dir, 0755)
   160  	if err != nil {
   161  		return noMeta, fmt.Errorf("error creating plugins directory: %s", err)
   162  	}
   163  
   164  	for _, v := range versions {
   165  		version, err := discovery.VersionStr(v).Parse()
   166  		if err != nil {
   167  			panic(err)
   168  		}
   169  
   170  		if req.Allows(version) {
   171  			// provider filename
   172  			name := i.FileName(provider, v)
   173  			path := filepath.Join(i.Dir, name)
   174  			f, err := os.Create(path)
   175  			if err != nil {
   176  				return noMeta, fmt.Errorf("error fetching provider: %s", err)
   177  			}
   178  			f.Close()
   179  			return discovery.PluginMeta{
   180  				Name:    provider,
   181  				Version: discovery.VersionStr(v),
   182  				Path:    path,
   183  			}, nil
   184  		}
   185  	}
   186  
   187  	return noMeta, fmt.Errorf("no suitable version for provider %q found with constraints %s", provider, req)
   188  }
   189  
   190  func (i *mockProviderInstaller) PurgeUnused(map[string]discovery.PluginMeta) (discovery.PluginMetaSet, error) {
   191  	i.PurgeUnusedCalled = true
   192  	ret := make(discovery.PluginMetaSet)
   193  	ret.Add(discovery.PluginMeta{
   194  		Name:    "test",
   195  		Version: "0.0.0",
   196  		Path:    "mock-test",
   197  	})
   198  	return ret, nil
   199  }
   200  
   201  type callbackPluginInstaller func(provider string, req discovery.Constraints) (discovery.PluginMeta, error)
   202  
   203  func (cb callbackPluginInstaller) Get(provider string, req discovery.Constraints) (discovery.PluginMeta, error) {
   204  	return cb(provider, req)
   205  }
   206  
   207  func (cb callbackPluginInstaller) PurgeUnused(map[string]discovery.PluginMeta) (discovery.PluginMetaSet, error) {
   208  	// does nothing
   209  	return make(discovery.PluginMetaSet), nil
   210  }