Попытка установить необязательный блок с именем «sensitive_labels», и я пытаюсь установить его как необязательный, однако не работает.
Мой код:
переменные.tf:
variable "notification_channels" {
type = any
}
variable "project_id" {
type = string
}
main.tf:
project = var.project_id
for_each = { for k, v in var.notification_channels : k => v }
type = each.value.type
display_name = each.value.display_name
description = each.value.description
labels = each.value.labels
enabled = each.value.enabled
dynamic "sensitive_labels" {
for_each = each.value.sensitive_labels != {} ?[each.value.sensitive_labels] : []
content {
auth_token = lookup(sensitive_labels.value, "auth_token", null)
}
}
}
dev.tfvars:
notification_channels = [
{
type = "email"
display_name = "a channel to send emails"
description = "a nice channel"
labels = {
email_address = "[email protected]"
}
enabled = true
sensitive_labels = {} // this one doesn't give any errors.
},
{
type = "email"
display_name = "HeyThere Email"
description = "a channel to send emails"
labels = {
email_address = "[email protected]"
}
enabled = true
}
]
Получающий:
Ошибка: неподдерживаемый атрибут
в строке 11 notification_channels.tf в ресурсе "google_monitoring_notification_channel" "каналы": 11: for_each = каждое.значение.чувствительные_метки != {} ? [каждое.значение.чувствительные_метки]: [] │ ├──────────────── каждое.значение - это объект с 5 атрибутами
Этот объект не имеет атрибута с именем «sensive_labels».
Как я могу установить здесь чувствительные метки в качестве необязательного атрибута?
Обновлено: Кажется, это работает, но немного не так:
project = var.project_id
for_each = { for k, v in var.notification_channels : k => v }
type = each.value.type
display_name = each.value.display_name
description = each.value.description
labels = each.value.labels
enabled = each.value.enabled
dynamic "sensitive_labels" {
for_each = lookup(each.value, "sensitive_labels", {})
content {
auth_token = lookup(sensitive_labels.value, "auth_token", null)
}
}
}
Есть ли лучший способ, который не кажется хакерским?
Это выглядит так, как если бы for_each = lookup(each.value, "sensitive_labels", {}), хотя я устанавливаю чувствительные_метки с auth_token в tfvars, которые я получаю: │ Ошибка: неверная комбинация аргументов │ │ "sensive_labels.0 .auth_token": необходимо указать один из sensitive_labels.0.auth_token,sensitive_labels.0.password,sensitive_labels.0.service_key
Вы написали: «Кажется, это работает, но немного не так:». Если это работает, почему вы хотите изменить это?
Эй, Марчин. Я имел в виду, что пропуск меток чувствительных_меток в решении для поиска работает, но теперь я столкнулся с другой проблемой с auth_token = lookup(sensitive_labels.value, "auth_token", null), поскольку он игнорирует его, даже если я устанавливаю для него значение. Извините за недопонимание.
Пожалуйста, перепишите свой вопрос, чтобы сосредоточиться на конкретной проблеме. На данный момент ваш вопрос сбивает с толку.
Хорошее место для начала — правильно определить ограничение типа для вашей входной переменной, чтобы Terraform мог лучше понять, какая структура данных ожидается, и помочь гарантировать, что заданное значение соответствует этой структуре данных.
type = any
здесь нет, поэтому вы можете пропустить определение ограничения типа, но вместо этого для очень редкой ситуации, когда модуль просто дословно передает структуру данных провайдеру, не интерпретируя ее вообще. Поскольку ваш модуль явно ожидает, что входная переменная будет картой объектов (в зависимости от того, как вы ее использовали), вы должны сообщить Terraform, какой тип объекта вы ожидаете получить:
variable "notification_channels" {
type = map(object({
type = string
display_name = string
labels = map(string)
enabled = bool
sensitive_labels = object({
auth_token = string
password = string
service_key = string
})
}))
}
Из вашего примера кажется, что вы хотите, чтобы sensitive_labels
был необязательным, чтобы вызывающий модуль мог его опустить. В этом случае вы можете использовать модификатор optional
при объявлении этого конкретного атрибута, а также трех атрибутов внутри него:
sensitive_labels = optional(object({
auth_token = optional(string)
password = optional(string)
service_key = optional(string)
}))
Атрибут, помеченный как optional
, может быть опущен вызывающей стороной, и в этом случае Terraform автоматически установит для него значение null
внутри вашего модуля, чтобы показать, что он не был установлен.
Теперь вы можете использовать эту переменную в другом месте вашего модуля и с уверенностью предположить, что она всегда будет иметь именно тот тип, который определен в блоке variable
:
resource "google_monitoring_notification_channel" "channels" {
for_each = var.notification_channels
project = var.project_id
type = each.value.type
display_name = each.value.display_name
description = each.value.description
labels = each.value.labels
enabled = each.value.enabled
dynamic "sensitive_labels" {
for_each = each.value.sensitive_labels[*]
content {
auth_token = sensitive_labels.value.auth_token
password = sensitive_labels.value.password
service_key = sensitive_labels.value.service_key
}
}
}
Выражение each.value.sensitive_labels[*]
— это выражение с платами, использующее функцию одиночных значений в виде списков, которая кратко преобразует заданное значение либо в список из одного элемента, либо в список из нулевого элемента, в зависимости от того, является ли значение нулевым. Фактически это означает, что будет один блок sensitive_labels
, если each.value.sensitive_labels
установлен, и ноль блоков этого типа, если этот атрибут не установлен (null
).
Атрибуты внутри этих блоков также могут быть просто назначены напрямую без какой-либо специальной логики, потому что Terraform автоматически установит для них значение null
, если оно не указано вызывающей стороной, а установка аргумента ресурса на null
всегда равнозначна его полному отсутствию.
Если вы потратите время на описание ожидаемых типов переменных, то логика в другом месте модуля будет намного проще, потому что вам больше не нужно иметь дело со всеми способами, которыми вызывающая сторона может передать вам неверное значение: Terraform либо автоматически преобразует значение в ожидаемый тип, если это возможно, либо сообщит вызывающей стороне об ошибке, объясняя, почему предоставленное значение неприемлемо.
Эй, Мартин. Большое спасибо за подробное объяснение. Определенно имеет смысл.
«Есть ли лучший способ, который не кажется хакерским?» почему вы думаете, что это "хакерский"?