HiveBrain v1.2.0
Get Started
← Back to all entries
debugterraformMinor

Terraform | Upgrade to 0.12 error Reference to "count" in non-counted context

Submitted by: @import:stackexchange-devops··
0
Viewed 0 times
referenceerrornoncountedcontextcountupgradeterraform

Problem

I'm trying to upgrade terraform from 0.11 to 0.12 but receiving error:

Error: Reference to "count" in non-counted context

  on main.tf line 33, in data "aws_subnet" "public":
  33:   id = data.aws_subnet_ids.public.ids[count.index]

The "count" object can be used only in "resource" and "data" blocks, and only
when the "count" argument is set.


Here is my part of code:

data "aws_subnet_ids" "public" {
  vpc_id = data.aws_vpc.vpc.id

  tags = {
    Tier = "public"
  }
}

data "aws_subnet" "public" {  
  id = data.aws_subnet_ids.public.ids[count.index]
}


Maybe someone know how to fix this error?
Thanks in advance.

Solution

It looks like your underlying goal here is to retrieve the full set of attributes for each of your subnets that are marked as Tier = public. Here's a different way to do that using features from Terraform 0.12.6:

data "aws_subnet_ids" "public" {
  vpc_id = data.aws_vpc.vpc.id

  tags = {
    Tier = "public"
  }
}

data "aws_subnet" "public" {  
  for_each = data.aws_subnet_ids.public.ids

  id = each.value
}


With the above, you should find that data.aws_subnet.public is a map from subnet id to the attributes of that particular subnet.

The reason for the error in your case is that you used count.index but didn't set the count argument, and so there is no count index to return.

The count-based equivalent of the above, which is more similar to your original example, would be this:

data "aws_subnet_ids" "public" {
  vpc_id = data.aws_vpc.vpc.id

  tags = {
    Tier = "public"
  }
}

data "aws_subnet" "public" {  
  count = length(data.aws_subnet_ids.public.ids)

  id = sort(data.aws_subnet_ids.public.ids)[count.index]
}


The result of this is very similar to the for_each-based example I gave above, but with one significant difference: in this case data.aws_subnet.public will be a list of subnet objects, ordered by the lexical ordering of their subnet ids. That will usually make the result harder to use elsewhere in the configuration, so I'd suggest using the for_each approach unless there's a specific reason why you need a list.

(If you use a map and then later find that you need a list in a specific context, you can always use values(data.aws_subnet.public) to take the values from the map, in the same lexical order.)

Code Snippets

data "aws_subnet_ids" "public" {
  vpc_id = data.aws_vpc.vpc.id

  tags = {
    Tier = "public"
  }
}

data "aws_subnet" "public" {  
  for_each = data.aws_subnet_ids.public.ids

  id = each.value
}
data "aws_subnet_ids" "public" {
  vpc_id = data.aws_vpc.vpc.id

  tags = {
    Tier = "public"
  }
}

data "aws_subnet" "public" {  
  count = length(data.aws_subnet_ids.public.ids)

  id = sort(data.aws_subnet_ids.public.ids)[count.index]
}

Context

StackExchange DevOps Q#8937, answer score: 1

Revisions (0)

No revisions yet.