2017-05-04 20:32:18 +02:00
|
|
|
package discovery
|
|
|
|
|
|
|
|
import (
|
2017-06-01 20:34:47 +02:00
|
|
|
"archive/zip"
|
2018-08-02 23:35:08 +02:00
|
|
|
"encoding/json"
|
2017-06-01 20:34:47 +02:00
|
|
|
"fmt"
|
|
|
|
"io"
|
|
|
|
"io/ioutil"
|
2018-08-02 23:35:08 +02:00
|
|
|
"log"
|
|
|
|
"net"
|
2017-05-04 20:32:18 +02:00
|
|
|
"net/http"
|
|
|
|
"net/http/httptest"
|
2017-06-01 20:34:47 +02:00
|
|
|
"os"
|
|
|
|
"path/filepath"
|
2017-06-13 03:22:47 +02:00
|
|
|
"reflect"
|
2018-08-02 23:35:08 +02:00
|
|
|
"runtime"
|
2017-06-01 20:34:47 +02:00
|
|
|
"strings"
|
2017-05-04 20:32:18 +02:00
|
|
|
"testing"
|
2017-08-14 13:32:48 +02:00
|
|
|
|
2019-10-11 11:34:26 +02:00
|
|
|
"github.com/hashicorp/terraform-svchost"
|
|
|
|
"github.com/hashicorp/terraform-svchost/disco"
|
2019-09-09 22:59:50 +02:00
|
|
|
"github.com/hashicorp/terraform/addrs"
|
2019-10-11 11:34:26 +02:00
|
|
|
"github.com/hashicorp/terraform/httpclient"
|
2018-08-02 23:35:08 +02:00
|
|
|
"github.com/hashicorp/terraform/registry"
|
|
|
|
"github.com/hashicorp/terraform/registry/response"
|
2019-10-11 11:34:26 +02:00
|
|
|
"github.com/hashicorp/terraform/version"
|
2017-08-14 13:32:48 +02:00
|
|
|
"github.com/mitchellh/cli"
|
2017-05-04 20:32:18 +02:00
|
|
|
)
|
|
|
|
|
2017-06-01 20:34:47 +02:00
|
|
|
const testProviderFile = "test provider binary"
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
func TestMain(m *testing.M) {
|
|
|
|
server := testReleaseServer()
|
|
|
|
l, err := net.Listen("tcp", "127.0.0.1:8080")
|
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewUnstartedServer creates a listener. Close that listener and replace
|
|
|
|
// with the one we created.
|
|
|
|
server.Listener.Close()
|
|
|
|
server.Listener = l
|
|
|
|
server.Start()
|
|
|
|
defer server.Close()
|
|
|
|
|
|
|
|
os.Exit(m.Run())
|
|
|
|
}
|
|
|
|
|
2017-06-01 20:34:47 +02:00
|
|
|
// return the directory listing for the "test" provider
|
|
|
|
func testListingHandler(w http.ResponseWriter, r *http.Request) {
|
2018-08-02 23:35:08 +02:00
|
|
|
parts := strings.Split(r.URL.Path, "/")
|
|
|
|
if len(parts) != 6 {
|
|
|
|
http.Error(w, "not found", http.StatusNotFound)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
provider := parts[4]
|
|
|
|
if provider == "test" {
|
|
|
|
js, err := json.Marshal(versionList)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Write(js)
|
|
|
|
}
|
|
|
|
http.Error(w, ErrorNoSuchProvider.Error(), http.StatusNotFound)
|
|
|
|
return
|
|
|
|
|
|
|
|
}
|
|
|
|
|
|
|
|
// return the download URLs for the "test" provider
|
|
|
|
func testDownloadHandler(w http.ResponseWriter, r *http.Request) {
|
|
|
|
js, err := json.Marshal(downloadURLs)
|
|
|
|
if err != nil {
|
|
|
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
w.Write(js)
|
2017-06-01 20:34:47 +02:00
|
|
|
}
|
|
|
|
|
2017-06-19 22:20:10 +02:00
|
|
|
func testChecksumHandler(w http.ResponseWriter, r *http.Request) {
|
2018-08-02 23:35:08 +02:00
|
|
|
// this exact plugin has a signature and checksum file
|
2017-06-19 22:20:10 +02:00
|
|
|
if r.URL.Path == "/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS" {
|
|
|
|
http.ServeFile(w, r, "testdata/terraform-provider-template_0.1.0_SHA256SUMS")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if r.URL.Path == "/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig" {
|
|
|
|
http.ServeFile(w, r, "testdata/terraform-provider-template_0.1.0_SHA256SUMS.sig")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-06-21 21:24:13 +02:00
|
|
|
// this this checksum file is corrupt and doesn't match the sig
|
|
|
|
if r.URL.Path == "/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS" {
|
|
|
|
http.ServeFile(w, r, "testdata/terraform-provider-badsig_0.1.0_SHA256SUMS")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if r.URL.Path == "/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS.sig" {
|
|
|
|
http.ServeFile(w, r, "testdata/terraform-provider-badsig_0.1.0_SHA256SUMS.sig")
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2017-06-19 22:20:10 +02:00
|
|
|
http.Error(w, "signtaure files not found", http.StatusNotFound)
|
|
|
|
}
|
|
|
|
|
2017-06-01 20:34:47 +02:00
|
|
|
// returns a 200 for a valid provider url, using the patch number for the
|
|
|
|
// plugin protocol version.
|
|
|
|
func testHandler(w http.ResponseWriter, r *http.Request) {
|
2018-08-02 23:35:08 +02:00
|
|
|
if strings.HasSuffix(r.URL.Path, "/versions") {
|
2017-06-01 20:34:47 +02:00
|
|
|
testListingHandler(w, r)
|
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
if strings.Contains(r.URL.Path, "/download") {
|
|
|
|
testDownloadHandler(w, r)
|
2017-06-01 20:34:47 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
parts := strings.Split(r.URL.Path, "/")
|
|
|
|
if len(parts) != 7 {
|
|
|
|
http.Error(w, "not found", http.StatusNotFound)
|
2017-06-01 20:34:47 +02:00
|
|
|
return
|
|
|
|
}
|
|
|
|
|
|
|
|
// write a dummy file
|
|
|
|
z := zip.NewWriter(w)
|
2018-08-02 23:35:08 +02:00
|
|
|
fn := fmt.Sprintf("%s_v%s", parts[4], parts[5])
|
2017-06-13 03:22:47 +02:00
|
|
|
f, err := z.Create(fn)
|
2017-06-01 20:34:47 +02:00
|
|
|
if err != nil {
|
|
|
|
panic(err)
|
|
|
|
}
|
|
|
|
io.WriteString(f, testProviderFile)
|
|
|
|
z.Close()
|
|
|
|
}
|
|
|
|
|
2017-05-31 23:38:55 +02:00
|
|
|
func testReleaseServer() *httptest.Server {
|
2017-05-04 20:32:18 +02:00
|
|
|
handler := http.NewServeMux()
|
2018-11-28 17:26:16 +01:00
|
|
|
handler.HandleFunc("/v1/providers/-/", testHandler)
|
2018-08-02 23:35:08 +02:00
|
|
|
handler.HandleFunc("/v1/providers/terraform-providers/", testHandler)
|
2017-06-19 22:20:10 +02:00
|
|
|
handler.HandleFunc("/terraform-provider-template/", testChecksumHandler)
|
2017-06-21 21:24:13 +02:00
|
|
|
handler.HandleFunc("/terraform-provider-badsig/", testChecksumHandler)
|
2018-08-02 23:35:08 +02:00
|
|
|
handler.HandleFunc("/.well-known/terraform.json", func(w http.ResponseWriter, r *http.Request) {
|
|
|
|
w.Header().Set("Content-Type", "application/json")
|
|
|
|
io.WriteString(w, `{"modules.v1":"http://localhost/v1/modules/", "providers.v1":"http://localhost/v1/providers/"}`)
|
|
|
|
})
|
2017-05-04 20:32:18 +02:00
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
return httptest.NewUnstartedServer(handler)
|
2017-05-31 23:38:55 +02:00
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
func TestVersionListing(t *testing.T) {
|
2017-05-31 23:38:55 +02:00
|
|
|
server := testReleaseServer()
|
2018-08-02 23:35:08 +02:00
|
|
|
server.Start()
|
|
|
|
defer server.Close()
|
2017-05-04 20:32:18 +02:00
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
i := newProviderInstaller(server)
|
|
|
|
|
2019-09-09 22:59:50 +02:00
|
|
|
allVersions, err := i.listProviderVersions(addrs.ProviderType{Name: "test"})
|
2017-05-04 20:32:18 +02:00
|
|
|
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
var versions []*response.TerraformProviderVersion
|
2017-05-31 23:38:55 +02:00
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
for _, v := range allVersions.Versions {
|
|
|
|
versions = append(versions, v)
|
|
|
|
}
|
|
|
|
|
2018-08-09 19:05:17 +02:00
|
|
|
response.ProviderVersionCollection(versions).Sort()
|
2018-08-02 23:35:08 +02:00
|
|
|
|
|
|
|
expected := []*response.TerraformProviderVersion{
|
|
|
|
{Version: "1.2.4"},
|
|
|
|
{Version: "1.2.3"},
|
|
|
|
{Version: "1.2.1"},
|
2017-05-31 23:38:55 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
if len(versions) != len(expected) {
|
2019-03-07 21:07:13 +01:00
|
|
|
t.Fatalf("Received wrong number of versions. expected: %#v, got: %#v", expected, versions)
|
2017-05-04 20:32:18 +02:00
|
|
|
}
|
|
|
|
|
2017-05-31 23:38:55 +02:00
|
|
|
for i, v := range versions {
|
2018-08-02 23:35:08 +02:00
|
|
|
if v.Version != expected[i].Version {
|
2019-03-07 21:07:13 +01:00
|
|
|
t.Fatalf("incorrect version: %#v, expected %#v", v, expected[i])
|
2017-05-04 20:32:18 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-01 23:17:14 +02:00
|
|
|
func TestCheckProtocolVersions(t *testing.T) {
|
2018-08-02 23:35:08 +02:00
|
|
|
tests := []struct {
|
|
|
|
VersionMeta *response.TerraformProviderVersion
|
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Protocols: []string{"1", "2"},
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Protocols: []string{"4"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Protocols: []string{"4.2"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
2019-01-09 22:20:33 +01:00
|
|
|
{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Protocols: []string{"4.0", "5.2"},
|
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Protocols: []string{"5.0", "6.1"},
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
2017-05-04 20:46:20 +02:00
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
server := testReleaseServer()
|
|
|
|
server.Start()
|
|
|
|
defer server.Close()
|
|
|
|
i := newProviderInstaller(server)
|
|
|
|
|
|
|
|
for _, test := range tests {
|
|
|
|
err := i.checkPluginProtocol(test.VersionMeta)
|
|
|
|
if test.Err {
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("succeeded; want error")
|
|
|
|
}
|
|
|
|
} else if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
|
|
|
}
|
2017-06-01 20:34:47 +02:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-01-11 00:09:37 +01:00
|
|
|
func TestFindClosestProtocolCompatibleVersion(t *testing.T) {
|
|
|
|
testCases := []struct {
|
|
|
|
Name string
|
|
|
|
PluginProtocolVersion uint
|
|
|
|
ProviderVersions []*response.TerraformProviderVersion
|
|
|
|
ExpectedVersion string
|
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
{
|
|
|
|
"no compatible version",
|
|
|
|
5,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "1.0.0",
|
|
|
|
Protocols: []string{"4.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"",
|
|
|
|
true,
|
|
|
|
}, {
|
|
|
|
"equal, suggests latest",
|
|
|
|
4,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "1.0.0",
|
|
|
|
Protocols: []string{"4.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "1.5.0",
|
|
|
|
Protocols: []string{"4.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"1.5.0",
|
|
|
|
false,
|
|
|
|
}, {
|
|
|
|
"provider protocol too old, suggests earliest",
|
|
|
|
5,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "1.0.0",
|
|
|
|
Protocols: []string{"4.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.5.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "3.0.0",
|
|
|
|
Protocols: []string{"5.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"2.0.0",
|
|
|
|
false,
|
|
|
|
}, {
|
|
|
|
"provider protocol too new, suggests latest",
|
|
|
|
4,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "1.0.0",
|
|
|
|
Protocols: []string{"4.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.5.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "3.0.0",
|
|
|
|
Protocols: []string{"5.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"2.5.0",
|
|
|
|
false,
|
2019-01-11 19:47:45 +01:00
|
|
|
}, {
|
|
|
|
"compatible prereleses are filtered",
|
|
|
|
5,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0-alpha",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"",
|
|
|
|
true,
|
|
|
|
}, {
|
|
|
|
"suggests latest non-prerelease",
|
|
|
|
4,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0-alpha",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.5.0-pre",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.5.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"2.5.0",
|
|
|
|
false,
|
|
|
|
}, {
|
|
|
|
"suggests earliest non-prerelease",
|
|
|
|
5,
|
|
|
|
[]*response.TerraformProviderVersion{
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0-alpha",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.0.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "2.6.0",
|
|
|
|
Protocols: []string{"4.0", "5.0"},
|
|
|
|
},
|
|
|
|
&response.TerraformProviderVersion{
|
|
|
|
Version: "3.0.0",
|
|
|
|
Protocols: []string{"5.0"},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
"2.0.0",
|
|
|
|
false,
|
2019-01-11 00:09:37 +01:00
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
for _, tc := range testCases {
|
|
|
|
t.Run(tc.Name, func(t *testing.T) {
|
|
|
|
i := ProviderInstaller{
|
|
|
|
Ui: cli.NewMockUi(),
|
|
|
|
PluginProtocolVersion: tc.PluginProtocolVersion,
|
|
|
|
}
|
|
|
|
|
|
|
|
closestMatch, err := i.findClosestProtocolCompatibleVersion(tc.ProviderVersions)
|
|
|
|
if err != nil {
|
|
|
|
if !tc.Err {
|
|
|
|
t.Fatalf("unexpected error: %q", err)
|
|
|
|
}
|
|
|
|
return
|
|
|
|
}
|
|
|
|
if tc.ExpectedVersion != closestMatch.Version {
|
|
|
|
t.Errorf("Expected %q, got %q", tc.ExpectedVersion, closestMatch.Version)
|
|
|
|
}
|
|
|
|
})
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-13 03:27:13 +02:00
|
|
|
func TestProviderInstallerGet(t *testing.T) {
|
2018-08-02 23:35:08 +02:00
|
|
|
server := testReleaseServer()
|
|
|
|
server.Start()
|
|
|
|
defer server.Close()
|
|
|
|
|
2017-06-01 20:34:47 +02:00
|
|
|
tmpDir, err := ioutil.TempDir("", "tf-plugin")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
|
2017-06-01 23:17:14 +02:00
|
|
|
// attempt to use an incompatible protocol version
|
2017-06-13 03:22:47 +02:00
|
|
|
i := &ProviderInstaller{
|
2018-09-09 19:18:08 +02:00
|
|
|
Dir: tmpDir,
|
2017-06-13 03:22:47 +02:00
|
|
|
PluginProtocolVersion: 5,
|
2017-06-17 16:52:30 +02:00
|
|
|
SkipVerify: true,
|
2017-08-14 13:32:48 +02:00
|
|
|
Ui: cli.NewMockUi(),
|
2018-08-02 23:35:08 +02:00
|
|
|
registry: registry.NewClient(Disco(server), nil),
|
2017-06-13 03:22:47 +02:00
|
|
|
}
|
2019-09-09 22:59:50 +02:00
|
|
|
|
|
|
|
_, _, err = i.Get(addrs.ProviderType{Name: "test"}, AllVersions)
|
2018-08-02 23:35:08 +02:00
|
|
|
|
|
|
|
if err != ErrorNoVersionCompatibleWithPlatform {
|
2017-06-13 03:22:47 +02:00
|
|
|
t.Fatal("want error for incompatible version")
|
2017-06-01 23:17:14 +02:00
|
|
|
}
|
2017-06-01 20:34:47 +02:00
|
|
|
|
2017-06-13 03:22:47 +02:00
|
|
|
i = &ProviderInstaller{
|
2018-09-09 19:18:08 +02:00
|
|
|
Dir: tmpDir,
|
2018-08-02 23:35:08 +02:00
|
|
|
PluginProtocolVersion: 4,
|
2017-06-17 16:52:30 +02:00
|
|
|
SkipVerify: true,
|
2017-08-14 13:32:48 +02:00
|
|
|
Ui: cli.NewMockUi(),
|
2018-08-02 23:35:08 +02:00
|
|
|
registry: registry.NewClient(Disco(server), nil),
|
2018-10-16 17:08:29 +02:00
|
|
|
OS: "mockos",
|
|
|
|
Arch: "mockarch",
|
2017-06-13 03:22:47 +02:00
|
|
|
}
|
2017-06-20 03:48:42 +02:00
|
|
|
|
|
|
|
{
|
2019-09-09 22:59:50 +02:00
|
|
|
_, _, err := i.Get(addrs.ProviderType{Name: "test"}, ConstraintStr(">9.0.0").MustParse())
|
2017-06-20 03:48:42 +02:00
|
|
|
if err != ErrorNoSuitableVersion {
|
|
|
|
t.Fatal("want error for mismatching constraints")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
{
|
2019-09-09 22:59:50 +02:00
|
|
|
provider := addrs.ProviderType{Name: "nonexist"}
|
|
|
|
_, _, err := i.Get(provider, AllVersions)
|
2017-06-20 03:48:42 +02:00
|
|
|
if err != ErrorNoSuchProvider {
|
|
|
|
t.Fatal("want error for no such provider")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2019-09-09 22:59:50 +02:00
|
|
|
gotMeta, _, err := i.Get(addrs.ProviderType{Name: "test"}, AllVersions)
|
2017-06-01 20:34:47 +02:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
// we should have version 1.2.4
|
|
|
|
dest := filepath.Join(tmpDir, "terraform-provider-test_v1.2.4")
|
2017-06-13 03:22:47 +02:00
|
|
|
|
|
|
|
wantMeta := PluginMeta{
|
|
|
|
Name: "test",
|
2018-08-02 23:35:08 +02:00
|
|
|
Version: VersionStr("1.2.4"),
|
2017-06-13 03:22:47 +02:00
|
|
|
Path: dest,
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(gotMeta, wantMeta) {
|
|
|
|
t.Errorf("wrong result meta\ngot: %#v\nwant: %#v", gotMeta, wantMeta)
|
|
|
|
}
|
|
|
|
|
2017-06-01 20:34:47 +02:00
|
|
|
f, err := ioutil.ReadFile(dest)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// provider should have been unzipped
|
|
|
|
if string(f) != testProviderFile {
|
|
|
|
t.Fatalf("test provider contains: %q", f)
|
|
|
|
}
|
|
|
|
|
|
|
|
}
|
|
|
|
|
2019-03-05 21:39:24 +01:00
|
|
|
// test that the provider installer can install plugins from a plugin cache dir
|
|
|
|
// into a target directory that does not exist.
|
|
|
|
// https://github.com/hashicorp/terraform/issues/20532
|
|
|
|
func TestProviderInstallerGet_cache(t *testing.T) {
|
|
|
|
server := testReleaseServer()
|
|
|
|
server.Start()
|
|
|
|
defer server.Close()
|
|
|
|
|
|
|
|
tmpDir, err := ioutil.TempDir("", "tf-plugin")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
cache := NewLocalPluginCache(filepath.Join(tmpDir, "cache"))
|
|
|
|
targetDir := filepath.Join(tmpDir, "non-existant-dir")
|
|
|
|
|
|
|
|
defer os.RemoveAll(tmpDir)
|
|
|
|
|
|
|
|
i := &ProviderInstaller{
|
|
|
|
Dir: targetDir,
|
|
|
|
Cache: cache,
|
|
|
|
PluginProtocolVersion: 4,
|
|
|
|
SkipVerify: true,
|
|
|
|
Ui: cli.NewMockUi(),
|
|
|
|
registry: registry.NewClient(Disco(server), nil),
|
|
|
|
OS: "mockos",
|
|
|
|
Arch: "mockarch",
|
|
|
|
}
|
|
|
|
|
2019-09-09 22:59:50 +02:00
|
|
|
gotMeta, _, err := i.Get(addrs.ProviderType{Name: "test"}, AllVersions)
|
2019-03-05 21:39:24 +01:00
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// we should have version 1.2.4
|
|
|
|
dest := filepath.Join(targetDir, "terraform-provider-test_v1.2.4")
|
|
|
|
|
|
|
|
wantMeta := PluginMeta{
|
|
|
|
Name: "test",
|
|
|
|
Version: VersionStr("1.2.4"),
|
|
|
|
Path: dest,
|
|
|
|
}
|
|
|
|
if !reflect.DeepEqual(gotMeta, wantMeta) {
|
|
|
|
t.Errorf("wrong result meta\ngot: %#v\nwant: %#v", gotMeta, wantMeta)
|
|
|
|
}
|
|
|
|
|
|
|
|
f, err := ioutil.ReadFile(dest)
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
|
|
|
// provider should have been unzipped
|
|
|
|
if string(f) != testProviderFile {
|
|
|
|
t.Fatalf("test provider contains: %q", f)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-13 03:27:13 +02:00
|
|
|
func TestProviderInstallerPurgeUnused(t *testing.T) {
|
2018-08-02 23:35:08 +02:00
|
|
|
server := testReleaseServer()
|
|
|
|
defer server.Close()
|
|
|
|
|
2017-06-13 03:27:13 +02:00
|
|
|
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{
|
2018-09-09 19:18:08 +02:00
|
|
|
Dir: tmpDir,
|
2017-06-13 03:27:13 +02:00
|
|
|
PluginProtocolVersion: 3,
|
2017-06-17 16:52:30 +02:00
|
|
|
SkipVerify: true,
|
2017-08-14 13:32:48 +02:00
|
|
|
Ui: cli.NewMockUi(),
|
2018-08-02 23:35:08 +02:00
|
|
|
registry: registry.NewClient(Disco(server), nil),
|
2017-06-13 03:27:13 +02:00
|
|
|
}
|
|
|
|
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)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2017-06-19 22:20:10 +02:00
|
|
|
// Test fetching a provider's checksum file while verifying its signature.
|
|
|
|
func TestProviderChecksum(t *testing.T) {
|
2018-11-14 20:52:46 +01:00
|
|
|
hashicorpKey, err := ioutil.ReadFile("testdata/hashicorp.asc")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
tests := []struct {
|
2018-11-14 20:52:46 +01:00
|
|
|
Name string
|
2019-03-21 17:17:15 +01:00
|
|
|
Resp *response.TerraformProviderPlatformLocation
|
2018-08-02 23:35:08 +02:00
|
|
|
Err bool
|
|
|
|
}{
|
|
|
|
{
|
2018-11-14 20:52:46 +01:00
|
|
|
"good",
|
2018-08-02 23:35:08 +02:00
|
|
|
&response.TerraformProviderPlatformLocation{
|
2018-11-14 20:52:46 +01:00
|
|
|
Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip",
|
2019-03-21 17:17:15 +01:00
|
|
|
Shasum: "3c3e7df78b1f0161a3f941c271d5501f7b5e5f2c53738e7a371459712f5d4726",
|
2018-08-02 23:35:08 +02:00
|
|
|
ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS",
|
|
|
|
ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig",
|
2018-11-14 20:52:46 +01:00
|
|
|
SigningKeys: response.SigningKeyList{
|
|
|
|
GPGKeys: []*response.GPGKey{
|
|
|
|
&response.GPGKey{
|
|
|
|
ASCIIArmor: string(hashicorpKey),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
2018-08-02 23:35:08 +02:00
|
|
|
},
|
|
|
|
false,
|
|
|
|
},
|
|
|
|
{
|
2018-11-14 20:52:46 +01:00
|
|
|
"bad",
|
2018-08-02 23:35:08 +02:00
|
|
|
&response.TerraformProviderPlatformLocation{
|
2018-11-14 20:52:46 +01:00
|
|
|
Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip",
|
2018-08-02 23:35:08 +02:00
|
|
|
ShasumsURL: "http://127.0.0.1:8080/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS",
|
|
|
|
ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-badsig/0.1.0/terraform-provider-badsig_0.1.0_SHA256SUMS.sig",
|
2018-11-14 20:52:46 +01:00
|
|
|
SigningKeys: response.SigningKeyList{
|
|
|
|
GPGKeys: []*response.GPGKey{
|
|
|
|
&response.GPGKey{
|
|
|
|
ASCIIArmor: string(hashicorpKey),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"no keys",
|
|
|
|
&response.TerraformProviderPlatformLocation{
|
2018-08-02 23:35:08 +02:00
|
|
|
Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip",
|
2018-11-14 20:52:46 +01:00
|
|
|
ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS",
|
|
|
|
ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig",
|
|
|
|
SigningKeys: response.SigningKeyList{
|
|
|
|
GPGKeys: []*response.GPGKey{},
|
|
|
|
},
|
2018-08-02 23:35:08 +02:00
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
2019-03-21 17:17:15 +01:00
|
|
|
{
|
|
|
|
"mismatch checksum",
|
|
|
|
&response.TerraformProviderPlatformLocation{
|
|
|
|
Filename: "terraform-provider-template_0.1.0_darwin_amd64.zip",
|
|
|
|
Shasum: "force mismatch",
|
|
|
|
ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS",
|
|
|
|
ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig",
|
|
|
|
SigningKeys: response.SigningKeyList{
|
|
|
|
GPGKeys: []*response.GPGKey{
|
|
|
|
&response.GPGKey{
|
|
|
|
ASCIIArmor: string(hashicorpKey),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
|
|
|
{
|
|
|
|
"missing checksum for file",
|
|
|
|
&response.TerraformProviderPlatformLocation{
|
|
|
|
Filename: "terraform-provider-template_0.1.0_darwin_amd64_missing_checksum.zip",
|
|
|
|
Shasum: "checksum",
|
|
|
|
ShasumsURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS",
|
|
|
|
ShasumsSignatureURL: "http://127.0.0.1:8080/terraform-provider-template/0.1.0/terraform-provider-template_0.1.0_SHA256SUMS.sig",
|
|
|
|
SigningKeys: response.SigningKeyList{
|
|
|
|
GPGKeys: []*response.GPGKey{
|
|
|
|
&response.GPGKey{
|
|
|
|
ASCIIArmor: string(hashicorpKey),
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
true,
|
|
|
|
},
|
2017-06-19 22:20:10 +02:00
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
i := ProviderInstaller{}
|
2017-06-19 22:20:10 +02:00
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
for _, test := range tests {
|
2019-03-21 17:17:15 +01:00
|
|
|
t.Run(test.Name, func(t *testing.T) {
|
|
|
|
sha256sum, err := i.getProviderChecksum(test.Resp)
|
|
|
|
if test.Err {
|
|
|
|
if err == nil {
|
|
|
|
t.Fatal("succeeded; want error")
|
|
|
|
}
|
|
|
|
return
|
|
|
|
} else if err != nil {
|
|
|
|
t.Fatalf("unexpected error: %s", err)
|
2018-08-02 23:35:08 +02:00
|
|
|
}
|
2017-06-19 22:20:10 +02:00
|
|
|
|
2019-03-21 17:17:15 +01:00
|
|
|
// get the expected checksum for our os/arch
|
|
|
|
sumData, err := ioutil.ReadFile("testdata/terraform-provider-template_0.1.0_SHA256SUMS")
|
|
|
|
if err != nil {
|
|
|
|
t.Fatal(err)
|
|
|
|
}
|
2017-06-19 22:20:10 +02:00
|
|
|
|
2019-03-21 17:17:15 +01:00
|
|
|
expected := checksumForFile(sumData, test.Resp.Filename)
|
2017-07-03 23:56:11 +02:00
|
|
|
|
2019-03-21 17:17:15 +01:00
|
|
|
if sha256sum != expected {
|
|
|
|
t.Fatalf("expected: %s\ngot %s\n", sha256sum, expected)
|
|
|
|
}
|
|
|
|
})
|
2017-06-21 21:24:13 +02:00
|
|
|
}
|
2018-08-02 23:35:08 +02:00
|
|
|
}
|
2017-06-21 21:24:13 +02:00
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
// newProviderInstaller returns a minimally-initialized ProviderInstaller
|
|
|
|
func newProviderInstaller(s *httptest.Server) ProviderInstaller {
|
|
|
|
return ProviderInstaller{
|
2019-01-09 22:20:33 +01:00
|
|
|
registry: registry.NewClient(Disco(s), nil),
|
|
|
|
OS: runtime.GOOS,
|
|
|
|
Arch: runtime.GOARCH,
|
|
|
|
PluginProtocolVersion: 4,
|
2017-06-21 21:24:13 +02:00
|
|
|
}
|
2018-08-02 23:35:08 +02:00
|
|
|
}
|
2017-06-21 21:24:13 +02:00
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
// Disco return a *disco.Disco mapping registry.terraform.io, localhost,
|
|
|
|
// localhost.localdomain, and example.com to the test server.
|
|
|
|
func Disco(s *httptest.Server) *disco.Disco {
|
|
|
|
services := map[string]interface{}{
|
|
|
|
// Note that both with and without trailing slashes are supported behaviours
|
|
|
|
"modules.v1": fmt.Sprintf("%s/v1/modules", s.URL),
|
|
|
|
"providers.v1": fmt.Sprintf("%s/v1/providers", s.URL),
|
|
|
|
}
|
|
|
|
d := disco.New()
|
2019-10-11 11:34:26 +02:00
|
|
|
d.SetUserAgent(httpclient.TerraformUserAgent(version.String()))
|
2018-08-02 23:35:08 +02:00
|
|
|
|
|
|
|
d.ForceHostServices(svchost.Hostname("registry.terraform.io"), services)
|
|
|
|
d.ForceHostServices(svchost.Hostname("localhost"), services)
|
|
|
|
d.ForceHostServices(svchost.Hostname("localhost.localdomain"), services)
|
|
|
|
d.ForceHostServices(svchost.Hostname("example.com"), services)
|
|
|
|
return d
|
2017-06-21 21:24:13 +02:00
|
|
|
}
|
|
|
|
|
2018-08-02 23:35:08 +02:00
|
|
|
var versionList = response.TerraformProvider{
|
2018-11-28 17:26:16 +01:00
|
|
|
ID: "terraform-providers/test",
|
2018-08-02 23:35:08 +02:00
|
|
|
Versions: []*response.TerraformProviderVersion{
|
|
|
|
{Version: "1.2.1"},
|
|
|
|
{Version: "1.2.3"},
|
|
|
|
{
|
|
|
|
Version: "1.2.4",
|
|
|
|
Protocols: []string{"4"},
|
|
|
|
Platforms: []*response.TerraformProviderPlatform{
|
|
|
|
{
|
2018-10-16 17:08:29 +02:00
|
|
|
OS: "mockos",
|
|
|
|
Arch: "mockarch",
|
2018-08-02 23:35:08 +02:00
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
},
|
|
|
|
}
|
|
|
|
|
|
|
|
var downloadURLs = response.TerraformProviderPlatformLocation{
|
|
|
|
ShasumsURL: "https://registry.terraform.io/terraform-provider-template/1.2.4/terraform-provider-test_1.2.4_SHA256SUMS",
|
|
|
|
ShasumsSignatureURL: "https://registry.terraform.io/terraform-provider-template/1.2.4/terraform-provider-test_1.2.4_SHA256SUMS.sig",
|
|
|
|
Filename: "terraform-provider-template_1.2.4_darwin_amd64.zip",
|
|
|
|
DownloadURL: "http://127.0.0.1:8080/v1/providers/terraform-providers/terraform-provider-test/1.2.4/terraform-provider-test_1.2.4_darwin_amd64.zip",
|
|
|
|
}
|