internal/getproviders: Package URL should always be absolute
Registries backed by static files are likely to use relative paths to their archives for simplicity's sake, but we'll normalize them to be absolute before returning because the caller wouldn't otherwise know what to resolve the URLs relative to.
This commit is contained in:
parent
c8f7223adb
commit
a77bc59c44
|
@ -201,6 +201,15 @@ func (c *registryClient) PackageMeta(provider addrs.Provider, version Version, t
|
||||||
}
|
}
|
||||||
protoVersions.Sort()
|
protoVersions.Sort()
|
||||||
|
|
||||||
|
downloadURL, err := url.Parse(body.DownloadURL)
|
||||||
|
if err != nil {
|
||||||
|
return PackageMeta{}, fmt.Errorf("registry response includes invalid download URL: %s", err)
|
||||||
|
}
|
||||||
|
downloadURL = resp.Request.URL.ResolveReference(downloadURL)
|
||||||
|
if downloadURL.Scheme != "http" && downloadURL.Scheme != "https" {
|
||||||
|
return PackageMeta{}, fmt.Errorf("registry response includes invalid download URL: must use http or https scheme")
|
||||||
|
}
|
||||||
|
|
||||||
ret := PackageMeta{
|
ret := PackageMeta{
|
||||||
ProtocolVersions: protoVersions,
|
ProtocolVersions: protoVersions,
|
||||||
TargetPlatform: Platform{
|
TargetPlatform: Platform{
|
||||||
|
@ -208,7 +217,7 @@ func (c *registryClient) PackageMeta(provider addrs.Provider, version Version, t
|
||||||
Arch: body.Arch,
|
Arch: body.Arch,
|
||||||
},
|
},
|
||||||
Filename: body.Filename,
|
Filename: body.Filename,
|
||||||
Location: PackageHTTPURL(body.DownloadURL),
|
Location: PackageHTTPURL(downloadURL.String()),
|
||||||
// SHA256Sum is populated below
|
// SHA256Sum is populated below
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -25,10 +25,10 @@ import (
|
||||||
// The second return value is a function to call at the end of a test function
|
// The second return value is a function to call at the end of a test function
|
||||||
// to shut down the test server. After you call that function, the discovery
|
// to shut down the test server. After you call that function, the discovery
|
||||||
// object becomes useless.
|
// object becomes useless.
|
||||||
func testServices(t *testing.T) (*disco.Disco, func()) {
|
func testServices(t *testing.T) (services *disco.Disco, baseURL string, cleanup func()) {
|
||||||
server := httptest.NewServer(http.HandlerFunc(fakeRegistryHandler))
|
server := httptest.NewServer(http.HandlerFunc(fakeRegistryHandler))
|
||||||
|
|
||||||
services := disco.New()
|
services = disco.New()
|
||||||
services.ForceHostServices(svchost.Hostname("example.com"), map[string]interface{}{
|
services.ForceHostServices(svchost.Hostname("example.com"), map[string]interface{}{
|
||||||
"providers.v1": server.URL + "/providers/v1/",
|
"providers.v1": server.URL + "/providers/v1/",
|
||||||
})
|
})
|
||||||
|
@ -42,7 +42,7 @@ func testServices(t *testing.T) (*disco.Disco, func()) {
|
||||||
"providers.v1": server.URL + "/fails-immediately/",
|
"providers.v1": server.URL + "/fails-immediately/",
|
||||||
})
|
})
|
||||||
|
|
||||||
return services, func() {
|
return services, server.URL, func() {
|
||||||
server.Close()
|
server.Close()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,10 +53,10 @@ func testServices(t *testing.T) (*disco.Disco, func()) {
|
||||||
//
|
//
|
||||||
// As with testServices, the second return value is a function to call at the end
|
// As with testServices, the second return value is a function to call at the end
|
||||||
// of your test in order to shut down the test server.
|
// of your test in order to shut down the test server.
|
||||||
func testRegistrySource(t *testing.T) (*RegistrySource, func()) {
|
func testRegistrySource(t *testing.T) (source *RegistrySource, baseURL string, cleanup func()) {
|
||||||
services, close := testServices(t)
|
services, baseURL, close := testServices(t)
|
||||||
source := NewRegistrySource(services)
|
source = NewRegistrySource(services)
|
||||||
return source, close
|
return source, baseURL, close
|
||||||
}
|
}
|
||||||
|
|
||||||
func fakeRegistryHandler(resp http.ResponseWriter, req *http.Request) {
|
func fakeRegistryHandler(resp http.ResponseWriter, req *http.Request) {
|
||||||
|
|
|
@ -14,7 +14,7 @@ import (
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSourceAvailableVersions(t *testing.T) {
|
func TestSourceAvailableVersions(t *testing.T) {
|
||||||
source, close := testRegistrySource(t)
|
source, baseURL, close := testRegistrySource(t)
|
||||||
defer close()
|
defer close()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -52,15 +52,10 @@ func TestSourceAvailableVersions(t *testing.T) {
|
||||||
{
|
{
|
||||||
"fails.example.com/foo/bar",
|
"fails.example.com/foo/bar",
|
||||||
nil,
|
nil,
|
||||||
`could not query provider registry for fails.example.com/foo/bar: Get http://placeholder-origin/fails-immediately/foo/bar/versions: EOF`,
|
`could not query provider registry for fails.example.com/foo/bar: Get ` + baseURL + `/fails-immediately/foo/bar/versions: 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://[^/]+/`)
|
|
||||||
|
|
||||||
for _, test := range tests {
|
for _, test := range tests {
|
||||||
t.Run(test.provider, func(t *testing.T) {
|
t.Run(test.provider, func(t *testing.T) {
|
||||||
// TEMP: We don't yet have a function for parsing provider
|
// TEMP: We don't yet have a function for parsing provider
|
||||||
|
@ -78,8 +73,7 @@ func TestSourceAvailableVersions(t *testing.T) {
|
||||||
if test.wantErr == "" {
|
if test.wantErr == "" {
|
||||||
t.Fatalf("wrong error\ngot: %s\nwant: <nil>", err.Error())
|
t.Fatalf("wrong error\ngot: %s\nwant: <nil>", err.Error())
|
||||||
}
|
}
|
||||||
gotErr := urlPattern.ReplaceAllLiteralString(err.Error(), "http://placeholder-origin/")
|
if got, want := err.Error(), test.wantErr; got != want {
|
||||||
if got, want := gotErr, test.wantErr; got != want {
|
|
||||||
t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want)
|
t.Fatalf("wrong error\ngot: %s\nwant: %s", got, want)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
@ -106,7 +100,7 @@ func TestSourceAvailableVersions(t *testing.T) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestSourcePackageMeta(t *testing.T) {
|
func TestSourcePackageMeta(t *testing.T) {
|
||||||
source, close := testRegistrySource(t)
|
source, baseURL, close := testRegistrySource(t)
|
||||||
defer close()
|
defer close()
|
||||||
|
|
||||||
tests := []struct {
|
tests := []struct {
|
||||||
|
@ -126,7 +120,7 @@ func TestSourcePackageMeta(t *testing.T) {
|
||||||
ProtocolVersions: VersionList{versions.MustParseVersion("5.0.0")},
|
ProtocolVersions: VersionList{versions.MustParseVersion("5.0.0")},
|
||||||
TargetPlatform: Platform{"linux", "amd64"},
|
TargetPlatform: Platform{"linux", "amd64"},
|
||||||
Filename: "happycloud_1.2.0.zip",
|
Filename: "happycloud_1.2.0.zip",
|
||||||
Location: PackageHTTPURL("/pkg/happycloud_1.2.0.zip"),
|
Location: PackageHTTPURL(baseURL + "/pkg/happycloud_1.2.0.zip"),
|
||||||
SHA256Sum: [32]uint8{30: 0xf0, 31: 0x0d}, // fake registry uses a memorable sum
|
SHA256Sum: [32]uint8{30: 0xf0, 31: 0x0d}, // fake registry uses a memorable sum
|
||||||
},
|
},
|
||||||
``,
|
``,
|
||||||
|
|
Loading…
Reference in New Issue