Default tags for Terraform AWS provider had been in the works since I started using Terraform a couple of years ago. Now that it is finally here, does it live up to its expectation?
What is Default Tags?
Default Tags allows its user to tag all AWS resources that support tags with the exception of the aws_autoscaling_group
resource. Default Tags are defined in the AWS provider configuration, and AWS resources configured with that provider will inherit default_tags
. A sample usage could be:
provider "aws" {
region = "ap-southeast-1"
default_tags {
tags = {
Environment = "dev"
Project = "example project"
Terraform = true
}
You can read more about it here and here.
Default Tags in different scenarios
From the official blog post, it states that individual resource tags will take precedence over default_tags
. Let’s see it in action with a few scenarios and observe its terraform plan
output.
Scenario 1: Only resource tags, no default_tags
provider "aws" {
region = "ap-southeast-1"
}
resource "aws_vpc" "tagging_test_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "tagging-test"
Environment = "dev"
Terraform = true
}
}
Here, we can see the existence of a tags_all
attribute that has the same value as the original tags
attribute. That being said, I’ve noticed this tags_all
attribute for some time now in the newer versions of AWS provider. Let’s move on to the next scenario.
Scenario 2: Only default_tags
, no resource tags
provider "aws" {
region = "ap-southeast-1"
default_tags {
tags = {
Environment = "stg"
Name = "tagging-test-3"
}
}
resource "aws_vpc" "tagging_test_vpc" {
cidr_block = "10.0.0.0/16"
}
Without resource tags, the tags
attribute disappears, leaving only the tags_all
attribute with the value inherited from default_tags
from the AWS provider configuration.
Scenario 3: Conflicting tags
provider "aws" {
region = "ap-southeast-1"
default_tags {
tags = {
Environment = "stg"
Name = "tagging-test-3"
}
}
resource "aws_vpc" "tagging_test_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "tagging-test"
Environment = "dev"
Terraform = true
}
}
Similar to what the official blog post mentioned, we can observe that resource tags take precedence over default tags when there is a conflict of tag name/key.
Scenario 4: Non-conflicting tags
provider "aws" {
region = "ap-southeast-1"
default_tags {
tags = {
environment = "stg"
name = "tagging-test-3"
provisionedby = "Terraform"
}
}
resource "aws_vpc" "tagging_test_vpc" {
cidr_block = "10.0.0.0/16"
tags = {
Name = "tagging-test"
Environment = "dev"
Terraform = true
}
}
terraform plan
truncated output:
Since tag names/keys are case-sensitive, all the default_tag tags in this example will be effected for aws_vpc
. The tags_all
attribute shows a combined list from default and resource tags, while the tags
attribute only shows the resource tags.
How this could affect your Terraform State design
In a medium-to-large-sized project, Terraform state separation is one of the early design considerations a team needs to settle on. If you don’t know what state is, check out this documentation first.
Each Terraform state culminates in a state file, and each state file has its own Terraform and provider configurations. Since default tags are a configured on the AWS provider level, being able to enforce different default tags in different states can make any mandatory organizational tagging requirements a breeze.
For example, if your organization has different tag values for each application, it might make sense to separate all applications into it’s own state and enforce their unique application tags at the provider level.
Terraform state design is a topic I’ve always seen a lot of discussion about. I will write about it in a future post.
Closing Thoughts
It’s good to know that Terraform and the AWS Provider is still well supported and constantly improved on. All in all, Terraform as an IaC tool is reaching a level of maturity that I’ve been looking forward to. With the current Terraform 0.15 touted as the “beginning of the pre-release period leading up to Terraform 1.0”, I think Terraform users can expect a lot of exciting and useful releases in the coming weeks and months.
Top comments (3)
Some things to add:
The
tags_all
is a new attribute that is added to each resource, hence the state file will be changed even if the tags remain the sameIf you try to specify the same list of tags globally (in provider configuration) and in the resource configuration, Terraform will throw an error:
Tags from
default_tags
are inherited by child modules. But if the child module has its own provider configuration for some resources, these resources will not inherit thedefault_tags
from the root module.The
default_tags
section supports variables:That's amazing! Thank you for highlighting this!
Great writeup!