240 lines
7.3 KiB
Go
240 lines
7.3 KiB
Go
package getproviders
|
|
|
|
import (
|
|
"context"
|
|
"fmt"
|
|
"regexp"
|
|
"strings"
|
|
"testing"
|
|
|
|
"github.com/apparentlymart/go-versions/versions"
|
|
"github.com/google/go-cmp/cmp"
|
|
svchost "github.com/hashicorp/terraform-svchost"
|
|
|
|
"github.com/hashicorp/terraform/addrs"
|
|
)
|
|
|
|
func TestSourceAvailableVersions(t *testing.T) {
|
|
source, baseURL, close := testRegistrySource(t)
|
|
defer close()
|
|
|
|
tests := []struct {
|
|
provider string
|
|
wantVersions []string
|
|
wantErr string
|
|
}{
|
|
// These test cases are relying on behaviors of the fake provider
|
|
// registry server implemented in registry_client_test.go.
|
|
{
|
|
"example.com/awesomesauce/happycloud",
|
|
[]string{"0.1.0", "1.0.0", "1.2.0", "2.0.0"},
|
|
``,
|
|
},
|
|
{
|
|
"example.com/weaksauce/no-versions",
|
|
nil,
|
|
``, // having no versions is not an error, it's just odd
|
|
},
|
|
{
|
|
"example.com/nonexist/nonexist",
|
|
nil,
|
|
`provider registry example.com does not have a provider named example.com/nonexist/nonexist`,
|
|
},
|
|
{
|
|
"not.example.com/foo/bar",
|
|
nil,
|
|
`host not.example.com does not offer a Terraform provider registry`,
|
|
},
|
|
{
|
|
"too-new.example.com/foo/bar",
|
|
nil,
|
|
`host too-new.example.com does not support the provider registry protocol required by this Terraform version, but may be compatible with a different Terraform version`,
|
|
},
|
|
{
|
|
"fails.example.com/foo/bar",
|
|
nil,
|
|
`could not query provider registry for fails.example.com/foo/bar: the request failed after 2 attempts, please try again later: Get "` + baseURL + `/fails-immediately/foo/bar/versions": EOF`,
|
|
},
|
|
}
|
|
|
|
for _, test := range tests {
|
|
t.Run(test.provider, func(t *testing.T) {
|
|
provider := addrs.MustParseProviderSourceString(test.provider)
|
|
gotVersions, _, err := source.AvailableVersions(context.Background(), provider)
|
|
|
|
if err != nil {
|
|
if test.wantErr == "" {
|
|
t.Fatalf("wrong error\ngot: %s\nwant: <nil>", err.Error())
|
|
}
|
|
if got, want := err.Error(), test.wantErr; got != want {
|
|
t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want)
|
|
}
|
|
return
|
|
}
|
|
|
|
if test.wantErr != "" {
|
|
t.Fatalf("wrong error\ngot: <nil>\nwant: %s", test.wantErr)
|
|
}
|
|
|
|
var gotVersionsStr []string
|
|
if gotVersions != nil {
|
|
gotVersionsStr = make([]string, len(gotVersions))
|
|
for i, v := range gotVersions {
|
|
gotVersionsStr[i] = v.String()
|
|
}
|
|
}
|
|
|
|
if diff := cmp.Diff(test.wantVersions, gotVersionsStr); diff != "" {
|
|
t.Errorf("wrong result\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestSourceAvailableVersions_warnings(t *testing.T) {
|
|
source, _, close := testRegistrySource(t)
|
|
defer close()
|
|
|
|
provider := addrs.MustParseProviderSourceString("example.com/weaksauce/no-versions")
|
|
_, warnings, err := source.AvailableVersions(context.Background(), provider)
|
|
if err != nil {
|
|
t.Fatalf("unexpected error: %s", err.Error())
|
|
}
|
|
|
|
if len(warnings) != 1 {
|
|
t.Fatalf("wrong number of warnings. Expected 1, got %d", len(warnings))
|
|
}
|
|
|
|
}
|
|
|
|
func TestSourcePackageMeta(t *testing.T) {
|
|
source, baseURL, close := testRegistrySource(t)
|
|
defer close()
|
|
|
|
tests := []struct {
|
|
provider string
|
|
version string
|
|
os, arch string
|
|
want PackageMeta
|
|
wantHashes []Hash
|
|
wantErr string
|
|
}{
|
|
// These test cases are relying on behaviors of the fake provider
|
|
// registry server implemented in registry_client_test.go.
|
|
{
|
|
"example.com/awesomesauce/happycloud",
|
|
"1.2.0",
|
|
"linux", "amd64",
|
|
PackageMeta{
|
|
Provider: addrs.NewProvider(
|
|
svchost.Hostname("example.com"), "awesomesauce", "happycloud",
|
|
),
|
|
Version: versions.MustParseVersion("1.2.0"),
|
|
ProtocolVersions: VersionList{versions.MustParseVersion("5.0.0")},
|
|
TargetPlatform: Platform{"linux", "amd64"},
|
|
Filename: "happycloud_1.2.0.zip",
|
|
Location: PackageHTTPURL(baseURL + "/pkg/awesomesauce/happycloud_1.2.0.zip"),
|
|
Authentication: PackageAuthenticationAll(
|
|
NewMatchingChecksumAuthentication(
|
|
[]byte("000000000000000000000000000000000000000000000000000000000000f00d happycloud_1.2.0.zip\n000000000000000000000000000000000000000000000000000000000000face happycloud_1.2.0_face.zip\n"),
|
|
"happycloud_1.2.0.zip",
|
|
[32]byte{30: 0xf0, 31: 0x0d},
|
|
),
|
|
NewArchiveChecksumAuthentication(Platform{"linux", "amd64"}, [32]byte{30: 0xf0, 31: 0x0d}),
|
|
NewSignatureAuthentication(
|
|
[]byte("000000000000000000000000000000000000000000000000000000000000f00d happycloud_1.2.0.zip\n000000000000000000000000000000000000000000000000000000000000face happycloud_1.2.0_face.zip\n"),
|
|
[]byte("GPG signature"),
|
|
[]SigningKey{
|
|
{ASCIIArmor: HashicorpPublicKey},
|
|
},
|
|
),
|
|
),
|
|
},
|
|
[]Hash{
|
|
"zh:000000000000000000000000000000000000000000000000000000000000f00d",
|
|
"zh:000000000000000000000000000000000000000000000000000000000000face",
|
|
},
|
|
``,
|
|
},
|
|
{
|
|
"example.com/awesomesauce/happycloud",
|
|
"1.2.0",
|
|
"nonexist", "amd64",
|
|
PackageMeta{},
|
|
nil,
|
|
`provider example.com/awesomesauce/happycloud 1.2.0 is not available for nonexist_amd64`,
|
|
},
|
|
{
|
|
"not.example.com/awesomesauce/happycloud",
|
|
"1.2.0",
|
|
"linux", "amd64",
|
|
PackageMeta{},
|
|
nil,
|
|
`host not.example.com does not offer a Terraform provider registry`,
|
|
},
|
|
{
|
|
"too-new.example.com/awesomesauce/happycloud",
|
|
"1.2.0",
|
|
"linux", "amd64",
|
|
PackageMeta{},
|
|
nil,
|
|
`host too-new.example.com does not support the provider registry protocol required by this Terraform version, but may be compatible with a different Terraform version`,
|
|
},
|
|
{
|
|
"fails.example.com/awesomesauce/happycloud",
|
|
"1.2.0",
|
|
"linux", "amd64",
|
|
PackageMeta{},
|
|
nil,
|
|
`could not query provider registry for fails.example.com/awesomesauce/happycloud: the request failed after 2 attempts, please try again later: Get "http://placeholder-origin/fails-immediately/awesomesauce/happycloud/1.2.0/download/linux/amd64": EOF`,
|
|
},
|
|
}
|
|
|
|
// Sometimes error messages contain specific HTTP endpoint URLs, but
|
|
// since our test server is on a random port we'd not be able to
|
|
// consistently match those. Instead, we'll normalize the URLs.
|
|
urlPattern := regexp.MustCompile(`http://[^/]+/`)
|
|
|
|
cmpOpts := cmp.Comparer(Version.Same)
|
|
|
|
for _, test := range tests {
|
|
t.Run(fmt.Sprintf("%s for %s_%s", test.provider, test.os, test.arch), func(t *testing.T) {
|
|
// TEMP: We don't yet have a function for parsing provider
|
|
// source addresses so we'll just fake it in here for now.
|
|
parts := strings.Split(test.provider, "/")
|
|
providerAddr := addrs.Provider{
|
|
Hostname: svchost.Hostname(parts[0]),
|
|
Namespace: parts[1],
|
|
Type: parts[2],
|
|
}
|
|
|
|
version := versions.MustParseVersion(test.version)
|
|
|
|
got, err := source.PackageMeta(context.Background(), providerAddr, version, Platform{test.os, test.arch})
|
|
|
|
if err != nil {
|
|
if test.wantErr == "" {
|
|
t.Fatalf("wrong error\ngot: %s\nwant: <nil>", err.Error())
|
|
}
|
|
gotErr := urlPattern.ReplaceAllLiteralString(err.Error(), "http://placeholder-origin/")
|
|
if got, want := gotErr, test.wantErr; got != want {
|
|
t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want)
|
|
}
|
|
return
|
|
}
|
|
|
|
if test.wantErr != "" {
|
|
t.Fatalf("wrong error\ngot: <nil>\nwant: %s", test.wantErr)
|
|
}
|
|
|
|
if diff := cmp.Diff(test.want, got, cmpOpts); diff != "" {
|
|
t.Errorf("wrong result\n%s", diff)
|
|
}
|
|
if diff := cmp.Diff(test.wantHashes, got.AcceptableHashes()); diff != "" {
|
|
t.Errorf("wrong AcceptableHashes result\n%s", diff)
|
|
}
|
|
})
|
|
}
|
|
|
|
}
|