Learn whether Terraform modules need their own required_providers blocks or inherit them from the root module and best practices for managing provider dependencies.
In Terraform, modules are designed to be self-contained units of infrastructure code. To achieve this, each module must explicitly declare its provider dependencies using the required_providers block within a terraform block. This declaration specifies the source and version constraints for each provider the module relies on. This practice is crucial for several reasons.
In Terraform, every module needs to explicitly declare its provider dependencies using required_providers within a terraform block. This declaration specifies the source of the provider (e.g., "hashicorp/aws") and the acceptable version constraints.
This requirement exists because modules are meant to be self-contained units of infrastructure code. By declaring providers directly within the module, you ensure that:
It's important to note that required_providers in a child module doesn't inherit declarations from the parent module. Each module must explicitly declare its own provider requirements. This ensures that modules remain independent and portable, even if they are used in different projects with potentially different provider configurations.
If you're transitioning from Terraform 0.12 to 0.13 or later, you'll need to add required_providers blocks to your modules. This change, while requiring a bit of upfront work, ultimately leads to more robust and maintainable Terraform code.
This code demonstrates how to define required providers within a Terraform module for deploying an AWS EC2 instance. The module specifies the AWS provider source and version constraint, ensuring version compatibility and reproducibility. When using the module, it automatically downloads and uses the correct AWS provider version, regardless of the root module's provider configuration. This approach promotes module independence, portability, and consistent deployments.
Let's say you have a module for deploying an AWS EC2 instance:
modules/ec2-instance/main.tf
terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 4.0"
    }
  }
}
resource "aws_instance" "example" {
  ami           = "ami-0c94855a"
  instance_type = "t2.micro"
}Explanation:
terraform block: This block is mandatory for declaring provider requirements.required_providers block: This block specifies the providers needed by the module.
aws: The name of the provider as used within the module.source: The source address of the provider. This tells Terraform where to download the provider plugin from.version: The version constraint for the provider. This ensures compatibility and reproducibility. Here, ~> 4.0 means any version within the 4.x.x range.Using the module:
Now, you can use this module in your root module or another module:
main.tf
module "ec2_instance" {
  source = "./modules/ec2-instance"
}Benefits:
ec2-instance module will always use a compatible version of the AWS provider, preventing issues from version mismatches.ec2-instance module can be easily shared and reused in different Terraform configurations without relying on provider configurations defined elsewhere.Important Note:
Even if your root module already defines the hashicorp/aws provider, the ec2-instance module still needs its own required_providers declaration. This ensures the module remains independent and portable.
required_providers block was introduced in Terraform 0.13. If you're using an older version, you'll need to upgrade to take advantage of this feature.~> 4.0 is crucial for maintaining compatibility. It ensures that future provider updates won't break your module unless they introduce major, backward-incompatible changes.required_providers, carefully review the error messages. They often provide clues about missing or incompatible provider versions.required_providers in every module, even if it seems redundant. This promotes clarity, maintainability, and avoids potential conflicts in the future.Terraform modules must explicitly declare their provider dependencies using the required_providers block within a terraform block. This declaration specifies the provider's source and acceptable version constraints.
Here's why:
| Benefit | Description
By explicitly declaring provider dependencies within each module using required_providers, Terraform ensures version compatibility, reproducibility, and portability. This practice guarantees that modules function as intended, regardless of where they are used, making your infrastructure code more robust and maintainable.
 Providers Within Modules - Configuration Language | Terraform ... | A provider requirement says, for example, "This module requires version v2.7.0 of the provider hashicorp/aws and will refer to it as aws ." It doesn't, however, ...
 Provider Requirements - Configuration Language | Terraform ... | Each Terraform module must declare which providers it requires, so that Terraform can install and use them. Provider requirements are declared in a ...
 Using a non hashicorp provider in a module - Terraform - HashiCorp ... | I am trying to use statuscake to setup monitoring of a website. It works fine when I do this in a standalone file. However when I try to break it out into a module, it fails with an error message when I run terraform init. The error message is  Initializing modules... - statuscake in ....\modules\statuscake  Initializing the backend...  Initializing provider plugins... - Reusing previous version of statuscakedev/statuscake from the dependency lock file - Finding latest version of hashicorp/stat...
 Required_providers not being used from module source - Terraform ... | Hello.  Trying to upgrade our Jenkins deployment from 0.12 to 0.13.  This code deploys many copies of Jenkins in a Kubernetes cluster.  We wanted the config to be as DRY as possible so we are using Terragrunt.  The main module source is used by all of the instances.  I’ve added the version.tf to the module source repo  terraform {   required_providers {     kubernetes = {       source = "hashicorp/kubernetes"     }     rancher2 = {       source = "terraform-providers/rancher2"     }   }   requir...required_providers causes lookup in ... | Terraform Version Terraform v1.0.9 Terraform Configuration Files Add a new module using Cloudflare records, but "forget" (i.e., not even realize you need) to add: terraform { required_providers { c...
 Why doesn't required_providers in a child module inherit ... | In my opinion it does not make sense, why can’t the module simply inherit the required_providers config from the parent? Whit this approach we need to maintain provider versions in many places which makes it less than ideal…