Pass For_each output to another Module Error

I’m following the “Pass For_each output to another Module”, post APR 21 by apparentlymart. I’m receiving the following error:

//// Error Code

The error code is:

Error: Invalid value for input varibale

on main.tf line 28, in modulle “ebs”

28: ec2_instance_ids = module.ec2.instance_ids

The given values is not suitable for module.ebs.var.ec2_instances_ids declared at modules/ebs/main.tf:1.1-28:incorrect map element

type: string required.

Not sure what I am missing here. Any help is appreciated!

.
|
|-----main.tf
|
|-----modules
      |
      |--- ebs
	  |     |
	  |     |__ main.tf
      |
	  |--- ec2
	        |
			|__ main.tf
			|
			|__ variables.tf

\\main.tf

#Declare the aws providers
terraform {
   required_version = "~> 1.2"
   required_providers {
      aws = {
	    source = "hashicorp/aws"
		version = "2.2.0"
	  }
    }
}

provider "aws" {
  region = "us-east-1"
}

module "ec2" {
  source = "modules/ec2"

  # ...
}

module "ebs" {
  source = "modules/ebs"

  ec2_instance_ids = module.ec2.instance_ids
  # ...
}

//modules/ebs/maint.tf
variable "ec2_instance_ids" {
  type = map(string)
}

resource "aws_volume_attachment" "example" {
  for_each = var.ec2_instance_ids

  # ...
}


resource "aws_ebs_volume" "example" {
  availablity_zone = "us-eat-1"
  size = 1 
}


//modules/ec2/main.tf
resource "aws_instance" "ec2-example" {
  ami = "Placeholder"
  instance_type = ""
  subnet_id = ""
  key_name = ""


  vpc_security_group_ids = [    aws_security_group.project-iac-sg.id  ]
  root_block_device {
    delete_on_termination = true
    iops = 150
    volume_size = 50
    volume_type = "gp2"
  }
  tags = {
    Name ="SERVER01"
  }
}


output "instance_ids" {
  value = tomap({
    for k, inst in aws_instance.example : k => inst.id
  })
}

Could you share a repo to explore this?
Other than that, I’d just output the ec2 outputs to console and review the structure.

Hi @mmauney,

If I’m reading your code example correctly, it looks like resource "aws_instance" "ec2-example" doesn’t use for_each, and so aws_instance.example is just a single EC2 instance object, rather than a map.

Unfortunately a for expression can also work on an object but it does something a bit different: it visits each attribute of the object, so it would end up visiting k and inst values for each attribute of one EC2 instance object:

  • k = "ami", inst = "Placeholder"
  • k = "instance_type", inst = ""
  • k = "tags", inst = { Name = "SERVER01" }

This means that instance_ids isn’t actually a map of instance ID strings but instead is a map of all of the attributes of one EC2 instance, and so that’s not of the correct type for variable "ec2_instance_ids".

To make this work you’ll need to either set for_each inside the resource "aws_instance" "ec2-example" block, so that aws_instance.example will be a map of EC2 instances, or you’ll need to change output "instance_ids" to return only the one instance ID instead (at which point it probably makes sense to rename it to just "instance_id").