Перейти к содержимому

Задача

Задача — одна запись списка tasks: в Destiny или сценарии: module: с его params: и ключами вокруг (register:, when:, loop:, …). Полная грамматика — на странице Destiny. Здесь — что происходит со входом задачи, её отрендеренными params:, когда одна задача идёт на много хостов.

Задачи рендерит Keeper; Soul получает значения, а не выражения. Когда задача идёт на несколько хостов, вход у хостов может различаться: ${ soulprint.self.sid }, vars самого хоста, loop: по фактам хоста. Правило — четыре шага.

Keeper рендерит params: задачи отдельно для каждого хоста, в контексте этого хоста: soulprint.self.*, vars хоста, переменные цикла. Так для каждой задачи, в том числе для той, в чьих params нет ни одного выражения.

После рендера Keeper сравнивает params каждого хоста с params первого (хосты упорядочены по SID):

  • все совпали — у задачи один вход на всех хостов. Это обычный случай, и ничего по хостам не хранится;
  • не совпал хотя бы один — у задачи полный вход для каждого хоста, включая совпавшие. Частичная карта отправила бы пропущенным хостам значения первого — ровно та молчаливая подмена, от которой это правило защищает.

Ключ, который есть у одного хоста и отсутствует у другого, — тоже расхождение. Одно исключение: у core.file.rendered render_context шаблона (факты, которые шаблон читает через .self) едет по хостам отдельно и в сравнении не участвует.

Каждый хост получает своё сообщение, поэтому каждая машина получает ровно свой вход. На проводе ничего не склеивается.

План прогона — то, что показывают деталь прогона в веб-UI и GET /v1/incarnations/{id}/runs/{apply_id}/tasks, — хранит одну карту params на задачу: вход первого хоста. Перед записью идут два прохода, в таком порядке:

  1. маскирование — каждое запечатанное значение (vault(), секретный input, …) заменяется маской;
  2. пометка — каждый ключ верхнего уровня, значение которого у хостов различается, заменяется на <per-host>.

Значит, <per-host> — пометка показа, а не маска: она говорит «значений несколько», а не «значение секретное». Ключи, совпавшие у всех хостов, видны как есть. Замаскированное остаётся маской — маска важнее пометки. Сравнение только по верхнему уровню: если внутри вложенной карты различается одно поле, помечается весь ключ верхнего уровня.

Пример — задача write marker на трёх хостах:

- name: write marker
module: core.file.present
params:
path: /tmp/demo-marker
content: '${ soulprint.self.sid }'
хост soul-1 получает: {path: /tmp/demo-marker, content: soul-1}
хост soul-2 получает: {path: /tmp/demo-marker, content: soul-2}
хост soul-3 получает: {path: /tmp/demo-marker, content: soul-3}
деталь прогона: {path: /tmp/demo-marker, content: <per-host>}

Задача вроде cmd: hostname имеет одинаковый вход на всех хостах и показывается как есть. Различается её вывод, и деталь прогона показывает вывод каждого хоста (stdout, stderr, exit_code) в его собственной строке.

Входы по хостам не сохраняются: после отправки в плане прогона остаётся только помеченная карта, и фактический вход хоста из прогона не прочитать. Смотрите результат на самом хосте или его вывод. Показ входа каждого хоста в детали прогона запланирован.