แผนที่หลายระดับ Terraform

Aug 27 2020

ฉันได้รับข้อผิดพลาดเกี่ยวกับ "แผนพื้นดิน" เมื่อพยายามใช้แผนที่หลายระดับ (3 ระดับขึ้นไป) และดูเหมือนจะไม่สามารถแก้ไขปัญหาที่แน่นอนได้ ข้อผิดพลาด: "ค่าที่ระบุไม่ถูกต้องสำหรับตัวแปร" secgroups ": element" bastion ": attribute" direction "is required" variable.tf ของฉันถูกต้องเมื่อแมปกับ secgroups.auto.tf หรือไม่ Ports_min และ ports_max จะเป็นรายการพอร์ตที่รวมไว้ทั้งหมดเพื่อเปิดสำหรับชื่อกลุ่มความปลอดภัย

เวอร์ชัน:

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

ตัวแปร. 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 (เพียงตัวอย่าง)

  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
           }
         }
       }
   })
 } 

คำตอบ

Marcin Aug 27 2020 at 08:00

มีปัญหาหลายประการเกี่ยวกับคำจำกัดความของคุณ

สมมติว่าเต็มของคุณsecgroups.auto.tfvarsคือ:

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"]
      }
    }
  }
}

คำจำกัดความที่เกี่ยวข้องควรเป็น:

variable "secgroups" {
  type = map(map(map(object({
        ports_min         = list(number)
        ports_max         = list(number)
        security_group_id = list(string)
      }))))
}

แต่วัตถุภายในข้างต้นจะทิ้งแอตทริบิวต์พิเศษทั้งหมดเช่นremote_ip_prefixเนื่องจากวัตถุของคุณไม่สอดคล้องกัน อย่างไรก็ตามตั้งแต่ingress, egress, tcpและudpดูเหมือนจะสอดคล้องคุณอาจอาจจะใช้ต่อไปนี้:

variable "secgroups" {
  type = map(object({
            ingress = object({tcp = map(any), udp = map(any)})
            egress =  object({tcp = map(any), udp = map(any)})
        }))
}

ในฐานะทรัพยากรสุดท้ายหากไม่มีสิ่งใดที่สอดคล้องกันคุณสามารถใช้:

variable "secgroups" {
  type = map(map(map(map(any))))
}

อัปเดต: ผลลัพธ์การทดสอบ

output "test" {
  value = var.secgroups.ssh_from_bastion.ingress.tcp.ports_min
}