-
-
Notifications
You must be signed in to change notification settings - Fork 1.1k
Description
Describe the bug
Functions such as get_original_terragrunt_dir and get_terragrunt_dir are not sufficient for consistently acquiring the terragrunt stack directory that is currently being generated.
i.e. when running terragrunt stack generate outside of a directory containing a terragrunt.stack.hcl during each discovered stacks generation:
- if invoked within the locals:
- ❌
get_original_terragrunt_dirwill return the directory in which the command is being run from - ✅
get_terragrunt_dirwill return the stack directory
- ❌
- if invoked in terragrunt config targeted via
read_terragrunt_config- ❌
get_original_terragrunt_dirwill return the directory in which the command is being run from - ❌
get_terragrunt_dirwill return the directory of theread_terragrunt_configtarget
- ❌
Steps To Reproduce
The following small repo provides a reproduction that can be observed.
But here is a tldr:
# live/common/stack_config.hcl
locals {
calling_dir = get_original_terragrunt_dir()
stack_name = basename(local.calling_dir)
tags = {
get_terragrunt_dir = get_terragrunt_dir()
get_original_terragrunt_dir = get_original_terragrunt_dir()
}
}# catalog/units/test-module/main.tf
variable "tags" {
type = map(any)
}
variable "stack_name" {
type = string
}
output "tags" {
value = var.tags
}
output "stack_name" {
value = var.stack_name
}
# catalog/units/test-module/terragrunt.hcl
terraform {
source = "./"
}
inputs = {
tags = values.tags
stack_name = values.stack_name
}# live/account/env/region/test1/terragrunt.stack.hcl
locals {
common = read_terragrunt_config(find_in_parent_folders("common/stack_config.hcl"))
values = local.common.locals
}
unit "test1" {
source = "${get_repo_root()}/catalog/units/test-module"
path = "test1"
values = local.values
}When running terragrunt stack generate from the live directory level produces the following values:
calling_dir = "<redacted>/stacks-file-functions/live/account"
stack_name = "live"
tags = {
get_original_terragrunt_dir = "<redacted>/stacks-file-functions/live"
get_terragrunt_dir = "<redacted>/stacks-file-functions/live/common"
}When running terragrunt stack generate from the account directory level produces the following values:
calling_dir = "<redacted>/stacks-file-functions/live/account"
stack_name = "account"
tags = {
get_original_terragrunt_dir = "<redacted>/stacks-file-functions/live/account"
get_terragrunt_dir = "<redacted>/stacks-file-functions/live/common"
}Expected behavior
I would expect in this scenario that get_original_terragrunt_dir would always fetch the directory where read_terragrunt_config was invoked from.
I would expect that if this capability where not possible with the current functions that a new one could possibly be added for this use case, i.e. get_terragrunt_stack_dir
Must haves
- Steps for reproduction provided.
Nice to haves
- Terminal output
- Screenshots
Versions
- Terragrunt version: v0.93.7
- OpenTofu/Terraform version: v1.9.8
- Environment Ubuntu 24.04
Additional context
From the code I can see the following:
# config/stack.go
func ReadStackConfigFile(ctx context.Context, l log.Logger, opts *options.TerragruntOptions, filePath string, values *cty.Value) (*StackConfig, error) {
l.Debugf("Reading Terragrunt stack config file at %s", filePath)
stackOpts := opts.Clone()
stackOpts.TerragruntConfigPath = filePath
parser := NewParsingContext(ctx, l, stackOpts)
file, err := hclparse.NewParser(parser.ParserOptions...).ParseFromFile(filePath)
if err != nil {
return nil, errors.New(err)
}
//nolint:contextcheck
return ParseStackConfig(l, parser, opts, file, values)
}whereby opts is cloned and stackOpts.TerragruntConfigPath is set to the filepath currently being generated.
However, for some reason unknown to me this is ignored via the get_terragrunt_dir, likely for the same reasons that made get_original_terragrunt_dir get introduced.
A few possible other options would be to explore reassigning OriginalTerragruntConfigPath and leverage get_original_terragrunt_dir or TerragruntStackConfigPath and exposing access to it via a function.