- PVSM.RU - https://www.pvsm.ru -

Разработка Sparrow плагинов

Приветствую!

В предыдущей статье [1] я писал о SparrowHub [2] — репозиторий готовых утилит для системного администрирования. Что же, время прошло, и теперь хочется рассказать о том КАК разрабатывать эти самые утилиты и загружать их на SparrowHub для повторного использования кем-либо.

Прежде чем показать конкретный пример написания плагина, хочу немного раскрыть идеологию фреймворка Sparrow [3], на котором собственно и разрабатываются скрипты.

Во-первых, Sparrow не навязывает какого-то жесткого DSL для разработки скриптов. У вас есть на выбор три языка, поддерживаемых Sparrow:

  • Perl
  • Ruby
  • Bash

Таким образом, вы просто пишите обычный скрипт, который делает нужную вам работу и "оборачиваете" его в плагин, и, вуаля — он готов к загрузке на 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 позволяет сделать два типа проверок:

  • проверить, что код завершения успешный ( == 0 )
  • проверить, что в текстовом выводе скрипта содержатся определенные данные ( проверка на соответствие строкам и регулярным выражениям )

Правила на именование скрипта простое — базовое имя должно быть story с соответствующим языку сценария расширением:

  • Bash — story.bash
  • Perl — story.pl
  • Ruby — story.rb

Итак, в случае с 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 запустил сценарий и проверил что:

  • код завершения успешный
  • сценарий вывел в stdout строчку 'Status: install ok installed'

Сценарий настройки

Далее, аналогичным образом создадим сценарий настройки 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

Протестировав работу сценариев и убедившись, что все работает как надо, мы готовы поделится нашим скриптом с остальным миром и загрузить его в SparrowHub — центральный репозитарий. Для этого нужно сделать два простых шага:

  • зарегистрироваться на сайте https://sparrowhub.org [2]
  • залогиниться и получить токен разработчика плагинов

После этого, вы сможете загружать плагины под своим авторством.

В корне нашего проекта, где лежат истории создадим файл с метаданными плагина:

$ 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. Приведу тезисно, что еще можно было бы раскрыть. ( Если у читателя будет интерес об этом можно будет в следующих статьях ).

  • Outthenitc API для Perl и Ruby
  • Параметры для второстепенных историй
  • Outthentic::DSL [11] — валидатор обычного текста ( генераторы проверочных правил, асерты, кепчи, текстовые блоки и т.д. )
  • Конфигурация Sparrow плагинов ( Задачи, runtime параметры, YAML конфигурационные файлы и в формате Config::General )

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