Funzione setproduct Terraform con più di due elenchi
Come utilizzare la funzione terraform setproduct con più di 2 elenchi nello scenario seguente o esiste un altro modo per ottenere il risultato finale.
Nel file main.tf ho i seguenti dati.
$ cat main.tf
variable "nodes" {
default = ["1", "2", "3"]
}
variable "ebs_volumes" {
default = [
{
ebs_name = "/dev/xdba"
ebs_size = "50"
ebs_type = "gp2"
},
{
ebs_name = "/dev/xdbb"
ebs_size = "20"
ebs_type = "gp2"
}
]
}
locals {
ebs_name = [for i in var.ebs_volumes : i.ebs_name]
ebs_size = [for i in var.ebs_volumes : i.ebs_size]
ebs_type = [for i in var.ebs_volumes : i.ebs_type]
}
locals {
node_disks = { for pair in setproduct(var.nodes, local.ebs_name) : "${pair[0]}:${pair[1]}" => {
node_index = pair[0]
ebs_name = pair[1]
ebs_size = [for i in var.ebs_volumes : i.ebs_size]
ebs_type = [for i in var.ebs_volumes : i.ebs_type]
} }
}
output "combined" {
value = local.node_disks
}
Quando eseguo terraform apply ottengo il seguente risultato
$ terraform apply
Apply complete! Resources: 0 added, 0 changed, 0 destroyed.
Outputs:
combined = {
"1:/dev/xdba" = {
"ebs_name" = "/dev/xdba"
"ebs_size" = [
"50",
"20",
]
"ebs_type" = [
"gp2",
"gp2",
]
"node_index" = "1"
}
"1:/dev/xdbb" = {
"ebs_name" = "/dev/xdbb"
"ebs_size" = [
"50",
"20",
]
"ebs_type" = [
"gp2",
"gp2",
]
"node_index" = "1"
}
"2:/dev/xdba" = {
"ebs_name" = "/dev/xdba"
"ebs_size" = [
"50",
"20",
]
"ebs_type" = [
"gp2",
"gp2",
]
"node_index" = "2"
}
"2:/dev/xdbb" = {
"ebs_name" = "/dev/xdbb"
"ebs_size" = [
"50",
"20",
]
"ebs_type" = [
"gp2",
"gp2",
]
"node_index" = "2"
}
"3:/dev/xdba" = {
"ebs_name" = "/dev/xdba"
"ebs_size" = [
"50",
"20",
]
"ebs_type" = [
"gp2",
"gp2",
]
"node_index" = "3"
}
"3:/dev/xdbb" = {
"ebs_name" = "/dev/xdbb"
"ebs_size" = [
"50",
"20",
]
"ebs_type" = [
"gp2",
"gp2",
]
"node_index" = "3"
}
}
Invece voglio essere in grado di avere il risultato come mostrato di seguito (psudo codice):
combined = {
"1:/dev/xvdb" = {
"disk_dev_path" = "/dev/xvda"
"node_name" = "1"
"disk_size" = "10"
"disk_type" = "gp2"
}
"1:/dev/xvdc" = {
"disk_dev_path" = "/dev/xvdb"
"node_name" = "1"
"disk_size" = "30"
"disk_type" = "gp2"
}
"2:/dev/xvdb" = {
"disk_dev_path" = "/dev/xvda"
"node_name" = "2"
"disk_size" = "10"
"disk_type" = "gp2"
}
"2:/dev/xvdc" = {
"disk_dev_path" = "/dev/xvdb"
"node_name" = "2"
"disk_size" = "30"
"disk_type" = "gp2"
}
"3:/dev/xvdb" = {
"disk_dev_path" = "/dev/xvda"
"node_name" = "3"
"disk_size" = "10"
"disk_type" = "gp2"
}
"3:/dev/xvdc" = {
"disk_dev_path" = "/dev/xvdb"
"node_name" = "3"
"disk_size" = "30"
"disk_type" = "gp2"
}
}
Come raggiungere questo obiettivo?
Ne ho bisogno per usarlo in for_each per creare istanze ec2 e volumi ebs e collegarli rispettivamente ogni volta che l'utente aggiunge un input nella variabile usando il nostro modulo ec2.
Risposte
Se puoi, forse potresti usare un doppio ciclo for per flatten
quello. Mi sembra più naturale.
Di seguito è riportato un esempio funzionante :
variable "nodes" {
default = ["1", "2", "3"]
}
variable "ebs_volumes" {
default = [
{
ebs_name = "/dev/xdba"
ebs_size = "50"
ebs_type = "gp2"
},
{
ebs_name = "/dev/xdbb"
ebs_size = "20"
ebs_type = "gp2"
}
]
}
locals {
node_disks2 = {for idx, value in flatten([for node in var.nodes:
[for volume in var.ebs_volumes:
{
node_index = node
ebs_name = volume.ebs_name
ebs_size = volume.ebs_size
ebs_type = volume.ebs_type
}]
]): idx => value}
}
output "combined" {
value = local.node_disks2
}
Produzione:
ombined = {
"0" = {
"ebs_name" = "/dev/xdba"
"ebs_size" = "50"
"ebs_type" = "gp2"
"node_index" = "1"
}
"1" = {
"ebs_name" = "/dev/xdbb"
"ebs_size" = "20"
"ebs_type" = "gp2"
"node_index" = "1"
}
"2" = {
"ebs_name" = "/dev/xdba"
"ebs_size" = "50"
"ebs_type" = "gp2"
"node_index" = "2"
}
"3" = {
"ebs_name" = "/dev/xdbb"
"ebs_size" = "20"
"ebs_type" = "gp2"
"node_index" = "2"
}
"4" = {
"ebs_name" = "/dev/xdba"
"ebs_size" = "50"
"ebs_type" = "gp2"
"node_index" = "3"
}
"5" = {
"ebs_name" = "/dev/xdbb"
"ebs_size" = "20"
"ebs_type" = "gp2"
"node_index" = "3"
}
}