Open jmosswcg opened 12 months ago
You can already do this - just escape from your contents string using HCL's string templating syntax. (i.e. ${<some expr here>}
.
Referencing your example:
locals {
account_id = get_env("foo")
api_key = get_env("bar")
environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
git_branch = local.environment_vars.locals.git_branch
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite_terragrunt"
contents = <<EOF
provider "newrelic" {
account_id = ${local.account_id}
api_key = ${local.api_key}
region = "US" # Valid regions are US and EU
}
EOF
}
You can already do this - just escape from your contents string using HCL's string templating syntax. (i.e.
${<some expr here>}
.Referencing your example:
locals { account_id = get_env("foo") api_key = get_env("bar") environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl")) git_branch = local.environment_vars.locals.git_branch } generate "provider" { path = "provider.tf" if_exists = "overwrite_terragrunt" contents = <<EOF provider "newrelic" { account_id = ${local.account_id} api_key = ${local.api_key} region = "US" # Valid regions are US and EU } EOF }
Thanks! I'll give this a shot. Didn't see this in any documentation so I'll give this a shot.
@evsl what if you want to setup the generate block in a file as follow:
provider.hcl
generate "provider" {
path = "aws_provider.tf"
if_exists = "overwrite"
contents = <<EOF
provider "aws" {
region = "${local.aws_region}"
allowed_account_ids = ["${local.account_id}"]
profile = "${local.aws_profile}"
default_tags {
tags = {
Env = "${local.aws_profile}"
AccountID = "${local.account_id}"
Region = "${local.aws_region}"
}
}
}
EOF
}
Calling it in the terragrunt.hcl file
locals {
gen_provider = read_terragrunt_config("${get_repo_root()}/providers/provider.hcl")
account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
account_name = local.account_vars.locals.account_name
account_id = local.account_vars.locals.aws_account_id
aws_profile = local.account_vars.locals.aws_profile
aws_region = local.region_vars.locals.aws_region
env = local.environment_vars.locals.environment
}
generate = local.gen_provider.generate
From my testing it failed because he is not aware to the locals. Do you have solution for it?
Based on your code, and assuming your structure looks something like this:
root
| `teragrunt.hcl`
| providers
| provider.hcl
You're seeing this error since your generate block in provider.hcl
is trying to access locals defined in terragrunt.hcl
- the only way you could do that is if your provider.hcl
looked something like this
locals {
root = read_terragrunt_config(find_in_parent_folders()).locals
}
generate "provider" {
path = "aws_provider.tf"
if_exists = "overwrite"
contents = <<EOF
provider "aws" {
region = "${local.root.aws_region}"
allowed_account_ids = ["${local.root.account_id}"]
profile = "${local.root.aws_profile}"
default_tags {
tags = {
Env = "${local.root.aws_profile}"
AccountID = "${local.root.account_id}"
Region = "${local.root.aws_region}"
}
}
}
EOF
}
However, since you're reading the config from provider.tf
, you couldn't do that as terraform would (currently - maybe it'll support lazily evaluating this / stopping when a cycle is detected one day) cause a cycle and endlessly process. There's ways to avoid this and do exactly what you want here, but not without either rethinking your folder/read_terragrunt_config structure so that either the root terragrunt.hcl
wouldn't itself need to read the provider.tf
file, or reading those variables themselves from the provider.tf
file and accessing them within their locals (a possible DRY violation of sorts - depends on how exactly you're using those variables of course).
To alleviate this, you can define terraform variables within your generate block. This way you can provide the values from the root by passing the variables as inputs, which you can do from your root terragrunt.hcl. You'd need to define the variables in your modules if they don't already have them - if it's a hassle to do that you can optionally add any required variables to the generated file.
provider.hcl
generate "provider" {
path = "aws_provider.tf"
if_exists = "overwrite"
contents = <<EOF
# example variable in generate block -- I personally would avoid this if the module
# defines or uses these variables or related ones elsewhere, but if they're only used in generated files
# then it's fine
variable "aws_region" {
type = "string"
}
# ... the other variables
provider "aws" {
region = var.aws_region
allowed_account_ids = [ var.aws_account_id ]
profile = "var.aws_profile"
default_tags {
tags = {
Env = var.aws_profile
AccountID = var.account_id
Region = var.aws_region
}
}
}
EOF
}
terragrunt.hcl
locals {
gen_provider = read_terragrunt_config("${get_repo_root()}/providers/provider.hcl")
account_vars = read_terragrunt_config(find_in_parent_folders("account.hcl"))
region_vars = read_terragrunt_config(find_in_parent_folders("region.hcl"))
environment_vars = read_terragrunt_config(find_in_parent_folders("env.hcl"))
account_name = local.account_vars.locals.account_name
account_id = local.account_vars.locals.aws_account_id
aws_profile = local.account_vars.locals.aws_profile
aws_region = local.region_vars.locals.aws_region
env = local.environment_vars.locals.environment
}
generate = local.gen_provider.generate
inputs = {
aws_region = locals.aws_region
aws_account_id = locals.account_id
aws_profile = locals.aws_profile
}
Hope that helps!
PSA for future reference: If you're in a scenario where you need to expand something (e.g. a variable used in a function like format()
) inside of a generated block, then you can use the double leading character syntax to reference it without causing the generate block itself to try to expand the contents.
e.g.
generate block contents:
variable "foo" {
type = "string"
}
resource "some_resource" "example" {
name = "$${foo}-resource"
}
@evsl thanks for the detailed answer! I would setup as you suggested
@evsl is it possible to use random_password's resource output in inputs block when using "generate" block?
Describe the solution you'd like Add support for passing in locals into the generate block. For example
Describe alternatives you've considered For now, I'm setting environment variables in my wrapper script when running terragrunt in CI.
Additional context Add any other context or screenshots about the feature request here.