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 (
|
||||
"fmt"
|
||||
"github.com/hashicorp/terraform/registry"
|
||||
"log"
|
||||
"os"
|
||||
"path/filepath"
|
||||
|
@ -13,6 +12,7 @@ import (
|
|||
"github.com/hashicorp/terraform/addrs"
|
||||
"github.com/hashicorp/terraform/internal/earlyconfig"
|
||||
"github.com/hashicorp/terraform/internal/modsdir"
|
||||
"github.com/hashicorp/terraform/registry"
|
||||
"github.com/hashicorp/terraform/registry/regsrc"
|
||||
"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
|
||||
// the files we need, and so we just load up what's already here.
|
||||
newDir := filepath.Join(parentRecord.Dir, req.SourceAddr)
|
||||
|
||||
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)
|
||||
if mod == nil {
|
||||
// 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) {
|
||||
if os.Getenv("TF_ACC") == "" {
|
||||
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