So führen Sie eine Liste (Objekte) in Terraform 0.12 durch


10

Wenn Sie eine Frage haben, muss ich eine Liste der GCP-Recheninstanzen bereitstellen. Wie kann ich for_each durch die "vms" in dieser Objektliste wie dieser schleifen?

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

Terraforming verwendet eine deklarative Sprache, folglich gibt es keine if, foroder whileAussagen. Sie können diese jedoch bis zu einem gewissen Grad simulieren, in einigen Fällen dank der countEigenschaft. Lesen Sie diesen ausgezeichneten Artikel über das Reproduzieren von Bedingungen oder Schleifen mit Terraform : blog.gruntwork.io/…
arvymetal

Ab Terraform 0.12.6 können Ressourcen for_eachBlöcke verwenden: 0.12.6 Changelog . Für das, was es wert ist, wenn / else-Bedingungen jetzt für einige Versionen in Terraform sind: Terraform-Dokumente: Bedingte Ausdrücke
Carlo Mencarelli

Antworten:


4

Scheint, als hätte ich gefunden, was ich tun soll. Wenn Sie nicht die Karten von Karten, sondern die Liste der Karten übergeben, können Sie einen solchen Code verwenden

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

Es wird die tatsächliche Anzahl der Instanzen erstellt, und wenn Sie beispielsweise die mittlere von drei entfernen (wenn Sie drei erstellen :)), entfernt terraform das, was wir gefragt haben.


Das funktioniert gut. Die Liste (Objekt) wird in eine Map konvertiert, die als for_each-Wert verwendet werden kann.
Wählen Sie

4

Ab Terraform 0.12 können Sie for_each mit folgenden Modulen verwenden:

modules / google_compute_instance / variables.tf

variable "hosts" {
    type = map(object({
        hostname        = string
        cpu             = number
        ram             = number
        hdd             = number
        log_drive       = number
        template        = string 
        service_types   = list(string)
      }))
    }

modules / google_compute_instance / main.tf

resource "google_compute_instance" "gcp_instance" {
  for_each = var.hosts

  hostname      = each.value.repository_name
  cpu           = each.value.cpu
  ram           = each.value.ram
  hdd           = each.value.hdd
  log_drive     = each.value.log_drive
  template      = each.value.template
  service_types = each.value.service_types
}

servers.tf

module "gcp_instances" {
    source = ./modules/google_compute_instance"

    hosts = {
        "test1-srfe" = {
            hostname        = "test1-srfe",
            cpu             = 1,
            ram             = 4,
            hdd             = 15,
            log_drive       = 300,
            template        = "Template-New",
            service_types   = ["sql", "db01", "db02"]
        },
        "test1-second" = {
            hostname        = "test1-second",
            cpu             = 1,
            ram             = 4,
            hdd             = 15,
            log_drive       = 300,
            template        = "APPs-Template",
            service_types   = ["configs"]
        },
    }
}

Natürlich können Sie beliebig viele Variablen hinzufügen und im Modul verwenden.


Es ist schön, aber die Variable wird jedes Mal dynamisch bereitgestellt.
TheShadow2707

Allgemeine Variablen können separat als Variablen hinzugefügt und als var.variable wiederverwendet werden. Die eindeutigen müssen ohnehin separat deklariert werden.
Tamás Juhász

1

Die Verwendung des for_eachBlocks ist ziemlich neu und es gibt nicht zu viel Dokumentation. Einige der besten Informationen stammen aus ihrem Ankündigungsblog: https://www.hashicorp.com/blog/hashicorp-terraform-0-12-preview-for-and-for-each/

Lesen Sie auch den Abschnitt Dynamische Blöcke in der Dokumentation: https://www.terraform.io/docs/configuration/expressions.html#dynamic-blocks

Wie Ihr Beispiel aussieht, benötigen Sie für jede erstellte Instanz eine Reihe von Werten, damit Sie eine Karte mit Karten erhalten:

Unten sehen Sie ein Beispiel, das ich mit Terraform 0.12.12 erstellt habe:

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

Ausgabe des Terraformplans:

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.

Also muss ich die Liste in eine Karte konvertieren, da ich verstehe, dass der Index der Liste in Schlüssel geändert wird und es sich um eine Karte handelt.
TheShadow2707
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.