17

To attach multiple tags to a resource, I currently use multiple tag blocks:

resource "aws_autoscaling_group" "instance" {
  ...

  tag {
    key                 = "Name"
    value               = "${var.cluster_prefix}"
    propagate_at_launch = true
  }

  tag {
    key                 = "Owner"
    value               = "${var.tag_Owner}"
    propagate_at_launch = true
  }

  tag {
    key                 = "Project"
    value               = "${var.tag_Project}"
    propagate_at_launch = true
  }
}

It works, but I wonder if there is a more concise syntax. It is also a bit error prone as you have to specify propagate_at_launch for each tag.

Update: The question was written before Terrafrom v0.12 came out. Since then the support has improved with Dynamic Nested Blocks (see my answer below).

5 Answers 5

9

For an auto-scaling-group this is the most concise syntax available.

For most other resources you use the tags syntax which looks like:

tags {
  Key1 = "value1"
  Key2 = "value2"
}
1
6

Terraform v0.12 added support for Dynamic Nested Blocks. The following example is derived from their blog post about the new features (see section Dynamic Nested Blocks):

locals {
  standard_tags = {
    Name    = var.cluster_prefix
    Owner   = var.tag_Owner
    Project = var.tag_Project
  }
}

resource "aws_autoscaling_group" "example" {
  # ...

  dynamic "tag" {
    for_each = local.standard_tags

    content {
      key                 = tag.key
      value               = tag.value
      propagate_at_launch = true
    }
  }
}
2

Another option is to use the terraform-null-label module. It supports passing a variable called tags as a standard Terraform map. The module then emits an output called tags_as_list_of_maps which contains the tags in the format you want. But an even better reason to use this module is to generate a consistent set of resource names that follow a fixed convention.

For example, you can do this:

module "example" {
  source     = "git::https://github.com/cloudposse/terraform-null-label.git?ref=master"
  namespace  = "eg"
  stage      = "prod"
  name       = "bastion"
  tags       = { 
                 "BusinessUnit" = "XYZ" 
                 "Snapshot" = "true"
               }
}

So from your example, we can then write something like this:

resource "aws_autoscaling_group" "instance" {
  ...
  name = "${module.example.id}"
  ...
  tags = "${module.example.tags_as_list_of_maps}"
  ...
}

NOTE: I added the name field to show how to generate co

1
  • What would be the best way to make "name" uniq to each ressource? if you use the null-label module every "name" on the ressources is the same. What if you want to name your subnets with a suffix like -private-subnet? Is there a way the null-label can handle that?
    – Izac
    Jun 27, 2019 at 15:27
1

The aws_autoscaling_group does support a list of tags now (https://www.terraform.io/docs/providers/aws/r/autoscaling_group.html#tags). But this looks a bit different to the syntax of other terraform resources:

tags = [
  {
    key                 = "explicit1"
    value               = "value1"
    propagate_at_launch = true
  },
  {
    key                 = "explicit2"
    value               = "value2"
    propagate_at_launch = true
  },
]

This also allows to dynamically build tags via interpolation.

0

Here is the best way to do now

To be able to

  1. Attach the same common tags to all resources
  2. While still being able to add custom tags to individual resources.

You can add the default tag section in terraform provider section

# Configure the AWS Provider
provider "aws" {
  region  = var.aws_region
  profile = var.aws_profile

  default_tags {
    tags = {
      environment = var.tag_environment
      created_by  = var.tag_created_by
    }
  }

}

You can check the read the docs here

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.