internal/initwd: follow local module path symlink (#21063)
* internal/initwd: follow local module path symlink Fixes #21060 While a previous commit fixed a problem when the local module directory contained a symlink, it did not account for the possibility that the entire directory was a symlink.
This commit is contained in:
parent
64f419ac76
commit
9327eedb04
|
@ -2,7 +2,6 @@ package initwd
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/hashicorp/terraform/registry"
|
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -13,6 +12,7 @@ import (
|
||||||
"github.com/hashicorp/terraform/addrs"
|
"github.com/hashicorp/terraform/addrs"
|
||||||
"github.com/hashicorp/terraform/internal/earlyconfig"
|
"github.com/hashicorp/terraform/internal/earlyconfig"
|
||||||
"github.com/hashicorp/terraform/internal/modsdir"
|
"github.com/hashicorp/terraform/internal/modsdir"
|
||||||
|
"github.com/hashicorp/terraform/registry"
|
||||||
"github.com/hashicorp/terraform/registry/regsrc"
|
"github.com/hashicorp/terraform/registry/regsrc"
|
||||||
"github.com/hashicorp/terraform/tfdiags"
|
"github.com/hashicorp/terraform/tfdiags"
|
||||||
)
|
)
|
||||||
|
@ -245,7 +245,18 @@ func (i *ModuleInstaller) installLocalModule(req *earlyconfig.ModuleRequest, key
|
||||||
// filesystem at all because the parent already wrote
|
// filesystem at all because the parent already wrote
|
||||||
// the files we need, and so we just load up what's already here.
|
// the files we need, and so we just load up what's already here.
|
||||||
newDir := filepath.Join(parentRecord.Dir, req.SourceAddr)
|
newDir := filepath.Join(parentRecord.Dir, req.SourceAddr)
|
||||||
|
|
||||||
log.Printf("[TRACE] ModuleInstaller: %s uses directory from parent: %s", key, newDir)
|
log.Printf("[TRACE] ModuleInstaller: %s uses directory from parent: %s", key, newDir)
|
||||||
|
// it is possible that the local directory is a symlink
|
||||||
|
newDir, err := filepath.EvalSymlinks(newDir)
|
||||||
|
if err != nil {
|
||||||
|
diags = diags.Append(tfdiags.Sourceless(
|
||||||
|
tfdiags.Error,
|
||||||
|
"Unreadable module directory",
|
||||||
|
fmt.Sprintf("Unable to evaluate directory symlink: %s", err.Error()),
|
||||||
|
))
|
||||||
|
}
|
||||||
|
|
||||||
mod, mDiags := earlyconfig.LoadModule(newDir)
|
mod, mDiags := earlyconfig.LoadModule(newDir)
|
||||||
if mod == nil {
|
if mod == nil {
|
||||||
// nil indicates missing or unreadable directory, so we'll
|
// nil indicates missing or unreadable directory, so we'll
|
||||||
|
|
|
@ -111,6 +111,67 @@ func TestModuleInstaller_error(t *testing.T) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestModuleInstaller_symlink(t *testing.T) {
|
||||||
|
fixtureDir := filepath.Clean("test-fixtures/local-module-symlink")
|
||||||
|
dir, done := tempChdir(t, fixtureDir)
|
||||||
|
defer done()
|
||||||
|
|
||||||
|
hooks := &testInstallHooks{}
|
||||||
|
|
||||||
|
modulesDir := filepath.Join(dir, ".terraform/modules")
|
||||||
|
inst := NewModuleInstaller(modulesDir, nil)
|
||||||
|
_, diags := inst.InstallModules(".", false, hooks)
|
||||||
|
assertNoDiagnostics(t, diags)
|
||||||
|
|
||||||
|
wantCalls := []testInstallHookCall{
|
||||||
|
{
|
||||||
|
Name: "Install",
|
||||||
|
ModuleAddr: "child_a",
|
||||||
|
PackageAddr: "",
|
||||||
|
LocalPath: "child_a",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
Name: "Install",
|
||||||
|
ModuleAddr: "child_a.child_b",
|
||||||
|
PackageAddr: "",
|
||||||
|
LocalPath: "child_a/child_b",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
if assertResultDeepEqual(t, hooks.Calls, wantCalls) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
loader, err := configload.NewLoader(&configload.Config{
|
||||||
|
ModulesDir: modulesDir,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Make sure the configuration is loadable now.
|
||||||
|
// (This ensures that correct information is recorded in the manifest.)
|
||||||
|
config, loadDiags := loader.LoadConfig(".")
|
||||||
|
assertNoDiagnostics(t, tfdiags.Diagnostics{}.Append(loadDiags))
|
||||||
|
|
||||||
|
wantTraces := map[string]string{
|
||||||
|
"": "in root module",
|
||||||
|
"child_a": "in child_a module",
|
||||||
|
"child_a.child_b": "in child_b module",
|
||||||
|
}
|
||||||
|
gotTraces := map[string]string{}
|
||||||
|
config.DeepEach(func(c *configs.Config) {
|
||||||
|
path := strings.Join(c.Path, ".")
|
||||||
|
if c.Module.Variables["v"] == nil {
|
||||||
|
gotTraces[path] = "<missing>"
|
||||||
|
return
|
||||||
|
}
|
||||||
|
varDesc := c.Module.Variables["v"].Description
|
||||||
|
gotTraces[path] = varDesc
|
||||||
|
})
|
||||||
|
assertResultDeepEqual(t, gotTraces, wantTraces)
|
||||||
|
}
|
||||||
|
|
||||||
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")
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
variable "v" {
|
||||||
|
description = "in child_a module"
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
module "child_b" {
|
||||||
|
source = "./child_b"
|
||||||
|
}
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
variable "v" {
|
||||||
|
description = "in child_b module"
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
output "hello" {
|
||||||
|
value = "Hello from child_b!"
|
||||||
|
}
|
|
@ -0,0 +1 @@
|
||||||
|
../child_a/
|
|
@ -0,0 +1,9 @@
|
||||||
|
|
||||||
|
variable "v" {
|
||||||
|
description = "in root module"
|
||||||
|
default = ""
|
||||||
|
}
|
||||||
|
|
||||||
|
module "child_a" {
|
||||||
|
source = "./modules/child_a"
|
||||||
|
}
|
Loading…
Reference in New Issue