I’ve attempted to get this working many, many different ways but keep falling short with the implementations. I need to grab a list of server names from a map and get the product of that list and another list of ports in order to iterate over each grouping into a bigip_ltm_pool_attachment resource block:
node = {
"node1" = "192.168.1.1"
"node2" = "192.168.1.2"
}
ports = [7001,7002,7003,7004,7005,7006,7007,7008,7009,7010]
poolattachports = [for pair in setproduct(keys(local.node), local.ports): {host: pair[0], port: pair[1]}]
resource "bigip_ltm_pool_attachment" "pool_attach" {
for_each = ...
}
The high level idea is to create an attachment for each possible combination of server/port. I’ve never really seen an example online for this where you start with 2 lists and create a data structure that can be for_each’d in a resource. The only way I’ve seen it done is with dynamic blocks and I don’t think they apply here, right?
Hi @rleonetti,
The main thing about for_each
is to produce a data structure that has one element for each instance you want to create and each element contains enough information to populate the resource configuration.
Your poolattachports
expression here seems to meet that requirement. I’m not really familiar with the bigip
provider but based on a quick read of the documentation I think the following would work:
locals {
nodes = {
"node1" = "192.168.1.1"
"node2" = "192.168.1.2"
}
ports = [7001,7002,7003,7004,7005,7006,7007,7008,7009,7010]
}
resource "bigip_ltm_node" "example" {
for_each = local.nodes
name = "/Common/${each.key}"
address = each.value
}
locals {
node_ports = [for pair in setproduct(keys(bigip_ltm_node.example), local.ports): {host: pair[0], port: pair[1]}]
}
resource "bigip_ltm_pool_attachment" "attach_node" {
for_each = { for np in local.node_ports : "${np.host}:${np.port}" => np }
pool = bigip_ltm_pool.example.name
node = each.key
}
The local.node_ports
above is essentially the same as your poolattachports
except that it refers to bigip_ltm_node.example
instead of directly to local.nodes; that tells Terraform that the bigip_ltm_pool_attachment
resource depends (indirectly) on the bigip_ltm_node
resource, so the pool attachments won’t be created until both the nodes and pool (not shown) have been created.
It looks like the node
argument of bigip_ltm_pool_attachment
expects a node:port
string, and Terraform also requires a unique string to identify each of the instances so I wrote this to use the same string for both purposes, which causes it to appear as each.key
inside the resource block. Terraform will therefore understand these instances as having addresses like this:
bigip_ltm_pool_attachment.attach_node["node1:7001"]
bigip_ltm_pool_attachment.attach_node["node1:7002"]
- …
bigip_ltm_pool_attachment.attach_node["node2:7001"]
bigip_ltm_pool_attachment.attach_node["node2:7002"]
- …
1 Like
Thank you! The only change I made was:
node = "${bigip_ltm_node.node[each.value["host"]].name}:${each.value["port"]}"
I’m so relieved to have this working lol