Using output in another module or resource

I’ve seen a good amount of posts that talk about passing a module’s output into another module. For some reason I can’t get this to work.

I can get the output of the module without any issues

$ terraform output
this_sg_id = sg-xxxxxxxxxxxxxxxxx

However, when I call the module in the resource or into another module, it asks me for the Security group ID.

$ terraform plan
var.vpc_security_group_ids
  Security Group ID
  Enter a value:

Here’s my file structure:

 ── dev
│     └── service
│       └── dev_instance
│           ├── main.tf
│           ├── outputs.tf
│           ├── variables.tf
├── modules
│       ├── ec2
│       │   ├── build_ec2.tf
│       │   ├── outputs.tf
│       │   └── variables.tf
│       └── sg
│           ├── build_sg.tf
│           ├── outputs.tf
│           └── variables.tf

Not sure if this is correct but in dev/service/dev_instance/main.tf:

module "build_sg" {
source         = "../../../modules/sg/"
vpc_id         = var.vpc_id
sg_name        = var.sg_name
sg_description = var.sg_description
sg_tag         = var.sg_tag
sg_tcp_ports   = var.sg_tcp_ports
sg_tcp_cidrs   = var.sg_tcp_cidrs
sg_udp_ports   = var.sg_udp_ports
sg_udp_cidrs   = var.sg_udp_cidrs
sg_all_ports   = var.sg_all_ports
sg_all_cidrs   = var.sg_all_cidrs
}

module "build_ec2" {
source                         = "../../../modules/ec2/"
vpc_security_group_ids     = ["${module.build_sg.this_sg_id}"]
}

In dev/service/dev_instance/output.tf:

output "this_sg_id" {
description = "The security group ID"
value       = "${module.build_sg.this_sg_id}"
}

My ec2 module build_ec2.tf file has the following:

resource "aws_instance" "ec2" {
vpc_security_group_ids = ["${module.build_sg.this_sg_id}"]
}

The output this_sg_id from module build_sg is available in the root module (the level which calls the build_sg and build_ec2 modules, in this case equivalent to the folder dev_instance as the value module.build_sg.this_sg_id, and you probably have a stanza in dev_instance/outputs.tf looking like this:

output this_sg_id {
  value = module.build_sg.this_sg_id
}

But the other module doesn’t know about that, it only knows what you feed into it.
So, in the ec2 module you should declare a variable like vpc_security_group_ids of type = list and use that in the build_ec2.tf file:

resource "aws_instance" "ec2" {
vpc_security_group_ids = var.vpc_security_group_ids
....
}

Now, the instantiation of the ec22 module becomes something like this:

module "build_ec2" {
source                         = "../../../modules/ec2/"
vpc_security_group_ids     = [module.build_sg.this_sg_id]
}

This means that when you call the module, you first construct a list consisting of one element - this_sg_id. Then the module is call is made and the list is passed to the module parameter vpc_security_group_ids. Inside the module, vpc_security_group_ids is just a variable like all others, the ec2 module neither knows nor cares that the value passed comes from another module.

Hope this helps

@bentterp this did help. Thanks. I followed your advice but I’m getting the following error now.

$ terraform plan

Error: Reference to undeclared resource

on …/…/…/modules/ec2/outputs.tf line 9, in output “this_sg_id”:
9: concat(aws_security_group.create_security_group.*.id, [""]),

A managed resource “aws_security_group” “create_security_group” has not been
declared in build_ec2.

As you can see above, I don’t have the “aws_security_group” declared in the build_ec2 module but it’s been declared in the build_sg module.

I created a github repo with a sample of what I’ve been working on.

Using the output from a module to another module isn’t really trivial.