Skip to content

5 — Outputs

Folder: 01-basics/4-dependencies/explicit/ has the simple case; the structured examples below need a scratch root.

An output exposes a value from a root module — to your terminal, to a parent module, or to another config reading this one's state.

The simple case

4-dependencies/explicit/main.tf ends with:

output "pet_output" {
  description = "Record the value of pet ID generated by the random_pet resource"
  value       = random_pet.my_pet.id
}
terraform apply
terraform output pet_output

Primitive vs structured

output "pet_id" {
  description = "The generated random pet name/id."
  value       = random_pet.my_pet.id
}

output "all_named_pet_files" {
  description = "Map of pet name to file path."
  value       = { for k, f in local_file.named_pets : k => f.filename }
}

The second uses a for expression to build a map from a for_each'd resource — see count and for_each for where local_file.named_pets comes from.

terraform apply
terraform output pet_id
terraform output -raw pet_id
terraform output -json all_named_pet_files
terraform output -json all_named_pet_files | jq -r '.fido'

-raw works on pet_id but errors on all_named_pet_files. -raw prints a bare string with no quotes or JSON wrapping, which only makes sense for a primitive. For maps, lists and objects you need -json. This is the distinction you hit the moment you try to pipe an output into a shell variable.

Outputs are the module interface

Inside a child module, output blocks are how the caller reads values back: module.<name>.<output>. That's the mechanism behind Lab 9, and the for-expression-over-module-instances pattern in Lab 13 is exactly the all_named_pet_files shape above applied to modules instead of resources.

Outputs land in state in plaintext

Anything you output is written to the state file as-is, including values you marked sensitive. sensitive = true suppresses the value in CLI output only — see Validation and sensitive values.

Convention

Outputs belong in outputs.tf. Terraform doesn't care — it concatenates every .tf file in the directory — but scattering them makes them hard to find. The core GCP root breaks this rule in two places, which is worth seeing precisely so you don't inherit the habit.

Key takeaway

An output is a published interface and a plaintext state entry at the same time. Declare one because something outside this config needs the value — a parent module, another root, a human running terraform output. Declaring one just to look at a value yourself is what terraform state show already does, without widening the contract.


Theory: §10 Outputs · Next: Data sources