Study guide
7.2 Output Values
HashiCorp Certified: Terraform Associate 004
Track your progress as you read
Finished sections get a check mark.
1 Introduction & Exam Overview
1.1 Current Exam Facts 1.2 Format, Delivery, Retakes, and Recertification 1.3 004 Changes, Terraform 1.12, and Study Plan
2 Infrastructure as Code with Terraform
2.1 What Infrastructure as Code Is 2.2 Advantages of IaC Patterns 2.3 Multi-Cloud, Hybrid, and Service-Agnostic Workflows
3 Terraform Fundamentals: Providers & State
3.1 Install and Version Terraform Providers 3.2 How Terraform Uses Providers 3.3 Configuration with Multiple Providers 3.4 How Terraform Uses and Manages State
4 Core Terraform Workflow: Init & Validate
4.1 The Terraform Write–Plan–Apply Workflow 4.2 Initialize a Working Directory 4.3 Validate a Configuration
5 Plan, Apply, Destroy, and Formatting
5.1 Generate and Review an Execution Plan 5.2 Apply Changes to Infrastructure 5.3 Destroy Terraform-Managed Infrastructure 5.4 Formatting and Style Adjustments
6 Resources, Data Sources, and References
6.1 Resource Blocks vs Data Blocks 6.2 Resource Attributes and Cross-Resource References 6.3 Resource Addressing and Interpolation Patterns
7 Variables, Outputs, and Complex Types
7.1 Input Variables, tfvars, and Precedence 7.2 Output Values 7.3 Complex Types: list, map, object, tuple, set
8 Dynamic Configuration and Dependencies
8.1 Expressions, count, for_each, and dynamic Blocks 8.2 Built-in Functions 8.3 Dependencies, depends_on, and Lifecycle Rules
9 Conditions, Secrets, and Sensitive Data
9.1 Custom Conditions: validation, precondition, postcondition, check 9.2 Sensitive Data Handling 9.3 Vault, Ephemeral Values, and Write-Only Arguments
10 Terraform Modules
10.1 How Terraform Sources Modules 10.2 Variable Scope within Modules 10.3 Using Modules in Configuration 10.4 Managing Module Versions
11 Terraform State Management
11.1 The Local Backend 11.2 State Locking 11.3 Remote State and the backend Block 11.4 Resource Drift and State Operations
12 Maintain Infrastructure with Terraform
12.1 Import Existing Infrastructure 12.2 Inspect State with the CLI 12.3 Verbose Logging and Diagnostics
13 HCP Terraform
13.1 Create Infrastructure with HCP Terraform 13.2 Collaboration and Governance Features 13.3 Workspaces and Projects 13.4 HCP Terraform Integrations
7.2 Output Values
Key Takeaways Explain This Topic AI
An output block requires value; description, sensitive, depends_on, and ephemeral are optional on Terraform 1.12
Root-module outputs print after apply and appear on the HCP Terraform workspace overview; terraform output only lists those root outputs
A parent module can read a child only through the child's output blocks, as module.vpc.vpc_id — never the child's internal resource addresses
terraform output -raw prints a string, number, or bool with no quotes; -json is the stable format for objects, lists, and automation
sensitive redacts CLI display but still writes the value into state; ephemeral (1.10+) omits state and plan and is legal only on child-module outputs
Last updated: August 2026
7.2 Output Values
Quick Answer: output "NAME" { value = ... } is a return value. Root outputs print after apply and show in the HCP Terraform UI. A parent reads a child only as module.vpc.vpc_id . Use terraform output , -raw (string/number/bool), or -json . sensitive = true redacts CLI text but still stores the value in state. ephemeral = true omits state and plan and is allowed only on child-module outputs.
Objective 4c continues: use variables and outputs. Official pages: Use outputs to expose module data , the output block reference , and terraform output . Product version is Terraform 1.12 .
What an output is for
HashiCorp lists four jobs for output blocks:
A child module exposes selected attributes to its parent.
A root module prints values on the CLI after apply.
Another configuration reads those root outputs through data "terraform_remote_state" (including HCP Terraform state sharing).
Automation scrapes values after a run ( terraform output -json ).
An output is not a resource. It does not create infrastructure. It exports an expression. output "instance_id" {
- description = "ID of the EC2 instance"
- value = aws_instance.web.id
- }
- output "instance_ip" {
- description = "Private IP address of the EC2 instance"
- value = aws_instance.web.private_ip
- }
After a successful apply, Terraform prints root outputs. In HCP Terraform the workspace overview lists the same values. Child-module outputs do not appear in that list unless the root re-exports them.
Arguments on the Terraform 1.12 output block
Argument Required? Default Exam meaning
value Yes none Any expression. This is the only required argument. Terraform evaluates it and (unless ephemeral) stores the result in state.
description No none Written for the consumer: what the value is and how to use it.
sensitive No false Redacts the value in plan and apply CLI output as (sensitive value) . Still stored in state.
ephemeral No false Terraform 1.10+. Omits the value from state and plan files. Child modules only — you cannot mark a root output ephemeral. The value must come from an ephemeral context and can only be read in ephemeral contexts.
depends_on No none Explicit dependency list when the value expression does not already reference the object that must finish first.
precondition No none Optional check before Terraform exposes the value or writes it to state. Chapter 9 covers the condition language.
Terraform 1.12 does not require a type argument on outputs. Do not invent one for 004.
depends_on on an output is the classic "IP is useless until the security-group rule exists" case. Prefer an implicit reference when you can; if you add depends_on , comment why. output "instance_ip_addr" {
- value = aws_instance.server.private_ip
- description = "Private IP of the main server."
- depends_on = [
- aws_security_group_rule.local_access,
- ]
- }
- Child module outputs are the only values a parent can read
A parent cannot write module.vpc.aws_subnet.private[0].id . That address is private to the child. The child must declare an output, and the parent reads that name: # modules/vpc/outputs.tf
- output "vpc_id" {
- description = "ID of the VPC this module manages"
- value = aws_vpc.this.id
- }
- output "private_subnet_ids" {
- description = "Private subnet IDs"
- value = aws_subnet.private[*].id
- } # root
- module "vpc" {
- source = "./modules/vpc"
- }
- resource "aws_instance" "app" {
- subnet_id = module.vpc.private_subnet_ids[0]
- }
- output "app_vpc" {
- value = module.vpc.vpc_id
- description = "Re-export so terraform output and remote state can see it"
- }
The reference shape is module.<CHILD_MODULE_NAME>.<OUTPUT_NAME> . That is the same rule section 6.2 stated from the resource-address side. 004 will show module.vpc.aws_vpc.this.id as a distractor. It is not valid in the parent.
terraform output also only shows root outputs. To print a child value on the CLI, re-export it from the root as app_vpc does above.
terraform output , -raw , and -json
Invocation What you get
terraform output Human-readable dump of every root output. Sensitive names print as <sensitive> .
terraform output NAME That one root output. On the 1.12 CLI, naming a sensitive output prints the raw value — redaction is for the listing and for apply logs, not a guarantee on a named lookup.
terraform output -raw NAME The value as a bare string, no quotes, no extra whitespace. Works only for values Terraform can convert to a string: string, number, bool. Use this in shell scripts.
terraform output -json / terraform output -json NAME Stable JSON. Required for lists, maps, and objects. Pipe to jq .
-json and -raw always display sensitive values in plain text . That is official, and it is an exam trap: sensitive is not an access-control system. Anyone who can run terraform output -json against the state can read the password. terraform output -raw lb_address
# my-app-alb-1657023003.us-east-1.elb.amazonaws.com
- terraform output -json instance_ips | jq -r '.[0]'
- # 54.43.114.12
Do not parse the default human-readable format in CI. HashiCorp says that format can change. -json is the contract.
Ephemeral outputs never appear in terraform output , even by name, because they were never stored in state.
- Sensitive versus ephemeral output "database_password" {
- description = "Auto-generated password for the RDS instance"
- value = aws_db_instance.main.password
- sensitive = true
- }
After apply you see database_password = (sensitive value) . terraform output lists it as <sensitive> . The state file still contains the password. Remote state consumers and anyone with backend access can read it.
ephemeral = true is the other switch. It is for short-lived tokens you must pass between modules without persisting them. Restrictions that 004 can test:
Legal only on child-module outputs. A root output cannot be ephemeral (there would be nothing left to print or to store).
The value must come from an ephemeral context (ephemeral variable, ephemeral resource, another ephemeral output, write-only-related flow).
Consumers can use it only in ephemeral contexts: another ephemeral output, a write-only argument, an ephemeral variable, provider configuration, or a provisioner.
If you need a password in the HCP Terraform UI or in terraform_remote_state , you cannot make that output ephemeral. You mark it sensitive and protect the state backend.
004 traps for outputs
value is required. An output with only description is invalid.
module.vpc.vpc_id is a child output . module.vpc.aws_vpc.this.id is not visible to the parent.
terraform output does not walk into child modules.
-raw rejects objects and lists; use -json .
sensitive does not remove the value from state. ephemeral does — and you cannot put ephemeral on a root output.
-json and -raw print secrets in clear text.