Spec-Zone.ru › Ansible 2.5

Руководство по переносу Ansible 2.0

В этом разделе обсуждаются изменения поведения между Ansible 1.x и Ansible 2.0.

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

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

Этот документ является частью коллекции руководств по переносу. Полный список руководств по переносу можно найти по адресу руководствам по переносу.

  • Playbook
    • Устаревшие элементы
    • Другие особенности
  • Перенос плагинов
    • Плагины lookup
    • Плагины соединения
    • Плагины действий
    • Плагины обратного вызова
    • Плагины соединения
  • Гибридные плагины
    • Плагины lookup
    • Плагины соединения
    • Плагины действий
    • Плагины обратного вызова
    • Плагины соединения
  • Перенос пользовательских скриптов

Playbook

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

# Syntax in 1.9.x
- debug:
    msg: "{{ 'test1_junk 1\\\\3' | regex_replace('(.*)_junk (.*)', '\\\\1 \\\\2') }}"
# Syntax in 2.0.x
- debug:
    msg: "{{ 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') }}"

# Output:
"msg": "test1 1\\3"

Чтобы создать экранированную строку, которая будет работать во всех версиях, у вас есть два варианта:

- debug: msg="{{ 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') }}"

использует экранирование key=value, которое не изменилось. Другой вариант — проверить версию ansible:

"{{ (ansible_version|version_compare('2.0', 'ge'))|ternary( 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') , 'test1_junk 1\\\\3' | regex_replace('(.*)_junk (.*)', '\\\\1 \\\\2') ) }}"
  • Конец строки. Когда строка с концом строки указывалась в playbook в формате словаря YAML, конец строки удалялся. При указании в формате key=value концы строк сохранялись. В версии 2 оба способа указания строки сохраняют концы строк. Если вы полагались на удаление конца строки, вы можете изменить свой playbook, используя следующий пример:

    # Syntax in 1.9.x
    vars:
      message: >
        Testing
        some things
    tasks:
    - debug:
        msg: "{{ message }}"
    
    # Syntax in 2.0.x
    vars:
      old_message: >
        Testing
        some things
      message: "{{ old_messsage[:-1] }}"
    - debug:
        msg: "{{ message }}"
    # Output
    "msg": "Testing some things"
    
  • Изменение поведения шаблонизации текстовых файлов типа DOS в Ansible v2.

    Ошибка в Ansible v1 приводит к тому, что текстовые файлы типа DOS (использующие возврат каретки и новую строку) шаблонизируются в текстовые файлы типа Unix (использующие только новую строку). В Ansible v2 эта давняя ошибка, наконец, исправлена, и текстовые файлы типа DOS сохраняются правильно. Это может быть неудивительно, когда вы ожидаете, что ваш playbook не покажет никаких различий при миграции в Ansible v2, в то время как на самом деле вы увидите, что каждый файл типа DOS полностью заменяется (с тем же, что кажется точным содержанием).

  • При указании сложных аргументов в качестве переменной, переменная должна использовать весь синтаксис jinja2 (`{{var_name}}`) - имена переменных без символов больше не поддерживаются. На самом деле, даже указание аргументов с переменными стало устаревшим и не будет разрешено в будущих версиях:

    ---
    - hosts: localhost
      connection: local
      gather_facts: false
      vars:
        my_dirs:
          - { path: /tmp/3a, state: directory, mode: 0755 }
          - { path: /tmp/3b, state: directory, mode: 0700 }
      tasks:
        - file:
          args: "{{item}}" # <- args here uses the full variable syntax
          with_items: "{{my_dirs}}"
    
  • перенос задачи включает
  • Более динамично. Случаи, которые не должны были работать, теперь не работают, как и ожидалось.
  • переменные, определенные в формате yaml словаря https://github.com/ansible/ansible/issues/13324
  • шаблонизация (переменные в playbooks и шаблонах поиска) улучшена с точки зрения сохранения оригинала вместо преобразования всего в строку. Если вам нужно старое поведение, укажите значение в кавычках, чтобы передать его как строку.
  • Пустые переменные и переменные, установленные в null в формате yaml, больше не преобразуются в пустые строки. Они сохранят значение None. Вы можете переопределить null_representation значение на пустую строку в файле конфигурации, установив переменную окружения ANSIBLE_NULL_REPRESENTATION.
  • Плагины обратного вызова extras должны быть внесены в белый список в ansible.cfg. Копирование больше не требуется, но внесение в белый список в ansible.cfg необходимо выполнить.
  • Модуль dnf был переписан. Могут наблюдаться незначительные изменения в поведении.
  • win_updates был переписан и теперь работает как ожидается.
  • начиная с версии 2.0.1, неявная задача setup из gather_facts теперь правильно наследует все от play, но это может вызвать проблемы для тех, кто устанавливает environment на уровне play и зависит от ansible_env.

Устаревшие элементы

Хотя все перечисленные элементы будут показывать предупреждение об устаревании, они по-прежнему работают так же, как и в версии 1.9.x. Обратите внимание, что они будут удалены в версии 2.2 (Ansible всегда ждет два основных выпуска, чтобы удалить устаревший функционал).

  • Голые переменные в циклах with_ должны вместо этого использовать синтаксис "{ {var }}", что помогает устранить неоднозначность.
  • Файл требований формата ansible-galaxy в текстовом формате. Пользователи должны использовать формат YAML для требований.
  • Неопределенные переменные внутри списка цикла with_ в настоящее время не прерывают цикл, но выдают предупреждение; в будущем они будут вызывать ошибку.
  • Использование переменных словарей для задания всех параметров задачи небезопасно и будет удалено в будущей версии. Например:

    - hosts: localhost
      gather_facts: no
      vars:
        debug_params:
          msg: "hello there"
      tasks:
        # These are both deprecated:
        - debug: "{{debug_params}}"
        - debug:
          args: "{{debug_params}}"
    
        # Use this instead:
        - debug:
            msg: "{{debug_params['msg']}}"
    
  • Шаблоны хостов должны использовать запятую (,) или двоеточие (:) вместо точки с запятой (;), чтобы разделять хосты/группы в шаблоне.
  • Диапазоны, указанные в шаблонах хостов, должны использовать синтаксис [x:y], а не [x-y].
  • Playbooks, использующие повышение привилегий, должны всегда использовать опции «become*», а не устаревшие опции su*/sudo*.
  • Короткий формат для vars_prompt больше не поддерживается. Например:

    vars_prompt:
        variable_name: "Prompt string"
    
  • Указание переменных на верхнем уровне задания include не поддерживается. Например:

    - include_tasks: foo.yml
        a: 1
    

Должно быть:

- include_tasks: foo.yml
  vars:
    a: 1
  • Указание any_errors_fatal в задаче больше не поддерживается. Это должно быть установлено только на уровне play.
  • Голые переменные в словаре environment (для play/задач и т. д.) больше не поддерживаются. Переменные, указанные там, должны использовать полный синтаксис переменных: «{{foo}}».
  • Теги (или любые директивы) больше не должны указываться с другими параметрами в задаче include. Вместо этого они должны быть указаны как опция задачи. Например:

    - include_tasks: foo.yml tags=a,b,c
    

    Должно быть:

    - include_tasks: foo.yml
      tags: [a, b, c]
    
  • Опция first_available_file в задачах устарела. Пользователи должны использовать опцию with_first_found или плагин lookup (‘first_found’, …).

Другие особенности

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

  • Неправильное составление переменных:

    with_items: myvar_{{rest_of_name}}
    

    Это работало «случайно», поскольку ошибки были перешаблонированы и в итоге разрешили переменную, но это никогда не было задумано как допустимый синтаксис, и теперь правильно возвращает ошибку. Используйте вместо этого следующее:

    hostvars[inventory_hostname]['myvar_' + rest_of_name]
    
  • Неправильно написанные директивы:

    - task: dostuf
      becom: yes
    

    Задача всегда выполнялась без повышения привилегий (для этого вам нужна become), но также молча игнорировалась, поэтому play «выполнялся», хотя этого не должно было быть. Теперь это ошибка синтаксического анализа.

  • Повторяющиеся директивы:

    - task: dostuf
      when: True
      when: False
    

    Первая when была проигнорирована, и использовалась только вторая, так как play выполнялся без предупреждения, что одна из директив игнорировалась. Теперь это ошибка синтаксического анализа.

  • Объединение переменных и директив:

    - role: {name=rosy, port=435 }
    
    # in tasks/main.yml
    - wait_for: port={{port}}
    

    Переменная port зарезервирована как директива play/задачи для переопределения порта соединения. В предыдущих версиях она была объединена с переменной с именем port и была доступна позже в play. Это создавало проблемы, если хост пытался переподключиться или использовал соединение без кэширования. Теперь она будет правильно идентифицирована как директива, и переменная port будет отображаться как неопределенная. Это теперь вынуждает использовать неконфликтующие имена и устраняет неоднозначность при добавлении настроек и переменных к вызову роли.

  • Операции без параметров на with_:

    with_items: var1 + var2
    

    Проблема с функцией «голой переменной», которая, как ожидалось, будет шаблонизировать только одну переменную без фигурных скобок ({{ }}), в некоторых версиях Ansible шаблонировала целые выражения. Теперь вам нужно использовать правильное шаблонирование и фигурные скобки для всех выражений, за исключением условных операторов (when):

    with_items: "{{var1 + var2}}"
    

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

Перенос плагинов

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

Плагины lookup

  • плагины lookup; версия импорта

Плагины соединения

  • плагины соединения

Плагины действий

  • плагины действий

Плагины обратного вызова

Хотя Ansible 2.0 предоставляет новый API обратного вызова, старый API продолжает работать для большинства плагинов обратного вызова. Однако, если ваш плагин обратного вызова использует self.playbook, self.play, или self.task, то вам придется хранить значения самостоятельно, так как Ansible больше не автоматически заполняет плагин обратного вызова ими. Вот небольшой фрагмент, который показывает вам, как это сделать:

import os
from ansible.plugins.callback import CallbackBase

class CallbackModule(CallbackBase):
    def __init__(self):
        self.playbook = None
        self.playbook_name = None
        self.play = None
        self.task = None

    def v2_playbook_on_start(self, playbook):
        self.playbook = playbook
        self.playbook_name = os.path.basename(self.playbook._file_name)

    def v2_playbook_on_play_start(self, play):
        self.play = play

    def v2_playbook_on_task_start(self, task, is_conditional):
        self.task = task

    def v2_on_any(self, *args, **kwargs):
        self._display.display('%s: %s: %s' % (self.playbook_name,
        self.play.name, self.task))

Плагины соединения

  • плагины соединения

Гибридные плагины

В определенных случаях вам может потребоваться плагин, который поддерживает как ansible-1.9.x, так и ansible-2.0. Подобно переносу плагинов из версии 1 в версию 2, вам нужно понять, как плагины работают в каждой версии, и поддерживать оба требования.

Поскольку система плагинов ansible-2.0 более продвинутая, проще адаптировать ваш плагин для предоставления похожих элементов (подклассов, методов) для ansible-1.9.x, как ожидается в ansible-2.0. Таким образом, ваш код будет намного чище.

Следующие советы могут быть полезны:

  • Проверьте, доступны ли классы ansible-2.0 и если их нет (ansible-1.9.x), имитируйте их с необходимыми методами (например, __init__)
  • Когда импортируются python-модули ansible-2.0, и они терпят неудачу (ansible-1.9.x), перехватывайте исключение ImportError и выполняйте эквивалентные импорты для ansible-1.9.x. С возможными переводами (например, импортирование конкретных методов).
  • Используйте наличие этих методов в качестве квалификатора версии Ansible, которую вы используете. Таким образом, вместо проверки версий можно использовать проверки возможностей. (См. примеры ниже)
  • Документируйте каждый случай if-then-else, для какой конкретной версии нужен каждый блок. Это поможет другим понять, как нужно адаптировать свои плагины, а также поможет вам удалить поддержку старых ansible-1.9.x, когда она будет устаревшей.
  • При разработке плагинов очень полезно иметь метод warning() во время разработки, но также важно выводить предупреждения для тупиковых ситуаций (случаев, которые, как ожидается, никогда не будут активированы) или граничных случаев (например, случаев, где ожидаются неправильные настройки).
  • Полезно изучить другие плагины в ansible-1.9.x и ansible-2.0, чтобы понять, как работает API и какие модули, классы и методы доступны.

Плагины поиска

В качестве простого примера мы собираемся создать гибридный fileglob плагин поиска.

from __future__ import (absolute_import, division, print_function)
__metaclass__ = type

import os
import glob

try:
    # ansible-2.0
    from ansible.plugins.lookup import LookupBase
except ImportError:
    # ansible-1.9.x

    class LookupBase(object):
        def __init__(self, basedir=None, runner=None, **kwargs):
            self.runner = runner
            self.basedir = self.runner.basedir

        def get_basedir(self, variables):
            return self.basedir

try:
    # ansible-1.9.x
    from ansible.utils import (listify_lookup_plugin_terms, path_dwim, warning)
except ImportError:
    # ansible-2.0
    from __main__ import display
    warning = display.warning

class LookupModule(LookupBase):

    # For ansible-1.9.x, we added inject=None as valid argument
    def run(self, terms, inject=None, variables=None, **kwargs):

        # ansible-2.0, but we made this work for ansible-1.9.x too !
        basedir = self.get_basedir(variables)

        # ansible-1.9.x
        if 'listify_lookup_plugin_terms' in globals():
            terms = listify_lookup_plugin_terms(terms, basedir, inject)

        ret = []
        for term in terms:
            term_file = os.path.basename(term)

            # For ansible-1.9.x, we imported path_dwim() from ansible.utils
            if 'path_dwim' in globals():
                # ansible-1.9.x
                dwimmed_path = path_dwim(basedir, os.path.dirname(term))
            else:
                # ansible-2.0
                dwimmed_path = self._loader.path_dwim_relative(basedir, 'files', os.path.dirname(term))

            globbed = glob.glob(os.path.join(dwimmed_path, term_file))
            ret.extend(g for g in globbed if os.path.isfile(g))

        return ret

Примечание

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

Плагины подключения

  • плагины подключения

Плагины действий

  • плагины действий

Плагины обратной связи

  • плагины обратной связи

Плагины подключения

  • плагины подключения

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

Пользовательские скрипты, которые использовали API ansible.runner.Runner в 1.x, должны быть перенесены в 2.x. См.: Python API

© 2012–2018 Michael DeHaan
© 2018–2019 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/2.5/porting_guides/porting_guide_2.0.html

Spec-Zone.ru

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