github.com/nirarg/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 }