Error de terraform con bloque dinámico en for_each
Estoy intentando crear una instancia de un mapa celeste storage_share utilizando el recurso azuremrm storage_share . Por diseño, necesito poder instanciar más de un recurso compartido de almacenamiento con el mismo bloque; cada una de esas acciones puede tener o no una sección "acl".
Estaba pensando en resolver este problema usando un for_each junto con un bloque dinámico, como en la pregunta SE relacionada:
Main.tf
resource "azurerm_storage_share" "storage_share" {
for_each = var.storage_share_map
name = each.key
storage_account_name = azurerm_storage_account.sa.name
quota = each.value.quota
dynamic "acl" {
for_each = each.value.acl
content {
id = acl.value.id
access_policy {
permissions = acl.value.access_policy.permissions
start = acl.value.access_policy.start
expiry = acl.value.access_policy.expiry
}
}
}
La variable se definiría como:
variable "storage_share_map" {
type = map(object({
quota = number,
acl = object({
id = string,
access_policy = object({
expiry = string,
permissions = string,
start = string
})
}),
}))
default = {}
}
y luego parametrizado en mis pruebas como:
storage_share_map = {
my-share-2 = {
quota = 123,
acl = {
id = "a-id",
access_policy = {
expiry = "ISO8061 UTC TIME"
permissions = "rwdl"
start = "ISO8601 UTC TIME"
},
},
}
Sin embargo, al realizar pruebas, terraform devuelve el siguiente resultado:
Error: Unsupported attribute
on .terraform\modules\sa\main.tf line 83, in resource "azurerm_storage_share" "storage_share":
83: id = acl.value.id
|----------------
| acl.value is object with 3 attributes
This object does not have an attribute named "id".
Error: Unsupported attribute
on .terraform\modules\sa\main.tf line 83, in resource "azurerm_storage_share" "storage_share":
83: id = acl.value.id
|----------------
| acl.value is "a-id"
This value does not have any attributes.
Error: Unsupported attribute
on .terraform\modules\sa\main.tf line 86, in resource "azurerm_storage_share" "storage_share":
86: permissions = acl.value.access_policy.permissions
|----------------
| acl.value is object with 3 attributes
This object does not have an attribute named "access_policy".
Error: Unsupported attribute
on .terraform\modules\sa\main.tf line 86, in resource "azurerm_storage_share" "storage_share":
86: permissions = acl.value.access_policy.permissions
|----------------
| acl.value is "a-id"
This value does not have any attributes.
Según tengo entendido, el problema aquí es que for_each dentro del bloque dinámico está mal formado o se comporta mal: acl.value parece estar valorado como la cadena "a-id" y llevar tres atributos (?).
Terraform versión 0.12.26 Azurerm versión 2.26.0
Cualquier idea sería apreciada.
Pregunta relacionada: Bloque dinámico con for_each dentro de un recurso creado con for_each
Respuestas
Al iterar en el bloque dinámico con for_each = each.value.acl, está iterando sobre los valores del objecttipo. Parece que realmente desea iterar sobre aclellos mismos. Debería ajustar su tipo a:
variable "storage_share_map" {
type = map(object({
quota = number,
acl = list(object({
...
}))
})),
}
Puede saber por los mensajes de error que actualmente está iterando idy luego access_policy, y no encuentra los dos atributos solicitados para cada uno, por lo que tiene 2 * 2 = 4 errores.
Puede ajustar su entrada correspondientemente a:
storage_share_map = {
my-share-2 = {
quota = 123,
acl = [{
id = "a-id",
access_policy = {
expiry = "ISO8061 UTC TIME"
permissions = "rwdl"
start = "ISO8601 UTC TIME"
},
}],
}
y esto logrará el comportamiento que desea.
Tenga en cuenta que Terraform 0.12 tiene problemas a veces con las especificaciones de tipo de objeto anidado, por lo que omitir el aclcon []puede provocar fallas en determinadas circunstancias.
Utilice corchetes para each.value.acl.
El bloque de recursos compartidos de Azure Storage debería verse así:
resource "azurerm_storage_share" "storage_share" {
for_each = var.storage_share_map
name = each.key
storage_account_name = azurerm_storage_account.sa.name
quota = each.value.quota
dynamic "acl" {
for_each = [each.value.acl]
content {
id = acl.value.id
access_policy {
permissions = acl.value.access_policy.permissions
start = acl.value.access_policy.start
expiry = acl.value.access_policy.expiry
}
}
}
}