Use non Hashicorp provider in module with for_each

I’m using the community Snowflake provider https://registry.terraform.io/providers/chanzuckerberg/snowflake/latest

I’ve created project that has a root terraform file and also a module that uses this provider e.g.

my_project
   |_
      main.tf
      modules
         |_
            my_mod
              |_
                 main.tf
   

In the root main.tf file I’ve defined these providers:

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = "~> 3.40.0"
    }
    snowflake = {
      source  = "chanzuckerberg/snowflake"
      version = "~> 0.25.12"
    }
  }

However when I run terraform init with only the above in the root module I get this error:


 Error: Failed to query available provider packages
│
│ Could not retrieve the list of available versions for provider hashicorp/snowflake: provider registry registry.terraform.io does not have a provider named
│ registry.terraform.io/hashicorp/snowflake
│
│ Did you intend to use chanzuckerberg/snowflake? If so, you must specify that source address in each module which requires that provider. To see which modules are      
│ currently depending on hashicorp/snowflake, run the following command:
│     terraform providers

It seems like because it’s not a Hashicorp provider (the source being chanzuckerberg/snowflake rather than hashicorp/snowflake) I have to specify the provider in the module itself rather than in the root and have it be inherited by the module.

So in the module (“my_mod”) main.tf file I have also defined the same provider:

terraform {
  required_providers {
    snowflake = {
      source  = "chanzuckerberg/snowflake"
      version = "~> 0.25.10"
    }
  }
}

This works fine until I try and use a for_each in the calling module block in the root main.tf, e.g.

module "my_mod" {
  source                 = "./modules/my_mod"
  for_each               = local.list_of_buckets
  s3_bucket              = "${each.key}"
}

which generates this error:

│ Error: Module module.my_mod contains provider configuration
│
│ Providers cannot be configured within modules using count, for_each or depends_on.
╵

Since I apparently must define the provider in the module itself because it’s not a Hashicorp one, does this mean there is no way to use a for_each in the calling module block in the root, or is there some other way to configure this so that the module will inherit the correct provider settings from the root?

Hi @nathan-protempo,

It is correct that each module must declare which providers it expects, but the error shown indicates that you have a provider block somewhere in the module which is not allowed.

If your module requires a specific configuration different from the root module, you can configure the provider in the root module, and pass the provider configuration into the module using the providers map within the module block.

See Providers Within Modules - Configuration Language - Terraform by HashiCorp for more details.

Thanks!

@jbardin do you have a roadmap item for fixing this bug in terraform and approximate timelines? it’s blocking the adoption of certain use-cases.

Hi @nfx,

Providers cannot be configured within a module which is expanded with count or for_each for a few reasons, but the error shown is intentional to prevent invalid configurations so there is no bug to be fixed.

If the use cases you are referring to are related allowing providers to be dynamically chosen for each specific module instance, then you can follow Dynamic provider configuration assignment · Issue #25244 · hashicorp/terraform · GitHub, and the related Instantiating Multiple Providers with a loop · Issue #19932 · hashicorp/terraform · GitHub.

I would disagree and still think it’s a fundamental weakness of Terraform DAG that has to be fixed and it must be possible to dynamically create providers from within for_each repeated modules. Thank you for linking the right issues, left a comment in github, as it gets way more attention than this forum.

Looks like they “fixed this” in 0.15.x See here:

Here’s another related one: