'How to access variables in a list / object in Terraform?
In Terraform, how can access the values from the variable below?
variable "egress_rules" {
type = list(object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
default = [
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
]
}
I tried:
resource "aws_security_group_rule" "egress" {
security_group_id = aws_security_group.new.id
type = "ingress"
for_each = var.egress_rules
from_port = each.value.from_port
to_port = each.value.from_port
protocol = each.value.protocol
cidr_blocks = each.value.cidr_blocks
}
But got this error:
Error: Invalid for_each argument
What is the correct way to reference this variable?
Solution 1:[1]
for_each will not work with a list of maps. You have to convert it to a map. This is commonly done through a for expression:
resource "aws_security_group_rule" "egress" {
security_group_id = aws_security_group.new.id
type = "ingress"
for_each = { for idx, rule in var.egress_rules: idx => rule }
from_port = each.value.from_port
to_port = each.value.from_port
protocol = each.value.protocol
cidr_blocks = each.value.cidr_blocks
}
Solution 2:[2]
to set multiple properties of a resource you could use a map of objects like this:
variable "egress_rules" {
type = map(object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
}))
}
Your variable definition would be:
egress_rules = {
{
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}
}
The updated resource definition would be:
resource "aws_security_group_rule" "egress" {
security_group_id = aws_security_group.new.id
type = "egress"
for_each = var.egress_rules
from_port = each.value["from_port"]
to_port = each.value["to_port"]
protocol = each.valuep["protocol"]
cidr_blocks = each.value["cidr_blocks"]
}
Solution 3:[3]
Adding to above answer from @Marcin
If you want to use single object instead of list then you can directly access without for_each
Instead of declaring it as list of objects; use single object as shown below
variable "egress_rules" {
type = object({
from_port = number
to_port = number
protocol = string
cidr_blocks = list(string)
})
default = ({
from_port = 0
to_port = 0
protocol = "-1"
cidr_blocks = ["0.0.0.0/0"]
}}
}
Then access in your resource like
resource "aws_security_group_rule" "egress" {
security_group_id = aws_security_group.new.id
from_port = var.egress_rules.from_port
to_port = var.egress_rules.from_port
protocol = var.egress_rules.protocol
cidr_blocks = var.egress_rules.cidr_blocks
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
Solution | Source |
---|---|
Solution 1 | Marcin |
Solution 2 | |
Solution 3 |