简体   繁体   中英

Terraform - get public ip of a sepcific vm when using for_each

I have a variable called variable "publicvms" which consists of 3 linux VM's being created using a for_each loop as below: vm.hostnames are VM1, VM2, VM3

resource "azurerm_virtual_machine" "publicvm" {
  for_each = { for vm in var.publicvms : vm.hostname => vm }

  provider                         = azurerm.xxxxxxxxxxxxxxxxxxxx
  name                             = each.value.hostname
  location                         = var.vm_location
  resource_group_name              = var.vm_resource_group
  network_interface_ids            = [azurerm_network_interface.publicnic[each.key].id]
  vm_size                          = each.value.size
  delete_data_disks_on_termination = true
  delete_os_disk_on_termination    = true
  #count                 = var.prometheus_group["instance_count"]

  storage_os_disk {
    name              = "${each.value.hostname}-Disk"
    caching           = "ReadWrite"
    create_option     = "FromImage"
    disk_size_gb      = each.value.disk_size_gb
    managed_disk_type = each.value.managed_disk_type

  }
  storage_image_reference {
    id = data.azurerm_shared_image_version.search.id
  }

  os_profile {
    computer_name  = each.value.hostname
    admin_username = var.admin_username
    admin_password = var.admin_password
  }

  os_profile_linux_config {
    disable_password_authentication = var.disable_authentication
  }

  tags = merge(var.generic_tags, each.value.extra_tag)
}

The vm's above use the id from the azurerm_public_ip to assign the ip_address to the vm's:

  for_each = { for vm in var.publicvms : vm.hostname => vm }

  provider            = azurerm.microsoftazureenterprise
  name                = "${each.value.hostname}-PublicIP"
  location            = var.vm_location
  resource_group_name = var.vm_resource_group
  allocation_method   = "Static"

  tags = var.generic_tags
}

I would like to create a variable which stores the value of one particular VM as I will use that variable to create a cloudflare dns entry.

  zone_id = var.cloudflare_zone_id
  name    = var.web_url_prefix
  value   = $azurerm_public_ip.publicip.Index_key["VM2"].ip_address
  type    = "A"
  proxied = false
}

I have tried the value above but it gives me the error:

azurerm_public_ip.publicip is object with 3 attributes The given key does not identify an element in this collection value.

in the tfstate file I see the following output:

      "module": "module.webserver_cluster",
      "mode": "managed",
      "type": "azurerm_public_ip",
      "name": "publicip",
      "provider": "module.webserver_cluster.provider[\"registry.terraform.io/hashicorp/azurerm\"].microsoftazure",
      "instances": [
        {
          "index_key": "VM1",
          "schema_version": 0,
          "attributes": {
            "allocation_method": "Static",
            "domain_name_label": null,
            "fqdn": null,
            "id": REDACTED,
            "idle_timeout_in_minutes": 4,
            "ip_address": "10.10.10.10",
            "ip_version": "IPv4",
            "location": "westeurope",
            "name": "VM1-PublicIP",
            "public_ip_prefix_id": null,
            "resource_group_name": "ResourceGroup1",
            "reverse_fqdn": null,
            "sku": "Basic",
            "tags": {
              "environment": "poc",
              "family": "Infrastructure",
            },
            "timeouts": null,
            "zones": []
          },
          "sensitive_attributes": [],
          "private": "REDACTED"
        },
        {
          "index_key": "VM2",
          "schema_version": 0,
          "attributes": {
            "allocation_method": "Static",
            "domain_name_label": null,
            "fqdn": null,
            "id": "REDACTED",
            "idle_timeout_in_minutes": 4,
            "ip_address": "20.20.20.20",
            "ip_version": "IPv4",
            "location": "westeurope",
            "name": "VM2-PublicIP",
            "public_ip_prefix_id": null,
            "resource_group_name": "ResourceGroup1",
            "reverse_fqdn": null,
            "sku": "Basic",
            "tags": {
              "environment": "poc",
              "family": "Infrastructure",
              "product": "Monitoring"
            },
            "timeouts": null,
            "zones": []
          },
          "sensitive_attributes": [],
          "private": "REDACTED"
        },
        {
          "index_key": "VM3",
          "schema_version": 0,
          "attributes": {
            "allocation_method": "Static",
            "domain_name_label": null,
            "fqdn": null,
            "id": "REDACTED",
            "idle_timeout_in_minutes": 4,
            "ip_address": "30.30.30.30",
            "ip_version": "IPv4",
            "location": "westeurope",
            "name": "VM3-PublicIP",
            "public_ip_prefix_id": null,
            "resource_group_name": "ResourceGroup1",
            "reverse_fqdn": null,
            "sku": "Basic",
            "tags": {
              "environment": "poc",
              "family": "Infrastructure",
              "product": "Monitoring"
            },
            "timeouts": null,
            "zones": []
          },
          "sensitive_attributes": [],
          "private": "REDACTED"
        }
      ]
    }

is there a way I can get the ip address "20.20.20.20" and pass it to the "value" in the cloudflare_record resource??

I have tried:

value   = $azurerm_public_ip.publicip.Index_key["VM2"].ip_address
value   = $azurerm_public_ip.publicip["VM2"].ip_address
value   = $azurerm_public_ip.publicip[1].ip_address
value   = $azurerm_public_ip.publicip["1"].ip_address

to no avail.

Regards, Raj

For your requirement, it seems you want to get the IP address of the public IP which you create using the for_each loop. Then it should be like this:

value = azurerm_public_ip.publicip["VM2"].ip_address

It shows differently in the state file and the output. So you can use the output to show what does it look like:

output "publicIPs" {
  value = azurerm_public_ip.publicip
}

And it will look like this:

publicIPs = {
  "VM1" = {
    xxxxx
  }
  "VM2" = {
    xxxxx
  }
  "VM3" = {
    xxx
  }
}

Yes, the output will be a map if you use the for_each loop. So you need to quote it with the key.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM