Spec-Zone.ru › Ansible 2.4

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

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

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

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

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

  • Плейбук
    • Устаревшие функции
    • Другие особенности
  • Перенос плагинов
    • Плагины поиска
    • Плагины соединений
    • Плагины действий
    • Плагины обратного вызова
    • Плагины соединений
  • Гибридные плагины
    • Плагины поиска
    • Плагины соединений
    • Плагины действий
    • Плагины обратного вызова
    • Плагины соединений
  • Перенос пользовательских скриптов

Плейбук

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

# 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') ) }}"
  • Конец строки. Когда строка с символом новой строки в конце была указана в плейбуке в формате словаря YAML, символ новой строки в конце удалялся. При указании в формате key=value символы новой строки в конце сохранялись. В версии v2 оба метода указания строки сохраняют символы новой строки в конце. Если вы полагались на удаление символа новой строки в конце, вы можете изменить свой плейбук, используя следующий пример:

    # 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 сохраняются правильно. Это может быть запутанным, когда вы ожидаете, что ваш плейбук не покажет никаких различий при миграции на 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
  • шаблонизация (переменные в плейбуках и поиск шаблонов) улучшена с точки зрения сохранения исходного значения, а не преобразования всего в строку. Если вам нужно старое поведение, укажите значение в кавычках, чтобы передать его как строку.
  • Пустые переменные и переменные, установленные в значение null в YAML, больше не преобразуются в пустые строки. Они сохранят значение None. Вы можете переопределить настройку null_representation на пустую строку в файле конфигурации, установив переменную среды ANSIBLE_NULL_REPRESENTATION.
  • Плагины дополнительных обратных вызовов должны быть включены в ansible.cfg. Копирование больше не требуется, но включение в ansible.cfg обязательно.
  • Модуль dnf переписан. Могут наблюдаться незначительные изменения в поведении.
  • win_updates переписан и теперь работает как ожидается.
  • С версии 2.0.1 задача setup по умолчанию из gather_facts теперь правильно наследует все данные от плейбука, но это может вызвать проблемы для тех, кто устанавливает environment на уровне плейбука и зависит от 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].
  • Плейбуки, использующие повышение привилегий, всегда должны использовать опции «become*», а не старые опции su*/sudo*.
  • «Сокращенная форма» для vars_prompt больше не поддерживается. Например:

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

    - include_tasks: foo.yml
        a: 1
    

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

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

    - 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), но также была молчаливо проигнорирована, поэтому плейбук «запускался», хотя это не должно было происходить. Теперь это ошибка парсинга.

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

    - task: dostuf
      when: True
      when: False
    

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

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

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

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

  • Операции без префиксов на with_:

    with_items: var1 + var2
    

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

    with_items: "{{var1 + var2}}"
    

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

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

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

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

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

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

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

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

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

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

Хотя 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. Подобно переносу плагинов из v1 в v2, вам нужно понять, как работают плагины в каждой версии, и поддерживать оба требования.

Поскольку система плагинов 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.4/porting_guide_2.0.html

Spec-Zone.ru

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