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.
https://github.com/hgfranco/terraform-2
Using the output from a module to another module isn’t really trivial.