带有列表抛出错误的 Terraform 多级地图

Terraform Multilevel Maps with list throwing error

我在执行 terraform plan 时出现以下错误。当我在 volume_name 中使用 单个 卷名时,我没有看到任何错误,当我在 volume_name= ["test-terraform-0", "test-terraform-1", "test-terraform-2"] 中指定多个卷名时,我遇到了这个错误。我请求您帮助我解决我的问题或建议替代方案 idea/solution 实现我的目标

terraform plan -var-file=customers/nike.tfvars

│ Error: Incorrect attribute value type
│
│   on gcp_compute_disk/gcp_compute_disk.tf line 4, in resource "google_compute_disk" "disk":
│    4:   name = each.value.volume_name
│     ├────────────────
│     │ each.value.volume_name is list of string with 3 elements
│
│ Inappropriate value for attribute "name": string required.
╵
│ Error: Incorrect attribute value type
│
│   on gcp_compute_disk/gcp_compute_disk.tf line 5, in resource "google_compute_disk" "disk":
│    5:   size = each.value.volume_size
│     ├────────────────
│     │ each.value.volume_size is list of number with 3 elements
│
│ Inappropriate value for attribute "size": number required.
╷
│ Error: Incorrect attribute value type
│
│   on gcp_compute_disk/gcp_compute_disk.tf line 6, in resource "google_compute_disk" "disk":
│    6:   type = each.value.volume_type
│     ├────────────────
│     │ each.value.volume_type is list of string with 3 elements
│
│ Inappropriate value for attribute "type": string required.

文件夹结构

├── gcp_compute_disk
│   ├── gcp_compute_disk.tf
│   └── variables.tf
├── gcp_instance
│   ├── gcp_instance.tf
│   └── variables.tf
├── main.tf
├── customers
│   └── nike.tfvars
└── variables.tf

vairable.tf

variable "instance_config" {

  type = map(object({
    name                = string
    image               = string
    type                = string
    tags                = list(string)
    deletion_protection = bool
    startup_script      = string
    hostname            = string
    volume_name         = list(string)
    volume_size         = list(number)
    volume_type         = list(string)

  }))

  default = {
    test_vm = {
      name                = "test_vm"
      image               = "debian-cloud/debian-9"
      type                = "n1-standard-4"
      tags                = ["test_vm"]
      deletion_protection = false
      startup_script      = "start-up.sh"
      hostname            = "test_vm"
      volume_name         = ["test-terraform-0", "test-terraform-1", "test-terraform-2"]
      volume_size         = [50, 50, 50]
      volume_type         = ["pd-standard", "pd-standard", "pd-standard", ]
    }
  }
}

.tfvars

instance_config = {

  testvm1 = {
    name                = "solr"
    image               = "debian-cloud/debian-9"
    type                = "n1-standard-4"
    tags                = ["testvm1"]
    deletion_protection = false
    startup_script      = "../scripts/start-up.sh"
    hostname            = "testvm1.terraform.test"
    volume_name         = ["testvm1-test-terraform-0", "testvm1-test-terraform-1", "testvm1-test-terraform-2"]
    volume_size         = [50, 50, 50]
    volume_type         = ["pd-standard", "pd-standard", "pd-standard", ]
  },

  testvm2 = {
    name                = "testvm2"
    image               = "debian-cloud/debian-9"
    type                = "f1-micro"
    tags                = ["testvm2"]
    deletion_protection = false
    startup_script      = "../scripts/start-up.sh"
    hostname            = "testvm2.terraform.test"
    volume_name         = ["testvm2-test-terraform-0", "testvm2-test-terraform-1", "testvm2-test-terraform-2"]
    volume_size         = [50, 50, 50]
    volume_type         = ["pd-standard", "pd-standard", "pd-standard", ]

  }
}

gcp_compute_disk.tf

resource "google_compute_disk" "disk" {
  for_each = var.instance_config
  name = each.value.volume_name
  size = each.value.volume_size
  type = each.value.volume_type
}

gcp_instance.tf

resource "google_compute_instance" "vm_instance" {

  for_each = var.instance_config

  name                = each.value.name
  machine_type        = each.value.type
  tags                = each.value.tags
  deletion_protection = each.value.deletion_protection
  hostname            = each.value.hostname

  boot_disk {
    initialize_params {
      image = each.value.image
    }
  }

  metadata_startup_script = file(each.value.startup_script)

  attached_disk {
    source = each.value.volume_name
  }


  network_interface {
    network = var.gcp_network
  }
}

您可以检查以下内容:

locals {

  instance_volume_map = merge([for key, val in var.instance_config:
            {
               for idx in range(length(val.volume_size)):
                 "${key}-${idx}" => {
                       volume_name = val.volume_name[idx]
                       volume_size = val.volume_size[idx]
                       volume_type = val.volume_type[idx]
                  }
            }
            
          ]...)
}

resource "google_compute_disk" "disk" {
  for_each = local.instance_volume_map
  name = each.value.volume_name
  size = each.value.volume_size
  type = each.value.volume_type
}

resource "google_compute_instance" "vm_instance" {

  for_each            = var.instance_config

  name                = each.value.name
  machine_type        = each.value.type
  tags                = each.value.tags
  deletion_protection = each.value.deletion_protection
  hostname            = each.value.hostname

  boot_disk {
    initialize_params {
      image = each.value.image
    }
  }

  metadata_startup_script = file(each.value.startup_script)


  dynamic "attached_disk" {

    for_each = {for idx, val in range(length(each.value.volume_name)):
                    idx => val}

    content {
        source = local.instance_volume_map["${each.key}-${attached_disk.key}"].volume_name
    }

  }

  network_interface {
    network = var.gcp_network
  }
}