Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/loops/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
List 如何通过Terraform 0.12中的列表(对象)为每个对象创建_List_Loops_Object_Foreach_Terraform - Fatal编程技术网

List 如何通过Terraform 0.12中的列表(对象)为每个对象创建

List 如何通过Terraform 0.12中的列表(对象)为每个对象创建,list,loops,object,foreach,terraform,List,Loops,Object,Foreach,Terraform,我需要部署一个GCP计算实例列表。如何通过如下对象列表中的“vms”为每个_循环: "gcp_zone": "us-central1-a", "image_name": "centos-cloud/centos-7", "vms": [ { "hostname": "test1-srfe",

我需要部署一个GCP计算实例列表。如何通过如下对象列表中的“vms”为每个_循环:

    "gcp_zone": "us-central1-a",
    "image_name": "centos-cloud/centos-7",
    "vms": [
      {
        "hostname": "test1-srfe",
        "cpu": 1,
        "ram": 4,
        "hdd": 15,
        "log_drive": 300,
        "template": "Template-New",
        "service_types": [
          "sql",
          "db01",
          "db02"
        ]
      },
      {
        "hostname": "test1-second",
        "cpu": 1,
        "ram": 4,
        "hdd": 15,
        "template": "APPs-Template",
        "service_types": [
          "configs"
        ]
      }
    ]    
}

为每个块使用
,这是非常新的,并且没有太多文档。一些最好的信息来自他们的公告博客:

另外,请确保查看其文档中的“动态块”部分:

根据您的示例的外观,您需要为创建的每个实例设置一组值,以便创建一个映射图:

下面是我使用Terraform 0.12.12创建的示例:

variable "hostnames" {
    default = {
        "one" = {
            "name" = "one",
            "machine" = "n1-standard-1",
            "os" = "projects/coreos-cloud/global/images/coreos-stable-2247-5-0-v20191016",
            "zone" = "us-central1-a"
        },
        "two" = {
            "name" = "two",
            "machine" = "n1-standard-2",
            "os" = "projects/centos-cloud/global/images/centos-8-v20191018",
            "zone" = "us-central1-b"
        }
    }
}

resource "google_compute_instance" "default" {
    for_each = var.hostnames
    name         = each.value.name
    machine_type = each.value.machine
    zone         = each.value.zone

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

    scratch_disk {
    }

    network_interface {
        network = "default"
    }
}
地形平面图输出:

Terraform will perform the following actions:

  # google_compute_instance.default["one"] will be created
  + resource "google_compute_instance" "default" {
      + can_ip_forward       = false
      + cpu_platform         = (known after apply)
      + deletion_protection  = false
      + guest_accelerator    = (known after apply)
      + id                   = (known after apply)
      + instance_id          = (known after apply)
      + label_fingerprint    = (known after apply)
      + machine_type         = "n1-standard-1"
      + metadata_fingerprint = (known after apply)
      + name                 = "one"
      + project              = (known after apply)
      + self_link            = (known after apply)
      + tags_fingerprint     = (known after apply)
      + zone                 = "us-central1-a"

      + boot_disk {
          + auto_delete                = true
          + device_name                = (known after apply)
          + disk_encryption_key_sha256 = (known after apply)
          + kms_key_self_link          = (known after apply)
          + mode                       = "READ_WRITE"
          + source                     = (known after apply)

          + initialize_params {
              + image  = "projects/coreos-cloud/global/images/coreos-stable-2247-5-0-v20191016"
              + labels = (known after apply)
              + size   = (known after apply)
              + type   = (known after apply)
            }
        }

      + network_interface {
          + address            = (known after apply)
          + name               = (known after apply)
          + network            = "default"
          + network_ip         = (known after apply)
          + subnetwork         = (known after apply)
          + subnetwork_project = (known after apply)
        }

      + scheduling {
          + automatic_restart   = (known after apply)
          + on_host_maintenance = (known after apply)
          + preemptible         = (known after apply)

          + node_affinities {
              + key      = (known after apply)
              + operator = (known after apply)
              + values   = (known after apply)
            }
        }

      + scratch_disk {
          + interface = "SCSI"
        }
    }

  # google_compute_instance.default["two"] will be created
  + resource "google_compute_instance" "default" {
      + can_ip_forward       = false
      + cpu_platform         = (known after apply)
      + deletion_protection  = false
      + guest_accelerator    = (known after apply)
      + id                   = (known after apply)
      + instance_id          = (known after apply)
      + label_fingerprint    = (known after apply)
      + machine_type         = "n1-standard-2"
      + metadata_fingerprint = (known after apply)
      + name                 = "two"
      + project              = (known after apply)
      + self_link            = (known after apply)
      + tags_fingerprint     = (known after apply)
      + zone                 = "us-central1-b"

      + boot_disk {
          + auto_delete                = true
          + device_name                = (known after apply)
          + disk_encryption_key_sha256 = (known after apply)
          + kms_key_self_link          = (known after apply)
          + mode                       = "READ_WRITE"
          + source                     = (known after apply)

          + initialize_params {
              + image  = "projects/centos-cloud/global/images/centos-8-v20191018"
              + labels = (known after apply)
              + size   = (known after apply)
              + type   = (known after apply)
            }
        }

      + network_interface {
          + address            = (known after apply)
          + name               = (known after apply)
          + network            = "default"
          + network_ip         = (known after apply)
          + subnetwork         = (known after apply)
          + subnetwork_project = (known after apply)
        }

      + scheduling {
          + automatic_restart   = (known after apply)
          + on_host_maintenance = (known after apply)
          + preemptible         = (known after apply)

          + node_affinities {
              + key      = (known after apply)
              + operator = (known after apply)
              + values   = (known after apply)
            }
        }

      + scratch_disk {
          + interface = "SCSI"
        }
    }

Plan: 2 to add, 0 to change, 0 to destroy.

好像我找到了该做的事。如果传递的不是地图的地图,而是地图列表,则可以使用此类代码

resource "google_compute_instance" "node" {
    for_each = {for vm in var.vms:  vm.hostname => vm}

    name         = "${each.value.hostname}"
    machine_type = "custom-${each.value.cpu}-${each.value.ram*1024}"
    zone         = "${var.gcp_zone}"

    boot_disk {
        initialize_params {
        image = "${var.image_name}"
        size = "${each.value.hdd}"
        }
    }

    network_interface {
        network = "${var.network}"
    }

    metadata = {
        env_id = "${var.env_id}"
        service_types = "${join(",",each.value.service_types)}"
  }
}

它将创建实际数量的实例,当您删除三个实例中的中间一个(如果您创建三个:)时,terraform将删除我们要求的内容。

从terraform 0.12中,您可以使用for_和如下模块:

for_each = toset(keys({for i, r in var.vms:  i => r}))
cpu = var.vms[each.value]["cpu"]
variable "vms" {
    type = list(object({
        hostname        = string
        cpu             = number
        ram             = number
        hdd             = number
        log_drive       = number
        template        = string 
        service_types   = list(string)
    }))
    default = [
        {
            cpu: 1
            ...
        }
    ]
}
modules/google\u compute\u instance/variables.tf modules/google\u compute\u instance/main.tf servers.tf
当然,您可以根据需要添加任意数量的变量并在模块中使用它们。

您可以执行以下操作:

for_each = toset(keys({for i, r in var.vms:  i => r}))
cpu = var.vms[each.value]["cpu"]
variable "vms" {
    type = list(object({
        hostname        = string
        cpu             = number
        ram             = number
        hdd             = number
        log_drive       = number
        template        = string 
        service_types   = list(string)
    }))
    default = [
        {
            cpu: 1
            ...
        }
    ]
}
假设您有以下情况:

for_each = toset(keys({for i, r in var.vms:  i => r}))
cpu = var.vms[each.value]["cpu"]
variable "vms" {
    type = list(object({
        hostname        = string
        cpu             = number
        ram             = number
        hdd             = number
        log_drive       = number
        template        = string 
        service_types   = list(string)
    }))
    default = [
        {
            cpu: 1
            ...
        }
    ]
}

我经常处理Terraform中的字符串列表和对象列表。这总是让我头疼。因此,我确定了两种最常见的模式,即字符串列表和对象列表。对于字符串列表,您可以始终使用
toset()
并使用
对每个字符串进行循环。使用对象列表时,需要将其转换为键为唯一值的贴图。对于唯一值,可以在列表中的所有对象中使用索引、哈希或唯一值

字符串列表:

locals {
  ip_addresses = ["10.0.0.1", "10.0.0.2"]
}

resource "example" "example" {
  for_each   = toset(local.ip_addresses)
  ip_address = each.key
}
locals {
  virtual_machines = [
    {
      ip_address = "10.0.0.1"
      name       = "vm-1"
    },
    {
      ip_address = "10.0.0.1"
      name       = "vm-1"
    }
  ]
}    

resource "example" "example" {
  for_each   = {
    for index, vm in local.virtual_machines:
    index => vm
    # OR: vm.name => vm (not always unique if names are the same)
    # OR: sha1(vm.name) vm => (not always unique if names are the same)
    # NOT: uuid() => vm (gets recreated everytime)
  }
  name       = each.value.name
  ip_address = each.value.ip_address
}
对象列表:

locals {
  ip_addresses = ["10.0.0.1", "10.0.0.2"]
}

resource "example" "example" {
  for_each   = toset(local.ip_addresses)
  ip_address = each.key
}
locals {
  virtual_machines = [
    {
      ip_address = "10.0.0.1"
      name       = "vm-1"
    },
    {
      ip_address = "10.0.0.1"
      name       = "vm-1"
    }
  ]
}    

resource "example" "example" {
  for_each   = {
    for index, vm in local.virtual_machines:
    index => vm
    # OR: vm.name => vm (not always unique if names are the same)
    # OR: sha1(vm.name) vm => (not always unique if names are the same)
    # NOT: uuid() => vm (gets recreated everytime)
  }
  name       = each.value.name
  ip_address = each.value.ip_address
}

Terraform使用声明性语言,因此没有
if
for
while
语句。但是,在某些情况下,由于
count
属性,您可以在一定程度上模拟这些。阅读这篇关于如何使用Terraform再现条件或循环的优秀文章:从Terraform 0.12.6开始,资源可以为每个块使用
。值得一提的是,if/else条件现在已经在Terraform中出现了几个版本:所以我需要将list转换为map,因为我理解了它,它将list的索引更改为key,这将是map。这很好,但每次都动态提供变量。公共变量可以作为变量单独添加,并作为var.variable重新使用。无论如何,唯一的一个必须单独声明。你是一个英雄。最后我找到了一个合适的例子,从头到尾,效果很好。列表(对象))将转换为一个贴图,该贴图可用作每个值的对应元素。只需选择唯一的密钥(例如主机名)