Terraform-provider-aws: aws_subnet_ids Data source is returning String

Created on 17 Jul 2019  Â·  12Comments  Â·  Source: hashicorp/terraform-provider-aws

_This issue was originally opened by @rajivreddy as hashicorp/terraform#22099. It was migrated here as a result of the provider split. The original body of the issue is below._


Terraform Version

➜  private_subnets git:(dev) ✗ terraform -v
Terraform v0.12.2
+ provider.aws v2.14.0

Terraform Configuration Files

data.tf

data "aws_subnet_ids" "public_subnet_ids" {
  vpc_id = var.vpc_id
  tags = merge(
    {
      "Environment" = format("%s", var.environment)
      "Tier"        = var.public_subnet_suffix
    },
    var.additional_tags
  )
}

main.tf

resource "aws_nat_gateway" "nat" {
  count = var.create_nat_in_each_az ? 3 : 1
  allocation_id = element(aws_eip.nat_eip.*.id,count.index)
  subnet_id     =  element(data.aws_subnet_ids.public_subnet_ids,count.index) # this is not working
  tags = merge(
    {
      "Name"        = format("%s-nat-gateway-%s-%d", var.name, var.environment,count.index+1)
      "Environment" = format("%s", var.environment)
    },
    var.additional_tags
  )
  lifecycle {
    create_before_destroy = true
    ignore_changes = [
      tags,
    ]
  }
}

Expected Behavior

aws_nat_gateway modules should be able to get individual public_subnet_ids based on count.index based on https://www.terraform.io/docs/providers/aws/d/subnet_ids.html#example-usage
As return value of data.aws_subnet_ids.public_subnet_ids.ids should be a list

Actual Behavior

➜  private_subnets git:(dev) ✗ terraform apply
data.aws_availability_zones.az[0]: Refreshing state...
aws_eip.nat_eip[0]: Refreshing state... [id=eipalloc-sdsd]
data.aws_subnet_ids.public_subnet_ids: Refreshing state...

Error: Error in function call

  on main.tf line 30, in resource "aws_nat_gateway" "nat":
  30:   subnet_id     =  "${element(data.aws_subnet_ids.public_subnet_ids.ids,count.index)}"
    |----------------
    | count.index is 0
    | data.aws_subnet_ids.public_subnet_ids.ids is set of string with 3 elements

Call to function "element" failed: cannot read elements from set of string.

Steps to Reproduce

Please list the full steps required to reproduce the issue, for example:
use the example listed https://www.terraform.io/docs/providers/aws/d/subnet_ids.html#example-usage with 0.12.x TF version

  1. terraform init
  2. terraform plan
  3. terraform apply

References

needs-triage servicec2

Most helpful comment

Convert it to a list should work

data "aws_subnet_ids" "private" {
vpc_id = "${var.vpc_id}"

tags = {
Tier = "Private"
}
}

resource "aws_instance" "app" {
count = "3"
ami = "${var.ami}"
instance_type = "t2.micro"
subnet_id = "${element(tolist(data.aws_subnet_ids.private.ids), count.index)}"
}

All 12 comments

+1

I have just encountered that same issue:
Terraform v0.12.2

  • provider.aws v2.16.0
  • provider.template v2.1.2

+1

Same issue for me.

Issue occurred at --> subnet_id = "${element(data.aws_subnet_ids.test.ids, 0)}

  • Terraform v0.12.3
  • provider.aws v2.20.0

Having the same issue with

  • Terraform v0.12.4/v0.12.5
  • provider.aws v2.20.0

As a workaround splat syntax works

  subnet_id = element(data.aws_subnet_ids.foobar.ids[*], count.index)

Trying the work around did not work for me

data "aws_subnet_ids" "nets" {
  vpc_id = "${aws_vpc.main.id}"

 depends_on = [aws_vpc.main]
}


resource "aws_instance" "mongo" {
  provider    = "aws"
  ami           = "ami-00aa61be0e9a8f948"
  subnet_id     = "${element(data.aws_subnet_ids.nets.ids[*], count.index)}"
}

Gets this error

Error: no matching subnet found for vpc with id vpc-095312a0dbf33a83f

on databases.tf line 9, in data "aws_subnet_ids" "nets":
9: data "aws_subnet_ids" "nets" {

while the VPC has been created

Tried using locals instead of element. This worked for me:

data "aws_subnet_ids" "mysubnets" {
  vpc_id = "${aws_vpc.myVpc.id}"
}

locals {
  subnet_ids_string = join(",", data.aws_subnet_ids.mysubnets.ids)
  subnet_ids_list = split(",", local.subnet_ids_string)
}

resource "aws_nat_gateway" "nat" {
     allocation_id = "${aws_eip.elastic_ip.id}"
     subnet_id = local.subnet_ids_list[0]
}

Convert it to a list should work

data "aws_subnet_ids" "private" {
vpc_id = "${var.vpc_id}"

tags = {
Tier = "Private"
}
}

resource "aws_instance" "app" {
count = "3"
ami = "${var.ami}"
instance_type = "t2.micro"
subnet_id = "${element(tolist(data.aws_subnet_ids.private.ids), count.index)}"
}

I used something like this :

# define a data provider
data "aws_subnet" "subnet-prv-1" {
  count = "${length(data.aws_subnet_ids.prv-1.ids)}"
  id    = "${tolist(data.aws_subnet_ids.prv-1.ids)[count.index]}"
}

# use them in this way
subnets         = ["${data.aws_subnet.subnet-prv-1[0].id}"]

@toddlers Yes
tolist()
Function will works

As @ninjapugdevil and @rajivreddy mentioned, using the tolist function will work. This is because the aws_subnet_ids data source returns a set and not a list.

See:

Someone really needs to update the docs to say that then.

"aws_subnet_ids provides a list of ids for a vpc_id"

As @ninjapugdevil and @rajivreddy mentioned, using the tolist function will work. This is because the aws_subnet_ids data source returns a set and not a list.

See:

Hi @bbaptist,
I already raised a PR for updating docs.

Convert it to a list should work

data "aws_subnet_ids" "private" {
vpc_id = "${var.vpc_id}"

tags = {
Tier = "Private"
}
}

resource "aws_instance" "app" {
count = "3"
ami = "${var.ami}"
instance_type = "t2.micro"
subnet_id = "${element(tolist(data.aws_subnet_ids.private.ids), count.index)}"
}

This works for me. Thanks

Was this page helpful?
0 / 5 - 0 ratings