internal/initwd: identify possible relative module sources
Identify module sources that look like relative paths ("child" instead of "./child", for example) and surface a helpful error. Previously, such module sources would be passed to go-getter, which would fail because it was expecting an absolute, or properly relative, path. This commit moves the check for improper relative paths sooner so a user-friendly error can be displayed.
This commit is contained in:
parent
420736333f
commit
bf04503f04
|
@ -52,17 +52,17 @@ func TestDirFromModule_registry(t *testing.T) {
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "root",
|
ModuleAddr: "root",
|
||||||
Version: v,
|
Version: v,
|
||||||
LocalPath: ".terraform/modules/root/hashicorp-terraform-aws-module-installer-acctest-5e87aff",
|
LocalPath: filepath.Join(dir, ".terraform/modules/root/hashicorp-terraform-aws-module-installer-acctest-5e87aff"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "root.child_a",
|
ModuleAddr: "root.child_a",
|
||||||
LocalPath: ".terraform/modules/root/hashicorp-terraform-aws-module-installer-acctest-5e87aff/modules/child_a",
|
LocalPath: filepath.Join(dir, ".terraform/modules/root/hashicorp-terraform-aws-module-installer-acctest-5e87aff/modules/child_a"),
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "root.child_a.child_b",
|
ModuleAddr: "root.child_a.child_b",
|
||||||
LocalPath: ".terraform/modules/root/hashicorp-terraform-aws-module-installer-acctest-5e87aff/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/root/hashicorp-terraform-aws-module-installer-acctest-5e87aff/modules/child_b"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -78,7 +78,7 @@ type reusingGetter map[string]string
|
||||||
// go-getter library, which have very inconsistent quality as
|
// go-getter library, which have very inconsistent quality as
|
||||||
// end-user-actionable error messages. At this time we do not have any
|
// end-user-actionable error messages. At this time we do not have any
|
||||||
// reasonable way to improve these error messages at this layer because
|
// reasonable way to improve these error messages at this layer because
|
||||||
// the underlying errors are not separatelyr recognizable.
|
// the underlying errors are not separately recognizable.
|
||||||
func (g reusingGetter) getWithGoGetter(instPath, addr string) (string, error) {
|
func (g reusingGetter) getWithGoGetter(instPath, addr string) (string, error) {
|
||||||
packageAddr, subDir := splitAddrSubdir(addr)
|
packageAddr, subDir := splitAddrSubdir(addr)
|
||||||
|
|
||||||
|
@ -186,3 +186,19 @@ func isRegistrySourceAddr(addr string) bool {
|
||||||
_, err := regsrc.ParseModuleSource(addr)
|
_, err := regsrc.ParseModuleSource(addr)
|
||||||
return err == nil
|
return err == nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func isMaybeRelativeLocalPath(addr, path string) bool {
|
||||||
|
realAddr, err := getter.Detect(addr, path, getter.Detectors)
|
||||||
|
// this error will be handled by the next function
|
||||||
|
if err != nil {
|
||||||
|
return false
|
||||||
|
} else {
|
||||||
|
if strings.HasPrefix(realAddr, "file://") {
|
||||||
|
_, err := os.Stat(realAddr[7:])
|
||||||
|
if err != nil {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
|
@ -199,6 +199,22 @@ func (i *ModuleInstaller) installDescendentModules(rootMod *tfconfig.Module, roo
|
||||||
diags = append(diags, mDiags...)
|
diags = append(diags, mDiags...)
|
||||||
return mod, v, diags
|
return mod, v, diags
|
||||||
|
|
||||||
|
case isMaybeRelativeLocalPath(req.SourceAddr, instPath):
|
||||||
|
log.Printf(
|
||||||
|
"[TRACE] ModuleInstaller: %s looks like a local path but is missing ./ or ../",
|
||||||
|
req.SourceAddr,
|
||||||
|
)
|
||||||
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
|
tfdiags.Error,
|
||||||
|
"Failed to locate local module source",
|
||||||
|
fmt.Sprintf(
|
||||||
|
"%s looks like a relative path, but Terraform cannot determine the module source. "+
|
||||||
|
"Add ./ at the start of the source string if this is a relative path.",
|
||||||
|
req.SourceAddr,
|
||||||
|
),
|
||||||
|
))
|
||||||
|
return nil, nil, diags
|
||||||
|
|
||||||
default:
|
default:
|
||||||
log.Printf("[TRACE] ModuleInstaller: %s address %q will be handled by go-getter", key, req.SourceAddr)
|
log.Printf("[TRACE] ModuleInstaller: %s address %q will be handled by go-getter", key, req.SourceAddr)
|
||||||
|
|
||||||
|
|
|
@ -93,12 +93,30 @@ func TestModuleInstaller(t *testing.T) {
|
||||||
assertResultDeepEqual(t, gotTraces, wantTraces)
|
assertResultDeepEqual(t, gotTraces, wantTraces)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestModuleInstaller_error(t *testing.T) {
|
||||||
|
fixtureDir := filepath.Clean("test-fixtures/local-module-error")
|
||||||
|
dir, done := tempChdir(t, fixtureDir)
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
hooks := &testInstallHooks{}
|
||||||
|
|
||||||
|
modulesDir := filepath.Join(dir, ".terraform/modules")
|
||||||
|
inst := NewModuleInstaller(modulesDir, nil)
|
||||||
|
_, diags := inst.InstallModules(".", false, hooks)
|
||||||
|
|
||||||
|
if !diags.HasErrors() {
|
||||||
|
t.Fatal("expected error")
|
||||||
|
} else {
|
||||||
|
assertDiagnosticSummary(t, diags, "Failed to locate local module source")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestLoaderInstallModules_registry(t *testing.T) {
|
func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
if os.Getenv("TF_ACC") == "" {
|
if os.Getenv("TF_ACC") == "" {
|
||||||
t.Skip("this test accesses registry.terraform.io and github.com; set TF_ACC=1 to run it")
|
t.Skip("this test accesses registry.terraform.io and github.com; set TF_ACC=1 to run it")
|
||||||
}
|
}
|
||||||
|
|
||||||
fixtureDir := filepath.Clean("test-fixtures/local-modules")
|
fixtureDir := filepath.Clean("test-fixtures/registry-modules")
|
||||||
dir, done := tempChdir(t, fixtureDir)
|
dir, done := tempChdir(t, fixtureDir)
|
||||||
defer done()
|
defer done()
|
||||||
|
|
||||||
|
@ -125,7 +143,7 @@ func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_child_a",
|
ModuleAddr: "acctest_child_a",
|
||||||
Version: v,
|
Version: v,
|
||||||
LocalPath: ".terraform/modules/acctest_child_a/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_a",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_child_a/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_a"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_child_a.child_b
|
// acctest_child_a.child_b
|
||||||
|
@ -133,7 +151,7 @@ func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_child_a.child_b",
|
ModuleAddr: "acctest_child_a.child_b",
|
||||||
LocalPath: ".terraform/modules/acctest_child_a/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_child_a/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_child_b accesses //modules/child_b directly
|
// acctest_child_b accesses //modules/child_b directly
|
||||||
|
@ -147,7 +165,7 @@ func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_child_b",
|
ModuleAddr: "acctest_child_b",
|
||||||
Version: v,
|
Version: v,
|
||||||
LocalPath: ".terraform/modules/acctest_child_b/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_child_b/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_root
|
// acctest_root
|
||||||
|
@ -161,7 +179,7 @@ func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_root",
|
ModuleAddr: "acctest_root",
|
||||||
Version: v,
|
Version: v,
|
||||||
LocalPath: ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_root.child_a
|
// acctest_root.child_a
|
||||||
|
@ -169,7 +187,7 @@ func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_root.child_a",
|
ModuleAddr: "acctest_root.child_a",
|
||||||
LocalPath: ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_a",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_a"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_root.child_a.child_b
|
// acctest_root.child_a.child_b
|
||||||
|
@ -177,7 +195,7 @@ func TestLoaderInstallModules_registry(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_root.child_a.child_b",
|
ModuleAddr: "acctest_root.child_a.child_b",
|
||||||
LocalPath: ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_root/hashicorp-terraform-aws-module-installer-acctest-853d038/modules/child_b"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -248,7 +266,7 @@ func TestLoaderInstallModules_goGetter(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_child_a",
|
ModuleAddr: "acctest_child_a",
|
||||||
LocalPath: ".terraform/modules/acctest_child_a/modules/child_a",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_child_a/modules/child_a"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_child_a.child_b
|
// acctest_child_a.child_b
|
||||||
|
@ -256,7 +274,7 @@ func TestLoaderInstallModules_goGetter(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_child_a.child_b",
|
ModuleAddr: "acctest_child_a.child_b",
|
||||||
LocalPath: ".terraform/modules/acctest_child_a/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_child_a/modules/child_b"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_child_b accesses //modules/child_b directly
|
// acctest_child_b accesses //modules/child_b directly
|
||||||
|
@ -268,7 +286,7 @@ func TestLoaderInstallModules_goGetter(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_child_b",
|
ModuleAddr: "acctest_child_b",
|
||||||
LocalPath: ".terraform/modules/acctest_child_b/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_child_b/modules/child_b"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_root
|
// acctest_root
|
||||||
|
@ -280,7 +298,7 @@ func TestLoaderInstallModules_goGetter(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_root",
|
ModuleAddr: "acctest_root",
|
||||||
LocalPath: ".terraform/modules/acctest_root",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_root"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_root.child_a
|
// acctest_root.child_a
|
||||||
|
@ -288,7 +306,7 @@ func TestLoaderInstallModules_goGetter(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_root.child_a",
|
ModuleAddr: "acctest_root.child_a",
|
||||||
LocalPath: ".terraform/modules/acctest_root/modules/child_a",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_root/modules/child_a"),
|
||||||
},
|
},
|
||||||
|
|
||||||
// acctest_root.child_a.child_b
|
// acctest_root.child_a.child_b
|
||||||
|
@ -296,7 +314,7 @@ func TestLoaderInstallModules_goGetter(t *testing.T) {
|
||||||
{
|
{
|
||||||
Name: "Install",
|
Name: "Install",
|
||||||
ModuleAddr: "acctest_root.child_a.child_b",
|
ModuleAddr: "acctest_root.child_a.child_b",
|
||||||
LocalPath: ".terraform/modules/acctest_root/modules/child_b",
|
LocalPath: filepath.Join(dir, ".terraform/modules/acctest_root/modules/child_b"),
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
variable "v" {
|
||||||
|
description = "in child_ba module"
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
output "hello" {
|
||||||
|
value = "Hello from child_a!"
|
||||||
|
}
|
|
@ -0,0 +1,8 @@
|
||||||
|
variable "v" {
|
||||||
|
description = "in root module"
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
module "child_a" {
|
||||||
|
source = "child_a"
|
||||||
|
}
|
Loading…
Reference in New Issue