Providing additional disk through in terraform

Hi Team,

I am using module to create additional disk but getting below error and u can see my code below any assistance please?

error : │ Error: Invalid for_each argument

│ on .terraform/modules/xxx/module/main.tf line 27, in resource “google_compute_disk” “additional_disks”:
│: for_each = { for disk in var.additional_disks : disk.name => disk }
│ ├────────────────
│ │ var.additional_disks is list of object with 1 element

Code :

resource “random_string” “add_disk_suffix” {
length = 4
number = true
min_numeric = 2
upper = false
special = false
}

module “gce” {
source = “xyz”
version = “1.0.3”

name = var.instance_name
project = var.gcp[var.environment].project_id
zone = var.zone
subnetwork_project = var.gcp[var.environment].network_project
subnetwork = var.gcp[var.environment].subnetwork
machine_type = var.machine_type
tags = “{split(",", var.tags)}" source_image = var.source_image source_image_project = var.source_image_project service_account_email = var.gcp[var.environment].service_account metadata = { env = var.environment, creator = var.vm_owner } metadata_startup_script = "{file(”./…/scripts/bootstrap.sh")}"
additional_disks = [{
name = “additional-disk-${random_string.add_disk_suffix.result}”,
type = “pd-ssd”,
size = var.additional_disk_size,
description = “”,
labels = {},
mode = “READ_WRITE”,
device_name = “”,
disk_encryption_key_raw = “”,
kms_key_self_link = “”,
snapshot = “”,
provisioned_iops = 0,
resource_policies =
}]
}

locals {
disk_name = “${var.instance_name}”
}

variable “additional_disks” {
description = “Additional persistent disks to attach to the instance.”
type = list(object({
name = string
size = number
type = string
provisioned_iops = number
description = string
labels = map(string)
device_name = string
mode = string
kms_key_self_link = string
disk_encryption_key_raw = string
snapshot = string
resource_policies = list(string)
provisioned_iops = number
}))
default =
}

Thanks
Mahen

Hi @mahendra03,

This error means that the name attribute of at least one of the elements of the additional disks list is derived from a resource attribute value that three provider cannot predict during planning.

The keys in for_each should typically be strings chosen statically in the configuration to ensure they will always be consistently known through plan and apply.

A random string result is not a suitable instance key, because that string will be decided only during the apply step.

I would suggest changing that variable to be a map of objects rather than a list of objects, and then you can use the map keys as instance IDs (local within Terraform, so no need for random suffix) and use the name attribute only for populating the corresponding field in the remote API, where that random suffix is presumably important to avoid collisions.

Hi @apparentlymart - actually we want every time when instance will be created and we want new additional disk created with different name else , if we create instance again then it give error stating that disk already exist.

Also I will give a try the way you suggested and will check and update you.

│ Sensitive values, or values derived from sensitive values, cannot be used
│ as for_each arguments

Hi All, @apparentlymart

Guys what I am doing wrong my instance is getting created and additional disk getting created but it is not attaching to instance vm in gcp.

resource “random_string” “add_disk_suffix” {
length = 4
number = true
min_numeric = 2
upper = false
special = false
}

module “gce” {
source = “xxxx”
version = “xxx”

name = var.instance_name
project = var.gcp[var.environment].project_id
zone = var.zone
subnetwork_project = var.gcp[var.environment].network_project
subnetwork = var.gcp[var.environment].subnetwork
machine_type = var.machine_type
tags = “{split(",", var.tags)}" source_image = var.source_image source_image_project = var.source_image_project service_account_email = var.gcp[var.environment].service_account metadata = { env = var.environment, creator = var.vm_owner } metadata_startup_script = "{file(”./…/scripts/bootstrap.sh")}"
/* additional_disks = [{
name = “additional-disk-123”,
type = “pd-ssd”,
size = var.additional_disk_size,
description = “”,
labels = {},
mode = “READ_WRITE”,
device_name = “”,
disk_encryption_key_raw = “”,
kms_key_self_link = “”,
snapshot = “”,
provisioned_iops = 0,
resource_policies =
}] */
}

locals {
disk_name = “${var.instance_name}”
}

resource “google_compute_disk” “additional_disks” {
provider = google-beta
zone = var.zone
name = local.add_disk_name
type = “pd-ssd”
size = var.additional_disk_size
description = “”
labels = {}
#mode = “READ_WRITE”
snapshot = “”
provisioned_iops = 0
resource_policies =

depends_on = [
module.gce,
]

}

locals {
add_disk_name = “add-disk-${random_string.add_disk_suffix.result}”
}

resource “google_compute_instance” “default” {
name = var.instance_name
machine_type = var.machine_type
zone = var.zone
boot_disk {
initialize_params {
image = var.source_image
}
}

attached_disk {
source = google_compute_disk.additional_disks.id
device_name = “data-disk-0”
mode = “READ_WRITE”
}

network_interface {
subnetwork_project = var.gcp[var.environment].network_project
subnetwork = var.gcp[var.environment].subnetwork
access_config {}
}

}

resource “google_compute_attached_disk” “default” {
disk = google_compute_disk.additional_disks.id
instance = google_compute_instance.default.id

depends_on = [
google_compute_disk.additional_disks,
google_compute_instance.default,
]

}