plugin/discovery: Installer.PurgeUnused method

Given a map describing the chosen plugin for each provider name, this
method should purge any other plugins present in the local cache
directory.
This commit is contained in:
Martin Atkins 2017-06-12 18:27:13 -07:00
parent f753974bb3
commit af4c82d151
2 changed files with 97 additions and 1 deletions

View File

@ -6,6 +6,7 @@ import (
"io/ioutil"
"log"
"net/http"
"os"
"runtime"
"strconv"
"strings"
@ -14,6 +15,7 @@ import (
cleanhttp "github.com/hashicorp/go-cleanhttp"
getter "github.com/hashicorp/go-getter"
multierror "github.com/hashicorp/go-multierror"
)
// Releases are located by parsing the html listing from releases.hashicorp.com.
@ -55,6 +57,7 @@ func providerURL(name, version string) string {
// from an online repository.
type Installer interface {
Get(name string, req Constraints) (PluginMeta, error)
PurgeUnused(used map[string]PluginMeta) (removed PluginMetaSet, err error)
}
// ProviderInstaller is an Installer implementation that knows how to
@ -140,6 +143,38 @@ func (i *ProviderInstaller) Get(provider string, req Constraints) (PluginMeta, e
return PluginMeta{}, fmt.Errorf("no versions of %q compatible with the plugin ProtocolVersion", provider)
}
func (i *ProviderInstaller) PurgeUnused(used map[string]PluginMeta) (PluginMetaSet, error) {
purge := make(PluginMetaSet)
present := FindPlugins("provider", []string{i.Dir})
for meta := range present {
chosen, ok := used[meta.Name]
if !ok {
purge.Add(meta)
}
if chosen.Path != meta.Path {
purge.Add(meta)
}
}
removed := make(PluginMetaSet)
var errs error
for meta := range purge {
path := meta.Path
err := os.Remove(path)
if err != nil {
errs = multierror.Append(errs, fmt.Errorf(
"failed to remove unused provider plugin %s: %s",
path, err,
))
} else {
removed.Add(meta)
}
}
return removed, errs
}
// Return the plugin version by making a HEAD request to the provided url
func checkPlugin(url string, pluginProtocolVersion uint) bool {
resp, err := httpClient.Head(url)

View File

@ -108,7 +108,7 @@ func TestCheckProtocolVersions(t *testing.T) {
}
}
func TestProviderInstaller(t *testing.T) {
func TestProviderInstallerGet(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "tf-plugin")
if err != nil {
t.Fatal(err)
@ -161,6 +161,67 @@ func TestProviderInstaller(t *testing.T) {
}
func TestProviderInstallerPurgeUnused(t *testing.T) {
tmpDir, err := ioutil.TempDir("", "tf-plugin")
if err != nil {
t.Fatal(err)
}
defer os.RemoveAll(tmpDir)
unwantedPath := filepath.Join(tmpDir, "terraform-provider-test_v0.0.1_x2")
wantedPath := filepath.Join(tmpDir, "terraform-provider-test_v1.2.3_x3")
f, err := os.Create(unwantedPath)
if err != nil {
t.Fatal(err)
}
f.Close()
f, err = os.Create(wantedPath)
if err != nil {
t.Fatal(err)
}
f.Close()
i := &ProviderInstaller{
Dir: tmpDir,
PluginProtocolVersion: 3,
}
purged, err := i.PurgeUnused(map[string]PluginMeta{
"test": PluginMeta{
Name: "test",
Version: VersionStr("1.2.3"),
Path: wantedPath,
},
})
if err != nil {
t.Fatal(err)
}
if got, want := purged.Count(), 1; got != want {
t.Errorf("wrong purged count %d; want %d", got, want)
}
if got, want := purged.Newest().Path, unwantedPath; got != want {
t.Errorf("wrong purged path %s; want %s", got, want)
}
files, err := ioutil.ReadDir(tmpDir)
if err != nil {
t.Fatal(err)
}
gotFilenames := make([]string, len(files))
for i, info := range files {
gotFilenames[i] = info.Name()
}
wantFilenames := []string{"terraform-provider-test_v1.2.3_x3"}
if !reflect.DeepEqual(gotFilenames, wantFilenames) {
t.Errorf("wrong filenames after purge\ngot: %#v\nwant: %#v", gotFilenames, wantFilenames)
}
}
const versionList = `<!DOCTYPE html>
<html>
<body>