Provider registry registry.terraform.io does not have a provider named registry.terraform.io/hashicorp/each

I have two files main.tf and a variables.tf

when running ‘terraform apply’ i receive a
Error: Failed to query available provider packages

Could not retrieve the list of available versions for provider hashicorp/each:
provider registry registry.terraform.io does not have a provider named
registry.terraform.io/hashicorp/each

If you have just upgraded directly from Terraform v0.12 to Terraform v0.14
then please upgrade to Terraform v0.13 first and follow the upgrade guide for
that release, which might help you address this problem.

main.tf

provider “aws” {
region = “us-west-2”
}

provider “aws” {
region = “us-west-1”
alias = “us-west-1”
}

resource “aws_ecs_cluster” “foo” {
name = “my-tf-cluster”
for_each = toset(var.regions)
provider = each.value
}

resource “aws_vpc” “my_vpc” {
cidr_block = “172.16.0.0/16”
provider = aws.us-west-1

tags = {
Name = “tf-example”
}
}

Hi @anderson.t.giang,

each.value is not a valid provider reference, so Terraform is understanding it as a reference to a provider called “each”, in the same way as it understands provider = aws.us-west-1 as a reference to a provider called “aws”.

What you are trying to do here isn’t possible today: the relationship between a resource and its provider configuration is a static thing Terraform must determine before it starts doing any normal expression evaluation, because it dictates the graph walk order (each resource depends on its provider configuration). Instead, you’ll need to write two separate aws_ecs_cluster resources that each have a different provider argument.

1 Like

thanks for the quick reply. is there a better way to deploy the same resource in multiple regions instead of writing two separate cluster resources.

Unfortunately for this provider region is a per-provider-configuration setting rather than a per-resource setting (which is in turn due to the design of the underlying AWS APIs) and so I don’t know of any way to avoid writing a separate set of resources per region.

If you have multiple objects to declare per region then one way to reduce the duplication is to factor out the per-region objects into a child module and then call that module multiple times with different provider configurations, like this:

provider “aws” {
  alias = “us-west-2”

  region = “us-west-2”
}

provider “aws” {
  alias = “us-west-1”

  region = “us-west-1”
}

module "us-west-2" {
  source = "./modules/per-region"
  providers = {
    aws = aws.us-west-2
  }

  # (region-specific module arguments)
}

module "us-west-1" {
  source = "./modules/per-region"
  providers = {
    aws = aws.us-west-1
  }

  # (region-specific module arguments)
}

locals {
  # Gather up the outputs from each of the instances
  # of the per-region module into a map in case
  # you need to look them up by region name
  # in the top-level module.
  regions = tomap({
    us-west-2 = module.us-west-2
    us-west-1 = module.us-west-1
  })
}
1 Like

that makes a lot of sense. thank you very much!!