Saturday, November 16, 2019

Streamlining Tagging in Terraform projects.

Tagging resources in Azure or AWS Terraform projects used to be such a mind-numbing pain before the release of Terraform 0.12. For each resource in a Terraform project, the tag section was very verbose and very repetitive.  Now, with new variable functionality that comes with Terraform 0.12, I've fallen into a much more streamlined way of maintaining tags.

Tagging before Terraform 0.12

Before new features for Terraform 0.12, often a variable file had a large section dedicated to tag values and resources assigned those tags had many lines dedicated to tagging as well. An example of what life used to be like is below.  This ritual was repeated for any other resoruces in the project that needed tags.
resource "aws_instance" "webServer" {
 ami           = "${data.aws_ami.linux_ami.id}"
 instance_type = "t2.micro"
 subnet_id  = "${var.subnet_id}"
 key_name = "${var.key_pair}"

 tags {
   "Name" = "${var.instance_name}"
   "Environment" = "${var.environment}"
   "ChargebackDept" = "${var.chargeback}"
   "Business Priority" = "${var.priority}"
Many more tags indeed ad nauseum!
 }

}

Tagging after Terraform 0.12

I've fallen into the habit of using Terraform's new variable typing construct along with the map variable type and the map and merge functions. Today, my tag references look like the following for all resources that need tags. The important part is yellow.

resource "aws_instance" "webServer" {
 ami           = "${data.aws_ami.linux_ami.id}"
 instance_type = "t2.micro"
 subnet_id  = "${var.subnet_id}"
 key_name = "${var.key_pair}"

 tags {
   tags = "${merge(var.project_tags, var.environment_tags, map("Name", var.instance_name))}"
 }
}

Notice I use the merge function to combine two maps together. The first is project-wide and the second contains environment-related tag names and values. I also use the map function to add an entry for this specific resource.

In a variable file I typically call vars.tf, there are two variables declared. One has project-wide tag entries and another I reserve for environment-related entries.  Here's an example from vars.tf:
variable "project_tags" {
  type          = map
  default = {
    ChargebackDept         = "dan_haberer@vfc.com"
    BusinessPriority          = "VF Services"
 Include any number of tags in a format easy to maintain
  }
}

variable "environment_tags" {
  type          = map

}

Additionally, I typically use a tfvars file for environment-related tags.  Here's an example:
environment_tags = {
    Environment = "Development"

}

Looking at the Pros and Cons

I like this approach over the previous approach for several reasons.

Tag names and values are easy to maintain. Most tag names and values are in one spot. 

There are not as many variables to declare. While the variables contain larger values in the form of maps, I don't need to handle nearly as many of them in my Terraform projects.

This solution is much less verbose. I've cut hundreds of lines from some of my Terraform projects with this trick alone.

I hope you find this trick useful. I'm always open to ways to streamline Terraform code even further.


No comments:

Post a Comment