2种不同的方式来做terraform动态语句,有什么区别

2 different ways of doing terraform dynamic statement, what's the difference

我遇到过 2 种 terraform 动态语法,只是想知道有什么区别?

dynamic "storage_account" {
    for_each = var.storage_account == null ? {} : var.storage_account
    content {
      name         = storage_account.value.name
      type         = storage_account.value.type
      account_name = storage_account.value.account_name
      share_name   = storage_account.value.share_name
      access_key   = storage_account.value.access_key
      mount_path   = storage_account.value.mount_path
    }
  }

dynamic "backup" {
    for_each = var.app_service_backup != null ? [1] : []
    content {
      name                = var.app_service_backup.name
      enabled             = true
      storage_account_url = var.app_service_backup.storage_account_url
      schedule {
        frequency_interval = var.app_service_backup.frequency_interval
        frequency_unit     = var.app_service_backup.frequency_unit
      }
    }
  }

变量是

variable "storage_account" {
  description = <<EOF
  (Optional) - One or more storage_account blocks as defined below.

  (Required) name - The name of the storage account identifier.
  (Required) type - The type of storage. Possible values are AzureBlob and AzureFiles.
  (Required) account_name - The name of the storage account.
  (Required) share_name - The name of the file share (container name, for Blob storage).
  (Required) access_key - The access key for the storage account.
  (Required) mount_path - The path to mount the storage within the site's runtime environment.
  EOF
  type = map(object({
    name         = string
    type         = string
    account_name = string
    share_name   = string
    access_key   = string
    mount_path   = string
  }))

  default = null
}


variable "app_service_backup" {
  description = <<EOF
    (Optional) - The app service backup block supports the following:

    (Required) name - Specifies the name for this Backup.
    (Required) storage_account_url - The SAS URL to a Storage Container where Backups should be saved.
    (Required) frequency_interval - Sets how often the backup should be executed.
    (Required) frequency_unit - Sets the unit of time for how often the backup should be executed. Possible values are Day or Hour.
  EOF

  type = object({
    name                = string
    storage_account_url = string
    frequency_interval  = number
    frequency_unit      = string

  })

  default = null
}

注意第一个动态 storage_account 它是如何使用 storage_account.value.name 之类的东西的 第二个“备份”正在使用 var.app_service_backup.name

第二个可以用backup.value.name吗?

当你在TF中有Conditional Expression

condition ? true_val : false_val

true_valfalse_val 必须是 同一类型 .

所以在你的第一个例子中:

for_each = var.storage_account == null ? {} : var.storage_account

var.storage_account 是地图,所以 true_val 也必须是 map。在这种情况下,它是一个空 map {}。由于这张地图没有任何元素,for_each 不会 运行.

在你的第二个例子中也可以使用地图,但是列表写起来更短,所以你有(只是一个约定):

 for_each = var.app_service_backup != null ? [1] : []

其中 [] 是一个空列表,[1] 是一个只有一个元素的列表。所以 for_each 只会 运行 一次。列表[1]中元素的值是1,但真的无所谓。它可以是任何值,只要列表的长度不为零。

更新.

你不能在第二个例子中使用 backup.value.name,因为在那种情况下 backup.value 字面意思是 1 作为它来自 [1] 的值。强行将 for_each 更改为使用 var.app_service_backup 也没有意义,因为它只是一个值。它不需要迭代。所以你直接访问它就可以了。