Terraform 7: The terraform{} block & provider version constraints
easy⏱ 5 mincourseterraform
The terraform{} settings block
The terraform{} block holds settings for Terraform itself — not your infrastructure. Two things live here first: required_version (which Terraform CLI versions may run this code) and required_providers (which plugins to download and from where). Each provider entry names a source (namespace/type, resolved from the public Registry) and a version constraint.
terraform {
required_version = ">= 1.5.0"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "~> 4.0"
}
random = {
source = "hashicorp/random"
version = "~> 3.6"
}
}
}
The pessimistic operator ~>
~> allows the rightmost version component to increase, and nothing to its left. ~> 4.0 means >= 4.0.0 and < 5.0.0 — you get 4.x bug fixes and features but never the breaking 5.0 jump. ~> 4.3.1 is tighter: >= 4.3.1 and < 4.4.0. Always constrain providers so a fresh terraform init can't silently pull a major release that breaks your plan.
# ~> 4.0 → >= 4.0.0, < 5.0.0 (allow 4.x)
# ~> 4.3 → >= 4.3.0, < 5.0.0 (allow 4.x, at least 4.3)
# ~> 4.3.1 → >= 4.3.1, < 4.4.0 (allow patches only)
# >= 3.2.0 → any version at or above 3.2.0 (no upper bound — risky)
The lock file pins the exact version
Your constraint is a range; terraform init then writes the exact selected version and its checksums to .terraform.lock.hcl. Commit that lock file — it guarantees teammates and CI resolve the identical provider build. Run terraform init -upgrade to move within your constraint and refresh the lock.
Model a provider requirement
Build a providerReq object with keys source ("hashicorp/azurerm") and version ("~> 4.0"). Write a function allowedRange(constraint: string) that, for a ~> X.0 constraint, returns the string ">= X.0.0, < (X+1).0.0". Log allowedRange(providerReq.version) — for ~> 4.0 it must print >= 4.0.0, < 5.0.0.