github.com/paultyng/terraform@v0.6.11-0.20180227224804-66ff8f8bed40/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 }