WaltDe
WaltDe

Reputation: 1832

terraform count dependent on data from target environment

I'm getting the following error when trying to initially plan or apply a resource that is using the data values from the AWS environment to a count.

$ terraform plan 
Refreshing Terraform state in-memory prior to plan...
The refreshed state will be used to calculate this plan, but will not be
persisted to local or remote state storage.


------------------------------------------------------------------------

Error: Invalid count argument

  on main.tf line 24, in resource "aws_efs_mount_target" "target":
  24:   count = length(data.aws_subnet_ids.subnets.ids)

The "count" value depends on resource attributes that cannot be determined
until apply, so Terraform cannot predict how many instances will be created.
To work around this, use the -target argument to first apply only the
resources that the count depends on.

$ terraform --version
Terraform v0.12.9
+ provider.aws v2.30.0

I tried using the target option but doesn't seem to work on data type.

$ terraform apply -target aws_subnet_ids.subnets

Apply complete! Resources: 0 added, 0 changed, 0 destroyed.

The only solution I found that works is:

  1. remove the resource
  2. apply the project
  3. add the resource back
  4. apply again

Here is a terraform config I created for testing.

provider "aws" {
  version = "~> 2.0"
}

locals {
  project_id = "it_broke_like_3_collar_watch"
}

terraform {
  required_version = ">= 0.12"
}

resource aws_default_vpc default {
}

data aws_subnet_ids subnets {
  vpc_id = aws_default_vpc.default.id
}

resource aws_efs_file_system efs {
  creation_token = local.project_id
  encrypted = true
}

resource aws_efs_mount_target target {
  depends_on = [ aws_efs_file_system.efs ]
  count = length(data.aws_subnet_ids.subnets.ids)
  file_system_id = aws_efs_file_system.efs.id
  subnet_id = tolist(data.aws_subnet_ids.subnets.ids)[count.index]
}

Upvotes: 3

Views: 4162

Answers (2)

WaltDe
WaltDe

Reputation: 1832

Finally figured out the answer after researching the answer by Dude0001.

Short Answer. Use the aws_vpc data source with the default argument instead of the aws_default_vpc resource. Here is the working sample with comments on the changes.

locals {
  project_id = "it_broke_like_3_collar_watch"
}

terraform {
  required_version = ">= 0.12"
}

// Delete this --> resource aws_default_vpc default {}

// Add this
data aws_vpc default {
  default = true
}


data "aws_subnet_ids" "subnets" {
// Update this from aws_default_vpc.default.id 
  vpc_id = "${data.aws_vpc.default.id}"
}

resource aws_efs_file_system efs {
  creation_token = local.project_id
  encrypted = true
}

resource aws_efs_mount_target target {
  depends_on = [ aws_efs_file_system.efs ]
  count = length(data.aws_subnet_ids.subnets.ids)
  file_system_id = aws_efs_file_system.efs.id
  subnet_id = tolist(data.aws_subnet_ids.subnets.ids)[count.index]
}

What I couldn't figure out was why my work around of removing aws_efs_mount_target on the first apply worked. It's because after the first apply the aws_default_vpc was loaded into the state file.

So an alternate solution without making change to the original tf file would be to use the target option on the first apply:

$ terraform apply  --target aws_default_vpc.default

However, I don't like this as it requires a special case on first deployment which is pretty unique for the terraform deployments I've worked with.

Upvotes: 2

Dude0001
Dude0001

Reputation: 3450

The aws_default_vpc isn't a resource TF can create or destroy. It is the default VPC for your account in each region that AWS creates automatically for you that is protected from being destroyed. You can only (and need to) adopt it in to management and your TF state. This will allow you to begin managing and to inspect when you run plan or apply. Otherwise, TF doesn't know what the resource is or what state it is in, and it cannot create a new one for you as it s a special type of protected resource as described above.

With that said, go get the default VPC id from the correct region you are deploying in your account. Then import it into your TF state. It should then be able to inspect and count the number of subnets.

For example

terraform import aws_default_vpc.default vpc-xxxxxx

https://www.terraform.io/docs/providers/aws/r/default_vpc.html

Using the data element for this looks a little odd to me as well. Can you change your TF script to get the count directly through the aws_default_vpc resource?

Upvotes: 0

Related Questions