Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Terraform error `Inappropriate value for attribute "vpc_zone_identifier": element 0: string required.`

I'm running into this error:

Inappropriate value for attribute "vpc_zone_identifier": element 0: string required.

The variable should be list of strings so element 0 should be string.

Here is the code:

VPC module:

resource "aws_subnet" "terraform-pub-sn" {
  count                   = "${length(data.aws_availability_zones.all.names)}"
  vpc_id                  = "${aws_vpc.terraform-vpc.id}"
  cidr_block              = "${element(var.vpc_subnet_cidr, count.index)}"
   availability_zone       = "${data.aws_availability_zones.all.names[count.index]}"
    }

Output:

output "terraform_subnet_ids" {
  value = ["${aws_subnet.terraform-pub-sn.*.id}"]
} 

Main.tf:

module "auto_scaling_group" {
  source = "./modules/AutoScalingGroup"
  terraform_subnet_ids = ["${module.vpc.terraform_subnet_ids}"]
}

ASG module:

variable "terraform_subnet_ids"{}

resource "aws_autoscaling_group" "terraform-asg" {
  vpc_zone_identifier  = ["${var.terraform_subnet_ids}"]

  ...
}

I spent half a day trying to fix this not sure what else to try and how it is supposed to be defined. AFAIK adding [] will make the variable into a list of strings and when it selects element 0 and returns the error the element should technically be a string, so no idea what the problem is. Maybe there is a way to check what it is on the fly?

Full error is here:

Error: Incorrect attribute value type

  on modules\AutoScalingGroup\asg.tf line 43, in resource "aws_autoscaling_group" "terraform-asg":
  43:   vpc_zone_identifier  = ["${var.terraform_subnet_ids}"]

Inappropriate value for attribute "vpc_zone_identifier": element 0: string
required.
like image 852
robliv Avatar asked Dec 14 '22 09:12

robliv


1 Answers

One of your examples was as follows:

output "terraform_subnet_ids" {
  value = ["${aws_subnet.terraform-pub-sn.*.id}"]
}

This includes two operations: aws_subnet.terraform-pub-sn.*.id returns a list of ids, and then [ ... ] constructs a list from its contents. So this expression is constructing a list of lists, looking something like this:

[
  ["subnet-abc123", "subnet-123abc"]
]

In the moduleblock there is a similar expression:

  terraform_subnet_ids = ["${module.vpc.terraform_subnet_ids}"]

This also has [ ...], so it's adding another level of list:

[
  [
    ["subnet-abc123", "subnet-123abc"]
  ]
]

Finally when you refer to this in the autoscaling group configuration, we have one more [ ... ] expression:

  vpc_zone_identifier  = ["${var.terraform_subnet_ids}"]

So by the time this gets here, the value being assigned to this argument is:

[
  [
    [
      ["subnet-abc123", "subnet-123abc"]
    ]
  ]
]

Element zero of this list is a list of lists of lists of strings, so Terraform reports a type error.

With all of that said, I think the way to make this work as you intended is to remove the [ ... ] list construction brackets from all of these expressions:

output "terraform_subnet_ids" {
  # A list of subnet ids
  value = aws_subnet.terraform-pub-sn.*.id
}
module "auto_scaling_group" {
  source = "./modules/AutoScalingGroup"

  # still a list of subject ids
  terraform_subnet_ids = module.vpc.terraform_subnet_ids
}
variable "terraform_subnet_ids" {
  # Setting an explicit type for your variable can be helpful to
  # catch this sort of problem at the caller, rather than in
  # the usage below. I used set(string) rather than list(string)
  # here because vpc_zone_identifier is an unordered set of subnet
  # ids; list(string) would work too, since Terraform will convert
  # to a set just in time to assign to vpc_zone_identifier.
  type = set(string)
}

resource "aws_autoscaling_group" "terraform-asg" {
  # because of the type declaration above, this is now a set
  # of strings, which is the type this argument is expecting.
  vpc_zone_identifier  = var.terraform_subnet_ids
}
like image 91
Martin Atkins Avatar answered Jan 12 '23 00:01

Martin Atkins