Cloud  /  Terraform

IaC Terraform 50 guides · updated 2026

Infrastructure as code done right — providers, state, reusable modules, and the workflow patterns that keep multi-cloud deployments sane in 2026.

terraform console

terraform console opens an interactive REPL (Read-Eval-Print Loop) where you can evaluate HCL expressions, test built-in functions, inspect variables, and query the current state — all without modifying anything. It’s Terraform’s built-in debugging tool.


Opening the Console

Terminal window
terraform console

The console loads the current working directory’s configuration and state. You’ll see a > prompt where you can type expressions.

Terminal window
$ terraform console
>

Exit with Ctrl+C or type exit.


Testing Built-in Functions

The console is the fastest way to verify function behavior before embedding it in configuration:

# String functions
> upper("hello world")
"HELLO WORLD"
> replace("hello-world-2025", "-", "_")
"hello_world_2025"
> format("%-20s %5d", "resource-name", 42)
"resource-name 42"
> trimspace(" padded string ")
"padded string"
> split(",", "us-east-1,us-west-2,eu-west-1")
tolist([
"us-east-1",
"us-west-2",
"eu-west-1",
])
# Numeric functions
> max(10, 20, 5, 30, 15)
30
> min(10, 20, 5)
5
> ceil(2.1)
3
> floor(2.9)
2
> abs(-42)
42
# List and collection functions
> length(["a", "b", "c", "d"])
4
> contains(["dev", "staging", "prod"], "prod")
true
> distinct(["a", "b", "a", "c", "b"])
tolist([
"a",
"b",
"c",
])
> flatten([["a", "b"], ["c"], ["d", "e"]])
tolist([
"a",
"b",
"c",
"d",
"e",
])
> index(["a", "b", "c"], "b")
1

CIDR and Networking Functions

Essential for infrastructure engineers working with VPC design:

> cidrsubnet("10.0.0.0/16", 8, 0)
"10.0.0.0/24"
> cidrsubnet("10.0.0.0/16", 8, 1)
"10.0.1.0/24"
> cidrsubnet("10.0.0.0/16", 8, 255)
"10.0.255.0/24"
# Generate multiple subnets
> [for i in range(4) : cidrsubnet("10.0.0.0/16", 8, i)]
tolist([
"10.0.0.0/24",
"10.0.1.0/24",
"10.0.2.0/24",
"10.0.3.0/24",
])
> cidrhost("10.0.1.0/24", 5)
"10.0.1.5"
> cidrnetmask("10.0.0.0/16")
"255.255.0.0"

Testing Variables and Locals

With configuration loaded, inspect variable values and local computations:

# In your config: variable "environment" { default = "staging" }
> var.environment
"staging"
# Local computed values
> local.name_prefix
"staging-myapp"
> local.common_tags
tomap({
"Environment" = "staging"
"ManagedBy" = "terraform"
"Team" = "platform"
})

Querying State

The console can access resources already in state:

# Read a provisioned resource's attributes
> aws_vpc.main.id
"vpc-0abc123def456789"
> aws_vpc.main.cidr_block
"10.0.0.0/16"
# Reference a count-based resource by index
> aws_instance.app[0].private_ip
"10.0.1.45"
# Reference a for_each resource by key
> aws_subnet.public["a"].id
"subnet-0abc123"

Testing For Expressions and Conditionals

# For expressions with conditions
> [for n in range(10) : n if n % 2 == 0]
tolist([
0,
2,
4,
6,
8,
])
# Map transformation
> {for k, v in {"a" = 1, "b" = 2, "c" = 3} : k => v * 10}
tomap({
"a" = 10
"b" = 20
"c" = 30
})
# Conditional expression
> var.environment == "production" ? "t3.large" : "t3.micro"
"t3.micro" # (when environment is "staging")

Encoding and Cryptographic Functions

> base64encode("Hello, Terraform!")
"SGVsbG8sIFRlcnJhZm9ybSE="
> base64decode("SGVsbG8sIFRlcnJhZm9ybSE=")
"Hello, Terraform!"
> jsonencode({"key" = "value", "count" = 3})
"{\"count\":3,\"key\":\"value\"}"
> jsondecode("{\"name\":\"terraform\",\"version\":\"1.8\"}")
tomap({
"name" = "terraform"
"version" = "1.8"
})
# File hash — useful for triggering resource updates on file changes
> filesha256("scripts/init.sh")
"abc123def456..."

Practical Debugging Session

# You want to compute names for 3 availability zones
> [for i, az in ["us-east-1a", "us-east-1b", "us-east-1c"] : "subnet-public-${i+1}-${az}"]
tolist([
"subnet-public-1-us-east-1a",
"subnet-public-2-us-east-1b",
"subnet-public-3-us-east-1c",
])
# Verify your tag merge logic
> merge({"Environment" = "prod"}, {"Team" = "platform"}, {"CostCenter" = "eng-42"})
tomap({
"CostCenter" = "eng-42"
"Environment" = "prod"
"Team" = "platform"
})
# Test regex before using it in a resource
> can(regex("^[a-z][a-z0-9-]{2,62}[a-z0-9]$", "my-bucket-name"))
true
> can(regex("^[a-z][a-z0-9-]{2,62}[a-z0-9]$", "MY-BUCKET"))
false

The console saves significant time — test expressions interactively here instead of making code changes, running plan, and checking for errors repeatedly.