terragrunt icon indicating copy to clipboard operation
terragrunt copied to clipboard

what is the best way to use global variables like per env, per region, global

Open suppix opened this issue 2 years ago • 4 comments

Could you please suggest what is the best way to use global variables like per env, per region, global

Now we have a lot of ways to define and to use variables:

locals {
  environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))

  region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))

  # Extract out common variables for reuse
  env           = local.environment_vars.locals.environment
  project       = local.environment_vars.locals.project
  cluster_name  = local.environment_vars.locals.cluster_name
  aws_region    = local.region_vars.locals.aws_region
}

terraform {
  source = "git::[email protected]:terraform-aws-modules/terraform-aws-vpc.git//.?ref=v3.11.0"
}

include "root" {
  path    = find_in_parent_folders()
  expose  = true
}

include "env" {
  path           = find_in_parent_folders("env.hcl")
  expose         = true
  merge_strategy = "no_merge"
}

inputs = {
  name                 = "${include.root.locals.environment_vars.locals.project}-${local.env}-${include.env.locals.project}"
....

On the one hand I don't like to have this repeatable block in each file:

locals {
  environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))

  region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))

  # Extract out common variables for reuse
  env           = local.environment_vars.locals.environment
  project       = local.environment_vars.locals.project
  cluster_name  = local.environment_vars.locals.cluster_name
  aws_region    = local.region_vars.locals.aws_region
}

on the other hand variables like ${include.root.locals.environment_vars.locals.project} are too complicated.

Can you please suggest what is the best approach to use common variables ?

suppix avatar Dec 10 '21 16:12 suppix

Both are equally valid approaches, so it will come down to personal preferences. However, I suspect that this is really a feature request for shared locals, which is tracked in this ticket: https://github.com/gruntwork-io/terragrunt/issues/814

yorinasub17 avatar Dec 10 '21 19:12 yorinasub17

@yorinasub17 Thank you that you find some time to answer to such questions.

I'm not sure if this feature can help to fix my problem.

Let me clarify.

In the child terragrunt.hcl I need some variables from region.hcl, env.hcl account.hcl. So I have 3 ways how to do it:

  1. duplicate in each child terragrunt file this locals block:
locals {
  environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))

  region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))

  # Extract out common variables for reuse
  env           = local.environment_vars.locals.environment
  project       = local.environment_vars.locals.project
  cluster_name  = local.environment_vars.locals.cluster_name
  aws_region    = local.region_vars.locals.aws_region
}
  1. "include" each file and again duplicate this include block in each child file.
include "env" {
  path            = find_in_parent_folders("env.hcl")
  expose          = true
}
  1. use include "root" + expose (because in our main terragrunt file we already have 3 read_terragrunt_config from env, account, and region)

and I'll have variables like: ${include.root.locals.environment_vars.locals.project}

It looks like only the 3-d method comply with the DRY idea, but variables although look logic but too long and difficult to read and understand

suppix avatar Dec 11 '21 08:12 suppix

local.environment_vars.locals,@suppix May be this can help you...

In my parent terragrunt.hcl I have something like this...

locals {
  # Load account-level variables
  account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))

  # Load the environment-level variables
  environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))

  # Load the application-level variables
  app_vars = read_terragrunt_config(find_in_parent_folders("app.hcl"))
}

# Configure root level variables that all resources can inherit. This is especially helpful with multi-account configs
# where terraform_remote_state data sources are placed directly into the modules.
inputs = merge(
  local.account_vars.locals,
  local.app_vars.locals,
  local.environment_vars.locals,
}

And then in each module you have...

terraform {
   source = "git::[email protected]:terraform-aws-modules/terraform-aws-vpc.git//.?ref=v3.11.0"
}

include {
  path = find_in_parent_folders()
}

One useful thing is the merge works on the basis of last one wins i.e. of a local is defined in app.hcl but also defined in environment.hcl the value in environment.hcl is emitted as it's later in the merge

You can also locally override an input in the module if you need to

phatcher avatar Jan 11 '22 17:01 phatcher

What is the easiest way to bring global constants to each Terraform module? For example, these are especially useful for a more readable aws_security_group_rule resource:

locals {
  https_port    = 443
  tcp_protocol  = 6
  all_ports     = 0
  all_protocols = "-1"
  any_ips       = ["0.0.0.0/0"]
}

@phatcher's solution in the previous post works, but one still has to declare each such constant as a variable to each module

variable "all_ports" {
  nullable = false
}

and then also have it be passed in as inputs in .hcl.

inputs = {
  all_ports = local.all_ports

Is there a better way?


A solution would be to generate these global locals in the root terragrunt.hcl:

generate "globals" {
  path      = "globals.tf"
  if_exists = "overwrite_terragrunt"
  contents  = <<EOF
variable "service_name" {
  nullable = false
  type = string
}
locals {
  https_port    = 443
  tcp_protocol  = 6
  all_ports     = 0
  all_protocols = "-1"
  any_ips       = ["0.0.0.0/0"]
}
EOF
}

(Also added variable "service_name" as something every module should have set on apply.)

Is the above advisable? Or potentially dangerous and/or unmaintainable?

oatmealb avatar Jun 10 '22 14:06 oatmealb