Terraform tuple to map conversion
You have 3 forms, to make the loop.
1º Using dynamic block
... Example:
resource "aws_security_group" "ecc_default" {
count = length(var.clusters)
vpc_id = var.vpc_id
name = "${terraform.workspace}.ecc-${var.clusters[count.index].engine}.sg"
description = "${terraform.workspace}.ecc-${var.clusters[count.index].engine}.sg"
ingress {
from_port = var.clusters[count.index].port
to_port = var.clusters[count.index].port
protocol = "tcp"
cidr_blocks = [var.vpc_cidr]
}
dynamic "ingress" {
iterator = item
for_each = var.enable_vpn ? var.vpn_cidr : []
content {
from_port = var.clusters[count.index].port
to_port = var.clusters[count.index].port
protocol = "tcp"
cidr_blocks = [item.value["cidr"]]
description = item.value["description"]
}
}
...
...
}
2º Using for_each
... (click here for answer)
3º Using arithmetic iteration... (click here for answer) Example:
resource "aws_security_group_rule" "ecc_internal" {
count = length(var.ingress_security_groups) > 0 ? length(var.ingress_security_groups) * length(var.clusters) : 0
security_group_id = aws_security_group.ecc_default[count.index % length(var.clusters)].id
type = "ingress"
from_port = var.clusters[count.index % length(var.clusters)].port
to_port = var.clusters[count.index % length(var.clusters)].port
protocol = "tcp"
source_security_group_id = var.ingress_security_groups[floor(count.index / length(var.clusters))]
}
And, for the error on convert: try to use coalescelist
with fake replacement. Like this:
resource "aws_lb_listener_certificate" "default" {
count = (coalescelist(data.aws_alb_listener.https, [{ certificate_arn = "" }])[0].certificate_arn != var.certificate_arn) ? local.enabled : 0
listener_arn = coalescelist(data.aws_alb_listener.https, [{ arn = "" }])[count.index].arn
certificate_arn = var.certificate_arn
}
The conversion of a tuple ([N1, N2, N3]
) to a map ({N1 = "", N2 = ""}
), is really not allowed. But, you can use a fake replacement to make the job. tomap
needs an object for argument. And map
, needs multiple args to make the result. Try to manipulate your list, to convert in map, with another form like this (if you want just convert, and not solve the problem):
environment_vars = jsonencode([
for key in sort(keys(data.external.environment_vars.result)) : {
name = key
value = lookup(data.external.environment_vars.result, key)
}])
I recommend for you: Terraform tips & tricks: loops, if-statements, and gotchas
Murat
Updated on June 04, 2022Comments
-
Murat almost 2 years
I am pretty new to Terraform and I am using this function to re-use same list of subnets to launch more instances than subnets I have. (It'll just loop over) This works great if I provide my own map of subnets but the data in the remote state is a tuple and I get this error:
Invalid value for "inputMap" parameter: lookup() requires a map as the first argument. data.terraform_remote_state.vpc.outputs.private_subnets is tuple with 4 elements
I have also tried the tomap( function but this fails with:
Invalid value for "v" parameter: cannot convert tuple to map of any single type.
Here is my code:
count = var.instance_count ami = var.ami instance_type = "t2.medium" subnet_id = lookup(data.terraform_remote_state.vpc.outputs.private_subnets, count.index%length(data.terraform_remote_state.vpc.outputs.private_subnets)) vpc_security_group_ids = ["${data.terraform_remote_state.foo_sg.outputs.foo_sg_id}"] key_name = var.key_name iam_instance_profile = var.iam_instance_profile user_data = <<-EOF #!/bin/bash hostnamectl set-hostname --static "${var.app_name}-${count.index + 1}.${data.terraform_remote_state.vpc.outputs.private_zone_domain_name}" echo "127.0.0.1 localhost.localdomain localhost4 localhost4.localdomain4 ${var.app_name}-${count.index + 1}.${data.terraform_remote_state.vpc.outputs.private_zone_domain_name} localhost" > hosts echo "::1 localhost localhost.localdomain localhost6 localhost6.localdomain6" >> hosts EOF tags = { Name = "${var.app_name}-${count.index +1}.${data.terraform_remote_state.vpc.outputs.private_zone_domain_name}" }
Like I said my goal is to re-use the 4 subnets in that remote state I have, so if I want 6 instances it would loop through the 4 I have and the 5th and 6th instance would be on subnet 1 and 2 in the Tuple. Any suggestions would be appreciated!