openlang

Ключи for_each - это адреса, а не ярлыки

Ключ for_each - не ярлык. Это половина адреса ресурса, terraform_data.queue["prod-orders"], и состояние хранит объект именно под этим адресом. Поменяйте ключ, и план не увидит переименования. Он увидит один объект на удаление и другой на создание.

Поэтому я нервничаю, когда ключи получаются из выражения.

locals {
  queues = { for q in var.queues : "${q.env}-${q.name}" => q }
}

resource "terraform_data" "queue" {
  for_each = local.queues
  input    = each.value
}

Выглядит безобидно. Потом кто-то решает, что имя лучше ставить первым, правит одну строку в locals, и дифф на ревью длиной в одну строку. Замена всех экземпляров видна в плане, а план как раз пролистывают. Я предпочитаю ключи, выписанные в файле, или взятые напрямую из одного поля, которое не меняется, а всю хитрую перестройку держать в значениях.

Разговор продолжается 6

Следуя доводам
  1. Ссылка на ответ

    А можно сделать сам список ключей частью того, что печатает план? Подозреваю, что проблема ревью не столько в выражении, сколько в том, что на ключи никто не смотрит как на множество. Output с keys(local.queues) вывел бы весь список в изменениях outputs в плане, и переформатированный ключ выглядел бы там как список, где поменялся каждый элемент, а такое трудно пролистать. Это не доказательство, что ничего не заменится, просто дешёвая вещь, которую можно попробовать на одном модуле.

  2. Ссылка на ответ

    Видно будет, но опираться на это всё равно не стоит. План и так перечисляет каждое удаление и каждое создание по адресу, так что информации хватало всегда. Не хватает ревьюера, который её читает, а output добавляет ещё одно место, которое не прочтут. Если нужно, чтобы что-то падало, считайте действия delete в JSON плана в CI и роняйте задачу, если они есть, а изменение никто не пометил как намеренное.

  3. Ссылка на ответ

    Под этим лежит вопрос, какие поля составляют идентичность очереди, а какие - её атрибуты. Если env определяет, где очередь живёт, ему место в ключе. Если это тег, который может поменяться, то, попав в ключ, он превращает правку атрибута в замену. Само выражение не проблема. Проблема - выражение, которое смешивает одно с другим. Приняли бы вы вычисляемый ключ, если бы он читал только поля, которые модуль документирует как неизменные?

  4. Ссылка на ответ

    И ещё, "${q.env}-${q.name}" - любимая дурная привычка тех, кто пишет регулярки, склейка через разделитель, который может встретиться внутри частей. env = "eu-west" с name = "orders" и env = "eu" с name = "west-orders" оба дают eu-west-orders. Хорошая новость в том, что выражение for не оставляет молча последний ключ, а отказывается от дубликатов, так что узнаёте вы об этом на этапе плана. Выберите разделитель, которого не бывает в именах, или повесьте на переменную блок validation, который его отвергает.

  5. Ссылка на ответ

    Такой случай мне как раз нравится. Он останавливает план ошибкой. Тихий случай - переформатирование, после которого ключи всё ещё уникальны. Ничего не падает, а все экземпляры заменяются. Если формат действительно надо поменять, блок moved на каждый экземпляр связывает старый адрес с новым, и план показывает перенос вместо удаления. Писать сорок таких вручную скучно, и в основном поэтому я держу формат ключей скучным.

  6. Ссылка на ответ

    Может быть, выражение можно оставить и просто лишить его права делать ключи. Держать map в файле литералом, ключи вписать руками, а выражению дать строить из неё только значения. Тогда смена ключа будет видимой правкой в диффе на ревью, а перестройка, которую не любит dario, может жить в значениях, где изменение обычно остаётся обновлением на месте, если сам атрибут не требует замены.

Другие стороны того же вопроса

  1. tryEval пропустил нарочно сломанный пакет

    Есть у меня небольшой обход оверлея, который оборачивает каждый пакет в builtins.tryEval и перечисляет упавшие. Он сообщил, ч…

    Ответы 4nix
  2. Остановленное задание оболочки ещё не завершено

    Пришёл вопрос про правило супервизора, которое считает остановленный процесс завершённым, и маленький пример сразу показывает…

    Ответы 17bashpython
  3. Циклам и условиям не место в build.gradle

    Попался build.gradle, где половина логики жила в замыканиях, которым во время выполнения подменяли delegate. Долго разбирался…

    Ответы 6groovy