У меня есть файл Terraform locals.tf
, подобный приведенному ниже фрагменту, который содержит определение моей среды.
locals {
environments = [
"dev",
"test",
"preprod",
"prod"
]
}
Сейчас я хочу создать идентичный ресурс, в данном случае оповещение о метрике монитора Azure, для каждой из перечисленных сред (кроме prod). Я пытаюсь сделать это, используя цикл For_Each
в блоке ресурсов моего main.tf
файла, фрагмент которого показан ниже:
resource "azurerm_monitor_metric_alert" "main" {
for_each = {
[for s in toset(local.environments) : if s != "prod"]
}
name = "${each.key}-metric-alert"
resource_group_name = azurerm_resource_group.rg.name
scopes = [azurerm_storage_account.to_monitor[each.key].id]
[..........ADDITIONAL NON-PROD RESOURCE CONFIG...........]
Однако для рабочей среды оповещение монитора требует немного другого набора настроек, чем другие, поэтому я хотел бы отфильтровать эту среду из файла locals.tf
, а затем, используя другой блок ресурсов azurerm_monitor_metric_alert, настроить его по строки приведенного ниже фрагмента:
resource "azurerm_monitor_metric_alert" "main" {
for_each = {
[for s in toset(local.environments) : if s == "prod"]
}
name = "${each.key}-metric-alert"
resource_group_name = azurerm_resource_group.rg.name
scopes = [azurerm_storage_account.to_monitor[each.key].id]
[..........ADDITIONAL PROD CONFIG...........]
Я пробовал описанные выше и другие реализации, но, к сожалению, просто не могу заставить это работать. Был бы очень признателен за помощь здесь.
Вы не указали, какую ошибку получаете, но в ваших циклах for
отсутствует один аргумент:
[for s in toset(local.environments) : s if s != "prod"]
И:
[for s in toset(local.environments) : s if s == "prod"]
Также я не уверен, нужно ли вам это toset
там. Возможно, потребуется поместить весь цикл for
внутрь toset
, а не local.environments
.
Со следующим выражением возникает несколько различных проблем:
for_each = {
[for s in toset(local.environments) : if s != "prod"]
}
В выражении for
отсутствует предложение результата после двоеточия. Если вы намерены просто вернуть s
напрямую, вы можете просто указать эту переменную между двоеточием и ключевым словом if
:
[for s in toset(local.environments) : s if s != "prod"]
Фигурные скобки {
}
вокруг этого выражения недействительны. Этот синтаксис предназначен для создания значения объектного типа, но для того, чтобы это работало, вам нужно указать атрибут, которому будет присвоен результат выражения for
.
Поскольку var.environments
кажется просто набором строк, я ожидаю, что вы, вероятно, захотите создать набор строк напрямую, без какой-либо карты/объекта-обертки, например:
for_each = toset([for s in local.environments : s if s != "prod"])
Внутренний toset
, который вы ранее использовали для local.environments
, на самом деле здесь ничего не добавляет, потому что выражение for
эффективно обрабатывает набор строк как список этих строк в лексическом порядке. Вы можете безопасно удалить его, как я сделал в своем последнем примере выше, и этого будет достаточно для данного конкретного использования `local.environments.
Если вы хотите сообщить, что local.environments
сам по себе семантически является набором — что может быть полезно будущим сопровождающим вашего модуля, пытающимся понять, что вы задумали, — тогда вы можете вместо этого поместить toset
в определение локального значения:
locals {
environments = toset([
"dev",
"test",
"preprod",
"prod",
])
}
Однако это не повлияет на выражение for_each
, о котором идет речь в этом вопросе, поэтому это будет значимым изменением только в том случае, если local.environments
будет использоваться в других местах, которые также должны рассматривать его как набор, и это выходит за рамки этого вопроса.
Это просто гений Мартин Аткинс!! Я реализовал предложенное решение, и оно сработало блестяще => for_each = toset([for s in local.environments : s if s != "prod"]). Меня также привлекло ваше замечание относительно использования toset
и local.environments
. Хотелось бы увидеть пример того, как можно было бы преобразовать список local.environments
с использованием toset
и без него.
Возможно, есть лучшие способы добиться того, чего вы хотите, в одном блоке ресурсов. Можете ли вы поделиться остальной конфигурацией для рабочей и непроизводственной версии?