github.com/hooklift/terraform@v0.11.0-beta1.0.20171117000744-6786c1361ffe/command/plugins_test.go (about)

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