Introduction Managing can be an extremely arduous process. AWS doesn’t have logical resource groups and other niceties that Azure and GCP have. This notwithstanding, AWS is still far and away from the most popular cloud provider in the world. Therefore, it’s still very important to find ways to organize your resources effectively. AWS resources One of the most important ways to organize and filter your resources is by using While tagging can be a tedious process, Terraform can help ease the pain by providing your AWS resources. In this blog and accompanying video series, we’re going to take a look at various methods and strategies to tag your resources and keep them organized efficiently. AWS tags. several ways to tag These posts are written so that you can follow along with the YouTube video below. You will just need an environment that has access to the AWS API in your region. I typically use for this purpose, but any environment with access will do. AWS Cloud9 https://www.youtube.com/watch?v=-U6k0eQSVfc Github repo: https://github.com/CloudForecast/aws-tagging-with-terraform Tag Blocks The first method we can use to tag resources is by using a basic tag block. Let’s create a file and configure an S3 bucket to take a look at this. main.tf Configure Terraform to use the AWS provider terraform { required_providers { aws = { source = "hashicorp/aws" version = "~> 4.0" } } } Configure the AWS Provider provider "aws" { region = "us-west-2" } Create a random ID to prevent bucket name clashes resource "random_id" "s3_id" { byte_length = 2 } We utilize the function: https://registry.terraform.io/providers/hashicorp/random/latest/docs/resources/id to create the entropy needed in our bucket names to ensure we do not overlap with the name of another S3 bucket. random_id Create an S3 Bucket w/ Terraform and Tag It resource "aws_s3_bucket" "devops_bucket" { bucket = "devops-bucket-${random_id.s3_id.dec}" tags = { Env = "dev" Service = "s3" Team = "devops" } } Now, let’s run . terraform apply -auto-approve Once the apply is finished, let’s run and then run to verify the tags: terraform console aws_s3_bucket.devops_bucket.tags > aws_s3_bucket.devops_bucket.tags tomap({ "Env" = "dev" "Service" = "s3" "Team" = "devops" }) To exit the console, run or . You can also just run , , or just scroll up through the output to see the tags. exit ctrl+c terraform state show aws_s3_bucket.devops_bucket.tags terraform show As you can see, AWS tags can be specified on AWS resources by utilizing a block within a resource. This is a simple way to ensure each s3 bucket has tags, but it is in no way efficient. Tagging every resource in AWS like this is not only tedious and the complete opposite of the DRY (Don’t Repeat Yourself) principle, but it’s also avoidable to an extent! tags Default AWS Tags & Terraform In order to specify deployment-wide tags, you can specify a block within the provider block. This will allow you to specify fallback tags for any resource that has no tags defined. If, however, you do specify tags on a specific resource, those tags will take precedence. Let’s take a look: default_tags Using Terraform to Create a Second S3 bucket resource "aws_s3_bucket" "finance_bucket" { bucket = "cloudforecast-finance-${random_id.s3_id.dec)" tags = { Env = "dev" Service = "s3" Team = "finance" } } Once you have added the second bucket definition and saved the file, go ahead and apply the configuration with . Once you have applied, you can run and access both buckets by their resource name: terraform apply -auto-approve terraform console > aws_s3_bucket.devops_bucket.tags tomap({ "Env" = "dev" "Service" = "s3" "Team" = "devops" }) > aws_s3_bucket.finance_bucket.tags tomap({ "Env" = "dev" "Service" = "s3" "Team" = "finance" }) If we were to deploy 10s, 100s, or even 1000s of resources, this would not be very efficient. Let’s add default tags to make this more efficient: Add Default AWS Tags w/ Terraform Within the block of our configuration, add the default tag in order to assign both resources the tag: provider Env provider "aws" { region = "us-west-2" default_tags { tags = { Env = "dev" } } } Remove Env tags w/ Terraform Now that we’ve added the default tags, let’s remove the tag from the AWS S3 buckets: Env resource "aws_s3_bucket" "devops_bucket" { bucket = "devops-bucket-${random_id.s3_id.dec}" tags = { Service = "s3" Team = "devops" } } resource "aws_s3_bucket" "finance_bucket" { bucket = "finance-bucket-${random_id.s3_id.dec}" tags = { Service = "s3" Team = "finance" } } Run again and, once it’s finished deploying, run . Within the console, type the resource address of each S3 bucket and view the output: terraform apply -auto-approve terraform console > aws_s3_bucket.devops_bucket.tags tomap({ "Service" = "s3" "Team" = "devops" }) > aws_s3_bucket.finance_bucket.tags tomap({ "Service" = "s3" "Team" = "finance" }) Do you notice something missing? Default tags are not displayed within the attribute. Default tags are found within the attribute, so re-run the previous commands with replacing : tags tags_all tags_all tags > aws_s3_bucket.devops_bucket.tags_all tomap({ "Env" = "dev" "Service" = "s3" "Team" = "devops" }) > aws_s3_bucket.finance_bucket.tags_all tomap({ "Env" = "dev" "Service" = "s3" "Team" = "finance" }) There they are! Keep this in mind. If you are querying the state to perform actions based on tags, you will want to use the attribute instead of just by themselves. tags_all tags Tag Precedence Now, for one last quick test to see the tag precedence in action, let’s add the tag back to our finance bucket, but define it as instead of : Env prod dev resource "aws_s3_bucket" "finance_bucket" { bucket = "finance-bucket-${random_id.s3_id.dec}" tags = { Env = "prod" Service = "s3" Team = "finance" } } Run again: terraform apply -auto-approve # aws_s3_bucket.finance_bucket will be updated in-place ~ resource "aws_s3_bucket" "finance_bucket" { id = "finance-bucket-52680" ~ tags = { + "Env" = "prod" # (2 unchanged elements hidden) } ~ tags_all = { ~ "Env" = "dev" -> "prod" # (2 unchanged elements hidden) } # (17 unchanged attributes hidden) } Notice the changes made, then run : terraform console > aws_s3_bucket.finance_bucket.tags_all tomap({ "Env" = "prod" "Service" = "s3" "Team" = "finance" }) Notice the tag has now been changed to , our updated value, overriding the default tags. Env prod Destroy Resources Now, if you’re ready, go ahead and destroy your resources! terraform destroy -auto-approve Conclusion Alright, so now that we have an idea of how to assign custom tags and default tags, join me on the next part in this series where we dive deeper! Also Published Here