Dave Michaels
Dave Michaels

Reputation: 937

Applying tags to instances created with for each Terraform

I have multiple EC2 instances created using for each. Each instance is being deployed into a different subnet. I am getting an error when trying to apply tags to each instance being deployed. Any advice would be helpful. Below is the code for my tags and instances:

resource "aws_instance" "private" {
  for_each      = aws_subnet.private
  ami           = var.ec2_amis[var.region]
  instance_type = var.tableau_instance
  key_name      = aws_key_pair.tableau.key_name
  subnet_id     = each.value.id

  tags = {
    Name = var.ec2_tags[each.key]
  }
}

variable "ec2_tags" {
  type = list(string)
  default = [
    "PrimaryEC2",
    "EC2Worker1",
    "EC2Worker2"
  ]
}

Error

Error: Invalid index

  on vpc.tf line 21, in resource "aws_instance" "private":
  21:     Name = var.ec2_tags[each.key]
    |----------------
    | each.key is "3"
    | var.ec2_tags is list of string with 3 elements

The given key does not identify an element in this collection value.

I had this code working earlier, not sure what happened. I made a change to the AMI it spins up, but I don't see why that could have an effect on tags. Any advice would be helpful.

UPDATE I have updated the resource with the following locals block and dynamic block within my "aws_instance" "private" code:

locals {
  private_instance = [{
    name = "PrimaryEC2"
    },
    {
      name = "EC2Worker1"
    },
    {
      name = "EC2Worker2"
  }]
}


    dynamic "tags" {
    for_each = local.private_instance

    content {
      Name = tags.value.name
    }
  }

Error

Error: Unsupported block type

  on vpc.tf line 28, in resource "aws_instance" "private":
  28:   dynamic "tags" {

Blocks of type "tags" are not expected here.

Any advice how to fix would help. Thanks!

Upvotes: 1

Views: 2542

Answers (2)

Marcin
Marcin

Reputation: 238081

If you want to make your tags dynamic, you could create them as follows:

  tags = {
    Name = each.key == "0" ? "PrimaryEC2" : "EC2Worker${each.key}" 
  }

You would use it as follows (assuming everything else is OK):

resource "aws_instance" "private" {
  for_each      = aws_subnet.private
  ami           = var.ec2_amis[var.region]
  instance_type = var.tableau_instance
  key_name      = aws_key_pair.tableau.key_name
  subnet_id     = each.value.id

  tags = {
    Name = each.key == "0" ? "PrimaryEC2" : "EC2Worker${each.key}" 
  }
}

The code uses conditional expression. It works as follows.

If each.key is equal to "0" (i.e., first instance being created) then its tag will be "PrimaryEC2". All remaining instances will be tagged: "EC2Worker1", "EC2Worker2", "EC2Worker3" and so on for as many subnets there are.

Upvotes: 2

khaleesi
khaleesi

Reputation: 983

One possible cause of this errors is that the aws_subnet.private variable is longer then the list of ec2 tags which would result in an error when the index 3 is used on your ec2_tags list looking for the 4th (nonexistent element).

Upvotes: 0

Related Questions