skip to Main Content
➜ terraform -v  
Terraform v0.12.24
+ provider.aws v2.60.0

My terraform example.tf:

locals {
  standard_tags = {
    team        = var.team
    project     = var.project
    component   = var.component
    environment = var.environment
  }
}

provider "aws" {
  profile = "profile"
  region  = var.region
}

resource "aws_key_pair" "security_key" {
  key_name   = "security_key"
  public_key = file(".ssh/key.pub")
}

# New resource for the S3 bucket our application will use.
resource "aws_s3_bucket" "project_bucket" {
  # NOTE: S3 bucket names must be unique across _all_ AWS accounts, so
  # this name must be changed before applying this example to avoid naming
  # conflicts.
  bucket = "project-bucket"
  acl    = "private"
}


resource "aws_security_group" "ssh_allow" {
  name = "allow-all-ssh"
  ingress {
    cidr_blocks = [
      "0.0.0.0/0"
    ]
    from_port = 22
    to_port   = 22
    protocol  = "tcp"
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}

resource "aws_security_group" "http_allow" {
  name = "allow-all-http"
  ingress {
    cidr_blocks = [
      "0.0.0.0/0"
    ]
    from_port = 80
    to_port   = 80
    protocol  = "tcp"
  }
  egress {
    from_port   = 0
    to_port     = 0
    protocol    = "-1"
    cidr_blocks = ["0.0.0.0/0"]
  }
}


resource "aws_instance" "example" {
  ami             = "ami-08ee2516c7709ea48"
  instance_type   = "t2.micro"
  security_groups = [aws_security_group.ssh_allow.name, aws_security_group.http_allow.name]
  key_name        = aws_key_pair.security_key.key_name

  connection {
    type        = "ssh"
    user        = "centos"
    private_key = file(".ssh/key")
    host        = self.public_ip
  }


  provisioner "local-exec" {
    command = "echo ${aws_instance.example.public_ip} > ip_address.txt"
  }

  provisioner "remote-exec" {
    inline = [
      "sudo yum -y install nginx",
      "sudo systemctl start nginx"
    ]
  }

  depends_on = [aws_s3_bucket.project_bucket, aws_key_pair.security_key]

  dynamic "tag" {
    for_each = local.standard_tags

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

}

And when I run terraform plan

I got the following error:

➜ terraform plan

Error: Unsupported block type

  on example.tf line 94, in resource "aws_instance" "example":
  94:   dynamic "tag" {

Blocks of type "tag" are not expected here.


3

Answers


  1. There isn’t a block type called tag defined in the schema for the aws_instance resource type. There is an argument called tags, which is I think the way to get the result you were looking for here:

      tags = local.standard_tags
    

    I expect you are thinking of the tag block in aws_autoscaling_group, which deviates from the usual design of tags arguments in AWS provider resources because for this resource type in particular each tag has the additional attribute propagate_at_launch. That attribute only applies to autoscaling groups because it decides whether instances launched from the autoscaling group will inherit a particular tag from the group itself.

    Login or Signup to reply.
  2. unfortunately since the aws_instance resource’s tags attribute is a map, w/in the HCL constructs atm, it cannot exist as repeatable blocks like a tag attribute in the aws_autoscaling_group example seen here in the Dynamic Nested Blocks section: https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each/

    but from your comment, it seems you’re trying to set the tags attribute with perhaps a map of key/value pairs? in this case, this is certainly doable 😄 you should be able to directly set the field with tags = local.standard_tags

    OR if you intend to set the tags attribute with a list of key/value pairs, a for loop can work as well by doing something like:

    locals {
      standard_tags = [
      {
          name   = "a"
          number = 1
        },
        {
          name   = "b"
          number = 2
        },
        {
          name   = "c"
          number = 3
        },
      ]
    }
    
    resource "aws_instance" "test" {
     ...
      tags = {
        for tag in local.standard_tags:
        tag.name => tag.number
      }
    }
    
    
    Login or Signup to reply.
  3. 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 complete docs here

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search