0
votes

terraform version 0.11.13

Error: Error refreshing state: 1 error(s) occurred:

  • data.aws_subnet.private_subnet: data.aws_subnet.private_subnet: value of 'count' cannot be computed

VPC code generated the error above:

resources.tf
data "aws_subnet_ids" "private_subnet_ids" {
  vpc_id            = "${module.vpc.vpc_id}"
}
data "aws_subnet" "private_subnet" {
  count = "${length(data.aws_subnet_ids.private_subnet_ids.ids)}"
  #count = "${length(var.private-subnet-mapping)}"
  id    = "${data.aws_subnet_ids.private_subnet_ids.ids[count.index]}"
}

Change the above code to use count = "${length(var.private-subnet-mapping)}", I successfully provisioned the VPC. But, the output of vpc_private_subnets_ids is empty. vpc_private_subnets_ids = []

Code provisioned VPC, but got empty list of vpc_private_subnets_ids:

resources.tf

data "aws_subnet_ids" "private_subnet_ids" {
  vpc_id            = "${module.vpc.vpc_id}"
}
data "aws_subnet" "private_subnet" {
  #count = "${length(data.aws_subnet_ids.private_subnet_ids.ids)}"
  count = "${length(var.private-subnet-mapping)}"
  id    = "${data.aws_subnet_ids.private_subnet_ids.ids[count.index]}"
}

outputs.tf
output "vpc_private_subnets_ids" {
  value = ["${data.aws_subnet.private_subnet.*.id}"]
}

The output of vpc_private_subnets_ids:
vpc_private_subnets_ids = []

I need the values of vpc_private_subnets_ids. After successfully provisioned VPC use the line, count = "${length(var.private-subnet-mapping)}", I changed code back to count = "${length(data.aws_subnet_ids.private_subnet_ids.ids)}". terraform apply, I got values of the list vpc_private_subnets_ids without above error.

vpc_private_subnets_ids = [
    subnet-03199b39c60111111,
    subnet-068a3a3e76de66666,
    subnet-04b86aa9dbf333333,
    subnet-02e1d8baa8c222222
    ......
]

I cannot use count = "${length(data.aws_subnet_ids.private_subnet_ids.ids)}" when I provision VPC. But, I can use it after VPC provisioned. Any clue?

1
Do you absolutely need a 0.11 compatible answer? 0.12 was released more than 15 months ago and is now on 0.13. 0.11 is already deprecated by the latest AWS provider (v3) so you should really avoid hanging around on this version if you can avoid it. If so you should explain that you cannot move to 0.12 and tag your question with terraform0.11. - ydaetskcoR
Why do you data to get your private_subnet_ids, if they are returned from your vpc module? There is probably some race condition happening the way you do it. You execute data but the subnets are not yet created or in the process of being created. - Marcin
I need to output subnet ids of VPC. Is there a better way to do it? - Melissa Jenner

1 Answers

0
votes

The problem here seems to be that your VPC isn't created yet and so the data "aws_subnet_ids" "private_subnet_ids" data source read must wait until the apply step, which in turn means that the number of subnets isn't known, and thus the number of data "aws_subnet" "private_subnet" instances isn't predictable and Terraform returns this error.

If this configuration is also the one responsible for creating those subnets then the better design would be to refer to the subnet objects directly. If your module.vpc is also the module creating the subnets then I would suggest to export the subnet ids as an output from that module. For example:

output "subnet_ids" {
  value = "${aws_subnet.example.*.id}"
}

Your calling module can then just get those ids directly from module.vpc.subnet_ids, without the need for a redundant extra API call to look them up:

output "vpc_private_subnets_ids" {
  value = ["${module.vpc.subnet_ids}"]
}

Aside from the error about count, the configuration you showed also has a race condition because the data "aws_subnet_ids" "private_subnet_ids" block depends only on the VPC itself, and not on the individual VPCs, and so Terraform can potentially read that data source before the subnets have been created. Exporting the subnet ids through module output means that any reference to module.vpc.subnet_ids indirectly depends on all of the subnets and so those downstream actions will wait until all of the subnets have been created.

As a general rule, a particular Terraform configuration should either be managing an object or reading that object via a data source, and not both together. If you do both together then it may sometimes work but it's easy to inadvertently introduce race conditions like this, where Terraform can't tell that the data resource is attempting to consume the result of another resource block that's participating in the same plan.