Expressions and References
So far every value has been a fixed string or number. Real configurations connect things: the bucket policy must point at the bucket, and the bucket name should include the environment. HCL does this with expressions.
The rule
Refer by address, never by copy; the reference sets the order.
An expression is anything that produces a value. The most important kind is a reference to something else in the configuration:
| You want | Address |
|---|---|
| an input variable | var.environment |
| a local value | local.name_prefix |
| a resource attribute | aws_s3_bucket.assets.arn |
| a data source attribute | data.aws_caller_identity.current.account_id |
A resource address is type.name.attribute. Some attributes, like arn and id, are only known after the cloud creates the object; the plan shows them as (known after apply).
resource "aws_s3_bucket" "assets" {
bucket = "crumb-${var.environment}-assets"
}
resource "aws_s3_bucket_versioning" "assets" {
bucket = aws_s3_bucket.assets.id
versioning_configuration {
status = "Enabled"
}
}Two expression tools appear here:
- Interpolation —
"crumb-${var.environment}-assets"places a value inside a string. - A reference —
aws_s3_bucket.assets.idreads the bucket's ID.
Because the versioning resource refers to the bucket, Terraform knows the bucket must be created first. This is an implicit dependency, and it is how Terraform orders most work.
Other expressions you will meet: arithmetic (2 * 10), comparisons (var.environment == "prod"), the conditional condition ? a : b, and built-in functions such as upper("crumb") or length(var.zones). You cannot write your own functions. terraform console lets you try expressions interactively.
The shortcut
Whenever you are about to type a value that already exists elsewhere, stop and write its address instead. Then read the address right to left: attribute, of the resource named, of the type.
Spot the repeat
The bucket name should contain the environment, which is already the variable
environment.
The trap: copying the literal bucket name into the second resource. It works once, then breaks when the name changes, and Terraform loses the dependency.
Drills
Answer fast — trust the rule.
How do you refer to the input variable environment?
What does aws_s3_bucket.assets.arn read?
If var.environment is "prod", what is "crumb-${var.environment}-assets"?
Resource B contains bucket = aws_s3_bucket.assets.id. What does Terraform conclude?
What does var.environment == "prod" ? "t3.small" : "t3.micro" give when environment is "dev"?
Remember
- References:
var.x,local.x,type.name.attr,data.type.name.attr. - Shortcut: never retype a value that has an address; the reference also sets build order.
- Trap: copied literals hide dependencies and drift apart.
