How to using double for_each in terraform?

everyone.
While using for_each in terraform, duplication is coming out. In this case, how should I bypass it?

The problematic points are 1), and 2). data values must be obtained from each resource through for_each.

// custom hostname binding
resource "azurerm_app_service_custom_hostname_binding" "service_host_bind" {      
  for_each                     =  azurerm_dns_cname_record.cname_target       
  hostname                  = trim(each.value.fqdn, ".")       
  app_service_name     = azurerm_app_service._service.name       
  resource_group_name = azurerm_resource_group._rg.name       
  depends_on          = [azurerm_dns_txt_record._txt_target] 
  lifecycle {         ignore_changes = [ssl_state, thumbprint]       }    }

// app service managed certificate
resource "azurerm_app_service_managed_certificate" "_service_manage_cert" {       
      for_each                    = azurerm_app_service_custom_hostname_binding._service_host_bind       
      custom_hostname_binding_id  = each.value.id          }

// app service certificate binding
resource "azurerm_app_service_certificate_binding" "xtrm_service_certi_bind" {       
      1) hostname_binding_id = azurerm_app_service_custom_hostname_binding._service_host_bind.id       // ## how to for_each??
      2) certificate_id               = azurerm_app_service_managed_certificate._service_manage_cert.id         // ## how to for_each??
      ssl_state           = "SniEnabled"            }

Hi @laguz1254,

I’m not very familiar with these particular resource types but I think what you want to achieve here is to have one instance of azurerm_app_service_certificate_binding.xtrm_service_certi_bind for every pair of azurerm_app_service_custom_hostname_binding.service_host_bind and azurerm_app_service_managed_certificate._service_manage_cert objects.

If so, you can achieve that by constructing a new data structure that represents that pairing using the setproduct function. For example:

locals {
  binding_pairs = toset([
    for pair in setproduct(
      keys(azurerm_app_service_custom_hostname_binding.service_host_bind),
      keys(azurerm_app_service_managed_certificate._service_manage_cert),
    ) : {
      hostname_binding_key = pair[0]
      certificate_key      = pair[1]
    }
  ])
}

This will construct a set of objects representing every combination of keys from those two other resources, which you can then use as the basis for your derived for_each:

resource "azurerm_app_service_certificate_binding" "xtrm_service_certi_bind" {
  for_each = { for p in local.binding_pairs : "${p.hostname_binding_key}:${p.certificate_key}" => p }

  hostname_binding_id = azurerm_app_service_custom_hostname_binding.service_host_bind[each.value.hostname_binding_key].id
  certificate_id      = azurerm_app_service_managed_certificate._service_manage_cert[each.value.certificate_key].id
  # ...
}

What I’ve shown here is a variant of the pattern described in the docs as Finding Combinations for for_each. The longer explanation in the docs might help to add some context for what I showed above, so that you might understand how to adapt this approach to other similar problems in the future.

1 Like