Terragrunt - Multiple conditional providers
techawsterraformterragruntcloudterraform providersinfrastructure as codedevops
549 Words
Sun, 26 Jun 2022 06:22:10 +0000
I was recently thinking of how I can make my terragrunt.hcl
files and directory structure neater…
Using the Helm provider to provision a few deployments on newly created EKS clusters, I was adding this generate
block to each file, so that the kubeconfig
file could be read from its appropriate location:
generate "provider-helm" {
path = "providers_helm.tf"
if_exists = "overwrite"
contents = <<EOF
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
}
}
EOF
}
But adding >10 lines each time I wanted to overwrite a provider configuration was bothering me. And I did not want to define the provider in the root terragrunt.hcl
file because it would be included in all resources, even if they did not need it.
…Or would it?
I got a nice idea reading this github discussion on gruntwork’s page, and remembering I can use directives. This opens the way to defining and loading Terraform providers conditionally.
Here’s what I did and satisfied my need for slimmer resource files.
First, in the root terragrunt.hcl
file, I put this, overwriting any generate
blocks:
# We define which providers to load, on top of the module's providers,
generate "provider" {
path = "providers.tf"
if_exists = "overwrite"
contents = <<-EOF
%{if contains(local.providers, "aws")}
provider "aws" {
region = "${local.aws_region}"
allowed_account_ids = ["${local.account_id}"]
default_tags {
tags = {
environment = "${local.environment}"
terraform = "true"
name = "${basename(get_terragrunt_dir())}"
}
}
}
%{endif}
%{if contains(local.providers, "helm")}
provider "helm" {
kubernetes {
config_path = "~/.kube/config"
}
}
%{endif}
EOF
}
So, in this excerpt I conditionally define the aws
and helm
Terraform providers, along with the configuration that I want to overwrite.
Then, assuming a directory structure where all of the Helm releases live under a folder called helm-releases
and the AWS resources live under a folder called infrastructure
, we can do the following.
So, let’s assume a simple tree structure of (similar to terragrunt-infrastructure-live-example):
aws-account-A
├── account.hcl
└── eu-west-1
├── infrastructure
│ ├── provider.hcl
│ ├── rds
│ │ └── grafana-rds
│ │ └── terragrunt.hcl
│ ├── security-groups
│ │ └── postgresql-kubernetes
│ │ └── terragrunt.hcl
│ └── vpc
│ └── vpcs
│ └── my-new-vpc
│ └── terragrunt.hcl
├── kubernetes
│ └── helm-releases
│ ├── falco
│ │ └── terragrunt.hcl
│ ├── grafana
│ │ └── terragrunt.hcl
│ ├── prometheus
│ │ └── terragrunt.hcl
│ └── provider.hcl
└── region.hcl
We introduce a new file called provider.hcl
, which will contain the Terraform providers that the resources in the children folders will use.
For example, the kubernetes/helm-releases/provider.hcl
file contains:
# Set providers
locals {
providers = ["helm"]
}
…while the infrastructure/provider.hcl
file contains:
# Set providers
locals {
providers = ["aws"]
}
And, of course, getting back to the root terragrunt.hcl
file, we need to add the provider locals, as we already do for the account and region ones, so we add to the locals{}
map:
# Automatically load provider variables
provider_vars = read_terragrunt_config(find_in_parent_folders("provider.hcl"))
# Extract the variables we need for easy access
providers = local.provider_vars.locals.providers
And there it is. Now, provider.hcl
files need to exist, and should include any Terraform providers that we want to conditionally include for any children resources.
Following this, we can easily handle multiple providers and their resources, while keeping the .hcl
files slim.
If this helped you, please feel free to give me a tip! https://ko-fi.com/kostavro