How do I enforce tagging using Terragrunt #756
Replies: 1 comment
-
|
One question that comes up on the items above is how to override the tags. There are a few scenarios for this: Scenario 1: overriding tags within a moduleLet's say you've configured provider "aws" {
default_tags {
tags = {
Environment = "test"
Name = "example"
}
}
}However, in some module, you want to override these tags in a specific resource. You can do so by using the resource "aws_vpc" "example" {
# ..other configuration...
tags = {
Name = "example-vpc"
}
}Any
Scenario 2: overriding tags on a per-environment / per-module basisAnother scenario may be that you want to override tags to different values in different live environments. For example, let's again assume you have provider "aws" {
default_tags {
tags = {
Environment = "test"
Name = "example"
}
}
}And in your variable "tags" {
description = "Custom tags to set on the VPC"
type = map(string)
default = {}
}
resource "aws_vpc" "example" {
# ..other configuration...
tags = var.tags
}Now you can optionally override the tags with different values in different environments. E.g., In stage, you might set: tags = {
Name = "example-vpc-stage"
}And in prod, you might set: tags = {
Name = "example-vpc-prod"
}Scenario 3: supporting tag overrides globally with TerragruntOne other neat thing you can do with Terragrunt is to add support for overriding the tags on all resources, globally. This way, you don't have to add a To do that, you first create a root locals {
# The default tags to apply in all environments
default_tags = {
Environment = "test"
Name = "example"
}
# Load an overrides.yml file in any Terragrunt folder, or fallback to {} if none is found
overrides = try(yamldecode(file("${get_terragrunt_dir()}/overrides.yml")), {})
# Read the override tags, if any, from overrides.yml, or fallback to {} if none are found
override_tags = lookup(local.overrides, "tags", {})
# The final tags to apply to all resources are a merge between the default tags and override tags
tags = merge(local.default_tags, local.override_tags)
}
generate "provider" {
path = "provider.tf"
if_exists = "overwrite"
contents = <<EOF
provider "aws" {
default_tags {
tags = ${jsonencode(local.tags)}
}
}
EOF
}This structure defines some default tags to apply to all modules, but it also allows each module to optionally define an So, for example, in # Include the root terragrunt.hcl config
include "root" {
path = find_in_parent_folders()
}And also in tags:
Name: vpc-stageIn tags:
Name: vpc-prodIn other words, any of your Terragrunt modules can now include an |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
I'm adapting an answer originally written by @brikis98.
Let's take a look at some options for solving this:
Use the Terraform AWS Provider
The AWS Provider supports the default_tags parameter. This works with all AWS resources except
aws_autoscaling_group. Here's an example:But this has a key limitation: you have to ensure every single module specifies those tags in its
providerblock. There is no way to "reuse" that logic with Terraform. You just have to manually copy/paste it into every single module you create. So it’s very error prone and easy to miss it.Static analysis
You could add static analysis to the CI / CD pipeline of your module repos that scans every module and blocks merge if that module doesn’t specify the proper
default_tagsblock. See this example using tfsec.Use
generateblocks with TerragruntTerragrunt supports a generate block. Instead of hard-coding the
providerblock in every single module, you can ensure that every repo that uses Terragrunt has a single, centralgenerateblock used by everything in that repo. Thatgenerateblock can include thedefault_tagsyou want.Here's an example of how Gruntwork handles this when we set up new DevOps foundations customers:
Tracked in ticket #110367
Beta Was this translation helpful? Give feedback.
All reactions