DEV Community

loading...
AWS Community Builders

Default Tags for Terraform AWS Provider is finally here

zhenkai profile image Zhen Kai Originally published at blog.zhenkai.xyz ・3 min read

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
  }
Enter fullscreen mode Exit fullscreen mode

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
  }
}
Enter fullscreen mode Exit fullscreen mode

terraform plan output:
image

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"
}
Enter fullscreen mode Exit fullscreen mode

terraform plan output:
image

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
  }
}
Enter fullscreen mode Exit fullscreen mode

terraform plan output:
image

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
  }
}
Enter fullscreen mode Exit fullscreen mode

terraform plan truncated output:
image

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.

image

From HashiCorp

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

image

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.

Discussion (3)

Collapse
svasylenko profile image
Serhii Vasylenko

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 same

If you try to specify the same list of tags globally (in provider configuration) and in the resource configuration, Terraform will throw an error:

Error: "tags" are identical to those in the "default_tags" configuration block of the provider: please de-duplicate and try again
Enter fullscreen mode Exit fullscreen mode

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 the default_tags from the root module.

The default_tags section supports variables:

  default_tags {
    tags = {
      Division    = var.test_tag
      Environment = "qa"
    }
  }
Enter fullscreen mode Exit fullscreen mode
Collapse
svasylenko profile image
Serhii Vasylenko

That's amazing! Thank you for highlighting this!

Collapse
justnick profile image
Nikolay Bunev

Great writeup!

Forem Open with the Forem app