I am kind of new to Terraform and could you help me with the lists in terraform.
This is my code
variable "ip_bitbucket" {
type = "list"
}
ip_bitbucket = ["34.199.54.113/32","34.232.25.90/32","34.232.119.183/32","34.236.25.177/32","35.171.175.212/32","52.54.90.98/32","52.202.195.162/32","52.203.14.55/32","52.204.96.37/32","34.218.156.209/32","34.218.168.212/32","52.41.219.63/32","35.155.178.254/32","35.160.177.10/32","34.216.18.129/32","3.216.235.48/32","34.231.96.243/32","44.199.3.254/32","174.129.205.191/32","44.199.127.226/32","44.199.45.64/32","3.221.151.112/32","52.205.184.192/32","52.72.137.240/32"]
and need to access the list as below
resource "aws_security_group_rule "server_rule" {
type = "ingress"
from_port = 443
to_port = 22
protocol = "tcp"
# for each = var.ip_bitbucket
cidr_blocks =
security_group_id = data.aws_security_group.server_sg.id
}
How do i access the variable ip_bitbucket
in cidr block?
I was trying with count
and element
but not getting clear idea
CodePudding user response:
You can use toset
built-in function [1] for that:
resource "aws_security_group_rule "server_rule" {
for_each = toset(var.ip_bitbucket)
type = "ingress"
from_port = 443
to_port = 22
protocol = "tcp"
cidr_blocks = each.value
security_group_id = data.aws_security_group.server_sg.id
}
[1] https://developer.hashicorp.com/terraform/language/functions/toset
CodePudding user response:
The for_each
argument requires either a map value (with any element type) or a set of strings. Your input variable is currently declared as being a list, and so it isn't directly compatible with for_each
.
It seems like the order of the elements in ip_bitbucket
has no significance and so I think the best answer would be to change the type constraint of that variable to be set(string)
, which is a more accurate description of how you will use that value:
variable "ip_bitbucket" {
type = set(string)
}
However, you can specify more than one CIDR block in a single security group rule so you may not actually need for_each
at all here:
resource "aws_security_group_rule" "server_rule" {
type = "ingress"
from_port = 443
to_port = 22
protocol = "tcp"
cidr_blocks = var.ip_bitbucket
security_group_id = data.aws_security_group.server_sg.id
}
The above will declare a single rule which applies to all of the given CIDR ranges.
If you do still want to use for_each
then you can use var.ip_bitbucket
as the for_each
value once you've changed its type constraint as described above:
resource "aws_security_group_rule" "server_rule" {
for_each = var.ip_bitbucket
type = "ingress"
from_port = 443
to_port = 22
protocol = "tcp"
cidr_blocks = [each.value]
security_group_id = data.aws_security_group.server_sg.id
}
Noice that each.value
needs to be in brackets here because each.value
is just a single element from var.ip_bitbucket
, and so it's a single string. cidr_blocks
expects a set of strings.
If some other part of your module that you've not shown here does rely on the specific ordering of the elements in var.ip_bitbucket
then you could leave it declared as a list and then convert it to a set inside the for_each
argument. However, I would recommend this only if you really do need to preserve the order of these elements, because users or future maintainers of your module may assume that the ordering is important if you declare it as a list.
variable "ip_bitbucket" {
type = list(string)
}
resource "aws_security_group_rule" "server_rule" {
for_each = toset(var.ip_bitbucket)
type = "ingress"
from_port = 443
to_port = 22
protocol = "tcp"
cidr_blocks = [each.value]
security_group_id = data.aws_security_group.server_sg.id
}
This is the same as the previous example except that the conversion from list to set happens explicitly with the toset
function, rather than automatically as Terraform prepares the value of var.ip_bitbucket
.