[Из песочницы] Готовим свой UI-интерфейс к Zabbix API средствами React component
Всем привет! Все началось с интеграции телефонной платформы в корпоративный сайт.
Будучи инженером VoIP телефонии, WEB-разработка поразила разнообразием подходов и методов реализации. Стек технологий пестрит разнообразием, выбор инструментов определяет стиль разработки, модульность или закостенелость проекта.
Про телефонную платформу я напишу в следующий раз. Сильный уклон в VoIP-специфику отвлечет от главного — методов разработки современного SPA-приложения.
В статье будет описан процесс внедрения стороннего сервиса в существующую рабочую среду.
Сегодня поиграемся с Zabbix-API.
Live Demo
Кому будет интересно
Тем кто лет десять назад реализовал WEB-интерактив средствами CGI-скриптов на серверной стороне, и хочет понять современные подходы. Если Вам приходилось выдумывать собственные API-интерфейсы, заниматься документацией того что получилось — решение ниже.
Ставим задачу
Первичная настройка Zabbix ведется через встроенный WEB-интерфейс. Рутина обычно сводится к простому добавлению хостов в группу.
Учет оборудования (добавление хостов) мы ведем в собственной системе на корпоративном сайте.
- Было бы не плохо интегрировать рутинные задачи Zabbix в существующую среду учета. Свести к минимуму количество параметров, в идеале одна кнопка «добавить»
Разработкой корпоративной системы обычно занимается отдельный коллектив.
- Было бы неплохо выдать им функционал в виде готового модуля. В идеале пара строчек кода «import …» и «render …»
- Постараться использовать современный стек технологий, желательно стандартные интерфейсы взаимодействия
Стек технологий
ReactJS
Пользовательский интерактив классически описан схемой работы MVC с ее вариациями. Изучая матчасть появились кандидаты Vue, Ember, Meteor, Angular, ReactJS.
Пришло понимание, что большинство фреймворков/библиотек пытается реализовать полную экосистему MVC с реализацией как на front-end так и back-end, называют это «full stack».
React — это только «V» от «MVC». Погружаться в чужую экосистему не хотелось, а вот простая рисовалка очень приглянулась. Порадовала перспектива со временем перескочить в React Native: один код для Web, IOS, Android. А подключив Redux, должен получиться full stack. Отдельно порадовал JSX, киллер-фича IMHO.
JSX
JSX -детище разработчиков React — синтаксическая надстройка над JavaScript, визуально упрощает работу с DOM-элементами браузера.
Матерые WEB-разработчики ругают его за то, что он перемешивает HTML разметку и JavaScript код. Я не матерый разработчик и JSX считаю отличным решением.
NodeJS
Сначала казалось удобным писать на «браузерном» JavaScript. Правда там неудобно разбивать проект на модули и подгружать необходимые. Проблему решил пакетный менеджер Bower. Там своя философия, Bower заботится чтобы версии модулей не конфликтовали друг с другом.
На практике оказалось что все необходимые инструменты доступны в виде npm пакетов. Если нужный модуль не доступен в виде npm пакета, Bower хорошее дополнение.
Итог. Пишем на Node, используем пакетный менеджер npm.
Browserify
NodeJS это серверный JavaScript, не браузерный. Хорошие люди придумали транспайлерBrowserify который переделывает Node-код в браузерный вариант.
Babel
Браузеры не отличаются высокой скоростью обновления встроенного JavaScript движка. Хотелось бы использовать весь «сахар» современного JavasScript, отсюда еще один инструмент — Babel. Транспайлер который умеет работать с последними версиями ECMAScript. А еще, именно он будет распознавать JSX-синтаксис.
Gulp
Помимо работы с JavaScript современная WEB-страничка плотно использует CSS, которые перешли на новый уровень абстракций SASS. Подгружаются собственные шрифты и картинки. HTML-текст может быть раскидан по различным файлам. В итоге, построение финального проекта сводится к десятку действий над различными файлами, разбросанными по файловой системе в разнообразном порядке.
Gulp это сборщик. По сути, обычный Node скрипт, в котором автоматизированы действия обработки исходных файлов проекта.
Я выбрал Gulp, в свое время понравился принцип его работы: поточная обработка, это быстро. Он выигрывал у Grunt, а еще попалась статья Insayt, на базе которой я и сделал свой gulpfile.js.
В качестве альтернативы, есть смысл рассмотреть webpack, я не пробоавл.
Здесь стоит заметить — основные инструменты для разработки front end мы перечислили. Теперь очередь за back end.
Но сначала, сформулируем принцип работы нашей будущей React-компоненты и Zabbix-API.
Цель
- Взаимодействие Front-Back свести до простейших REST-запросов
- Сосредоточить всю логику взаимодействия с Zabbix-сервером на back end
- Желательно стандартный интерфейс + документация
Можно было бы взгромоздить всю логику на front end, но это плохо:
- Zabbix-API придется открыть для всех клиентских браузеров. Безопасней открывать отдельный ресурс с ограниченным набором действий
- Создаем общее решение, способное работать с кардитально разными системами: SNMP-датчиками, telnet-сессиями, с ресурсами ОС серверов и проч. (Zabbix — лишь одна из реализаций). Браузер просто не имеет подобного функционала
Итог. Нужен «умный» back end, имеющий свой API.
Еще немножко технологий
OpenAPI
При интеграции в телефонную платформу были пройдены первые «грабли». Был написан свой собственный API-сервер. Он работал. Успешно «рулил» софтсвичем, принимал REST-запросы которые по сути не являлись REST. Никакой документации по формату, методам и параметрам запросов не было.
Такая ситуация породила интерес, можно ли как-то формализовать API-интерфейс, чтобы документация формировалась автоматически? Приглянулся подход OpenAPI.
Суть сводится к тому, что сначала надо написать файл спецификации, в котором будут описаны все методы, поля, форматы ответов и т.п. Потом на базе этого файла можно сгенерировать готовый API-сервер. Список языков впечатляет, мы сделаем на NodeJS.
Так-как файл спецификации стандартный, для него уже придуманы инструменты: Swagger, ReDoc, OA Viewer, … подробней здесь. Вопрос с документацией решается автоматически — это и есть файл спецификации.
Docker
Совсем скоро мы начнем писать исполнимый код. Скрипты будут на языке NodeJS. Любой язык эволюционирует, меняются версии, было бы неплохо пробовать результат на разных версиях языка. В каждом языке есть спец.инструменты для «жонглирования» версиями.
Я поступаю радикальней. Есть отличная технология LXC, предлагающая очень легкую виртуализацию на уровне ядра Linux. Грех было бы ей не воспользоваться. В случае с другими ОС есть своя специфика, разработчики учли нюансы и создали продукт Docker.
Необходимую среду разработки мы будем строить в нужном Docker-контейнере.
Приступим
Проект доступен на Github
git clone https://github.com/ars-anosov/zabbix-react.git
zabbix-reactor-node
Back end сервер назовем «zabbix-reactor-node». Просматриваем файл спецификации. Проверяем поле «host».
less zabbix-react/node-back/api/zabbix-api.yaml
Если разворачиваем сервер на своей машине
host: 'localhost:8002'
Сервер собран при помощи swagger editor на базе «zabbix-api.yaml». Структура такова:
index.js — стартовый скрипт
var app = require('connect')()
var swaggerTools = require('swagger-tools')
var http = require('http')
- http — WEB-сервер
- connect при помощи middleware swagger-tools — обработка запросов
// Route validated requests to appropriate controller
app.use(middleware.swaggerRouter(options));
// Serve the Swagger documents and Swagger UI
app.use(middleware.swaggerUi({
apiDocs: '/spec/swagger.json',
swaggerUi: '/spec-ui'
Методы:
- middleware.swaggerRouter — роутер, прокидывает запросы на соответствующий контроллер в директории zabbix-react/node-back/controllers
- middleware.swaggerUi — инструмент SwaggerUI. Это и есть наша документация к API, позволяет выполнять тестовые REST-запросы
controllers/ — скрипты отвечающие за обработку API-запросов
Configuration.js
Data.js
config_host_del.js
config_host_get.js
config_host_post.js
config_host_put.js
config_hostgroup_get.js
data_hostlink_get.js
Именно здесь наполняем логикой наши взаимодействия с Zabbix-API.
В Docker-контейнер будет прокинута директория «node-back»: переходим в нее.
cd zabbix-react/node-back/
Запускаем «zabbix-reactor-node». Передаем в контейнер переменные окружения ZX_URL, ZX_USER, ZX_PASS — вбиваем свои, если есть свой Zabbix. В качестве примера можете использовать мой тестовый Zabbix:
docker run \
--name zabbix-reactor-node \
-v $PWD:/zabbix-reactor-node \
-w /zabbix-reactor-node \
--publish=8002:8002 \
--env="ZX_URL=http://zabbix-server.react.com.ru/api_jsonrpc.php" \
--env="ZX_USER=guest" \
--env="ZX_PASS=" \
-it \
node:8 bash
Старые версии заббикса могут принимать запросы на другом URL. Смотрим Zabbix doc.
Дальше все действия внутри контейнера.
npm install
node index.js $ZX_URL $ZX_USER $ZX_PASS
Выскочить из контейнера: Ctrl+P+Q
Проверяем доступноать SwaggerUI — http://localhost:8002/spec-ui/
В поле «token» вписываем «test». Здесь будет токен авторизации, его проверкой занимается скрипт node-back/sub_modules/aaa_handle.js.
Zabbix настройки
Мы хотим открыть доступ только к определенным Host group на Zabbix. Для этого необходимо создать отдельного пользователя «react_user».
- Administration/User groups — добавляем группу пользователей «react_user_group»
- Administration/User groups/Permissions — добавляем Host groups, с которыми будет позволено работать «react_user». Выставляем Read-write.
- Administration/Users — добавляем пользователя, включаем в группу пользователей созданную в пп.1
- Administration/Users/Permissions — User type выставляем «Zabbix Admin»
zabbix-react-front
Строим среду разработку назовем ее «zabbix-react-front».
В Docker-контейнер будет прокинута директория «web-front»: переходим в нее.
cd zabbix-react/web-front/
Запускаем «zabbix-react-front»:
docker run \
--name zabbix-react-front \
-v $PWD:/web-front \
-w /web-front \
--publish=8003:8003 \
-it \
node:8 bash
Дальше все действия внутри контейнера.
# глобально устанавливаем gulp-cli
npm install -g gulp-cli
# Теперь все необходимое (транспайлеры, утилиты, плагины)
npm install
Компоненты находятся в директории web-front/src/js/components, они имеют свои зависимости.
Устанавливаем:
npm run install-components
Собираем проект в директорию web-front/build
gulp
Выскочить из контейнера: Ctrl+P+Q
Проверяем работу компонент — http://localhost:8003/
zabbix-react-component
Вот мы и добрались до работы с компонентами. Посмотрим что сейчас запущено.
- zabbix-reactor-node — OpenAPI-сервер, открыт для приема REST-запросов на http://localhost:8002/…
- zabbix-react-front — livereload-web-сервер для отображения React-компонент, рисует на http://localhost:8003/
Работаем со следующей структурой файлов:
web-front/src/index.jsx — JSX-скрипт с компонентами
import React from 'react';
import ReactDOM from 'react-dom'
import { OpenApiSwagger, HostConfig, HostGraph } from './components/zabbix-react-component'
window.localStorage.setItem('token', 'test')
const specUrl = 'http://localhost:8002/spec/swagger.json'
const swg = new OpenApiSwagger(specUrl)
swg.connect((client, err) => {
if (err) {
ReactDOM.render(
no spec - {specUrl} !,
document.getElementById('root')
)
}
else {
ReactDOM.render(
,
document.getElementById('root')
)
}
})
- specUrl — путь к файлу спецификации на zabbix-reactor-node
web-front/src/components/ — директория с компонентами
web-front/src/components/zabbix-react-component.js — экспортируемые классы. Доступны в качестве npm пакета zabbix-react-component.
export { OpenApiSwagger } from './OpenApiSwagger.js'
export { HostConfig } from './HostConfig.jsx'
export { HostGraph } from './HostGraph.jsx'
С этого места можно смело ваять свои компоненты, наращивать функционал.
В качестве примера, приделал инструмент, который есть в Nagios, но отсутствует в Zabbix. Автоматическое построение карты сети на базе мета-информации «source-target» в описании элементов сети.
Смотрим компоненту HostGraph. Для хранения информации использую в Zabbix Host закладку «Host inventory» поле «Notes». Туда в JSON-формате заносим связки элементов «source-target». Для визуализации использовал проект d3 — Force-Directed Graph.
Заключение
Теперь у нас в руках находится среда разработки, front-end и back-end. Для работы достаточно знания JavaScript и специфики NodeJS.
API-документирован и доступен для тестирования сторонними front-end разработчиками. API-сервер не привязан именно к Zabbix, это общее решение. Возможна интеграция к любой системе.
Собраны готовые React-компоненты выполняющие стандартные CRUD функции. Компоненты освобождены от сложностей взаимодействия с интегрируемыми системами, только отображение.