【问题标题】:How to use Terraform dynamic block如何使用 Terraform 动态块
【发布时间】:2021-09-02 10:39:33
【问题描述】:

我正在尝试使用terraform 创建一个azure 应用程序网关,我的代码如下所示:

main.tf

# Create Application Gateway
resource "azurerm_application_gateway" "app_gateway" {
  name                = var.name
  resource_group_name = var.appg_name
  location            = var.appg_location
  .
  .
  .

#   backend_address_pool {
#     name = var.backend_address_pool_name
#   }

  dynamic "backend_address_pool" {
    for_each = var.backend_pools
    content {
      name      = backend_pools.value["name"]
      fqdns     = backend_pools.value["fqdns"]
      ip_addresses = backend_pools.value["ip_addresses"]
    }
  }    

  backend_http_settings {
    name                  = var.http_setting_name
    cookie_based_affinity = var.cookie_based_affinity
    path                  = var.backend_http_settings_path
    port                  = var.http_setting_port
    protocol              = var.http_setting_protocol
    request_timeout       = var.http_setting_request_time_out_value
  }
  .
  .
  .
}

这是我的variables.tf - 所有变量中只提到backend_pools

variable "backend_pools" {
  type = list(map(string))
}

这是我的terraform.tfvars

backend_pools = [
 {
   name = "pool1"
   fqdns = "fqdns1"
   ip_addresses = "10.0.0.0"
 },
 {
   name = "pool2"
   fqdns = "fqdns2"
   ip_addresses = "10.0.0.0"
 },
 {
   name = "pool3"
   fqdns = "fqdns3"
   ip_addresses = "10.0.0.0"
 }, 
]

我担心的是,根据terraform docs 提到fqdnsip_addresses 的数据类型都是list,那么我该如何更改我的variables.tf 和@987654335 @ 和 main.tf 相应地包含 dynamic 块。

我想要做的是,创建多个后端池并使用变量文件传递值,或者是否可以创建具有多个后端池的json 文件并将其传递给backend_pools 参数?

有人可以帮我解决这个问题吗?

【问题讨论】:

  • 如果你尝试这样做,你会得到一个错误吗?如果将fqdnsip_addresses 包裹在terraform.tfvars 中的方括号中,如fqdns = ["fqdns1"],会发生什么?
  • 尝试配置时是否存在实际错误?我认为您的原始代码实际上看起来不错。如果你想设置一个变量约束,你可以试试list(map(object(name = string fqdns = list(string) ip_addresses = list(string))))。您需要将每个对象设置为带有选项卡的新行,无法在此处的评论回复中真正格式化。

标签: terraform terraform-provider-azure azure-application-gateway


【解决方案1】:

首先,您的 Terraform 代码中有一个错误:

dynamic "backend_address_pool" {
    for_each = var.backend_pools
    content {
      name      = backend_pools.value["name"]
      fqdns     = backend_pools.value["fqdns"]
      ip_addresses = backend_pools.value["ip_addresses"]
    }
  } 

当你使用for_each循环时,应该是:

dynamic "backend_address_pool" {
    for_each = var.backend_pools
    content {
      name      = each.value["name"]
      fqdns     = each.value["fqdns"]
      ip_addresses = each.value["ip_addresses"]
    }
  }    

当你在for_each循环中使用列表时,你可以尝试像这样改变类型:

for_each = toset(var.backend_pools)

但更好的方法是使用地图,因此您可以像这样更改变量:

backend_pools = {
 pool1 = {
    fqdns = "fqdns1"
    ip_addresses = "10.0.0.0"
 },
 pool2 = {
    fqdns = "fqdns2"
    ip_addresses = "10.0.0.0"
 },
 pool3 = {
    fqdns = "fqdns3"
    ip_addresses = "10.0.0.0"
 }
}

那么您的动态块将如下所示:

dynamic "backend_address_pool" {
  for_each = var.backend_pools
  content {
    name      = each.key
    fqdns     = each.value["fqdns"]
    ip_addresses = each.value["ip_addresses"]
  }
} 

【讨论】:

  • 嗨,在您定义变量值的文件中,fqdnsip_addresses 不应该分别像 fqdns = ["fqdns2"]ip_addresses = ["10.0.0.0"] 吗?在列表/数组中?以及变量声明应该是什么样子?就像variable "backend_pools" { type = map(object({ name = string fqdns = list(string) ip_addresses = list(string) })) }
  • @JananathBanuka 仔细看,是map(object(string))的类型。所以像fqdns = ["fqdns"] 这样的值是不对的。每个对象仅用于一种配置。试试看吧。
  • 我不明白,根据你的例子,那会是什么?是map(object(string)) 还是别的什么?
  • @CharlesXu 为什么说 map 语法比 list(object(string)) 更好?
  • @rk92 map 语法是更适合 for_each 循环的类型。并且你可以得到一个带有键名的特殊后端池。
猜你喜欢
  • 2020-08-18
  • 2021-11-16
  • 1970-01-01
  • 2021-09-08
  • 2021-07-25
  • 1970-01-01
  • 1970-01-01
  • 2021-01-06
相关资源
最近更新 更多