Tagging with Terraform
Tags: aws, devops, terraform, howto
Published: 2019-06-25 12:08:04

---
title: Tagging with Terraform
published: true
description: Using cloud resources can be accelerating to the business, liberating to the engineering teams, and expensive to bank account. Use tags to manage your resources!
tags: aws, devops, terraform, howto
cover_image: https://blog.davidjeddy.com/wp-content/uploads/2018/07/hashicorp_terraform.png
---

[Sourced from my blog](https://blog.davidjeddy.com/2019/06/25/tagging-with-terraform/).

<!-- wp:paragraph {"dropCap":true} -->
<p class="has-drop-cap">Using cloud resources can be accelerating to the business, liberating to the engineering teams, and expensive to bank account. If you have every left a large compute or database instance running over a weekend (or accidentally committed API keys to GitHub) it is easy to experience a large increase in operating costs for the month. Using the resource metadata <strong>tagging</strong> functionality responsible parties(1) can audit, track, and manage resources. It is even possible to enact automatic based on tag values (or lack thereof).</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Basic Usage</h2>
<!-- /wp:heading -->

<!-- wp:paragraph {"dropCap":true} -->
<p class="has-drop-cap">The basic tagging structure in Terraform is straightforward enough. If you are familiar with the JSON data interchange format you should recognize this immediately. It is a Java inspired object declaration with quoted key values pairs using a colon as separator and a comma as a delimiter. Yeay, another DSL to learn. #welcometowebdev</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>...
"aws_resource_type" "aws_resource" {
    ...
    tags {
        "key": "value",
        "Name": "Value",
        "department": "engineering",
        "team": "core_api",
        "app": "name",
        "env": "dev"
        ...
    }
    ...
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph {"dropCap":true} -->
<p class="has-drop-cap">Nothing to difficult about that. Most (not all) resources in AWS support tagging in this manner. Straight forward JSON styled key/value pairs. Terraform even allows us to use variables in place of values, but not keys(2).</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":1381} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://blog.davidjeddy.com/wp-content/uploads/Chad_Hagan_Art_and_Design/The-New-Yorker/Gonnorea_final_New_Yorker_f-1440x1440.jpg" alt="" class="wp-image-1381"/><figcaption>Weird..</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:code -->
<pre class="wp-block-code"><code>...
"aws_resource_type" "aws_resource" {
    ...
    tags {
        "key": "value",
        "Name": "Value",
        "department": "${var.dept_name",
        "team": "${var.team_name",
        "app": "${var.app_name",
        "env": "${var.app_env}"
        ...
    }
    ...
}</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>"But David" you will say "application infrastructure can be very complicated. Will I have to copy / paste the 'tag' attribute all over the place?" Short answer; No. Long Answer: ...</p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Advanced Usage</h2>
<!-- /wp:heading -->

<!-- wp:paragraph {"dropCap":true} -->
<p class="has-drop-cap">Using some Terraform-fu we can assign the default sets of key/value pairs to a map type variable (local or imported) and that variable as the default tags data set. The format changes slightly between a JSON object to a Terraform (HCL) map data type; but not by much.</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>variable "default_tags" { 
    type = "map" 
    default = { 
        key: "value",
        Name: "Value",
        department: "${var.dept_name",
        team: "${var.team_name",
        app: "${var.app_name",
        env: "${var.app_env}"
  } 
}
...</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph -->
<p>With the tags abstracted as a map the tag attribute for the resource is linimized to a one liner.</p>
<!-- /wp:paragraph -->

<!-- wp:image {"align":"center","id":1355} -->
<div class="wp-block-image"><figure class="aligncenter"><img src="https://blog.davidjeddy.com/wp-content/uploads/Chad_Hagan_Art_and_Design/IEEE/IEEE__Complicated_Fin.jpg" alt="" class="wp-image-1355"/><figcaption>Electrical circuits or IaC diagram? You decide!</figcaption></figure></div>
<!-- /wp:image -->

<!-- wp:code -->
<pre class="wp-block-code"><code>...
"aws_resource_type" "aws_resource" {
    ...
    tags = var.default_tags
    ...
}
...</code></pre>
<!-- /wp:code -->

<!-- wp:paragraph {"dropCap":true} -->
<p class="has-drop-cap">The power level up is to merging the default tags map variable with custom inline tags. We for this we get fancy and start using the TF merge(). Providing the  default tag map variable as one function argument and the custom tags as a second map type function argument we get to use both the default provided tags AND custom inline tags! Boom, Magic!</p>
<!-- /wp:paragraph -->

<!-- wp:code -->
<pre class="wp-block-code"><code>...
"aws_resource_type" "aws_resource" {
    ...
    tags = "${merge(map( 
            "Special_Key", "some special value", 
            "Special_Key_2", "some other special value",
            ...
        ), var.default_tags)}"
    ...
}
...</code></pre>
<!-- /wp:code -->

<!-- wp:heading -->
<h2>Wrap Up</h2>
<!-- /wp:heading -->

<!-- wp:paragraph {"dropCap":true} -->
<p class="has-drop-cap">Hashicorp continues to improve Terraform with each release. Say what you will about HCL being nearly JSON but with additional functionality; it is a powerful and featurful tool set to manage a projects infrastructure. With an appropriate  tagging strategy it also becomes a powerful way to track that infrastructure as well. </p>
<!-- /wp:paragraph -->

<!-- wp:heading -->
<h2>Notes</h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li>I did <strong>not</strong> say "managers" on purpose. In a true DevOps environment every developer, operator,  SysAdmin, on every team within every technology value stream is should be aware of how and responsible for the system as a whole. Share the burden. No silos.</li><li>Using map() it is possible to use a variable as a key. This is because map() evaluated the variable "key" before returning.</li><li>This concept weirded me out at out first. But after thinking about the mechanics it makes sense. Why would the last operation in a function be on a variable NOT being returned?</li></ul>
<!-- /wp:list -->

<!-- wp:heading -->
<h2>Additional Reading</h2>
<!-- /wp:heading -->

<!-- wp:list -->
<ul><li><a href="https://weidongzhou.wordpress.com/2018/12/13/how-to-do-tagging-efficiently-in-terraform/">https://weidongzhou.wordpress.com/2018/12/13/how-to-do-tagging-efficiently-in-terraform/</a></li><li><a href="https://groups.google.com/forum/#!topic/terraform-tool/1yjotodsBog">https://groups.google.com/forum/#!topic/terraform-tool/1yjotodsBog</a></li><li><a href="https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html">https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html</a></li><li><a href="https://blog.scottlowe.org/2018/06/11/using-variables-in-aws-tags-with-terraform/">https://blog.scottlowe.org/2018/06/11/using-variables-in-aws-tags-with-terraform/</a></li><li><a href="https://blog.scottlowe.org/2018/06/11/using-variables-in-aws-tags-with-terraform/">https://blog.scottlowe.org/2018/06/11/using-variables-in-aws-tags-with-terraform/</a></li><li><a href="https://www.terraform.io/docs/configuration/locals.html">https://www.terraform.io/docs/configuration/locals.html</a> (0.12+)</li></ul>
<!-- /wp:list -->