How to set the EC2 resource instance count from a map value in a for_each in Terraform

For the following Terraform code - I would like to end up with 2x testing-sandbox-dev instances and 1x testing-sandbox-test instance. I'd like to be able to derive the count from the map value instance_count.

I have tried using count but Terraform doesn't allow this with the user of for_each.

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.27"
    }
  }

  required_version = ">= 0.14.9"
}

variable "instance_name" {
  description = "Value of the Name tag for the EC2 instance"
  type        = string
  default     = "ChangedName"
}

variable "aws_region" {
  description = "AWS Region"
  type        = string
  default     = "eu-west-2"
}

variable "instance_size_small" {
  description = "Instance size small"
  type        = string
  default     = "t3.micro"
}

variable "redundant_count" {
  description         = "Default redundancy - base number of instances to create for redundant services"
  type                = number
  default             = 1
}

variable "ami" {
  description = "Ubuntu 20.04 AMI"
  type        = string
  default     = "ami-0015a39e4b7c0966f"
}

provider "aws" {
  profile = "sandbox"
  region  = var.aws_region
}

variable "environment_name" {
  description         = "Environment Name"
  type                = string
  default             = "dev"
}

variable "client_name" {
  description         = "Client Name"
  type                = string
  default             = "sandbox"
}

variable "instances" {
  description = "Map of modules names to configuration."
  type        = map
  default     = {
    testing-sandbox-dev = {
      instance_count          = 2,
      instance_type           = "t3.micro",
      environment             = "dev"
    },
    testing-sandbox-test = {
      instance_count          = 1,
      instance_type           = "t3.micro",
      environment             = "test"
    }
  }
}

resource "aws_instance" "ec2-instance" {
  for_each = var.instances

  ami           = var.ami
  instance_type = each.value.instance_type

  tags = {
    Name = "${each.key}.${var.client_name}"
    client = var.client_name
    environment = var.environment_name
  }
}

How can I specify the instance count from the pre-defined map?


You have to expand your var.instances as follows:

locals {
  instances_flat = merge([
          for env, val in var.instances:
           {
             for idx in range(val["instance_count"]):
               "${env}-${idx}" => {
                   instance_type           = val["instance_type"]
                   environment             = val["environment"]
               }
           }
      ]...)
}

which gives:

instances_flat = {
  "testing-sandbox-dev-0" = {
    "environment" = "dev"
    "instance_type" = "t3.micro"
  }
  "testing-sandbox-dev-1" = {
    "environment" = "dev"
    "instance_type" = "t3.micro"
  }
  "testing-sandbox-test-0" = {
    "environment" = "test"
    "instance_type" = "t3.micro"
  }
}

then

resource "aws_instance" "ec2-instance" {
  for_each      = local.instances_flat

  ami           = var.ami
  instance_type = each.value.instance_type

  tags = {
    Name = "${each.value.environment}.${var.client_name}"
    client = var.client_name
    environment = var.environment_name
  }
}