首页 > 解决方案 > 两个模块之间的模块组合使用条件 for_each 双向

问题描述

在我的根模块上,我声明了两个模块(paired_regions_network 和paired_regions_app),它们都迭代了一组区域。

module "paired_regions_network" {
  source                  = "./modules/network"
  application_hostname    = module.paired_regions_app[each.key].website_hostname
  ...
  for_each = ( var.environment == "TEST" || var.environment == "PROD") ? { region1 = var.paired_regions.region1 } : {  }
}

module "paired_regions_app" {
  source                  = "./modules/multi-region"
  wag_public_ip           = module.paired_regions_network[each.key].wag_public_ip
  ...
  for_each = (var.environment == "TEST" || var.environment == "PROD") ? var.paired_regions : { region1 = var.paired_regions.region1 }
}

output "network_outputs" {
  value = module.paired_regions_network
}

output "app_outputs" {
  value = module.paired_regions_app
}

迭代区域声明如下:

variable "paired_regions" {
  description = "The paired regions"
  default = { 
    region1 = { 
      ...
    },
    region2 = { 
      ...
    }
  }
}

paired_regions_network模块中,我想访问来自paired_regions_app模块的输出,即website_hostname我想分配给模块application_hostname参数的值paired_regions_network,如上所示。

output "website_hostname" {
  value       = azurerm_app_service.was_app.default_site_hostname
  description = "The hostname of the website"
}

paired_regions_app模块中,我想访问来自paired_regions_network模块的输出,即wag_public_ip我想分配给模块的同名参数的值paired_regions_app,如上所示。

output "wag_ip_address" {
  value       = azurerm_public_ip.network_ip.ip_address
  description = "The Public IP address that will be used by the app gateway"
}

但这会导致一个依赖循环,我无法摆脱。错误如下:

错误:周期:...

我可以在两个模块之间传递输出,而不引起依赖循环吗?

标签: terraformterraform-provider-azure

解决方案


根据@Marcin 的建议,我能够通过创建仅包含公共 IP 资源的第三个模块来克服这个问题。因此,paired_regions_app模块将依赖于新模块而不是依赖于paired_regions_network模块。然后paired_regions_network将依赖于其他两个模块。除了从paired_regions_network模块中删除输出外,代码更改如下:

根模块

module "paired_regions_ips" {
  source                  = "./modules/public-ip"
  ...
  for_each = ( var.environment == "TEST" || var.environment == "PROD") ? { region1 = var.paired_regions.region1 } : {  }
}

module "paired_regions_app" {
  source                  = "./modules/multi-region"
  wag_public_ip           = length(module.paired_regions_ips) > 0 ? (lookup(module.paired_regions_ips, each.key, "") != "" ? join("/", ["${module.paired_regions_ips[each.key].ip_obj.ip_address}", "32"]) : "" ) : ""
  ...
  for_each = (var.environment == "TEST" || var.environment == "PROD") ? var.paired_regions : { region1 = var.paired_regions.region1 }
}

module "paired_regions_network" {
  source                  = "./modules/network"
  wag_public_ip_id        = module.paired_regions_ips[each.key].ip_obj.id
  application_hostname    = module.paired_regions_app[each.key].website_hostname
  ...
  for_each = ( var.environment == "TEST" || var.environment == "PROD") ? { region1 = var.paired_regions.region1 } : {  }
}

output "network_outputs" {
  value = module.paired_regions_ips
}

output "app_outputs" {
  value = module.paired_regions_app
}

新模块

output "ip_obj" {
  value       = azurerm_public_ip.network_ip
  description = "The Public IP address"
}

一些备注:

  • 因为与模块相比,模块在循环paired_regions_ips上的条件不同,所以在从后者获取输出时我不得不添加一些逻辑for_eachpaired_regions_app
  • 新模块输出一个公共 IP 对象,以便我可以访问它的 ID(来自paired_regions_network模块)和 IP 地址(来自paired_regions_app模块)

推荐阅读