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

map of string within a map object


I'm trying to create a Compute Engine instance and I'm trying to map values of different types, but I'm getting error as you can see from the following code.

variable "compute_engine_instances" {
  type = map(object({
    instance_name = string
    machine_type  = string
    zone          = string
    tags          = list(string)
    image_name    = string
    image_project = string
    labels        =list(object({
    app_id      = number
    cost_center = string
    owner       = string
    email       = string
  }))
  }))
}

module "compute_engines" {
  source = "../modules/compute_engine"

  for_each      = var.compute_engine_instances
  project_id    = var.project_id
  instance_name = each.value.instance_name
  machine_type  = each.value.machine_type
  tags          = each.value.tags
  labels        = each.value.labels
  subnetwork    = var.subnetwork
  zone          = each.value.zone
  image_name    = each.value.image_name
  image_project = each.value.image_project
}

Terraform tf vars file as:

compute_engine_instances ={
    "test-adi"={

    instance_name = "test-vm"
    machine_type  = "n1-standard-1"
    zone           = "us-east4-b"
    tags   = ["foo","bar"]
    image_name    = "centos-7"
    image_project = "cc-devtools"
    labels = [{
  app_id      = "6"
  cost_center = "0156"
  owner       = "ops"
  email       = "ps"
}]
}
}

I'm getting the following error when I run tf plan, How can i fix this error?

Thanks for you help.

Error: Incorrect attribute value type

  on ..\modules\compute_engine\main.tf line 14, in resource "google_compute_instance" "generic_instance":
  14:   labels = var.labels

Inappropriate value for attribute "labels": map of string required.

modules folder looks like the following:

data "google_compute_image" "compute_image" {
  name    = var.image_name
  project = var.image_project
}

resource "google_compute_instance" "generic_instance" {
  project      = var.project_id
  name         = var.instance_name
  machine_type = var.machine_type
  zone         = var.zone

  tags   = var.tags
  labels = var.labels

  boot_disk {
    initialize_params {
      image = data.google_compute_image.compute_image.self_link
    }
    auto_delete = true
  }

  network_interface {
    subnetwork = var.subnetwork
  }
}

labels variable in modules is as follows:

variable "labels" {
  type        = any
  description = "A list of labels for this VM"
} 

Solution

  • If you check tf docs, labels, it should be a map (not list like in your case) of key/value label pairs:

    variable "compute_engine_instances" {
      type = map(object({
        instance_name = string
        machine_type  = string
        zone          = string
        tags          = list(string)
        image_name    = string
        image_project = string
        labels        =object({
        app_id      = number
        cost_center = string
        owner       = string
        email       = string
      })
      }))
    }
    
    
    compute_engine_instances ={
        "test-adi"={
    
        instance_name = "test-vm"
        machine_type  = "n1-standard-1"
        zone           = "us-east4-b"
        tags   = ["foo","bar"]
        image_name    = "centos-7"
        image_project = "cc-devtools"
        labels = {
      app_id      = "6"
      cost_center = "0156"
      owner       = "ops"
      email       = "ps"
    }
    }
    }