
As the name implies, the terraform output command is used to return outputs. Let's say you have the following files on your Terraform server.
├── main.tf (root module)
├── data.tf
├── locals.tf
├── outputs.tf
├── providers.tf
├── terraform.tfstate
├── variables.tf
├── child (directory)
│ ├── main.tf (child module)
│ ├── data.tf
│ ├── outputs.tf
│ ├── resources.tf
This assumes terraform has already been initialized by the terraform init command.
~]# terraform init
Initializing the backend...
Initializing modules...
Initializing provider plugins...
Terraform has been successfully initialized!
Let's say you issue the terraform output command and Warning: No outputs found is returned.
Warning: No outputs found
This should mean the outputs key in your terraform.tfstate file is empty.
~]$ cat terraform.tfstate
{
"version": 4,
"terraform_version": "1.2.6",
"serial": 1,
"outputs": {},
This can happen if the outputs.tf file in the same directory as your main root module (main.tf) is empty, has no outputs.
~]# cat outputs.tf
Let's say you add one or more outputs to the outputs.tf file in the same directory as your main root module (main.tf).
output "greeting" {
value = "Hello World"
}
And then you issue the terraform refresh command. The outputs in the outputs.tf file in the same directory as your main root module (main.tf) should now be displayed.
~]# terraform refresh
Outputs:
greeting = "Hello World"
And your terraform.tfstate file should contain the outputs.
]$ cat terraform.tfstate
{
"version": 4,
"terraform_version": "1.5.2",
"serial": 1,
"lineage": "162d2e73-f0c7-4374-e946-2ce75c65ef76",
"outputs": {
"greeting": {
"value": "Hello World",
"type": "string"
}
},
Child Modules
Let's say you want to pass outputs from a child module to the main root module. I first happened upon this when I had a root module that contained a child module (vpc in this example).
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
provider "aws" {
access_key = var.access_key
secret_key = var.secret_key
}
module "vpc" {
source = "./vpc"
}
And the child module had outputs.
]$ cat vpc/outputs.tf
output "my_vpcs" {
value = data.aws_vpc.my_vpcs
}
outputs must be in the root module. Thus, what I ended up doing was using a directory structure like this.
├── main.tf
├── outputs.tf
├── vpc (directory)
│ ├── vpc.tf
In the vpc.tf file in the child module, I used "data" to get the JSON of the VPC named my-vpc and then used "output" to store the JSON in a variable named my_vpc.
data "aws_vpc" "my-vpc" {
filter {
name = "tag:Name"
values = ["my-vpc"]
}
}
output "my_vpc" {
value = data.aws_vpc.my-vpc
}
And then I had the following in outputs.tf in the same directory as my root module.
output "vpc" {
value = module.vpc.my_vpc
}
And then the terraform refresh command gave me the following.
]$ terraform refresh
module.vpc.data.aws_vpc.my_vpcs: Reading...
module.vpc.data.aws_vpc.my_vpcs: Read complete after 1s [id=vpc-014d2fcfa335d3c01]
Outputs:
vpc = {
"arn" = "arn:aws:ec2:us-east-1:713542074252:vpc/vpc-0521ac4b76ed94d8a"
"cidr_block" = "10.0.0.0/16"
"cidr_block_associations" = tolist([
{
"association_id" = "vpc-cidr-assoc-09ff7264a51c86a4b"
"cidr_block" = "10.0.0.0/16"
"state" = "associated"
},
])
"default" = false
"dhcp_options_id" = "dopt-017f0a715e4ce2fc9"
"enable_dns_hostnames" = false
"enable_dns_support" = true
"filter" = toset([
{
"name" = "tag:Name"
"values" = toset([
"my-vpc",
])
},
])
"id" = "vpc-0521ac4b76ed94d8a"
"instance_tenancy" = "default"
"ipv6_association_id" = ""
"ipv6_cidr_block" = ""
"main_route_table_id" = "rtb-091e5416b1c0d33a6"
"owner_id" = "713542074252"
"state" = tostring(null)
"tags" = tomap({
"Name" = "my-vpc"
})
"timeouts" = null /* object */
}
Did you find this article helpful?
If so, consider buying me a coffee over at