I'm building code that needs to talk to two different AWS accounts, which the documentation says should work. This worked under 0.11.14
In the main, in my providers.tf file I have:
provider "aws" {
alias = "ca-central-1"
region = "ca-central-1"
profile = var.aws_profile
}
provider "aws" {
alias = "other-ca-central-1"
region = "ca-central-1"
profile = var.aws_other_profile
}
(Those variables are set the correct profiles in my credentials file.)
In the root, in the code that calls the module,
module "obfuscated" {
source = "./modules/obfuscated"
providers = {
aws.main = "aws.ca-central-1"
aws.other = "aws.other-ca-central-1"
}
#other stuff
}
In ./modules/obfuscated/main.tf I have
provider "aws" {
alias = "main"
}
provider "aws" {
alias = "other"
}
Which the docs say is a placeholder, which can only be empty or have an alias. Without it, it complains the provider doesn't exist. But with it, it complains I didn't specify the region, which conflicts with the docs.
Surely the documentation couldn't be wrong, no, that couldn't be possible.. Help me obi-wan-overflow..
Configuring Multiple AWS providersWe can't write two or more providers with the same name i.e. two AWS providers. If there's any such need the terraform has provided a way to do that which is to use alias argument. Note: A provider block without an alias argument is the default configuration for that provider.
Providers can be passed down to descendent modules in two ways: either implicitly through inheritance, or explicitly via the providers argument within a module block.
While Terraform 0.12 does have backward compatibility with Terraform 0.11 syntax, if you have access to the module's source, it is highly recommended to upgrade the modules to 0.12 as well.
If your root Terraform module has child modules initialized in it then you can pass providers attribute with value as an object of different providers. Passing providers to the child module (s).
Providers are Terraform plugins that are used to interact with remote systems such as Docker, AWS, Azure… Terraform has a huge list of providers. A complete list of providers can be found here. Every root module will have at least one default provider which then will be used by all the child modules.
On digging further we figured out a simple way Terraform provides us to have multiple AWS providers by creating aliases. There are multiple use cases where provider alias can be used: Creating resources in multiple AWS accounts in the same terraform module. Creating resources in resources in different regions of the same AWS account.
To retain the backward compatibility as much as possible, Terraform v0.13 continues to support the legacy pattern for module blocks that do not use these new features, but a module with its own provider configurations is not compatible with for_each, count, or depends_on. Terraform will produce an error if you attempt to combine these features.
Here is an example of how I am handling the issue
#af-south-1
data aws_vpcs af-south-1 {
provider = aws.af-south-1
}
module af-south-1 {
source = "./modules/flow_log"
providers = {
aws = aws.af-south-1
}
iam_role_arn = aws_iam_role.vpc_flow_log.arn
log_destination = aws_s3_bucket.vpc_flow_log.arn
log_destination_type = "s3"
traffic_type = "REJECT"
aws_vpc_ids = data.aws_vpcs.af-south-1.ids
depends_on = [ aws_s3_bucket.vpc_flow_log ]
}
#ap-east-1
data aws_vpcs ap-east-1 {
provider = aws.ap-east-1
}
module ap-east-1 {
source = "./modules/flow_log"
providers = {
aws = aws.ap-east-1
}
iam_role_arn = aws_iam_role.vpc_flow_log.arn
log_destination = aws_s3_bucket.vpc_flow_log.arn
log_destination_type = "s3"
traffic_type = "REJECT"
depends_on = [ aws_s3_bucket.vpc_flow_log ]
aws_vpc_ids = data.aws_vpcs.ap-east-1.ids
}
#ap-northeast-1
data aws_vpcs ap-northeast-1 {
provider = aws.ap-northeast-1
}
....
In this example I am creating a datasource aws_vpcs
for each provider region. Then I pass the list of ids for each region into the module. At this time you must specify the provider for the module to use unless you are using the default provider.
The main problem may be that you are attempting to pass the providers values as strings rather than references to the actual provider. "aws.<alias>"
vs aws.<alias>
I could be wrong, but I think you will need to include required_providers
in your module terraform
block.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
}
}
}
Then you may use an empty provider
or one with alias
to declare the provider as a required item to be passed in the modules providers
configuration.
The solution provided by @NeoVance is almost solving it. Indeed, the required_providers
block is required in the module, but it requires the so called configuration_aliases
, additionally.
terraform {
required_providers {
aws = {
source = "hashicorp/aws"
version = ">= 2.7.0"
configuration_aliases = [ aws.main, aws.other ]
}
}
}
Here your can find the related documentation about Passing Providers Explicitely.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With