sokolata
sokolata

Reputation: 549

How can i set a count in for_each in terraform

I'm learning terraform by building a template to create my infrastructure in the hetzner cloud. For this purpose I'm using the hcloud provider.

I create a map variable hosts to create >1 server with different configuration.

variable "hosts" {
    type = map(object({
        name                    = string
        serverType              = string
        serverImage             = string
        serverLocation          = string
        serverKeepDisk          = bool
        serverBackup            = bool 
        ip                      = string
      }))
    }

This is working fine. But I need to configure also volumes. I need only for 2 servers additional volumes and terraform has to check if variable volume is true or not. If true a new volume with given details should be created and attached to the server. For this I edit my variable hosts:

variable "hosts" {
    type = map(object({
        name                    = string
        serverType              = string
        serverImage             = string
        serverLocation          = string
        serverKeepDisk          = bool
        serverBackup            = bool 
        ip                      = string

        volume                  = bool
        volumeName              = string
        volumeSize              = number
        volumeFormat            = string
        volumeAutomount         = bool
        volumeDeleteProtection  = bool
      }))
    }

in the main.tf the volume block looks like this, but it doesnt work because for_each and count cant be used together. How can I get what I'm looking for? Is that possible?

resource "hcloud_volume" "default" {
  for_each          = var.hosts
  count             = each.value.volume ? 1 : 0
  name              = each.value.volumeName
  size              = each.value.volumeSize
  server_id         = hcloud_server.default[each.key].id
  automount         = each.value.volumeAutomount
  format            = each.value.volumeFormat
  delete_protection = each.value.volumeDeleteProtection
}

Upvotes: 6

Views: 22835

Answers (1)

Matthew Schuchard
Matthew Schuchard

Reputation: 28739

The former iterative meta-argument count will not provide you with the functionality you need here, as you need to access the volume bool type on a per var.hosts iteration in the map. To that end, you can add a conditional in a for expression within the for_each meta-argument.

for_each = { for host, values in var.hosts: host => values if values.volume }

This will construct a map for the value of the for_each meta-argument. It will contain every key value pair of var.hosts for which the volume object key is true.

It would seem like this would be a good fit for a collect or map method or function which transforms list and map types and exist in many other languages, but these do not yet exist in Terraform. Therefore, we use a for expression lambda equivalent.

Upvotes: 8

Related Questions