Combine 2 lists to create multiple resources

Description

Hi,

In order to create multiple CloudFront distros in aws I need to use the following details:
I have a list of prefixes (api1, api2, api3), and I have several domains (example1.com, example2.com) - I counted the prefixes and the domains by different amounts on purpose.

To do so I thought I might need to use dynamic blocks this way:
certificates = [
{
domain = [“example1.com”, “example2.com”]
prefix = [“api1”, “api2”, “api3”]
}
and then configure the resource with 2 dynamic blocks (One for each list) but it seems like it’s not the way I need to implement it as the variable in the content section shouldn’t be a list…

Hope you guys can help me with a hint.

Terraform Version

0.13

Expected Behavior

The expected behavior should be a CloudFront distro for every mix:
api1 .example1 .com
api2 .example1 .com
api3 .example1 .com
api1 .example2 .com
api2 .example2 .com
api3 .example2 .com
etc.

Hi @eladazary,

This idea of taking every combination of elements from a set of collections is called the cartesian product in set theory, and Terraform has thesetproduct function to implement that operation.

For example, here’s a set of local values showing a way to combine the two sets you shared into a single map that is compatible with what resource for_each expects:

locals {
  domains  = ["example1.com", "example2.com"]
  prefixes = ["api1", "api2", "api3"]

  api_hosts = {
    for pair in setproduct(local.prefixes, local.domains) : "${pair[0]}.${pair[1]}" => {
      prefix = pair[0]
      domain = pair[1]
    }
  }
}

If you write a aws_cloudformation_distribution resource with for_each = local.api_hosts then you’d be declaring one instance per distinct host, and in the resource block you can use:

  • each.key to get the whole hostname, like api1.example1.com
  • each.value.prefix to get the subdomain part, like api1
  • each.value.domain to get the domain part, like example1.com

Terraform will track these instances with addresses like aws_cloudformation_distribution.example["api1.example1.com"], so you’ll need to make sure that all of the combinations of prefix and domain create unique hostnames. If you add new elements to either local.domains or local.prefixes in future then Terraform will understand that as intent to create all of the new distributions needed for all of the new hostnames the changes imply.