Практическое руководство по разработке модулей Ansible для Windows
В этом разделе мы рассмотрим разработку, тестирование и отладку модуля Ansible для Windows.
Поскольку модули для Windows написаны на Powershell и должны выполняться на хосте Windows, это руководство отличается от обычного руководства по разработке.
Что охватывается в этом разделе:
- Практическое руководство по разработке модулей Ansible для Windows
- Настройка среды Windows
- Разработка нового модуля Windows
- Тестирование модуля Windows с помощью playbook
- Отладка в Windows
- Единое тестирование в Windows
- Интеграционное тестирование в Windows
- Поддержка коммуникаций и разработки в Windows
Настройка среды Windows
TODO: Добавить больше информации о том, как использовать Vagrant для настройки хоста Windows.
Разработка нового модуля Windows
При создании нового модуля необходимо учитывать несколько моментов:
- Код модуля находится в файлах Powershell (.ps1), а документация — в файлах Python (.py) с тем же именем
- Избегайте использования
Write-Host/Debug/Verbose/Errorв модуле и добавьте то, что должно быть возвращено, в переменную$result - При обработке исключений используйте
Fail-Json -obj $result -message "exception message here" - Большинство новых модулей требуют режима проверки и интеграционных тестов перед включением в основной код Ansible
- Избегайте использования try/catch для обработки больших блоков кода, а используйте их для отдельных вызовов, чтобы сообщение об ошибке было более информативным
- При использовании try/catch старайтесь обрабатывать конкретные исключения
- Избегайте использования PSCustomObjects, если это не требуется
- Ищите общие функции в
./lib/ansible/module_utils/powershell/и используйте код оттуда вместо дублирования работы. Их можно импортировать, добавив строку#Requires -Module *, где * — имя файла для импорта, и они будут автоматически включены в код модуля, отправленный целевому устройству Windows при запуске через Ansible - Убедитесь, что код работает под Powershell v3 и выше на Windows Server 2008 и выше; если требуются более новые версии Powershell или ОС, убедитесь, что документация чётко это отражает
- Ansible запускает модули в режиме strictmode версии 2.0. Убедитесь, что вы тестируете с включённым strictmode, поместив
Set-StrictMode -Version 2.0в начало вашего скрипта разработки - Если возможно, отдавайте предпочтение встроенным командлетам Powershell по сравнению с вызовами исполняемых файлов
- Если вы добавляете объект в
$result, убедитесь, что все завершающие слэши удалены или экранированы, так какConvertTo-Jsonне сможет их преобразовать - Используйте полные имена командлетов вместо псевдонимов, например,
Remove-Itemвместоrm - Используйте именованные параметры с командлетами, например,
Remove-Item -Path C:\tempвместоRemove-Item C:\temp
Ниже приведён шаблон очень простого модуля Powershell:
#!powershell
# This file is part of Ansible
# GNU General Public License v3.0+ (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)
#Requires -Module Ansible.ModuleUtils.Legacy.psm1
$ErrorActionPreference = 'Stop'
$params = Parse-Args -arguments $args -supports_check_mode $true
$check_mode = Get-AnsibleParam -obj $params -name "_ansible_check_mode" -type "bool" -default $false
$diff_mode = Get-AnsibleParam -obj $params -name "_ansible_diff" -type "bool" -default $false
# these are your module parameters, there are various types which can be
# used to format your parameters. You can also set mandatory parameters
# with -failifempty, set defaults with -default and set choices with
# -validateset.
$string = Get-AnsibleParam -obj $params -name "string" -type "str" -failifempty $true
$bool = Get-AnsibleParam -obj $params -name "bool" -type "bool" -default $false
$int = Get-AnsibleParam -obj $params -name "int" -type "int"
$path = Get-AnsibleParam -obj $params -name "path" -type "path"
$list = Get-AnsibleParam -obj $params -name "list" -type "list"
$choices = Get-AnsibleParam -obj $params -name "choices" -type "str" -default "present" -validateset "absent","present"
$result = @{
changed = $false
}
if ($diff_mode) {
$result.diff = @{}
}
# code goes here
# you can add/set new result objects with
$result.changed = $true
$result.new_result = "Hi"
Exit-Json -obj $result
В случае сомнений, обратитесь к некоторым основным модулям и посмотрите, как там реализованы вещи.
Иногда в Windows существуют несколько способов выполнения задачи; вот порядок их предпочтения при написании модулей:
- Встроенные командлеты Powershell, например,
Remove-Item -Path C:\temp -Recurse - Классы .NET, например,
[System.IO.Path]::GetRandomFileName() - Объекты WMI через командлет
New-CimInstance - Объекты COM через командлет
New-Object -ComObject - Вызовы нативных исполняемых файлов, например,
Secedit.exe
Тестирование модуля Windows с помощью playbook
Для тестирования модуля можно использовать playbook Ansible.
- Создайте playbook в любом каталоге
touch testmodule.yml - Создайте файл инвентаризации в том же каталоге
touch hosts - Заполните файл инвентаризации переменными, необходимыми для подключения к хосту(ам) Windows.
-
Добавьте следующее в новый файл playbook:
--- - name: test out windows module hosts: windows tasks: - name: test out module win_module: name: test name - Запустите playbook
ansible-playbook -i hosts testmodule.yml
Это может быть довольно высоким уровнем и полезно для просмотра того, как Ansible работает с новым модулем от начала до конца: но есть лучшие способы протестировать модуль, как показано ниже.
Отладка в Windows
Отладка модуля в настоящее время возможна только на хосте Windows. Это очень полезно при разработке нового модуля или поиске ошибок. Ниже приведены шаги по настройке.
- Скопируйте скрипт модуля на сервер Windows
- Скопируйте
./lib/ansible/module_utils/powershell/Ansible.ModuleUtils.Legacy.psm1в ту же папку, что и скрипт выше -
Чтобы предотвратить выход скрипта из редактора при успешном выполнении, в
Ansible.ModuleUtils.Legacy.psm1внутри функцииExit-Jsonзамените две последние строки функции на:ConvertTo-Json -InputObject $obj -Depth 99
-
Чтобы предотвратить выход скрипта из редактора при неудачном выполнении, в
Ansible.ModuleUtils.Legacy.psm1внутри функцииFail-Jsonзамените две последние строки функции на:Write-Error -Message (ConvertTo-Json -InputObject $obj -Depth 99)
-
Добавьте следующее в начало скрипта модуля, который был скопирован на сервер:
### start setup code $complex_args = @{ "_ansible_check_mode" = $false "_ansible_diff" = $false "path" = "C:\temp" "state" = "present" } Import-Module -Name .\Ansible.ModuleUtils.Legacy.psm1 ### end setup code
Вы можете добавить дополнительные аргументы в $complex_args по мере необходимости модуля. Теперь модуль можно запустить на хосте Windows либо напрямую через Powershell, либо через IDE.
Для отладки скрипта Powershell можно использовать различные IDE, две из самых популярных:
Для просмотра аргументов, передаваемых Ansible модулю, выполните следующие действия.
- Добавьте префикс
ANSIBLE_KEEP_REMOTE_FILES=1к команде Ansible, чтобы Ansible сохранял файлы exec на сервере - Войдите на сервер Windows с тем же пользователем, от имени которого Ansible запустил модуль
- Перейдите в
%TEMP%\.., там должна быть папка, начинающаяся сansible-tmp- - Внутри этой папки откройте Powershell-скрипт для модуля
- В этом скрипте есть сырой JSON-скрипт в
$json_raw, содержащий аргументы модуля вmodule_args - Эти аргументы можно вручную назначить переменной
$complex_args, определённой в вашем отладочном скрипте
Единое тестирование в Windows
В настоящее время нет механизма для запуска модулей unit-тестов Powershell в Ansible CI. Работа над внедрением этой возможности в будущем.
Интеграционное тестирование в Windows
Интеграционные тесты модулей Ansible обычно пишутся как роли Ansible. Тестовые роли находятся в ./test/integration/targets. Сначала необходимо настроить тестовую среду и конфигурировать инвентаризацию Ansible для подключения к ней. В этом примере мы настраиваем тестовую инвентаризацию для подключения к двум хостам и запускаем интеграционные тесты для win_stat.
- Создайте копию
./test/integration/inventory.winrm.templateи просто назовите еёinventory.winrm - Заполните записи в
[windows]и задайте необходимые переменные для подключения к хосту - Чтобы запустить интеграционные тесты, выполните
ansible-test windows-integration win_stat- можете заменитьwin_statна роль, которую хотите протестировать
Это запустит все тесты, которые в данный момент определены для этой роли. Уровень подробности можно настроить с помощью аргумента -v так же, как и с ansible-playbook.
При разработке тестов для нового модуля рекомендуется протестировать сценарий в режиме проверки и 2 раза без режима проверки. Это гарантирует, что режим проверки не вносит изменений, но сообщает о них, а также, что повторное выполнение является идемпотентным и не сообщает о изменениях. Ниже приведен пример того, как это можно сделать:
- name: remove a file (check mode)
win_file:
path: C:\temp
state: absent
register: remove_file_check
check_mode: yes
- name: get result of remove a file (check mode)
win_command: powershell.exe "if (Test-Path -Path 'C:\temp') { 'true' } else { 'false' }"
register: remove_file_actual_check
- name: assert remove a file (check mode)
assert:
that:
- remove_file_check|changed
- remove_file_actual_check.stdout == 'true\r\n'
- name: remove a file
win_file:
path: C:\temp
state: absent
register: remove_file
- name: get result of remove a file
win_command: powershell.exe "if (Test-Path -Path 'C:\temp') { 'true' } else { 'false' }"
register: remove_file_actual
- name: assert remove a file
assert:
that:
- remove_file|changed
- remove_file_actual.stdout == 'false\r\n'
- name: remove a file (idempotent)
win_file:
path: C:\temp
state: absent
register: remove_file_again
- name: assert remove a file (idempotent)
assert:
that:
- not remove_file_again|changed
Поддержка коммуникаций и разработки в Windows
Присоединяйтесь к каналу IRC #ansible-devel или #ansible-windows на freenode для обсуждений разработки Ansible для Windows.
Для вопросов и обсуждений, связанных с использованием продукта Ansible, используйте канал #ansible.
© 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_general_windows.html