Hi,
I use a list of objects as input for creating multiple vm’s using for each:
variable "servers" {
type = list(object({
name = string
}))
default = [
{
name = "tst-vm-01"
},
{
name = "tst-vm-02"
}
]
}
module "server" {
source = "../../modules/server_app/03"
for_each = {
for vm in var.servers:
vm.name => vm}
# Server specific
name = "${each.value.name}"
.....
}
output "Servers" {
value = {
for server in module.server : server.name => server.private_ip
}
}
This works fine and provides server name and private ip in the output.
The following variable is used creating backend sets on the loadblancer. I also want to use the same list for adding the vm’s created above to the loadbalancer backend:
variable "services" {
description = "Map of services"
type = list(object({
service = string
port = string
}))
default = [
{
service = "servicename-01",
port = "7000",
},
{
service = "servicename-02",
port = "7003",
}
]
}
How to get a list/map/something which I can loop to add the servers (with their internal ip) to the loadbalancer backend?
I tried to create a tuple, but van not get the internal_ip into that, only the name of the vm from it’s own list.
Any help is highly appreciated
Might be helpful to include the way you’re trying to use the resulting data structure?
What I usually do in cases like this is first figure out how the data should be structured, and then setup a self-contained tf file with just the starting point and an output with the data structure I want. That way, I can play around with different things quickly.
Because of Terraform’s weird pseudo-iteration, there is sometimes a lot of this necessary (wrangling from one data structure to another). Figuring out the structure you need is often half the battle.
I put an example of this here, just in case that helps.
Also, is your original data structure more complicated than in the example above? I would probably tend to just make a set of instance names vs. a list of objects, unless you’ve also got additional information stuffed in there besides name
?
Thanks for your reply and suggestion. Indeed, there is more information in the list of instances, but not related to this part.
After a lot of time trying and battling the code, I finally managed to get this working. Might not be the nicest setup, but at least it does what I need :-).
First I create a local producing the the required output (thanks for that tip):
locals {
# flatten ensures that this local is a flat list of objects, rather than a list of lists of objects.
servers_services = flatten([
for server in module.server : [
for service in var.services : {
server_name = server.name
server_ip = server.private_ip
service_name = service.name
service_port = service.port
}
]
])
}
After that a loop to process each record in the local variable:
resource "oci_network_load_balancer_backend" "Backend" {
for_each = {for i,v in local.servers_services: i=>v}
backend_set_name = "${each.value.service_name}"
network_load_balancer_id = oci_network_load_balancer_network_load_balancer.services.id
ip_address = each.value.server_ip
port = each.value.service_port
name = "${each.value.server_name}_${each.value.service_port}"
}