Dynamic/conditional provider in resource

I have multi environments in my infrastructure, qa, prod and prod2 each having its own set of environment variables. I’d like to define a route53 resource in prod environment that will create a record in route53 zone in prod2. Simple cross account access. I want this resource to be created only if environment variable is not empty. What I have almost works, but it looks like it is not possible to have dynamic provider value.

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

provider "aws" {
  alias   = "prod2"
  region  = var.aws_region
  profile = "prod2"
}

# sourcing zone from another account
data "aws_route53_zone" "domain_com" {
  name     = "domain.com"
  provider = aws.dns
}

resource "aws_route53_record" "static_records_in_prod2" {
  provider = aws.prod2
  for_each = length(coalesce(var.static_dns_records, [])) > 0 ? {
    for record in var.static_dns_records : "${record.name}_${record.type}" => record
  } : {}

  zone_id = lookup(
    {
      "${data.aws_route53_zone.domain_com.name}" = data.aws_route53_zone.domain_com.zone_id
    },
    each.value.zone,
    null
  )

  name    = each.value.name
  records = each.value.records
  ttl     = each.value.ttl
  type    = each.value.type

  depends_on = [
    data.aws_route53_zone.domain_com
  ]
}

variable "static_dns_records" {
  type = list(object({
    name    = string
    zone    = string
    type    = string
    records = list(string)
    ttl     = number
  }))
  default = null
}

vars:

static_dns_records = [
  {
    name    = "sub.domain.com."
    zone    = "domain.com"
    records = [
      "anotherdomain.com"
    ]
    ttl             = 300
    type            = "CNAME"
  }
]

What I’ve been trying was for example adding locals

locals {
  dns_providers = {
    "prod2" = aws.prod2
    "default"    = aws
  }
}

and a provider in a resource like:

provider = lookup(local.dns_providers, each.value.foreign_account, aws)

or:

provider = each.value.foreign_account == "prod2" ? aws.prod2 : null
  • a variable in static_dns_records:
    foreign_account = null or foreign_account = "prod2"

but I am getting errors like:

on route53.tf line 9, in resource "aws_route53_record" "static_records":
9:   provider = each.value.foreign_account == "prod2" ? aws.prod2 : null
The provider argument requires a provider type name, optionally followed by a period and then a configuration alias.

or:

Error: Invalid provider configuration reference on route53.tf line 20, in resource "aws_route53_record" "static_records":
20:   provider = lookup(local.dns_providers, each.value.foreign_account, aws)
The provider argument requires a provider type name, optionally followed by a period and then a configuration alias.

Hi @horizn,

Providers are not values in Terraform which can be passed around through expressions, they must be statically assigned before Terraform can construct the dependency graph and evaluate the configuration.

The only way to do something like this currently, is to have multiple resource blocks pointing to different provider configurations, and selectively create instances of the resource you want, rather than selecting the provider within a single resource block.