terragrunt
terragrunt copied to clipboard
what is the best way to use global variables like per env, per region, global
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 ?
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 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:
- 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
}
- "include" each file and again duplicate this include block in each child file.
include "env" {
path = find_in_parent_folders("env.hcl")
expose = true
}
- 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
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
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?