HashiCorp Certified: Terraform Associate
Provider versions and the lock file for Terraform Associate
You declare each provider in required_providers inside the terraform block, with a source address and a version constraint. terraform init picks the newest version that meets the constraint and records it, with checksums, in .terraform.lock.hcl. Later runs of init re-select the recorded version even when a newer one exists, until you run terraform init -upgrade.
required_providers
Each entry has a local name as its key and an object with source and version, for example aws = { source = "hashicorp/aws", version = "~> 5.0" }. The block must sit inside the top-level terraform block.
A source address has the form [HOSTNAME/]NAMESPACE/TYPE. The hostname is optional and defaults to registry.terraform.io, so hashicorp/aws means registry.terraform.io/hashicorp/aws. Everywhere else in the module, including provider blocks, you use the local name.
Version constraint operators
= or no operator allows one exact version. != excludes one. >, >=, < and <= compare. Conditions are joined with commas, as in ">= 1.2.0, < 2.0.0".
~> lets only the right-most version part increase. ~> 1.0.4 allows 1.0.5 and 1.0.10 but not 1.1.0. ~> 1.1 allows 1.2 and 1.10 but not 2.0. Pre-release versions such as 1.2.0-beta match only an exact = constraint.
HashiCorp's advice: reusable modules should set only a minimum, such as >= 0.12.0. Root modules should use ~> to set both a lower and an upper bound for each provider.
How the lock file decides
.terraform.lock.hcl sits in the root module directory. terraform init creates or updates it, and you should commit it so provider changes go through code review.
If a provider has no recorded selection, init picks the newest version that meets the constraints and records it. If a selection is recorded, init re-selects that version even if a newer matching one exists. For example, with 1.0.5 recorded and ~> 1.0.4 in the configuration, init installs 1.0.5 even when 1.0.10 is out. terraform init -upgrade ignores the recorded selection and takes the newest match.
Each entry records version, constraints and hashes. Terraform does not use constraints to decide anything; it is there for human readers. On install, Terraform checks the package against the recorded hashes and fails if none match.
Teams on several platforms
Providers installed from a filesystem or network mirror get checksums only for the platform where init ran, so the lock file may not work on another platform.
terraform providers lock -platform=OS_ARCH records checksums for each platform you name, and you can repeat the option. For a team on macOS that runs pipelines on Linux, add -platform=linux_amd64 alongside the macOS platform. With no arguments, the command updates the lock file for every provider the configuration uses.
Where the exam catches people
- Believing
~> 1.0.4allows 1.1.0: only the last part can increase, so 1.0.x versions from 1.0.4 up are allowed. - Believing
terraform initupgrades to a newer allowed version on its own: the recorded version wins until you runterraform init -upgrade. - Believing the lock file's
constraintsfield controls installs: Terraform keeps it only to explain the earlier choice. - Believing the lock file should stay out of version control: HashiCorp says to commit it.
- Believing a reusable module should pin providers with
~>: HashiCorp recommends only a minimum version in reusable modules.