Reputation: 457
I want to reserve an IP and then use it. If I create a separate google_compute_address
block for each IP, it works well. But since I want to make the code as dry and optimized as possible, I am learning how to loop and use for_each
My main.tf looks like this
module "nat" {
source = "../../modules/nat"
reserved_ips = [
{
name = "gke-frontend-prod-lb"
ip = "10.238.232.10"
},
{
name = "gke-frontend-test-lb"
ip = "10.238.232.11"
}
]
}
As you can see, I would like to form a list of reserved IPs having name and IP.
Now lets look at my module
My variables.tf looks like
variable "reserved_ips" {
type = list(object({
name = string
ip = string
}))
description = <<EOF
Reserved IPs.
EOF
}
And the main.tf of my module looks like
locals {
ips = {
# for_each needs transform to map
for ip in var.reserved_ips : "${ip.name}" => "${ip.ip}"
}
}
resource "google_compute_address" "gke-frontend" {
for_each = local.ips
name = "${each.value.name}"
subnetwork = "mysubnet"
address_type = "INTERNAL"
address = "${each.value.ip}"
}
But running the code gives me
Error: Unsupported attribute
on ../../modules/nat/main.tf line 11, in resource "google_compute_address" "gke-frontend":
11: name = "${each.value.name}"
|----------------
| each.value is "10.238.232.10"
This value does not have any attributes.
Error: Unsupported attribute
on ../../modules/nat/main.tf line 11, in resource "google_compute_address" "gke-frontend":
11: name = "${each.value.name}"
|----------------
| each.value is "10.238.232.11"
This value does not have any attributes.
Error: Unsupported attribute
on ../../modules/nat/main.tf line 14, in resource "google_compute_address" "gke-frontend":
14: address = "${each.value.ip}"
|----------------
| each.value is "10.238.232.10"
This value does not have any attributes.
Error: Unsupported attribute
on ../../modules/nat/main.tf line 14, in resource "google_compute_address" "gke-frontend":
14: address = "${each.value.ip}"
|----------------
| each.value is "10.238.232.11"
This value does not have any attributes.
Im confused as to what am I missing here exactly.
Upvotes: 0
Views: 715
Reputation: 8937
The issue is that your ips
local converts the list to a map(string)
(i.e. a map with string values)
locals {
ips = {
# for_each needs transform to map
for ip in var.reserved_ips : "${ip.name}" => "${ip.ip}"
}
}
Notice that on the right-side of =>
you have "${ip.ip}"
.
When for_each
loops over a map
it assigns each.key
to each key (a string
) and each.value
to each corresponding value in the map (in this case "${ip.ip}
is also a string
).
So, I think what you want in this case is something like the following
# ...
name = each.key
# ...
address = each.value
# ...
Upvotes: 2