Terraform child module does not inherit provider from root module - terraform

My problem
I am having trouble defining the provider for my module.
Terraform fails to find the provider's plugin when I run terraform init and it shows the wrong provider for my module when I run terraform providers.
Setup
I am using Terraform version 1.3.7 on Debian 11.
Here's an example of what I am trying to do.
I have a main.tf where is my main configuration and modules. In this example I use a single module for creating a docker container.
.
├── main.tf
└── modules/
└── container_module/
└── main.tf
In the root module project/main.tf file, I define the provider and call the module:
terraform {
required_providers {
docker = {
source = "kreuzwerker/docker"
version = "3.0.1"
}
}
}
provider "docker" {
host = "unix:///var/run/docker.sock"
}
module "container" {
source = "./modules/container_module"
}
In the modules/container_module/main.tf, I create the docker container resource:
resource "docker_image" "debian" {
name = "debian:latest"
}
resource "docker_container" "foo" {
image = docker_image.debian.image_id
name = "foo"
}
What I expect to happen
When I run terraform init, it should download the provider's plugin from kreuzwerker/docker.
What actually happens
Instead, terraform downloads the plugin from kreuzwerker/docker once, then attempt to download it again from hashicorp/docker.
Here's the command's output:
terraform init
Initializing modules...
- container in modules/container_module
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/docker...
- Finding kreuzwerker/docker versions matching "3.0.1"...
- Installing kreuzwerker/docker v3.0.1...
- Installed kreuzwerker/docker v3.0.1 (self-signed, key ID BD080C4571C6104C)
Partner and community providers are signed by their developers.
If you'd like to know more about provider signing, you can read about it here:
https://www.terraform.io/docs/cli/plugins/signing.html
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/docker: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/docker
│
│ Did you intend to use kreuzwerker/docker? If so, you must specify that source address in each module which requires that provider. To see which modules are currently depending on
│ hashicorp/docker, run the following command:
│ terraform providers
╵
When I run terraform providers I get two different sources depending on the file:
terraform providers
Providers required by configuration:
.
├── provider[registry.terraform.io/kreuzwerker/docker] 3.0.1
└── module.container
└── provider[registry.terraform.io/hashicorp/docker]
According to the documentation, the child modules should inherit the provider from their parent:
Default Behavior: Inherit Default Providers:
If the child module does not declare any configuration aliases, the providers argument is optional. If you omit it, a child module inherits all of the default provider configurations from its parent module. (Default provider configurations are ones that don't use the alias argument.)
I have already checked this
Do terraform modules need required_providers?
This answer confirms the provider inheritence.
Terraform provider's resources not available in other tf files:
This question didn't help.
Terraform, providers miss inherits on module
This answer to this similar question says that I should add required_providers in the child module, but it is for an older version and it contradicts what I saw elsewhere.
I have the same issue when I create a providers.tf file in the root directory.
My question
How should I declare my provider so that the child module can inherit the provider from the root module?

kreuzwerker/docker is not a hashicorp provider. Thus as explained here, you have to explicitly define required_providers in each module, as such providers are not inherited.

Related

Terraform: remote module not following providers block - Warning: Reference to undefined provider

I'm trying to use a (private) remote terraform module, and trying to pass a different provider to it. For the remote module, there are no providers defined and to my understanding, it will use a the local provider instead.
I can't seem to be able to get it to use a provider alias - there are a few files at play here:
# main.tf
provider "aws" {
region = var.aws_region
}
provider "aws" {
alias = "replica_region"
region = var.replica_region
}
terraform {
backend "s3" {
}
}
# s3.tf
module "some-remote-module" {
source = 'git::ssh.......'
providers = {
aws = aws.replica_region
}
}
Whenever I plan (with terragrunt), The region is that of the primary aws provider config. I get the following warning, too:
│ Warning: Reference to undefined provider
│
│ on s3.tf line 12, in module "some-remote-module":
│ 12: aws = aws.replica_region
│
│ There is no explicit declaration for local provider name "aws" in
│ module.some-remote-module, so Terraform is assuming you
│ mean to pass a configuration for "hashicorp/aws".
│
│ If you also control the child module, add a required_providers entry named
│ "aws" with the source address "hashicorp/aws".
╵
Am I passing the providers in incorrectly? Is this even something that terraform is capable of? I'm using terraform 1.3. The remote module doesn't have any provider config.
The last paragraph of this message is suggesting that you modify the child module to include the following declaration so that it's explicit that when you say "aws" it means hashicorp/aws rather than a provider in some other namespace that might coincidentally also be called "aws":
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
}
}
}
This is what the error message means by a required_providers entry named "aws" with the source address "hashicorp/aws".
This allows Terraform to see for certain (rather than guessing) that the short name "aws" refers to the same provider in both the calling module and the called module.

Did you intend to use mongodb/mongodbatlas? If so, you must specify that │ source address in each module which requires that provider

I have below in my provider.tf in the root directory
terraform {
required_version = ">= 1.0.5"
required_providers {
azurerm = {
source = "hashicorp/azurerm"
version = "= 3.8.0"
}
mongodbatlas = {
source = "mongodb/mongodbatlas"
}
}
}
I am getting below error in terraform init stage
Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider
│ hashicorp/mongodbatlas: provider registry registry.terraform.io does not
│ have a provider named registry.terraform.io/hashicorp/mongodbatlas
│
│ Did you intend to use mongodb/mongodbatlas? If so, you must specify that
│ source address in each module which requires that provider. To see which
│ modules are currently depending on hashicorp/mongodbatlas, run the
│ following command:
│ terraform providers
After this error, I included below in my mongodb atlas child module too which needed it and it worked.
terraform {
required_providers {
mongodbatlas = {
source = "mongodb/mongodbatlas"
}
}
}
My question is why do I need to do this? I don't have to do it for any other required providers? Thanks in advance.
similar question is answered here - Terraform using both required_providers and provider blocks
gist - if the provider you are using is not one of the official provider by Terraform then you need to specify the terraform required_providers block to let terraform know the source to download the provider plugin.
LIST OF OFFICIAL PROVIDERS BY TERRAFORM -
https://registry.terraform.io/browse/providers?category=database%2Chashicorp%2Cinfrastructure-management%2Cpublic-cloud%2Casset%2Ccloud-automation%2Ccommunication-messaging%2Cvcs%2Cutility%2Cweb%2Csecurity-authentication%2Cplatform%2Clogging-monitoring%2Cnetworking%2Cinfrastructure%2Cdata-management%2Cci-cd%2Ccontainer-orchestration&tier=official
Just for visitors who are having the same error, follow the instructions
Check the message:
Did you intend to use mongodb/mongodbatlas? If so, you must specify
that source address in each module which requires that provider.
You need to put your MongoDB provider inside each module you're using.
Run terraform providers and check which modules require MongoDB.
Create a versions.tf file inside each module.
Add the following code (with your desired version):
terraform {
required_providers {
mongodbatlas = {
source = "mongodb/mongodbatlas",
version = "1.8.0"
}
}
}
About the need to put required_providers inside each module
Testing Atlas Provider Versions that are NOT hosted on Terraform Registry (i.e. pre-release versions)
To test development / pre-release versions of the Terraform Atlas
Provider that are not hosted on the Terraform Registry, you will need
to create a Terraform Provider Network Mirror.
The provider network mirror protocol is an optional protocol which you
can implement to provide an alternative installation source for
Terraform providers, regardless of their origin registries. Terraform
uses network mirrors only if you activate them explicitly in the CLI
configuration's provider_installation block. When enabled, a network
mirror can serve providers belonging to any registry hostname, which
can allow an organization to serve all of the Terraform providers they
intend to use from an internal server, rather than from each
provider's origin registry.
source: https://github.com/mongodb/terraform-provider-mongodbatlas

terraform init vsphere provider - Failed to query available provider packages vmsphere

terraform v1.0.3 installed via brew on Mac OS
It's my first time using Terraform with a "vshpere" provider. When I do a terraform init on my plan, I get the following error.
provider "vsphere" {
user = var.vsphere_user
password = var.vsphere_password
vsphere_server = var.vsphere_server
}
module "exa_v30_01" {
source = "../modules/vm"
vsphere_user = var.vsphere_user
vsphere_password = var.vsphere_password
template_name = var.template_name
vm_name = var.vm_name
}
$ terraform init
Initializing modules...
Initializing the backend...
Initializing provider plugins...
- Finding latest version of hashicorp/vsphere...
- Finding latest version of hashicorp/vmsphere...
- Installing hashicorp/vsphere v2.0.2...
- Installed hashicorp/vsphere v2.0.2 (signed by HashiCorp)
╷
│ Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider
│ hashicorp/vmsphere: provider registry registry.terraform.io does
│ not have a provider named registry.terraform.io/hashicorp/vmsphere
│
│ All modules should specify their required_providers so that
│ external consumers will get the correct providers when using a
│ module. To see which modules are currently depending on
│ hashicorp/vmsphere, run the following command:
│ terraform providers
╵
$ terraform providers
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/vsphere]
└── module.exa_v30_01
├── provider[registry.terraform.io/hashicorp/vsphere]
└── provider[registry.terraform.io/hashicorp/vmsphere]
How do I solve this? I googled and searched here, but nothing relating to VSphpere. Any clues? Thanks
UPDATE:
I see Force Terraform to install providers from local disk only, disabling Terraform Registry, but that's for a terraform version upgrade.
The error message is correct. There is not provider called vmsphere. Maybe you wanted vsphere provider? Your module exa_v30_01 seems to be using wrong providers somewhere.

upgrade from 0.12 to 0.13: Failed to instantiate provider "registry.terraform.io/-/aws" to obtain

I'm trying to upgrade from terraform 0.12 to 0.13.
it seems to have no specific problem of syntax when I run terraform 0.13upgrade nothing is changed.
only a file version.tf is added
+terraform {
+ required_providers {
+ aws = {
+ source = "hashicorp/aws"
+ }
+ }
+ required_version = ">= 0.13"
+}
and when I run terraform plan I got
Error: Could not load plugin
Plugin reinitialization required. Please run "terraform init".
Plugins are external binaries that Terraform uses to access and manipulate
resources. The configuration provided requires plugins which can't be located,
don't satisfy the version constraints, or are otherwise incompatible.
Terraform automatically discovers provider requirements from your
configuration, including providers used in child modules. To see the
requirements and constraints, run "terraform providers".
2 problems:
- Failed to instantiate provider "registry.terraform.io/-/aws" to obtain
schema: unknown provider "registry.terraform.io/-/aws"
- Failed to instantiate provider "registry.terraform.io/-/template" to obtain
schema: unknown provider "registry.terraform.io/-/template"
running terraform providers shows
Providers required by configuration:
.
├── provider[registry.terraform.io/hashicorp/aws]
├── module.bastion
│   ├── provider[registry.terraform.io/hashicorp/template]
│   └── provider[registry.terraform.io/hashicorp/aws]
└── module.vpc
└── provider[registry.terraform.io/hashicorp/aws] >= 2.68.*
Providers required by state:
provider[registry.terraform.io/-/aws]
provider[registry.terraform.io/-/template]
So my guess is form some reason I have -/aws instead of hashicorp/aws in my tfstate, however I can't find this specific string at all in the tfstate.
I tried:
running terraform init
terraform init -reconfigure
deleting the .terraform folder
deleting the ~/.terraform.d folder
So I'm running out of ideas on how to solve this problem
I followed the steps here
terraform state replace-provider registry.terraform.io/-/template registry.terraform.io/hashicorp/template
terraform state replace-provider registry.terraform.io/-/aws registry.terraform.io/hashicorp/aws
and it fixed my problem.

Configured provider not recognized inside module

I am working on a Terraform configuration for a new project. The project consists of multiple microservices for which I've written modules. The project is supposed to be hosted on Digitalocean, so I installed the Terraform DigitalOcean Provider as a required provider:
# ./versions.tf
terraform {
required_version = ">= 0.14"
required_providers {
digitalocean = {
source = "digitalocean/digitalocean"
version = "2.3.0"
}
}
}
which is then 'initialized' in ./main.tf:
provider "digitalocean" {
token = var.do_token
}
However, when I try to run terraform init it fails because of error Error: Failed to query available provider packages.
terraform providers reveals that this happens because a module tries to require provider hashicorp/digitalocean instead of digitalocean/digitalocean:
├── provider[registry.terraform.io/digitalocean/digitalocean] 2.3.0
├── provider[registry.terraform.io/hashicorp/kubernetes] 1.13.3
├── provider[registry.terraform.io/hashicorp/kubernetes-alpha] 0.2.1
└── module.spaces
└── provider[registry.terraform.io/hashicorp/digitalocean]
I have tried to pass a the provider through the providers option in the module, but that didn't seem to make a difference:
module "spaces" {
source = "./Spaces"
providers = {
digitalocean = digitalocean
}
}
Is this a bug within Terraform 0.14 perhaps, or am I just misunderstanding?
Thanks.
It's failing when it's used in a submodule because you only have the required_providers configuration at the top level, you need to add it in each module.
This is explained in detail in this thread
The provider source needs to be declared in each module because an
interesting side effect of the provider source work is that we can now
use multiple providers with the same name in configuration. Each
module could use a provider named 'dns' with a different source.
Internally, terraform uses the source to create a FQN (fully-qualified
name) for each provider, so you could have for example three modules,
each using one of "mildwonkey/dns" "hashicorp/dns" and "yourname/dns".

Resources