Search code examples
google-cloud-platformterraformgoogle-compute-engine

GCP Fetch Public IP address for compute instance created from google_compute_instance_template


How can I fetch public IP address for compute instances created by google_compute_instance_template using terraform.

google_compute_instance_template There is no attribute to get name of the compute instances created . I can see only name_prefix which will be suffixed with some random string.

I was thinking of using google_compute_instance data source which as attribute network_interface.0.access_config.0.nat_ip , but it requires compute instance name. eg.

data "google_compute_instance" "appserver" {
  name = "primary-application-server"
  zone = "us-central1-a"
}

Below is the code I am using , I am attaching compute instance group manager to the backend service of a load balancer. I need the public ip of the instance for connecting to SQL database

resource "google_compute_region_instance_group_manager" "mig" {
  project = var.project
  name    = "${var.name}-instance-group"
  region  = var.region
  version {
    instance_template = google_compute_instance_template.instance_template.id
    name              = "primary"
  }
  
  named_port {
    name = "https"
    port = 443
  }
  base_instance_name = "${var.name}-mig"
  target_size        = var.instance_count
}
resource "google_compute_instance_template" "instance_template" {
  name_prefix             = "${var.name}-instance"
  project                 = var.project
  machine_type            = var.machine_type
  labels                  = var.labels
  tags                    = local.firewall_rules.target_tags
  can_ip_forward          = var.can_ip_forward
  metadata_startup_script = file("${path.module}/${var.startup_script}")
  region                  = var.region
  #min_cpu_platform        = var.min_cpu_platform
  dynamic "disk" {
    for_each = local.all_disks
    content {
      auto_delete  = lookup(disk.value, "auto_delete", null)
      boot         = lookup(disk.value, "boot", null)
      device_name  = lookup(disk.value, "device_name", null)
      disk_name    = lookup(disk.value, "disk_name", null)
      disk_size_gb = lookup(disk.value, "disk_size_gb", lookup(disk.value, "disk_type", null) == "local-ssd" ? "375" : null)
      disk_type    = lookup(disk.value, "disk_type", null)
      interface    = lookup(disk.value, "interface", lookup(disk.value, "disk_type", null) == "local-ssd" ? "NVME" : null)
      mode         = lookup(disk.value, "mode", null)
      source       = lookup(disk.value, "source", null)
      source_image = lookup(disk.value, "source_image", null)
      type         = lookup(disk.value, "disk_type", null) == "local-ssd" ? "SCRATCH" : "PERSISTENT"
      #labels       = lookup(disk.value, "disk_labels", {}) 

      dynamic "disk_encryption_key" {
        for_each = compact([var.disk_encryption_key == null ? null : 1])
        content {
          kms_key_self_link = var.disk_encryption_key
        }
      }
    }
  }

  dynamic "service_account" {
    for_each = [var.service_account]
    content {
      email  = lookup(service_account.value, "email", null)
      scopes = lookup(service_account.value, "scopes", null)
    }
  }

  dynamic "network_interface" {
    for_each = var.network_interfaces
    iterator = config
    content {
      network    = config.value.network
      subnetwork = "projects/${var.project}/regions/${var.region}/subnetworks/${config.value.subnetwork}"
      network_ip = try(config.value.addresses.internal, null)
      dynamic "access_config" {
        for_each = config.value.nat ? [""] : []
        content {
          nat_ip = try(config.value.addresses.external, null)
        }
      }
      dynamic "alias_ip_range" {
        for_each = local.network_interface_options[config.key].alias_ips != null ? local.network_interface_options[config.key].alias_ips : {}
        iterator = config_alias
        content {
          subnetwork_range_name = config_alias.key
          ip_cidr_range         = config_alias.value
        }
      }
      nic_type = local.network_interface_options[config.key].nic_type
    }
  }

  lifecycle {
    create_before_destroy = "true"
  }

  # scheduling must have automatic_restart be false when preemptible is true.
  scheduling {
    automatic_restart   = !var.options.preemptible
    on_host_maintenance = local.on_host_maintenance
    preemptible         = var.options.preemptible
  }

  dynamic "shielded_instance_config" {
    for_each = var.shielded_config != null ? [var.shielded_config] : []
    iterator = config
    content {
      enable_secure_boot          = config.value.enable_secure_boot
      enable_vtpm                 = config.value.enable_vtpm
      enable_integrity_monitoring = config.value.enable_integrity_monitoring
    }
  }

  dynamic "confidential_instance_config" {
    for_each = var.confidential_compute ? [""] : []
    content {
      enable_confidential_compute = true
    }
  }

Solution

  • I think this can be done by the following:

    #Get the list of instances
    data "google_compute_region_instance_group" "mig_data" {
        name = google_compute_region_instance_group_manager.mig.name
        region = var.region
    }
    
    #Get each instance data 
    data "google_compute_instance" "intance_data" {
      count = length(data.google_compute_region_instance_group.mig_data.instances)
      self_link = data.google_compute_region_instance_group.mig_data.instances[count.index].instance
    }
    
    #Print the data needed
    output "public_ips" {
      value = [
        for instance in data.google_compute_instance.intance_data: 
        [
          instance.name, instance.network_interface.0.access_config.0.nat_ip
        ]
      ]
    }
    

    Basically we need to get the list of instances created in the MIG using the data.google_compute_region_instance_group and then iterate over this list to get the data for each instance.

    I'm using output just to print the IPs but of course you can use those values in any other resource if you want.