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:
parent
f753974bb3
commit
af4c82d151
|
@ -6,6 +6,7 @@ import (
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"os"
|
||||||
"runtime"
|
"runtime"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -14,6 +15,7 @@ import (
|
||||||
|
|
||||||
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
cleanhttp "github.com/hashicorp/go-cleanhttp"
|
||||||
getter "github.com/hashicorp/go-getter"
|
getter "github.com/hashicorp/go-getter"
|
||||||
|
multierror "github.com/hashicorp/go-multierror"
|
||||||
)
|
)
|
||||||
|
|
||||||
// Releases are located by parsing the html listing from releases.hashicorp.com.
|
// 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.
|
// from an online repository.
|
||||||
type Installer interface {
|
type Installer interface {
|
||||||
Get(name string, req Constraints) (PluginMeta, error)
|
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
|
// 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)
|
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
|
// Return the plugin version by making a HEAD request to the provided url
|
||||||
func checkPlugin(url string, pluginProtocolVersion uint) bool {
|
func checkPlugin(url string, pluginProtocolVersion uint) bool {
|
||||||
resp, err := httpClient.Head(url)
|
resp, err := httpClient.Head(url)
|
||||||
|
|
|
@ -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")
|
tmpDir, err := ioutil.TempDir("", "tf-plugin")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatal(err)
|
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>
|
const versionList = `<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<body>
|
<body>
|
||||||
|
|
Loading…
Reference in New Issue