Spec-Zone.ru › Ansible 2.4

Конвенции, лучшие практики и распространённые ошибки

В качестве напоминания из примера кода выше, вот некоторые основные конвенции и рекомендации:

  • Если модуль обращается к объекту, параметр для этого объекта должен называться «name», когда это возможно, или принимать «name» в качестве псевдонима.
  • Если у вас есть модуль компании, который возвращает факты, специфичные для ваших установок, хорошим именем для этого модуля является site_facts.
  • Модули, принимающие логическое значение, должны, как правило, принимать «да», «нет», «истина», «ложь» или что-то ещё, что пользователь, вероятно, им передаст. Общий код AnsibleModule поддерживает это с «type=’bool’».
  • Если возможно, включите минимальное количество зависимостей. Если есть зависимости, документируйте их в верхней части файла модуля и заставляйте модуль выводить JSON-сообщения об ошибках при сбое импорта.
  • Модули должны быть самодостаточными в одном файле для автоматической передачи Ansible.
  • При упаковке модулей в RPM их нужно устанавливать только на контрольный компьютер и помещать в /usr/share/ansible. Это полностью необязательно и зависит от вас.
  • Модули должны выводить только корректный JSON. Тип возвращаемого значения верхнего уровня должен быть хешем (словарём), хотя они могут быть вложенными. Список или простые скалярные значения не поддерживаются, хотя они могут быть тривиально заключены в словарь.
  • В случае сбоя должен включаться ключ «failed», а также строковое объяснение в «msg». Модули, которые генерируют отслеживания ошибок (стеки вызовов), как правило, считаются «плохими» модулями, хотя Ansible может обрабатывать такие возвращаемые значения и автоматически преобразует всё неразбираемое в результат с ошибкой. Если вы используете общий код AnsibleModule на Python, элемент «failed» будет автоматически включён, когда вы вызовете «fail_json».
  • Коды возврата из модулей фактически не имеют значения, но продолжают использовать 0=успех и ненулевое значение=сбой по соображениям будущего.
  • Поскольку результаты с многих хостов будут агрегированы одновременно, модули должны возвращать только релевантный вывод. Возврат всего содержимого файла журнала, как правило, является плохой практикой.

Отладка модулей на основе AnsibleModule

Подсказка

Если вы используете скрипт hacking/test-module, то большая часть этого делается за вас. Если вам нужно выполнить отладку модуля на удалённой машине, на которой будет выполняться модуль, или когда модуль используется в playbook, то вам, возможно, потребуется использовать эту информацию вместо того, чтобы полагаться на test-module.

Начиная с Ansible-2.1.0, модули на основе AnsibleModule собираются в виде zip-архива, содержащего файл модуля и различные шаблоны модуля Python внутри оболочки скрипта, а не как один файл со всем кодом, объединённым вместе. Без некоторой помощи это может быть сложнее отладить, так как файл нужно извлечь из оболочки, чтобы увидеть, что происходит на самом деле в модуле. К счастью, скрипт оболочки предоставляет некоторые вспомогательные методы для этого.

Если вы используете Ansible с переменными среды ANSIBLE_KEEP_REMOTE_FILES для сохранения удалённого файла модуля, вот пример того, как начнётся ваша сессия отладки:

$ ANSIBLE_KEEP_REMOTE_FILES=1 ansible localhost -m ping -a 'data=debugging_session' -vvv
<127.0.0.1> ESTABLISH LOCAL CONNECTION FOR USER: badger
<127.0.0.1> EXEC /bin/sh -c '( umask 77 && mkdir -p "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" && echo "` echo $HOME/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595 `" )'
<127.0.0.1> PUT /var/tmp/tmpjdbJ1w TO /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping
<127.0.0.1> EXEC /bin/sh -c 'LANG=en_US.UTF-8 LC_ALL=en_US.UTF-8 LC_MESSAGES=en_US.UTF-8 /usr/bin/python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping'
localhost | SUCCESS => {
    "changed": false,
    "invocation": {
        "module_args": {
            "data": "debugging_session"
        },
        "module_name": "ping"
    },
    "ping": "debugging_session"
}

Установка ANSIBLE_KEEP_REMOTE_FILES в значение 1 сообщает Ansible сохранять удалённые файлы модулей вместо удаления их после завершения выполнения модуля. Предоставление Ansible опции -vvv делает Ansible более подробным. Таким образом, он выводит имя файла временного файла модуля для вас.

Если вы хотите проверить файл оболочки, вы можете это сделать. Он покажет небольшой скрипт Python с большой строкой, закодированной в base64. Строка содержит модуль, который будет выполнен. Запустите команду explode оболочки, чтобы преобразовать строку в файлы Python, с которыми можно работать:

$ python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping explode
Module expanded into:
/home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/debug_dir

Когда вы посмотрите в debug_dir, вы увидите структуру каталога, подобную этой:

├── ansible_module_ping.py
├── args
└── ansible
    ├── __init__.py
    └── module_utils
        ├── basic.py
        └── __init__.py
  • ansible_module_ping.py - это код самого модуля. Имя основано на имени модуля с префиксом, чтобы не возникало конфликтов с другими именами модулей Python. Вы можете изменить этот код, чтобы увидеть, какое влияние это окажет на ваш модуль.
  • Файл args содержит строку JSON. Строка представляет собой словарь, содержащий аргументы модуля и другие переменные, которые Ansible передает в модуль, чтобы изменить его поведение. Если вы хотите изменить параметры, передаваемые в модуль, это тот файл, в котором нужно это сделать.
  • Каталог ansible содержит код из ansible.module_utils, используемый модулем. Ansible включает файлы для любых импортов :module:`ansible.module_utils в модуле, но не файлы из других модулей. Таким образом, если ваш модуль использует ansible.module_utils.url, Ansible включит его для вас, но если ваш модуль включает requests, вам нужно убедиться, что библиотека Python requests установлена на системе перед запуском модуля. Вы можете изменить файлы в этом каталоге, если подозреваете, что модуль испытывает проблему в каком-то из этих шаблонов кода, а не в коде модуля, который вы написали.

После редактирования кода или аргументов в разорванном дереве вам нужен способ его запуска. Для этого есть отдельная подкоманда оболочки:

$ python /home/badger/.ansible/tmp/ansible-tmp-1461434734.35-235318071810595/ping execute
{"invocation": {"module_args": {"data": "debugging_session"}}, "changed": false, "ping": "debugging_session"}

Эта подкоманда заботится о настройке PYTHONPATH для использования разорванного каталога debug_dir/ansible/module_utils и вызове скрипта с использованием аргументов в файле args. Вы можете продолжать запускать его так до тех пор, пока не поймёте проблему. Затем вы можете скопировать его обратно в ваш реальный файл модуля и проверить, что реальный модуль работает через ansible или ansible-playbook.

Примечание

Оболочка предоставляет ещё одну подкоманду, excommunicate. Эта подкоманда очень похожа на execute в том, что она вызывает разорванный модуль с аргументами в args. Однако способ, которым она это делает, отличается. excommunicate импортирует функцию main() из модуля и затем вызывает её. Это заставляет excommunicate выполнять модуль в процессе оболочки. Это может быть полезно для запуска модуля под некоторыми графическими отладчиками, но это очень отличается от того, как модуль выполняется самим Ansible. Некоторые модули могут не работать с excommunicate или могут вести себя иначе, чем при обычном использовании с Ansible. Это не ошибки в модуле, а ограничения excommunicate. Используйте с осторожностью.

Пути к модулям

Если у вас возникают трудности с «обнаружением» модуля Ansible, убедитесь, что он находится в переменной среды ANSIBLE_LIBRARY.

Если у вас есть вилка одного из проектов модулей Ansible, сделайте что-то вроде этого:

ANSIBLE_LIBRARY=~/ansible-modules-core

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

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

Распространённые ошибки

Никогда не делайте этого в модуле:

print("some status message")

Потому что вывод должен быть корректным JSON.

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

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

Не записывайте данные напрямую в файлы; используйте временный файл, а затем используйте функцию atomic_move из ansible.module_utils.basic для перемещения обновлённого временного файла на место. Это предотвращает повреждение данных и гарантирует сохранение правильного контекста файла.

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

Избегайте создания «кэшей». Ansible разработан без центрального сервера или авторитета, поэтому вы не можете гарантировать, что он не будет выполняться с разными правами, параметрами или расположениями. Если вам нужен центральный авторитет, разместите его поверх Ansible (например, с помощью сервера bastion/cm/ci или Tower); не пытайтесь интегрировать его в модули.

Всегда используйте скрипт hacking/test-module при разработке модулей, и он предупредит вас об этих проблемах.

© 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/dev_guide/developing_modules_best_practices.html

Spec-Zone.ru

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