Open aamm19 opened 2 years ago
Hi, it will be hard to debug this without access to the code. Is there any way you can create a minimum reproducible gist?
Alternatively, you can try running with --terragrunt-log-level debug
. Since you are not using the generate
attribute of remote_state
, you should be able to see the backend configuration calls in the logs tacked on to calls to terragrunt init
. That might give you insight into whether that is happening because terragrunt
isn't configuring the state correctly.
You can also use render-json to introspect what the combined config is. My suspicion is that you have a bug in the terragrunt.hcl
for the security_groups
folder that is either overriding the remote_state
or is not getting the right parent terragrunt.hcl
file.
Hi Yano, thanks for the reply.
Here's a basic summary of the files:
terragrunt.hcl (parent folder)
#The Terragrunt root file includes the configuration of all modules
# Locals are named constants that are reusable within the configuration.
# Loading the common and env variables
remote_state {
backend = "local"
config = {
path = "${path_relative_to_include()}/output/terraform.tfstate"
}
}
locals {
aws_region = "REGION"
tags = {
Terraform = "True"
Environment = "ENVIRONMENT"
}
aws_account_id = get_aws_account_id()
}
terraform {
#source = "../"
# Force Terraform to keep trying to acquire a lock for
# up to 20 minutes if someone else already has the lock
extra_arguments "retry_lock" {
commands = get_terraform_commands_that_need_locking()
arguments = ["-lock-timeout=20m"]
}
# Pass custom var files to Terraform
extra_arguments "custom_vars" {
commands = [
"apply",
"plan",
"import",
"push",
"refresh"
]
}
}
terragrunt.hcl (networking module)
include "root" {
path = find_in_parent_folders()
expose = true
}
locals {
aws_region = include.root.locals.aws_region
tags = include.root.locals.tags
local_tags = {
Services = "Networking"
}
}
inputs = {
aws_region = local.aws_region
tags = merge(local.tags, local.local_tags)
}
terragrunt.hcl (security_groups module)
include "root" {
path = find_in_parent_folders()
expose = true
}
dependencies {
paths = ["../networking"]
}
dependency "networking" {
config_path = "../networking"
mock_outputs = {
vpc_id = "vpc-00a11b2c"
}
#skip_outputs = true # means use mocks all the time if mock_outputs are set.
#mock_outputs_allowed_terraform_commands = ["init", "validate", "plan" ]
#partial_mock_outputs = true # Set true if would merge the actual outputs with the mocked ones
#mock_outputs_merge_with_state = true # force terragrunt to merge mock_outputs with the dependency output that was fetched from state.
#mock_outputs_merge_strategy_with_state = "shallow"
}
locals {
aws_region = include.root.locals.aws_region
tags = include.root.locals.tags
local_tags = {
Services = "Security_group"
}
}
inputs = {
aws_region = local.aws_region
use_name_prefix = local.use_name_prefix
revoke_rules_on_delete = local.revoke_rules_on_delete
tags = merge(local.tags, local.local_tags)
vpc_id = dependency.networking.outputs.vpc_id
}
I used the render-json to print out the json, and this is the configuration block for the parent json:
"remote_state":{"backend":"local","config":{"path":"./output/terraform.tfstate"},"disable_dependency_optimization":false,"disable_init":false,"generate":null}
,
networking json:
"remote_state":{"backend":"local","config":{"path":"networking/output/terraform.tfstate"},"disable_dependency_optimization":false,"disable_init":false,"generate":null}
security groups json:
"remote_state":{"backend":"local","config":{"path":"security_groups/output/terraform.tfstate"},"disable_dependency_optimization":false,"disable_init":false,"generate":null}
I would've thought it might have something to do with the path_relative_to_include()
and how it is interpreted, but then again it wouldn't show only on the security group module.
Thanks for sharing the code. I see a few potential issues that may or may not be related:
Since you aren't using the generate attribute, the backend configuration in the TF code would have precedence. So it's possible that you misconfigured the terraform
block in the main.tf
for the security_groups
module, which is overriding the path config.
terraform
block in the modules to make sure the backend
block is empty without any path
field set.remote_state
. There is no advantage to using remote_state
block unless you are using the GCS or S3 backend.Relative paths can be tricky to understand in terragrunt
because the folder where Terragrunt calls Terraform is highly dependent on the terraform source. It's advised to generally prefer to use absolute paths when dealing with file paths in the code. For your case, the following should do the trick:
path = "${get_parent_terragrunt_dir()}/${path_relative_to_include()}/output/terraform.tfstate"
Thanks for the tips Yano.
I was able to solve the issue implementing the generate backend pattern similar to the documentation and generating the absolute path, as suggested.
terragrunt.hcl (parent folder)
generate "backend" {
path = "backend.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
terraform {
backend "local" {
path = "${get_parent_terragrunt_dir()}/${path_relative_to_include()}/output/terraform.tfstate"
}
}
EOF
}
[omitted rest of file for brevity]
Having said that, during the testing I did find that the dependant module (security_groups) gets re-initialized everytime I run "terragrunt run-all apply", even if it was initialized before.
I'm not sure if during the initialization the remote_state
block gets overwritten during execution, but if it does, I'm guessing this might be related to the unexpected behavior.
remote_state
works too
remote_state {
backend = "local"
config = {
path = "${get_parent_terragrunt_dir()}/${path_relative_to_include()}/terraform.tfstate"
}
generate = {
path = "backend.tf"
if_exists = "overwrite"
}
}
IMO this (local backends) should be documented.
Note: I linked to this issue in a SO answer.
Hi,
I'm currently having an issue in a setup I'm using for a project with terragrunt.
I have a set of modules that I'm creating (sns, networking, secret manager and security groups). However, security groups is dependant on the networking module.
The command I'm using to run terragrunt currently is:
terragrunt run-all apply --terragrunt-include-dir ./networking --terragrunt-include-dir ./secret_manager --terragrunt-include-dir ./sns --terragrunt-include-dir ./security_groups
And the groups are to be executed as follows:
in my root terragrunt.hcl I have declared the remote_state with the
backend="local"
option like so:And I have imported it on all the modules themselves:
All of the base modules (sns, networking and secret manager) work as expected, showing the folder structure I paste on the below tree. When the execution for the security group module happens, it saves the statefile in the same level as the terragrunt.hcl file.
Is anyone else facing this issue?
Directory tree: