Spec-Zone.ru › Ansible

Руководство по переносу Ansible-core 2.19

В этом разделе рассматриваются изменения поведения между ansible-core 2.18 и ansible-core 2.19.

Руководство поможет обновить плейбуки, плагины и другие компоненты инфраструктуры Ansible, чтобы они работали с этой версией Ansible.

Изучите эту страницу и список изменений ansible-core 2.19, чтобы понять, какие изменения необходимо внести.

Этот документ входит в подборку руководств по переносу. Полный список руководств по переносу приведен в разделе руководства по переносу.

  • Введение
  • Плейбук

    • Некорректные условные выражения

      • Пример — неявное преобразование в логический тип
      • Пример — непреднамеренное истинное условие
      • Пример — синтаксическая ошибка в выражении
      • Пример — порядок операций в Jinja
      • Пример — словарь в качестве условия
    • Многоэтапная обработка шаблонов

      • Пример — ненужный шаблон в выражении
      • Пример — динамическое построение выражения
    • Диагностика проблем с недоверенными шаблонами
    • Циклы больше не передают служебные заполнители omit

      • Пример — отсутствующий default(omit)
    • Тайм-ауты повышения привилегий
  • Ядро

    • Обработка шаблонов

      • Инверсия модели доверия шаблонам
      • Обязательный нативный режим Jinja

        • Пример — непреднамеренное преобразование в строку
        • Пример — непреднамеренный результат None
      • Отложенная обработка шаблонов
      • Единообразная обработка range

        • Пример — намеренное преобразование в список
        • Пример — непреднамеренное преобразование в строку
    • Обработка ошибок

      • Контекстные предупреждения и ошибки
      • Отслеживание происхождения переменных
      • Предупреждения об устаревании при обращении к значениям
      • Улучшенная обработка ошибок модулей Ansible
      • Улучшенная обработка неопределенных значений

        • Пример — отсутствующий атрибут
      • Отображение трассировок стека
      • Предупреждение при наличии неопределенных переменных в файлах vars
  • API плагинов

    • Пометка значений как устаревших
    • Применение доверия к шаблону для отдельных значений
    • Применение доверия к шаблону в плагинах inventory и vars
    • Генерация исключений
    • Слишком широкая обработка исключений в плагинах Jinja
    • Пользовательские типы данных Ansible
    • AnsibleVaultEncryptedUnicode заменен на EncryptedString
    • Нет неявного преобразования строковых ключей словаря
  • Командная строка
  • Устаревшее
  • Модули

    • Удаленные модули
    • Уведомления об устаревании
    • Важные изменения модулей
  • Плагины

    • Важные изменения плагинов
  • Перенос пользовательских скриптов
  • Сетевые функции

Введение

В этом выпуске переработана система обработки шаблонов и добавлена новая функция, получившая название «Тегирование данных». Эти изменения позволяют выявлять многочисленные проблемные ситуации, которые оставались незамеченными в предыдущих выпусках, и оказывают широкое положительное влияние на безопасность, производительность и удобство использования.

Обратная совместимость сохранена там, где это было практически возможно, однако избежать некоторых несовместимых изменений не удалось. В этом руководстве описаны распространенные проблемные сценарии, примеры содержимого, сообщения об ошибках и предлагаемые решения.

Рекомендуем проверить плейбуки и роли в тестовой среде с этим выпуском, чтобы определить, где потребуется внести изменения.

Плейбук

Некорректные условные выражения

Условные выражения некорректны, если входное выражение или шаблон не является строкой либо результат не является логическим значением. Python и Jinja неявно интерпретируют как «истинные» большинство непустых значений, не являющихся логическими, в условных выражениях. Такая оценка истинности иногда удобна и позволяет писать короче, но часто маскирует серьезные логические ошибки в плейбуках, которые предыдущие версии ansible-core не могли надежно выявить.

Изменения обработки шаблонов в этом выпуске позволяют обнаруживать условные выражения с результатом, отличным от логического значения, во время вычисления выражения и по умолчанию сообщать об ошибке. С помощью настройки конфигурации ALLOW_BROKEN_CONDITIONALS ошибку можно временно заменить предупреждением.

В следующих примерах показаны некорректные условные выражения, маскировавшие логические ошибки в реальных плейбуках.

Пример — неявное преобразование в логический тип

Это выражение полагается на неявную оценку inventory_hostname как истинного значения. Вместо этого следует использовать явный предикат с логическим результатом, например | length > 0 или is truthy.

- assert:
    that: inventory_hostname

Сообщение об ошибке:

Conditional result was 'localhost' of type 'str', which evaluates to True. Conditionals must have a boolean result.

Исправить это можно, выполнив явное преобразование в логическое значение:

- assert:
    that: inventory_hostname | length > 0

Пример — непреднамеренное истинное условие

Вторая часть этого условия ошибочно заключена в кавычки. Заключенная в кавычки часть становится результатом выражения (который оценивается как истинный), поэтому выражение никогда не может быть False.

- assert:
    that: inventory_hostname is defined and 'inventory_hostname | length > 0'

Сообщение об ошибке:

Conditional result was 'inventory_hostname | length > 0' of type 'str', which evaluates to True. Conditionals must have a boolean result.

Исправить это можно, убрав лишние кавычки:

- assert:
    that: inventory_hostname is defined and inventory_hostname | length > 0

Пример — синтаксическая ошибка в выражении

Предыдущие выпуски Ansible могли маскировать некоторые синтаксические ошибки выражений, возвращая истинное значение.

- assert:
    that: 1 == 2,
#               ^ invalid comma

Сообщение об ошибке:

Syntax error in expression: chunk after expression

Исправить это можно, удалив недопустимую запятую после выражения.

Пример — порядок операций в Jinja

В этом выражении используется оператор конкатенации ~, который выполняется после проверки contains. Результатом всегда является непустая строка, которая считается истинной.

- assert:
    that: inventory_hostname is contains "local" ~ "host"

Сообщение об ошибке:

Conditional result was 'Truehost' of type 'str', which evaluates to True. Conditionals must have a boolean result.

Исправить это можно, добавив скобки, чтобы выполнить операцию конкатенации до проверки contains:

- assert:
    that: inventory_hostname is contains("local" ~ "host")

Пример — словарь в качестве условия

Это условие следовало заключить в кавычки. В элементе списка YAML строка без кавычек, содержащая пробел после двоеточия, интерпретируется анализатором YAML как отображение. Непустые отображения всегда считаются истинными.

- assert:
    that:
     - result.msg == "some_key: some_value"
#                             ^^ colon+space == problem

Сообщение об ошибке:

Conditional expressions must be strings.

Исправить это можно, заключив все выражение утверждения в кавычки:

- assert:
    that:
     - 'result.msg == "some_key: some_value"'

Многоэтапная обработка шаблонов

Ранее встраивание шаблонов в другие шаблоны или выражения могло приводить к выполнению недоверенных шаблонов. Переработанный механизм обработки шаблонов в этом выпуске больше не поддерживает такое небезопасное поведение.

Пример — ненужный шаблон в выражении

В этом условии переменная указывается с помощью шаблона вместо прямого обращения к ней в выражении.

- assert:
    that: 1 + {{ value }} == 2
  vars:
    value: 1

Сообщение об ошибке:

Syntax error in expression. Template delimiters are not supported in expressions: expected token ':', got '}'

Исправить это можно, обратившись к переменной без шаблона:

- assert:
    that: 1 + value == 2
  vars:
    value: 1

Пример — динамическое построение выражения

Это условие динамически создается с помощью шаблона, который, как предполагается, должен быть вычислен как выражение. Ранее шаблон обрабатывался при обработке аргументов задачи, в результате чего получалась обычная строка, которую позднее вычисляло действие assert.

- assert:
    that: inventory_hostname {{ comparison }} 'localhost'
  vars:
    comparison: ==

Сообщение об ошибке:

Syntax error in expression. Template delimiters are not supported in expressions: chunk after expression

Динамическое построение выражений в плейбуках небезопасно и не поддерживается.

Диагностика проблем с недоверенными шаблонами

По умолчанию недоверенные шаблоны молча игнорируются. Для диагностики проблем с доверием к шаблонам можно включить предупреждения или ошибки для недоверенных шаблонов. Управлять этим поведением можно с помощью переменной среды _ANSIBLE_TEMPLAR_UNTRUSTED_TEMPLATE_BEHAVIOR.

Допустимые значения:

  • warning — при обнаружении недоверенного шаблона будет выведено предупреждение.
  • error — при обнаружении недоверенного шаблона будет вызвана ошибка.
  • ignore — недоверенные шаблоны молча игнорируются и используются как есть. Это поведение используется по умолчанию.

Примечание

Это необязательное поведение, связанное с предупреждениями и ошибками, является экспериментальным и может измениться в будущих версиях.

Циклы больше не передают служебные заполнители omit

Заполнители omit больше не передаются между обработкой шаблонов элементов цикла и обработкой шаблонов задачи.

Ранее заполнители omit могли оставаться во встроенном виде в элементах цикла после обработки шаблона и использоваться как omit при обработке шаблона задачи. Теперь значения, результатом которых является omit, сразу удаляются при обработке шаблонов элементов цикла.

Чтобы преобразовать отсутствующие значения в omit для обработки шаблона задачи, используйте | default(omit). Это решение обратно совместимо с предыдущими версиями ansible-core.

Пример — отсутствующий default(omit)

Следующая задача пытается передать omit из цикла в задачу, но значение не определено, поскольку оно было пропущено:

- debug:
    msg: "{{ item.msg }}"  # 'msg' is undefined
  loop:
   - msg: "{{ omit }}"  # 'msg' will be omitted from the loop item

В этой обновленной задаче для отсутствующего значения используется default(omit), чтобы оно было пропущено при обработке задачи:

- debug:
    msg: "{{ item.msg | default(omit) }}"  # 'msg' is undefined, use 'default(omit)' to turn it into an omit
  loop:
   - msg: "{{ omit }}"  # passed through in earlier versions, this value is now omitted from the loop item

Тайм-ауты повышения привилегий

Тайм-аут ожидания повышения привилегий (become) теперь приводит к ошибке недоступности узла, а не к ошибке задачи. В существующих плейбуках следует заменить ignore_errors на ignore_unreachable для задач, в которых тайм-аут become следует игнорировать.

Ядро

Обработка шаблонов

Инверсия модели доверия шаблонам

Ранее ansible-core неявно считал все строковые значения доверенными и обрабатывал их как шаблоны Jinja, но строки из недоверенных источников (например, результаты модулей) оборачивал в объект «небезопасной» строки. Механизм обработки шаблонов молча игнорировал строки в такой оболочке, поскольку многие операции с шаблонами могут выполнять произвольный код на управляющем узле от имени пользователя, запускающего ansible-core. Поэтому любой код, работающий со строками, должен был правильно передавать объект-оболочку, что привело к появлению многочисленных уязвимостей RCE (удаленного выполнения кода), достойных присвоения CVE.

В этом выпуске предыдущая модель доверия инвертирована. Обрабатывать как шаблоны можно только строки, помеченные как загруженные из доверенного источника. На недоверенные значения, как и раньше, можно ссылаться в шаблонах, но само выражение шаблона всегда должно быть доверенным. Хотя при таком изменении по-прежнему необходимо учитывать передачу маркеров доверия при работе со строками, их отсутствие теперь приводит к утрате возможности обработки шаблона, а не к потенциально серьезной проблеме безопасности.

Попытки обработать шаблон, содержащийся в недоверенной строке, как и раньше, возвращают исходную строку без изменений. По умолчанию попытки обработать недоверенный шаблон безуспешно завершаются без вывода сообщений, однако с помощью конфигурации такие ситуации можно преобразовать в предупреждения или ошибки.

Для строк, созданных в результате операций с шаблонами, доверие не применяется автоматически. Однако шаблоны, возвращающие существующие доверенные строки без изменений, не снимают с них отметку доверия. Плагины также могут явно применять доверие.

В большинстве случаев совместимое с предыдущими версиями поведение доверия к шаблонам применяется автоматически. Например, шаблоны в плейбуках, ролях, файлах переменных и большинстве встроенных плагинов инвентаризации будут считаться доверенными. Пользовательским плагинам, получающим строки шаблонов из источников, потребуется использовать новые общедоступные API для применения доверия там, где это необходимо.

Дополнительные сведения см. в разделах API плагинов и Диагностика проблем с недоверенными шаблонами.

Обязательный нативный режим Jinja

Предыдущие версии поддерживали два режима обработки шаблонов:

  • Исходный режим обработки строк в Jinja преобразовывал результат каждой операции обработки шаблона в строку.
  • Нативный режим Jinja обычно сохранял типы переменных в результатах шаблонов.

В обоих режимах ansible-core вычислял результаты обработки конечных строк шаблонов как литералы Python, а в случае ошибки возвращал исходную строку. Выбор режима обработки шаблонов задавался конфигурацией; по умолчанию использовался исходный режим обработки строк Jinja.

Теперь используется исключительно нативный режим обработки шаблонов Jinja. Параметр конфигурации для выбора режима обработки шаблонов объявлен устаревшим и больше не оказывает никакого влияния.

Сохранение нативных типов при обработке шаблонов улучшено, чтобы устранить пробелы в предыдущей реализации; заключительный этап вычисления литералов полностью удален (он часто вызывал путаницу, ошибки и проблемы с производительностью). В редких случаях, когда плейбуки полагались на неявное преобразование объектов из строк, потребуется явное преобразование.

Некоторые существующие шаблоны могут непреднамеренно преобразовывать значения, не являющиеся строками, в строки. В предыдущих версиях это преобразование могло маскироваться вычислением строк в качестве литералов Python.

Пример — непреднамеренное преобразование в строку

В этом выражении в фильтр replace по ошибке передается список, хотя он работает только со строками. Фильтр молча преобразует входной список в строку. Поскольку ранее некоторые строковые результаты преобразовывались в списки при разборе, эта ошибка часто оставалась незамеченной в предыдущих версиях.

- debug:
    msg: "{{ ['test1', 'test2'] | replace('test', 'prod') }}"

Результатом этого шаблона становится строка:

ok: [localhost] => {
    "msg": "['prod1', 'prod2']"
}

Исправить это можно с помощью фильтра map, который применяет фильтр replace к каждому элементу списка:

- debug:
    msg: "{{ ['test1', 'test2'] | map('replace', 'test', 'prod') }}"

Результатом исправленного шаблона остается список:

ok: [localhost] => {
    "msg": [
        "prod1",
        "prod2"
    ]
}
Пример — непреднамеренный результат None

Если результатом обработки шаблона было None, в предыдущих версиях ansible-core он неявно преобразовывался в пустую строку. Теперь шаблон может вычисляться в значение None.

В следующем примере показан такой случай:

- set_fact:
    # If 'foo' is not defined, the else branch basically evaluates to None.
    # So value_none will not be an empty string, but None:
    value_none: |-
      {% if foo is defined %}foo is defined{% endif %}

Этот пример можно исправить следующим образом:

- set_fact:
    # Explicitly return an empty string in the 'else' branch.
    # The value is always a string: either "foo is defined" or "".
    value_none: |-
      {% if foo is defined %}foo is defined{% else %}{{ "" }}{% endif %}

Это изменение обратно совместимо с предыдущими версиями ansible-core.

Примечание

Начиная с ansible-core 2.19.1 параметры модулей со строковым типом принимают None и преобразуют его в пустую строку. До ansible-core 2.18 передача None таким параметрам приводила к ошибке. Это означает, что в большинстве случаев нет необходимости корректировать выражения в ролях и плейбуках из-за непреднамеренных результатов None.

Отложенная обработка шаблонов

Интерфейс Ansible к механизму обработки шаблонов Jinja был существенно усовершенствован, что значительно повысило производительность многих сложных операций с шаблонами. Ранее глубоко вложенные, рекурсивные или ссылающиеся на себя операции обработки шаблонов всегда вычислялись полностью при каждом обращении, в том числе при повторном обращении к одним и тем же данным в рамках одной операции обработки шаблона. Это приводило к затратному повторному вычислению одних и тех же шаблонов в рамках одной логической операции, даже если шаблоны находились глубоко во вложенных структурах данных и к ним не обращались напрямую. Новый механизм шаблонов откладывает практически всю рекурсию и обработку до момента обращения к значениям или до момента, когда становится известно, что они покидают механизм обработки шаблонов. Промежуточные вложенные или косвенно обработанные результаты шаблонов кэшируются на время выполнения операции, что сокращает количество повторных вычислений. В реальных сценариях со сложными шаблонами эти изменения обеспечили экспоненциальный рост производительности.

Единообразная обработка range

Результат использования глобальной функции Jinja range() сильно зависел от контекста ее вызова и от того, был ли включен нативный режим Jinja. Чтобы сохранить возможность использовать очень большие диапазоны в цепочках фильтров, теперь функция всегда возвращает объект range. Это означает, что его нельзя вернуть из шаблона без предварительного преобразования в возвращаемый тип.

Пример — намеренное преобразование в список
- debug:
  loop: "{{ range(0, 2) }}"

Диапазоны, не включенные в контейнеры, обычно преобразовывались в списки при финализации шаблона. Теперь это приводит к следующей ошибке:

Error rendering template: Type 'range' is unsupported for variable storage.

Исправить это можно, выполнив преобразование явно:

- debug:
  loop: "{{ range(0, 2) | list }}"
Пример — непреднамеренное преобразование в строку
- debug:
    msg: "{{ [range(0,2), range(7,10)] }}"

Диапазоны, включенные в контейнеры, обычно преобразовывались в строковое представление объекта range.

ok: [localhost] => {
    "msg": "[range(0, 2), range(7, 10)]"
}

Теперь такая попытка приводит к ошибке. Чтобы воспроизвести прежнее поведение, можно явно преобразовать контейнер в строку или преобразовать диапазоны в списки, если вы действительно хотите использовать их для чего-либо полезного.

- debug:
    msg: "{{ [range(0,2), range(7,10)] | string }}"

- debug:
    msg: "{{ [range(0,2), range(7,10)] | map('list') }}"

Обработка ошибок

Контекстные предупреждения и ошибки

Изменения внутренней обработки ошибок в ansible-core будут заметны во многих ситуациях, приводящих к предупреждению или ошибке. В большинстве случаев в сообщениях для пользователей указываются операционный контекст (что происходило в момент возникновения ошибки или предупреждения) и задействованные элементы данных. Ошибки и предупреждения, возникающие во время выполнения задачи, более последовательно включаются в результат задачи. Полная информация доступна обработчикам обратных вызовов, а в случае ошибок краткое сообщение об ошибке содержится в поле msg результата. Из-за стандартизированного характера обработки ошибок в некоторых сообщениях могут встречаться кажущиеся избыточными элементы. Со временем они будут улучшаться по мере доработки обработки ошибок, но сейчас необходимы для обеспечения правильного контекста во всех ситуациях возникновения ошибок. Содержимое сообщений об ошибках не считается стабильным, поэтому по возможности не следует создавать автоматизацию, зависящую от него.

Отслеживание происхождения переменных

Новая функция «Тегирование данных» расширяет отслеживание происхождения переменных практически на все источники. Это позволяет предоставлять более подробные сообщения об ошибках, поскольку можно проследить всю цепочку выполнения и добавить контекстную информацию о том, что происходило в момент возникновения ошибки. В большинстве случаев указываются путь к файлу, строки исходного кода и маркеры столбцов. Поддерживаются также источники переменных, не связанные с файлами, например аргументы CLI, плагины инвентаризации и окружение.

Предупреждения об устаревании при обращении к значениям

Новые функции позволяют помечать как устаревшие большинство переменных и значений ansible-core. Плагины и модули могут применять эти метки, дополняя устаревшие элементы возвращаемых значений описанием и справочным текстом с предложением альтернатив. При обращении к помеченному значению, например из плейбука или шаблона, во время выполнения будет выведено предупреждение. Это упрощает изменение и удаление результатов модулей и фактов, а также устаревшего поведения ядра.

Например, обращение к устаревшей магической переменной play_hosts вызовет предупреждение об устаревании с рекомендацией использовать вместо нее переменную ansible_play_batch.

Улучшенная обработка ошибок модулей Ansible

Обработку исключений для модулей Ansible, реализованных на Python, теперь обеспечивает оболочка AnsiballZ. В предыдущих версиях ansible-core необработанные исключения в модуле Ansible просто выводили трассировку стека и завершали работу без стандартного ответа модуля. В результате задача получала общее сообщение MODULE FAILURE и любой необработанный текстовый вывод модуля.

Для решения этой проблемы в модулях часто реализовывали ненужные блоки try/except вокруг большей части кода, для которого нельзя было предусмотреть специальную обработку ошибок, только чтобы вызвать AnsibleModule.fail_json с общим сообщением о сбое. Теперь такой подход не нужен: все необработанные исключения в модулях Ansible на Python перехватываются оболочкой AnsiballZ и возвращаются в виде структурированного результата модуля. Если контроллер включил соответствующую настройку, информация о трассировке стека добавляется автоматически.

Улучшенная обработка неопределенных значений

Обработка неопределенных значений улучшена, чтобы избежать ситуаций, в которых плагин Jinja молча игнорирует такие значения.

Чаще всего это происходит, когда плагин Jinja, например фильтр или проверка, определяет тип переменной, не учитывая возможность наличия неопределенного значения.

Пример — отсутствующий атрибут

В этой задаче в условии ошибочно указывается неопределенный атрибут exists результата stat. В предыдущих версиях неопределенное значение не обнаруживалось, поскольку передавалось плагину проверки Jinja false, который молча игнорирует неопределенные значения. В результате в предыдущих версиях ansible-core это условие никогда не могло быть True, и ничто не указывало на то, что выражение failed_when было недопустимым.

- stat:
    path: /does-not-exist
  register: result
  failed_when: result.exists is false
  #                   ^ missing reference to stat

В текущем выпуске ошибочное выражение обнаруживается и приводит к ошибке.

Исправить это можно, добавив в условие отсутствующий атрибут stat:

- stat:
    path: /does-not-exist
  register: result
  failed_when: result.stat.exists is false

Отображение трассировок стека

В предыдущих версиях ansible-core трассировки стека для некоторых ошибок на стороне контроллера можно было получить, увеличив подробность вывода с помощью параметра -vvv, но доступность этой функции и ее поведение были непоследовательными. Кроме того, функция работала только для ошибок.

Обработка ошибок, предупреждений и уведомлений об устаревании в большей части кодовой базы ansible-core теперь стандартизирована. С помощью переменной среды ANSIBLE_DISPLAY_TRACEBACK можно включить сбор и отображение трассировок стека для всех исключений, а также в месте возникновения ошибок, предупреждений или уведомлений об устаревании (в том числе в коде модулей).

Допустимые значения:

  • always — трассировки стека отображаются всегда. Этот параметр имеет приоритет над всеми приведенными ниже.
  • never — трассировки стека никогда не отображаются. Этот параметр имеет приоритет над всеми приведенными ниже.
  • error — трассировки стека отображаются для ошибок.
  • warning — трассировки стека отображаются для всех предупреждений, кроме предупреждений об устаревании.
  • deprecated — трассировки стека отображаются для предупреждений об устаревании.

Можно указать несколько значений, разделив их запятыми.

Предупреждение при наличии неопределенных переменных в файлах vars

В предыдущих версиях ansible-core неопределенные переменные, использовавшиеся при указании путей к файлам в vars_files, молча игнорировались и не вызывали предупреждений. Теперь поведение изменено: при обнаружении неопределенных переменных во время указания путей к файлам в vars_files будет выводиться предупреждение.

- hosts: all
  vars_files:
    - "{{ inventory_dir }}/vars_files/bar.yml"
PLAYBOOK: foo.yml ************************************************************************
1 plays in foo.yml
[WARNING]: skipping vars_file item due to an undefined variable
Origin: /examples/foo.yml:6:7

4
5   vars_files:
6     - "{{ inventory_dir }}/vars_files/bar.yml"
        ^ column 7

В приведенном выше примере предупреждение отображается, поскольку inventory_dir — это переменная уровня узла, вычисляемая на уровне задачи, а не на уровне плейбука, где обрабатывается vars_files. Хотя inventory_dir не работает в vars_files, ее можно использовать в переменных уровня задачи, где уже доступны переменные из vars_files.

API плагинов

Устаревание значений

Плагины и модули Python могут помечать возвращаемые значения как устаревшие с помощью новой функции deprecate_value из ansible.module_utils.datatag. К значению можно добавить описание устаревшей функции, необязательный текст справки и сроки удаления. Они будут отображаться в предупреждении во время выполнения, если устаревшее значение используется в выражении. Сообщение предупреждения будет содержать информацию о модуле/плагине, который добавил тег устаревания, и о расположении выражения, в котором было выполнено обращение к этому значению.

from ansible.module_utils.datatag import deprecate_value

...

module.exit_json(
    color_name=deprecate_value(
        value="blue",
        msg="The `color_name` return value is deprecated.",
        help_text="Use `color_code` instead.",
    ),
    color_code="#0000ff",
)

При обращении к color_name из результата модуля будет показано следующее предупреждение

[DEPRECATION WARNING]: The `color_name` return value is deprecated. This feature will be removed from the 'ns.collection.paint' module in a future release.
Origin: /examples/use_deprecated.yml:8:14

6
7     - debug:
8         var: result.color_name
               ^ column 14

Use `color_code` instead.

Применение доверия к шаблонам для отдельных значений

По умолчанию строковые значения больше не считаются доверенными для обработки в качестве шаблонов. Строки, загруженные из плейбуков, файлов vars и других встроенных доверенных источников, обычно по умолчанию помечаются как доверенные. Плагины, создающие новые экземпляры строк со встроенными шаблонами, должны использовать новую функцию trust_as_template из ansible.template, чтобы помечать такие значения как полученные из доверенного источника и разрешать обработку шаблонов.

Предупреждение

Этот раздел и связанный с ним публичный API пока не завершены.

Применение доверия к шаблонам в плагинах инвентаризации и vars

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

Предупреждение

Этот раздел и связанный с ним публичный API пока не завершены.

Генерация исключений

При генерации исключений в обработчике исключений обязательно используйте raise ... from в соответствующих случаях. Это заменяет использование аргумента AnsibleError orig_exc для указания причины. Для обеспечения обратной совместимости по-прежнему разрешается указывать orig_exc в качестве причины.

Если при установленном orig_exc не использовать raise ... from, будет выдано предупреждение. Кроме того, если два исключения-причины не совпадают, будет выдано предупреждение.

Слишком широкая обработка исключений в плагинах Jinja

Плагины Jinja со слишком широкой обработкой исключений, например except Exception, могут работать некорректно при доступе к содержимому переменных-контейнеров (dict, list). Это может произойти, если шаблонное значение из переменной не определено, является незашифровываемым значением из хранилища vault или представляет собой другое значение, которое вызывает отложенное сообщение об ошибке.

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

Пользовательские типы данных Ansible

Многие объекты переменных в ansible-core представлены пользовательскими типами. В предыдущих версиях они могли иметь такие типы, как:

  • AnsibleUnicode (подкласс str)
  • AnsibleSequence (подкласс list)
  • AnsibleMapping (подкласс dict)

Эти и другие типы теперь имеют новые подклассы, производные от соответствующих встроенных типов Python. В большинстве случаев эти типы ведут себя так же, как расширяемые ими типы, и существующий код должен работать как обычно. Однако некоторые библиотеки Python некорректно обрабатывают подклассы встроенных объектов. Пользовательские плагины, взаимодействующие с такими библиотеками, могут потребовать изменений для преобразования и передачи встроенных типов.

Предупреждение

Этот раздел и связанный с ним публичный API пока не завершены.

AnsibleVaultEncryptedUnicode заменён на EncryptedString

Тип AnsibleVaultEncryptedUnicode заменён на EncryptedString.

Плагины, создающие AnsibleVaultEncryptedUnicode, теперь будут получать экземпляры EncryptedString. Эта функция обеспечивает обратную совместимость с предыдущими версиями ansible-core.

Плагины, выполняющие проверки isinstance на наличие AnsibleVaultEncryptedUnicode, больше не будут встречать эти типы. Значения, ранее представленные этим типом, теперь будут отображаться как помеченный str. Для доступа к содержимому этих значений специальная обработка в плагинах больше не требуется.

Неявное преобразование ключей словаря, не являющихся строками, больше не выполняется

В предыдущих версиях ansible-core полагался на json.dumps Python для неявного преобразования ключей словаря int, float, bool и None в строки в различных сценариях, в том числе при возврате результатов модуля. Например, модуль мог содержать следующий код:

oid = 123
d = {oid: "value"}
module.exit_json(return_value=d)

Начиная с этого выпуска, модули должны явно преобразовывать все ключи, не являющиеся строками, в строки (например, с помощью функции Python str()), прежде чем передавать словари методу AnsibleModule.exit_json() объекта ansible-core. Приведённый выше код необходимо изменить следующим образом:

oid = 123
d = {str(oid): "value"}
module.exit_json(return_value=d)

Если вы столкнулись с "[ERROR]: Task failed: Module failed: Key of type '<NON-STRING>' is not JSON serializable by the 'module_legacy_m2c' profile., это означает, что используемый в задаче модуль не выполняет требуемое преобразование ключей.

Командная строка

Заметных изменений нет

Устаревшие функции

Заметных изменений нет

Модули

  • В связи с изменениями в системе шаблонов свойства started и finished типа integer модуля async_status больше нельзя использовать в качестве значений в условных выражениях, поскольку для этого требуются логические значения. Вместо этого рекомендуется использовать тестовые плагины started и finished, например:
- async_status:
    jid: '{{ registered_task_result.ansible_job_id }}'
  register: job_result
  until: job_result is finished
  retries: 5
  delay: 10

Удалённые модули

Следующие модули больше не существуют:

  • Заметных изменений нет

Уведомления об устаревании

Заметных изменений нет

Важные изменения модулей

Заметных изменений нет

Плагины

Важные изменения плагинов

  • Плагин подключения ssh теперь поддерживает использование SSH_ASKPASS для передачи паролей аутентификации в качестве альтернативы программе sshpass. По умолчанию используется SSH_ASKPASS вместо sshpass. Это настраивается параметром password_mechanism для плагина подключения ssh. Чтобы вернуться к использованию sshpass, внесите одно из следующих изменений:

    В файл ansible.cfg:

    [ssh_connection]
    password_mechanism = sshpass
    

    Экспортировав переменную окружения:

    export ANSIBLE_SSH_PASSWORD_MECHANISM=sshpass
    

    Задав следующую переменную:

    ansible_ssh_password_mechanism: sshpass
    
  • Приведение нераспознанных входных значений в фильтре bool устарело. Фильтр bool теперь возвращает только True или False в зависимости от входных данных:

    • True — возвращается для True, 1 и строк, совпадающих без учёта регистра: “yes”, “on”, “true”, “1”
    • False — возвращается для False, 0 и строк, совпадающих без учёта регистра: “no”, “off”, “false”, “0”

    Любые другие входные данные приведут к предупреждению об устаревании. В ansible-core 2.23 это предупреждение станет ошибкой.

    При выдаче предупреждения об устаревании возвращаемым значением будет False, если только входные данные не равны 1. Такое возможно, когда входными данными является значение float из 1.0.

    Если входные данные — None, фильтр теперь возвращает False вместо None. В этом случае также выдаётся упомянутое выше предупреждение об устаревании.

  • Передача фильтрам Jinja2, таким как default и mandatory, а также тестовым плагинам, включая defined и undefined, вложенных нескалярных значений со встроенными шаблонами, которые могут разрешиться в Undefined, больше не приводит к их вычислению так, как в предыдущих версиях, поскольку вложенные нескалярные значения со встроенными шаблонами обрабатываются только при использовании. В версии 2.19 это утверждение выполняется:

    - assert:
        that:
          # Unlike earlier versions, complex_var is defined even though complex_var.nested is not.
          - complex_var is defined
          # Unlike earlier versions, the default value is not applied because complex_var is defined.
          - (complex_var | default(unused)).nested is undefined
          # Like earlier versions, directly accessing complex_var.nested evaluates as undefined.
          - complex_var.nested is undefined
      vars:
        complex_var:
          # Before 2.19, complex_var.nested is evaluated immediately when complex_var is accessed.
          # In 2.19, complex_var.nested is evaluated only when it is accessed.
          nested: "{{ undefined_variable }}"
        unused:
          # This variable is used only if complex_var is undefined.
          # This only happens in ansible-core before 2.19.
          nested: default
    

Перенос пользовательских скриптов

Заметных изменений нет

Сетевые функции

Заметных изменений нет

© 2012–2018 Michael DeHaan
© 2018–2025 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/projects/ansible/latest/porting_guides/porting_guide_core_2.19.html

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API