Dynamic 具有多个内容字段的Terraform v12动态嵌套块?

Dynamic 具有多个内容字段的Terraform v12动态嵌套块?,dynamic,module,nested-loops,terraform0.12+,Dynamic,Module,Nested Loops,Terraform0.12+,我的Azure应用程序网关模块遇到问题。我已经把所有的东西都转换成了动态块,当我用1个应用程序的输入调用我的模块时,它工作得非常出色 1应用程序: 然而,当我在通话中添加第二个应用程序时,我会发现问题 2个应用程序 添加新应用程序时,它同时具有80重定向和443规则。然而,由于索引,terraform想要覆盖我的第一条应用程序规则,因此80条重定向规则都是列表中的第一条和第二条,然后是列表中的第三条和第四条443规则。我们可以在一个动态块中创建多个内容块吗?正如您所看到的,当我将第二个应用程序添

我的Azure应用程序网关模块遇到问题。我已经把所有的东西都转换成了动态块,当我用1个应用程序的输入调用我的模块时,它工作得非常出色

1应用程序: 然而,当我在通话中添加第二个应用程序时,我会发现问题

2个应用程序 添加新应用程序时,它同时具有80重定向和443规则。然而,由于索引,terraform想要覆盖我的第一条应用程序规则,因此80条重定向规则都是列表中的第一条和第二条,然后是列表中的第三条和第四条443规则。我们可以在一个动态块中创建多个内容块吗?正如您所看到的,当我将第二个应用程序添加到模块中时,第一个应用程序正在更改,导致密钥不匹配(即app1 id与app2密钥不匹配,等等)。我的http_侦听器也会发生同样的情况

输出变化 或者在动态块中嵌套动态块,也不起作用
有人知道如何解决这个问题吗?如果现有应用程序将发生更改,并且每次添加新应用程序时都必须受到污染并重新创建,则会使应用程序网关模块无法使用。

我最终找到了答案。我只需要在初始for循环中嵌套一个额外的for循环,而不是多个动态嵌套块

下面是为每个应用程序创建HTTP和HTTPS侦听器的相关示例代码。它还为后端池创建一个HTTPS规则,以及一个HTTP重定向规则

dynamic "http_listener" {
    for_each = flatten([
      for app in var.app: [
        for listener in app.listener : {
            fqdn    = app.fqdn
            protocol = listener.protocol
            port = listener.port
        }
      ]
    ])
    content {
        name                           = "%{ if http_listener.value.protocol == "https" }${http_listener.value.fqdn}-${http_listener.value.port}-${local.https_listener_name}%{ else }${http_listener.value.fqdn}-${local.http_listener_name}%{ endif }"  
        frontend_ip_configuration_name = local.frontend_ip_configuration_name
        frontend_port_name             = http_listener.value.port
        host_name                      = http_listener.value.fqdn
        protocol                       = upper(http_listener.value.protocol)
        ssl_certificate_name           = "%{ if http_listener.value.protocol == "https" }${data.azurerm_key_vault_secret.cert_fe.name}%{ endif }" 
      }
  }

dynamic "request_routing_rule" {
    for_each = flatten([
      for app in var.app: [
        for listener in app.listener : {
            fqdn    = app.fqdn
            protocol = listener.protocol
            port = listener.port
        }
      ]
    ])
    content {
        name                        = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}-${request_routing_rule.value.port}%{ else }${request_routing_rule.value.fqdn}-redirect%{ endif }"  
        rule_type                   = "Basic"
        http_listener_name          = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}-${request_routing_rule.value.port}-${local.https_listener_name}%{ else }${request_routing_rule.value.fqdn}-${local.http_listener_name}%{ endif }"
        backend_address_pool_name   = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}%{ endif }" 
        backend_http_settings_name  = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}-${local.backend_https_settings_name}%{ endif }" 
        redirect_configuration_name = request_routing_rule.value.protocol == "http" ? "${request_routing_rule.value.fqdn}-redirect" : null
    }

  }

  dynamic "redirect_configuration" {
    for_each = [for app in var.app : {
            fqdn    = app.fqdn
            port = app.listener.https.port

    }]
    content {
      name                 = "${redirect_configuration.value.fqdn}-redirect"
      redirect_type        = "Permanent"
      target_listener_name = "${redirect_configuration.value.fqdn}-${redirect_configuration.value.port}-${local.https_listener_name}"
    }

#... additional output omitted
这是对它的模块调用。您需要为应用程序指定http和https侦听器。您可以指定任何端口,也可以是非标准端口

module "my_appgw" {
  source = "../../../modules/module-application-gateway"
  location                    = var.location
  resource_group_name         = var.rsg
  subnet_id                   = "${data.azurerm_virtual_network.vnet_dmz.id}/subnets/waf"
  app = {
    1 = {
      fqdn                        = "app1.com"
      pick_host_name_from_backend = true
      listener                    = {

         http = {
          protocol = "http"
          port = 80
        }
         https = {
          protocol = "https"
          port = 443
        }
      }

    }

  }


#... additional output omitted

}
request_routing_rule {

backend_address_pool_id = "<output omitted>/backendAddressPools/app1-example.com"

backend_address_pool_name = "app1-example.com"

backend_http_settings_id = "<output omitted>/backendHttpSettingsCollection/app1-example.com-https-settings"

backend_http_settings_name = "app1-example.com-https-settings"

http_listener_id = "<output omitted>/httpListeners/app1-example.com-443-https-list"

http_listener_name = "app1-example.com-443-https-list"

id = "<output omitted>/requestRoutingRules/app1-example.com-443"

name = "app1-example.com-443"

rule_type = "Basic"

}

~ request_routing_rule {

+ backend_address_pool_name = "app2-example.com"

+ backend_http_settings_name = "app2-example.com-https-settings"

http_listener_id = "<output omitted>/httpListeners/app1-example.com-http-list"

~ http_listener_name = "app1-example.com-http-list" -> "app2-example.com-443-https-list"

id = "<output omitted>/requestRoutingRules/app1-example.com-http-redirect"

~ name = "app1-example.com-http-redirect" -> "app2-example.com-443"

redirect_configuration_id = "<output omitted>/redirectConfigurations/app1-example.com-redirect"

- redirect_configuration_name = "app1-example.com-redirect" -> null

rule_type = "Basic"

}

+ request_routing_rule {

+ http_listener_name = "app1-example.com-http-list"

+ name = "app1-example.com-http-redirect"

+ redirect_configuration_name = "app1-example.com-redirect"

+ rule_type = "Basic"

}

+ request_routing_rule {

+ http_listener_name = "app2-example.com-http-list"

+ name = "app2-example.com-http-redirect"

+ redirect_configuration_name = "app2-example.com-redirect"

+ rule_type = "Basic"

}
    for_each = [for i in var.app : {
      name = i.name
    }]
    content {
      name                           = "${http_listener.value.name}-${local.http_listener_name}"
      frontend_ip_configuration_name = local.frontend_ip_configuration_name
      frontend_port_name             = 80
      protocol                       = "Http"
    }
    content {
      name                           = "${http_listener.value.name}-${http_listener.value.port}-${local.https_listener_name}"
      frontend_ip_configuration_name = local.frontend_ip_configuration_name
      frontend_port_name             = http_listener.value.port
      ssl_certificate_name           = data.azurerm_key_vault_secret.cert_fe.name
      protocol                       = "Https"
    }
  }
dynamic "http_listener" {
    for_each = [for i in var.app : {
      name = i.name
    }]
    content {
      name                           = "${http_listener.value.name}-${local.http_listener_name}"
      frontend_ip_configuration_name = local.frontend_ip_configuration_name
      frontend_port_name             = 80
      protocol                       = "Http"

      dynamic "http_listener" {
        for_each = [for i in var.app : {
          name = i.name
          port = lookup(i, "frontend_port", 443) 
        }]
        content {
          name                           = "${http_listener.value.name}-${http_listener.value.port}-${local.https_listener_name}"
          frontend_ip_configuration_name = local.frontend_ip_configuration_name
          frontend_port_name             = http_listener.value.port
          ssl_certificate_name           = data.azurerm_key_vault_secret.cert_fe.name
          protocol                       = "Https"
        }
      }
    }
dynamic "http_listener" {
    for_each = flatten([
      for app in var.app: [
        for listener in app.listener : {
            fqdn    = app.fqdn
            protocol = listener.protocol
            port = listener.port
        }
      ]
    ])
    content {
        name                           = "%{ if http_listener.value.protocol == "https" }${http_listener.value.fqdn}-${http_listener.value.port}-${local.https_listener_name}%{ else }${http_listener.value.fqdn}-${local.http_listener_name}%{ endif }"  
        frontend_ip_configuration_name = local.frontend_ip_configuration_name
        frontend_port_name             = http_listener.value.port
        host_name                      = http_listener.value.fqdn
        protocol                       = upper(http_listener.value.protocol)
        ssl_certificate_name           = "%{ if http_listener.value.protocol == "https" }${data.azurerm_key_vault_secret.cert_fe.name}%{ endif }" 
      }
  }

dynamic "request_routing_rule" {
    for_each = flatten([
      for app in var.app: [
        for listener in app.listener : {
            fqdn    = app.fqdn
            protocol = listener.protocol
            port = listener.port
        }
      ]
    ])
    content {
        name                        = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}-${request_routing_rule.value.port}%{ else }${request_routing_rule.value.fqdn}-redirect%{ endif }"  
        rule_type                   = "Basic"
        http_listener_name          = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}-${request_routing_rule.value.port}-${local.https_listener_name}%{ else }${request_routing_rule.value.fqdn}-${local.http_listener_name}%{ endif }"
        backend_address_pool_name   = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}%{ endif }" 
        backend_http_settings_name  = "%{ if request_routing_rule.value.protocol == "https" }${request_routing_rule.value.fqdn}-${local.backend_https_settings_name}%{ endif }" 
        redirect_configuration_name = request_routing_rule.value.protocol == "http" ? "${request_routing_rule.value.fqdn}-redirect" : null
    }

  }

  dynamic "redirect_configuration" {
    for_each = [for app in var.app : {
            fqdn    = app.fqdn
            port = app.listener.https.port

    }]
    content {
      name                 = "${redirect_configuration.value.fqdn}-redirect"
      redirect_type        = "Permanent"
      target_listener_name = "${redirect_configuration.value.fqdn}-${redirect_configuration.value.port}-${local.https_listener_name}"
    }

#... additional output omitted
module "my_appgw" {
  source = "../../../modules/module-application-gateway"
  location                    = var.location
  resource_group_name         = var.rsg
  subnet_id                   = "${data.azurerm_virtual_network.vnet_dmz.id}/subnets/waf"
  app = {
    1 = {
      fqdn                        = "app1.com"
      pick_host_name_from_backend = true
      listener                    = {

         http = {
          protocol = "http"
          port = 80
        }
         https = {
          protocol = "https"
          port = 443
        }
      }

    }

  }


#... additional output omitted

}