[Из песочницы] Готовим свой UI-интерфейс к Zabbix API средствами React component

Всем привет! Все началось с интеграции телефонной платформы в корпоративный сайт.

Будучи инженером VoIP телефонии, WEB-разработка поразила разнообразием подходов и методов реализации. Стек технологий пестрит разнообразием, выбор инструментов определяет стиль разработки, модульность или закостенелость проекта.

Про телефонную платформу я напишу в следующий раз. Сильный уклон в VoIP-специфику отвлечет от главного — методов разработки современного SPA-приложения.

В статье будет описан процесс внедрения стороннего сервиса в существующую рабочую среду.

Сегодня поиграемся с Zabbix-API.

image

Live Demo

image

Кому будет интересно


Тем кто лет десять назад реализовал 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, но это плохо:

  1. Zabbix-API придется открыть для всех клиентских браузеров. Безопасней открывать отдельный ресурс с ограниченным набором действий
  2. Создаем общее решение, способное работать с кардитально разными системами: 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».

  1. Administration/User groups — добавляем группу пользователей «react_user_group»
  2. Administration/User groups/Permissions — добавляем Host groups, с которыми будет позволено работать «react_user». Выставляем Read-write.
  3. Administration/Users — добавляем пользователя, включаем в группу пользователей созданную в пп.1
  4. 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 функции. Компоненты освобождены от сложностей взаимодействия с интегрируемыми системами, только отображение.

© Habrahabr.ru