Skip to main content

Terraform Language & Terms

Configurations and the HashiCorp language

Exam guide§2.4

A configuration is a complete document in the Terraform language that tells Terraform how to manage a collection of infrastructure. You author it in the Author phase of the workflow as one or more files with a .tf extension.

Directory structure

A configuration lives in a directory that can hold multiple files and subdirectories. It consists of a root module plus an optional tree of child modules. You can put every resource in a single root file, but the best practice is to split files logically.

-- main.tf-- servers/-- main.tf-- providers.tf-- variables.tf-- outputs.tf-- terraform.tfvarsRoot moduleChild module
A Terraform configuration: the root module (the working directory Terraform runs in) plus an optional tree of child modules.
FactsWhat each file holds
  • main.tf - the root module (root configuration); the entry point.
  • child modules - zero or more, factored into their own subdirectories.
  • variables.tf - input variables (optional but recommended).
  • outputs.tf - values surfaced after apply (optional but recommended).
  • terraform.tfvars - values assigned to those variables (optional but recommended).
GotchaThe root module is the working directory

The root module is the directory you run terraform commands in. Terraform picks up every .tf file in that directory (not just main.tf) and uses them together to build the plan and the infrastructure. Child modules are optional - a valid configuration can be a single root module.

HashiCorp Configuration Language (HCL)

Configurations are written in HCL - a JSON-based variant that is both human- and machine-friendly. HCL creates and manages API-based resources (virtual machines, storage buckets, containers, networks), defines the dependencies between them, and declares the data to fetch.

GotchaHCL is a configuration language, not a programming one

Despite the resemblance, HCL has no traditional statements or control loops. It exposes a limited set of primitives - variables, resources, outputs, modules - and expresses logic only through assignments, count, and interpolation functions. Its simplicity is the point: it keeps Terraform approachable.

Syntax anatomy

Generic block, then a concrete google_compute_network resource:

<BLOCK TYPE> "<BLOCK LABEL>" "<BLOCK LABEL>" {
# Block body
<IDENTIFIER> = <EXPRESSION> # Argument
}
resource "google_compute_network" "default" {
# custom mode network definition
name = "mynetwork"
auto_create_subnetworks = false
}
ConstructWhat it is
BlockLines belonging to a type (resource, variable, output); can be simple or nested inside another block
ArgumentAssigns a value to a name inside a block; some are mandatory, others optional
IdentifierThe name of an argument, block type, or construct. Letters, underscores, hyphens, digits - cannot start with a digit
ExpressionThe value assigned to an identifier; simple or complex
CommentStarts with # for a single line
GotchaDeclarative: order does not matter

HCL is declarative - you define the end state of the infrastructure, not the steps to reach it. As a result, the order of blocks or files is irrelevant; Terraform works out the dependency order itself.

Author-phase terms and concepts

Exam guide§2.4

While authoring a configuration, you work with a small vocabulary of building blocks: resources, providers, variables, outputs, state, and modules. Each maps to a .tf file or block you write by hand.

Resources

A resource is a code block that defines an infrastructure component - the keyword resource, a resource type, and a name you choose. Resources are the core building block, with their own page covering meta-arguments (count, for_each) and dependencies between resources.

Providers

Providers implement every resource type - without a provider, Terraform can manage no infrastructure. They expose a service's APIs as Terraform resources and manage the interactions. You declare them in the terraform block (by convention in providers.tf), and Terraform downloads the provider plugin into the root configuration on init.

terraform {
required_providers {
google = {
source = "hashicorp/google"
version = "4.23.0"
}
}
}
 
provider "google" {
# configuration options
project = "<project_id>"
region = "us-central1"
}

The source is the global source address on the Terraform Registry (hashicorp/google); google is the provider's local name, which must also appear in required_providers. Arguments like project and region are specific to the Google provider. Provider configuration belongs in the root module.

GotchaPin the provider version to avoid surprise breaking changes

The version argument is optional but recommended: it constrains the provider to a specific version or range so a new release with breaking changes cannot slip in. If you omit it, Terraform downloads the most recent provider during init. Likewise, if you include no provider block at all, Terraform assumes an empty default configuration.

Variables

Input variables parameterize your configuration - they let you customize and share it without altering the source code, supplying values at run time via CLI options, environment variables, or a .tfvars file. See their own page for types, defaults, precedence, and best practices.

Outputs

Output values expose information from the resources Terraform manages - a bucket URL, an instance IP - so it can be surfaced after apply or consumed by other configurations. See their own page.

State

Terraform records the state of the resources it manages in a state file (terraform.tfstate). By default it is stored locally, but it can also be stored remotely - the preferred method when working in a team.

GotchaNever touch the state file by hand

The state file is created and updated automatically - do not modify or edit it. State is covered in detail on its own page.

Modules

A module is a set of Terraform configuration files in a single directory - even one directory with a single .tf file counts as a module. Modules are the primary method for code reuse in Terraform: you reuse one by specifying its source, which can be local (a directory in your config) or remote (an upstream module from the HashiCorp module registry, or your own). Modules have their own page.