terragrunt
terragrunt copied to clipboard
dependencyBlocksToModuleDependencies does not resolve relative config_path values
The dependencyBlocksToModuleDependencies
function should resolve config_path
values relative to the terragrunt.hcl
file they are declared in instead of simply appending them to an array.
This becomes a problem during multi-level dependencies:
Terragrunt A has a dependency on Terragrunt B: A -> B Terragrunt C has a dependency on Terragrunt A: C -> A
Eg. in my case:
sqs/data-queue/terragrunt.hcl
depends on sqs/deadletter-queue/terragrunt.hcl
lambda-function/terragrunt.hcl
depends on sqs/data-queue/terragrunt.hcl
Deploying the sqs/data-queue/terragrunt.hcl
from its own directory properly finds the dependency.
This means, that in this case the path get_terragrunt_dir()
gets resolved to sqs/data-queue
as it should.
However, when I try to deploy lambda-function/terragrunt.hcl
which depends on sqs/data-queue/terragrunt.hcl
, I get an error:
[terragrunt] 2021/02/10 16:24:10 Terraform version: 0.13.5
[terragrunt] 2021/02/10 16:24:10 Reading Terragrunt config file at <redacted>/lambda-function/terragrunt.hcl
[terragrunt] 2021/02/10 16:24:10 Error reading file at path <redacted>/iam/sqs/deadletter-queue: open <redacted>/iam/sqs/deadletter-queue: no such file or directory
The interesting thing about the path in the log, is that it comes from sqs/data-queue/terragrunt.hcl
where it is defined so:
dependency "deadletter_queue" {
config_path = abspath("${get_terragrunt_dir()}/../deadletter-queue")
}
I have also tried using ..
instead of the get_terragrunt_dir()
function, with and without the abspath
function.
These also don't work obviously, as there's no path resolution done in dependencyBlocksToModuleDependencies
:
func dependencyBlocksToModuleDependencies(decodedDependencyBlocks []Dependency) *ModuleDependencies {
if len(decodedDependencyBlocks) == 0 {
return nil
}
paths := []string{}
for _, decodedDependencyBlock := range decodedDependencyBlocks {
configPath := decodedDependencyBlock.ConfigPath
if util.IsFile(configPath) && filepath.Base(configPath) == DefaultTerragruntConfigPath {
// dependencies system expects the directory containing the terragrunt.hcl file
configPath = filepath.Dir(configPath)
}
paths = append(paths, configPath)
}
return &ModuleDependencies{Paths: paths}
}
If this function would simply resolve the configPath
values to canonical paths based on where the dependency is declared, it would not only work correctly, but the expected path would be self-explanatory from a developer point of view.
Oddly the examples in the docs here are using this non-working notation: https://terragrunt.gruntwork.io/docs/features/keep-your-terragrunt-architecture-dry/
The dependency blocks:
dependency "vpc" {
config_path = "../vpc"
}
dependency "mysql" {
config_path = "../mysql"
}
that are moved to _env/app.hcl for added DRY'ness does not work unless changed to
dependency "vpc" {
config_path = "${get_terragrunt_dir()}/../vpc"
}
dependency "mysql" {
config_path = "${get_terragrunt_dir()}/../mysql"
}