我尝试使用 Terraform 来部署具有可变存储容器的多个存储帐户。但我只想调用结节一次,因此存储帐户变量是对象的映射。存储容器是存储帐户映射内对象的嵌套映射。
看起来像这样:
variables.tf
variable "location" {
type = string
description = "Location for storage account resource."
}
variable "resource_group_name" {
type = string
description = "Resource group that will contain the resource."
}
variable "storage_account" {
type = map(object({
name = string
access_tier = string
account_kind = string
account_replication_type = string
account_tier = string
public_network_access_enabled = bool
containers = optional(map(object({
name = string
container_access_type = optional(string, "private")
})))
network_rules = list(object({
default_action = string
bypass = optional(set(string))
ip_rules = optional(set(string))
virtual_network_subnet_ids = optional(set(string))
}))
}))
}
资源模块代码如下所示:
main.tf
resource "azurerm_storage_account" "storage" {
for_each = var.storage_account
name = each.value.name
resource_group_name = var.resource_group_name
location = var.location
account_tier = each.value.account_tier
account_replication_type = each.value.account_replication_type
account_kind = each.value.account_kind
access_tier = each.value.access_tier
public_network_access_enabled = each.value.public_network_access_enabled != null ? each.value.public_network_access_enabled : false
}
locals {
containers_list = flatten([
for key, value in var.storage_account : [
for container in value.containers : {
name = container
storage_account_name = azurerm_storage_account.storage[key].name
}
]
]...)
}
resource "azurerm_storage_container" "storage" {
#for_each = { for container in local.containers_list : container.name.name => container }
for_each = tomap({
for container in local.containers_list : container.name.name => container
})
name = each.value.container.name
storage_account_name = each.value.storage_account_name
}
我用这个来调用模块:
main.tf
module "storage_account" {
source = "./modules/azurerm_storage_account"
resource_group_name = "rg-temp"
location = "uksouth"
tags = {}
storage_account = {
"storage01" = {
name = "storagerandom0001"
account_kind = "StorageV2"
account_tier = "Standard"
account_replication_type = "LRS"
access_tier = "Hot"
public_network_access_enabled = true
network_rules = []
containers = {
"container-aa" = {
name = "random01"
container_access_type = "private"
},
"container-ab" = {
name = "random02"
container_access_type = "private"
}
}
},
"storage02" = {
name = "storagerandom0002"
account_kind = "StorageV2"
account_tier = "Standard"
account_replication_type = "LRS"
access_tier = "Hot"
public_network_access_enabled = true
network_rules = []
containers = {
"container-01" = {
name = "container01"
container_access_type = "private"
},
"container-02" = {
name = "container02"
container_access_type = "private"
}
}
}
}
}
当我运行此命令时,我收到错误:
│ Error: Too many function arguments
│
│ on modules/azurerm_storage_account/main.tf line 17, in locals:
│ 17: containers_list = flatten([
│ 18: for key, value in var.storage_account : [
│ 19: for container in value.containers : {
│ 20: name = container
│ 21: storage_account_name = azurerm_storage_account.storage[key].name
│ 22: }
│ 23: ]
│ 24: ]...)
│ ├────────────────
│ │ while calling flatten(list)
│ │ azurerm_storage_account.storage is object with 2 attributes
│ │ var.storage_account is map of object with 2 elements
│
│ Function "flatten" expects only 1 argument(s).
从这个问题(看起来与我想做的非常相似):
如何在 Terraform 中的 for_each 循环内访问地图中的序列
我想知道我是否需要合并而不是展平?
但是如果我更改为
merge
我会收到此错误:
╷
│ Error: Error in function call
│
│ on modules/azurerm_storage_account/main.tf line 17, in locals:
│ 17: containers_list = merge([
│ 18: for key, value in var.storage_account : [
│ 19: for container in value.containers : {
│ 20: name = container
│ 21: storage_account_name = azurerm_storage_account.storage[key].name
│ 22: }
│ 23: ]
│ 24: ]...)
│ ├────────────────
│ │ while calling merge(maps...)
│ │ azurerm_storage_account.storage is object with 2 attributes
│ │ var.storage_account is map of object with 2 elements
│
│ Call to function "merge" failed: arguments must be maps or objects, got "tuple".
╵
这是我第一次必须嵌套循环(或使用合并或展平),所以我做得不太好。
可以帮忙并尝试用简单的语言解释我需要做什么/做错了什么吗?
谢谢。
展平函数需要一个参数,因为错误提示为
while calling flatten(list) [...] Function "flatten" expects only 1 argument(s)
。出现错误的原因是您添加到生成的列表列表中的 ...
运算符。只要把它去掉就可以了。
然后您应该将本地值更改为:
containers_list = flatten([
for key, value in var.storage_account : [
for _, container in value.containers : {
name = container
storage_account_name = azurerm_storage_account.storage[key].name
}
]
])
此外,由于容器是可选的,并且可能为空,因此我默认为其提供一个空地图:
variable "storage_account" {
type = map(object({
name = string
access_tier = string
account_kind = string
account_replication_type = string
account_tier = string
public_network_access_enabled = bool
containers = optional(map(object({
name = string
container_access_type = optional(string, "private")
})), {})
network_rules = list(object({
default_action = string
bypass = optional(set(string))
ip_rules = optional(set(string))
virtual_network_subnet_ids = optional(set(string))
}))
}))
}