11
votes

I'm playing around with Terraform for a bit and I was wondering if this is possible. It's best practice to assign tags to each resource you create on AWS (for example). So, what you do first is come up with a tagging strategy (for example, which business unit, a name of the app, a team responsible for it, ...).

However, in Terraform, this means that you have to repeat each tags-block for each resource. This isn't very convenient and if you want to update 1 of the tag names, you have to update each resource that you created.

For example:

resource "aws_vpc" "vpc" {
  cidr_block = "${var.cidr}"

  tags {
    Name         = "${var.name}"
    Project      = "${var.projectname}"
    Environment  = "${var.environment}"
  }
}

If I want to create a Subnet and EC2 in that VPC with the same tags, I have to repeat that tags-block. If I want to update 1 of the tag names later on, I have to update each resource individually, which is very time consuming and tedious.

Is there a possibility to create a block of tags in a centralized location and refer to that? I was thinking of Modules, but that doesn't seem to fit the definition of a module.

4
Although it's not completely what I want, it's a start. I had a look at the Github repository with the Terraform Community Modules and found a much cleaner way: github.com/terraform-community-modules/tf_aws_vpc.Bjorn121
So why not answer your own question?BMW

4 Answers

13
votes

You can also try local values from version 0.10.3. It allows you to assign a symbolic local name to an expression so it can be used multiple times in configuration without repetition.

# Define the common tags for all resources
locals {
  common_tags = {
    Component   = "awesome-app"
    Environment = "production"
  }
}

# Create a resource that blends the common tags with instance-specific tags.
resource "aws_instance" "server" {
  ami           = "ami-123456"
  instance_type = "t2.micro"

  tags = "${merge(
    local.common_tags,
    map(
      "Name", "awesome-app-server",
      "Role", "server"
    )
  )}"
}
3
votes

Terraform version .12 onwords,

This is the variable

variable "sns_topic_name" {
  type        = string
  default     = "VpnTopic"
  description = "Name of the sns topic"
}

This is the code


locals {
  common_tags = {
    Terraform = true
  }
}

# Create a Resource

resource "aws_sns_topic" "sns_topic" {
  name         = var.sns_topic_name

  tags = merge(
    local.common_tags,
    {
      "Name" = var.sns_topic_name
    }
  )
}

Output will be

  + tags         = {
      + "Name"      = "VpnTopic"
      + "Terraform" = "true"
    }
1
votes

Terraform now natively support it for AWS provider.

Check out here

0
votes

As of version 3.38.0 of the Terraform AWS Provider, the Terraform Configuration language also enables provider-level tagging. Reference Link

# Terraform 0.12 and later syntax

provider "aws" {
  # ... other configuration ...
  default_tags {
    tags = {
      Environment = "Production"
      Owner       = "Ops"
    }
  }
}

resource "aws_vpc" "example" {
  # ... other configuration ...

  # This configuration by default will internally combine tags defined
  # within the provider configuration block and those defined here
  tags = {
    Name = "MyVPC"
  }
}

For "aws_vpc.example" resouce below tags will be assigned, which is combination of tags defined under provider and tags defined under aws_vps section:

 + tags         = {
      + "Environment"  = "Production"
      + "Owner"        = "Ops"
      + "Name"         = "MyVPC"
    }