- PVSM.RU - https://www.pvsm.ru -
Приветствую!
В предыдущей статье [1] я писал о SparrowHub [2] — репозиторий готовых утилит для системного администрирования. Что же, время прошло, и теперь хочется рассказать о том КАК разрабатывать эти самые утилиты и загружать их на SparrowHub для повторного использования кем-либо.
Прежде чем показать конкретный пример написания плагина, хочу немного раскрыть идеологию фреймворка Sparrow [3], на котором собственно и разрабатываются скрипты.
Во-первых, Sparrow не навязывает какого-то жесткого DSL для разработки скриптов. У вас есть на выбор три языка, поддерживаемых Sparrow:
Таким образом, вы просто пишите обычный скрипт, который делает нужную вам работу и "оборачиваете" его в плагин, и, вуаля — он готов к загрузке на SparrowHub и для повторного использования. Ну, я немножко упростил, не совсем конечно так. Разрабатывая скрипт, вы все же придерживаетесь некоторых соглашений ( например на именования скриптовых файлов и т.д. ) для того что бы ваша утилита могла быть упакована в плагин в "sparrow" формате.
Другой особенностью Sparrow плагинов является встроенная система тестирования работы скриптов. Встроенная, потому что из коробки у вас есть возможность совершить дополнительные проверки работы скриптов, кроме банального кода завершения. Данная система проверок в ряде случаев может оказаться очень полезной. Детали станут ясны на конкретном примере.
Ну и третья, связанная с предыдущей, особенность Sparrow плагинов, это то, что результат их работы выводится в TAP [4] формате. В двух словах TAP — специальный протокол ( плюс формат вывода ), разработанный для тестирования программных модулей, он является стандартным для написания unit тестов в Perl, но не привязан к конкретному языку программирования и имеет поддержку во многих системах и языках.
Таким образом, в Sparrow предпринята попытка ( насколько удачная покажет практика ;) ) совместить написание скриптов системного администрирования с системой тестирования работы самих скриптов. Похожие идеи можно увидеть в различных системах управления конфигурациями, например в chef [5] — это minitest chef handler [6] и новая разработка chef inspec [7].
Итак, напишем простейший Sparrow плагин.
Допустим, требуется установить пакет nginx [8] и настроить запускаемый nginx сервер. Разобьем задачу на два сценария — собственно установка самого пакета и настройка сервера. Под настройкой будем понимать добавление сервера в автозагрузку, старт сервера и простейший тест на то, что сервер доступен по порту 80. Операционная система — Ubuntu [9]. Сразу же оговорюсь, что пример достаточно умозрительный и тривиальный, любой системный администратор или программист способен выполнить подобную задачу, но хорошо подходит для объяснения того как пишутся плагины Sparrow.
Итак, у нас есть два сценария:
В качестве языка, на котором будем писать плагин, выберем Bash [10] т.к. в данной постановке задачи ( очень простые действия на уровне настройки операционные системы ) он больше всего подходит к нашей предметной области. В принципе, все тоже самое можно реализовать на Perl или Ruby.
В терминах Sparrow запускаемые сценарий — это история, в том смысле что есть некий скрипт, который можно запустить и который выводит что-то в stdout ( оставляет след, образно выражаясь ). После выполнения скрипта Sparrow позволяет сделать два типа проверок:
Правила на именование скрипта простое — базовое имя должно быть story
с соответствующим языку сценария расширением:
Итак, в случае с Bash имеем такую историю:
$ cat story.bash
sudo DEBIAN_FRONTEND=noninteractive apt-get -y install nginx >/dev/null
dpkg -s nginx | grep Status:
Запустив, данный скрипт руками посмотрим его вывод:
$ bash story.bash
Status: install ok installed
Теперь несложно написать проверку для корректности работы данного скрипта. В Sparrow это делается с помощью так называемых проверочных файлов. У каждой истории должен быть свой проверочный файл, он должен лежать в той же директории что и запускаемый сценарий и называться story.check. Содержимое проверочного файла должно быть создано на языке проверочных правил Outthentic::DSL [11], который был разработан специально для анализа текстового вывода произвольных программ. DSL предлагает большой набор возможностей, из которых на практике может потребоваться только проверка на построчное включение заданных строк и соответствие регулярному выражению. Итак, story.check
будет таким:
$ cat story.check
install ok installed
Отлично, теперь можно запустить нашу истории посредством Sparrow. Это будет прототипом нашего плагина. Для этого установим из CPAN модуль Sparrow, который предоставляет средства разработки и запуска Sparrow плагинов.
$ cpanm Sparrow
Отлично, перейдя в директорию, где лежит наш сценарий запустим его посредством утилиты strun
— это клиент для запуска сценариев в формате Sparrow:
$ strun
/tmp/.outthentic/30382/home/melezhik/projects/nginx-example/story.t ..
# Status: install ok installed
ok 1 - output match 'Status: install ok installed'
1..1
ok
All tests successful.
Files=1, Tests=1, 1 wallclock secs ( 0.01 usr 0.00 sys + 0.51 cusr 0.03 csys = 0.55 CPU)
Result: PASS
Как уже говорилось, мы получили результат работы нашего сценария в виде TAP отчета, по которому видно что скрипт отработал корректно. Что здесь произошло? strun
запустил сценарий и проверил что:
Далее, аналогичным образом создадим сценарий настройки nginx сервера вместе с проверочный файлом. Так как каждая история должна находится в своей директории создадим для сценария настройки отдельную директорию:
$ mkdir nginx-setup
$ cd nginx-setup
Сценарий настройки будет очень простым:
$ cat nginx-setup/story.bash
sudo update-rc.d nginx defaults
sudo service nginx start
sudo service nginx status
curl -sf -o /dev/null 127.0.0.1
Для начала можно просто запустить сценарий руками и посмотреть вывод
System start/stop links for /etc/init.d/nginx already exist.
* nginx is running
Теперь можно создать проверочный файл:
$ cat nginx-setup/story.check
nginx is running
Отлично, снова запустим наша сценарии уже через strun
клиент:
$ strun
/tmp/.outthentic/32332/home/melezhik/projects/nginx-example/nginx-setup/story.t ..
# System start/stop links for /etc/init.d/nginx already exist.
# * nginx is running
ok 1 - output match 'nginx is running'
1..1
ok
/tmp/.outthentic/32332/home/melezhik/projects/nginx-example/story.t ..............
# Status: install ok installed
ok 1 - output match 'Status: install ok installed'
1..1
ok
All tests successful.
Files=2, Tests=2, 1 wallclock secs ( 0.01 usr 0.00 sys + 0.58 cusr 0.08 csys = 0.67 CPU)
Result: PASS
Убеждаемся, что мы достигли заданной цели. Nginx установлен, запущен, добавлен в автозагрузку и доступен по 80 порту.
Внимательный читатель увидит однако одну особенность в написанном нами наборе скриптов, а именно — сценарий установки nginx запускается после сценария настройки. Все дело в том, что по умолчанию все истории запускаемые клиентом strun
считаются независимыми и никак не связанными, порядок их запуска, вообще говоря, не гарантирован и даже больше — разные истории могут быть запущены в параллельном режиме ( читайте документацию [12] по параметрам утилиты prove [13], которой strun диспетчеризирует запуск тестов ).
Очевидно, что при таком поведении, запуск плагина в первый раз, когда пакет nginx еще не установлен в системе, даст нам ошибку.
Что же нам делать? Как обеспечить запуск сценариев в заданной последовательности. Нам нужно сначала установить пакет nginx, а затем уже произвести настройку сервера. Для этого в Sparrow существует понятие модулей или второстепенных ( downstream ) историй.
Второстепенные истории — это сценарии, которые вы можете вызвать ПЕРЕД выполнением какого-то основного сценария ( основная ( upstream ) истории ). В нашем случае — основной сценарий будет сценарий настройки, а вторичным — сценарием сценарий установки пакета. Вторичные сценарии никогда не запускаются клиентом strun
напрямую, вы должны сделать их вызов явно в основном сценарии. Вот как это делается:
Что бы сценарий стал вторичным необходимо поместить соответствующую историю в директорию под названием ./modules
, таким образом strun
поймет, что данная история второстепенная:
$ mkdir -p modules/nginx-install
$ mv story.bash story.check modules/nginx-install
Для вызова второстепенной истории воспользуемся так называемый hook
файлом — основным механизмом в Sparrow, позволяющим расширять логику работы strun
клиента и добавлять вызовы стороннего кода перед выполнением основного сценария:
$ cat nginx-setup/hook.bash
run_story nginx-install
Не вдаваясь здесь в детали Hook API [14] скажу лишь, что в данном примере в хук файле мы вызываем второстепенную историю nginx-install
с помощью функции run_story
. Обратите внимание, что аргумент функции — путь до директории, в которой находится второстепенная история, из которого исключается фрагмент modules
.
Итак запустим переработанный код:
$ strun
/tmp/.outthentic/367/home/melezhik/projects/nginx-example/nginx-setup/story.t ..
# Status: install ok installed
ok 1 - output match 'Status: install ok installed'
# System start/stop links for /etc/init.d/nginx already exist.
# * nginx is running
ok 2 - output match 'nginx is running'
1..2
ok
All tests successful.
Files=1, Tests=2, 1 wallclock secs ( 0.01 usr 0.00 sys + 0.54 cusr 0.06 csys = 0.61 CPU)
Result: PASS
Отлично, судя по выводу убеждаемся, что сценарий установки запускается перед сценарием настройки, чего и хотелось.
Подробнее про основные и второстепенные истории читайте в документации [15] по клиенту strun
.
Протестировав работу сценариев и убедившись, что все работает как надо, мы готовы поделится нашим скриптом с остальным миром и загрузить его в SparrowHub — центральный репозитарий. Для этого нужно сделать два простых шага:
После этого, вы сможете загружать плагины под своим авторством.
В корне нашего проекта, где лежат истории создадим файл с метаданными плагина:
$ cat sparrow.json
{
"name" : "nginx-example",
"version" : "0.1.0",
"description" : "simple nginx server installer for Ubuntu",
"url" : "https://github.com/melezhik/nginx-example.git"
}
Формат файла подробно описан здесь [16], не будем подробно останавливаться на нем. Важно лишь сказать, что Sparrow поддерживает версионирование плагинов, позволяя загружать и устанавливать разные версии одного плагина.
Из в директории со скриптами запустим команду sparrow менеджера, указав свои идентификаторы на SparrowHub
$ export sph_user=melezhik
$ export sph_token=FOO-BAR-BAZ-FOO-BAR-BAZ
$ sparrow plg upload
sparrow.json file validated ...
plugin nginx-example version 0.001000 upload OK
Все отлично. Плагин [17] загружен и находится в SparrowHub репозитарии. Мы можем зайти на другой сервер и воспользоваться данным плагином:
$ ssh some-other-host
$ sparrow index update
$ sparrow plg install nginx-example
$ sparrow plg run nginx-example
Нет возможности описать в данной статье все возможности и тонкости системы Sparrow и среды разработки Outthentic. Приведу тезисно, что еще можно было бы раскрыть. ( Если у читателя будет интерес об этом можно будет в следующих статьях ).
PS Надеюсь на конструктивную критику :) и конечно же на привлечение новых разработчиков плагинов в проект SparrowHub.
Спасибо!
Автор: alexey_melezhik
Источник [18]
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/linux/120834
Ссылки в тексте:
[1] статье: https://habrahabr.ru/post/281583
[2] SparrowHub: https://sparrowhub.org
[3] Sparrow: https://github.com/melezhik/sparrow
[4] TAP: https://en.wikipedia.org/wiki/Test_Anything_Protocol
[5] chef: https://www.chef.io/chef/
[6] minitest chef handler: https://github.com/chef/minitest-chef-handler
[7] chef inspec: https://www.chef.io/inspec/
[8] nginx: http://nginx.org/ru/
[9] Ubuntu: https://ru.wikipedia.org/wiki/Ubuntu
[10] Bash: https://ru.wikipedia.org/wiki/Bash
[11] Outthentic::DSL: https://metacpan.org/pod/Outthentic::DSL
[12] документацию: https://metacpan.org/pod/Outthentic#Prove-settings
[13] prove: http://perldoc.perl.org/prove.html
[14] Hook API: https://metacpan.org/pod/Outthentic#Hooks-API
[15] документации: https://metacpan.org/pod/Outthentic#Upstream-and-downstream-stories
[16] здесь: https://metacpan.org/pod/Sparrow#Create-a-plugin-meta-file-sparrow.json
[17] Плагин: https://sparrowhub.org/info/nginx-example
[18] Источник: https://habrahabr.ru/post/300876/?utm_source=habrahabr&utm_medium=rss&utm_campaign=best
Нажмите здесь для печати.