Bản đồ nhiều cấp Terraform
Tôi đang gặp lỗi trên "sơ đồ địa hình" khi cố gắng sử dụng bản đồ nhiều cấp (3+ cấp) và dường như không thể giải quyết vấn đề chính xác. Lỗi: "Giá trị đã cho không hợp lệ cho biến" secgroups ": phần tử" bastion ": thuộc tính" hướng "là bắt buộc." Các biến.tf của tôi có đúng khi được ánh xạ tới secgroups.auto.tf không? port_min và port_max sẽ là danh sách bao gồm tất cả các cổng để mở cho tên nhóm bảo mật.
Các phiên bản:
Terraform v0.13.0
+ provider registry.terraform.io/hashicorp/local v1.4.0
+ provider registry.terraform.io/hashicorp/null v2.1.2
+ provider registry.terraform.io/hashicorp/tls v2.2.0
+ provider registry.terraform.io/terraform-providers/openstack v1.26.0
biến.tf
variable "secgroups" {
type = map(object({
direction = (map(object({
protocols = (map(object({
name = string
description = string
ports_min = list(number)
ports_max = list(number)
remote_ip_prefix = list(string)
remote_group_id = list(string)
security_group_id = list(string)
})))
})))
}))
}
secgroups.auto.tfvars (chỉ là một đoạn mã)
ssh_from_bastion = {
ingress = {
tcp = {
ports_min = [22]
ports_max = [22]
remote_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
},
udp = {
ports_min = [0]
ports_max = [0]
remote_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
}
},
egress = {
tcp = {
ports_min = [0]
ports_max = [0]
remote_ip_prefix = ["0.0.0.0/0"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
},
udp = {
ports_min = [0]
ports_max = [0]
remote_ip_prefix = ["0.0.0.0/0"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
}
}
},
Main.tf
locals {
security_groups = flatten({
for secgroup_name,direction in var.secgroups : {
name = each.secgroup_name
description = "Security group for ${each.secgroup_name}"
for protocol,config in each.direction : {
direction = each.direction
protocol = each.protocol
for config_value in config : {
ports_min = each.config_value.ports_min
ports_max = each.config_value.ports_max
remote_ip_prefix = each.config_value.remote_ip_prefix
security_group_id = each.config_value.security_group_id
}
}
}
})
}
Trả lời
Có một số vấn đề với định nghĩa của bạn.
Giả sử rằng đầy đủ của bạn secgroups.auto.tfvarslà:
secgroups = {
ssh_from_bastion = {
ingress = {
tcp = {
ports_min = [22]
ports_max = [22]
remote_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
},
udp = {
ports_min = [0]
ports_max = [0]
remote_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
}
},
egress = {
tcp = {
ports_min = [0]
ports_max = [0]
remote_ip_prefix = ["0.0.0.0/0"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
},
udp = {
ports_min = [0]
ports_max = [0]
remote_ip_prefix = ["0.0.0.0/0"]
security_group_id = ["openstack_networking_secgroup_v2.bastion.id"]
}
}
}
}
Định nghĩa tương ứng phải là:
variable "secgroups" {
type = map(map(map(object({
ports_min = list(number)
ports_max = list(number)
security_group_id = list(string)
}))))
}
Nhưng đối tượng bên trong ở trên sẽ loại bỏ tất cả các thuộc tính phụ, chẳng hạn như remote_ip_prefixvì các đối tượng của bạn không nhất quán. Tuy nhiên, kể từ khi ingress, egress, tcpvà udpdường như là phù hợp, bạn có thể có thể sử dụng như sau:
variable "secgroups" {
type = map(object({
ingress = object({tcp = map(any), udp = map(any)})
egress = object({tcp = map(any), udp = map(any)})
}))
}
Là tài nguyên cuối cùng, nếu không có gì nhất quán, thì bạn có thể sử dụng:
variable "secgroups" {
type = map(map(map(map(any))))
}
Cập nhật: kiểm tra đầu ra
output "test" {
value = var.secgroups.ssh_from_bastion.ingress.tcp.ports_min
}