Terraform / Language, providers, and managed identity / Lesson 2
HCL structure, values, and expressions
Read blocks and typed expressions without treating interpolation or implicit conversion as a substitute for a clear data model.
On this page
Lesson goals
- Identify blocks, arguments, collections, and expression references.
- Reason about null, empty values, types, and deterministic transformations.
Blocks and arguments describe different structure
HCL uses blocks to represent constructs such as resources and variables, and arguments to assign expressions to named settings. Labels identify particular blocks according to the surrounding schema. Braces can also construct objects inside expressions, so not every brace-delimited form is a resource block. The provider and Terraform language together determine which arguments and nested blocks are accepted. Familiar syntax therefore does not prove that an invented field belongs to a resource. Read the applicable schema instead of guessing names from another tool.
Keep values typed and transformations explicit
Strings, numbers, booleans, collections, objects, and null carry different meanings. A list preserves ordering and can contain repeated values; a set represents unique members without a meaningful user-defined order. A map associates string keys with values, while an object can describe attributes with different types. Choose the structure that matches the contract. Converting everything to strings can hide validation errors and produce surprising provider behavior. A conditional expression also needs compatible result types rather than arbitrary unrelated branches.
terraform {
required_version = ">= 1.16.0, < 1.17.0"
}
locals {
prefix = "atlas"
services = ["api", "worker"]
labels = { for name in local.services : name => "${local.prefix}-${name}" }
}
output "labels" {
value = local.labels
}
The expression constructs api -> atlas-api and worker -> atlas-worker. The output is a map, not two resources. The keys are explicit service identities; no provider or execution result is required to reason about this fixed expression.
Null is not an empty string or empty collection
Null commonly represents omission or absence in a configuration contract, whereas an empty string is a supplied string and an empty collection is a supplied collection with zero elements. Providers and variable declarations can distinguish those cases. Optional object attributes and defaults add further rules that should be documented. Do not replace a missing required value with empty text merely to silence a type error. Decide whether absence is valid, whether a default applies, and whether the receiving resource permits omission.
Mirror only the declared expression in an offline model
The Python example below mirrors one fixed collection transformation. It is useful for checking the teaching result, but Python and Terraform have different type systems, evaluation rules, unknown values, and collection conversions. A passing Python calculation cannot validate arbitrary HCL. Keep that distinction explicit whenever an offline model is used later in the course. The objective is to make expected values inspectable while avoiding any provider initialization, workspace access, backend connection, or infrastructure operation.
prefix = 'atlas'
services = ['api', 'worker']
labels = {name: f'{prefix}-{name}' for name in services}
for key in sorted(labels):
print(f'{key}={labels[key]}')
api=atlas-api
worker=atlas-worker
Sorted keys make the display order explicit: api then worker. That sorting belongs to the demonstration, not a promise of Terraform map iteration as a deployment sequence. No resource instances are created.
Readable expressions make review more reliable
Use locals to name a repeated transformation when the name clarifies its meaning. Avoid a single enormous expression that mixes defaults, identity selection, and provider arguments beyond easy review. Preserve stable keys separately from display labels, and test null, empty, duplicate, and boundary cases in the contract. Formatting helps humans see structure but does not check provider schemas or runtime effects. This course can inspect text and run small offline models; it does not claim Terraform validation when the CLI and required dependencies are unavailable.
Common errors and fixes
Unsupported argument.
- Why it happens
- An argument name was invented or borrowed from another resource schema.
- How to fix it
- Check the exact resource and provider-version documentation for accepted structure.
- Prevent it next time
- Review schema changes independently from HCL punctuation and indentation.
Null and empty text are treated as identical.
- Why it happens
- Absence and an explicitly supplied string were collapsed into one case.
- How to fix it
- Define absence and default behavior at the variable and resource boundaries.
- Prevent it next time
- Test missing, null, empty, and ordinary values separately.
A collection conversion removes meaningful duplicates.
- Why it happens
- A list was converted to a set without reviewing identity semantics.
- How to fix it
- Retain the appropriate ordered or keyed structure for the actual contract.
- Prevent it next time
- Document whether order and duplicates have business meaning.
Check your understanding
1. How many resources does the labels output declare?
Show worked solution
None. It computes a map from two strings, producing two entries. Values and resource instances are different concepts. A later resource can consume this map, but a for expression alone does not request object creation or automatically assign managed identities.
2. Why might an empty string be a poor fallback for a missing object id?
Show worked solution
It supplies an apparently typed string without a valid identity and can defer the failure to a less clear provider error. Decide whether null is permitted, require a nonempty validated id when necessary, or redesign the dependency so the correct identity is referenced explicitly.
Key takeaways
- Choose collection structure from identity and ordering requirements.
- Formatting and offline arithmetic do not replace Terraform schema validation.