Skip to main content
RunBook Academy

← All labs in Terraform

Lab · advanced · ~25 min

Lab: Using terraform output for Cross-Stack Consumption

C · Simulation

Objectives

  • Create a producer configuration with outputs
  • Create a consumer configuration that reads the producer outputs
  • Use terraform_remote_state to bridge the two configurations
  • Refactor the producer and consumer together

Prerequisites

Objective

By the end of this lab, you will have:

  • Created a producer configuration with outputs.
  • Created a consumer configuration that reads the outputs.
  • Used terraform_remote_state to bridge the two configurations.
  • Refactored the producer and consumer together.

Requirements

  • A Linux or macOS workstation with shell access.
  • The Terraform CLI 1.9.x or later installed.

Scenario

You have a producer configuration that creates a file. You have a consumer configuration that reads the files metadata. The two configurations are separate. The producers outputs are the consumers inputs.

Tasks

Task 1: Create the working directory

mkdir -p ~/rb-remote-state-lab/producer
mkdir -p ~/rb-remote-state-lab/consumer
cd ~/rb-remote-state-lab

Task 2: Create the producer configuration

Create producer/main.tf:

terraform {
  required_version = ">= 1.9.0"
  required_providers {
    local = {
      source  = "hashicorp/local"
      version = "~> 2.5"
    }
  }

  backend "local" {
    path = "terraform.tfstate"
  }
}

resource "local_file" "config" {
  filename = "${path.module}/config.yaml"
  content  = "Configuration for the project.\n"
}

output "filename" {
  value       = local_file.config.filename
  description = "The path to the configuration file."
}

output "size" {
  value       = local_file.config.content_length
  description = "The size of the configuration file in bytes."
}

Task 3: Apply the producer

cd ~/rb-remote-state-lab/producer
terraform init
terraform apply

Verify the producer:

terraform output

The output shows the filename and size.

Task 4: Create the consumer configuration

cd ~/rb-remote-state-lab/consumer

Create consumer/main.tf:

terraform {
  required_version = ">= 1.9.0"

  backend "local" {
    path = "terraform.tfstate"
  }
}

data "terraform_remote_state" "producer" {
  backend = "local"

  config = {
    path = "${path.module}/../producer/terraform.tfstate"
  }
}

output "producer_filename" {
  value       = data.terraform_remote_state.producer.outputs.filename
  description = "The filename from the producer state."
}

output "producer_size" {
  value       = data.terraform_remote_state.producer.outputs.size
  description = "The size from the producer state."
}

Task 5: Apply the consumer

cd ~/rb-remote-state-lab/consumer
terraform init
terraform apply

The consumer reads the producers outputs.

terraform output

The output shows the producers filename and size.

Task 6: Modify the producer

cd ~/rb-remote-state-lab/producer

Edit producer/main.tf to change the file content:

resource "local_file" "config" {
  filename = "${path.module}/config.yaml"
  content  = "Configuration for the project.\nversion: 1.1\n"
}

Apply:

terraform apply

The file is updated.

Task 7: Re-read the consumer

cd ~/rb-remote-state-lab/consumer
terraform apply

The consumers outputs are updated.

terraform output

The size has changed.

Task 8: Refactor the producer

Suppose the producer is renamed from config to settings.

Edit producer/main.tf:

moved {
  from = local_file.config
  to   = local_file.settings
}

resource "local_file" "settings" {
  filename = "${path.module}/config.yaml"
  content  = "Configuration for the project.\nversion: 1.1\n"
}

output "filename" {
  value       = local_file.settings.filename
  description = "The path to the configuration file."
}

output "size" {
  value       = local_file.settings.content_length
  description = "The size of the configuration file in bytes."
}

Apply:

cd ~/rb-remote-state-lab/producer
terraform apply

The state is updated. The real-world file is unchanged.

Task 9: Update the consumer

Edit consumer/main.tf to read the new resource:

output "producer_filename" {
  value       = data.terraform_remote_state.producer.outputs.filename
  description = "The filename from the producer state."
}

output "producer_size" {
  value       = data.terraform_remote_state.producer.outputs.size
  description = "The size from the producer state."
}

(The consumer does not need to change because the output names are the same.)

Apply:

cd ~/rb-remote-state-lab/consumer
terraform apply

The consumers outputs are unchanged.

Validation

The lab is successful if:

  • The producer configuration has outputs.
  • The consumer configuration reads the outputs.
  • The two configurations are wired together.
  • A refactor of the producer is reflected in the consumer.

Expected Outcome

At the end of the lab:

+---------------------------------+
| ~/rb-remote-state-lab/             |
|   producer/                       |
|   │   ├── config.yaml              |
|   │   ├── main.tf                   |
|   │   └── terraform.tfstate        |
|   consumer/                       |
|       ├── main.tf                   |
|       └── terraform.tfstate        |
+---------------------------------+

The producers outputs are consumed by the consumer. The two are wired together.

Cleanup

cd ~/rb-remote-state-lab/producer
terraform destroy
rm -rf .terraform .terraform.lock.hcl terraform.tfstate

cd ~/rb-remote-state-lab/consumer
terraform destroy
rm -rf .terraform .terraform.lock.hcl terraform.tfstate

The two configurations are the artefacts worth keeping.

What You Learned

You learned the cross-stack pattern:

  1. The producer has outputs. The outputs are the contract.
  2. The consumer reads the outputs. The consumer is wired to the producer via terraform_remote_state.
  3. A refactor of the producer is reflected in the consumer. The consumers data block is updated.
  4. The two configurations are independent. The producer can be applied without the consumer.
  5. The output names are the contract. Renaming an output breaks the consumer.

Deliverables

  • · A producer configuration with outputs
  • · A consumer configuration that reads the outputs
  • · A working cross-stack reference
  • · A refactor that updates both configurations

Verification status

Last reviewed
2026-08-12
Executed end to end
not yet run on hardware

The commands and configuration here have been reviewed against the verified software versions, but nobody has run this lab start to finish on a system meeting its prerequisites. Treat the Expected Outcome as the intended result rather than an observed one, and keep the Cleanup section to hand.