#terragrunt (2023-06)

terragrunt

Terragrunt discussions

Archive: https://archive.sweetops.com/terragrunt/

2023-06-22

dec.soham avatar
dec.soham

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?

loren avatar

You are mixing terragrunt and terraform configurations. They are separate

loren avatar

you have to declare a terraform variable, and then pass the input from terragrunt to terraform using the inputs block

dec.soham avatar
dec.soham

You have an example @loren?

dec.soham avatar
dec.soham

Let me try and report back.

dec.soham avatar
dec.soham

Yeah not sure how I can pass it as an input with inputs block. Any example would be very helpful.

loren avatar

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
}
1
dec.soham avatar
dec.soham

Perfect. Thanks @loren This is working. I will give it some more thought and come back with any questions

dec.soham avatar
dec.soham

@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.
dec.soham avatar
dec.soham

If you want, I can pastebin the working and non working configuration.

loren avatar

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

dec.soham avatar
dec.soham

No worries at all You have helped enough already.

dec.soham avatar
dec.soham

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

#1476 General Guidance Around Merging Maps/Tags

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#1011https://github.com/gruntwork-io/terragrunt-infrastructure-modules-examplehttps://github.com/gruntwork-io/terragrunt-infrastructure-live-examplehttps://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.

1
    keyboard_arrow_up