#terragrunt (2023-06)
Terragrunt discussions
Archive: https://archive.sweetops.com/terragrunt/
2023-06-22
I have a terragrunt config where I have this tags.hcl
file under workloads/production/eu-west-1
locals {
env_tags = {
Environment = "Production"
Region = "eu-west-1"
Managed_by = "Terraform"
}
}
Now, in the child module, I have this terragrunt.hcl
file
include "root" {
path = find_in_parent_folders()
}
locals {
common_tags = read_terragrunt_config(find_in_parent_folders("tags.hcl"))
}
Now in my resource definition, I am trying to use the common_tags
module "ec2-instance" {
source = "terraform-aws-modules/ec2-instance/aws"
version = "5.1.0"
name = "important-ec2"
ami = var.ami
instance_type = var.instance_type
tags = merge(
locals.common_tags,
{
App = "xxx"
Role = "yyy"
}
)
}
But it fails with
│ A managed resource "locals" "common_tags" has not been declared in the root
│ module.
Pretty sure I am misinterpreting the last section where I have to define it in the ec2-instance
module. What I am doing wrong? I asked in another slack and think that locals cannot be passed to the TF config. Is that a right assumption?
You are mixing terragrunt and terraform configurations. They are separate
you have to declare a terraform variable, and then pass the input from terragrunt to terraform using the inputs
block
You have an example @loren?
Let me try and report back.
Yeah not sure how I can pass it as an input with inputs
block. Any example would be very helpful.
define a variable in your .tf file:
variable "common_tags" {
type = map(string)
default = {}
}
use the variable in your .tf file “resource definition”:
tags = merge(
var.common_tags,
{
App = "xxx"
Role = "yyy"
}
)
pass the input in your terragrunt.hcl
:
inputs = {
common_tags = local.common_tags
}
Perfect. Thanks @loren This is working. I will give it some more thought and come back with any questions
@loren another related question. I managed to get it working with env.yaml
at the root and then using yamldecode
in child module’s terragrunt.hcl
.
But using it as I showed above, I have this:
tags.hcl
at the root
locals {
env_tags = {
Environment = "Production"
Region = "eu-west-1"
Managedby = "Terraform"
}
}
Then in child module’s terragrunt.hcl
:
include "root" {
path = find_in_parent_folders()
}
locals {
common_tags = read_terragrunt_config(find_in_parent_folders("tags.hcl"))
}
inputs = {
common_tags = local.common_tags
}
And then in TF config
tags = merge(
# var.common_vars,
var.common_tags,
{
App = "xx"
Role = "yy"
}
)
And it fails with
│ Error: Invalid value for input variable
│
│ The environment variable TF_VAR_common_tags does not contain a valid value
│ for variable "common_tags": element "locals": string required.
If you want, I can pastebin the working and non working configuration.
sorry i don’t have a lot of time to troubleshoot further. i’m swamped for days. that was all the time i could spare
No worries at all You have helped enough already.
Hey @loren I managed to fix this. Needed to do
inputs = {
default_tags = local.common_tags.locals.env_tags
}
Got the hint from https://github.com/gruntwork-io/terragrunt/issues/1476
Terraform version: 0.12.20
Terragrunt version: 0.21.11
As a test, we are using a project with the following directory structure:
./
└── terraform
├── aws
│ ├── <account>
│ │ ├── account.tfvars
│ │ └── us-west-2
│ │ ├── <env_suffx>-myapp-s3-bucket
│ │ │ ├── terraform_init.tf
│ │ │ └── terragrunt.hcl
│ │ ├── <env_suffix>-myapp-s3-bucket
│ │ │ ├── terraform_init.tf
│ │ │ └── terragrunt.hcl
│ │ ├── region.tfvars
│ │ └── <env_suffix>-myapp-s3-bucket
│ │ ├── terraform_init.tf
│ │ └── terragrunt.hcl
│ └── <account_2>
│ ├── account.tfvars
│ └── us-west-2
│ ├── <env_suffix>-myapp-s3-bucket
│ │ ├── terraform_init.tf
│ │ └── terragrunt.hcl
│ └── region.tfvars
├── modules
│ └── s3
│ ├── README.md
│ ├── main.tf
│ ├── outputs.tf
│ ├── variables.tf
│ └── versions.tf
└── terragrunt.hcl
For consistency sake, the module uses the following naming convention for each bucket:
name = "${var.default_tags["environment"]}-${var.default_tags["env_suffix"]}-${var.default_tags["application_name"]}-${var.default_tags["component"]}"
default_tags
is defined like so:
.....
variable "default_tags" {
description = "(Optional) A mapping of tags to assign to the bucket."
type = map(string)
default = {}
}
.....
FYI, a majority of the tags are shared across all the resources in the account and so, they can be defined at the account-level. For this reason, the terraform/aws/<account>/account.tfvars
looks like so:
default_tags = {
application_name = "<application_name>"
environment = "<environment>"
.....
}
Some tags
however, must be component/environment-specific. For this reason, the terraform/aws/<account>/us-west-2/<env_suffix>-myapp-s3-bucket/terragrunt.hcl
looks like so:
.....
inputs = {
default_tags = {
component = "<component>"
env_suffix = "<env_suffix>"
}
}
Running a terragrunt plan
on the structure outlined above, returns the following error:
Error: Invalid index
on main.tf line 2, in locals:
2: name = "${var.default_tags["environment"]}-${var.default_tags["env_suffix"]}-${var.default_tags["application_name"]}-${var.default_tags["component"]}"
|----------------
| var.default_tags is map of string with 15 elements
The given key does not identify an element in this collection value.
Error: Invalid index
on main.tf line 2, in locals:
2: name = "${var.default_tags["environment"]}-${var.default_tags["env_suffix"]}-${var.default_tags["application_name"]}-${var.default_tags["component"]}"
|----------------
| var.default_tags is map of string with 15 elements
The given key does not identify an element in this collection value.
Based on the version of Terraform/Terragrunt being used, after reviewing a few of the following issues/examples:
• #744 • #1011 • https://github.com/gruntwork-io/terragrunt-infrastructure-modules-example • https://github.com/gruntwork-io/terragrunt-infrastructure-live-example • https://www.terraform.io/docs/configuration/functions/merge.html
I am a bit confused on the best approach for merging the required tags
. Would someone be able to point me in the right direction for addressing our use-case? I’m happy to provide more details if required.