Terraform / Language, providers, and managed identity / Lesson 4
Provider requirements, versions, and the lock file
Keep Terraform CLI compatibility, provider selection, provider configuration, and dependency integrity as separate decisions.
On this page
Lesson goals
- Explain source addresses, local names, constraints, and selected versions.
- Distinguish provider locking from module version selection.
Terraform and providers have independent versions
required_version constrains the Terraform CLI itself. required_providers identifies provider source addresses and acceptable plugin versions. A provider block configures a selected provider’s settings; it does not replace its source declaration. These version numbers do not need to match. A language feature can depend on the CLI version while a resource argument depends on the provider version. Diagnose the appropriate boundary before upgrading everything or attributing a schema error to HCL syntax. This course targets the documented Terraform 1.16 family and excludes prerelease 1.17 assumptions.
Declare origin and acceptable range explicitly
The example declares the official Random provider as an illustrative external dependency and also includes built-in terraform_data. The Random range is a teaching constraint, not a claim that this course installed or integration-tested those provider releases. There is no real credential or target API configuration. The built-in Terraform provider does not need an external requirement. Do not invent lock-file checksums: actual selected package identities must come from the supported dependency workflow in an independently approved environment.
terraform {
required_version = ">= 1.16.0, < 1.17.0"
required_providers {
random = {
source = "hashicorp/random"
version = "~> 3.7.0"
}
}
}
resource "terraform_data" "catalog" {
input = "atlas-lab"
}
The CLI range accepts the 1.16 family. The provider constraint allows 3.7 patch releases below 3.8.0. Merely declaring an unused provider does not install it in this lesson. No initialization or registry download is performed.
A constraint is not a selected package
A constraint describes permitted versions. The dependency lock file records selected provider versions and package checksums for the configuration, supporting repeatable installation and integrity checks. Review lock-file changes as part of dependency updates rather than deleting the file when selection becomes inconvenient. Its constraints field explains selection context but is not a substitute for the configuration’s requirements. A checksum match establishes package integrity against trusted recorded evidence; it does not prove that the provider behavior is safe for every proposed resource change.
Read pessimistic constraints at the right precision
The number of components after ~> changes the allowed range. For stable versions, ~>3.7.0 permits 3.7.x but not 3.8.0; ~>3.7 permits later 3.x versions below 4.0.0. The following tuple comparison models only the first stated stable range. It is not a complete semantic-version parser and does not handle prereleases. When several modules require one provider source, their constraints must admit a compatible common selection. Making each module independently demand an incompatible exact version cannot create several versions under one source in the same configuration.
lower, upper = (3, 7, 0), (3, 8, 0)
for version in ((3, 7, 0), (3, 7, 2), (3, 8, 0), (4, 0, 0)):
text = '.'.join(map(str, version))
print(f'{text}: {lower <= version < upper}')
3.7.0: True
3.7.2: True
3.8.0: False
4.0.0: False
Only 3.7.0 and 3.7.2 satisfy this simplified interval. The example neither queries a registry nor verifies that a package is installed. Real Terraform constraint syntax and prerelease selection remain governed by the official language rules.
Module versions need their own reproducibility contract
The provider lock file does not lock remote module versions. A module source and its version or immutable revision need a separate review strategy. Provider aliases represent multiple configurations of one provider, not independent plugin version selections. Reusable modules should declare their requirements and let callers supply intended configurations where appropriate. Record CLI, providers, modules, and execution platform together, then test upgrades deliberately. A provider upgrade can alter a plan even when the application configuration text did not otherwise change.
Common errors and fixes
Failed to query available provider packages.
- Why it happens
- Source, constraints, registry access, or the approved installation path may be wrong.
- How to fix it
- Inspect the declared dependency context without disabling integrity checks or guessing a source.
- Prevent it next time
- Review origins and compatible ranges before dependency changes.
The lock file is assumed to freeze module versions.
- Why it happens
- Provider selection storage was generalized to a different dependency class.
- How to fix it
- Specify and review module versions or immutable revisions separately.
- Prevent it next time
- Track every dependency class in release evidence.
A provider alias is used to request another plugin version.
- Why it happens
- Configuration instances were confused with source-level version selection.
- How to fix it
- Use aliases for supported configuration differences and resolve one compatible provider version.
- Prevent it next time
- Separate provider source, version, and configuration in design reviews.
Check your understanding
1. Would ~>3.7 accept 3.8.0 while ~>3.7.0 rejects it?
Show worked solution
Yes for the stated stable-version rules. The shorter constraint allows compatible 3.x updates, while the three-component constraint limits selection to the 3.7 patch series. Choose the range from known compatibility and the root configuration’s update policy, not from an assumption that more permissive always means better.
2. Does the required_version block pin the Random provider?
Show worked solution
No. It constrains Terraform CLI versions. The required_providers entry constrains the Random plugin, and the lock file records an actual selected provider package version and integrity evidence. Each mechanism serves a separate boundary; mixing them makes dependency failures difficult to diagnose.
Key takeaways
- Constrain CLI, provider, and module dependencies independently.
- Review real lock evidence instead of inventing or discarding checksums.