internal: Fix LookupLegacyProvider
When looking up the namespace for a legacy provider source, we need to use the /v1/providers/-/{name}/versions endpoint. For non-HashiCorp providers, the /v1/providers/-/{name} endpoint returns a 404. This commit updates the LegacyProviderDefaultNamespace method and the mock registry servers accordingly.
This commit is contained in:
parent
f82700bc56
commit
62b0cbed12
|
@ -1,6 +1,7 @@
|
||||||
package command
|
package command
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
|
@ -361,21 +362,22 @@ func fakeRegistryHandler(resp http.ResponseWriter, req *http.Request) {
|
||||||
|
|
||||||
pathParts := strings.Split(path, "/")[3:]
|
pathParts := strings.Split(path, "/")[3:]
|
||||||
|
|
||||||
if len(pathParts) != 2 {
|
if len(pathParts) != 3 {
|
||||||
resp.WriteHeader(404)
|
resp.WriteHeader(404)
|
||||||
resp.Write([]byte(`unrecognized path scheme`))
|
resp.Write([]byte(`unrecognized path scheme`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if pathParts[0] != "-" {
|
if pathParts[0] != "-" || pathParts[2] != "versions" {
|
||||||
resp.WriteHeader(404)
|
resp.WriteHeader(404)
|
||||||
resp.Write([]byte(`this registry only supports legacy namespace lookup requests`))
|
resp.Write([]byte(`this registry only supports legacy namespace lookup requests`))
|
||||||
}
|
}
|
||||||
|
|
||||||
if namespace, ok := legacyProviderNamespaces[pathParts[1]]; ok {
|
name := pathParts[1]
|
||||||
|
if namespace, ok := legacyProviderNamespaces[name]; ok {
|
||||||
resp.Header().Set("Content-Type", "application/json")
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(`{"namespace":"` + namespace + `"}`))
|
resp.Write([]byte(fmt.Sprintf(`{"id":"%s/%s"}`, namespace, name)))
|
||||||
} else {
|
} else {
|
||||||
resp.WriteHeader(404)
|
resp.WriteHeader(404)
|
||||||
resp.Write([]byte(`provider not found`))
|
resp.Write([]byte(`provider not found`))
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package getproviders
|
package getproviders
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
|
@ -27,3 +28,37 @@ func TestLookupLegacyProvider(t *testing.T) {
|
||||||
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, want)
|
t.Errorf("wrong result\ngot: %#v\nwant: %#v", got, want)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestLookupLegacyProvider_invalidResponse(t *testing.T) {
|
||||||
|
source, _, close := testRegistrySource(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
got, err := LookupLegacyProvider(
|
||||||
|
addrs.NewLegacyProvider("invalid"),
|
||||||
|
source,
|
||||||
|
)
|
||||||
|
if !got.IsZero() {
|
||||||
|
t.Errorf("got non-zero addr\ngot: %#v\nwant: %#v", got, nil)
|
||||||
|
}
|
||||||
|
wantErr := "Error parsing provider ID from Registry: Invalid provider source string"
|
||||||
|
if gotErr := err.Error(); !strings.Contains(gotErr, wantErr) {
|
||||||
|
t.Fatalf("unexpected error: got %q, want %q", gotErr, wantErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestLookupLegacyProvider_unexpectedTypeChange(t *testing.T) {
|
||||||
|
source, _, close := testRegistrySource(t)
|
||||||
|
defer close()
|
||||||
|
|
||||||
|
got, err := LookupLegacyProvider(
|
||||||
|
addrs.NewLegacyProvider("changetype"),
|
||||||
|
source,
|
||||||
|
)
|
||||||
|
if !got.IsZero() {
|
||||||
|
t.Errorf("got non-zero addr\ngot: %#v\nwant: %#v", got, nil)
|
||||||
|
}
|
||||||
|
wantErr := `Registry returned provider with type "newtype", expected "changetype"`
|
||||||
|
if gotErr := err.Error(); gotErr != wantErr {
|
||||||
|
t.Fatalf("unexpected error: got %q, want %q", gotErr, wantErr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -292,7 +292,7 @@ func (c *registryClient) PackageMeta(provider addrs.Provider, version Version, t
|
||||||
return ret, nil
|
return ret, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
// LegacyProviderCanonicalAddress returns the raw address strings produced by
|
// LegacyProviderDefaultNamespace returns the raw address strings produced by
|
||||||
// the registry when asked about the given unqualified provider type name.
|
// the registry when asked about the given unqualified provider type name.
|
||||||
// The returned namespace string is taken verbatim from the registry's response.
|
// The returned namespace string is taken verbatim from the registry's response.
|
||||||
//
|
//
|
||||||
|
@ -300,7 +300,7 @@ func (c *registryClient) PackageMeta(provider addrs.Provider, version Version, t
|
||||||
// in older configurations. New configurations should be written so as not to
|
// in older configurations. New configurations should be written so as not to
|
||||||
// depend on it.
|
// depend on it.
|
||||||
func (c *registryClient) LegacyProviderDefaultNamespace(typeName string) (string, error) {
|
func (c *registryClient) LegacyProviderDefaultNamespace(typeName string) (string, error) {
|
||||||
endpointPath, err := url.Parse(path.Join("-", typeName))
|
endpointPath, err := url.Parse(path.Join("-", typeName, "versions"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
// Should never happen because we're constructing this from
|
// Should never happen because we're constructing this from
|
||||||
// already-validated components.
|
// already-validated components.
|
||||||
|
@ -338,7 +338,7 @@ func (c *registryClient) LegacyProviderDefaultNamespace(typeName string) (string
|
||||||
}
|
}
|
||||||
|
|
||||||
type ResponseBody struct {
|
type ResponseBody struct {
|
||||||
Namespace string
|
Id string
|
||||||
}
|
}
|
||||||
var body ResponseBody
|
var body ResponseBody
|
||||||
|
|
||||||
|
@ -347,7 +347,16 @@ func (c *registryClient) LegacyProviderDefaultNamespace(typeName string) (string
|
||||||
return "", c.errQueryFailed(placeholderProviderAddr, err)
|
return "", c.errQueryFailed(placeholderProviderAddr, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
return body.Namespace, nil
|
provider, diags := addrs.ParseProviderSourceString(body.Id)
|
||||||
|
if diags.HasErrors() {
|
||||||
|
return "", fmt.Errorf("Error parsing provider ID from Registry: %s", diags.Err())
|
||||||
|
}
|
||||||
|
|
||||||
|
if provider.Type != typeName {
|
||||||
|
return "", fmt.Errorf("Registry returned provider with type %q, expected %q", provider.Type, typeName)
|
||||||
|
}
|
||||||
|
|
||||||
|
return provider.Namespace, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *registryClient) addHeadersToRequest(req *http.Request) {
|
func (c *registryClient) addHeadersToRequest(req *http.Request) {
|
||||||
|
|
|
@ -114,34 +114,12 @@ func fakeRegistryHandler(resp http.ResponseWriter, req *http.Request) {
|
||||||
}
|
}
|
||||||
|
|
||||||
pathParts := strings.Split(path, "/")[3:]
|
pathParts := strings.Split(path, "/")[3:]
|
||||||
if len(pathParts) < 2 {
|
|
||||||
resp.WriteHeader(404)
|
|
||||||
resp.Write([]byte(`unexpected number of path parts`))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
log.Printf("[TRACE] fake provider registry request for %#v", pathParts)
|
|
||||||
if len(pathParts) == 2 {
|
|
||||||
switch pathParts[0] + "/" + pathParts[1] {
|
|
||||||
|
|
||||||
case "-/legacy":
|
|
||||||
// NOTE: This legacy lookup endpoint is specific to
|
|
||||||
// registry.terraform.io and not expected to work on any other
|
|
||||||
// registry host.
|
|
||||||
resp.Header().Set("Content-Type", "application/json")
|
|
||||||
resp.WriteHeader(200)
|
|
||||||
resp.Write([]byte(`{"namespace":"legacycorp"}`))
|
|
||||||
|
|
||||||
default:
|
|
||||||
resp.WriteHeader(404)
|
|
||||||
resp.Write([]byte(`unknown namespace or provider type for direct lookup`))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(pathParts) < 3 {
|
if len(pathParts) < 3 {
|
||||||
resp.WriteHeader(404)
|
resp.WriteHeader(404)
|
||||||
resp.Write([]byte(`unexpected number of path parts`))
|
resp.Write([]byte(`unexpected number of path parts`))
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
log.Printf("[TRACE] fake provider registry request for %#v", pathParts)
|
||||||
|
|
||||||
if pathParts[2] == "versions" {
|
if pathParts[2] == "versions" {
|
||||||
if len(pathParts) != 3 {
|
if len(pathParts) != 3 {
|
||||||
|
@ -162,6 +140,21 @@ func fakeRegistryHandler(resp http.ResponseWriter, req *http.Request) {
|
||||||
resp.Header().Set("Content-Type", "application/json")
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
resp.WriteHeader(200)
|
resp.WriteHeader(200)
|
||||||
resp.Write([]byte(`{"versions":[]}`))
|
resp.Write([]byte(`{"versions":[]}`))
|
||||||
|
case "-/legacy":
|
||||||
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
|
resp.WriteHeader(200)
|
||||||
|
// This response is used for testing LookupLegacyProvider
|
||||||
|
resp.Write([]byte(`{"id":"legacycorp/legacy"}`))
|
||||||
|
case "-/changetype":
|
||||||
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
|
resp.WriteHeader(200)
|
||||||
|
// This (unrealistic) response is used for error handling code coverage
|
||||||
|
resp.Write([]byte(`{"id":"legacycorp/newtype"}`))
|
||||||
|
case "-/invalid":
|
||||||
|
resp.Header().Set("Content-Type", "application/json")
|
||||||
|
resp.WriteHeader(200)
|
||||||
|
// This (unrealistic) response is used for error handling code coverage
|
||||||
|
resp.Write([]byte(`{"id":"some/invalid/id/string"}`))
|
||||||
default:
|
default:
|
||||||
resp.WriteHeader(404)
|
resp.WriteHeader(404)
|
||||||
resp.Write([]byte(`unknown namespace or provider type`))
|
resp.Write([]byte(`unknown namespace or provider type`))
|
||||||
|
|
Loading…
Reference in New Issue