Reputation: 11
I am struggling a bit here and am wondering if it would be even possible. I have a vars decalred as shown below:
variable "subnets" {
type = list(object({
name = string
cidr_block = string
}))
default = [
{
name = private
cidr_block = 10.0.0.1/24
},
{
name = public
cidr_block = 10.0.0.2/24
}
]
}
and then I use a data source to query zones in the current region
data aws_availability_zones available {}
now what I'm trying to do is create the above subnets in each az zone and I don't seem able to combine the zones to the above var.
what I am trying is
resource aws_suubnet subnet {
for each = {for idx,az.name in data.aws_availability_zones.available.names : idx => az.name}
vpc_id = var.vpc_id
availability_zone = data.aws_availability_zones.available.names[each.key]
cidr_block = (this is where I want to query my var.subnets but I don't seem to be able to do another for
here)
}
What I am hoping to end up with is 6 subnets 3 private and 3 public with one of each in each of the zones. Would appreciate any help here. Thanks
Upvotes: 1
Views: 217
Reputation: 74219
I think your intent here is to dynamically select two of the available availability zones and declare a subnet in each.
This is possible to do and I will show a configuration example below but first I want to caution that this a potentially-risky design because the set of availability zones can vary over time, and so you might find that without any direct changes to your configuration a later Terraform plan proposes to recreate one or both of your subnets in different availability zones.
For that reason, I'd typically suggest making the assignment of subnets to availability zones something you intentionally choose and encode statically in your configuration, rather than selecting them dynamically, to ensure that your configuration's effect remains stable over time unless you intentionally change it.
With that caveat out of the way, I do still want to answer the general question here, because this general idea of "zipping together" two collections of different lengths can arise in other situations, and so knowing a pattern for it might still prove useful, including if you ultimately decide to make the list of availability zones a variable rather than a data source lookup.
variable "subnets" {
type = list(object({
name = string
cidr_block = string
}))
}
data "aws_availability_zones" "available" {
}
locals {
# The availability zones are returned as an unordered
# set, so we'll sort them to be explicit that we're
# depending on one particular ordering.
zone_names = sort(data.aws_availabililty_zones.available.names)
subnets = tolist([
for i, sn in var.subnets : {
name = sn.name
cidr_block = sn.cidr_block
zone = element(local.zone_names, i)
}
])
}
The last expression in the above example relies on the element
function, which is similar to indexing like local.zone_names[i]
but instead of returning an error if i
is too large it will instead wrap around and reselect the same items from the zone list again.
Upvotes: 2