Spec-Zone.ru › Ansible

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

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

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

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

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

  • Playbook

    • Устаревшие элементы
    • Другие особенности
  • Перенос плагинов

    • Плагины поиска
    • Плагины соединения
    • Плагины действий
    • Плагины обратного вызова
    • Плагины соединения
  • Гибридные плагины

    • Плагины поиска
    • Плагины соединения
    • Плагины действий
    • Плагины обратного вызова
    • Плагины соединения
  • Перенос пользовательских скриптов

Playbook

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

  • Синтаксис в 1.9.x
- debug:
    msg: "{{ 'test1_junk 1\\\\3' | regex_replace('(.*)_junk (.*)', '\\\\1 \\\\2') }}"
  • Синтаксис в 2.0.x
- debug:
    msg: "{{ 'test1_junk 1\\3' | regex_replace('(.*)_junk (.*)', '\\1 \\2') }}"
  • Вывод:
"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 }}"
    
    • Синтаксис в 2.0.x
    vars:
      old_message: >
        Testing
        some things
      message: "{{ old_message[:-1] }}"
    - debug:
        msg: "{{ message }}"
    
    • Вывод
    "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}}"
      with_items: "{{my_dirs}}"
  • перенос задачи включает
  • Более динамично. Случаи с форматированием, которые не должны были работать, теперь не работают, как ожидалось.
  • Переменные, определенные в формате YAML, см. проблему 13324
  • Шаблонизация (переменные в playbooks и шаблонах поиска) улучшена в отношении сохранения оригинального значения вместо преобразования всего в строку. Если вам нужно старое поведение, оформите значение в кавычки, чтобы передать его как строку.
  • Пустые переменные и переменные, установленные в null в YAML, больше не преобразуются в пустые строки. Они сохранят значение None. Вы можете переопределить null_representation значение на пустую строку в файле конфигурации, установив переменную окружения ANSIBLE_NULL_REPRESENTATION.
  • Плагины дополнительных обратных вызовов должны быть включены в ansible.cfg. Копирование больше не требуется, но их нужно включить в ansible.cfg.
  • Модуль dnf был переписан. Могут наблюдаться некоторые незначительные изменения в поведении.
  • Модуль win_updates был переписан и теперь работает как ожидается.
  • Начиная с версии 2.0.1, неявная задача настройки из gather_facts теперь корректно наследует все от playbook, но это может вызвать проблемы для тех, кто устанавливает environment на уровне playbook и зависит от наличия ansible_env. Ранее это игнорировалось, но теперь может выдать ошибку «Undefined».

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

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

  • Необработанные переменные в циклах with_ должны использовать синтаксис "{{ var }}", что помогает устранить неоднозначность.
  • Требования к файлу формата ansible-galaxy. Пользователи должны использовать формат YAML для требований.
  • Неопределенные переменные внутри списка цикла with_ в настоящее время не прерывают цикл, но выдают предупреждение; в будущем они будут выдавать ошибку.
  • Использование переменных словарей для установки всех параметров задачи небезопасно и будет удалено в будущей версии. Пример устаревшего варианта:
- hosts: localhost
  gather_facts: no
  vars:
    debug_params:
      msg: "hello there"
  tasks:
    - debug: "{{debug_params}}"
    - debug:
      args: "{{debug_params}}"

Пример рекомендуемого варианта:

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

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

    - include_tasks: foo.yml
        a: 1
    

Теперь должно быть:

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

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

    Должно быть:

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

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

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

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

    with_items: myvar_{{rest_of_name}}
    

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

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

    - task: dostuf
      becom: yes
    

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

  • Повторные директивы:

    - task: dostuf
      when: True
      when: False
    

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

  • Смешивание переменных и директив:

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

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

  • Необработанные операции над with_:

    with_items: var1 + var2
    

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

    with_items: "{{var1 + var2}}"
    

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

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

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

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

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

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

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

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

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

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

Хотя Ansible 2.0 предоставляет новый 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 ansible.utils.display 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–2024 Red Hat, Inc.
Licensed under the GNU General Public License version 3.
https://docs.ansible.com/ansible/latest/porting_guides/porting_guide_2.0.html

Spec-Zone.ru

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