Answers: <p>When you want to refer to a specific instance of a resource that has multiple instances due to using <code>for_each</code>, you need to include the specific key of the instance you want in your references:</p>
  
  <pre><code>  subnet_id = aws_subnet.private["us-east-1a"].id
  </code></pre>
  
  <p>If you just want to select any one subnet from the list, without needing to specify its name directly, you can use an expression like the following to select a single key by sorting the keys lexically and taking the first one:</p>
  
  <pre><code>  subnet_id = aws_subnet.private[keys(aws_subnet.private)[0]].id
  </code></pre>
  
  <p>However, beware that if you do the above then any later changes to <code>var.subnet_numbers_private</code> that affect which subnet sorts first will cause a different subnet id to be selected, which will then in turn cause Terraform to plan to replace your instance to move it into a new subnet.</p>
  
  <hr>
  
  <p>From the way you wrote the question it sounds like you want just one instance in a single subnet rather than one instance <em>per</em> subnet, but if you did want an instance per subnet then you can achieve that by putting <code>for_each</code> in the <code>aws_instance</code> resource too, using the subnet resource itself (represented in expressions as a map) as the repetition expression:</p>
  
  <pre><code>resource "aws_instance" "jenkins" {
    for_each = aws_subnet.private
  
    # ...
    subnet_id = each.value.id
    # ...
  }
  </code></pre>
  
  <p>In this latter case, the <code>aws_instance.jenkins</code> instances will also be identified by the keys you selected for the subnets, so you'd have instances with addresses like <code>aws_instance.jenkins["us-east-1a"]</code> and <code>aws_instance.jenkins["us-east-1b"]</code> so both you and Terraform can see which instance belongs to which subnet.</p>
  
Answers: CC BY-SA 4.0
Answers: 2019-11-04T17:05:38.333Z
Answers: 2019-11-04T17:05:38.333Z
Answers: Martin Atkins
Body: <p>I am trying to create an ec2 instance that will hold my Jenkins server. I want this to be in a private subnet which I created using a for each loop. Below is my subnet for each loop and my ec2 instance resource. I have also included the error message. Idea is I want it in the first private subnet.</p>
  
  <p>ec2 instance</p>
  
  <pre><code>resource "aws_instance" "jenkins" {
    ami           = "${var.ubuntuAMI}"
    instance_type = "t3.micro"
    availability_zone = "us-east-1a"
    key_name = "me"
    monitoring = true
    vpc_security_group_ids = [aws_security_group.ssh_access.id]
    disable_api_termination = true
    subnet_id = "${aws_subnet.private[each.key]}"
  
    tags = {
      Name = "Jenkins"
    }
  }
  </code></pre>
  
  <p>subnet resource</p>
  
  <pre><code>resource "aws_subnet" "private" {
    for_each = var.subnet_numbers_private
  
    vpc_id            = aws_vpc.Main_VPC.id
    availability_zone = each.key
    cidr_block        = cidrsubnet(aws_vpc.Main_VPC.cidr_block, 8, each.value)
    tags = {
        Name = "Private-${each.key}"
    }
  }
  </code></pre>
  
  <p>variable used by the subnet loop</p>
  
  <pre><code>variable "subnet_numbers_private" {
    description = "Map for private subnets"
    default     = {
      "us-east-1a" = 1
      "us-east-1b" = 2
      "us-east-1c" = 3
    }
  }
  </code></pre>
  
  <p>error message seen when doing a <code>terraform plan</code></p>
  
  <pre><code>The "each" object can be used only in "resource" blocks, and only when the
  "for_each" argument is set.
  </code></pre>
  
Tags: <terraform>
Title: How to specify specific subnet in Terraform when using for each
UserDisplayName: joshk132
ThreadText: # How to specify specific subnet in Terraform when using for each
  
  (Asked by: username_0 on 2019-11-03)
  
  I am trying to create an ec2 instance that will hold my Jenkins server. I want this to be in a private subnet which I created using a for each loop. Below is my subnet for each loop and my ec2 instance resource. I have also included the error message. Idea is I want it in the first private subnet.
  
  ec2 instance
  
  ```
  resource "aws_instance" "jenkins" {
    ami           = "${var.ubuntuAMI}"
    instance_type = "t3.micro"
    availability_zone = "us-east-1a"
    key_name = "me"
    monitoring = true
    vpc_security_group_ids = [aws_security_group.ssh_access.id]
    disable_api_termination = true
    subnet_id = "${aws_subnet.private[each.key]}"
  
    tags = {
      Name = "Jenkins"
    }
  }
  
  ```
  
  subnet resource
  
  ```
  resource "aws_subnet" "private" {
    for_each = var.subnet_numbers_private
  
    vpc_id            = aws_vpc.Main_VPC.id
    availability_zone = each.key
    cidr_block        = cidrsubnet(aws_vpc.Main_VPC.cidr_block, 8, each.value)
    tags = {
        Name = "Private-${each.key}"
    }
  }
  
  ```
  
  variable used by the subnet loop
  
  ```
  variable "subnet_numbers_private" {
    description = "Map for private subnets"
    default     = {
      "us-east-1a" = 1
      "us-east-1b" = 2
      "us-east-1c" = 3
    }
  }
  
  ```
  
  error message seen when doing a `terraform plan`
  
  ```
  The "each" object can be used only in "resource" blocks, and only when the
  "for_each" argument is set.
  
  ```
  
  **Tags:** terraform
  
  
  ---
  
  ## 1 answers
  
  ### Answer by username_1 on 2019-11-04. Score: 1 | Accepted answer
  
  When you want to refer to a specific instance of a resource that has multiple instances due to using `for_each`, you need to include the specific key of the instance you want in your references:
  
  ```
    subnet_id = aws_subnet.private["us-east-1a"].id
  
  ```
  
  If you just want to select any one subnet from the list, without needing to specify its name directly, you can use an expression like the following to select a single key by sorting the keys lexically and taking the first one:
  
  ```
    subnet_id = aws_subnet.private[keys(aws_subnet.private)[0]].id
  
  ```
  
  However, beware that if you do the above then any later changes to `var.subnet_numbers_private` that affect which subnet sorts first will cause a different subnet id to be selected, which will then in turn cause Terraform to plan to replace your instance to move it into a new subnet.
  
  ---
  
  From the way you wrote the question it sounds like you want just one instance in a single subnet rather than one instance *per* subnet, but if you did want an instance per subnet then you can achieve that by putting `for_each` in the `aws_instance` resource too, using the subnet resource itself (represented in expressions as a map) as the repetition expression:
  
  ```
  resource "aws_instance" "jenkins" {
    for_each = aws_subnet.private
  
    # ...
    subnet_id = each.value.id
    # ...
  }
  
  ```
  
  In this latter case, the `aws_instance.jenkins` instances will also be identified by the keys you selected for the subnets, so you'd have instances with addresses like `aws_instance.jenkins["us-east-1a"]` and `aws_instance.jenkins["us-east-1b"]` so both you and Terraform can see which instance belongs to which subnet.
  
  
  ---
  
  