Switch between aws regions by variable

Hi guys,
I need to separate different aws regions by input variable.
For example if my variable value is “eu” then terraform calls only “aws_eu” module
if variable is “sa” then calls only “aws_sa” module and etc…

common_vars.tf

variable "region" {
  type        = string
  description = "Choose what region proxy should up and run \n EU, SA, US"
}
variable "vendor" {
  type        = string
  description = "Choose proxy provider between aws/hcloud"

  validation {
    condition     = contains(["aws", "hcloud"], var.vendor)
    error_message = "Invalid input, options: \"aws\", \"hcloud\"."
  }
}

main.tf

terraform {
    required_version = ">= 1.0.5"
}

provider "aws" {
  alias = "sa"
  region  = "af-south-1"
}

provider "aws" {
  alias = "eu"
  region  = "eu-west-1"
}

provider "aws" {
  alias = "us"
  region  = "us-east-1"
}

module "aws_eu" {
  providers = {
    aws = aws.eu
  }
  source = "./modules/aws" 
}

aws_eu

terraform {
  required_providers {
    aws = {
      source  = "hashicorp/aws"
      version = ">= 2.7.0"
      configuration_aliases = [ aws.eu ]
    }
  }
}

resource "aws_instance" "proxy_server" {
  count           = var.vendor == "aws" ? 1 : 0
  ami             = "ami-0d09937634XXX"
  instance_type   = "t2.micro"
  subnet_id       = "subnet-d092XXX"
  security_groups = "sg-bcbf8XXX"
  key_name        = "my@name.key"
  
  tags = {
    Name = var.proxy_hostname
  }
}

What is the best practice to switch between aws regions by variable ?
afaik at earlier terraform versions provider in resource block could be defined as variable
but now it needs to be called by separate modules

  1. Please could you describe what you’re trying to achieve at a high level, without assuming that Terraform modules are the right solution? I’m not sure they are, but it’s hard to tell from what you’ve said so far.

  2. Terraform always evaluates all modules that are defined (it’s not really something that can be described as a “call”). You could potentially apply count = 0 to one though. I’m not totally sure that’s right for your use-case though.

  3. This line is incorrect and should be deleted:

because inside the module, the provider has been remapped to not have any provider alias.

Thanks for you answer @maxb
I will try to explain:
I have different providers for example aws, hetzner_cloud, DigitalOcean.
I need to enter a several main variables like:
var.vendor - values between [aws, hcloud, DO]
var.region - values between [eu, sa, us]
for example var.vendor=aws and var.region=eu
I need to call a suitable resource for instance creating

As you mentioned about count = x
I think that it could be something like
but I’m not sure if that’s a good way

resource "aws_instance" "eu_proxy_server" {
  count                 = var.vendor == "aws" && var.region == "eu" ? 1 : 0
  ami                    = ....
  instance_type   = ....
...
...
}

Why do you want to use one Terraform setup to control all of these?

I think it would be considerably simpler if you just used entirely separate Terraform configurations for each vendor. They’re going to need distinct providers anyway.

For the multiple regions of AWS, you might want a common module that you reference to share some of the code - but still have separate Terraform root directories for each region.

I’m not sure you’ve quite got the point of the variables and how the code works/is organised.

With Terraform you fully describe all the resources you want (which could be implemented by different providers, for example multi-cloud). Running terraform apply then creates any missing resources, updates ones which are different from what the code says and deletes any no longer in the code.

You then modify the code over time and your resources are modified accordingly.

Things like vendor or region would generally never make sense to have as variables. They would just be part of the code - you’d have different provider blocks for each region and vendor.

Thanks guys for your answers.
Found some multi-cloud solutions, similar to mine infrastructure.

That’s not entirely true.
It is true that it cannot be done.
It is not true that id doesn’t make sense.

I would like to be able to create, for example, a set of VPCs, one for each region I need.
According to current limitation, I need to manually create as many providers as regions and as many resources (no iterators) all mentioning a different static provider.
If I could express the region as a string (as opposed to a static identificator) than that would be possible in a loop.