config/module: allow registry download sources to be relative paths
It's not always easy or convenient for a web application to determine its own absolute URL to return, so here we pragmatically allow the download source string from a registry to be a path relative to the download endpoint. Since X-Terraform-Get is a go-getter string, not all valid values are valid URLs and so we sniff for certain relative-path-looking prefixes in order to decide whether to apply the relative lookup transform.
This commit is contained in:
parent
4a01bf0b97
commit
288f7c00e4
|
@ -49,6 +49,10 @@ var testMods = map[string][]testMod{
|
|||
location: "file:///registry/exists",
|
||||
version: "0.2.0",
|
||||
}},
|
||||
"relative/foo/bar": {{ // There is an exception for the "relative/" prefix in the test registry server
|
||||
location: "/relative-path",
|
||||
version: "0.2.0",
|
||||
}},
|
||||
"test-versions/name/provider": {
|
||||
{version: "2.2.0"},
|
||||
{version: "2.1.1"},
|
||||
|
@ -103,7 +107,7 @@ func mockRegHandler() http.Handler {
|
|||
mod := versions[0]
|
||||
|
||||
location := mod.location
|
||||
if !strings.HasPrefix(location, "file:///") {
|
||||
if !strings.HasPrefix(matches[0], "relative/") && !strings.HasPrefix(location, "file:///") {
|
||||
// we can't use filepath.Abs because it will clean `//`
|
||||
wd, _ := os.Getwd()
|
||||
location = fmt.Sprintf("file://%s/%s", wd, location)
|
||||
|
|
|
@ -186,5 +186,25 @@ func (s *Storage) lookupModuleLocation(module *regsrc.Module, version string) (s
|
|||
return "", fmt.Errorf("failed to get download URL for %q: %s resp:%s", module, resp.Status, body)
|
||||
}
|
||||
|
||||
// If location looks like it's trying to be a relative URL, treat it as
|
||||
// one.
|
||||
//
|
||||
// We don't do this for just _any_ location, since the X-Terraform-Get
|
||||
// header is a go-getter location rather than a URL, and so not all
|
||||
// possible values will parse reasonably as URLs.)
|
||||
//
|
||||
// When used in conjunction with go-getter we normally require this header
|
||||
// to be an absolute URL, but we are more liberal here because third-party
|
||||
// registry implementations may not "know" their own absolute URLs if
|
||||
// e.g. they are running behind a reverse proxy frontend, or such.
|
||||
if strings.HasPrefix(location, "/") || strings.HasPrefix(location, "./") || strings.HasPrefix(location, "../") {
|
||||
locationURL, err := url.Parse(location)
|
||||
if err != nil {
|
||||
return "", fmt.Errorf("invalid relative URL for %q: %s", module, err)
|
||||
}
|
||||
locationURL = download.ResolveReference(locationURL)
|
||||
location = locationURL.String()
|
||||
}
|
||||
|
||||
return location, nil
|
||||
}
|
||||
|
|
|
@ -93,7 +93,30 @@ func TestRegistryAuth(t *testing.T) {
|
|||
}
|
||||
|
||||
}
|
||||
func TestLookupModuleLocationRelative(t *testing.T) {
|
||||
server := mockRegistry()
|
||||
defer server.Close()
|
||||
|
||||
regDisco := testDisco(server)
|
||||
storage := testStorage(t, regDisco)
|
||||
|
||||
src := "relative/foo/bar"
|
||||
mod, err := regsrc.ParseModuleSource(src)
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
got, err := storage.lookupModuleLocation(mod, "0.2.0")
|
||||
if err != nil {
|
||||
t.Fatal(err)
|
||||
}
|
||||
|
||||
want := server.URL + "/relative-path"
|
||||
if got != want {
|
||||
t.Errorf("wrong location %s; want %s", got, want)
|
||||
}
|
||||
|
||||
}
|
||||
func TestAccLookupModuleVersions(t *testing.T) {
|
||||
if os.Getenv("TF_ACC") == "" {
|
||||
t.Skip()
|
||||
|
|
Loading…
Reference in New Issue