Практики ChatOps с VK Teams (часть II): OpsDroid — коннектор, скиллы, боты

от автора

Всем привет! Меня зовут Макарий, я DevOps-инженер в команде кросс-платформенной инфраструктуры корпоративного супераппа VK Teams. Сегодня я продолжу рассказ о том, как мы применяем практики ChatOps в наших рабочих процессах. Первую часть о самих практиках и мини-аппах для их реализации можно прочитать здесь.

Напомню, ChatOps — модель организации работы и коммуникации внутри команды через общение, то есть через мессенджер. Такой подход объединяет разработчиков, DevOps-инженеров, QA-специалистов, инженеров поддержки, продуктовых менеджеров, аналитиков и других участников процесса в единую коммуникационную платформу. Мы рассмотрим открытый кросс-платформенный фреймворк OpsDroid, его возможности, напишем коннектор между OpsDroid и VK Teams, а также реализуем бота. Уверен, этот опыт откроет для ваc новые возможности, которые предоставляет ChatOps.

ChatOps и корпоративные мессенджеры

В предыдущей части мы рассмотрели основные принципы построения ChatOps:

Также мы поговорили о том, как работает автоматизация процессов с использованием корпоративного мессенджера:

Здесь нам на помощь приходит VK Teams — корпоративный суперапп от VK, который объединяет в себе мессенджер для общения с коллегами, ботов для автоматизации, свой таск-трекер, видеоконференции на 100 пользователей и платформу мини-приложений. 

Успешная реализация ChatOps требует не только выбора подходящих инструментов, но и создания культуры, при которой команды готовы активно использовать и вкладываться в принципы ChatOps.

Open-Source-фреймворк OpsDroid

OpsDroid — это кросс-платформенный фреймворк для разработки ChatOps-решений. Его основная идея заключается в создании единого центра управления ботом, который может работать одновременно на нескольких платформах, таких как Slack, MS Teams, Webex Teams, Facebook Messenger, Telegram, Matrix, Discord и других. Это позволяет командам использовать существующую инфраструктуру мессенджеров для управления операциями и взаимодействия с OpsDroid.

Взаимодействие между OpsDroid и платформой мессенджера осуществляется через коннекторы. Они представляют собой абстракцию над API и протоколами, используемыми различными мессенджерами и сервисами уведомлений. Коннекторы обеспечивают унифицированный интерфейс для взаимодействия с платформами и позволяют:

  • принимать и отправлять сообщения,
  • управлять каналами и пользователями,
  • получать уведомления о событиях и реагировать.

Например, для связи OpsDroid и VK Teams потребуется соответствующий коннектор, который свяжет Bot API VK Teams с функциональностью OpsDroid.

OpsDroid также предоставляет удобный интерфейс для создания ботов: в виде навыков (skills) — то есть модулей, которые обрабатывают входящие события (events), анализируют их, взаимодействуют с внешними сервисами, возвращают результат для обработки.

Установить OpsDroid можно удобным для вас способом на личный компьютер или сервер. Для запуска бота необходимо настроить OpsDroid в соответствии с инструкциями:

Linux, MacOS — используйте Docker (руководство). Вы также можете установить OpsDroid без использования Docker, просто с помощью:

pip3 install opsdroid[common]  

Руководство для Windows.

Коннектор OpsDroid-VK Teams

Для связи VK Teams и OpsDroid можно написать простой коннектор.

Вот его код

import aiohttp import asyncio  from opsdroid.connector import Connector from opsdroid.events import Message   class ConnectorVKTeams(Connector): """A connector for VK Teams"""      def __init__(self, config, opsdroid=None):         # Инициализация коннектора                super().__init__(config, opsdroid=opsdroid)         self.name = "vkteams"          self.opsdroid = opsdroid         self.latest_update = None         self.listening = True         self.default_target = self.default_user         self.session = None         self._closing = asyncio.Event()         self.loop = asyncio.get_event_loop()           self.base_url = config.get("base-url", None)         self.default_user = config.get("default-user", None)         self.whitelisted_users = config.get("whitelisted-users", None)         self.update_interval = config.get("update-interval", 1)         # без токена бот работать не сможет         self.token = config["token"]      async def _get_messages(self):         # Получение сообщений из ивентов. Ивенты получаем: events/get из Bot API          data = {             'token': self.token,             'pollTime': 30,             'lastEventId': 1         }         if self.latest_update is not None:             data["lastEventId"] = self.latest_update          await asyncio.sleep(self.update_interval)         resp = await self.session.get(self.build_url("events/get"), params=data)          if 200 == resp.status:             json = await resp.json()             await self._parse_message(json)      async def _parse_message(self, response):         # Отдаем сообщения, которые нашли в json-е ивента          for event in response["events"]:             user = self.get_user(event)             target = self.get_target(event)             parsed_event = await self.handle_messages(                 user=user,                 target=target,                 event_id=event.get("eventId"),                 raw_event=event             )             if parsed_event:                 if self.handle_user_permission(event, user):                     await self.opsdroid.parse(parsed_event)                 else:                     block_message = Message(                         text="У вас нет доступа к взаимодействию с ботом",                         user=user,                         user_id=user,                         target=target,                         connector=self                     )                     await self.send(block_message)                 self.latest_update = event["eventId"]             elif "eventId" in event:                 # игнорируем                 self.latest_update = event["eventId"] 

    

Также в коннекторе необходимо реализовать методы для отправки сообщений, согласуя с Bot API.

Вот код реализации

import aiohttp  from opsdroid.connector import register_event from opsdroid.events import Message, File  ...   @register_event(Message) async def send_message(self, message):  data = dict() data["token"] = self.token data["chatId"] = message.target data["text"] = message.text  resp = await self.session.post(self.build_url("messages/sendText"), data=data)   @register_event(File) async def send_file(self, file_event):  data = aiohttp.FormData() data.add_field(       "token", str(self.token)) data.add_field(         "chatId", str(file_event.target), content_type="multipart/form-data") data.add_field(         "file",         await file_event.get_file_bytes(),         content_type="multipart/form-data")  async with aiohttp.ClientSession() as session:       resp = await session.post(self.build_url("messages/sendFile"), data=data)  

Подробнее пример коннектора смотрите в репозитории. Коннектор позволяет OpsDroid понимать, когда приходит новое сообщение в VK Teams, и получать его содержимое, а также самому отправлять сообщения. Коннектор можно дополнительно расширить. Например, добавить поддержку всех возможных ивентов от OpsDroid:

from opsdroid.events import JoinGroup  ...  if raw_event.get("type") == "newChatMembers":     return JoinGroup(         user=f"@[{user}]",         user_id=user,         event_id=event_id,         target=target,         connector=self,         raw_event=raw_event,     ) 

Или реализовать поддержку всех типов событий, которые доступны на платформе (для VK Teams см. /events/get).

Код реализации

from opsdroid.events import Message from . import vkt_events  ...  if raw_event['payload']['parts'][0].get("type") == "forward": return vkt_events.Forward(         user=f"@[{user}]",         user_id=user,         event_id=event_id,         target=target,         message=Message(             text=raw_event['payload']['text'],             user=f"@[{first_part['payload']['message']['from']['userId']}]",             user_id=first_part['payload']['message']['from']['userId'],             connector=self,             raw_event=first_part,         ),         connector=self,         raw_event=raw_event ) 

Расширение коннектора увеличивает возможности навыков, которыми будут обладать ваши боты. В нашем случае добавим поддержку следующих ивентов: Reply, Forward, File, Voice, Sticker, Mention для нового сообщения, а также Edited Message, Deleted Message, Pinned/Unpinned Message, Join/Left chat для других событий в чате.

Еще OpsDroid предоставляет широкие возможности для тестирования. Принято полностью покрывать новый коннектор тестами.

Пример бота с OpsDroid

Давайте реализуем такого же бота, который отправляет на указанный имейл сообщение, если на него был дан ответ с ключевым словом «send_email». Мы будем использовать OpsDroid для создания кросс-платформенного бота, который будет работать как в VK Teams, так и в Slack и, например, в Matrix. Код не претерпит значительных изменений, мы обернем его в OpsDroid. Действия, которые мы ранее выполняли с распаковкой payload вложенного сообщения, перенесены в код коннектора, разобранный выше, в парсинг ивента типа Reply. В данном случае нам останется лишь получить содержимое ивента, которое привязано к основному:

message.linked_event.text 

Навык, который будет использоваться в нашем кросс-платформенном боте в файле configuration.yaml, выглядит следующим образом:

from opsdroid.skill import Skill from opsdroid.matchers import match_regex from opsdroid.constraints import constrain_connectors   class SendEmailSkill(Skill):      @match_regex(r'send_email', matching_condition="fullmatch")     async def send_email(self, message):         if not isinstance(message, Reply):             await message.respond("Сделайте реплай на сообщение, "                                   "которое хотите переслать на имейл")             return          message_for_email = f"{message.linked_event.user_id}:\n\n" \                              f"{message.linked_event.text}\n\n"          send_email(to=["your.real.email@mail.ru"],                        subject=f"Сообщение из {message.connector.name}(opsdroid)",                        text=message_for_email)         await message.respond(f"Сообщение переслано на имейл")       @match_regex(r'send_email', matching_condition="fullmatch")     @constrain_connectors(['slack'])     async def send_email_slack(self, message):         slack = self.opsdroid.get_connector('slack')          thread_timestamp = message.raw_event.get('thread_ts', None)         replies = await slack.slack_web_client.conversations_replies(             channel=message.target, ts=thread_timestamp         )         messages = replies['messages']          thread_head = messages[0]         users_info = await slack.slack_web_client.users_info(user=thread_head['user'])          message_for_email += f"{users_info.get('user').get('real_name')}:" \                              f"\n\n{thread_start['text']}\n\n"          send_email(to=["your.real.email@mail.ru"],                    subject=f"Сообщение из Slack (opsdroid)",                    text=remove_emoji(message_for_email))         await message.respond(f"Сообщение переслано на имейл") 

Код этого навыка для Slack отличается, так как коннектор Slack не поддерживает тип ивента Reply. Здесь мы используем разбиение с помощью constrain_connectors, чтобы в случае, если бот принял ивент в Slack, он распарсил его одним способом, а если принял в VK Teams или в Matrix — то другим, более подходящим. Коды навыка для VK Teams и Matrix идентичны.

Подробнее пример навыка смотрите в репозитории. Для более глубокого погружения используйте полную документацию OpsDroid.

Затем нам необходимо организовать структуру проекта следующим образом:

.
├── Dockerfile*
├── configuration.yaml
└── skills
    └── email_sender (имя кастомного скилла)
        └── __init__.py

* Dockerfile — если вы запускаете OpsDroid с помощью docker.

Для этого выполним следующие команды:

cd /home/username/Projects  mkdir -p my_opsdroid_project/skills/email_sender  cd my_opsdroid_project  vim __init__.py  <- сюда положим код навыка 

Соберем нашего кросс-платформенного бота:

configuration.yaml

logging:   level: debug   timestamp: true   welcome-message: false   # Web server web:   host: '0.0.0.0'   port: 8080   ## Parsers parsers: []  ## Connectors modules connectors:   vkteams:     token: "VKT_BOT_TOKEN"  # <- токен, который получили у Метабота     bot-name: "email_sender_bot"  # <- имя бота, которое задали Метаботу при создании     base-url: "api.my-company.myteam.mail.ru/bot/v1/"  # <- base-url бот-апи     repo: https://github.com/mboriskin/connector-vkteams  # <- код коннектора    # как настроить slack - https://docs.opsdroid.dev/en/stable/connectors/slack.html   slack:     bot-token: "SLACK_BOT_TOKEN"     bot-name: "email_sender_bot"     socket-mode: true     app-token: "SLACK_APP_TOKEN"    # как настроить matrix - https://docs.opsdroid.dev/en/stable/connectors/matrix.html   matrix:     mxid: "@bot_account_username:matrix.org"     password: "bot_account_password"     rooms:       'main': '#my-corporate-bots:matrix.org'     nick: "Botty EmailSender"      ## Skill modules skills:   ## Hello (https://github.com/opsdroid/skill-hello)   hello: {}  # <- как пример, навык по умолчанию     ## Отправить сообщение на имейл   email_sender:     path: /opt/opsdroid/skills/email_sender  # <- там лежит навык (если через docker)     no-cache: true     app-name: my_opsdroid_vkt 

Соберем бота:

opsdroid config -f configuration.yaml build

Запустим в работу:

opsdroid start 

Для запуска через Docker стяните скрипт startup.sh и Dockerfile из репозитория с примерами. Затем запустите скрипт для сборки бота:

IMAGE_NAME="my_opsdroid_vkt" ./startup.sh --build 

Запустить скрипт можем как напрямую (для отладки и наблюдения за логами):

./startup.sh --run 

Так и в фоне:

./startup.sh --runbg 

И когда придет время, остановить бота:

./startup.sh --stop

Также можем удалить отработавший образ:

./startup.sh --remove

После запуска бота вы сможете написать ему личное сообщение или сообщение в групповом чате, куда он добавлен, и он выполнит нужную операцию, отправив сообщение на указанный имейл.

Например, в Slack:

В VK Teams:

И в Matrix:

OpsDroid представляет собой мощный кросс-платформенный фреймворк для разработки ChatOps-решений. Благодаря способности работать одновременно на нескольких платформах, таких как Slack, MS Teams, VK Teams и других, OpsDroid обеспечивает командам гибкость и удобство при управлении операциями и взаимодействии с ботами. Концепция коннекторов упрощает интеграцию с различными сервисами, обеспечивая единый интерфейс для взаимодействия. Навыки в OpsDroid позволяют разработчикам создавать функциональность ботов, обрабатывать события и взаимодействовать с внешними сервисами. Благодаря простой установке и настройке OpsDroid является эффективным инструментом для разработки кросс-платформенных ботов, способных оперативно выполнять задачи и обеспечивать эффективное взаимодействие с пользователями.

Готовые решения OpsDroid можно шарить между мессенджерами.

Можно найти множество уже готовых решений для OpsDroid и затем интегрировать их для использования в VK Teams или другом сервисе.

Список готовых решений

  • skill-ssh — навык для взаимодействия с Linux-серверами с помощью SSH-команд;
  • skill-devops — навык для взаимодействия с Docker и Gitlab;
  • skill-sysanalytics — мониторинг системы при запущенном экземпляре OpsDroid;
  • skill-nginx-rtmp — мониторинг запуска, остановки nginx-rtmp и состояния в целом;
  • skill-github-linker — предоставление ссылок на GitHub Issues и PR при упоминании;
  • skill-jenkins — навык для взаимодействия с Jenkins;
  • skill-repohook — предоставление ссылок на события в Git{Hub|Lab};
  • skill-docker-daemon — навык для управления Docker;
  • skill-k8s — навык для работы с Kubernetes; 
  • skill-shell — навык для запуска shell-скриптов;
  • skill-yourextip — получение своего внешнего IP-адреса в чате;
  • skill taginfo — навык для получения данных из OpenStreetMap;
  • skill-awx — навык для взаимодействия с AWX;
  • skill-grafana-annotation — навык для создания и просмотра аннотаций Grafana;
  • skill-prometheus-scrape — навык для сбора метрик через Prometheus прямо из чата;
  • skill-github — навык для взаимодействия с GitHub;
  • skill-cloudhealth — навык для взаимодействия с CloudHealth;
  • skill-reminders — для установки напоминаний;
  • skill-minecraft — навык для отслеживания и публикации логов сервера Minecraft;
  • skill-google-it — для ответа ссылкой на поиск в Google;
  • skill-iss — навык для определения местоположения МКС;
  • skill-formula1-schedule — обработка календаря «Формулы-1» и отправка напоминаний;
  • skill-random — навык для примера: отображение случайных событий;
  • skill-words — навык, использующий модуль NLTK для игры в слова;
  • skill-word-of-the-day — прислать слово дня из Оксфордского словаря английского языка.

Заключение

ChatOps представляет собой модель организации работы и коммуникации внутри команды через мессенджеры, объединяя различные роли и функции в единую коммуникационную платформу. 

VK Teams как корпоративный суперапп предоставляет широкий набор инструментов для общения, автоматизации, управления задачами и видеоконференций. Успешная реализация ChatOps требует создания соответствующей культуры в команде, готовности использовать инструменты и принципы ChatOps.

OpsDroid является кросс-платформенным фреймворком для разработки ChatOps-решений. Он позволяет создать единую централизованную систему управления ботом, который может работать на различных платформах, таких как Slack, MS Teams, VK Teams, Matrix и других. Взаимодействие с мессенджерами осуществляется через коннекторы, которые предоставляют унифицированный интерфейс для обмена сообщениями, управления пользователями и получения уведомлений о событиях.

В качестве примера использования OpsDroid был рассмотрен простой бот, способный отправлять сообщения на указанный имейл при получении определенного ключевого слова. Благодаря гибкости OpsDroid и его возможности работать на различных платформах такой бот может быть использован как в VK Teams, так и в других мессенджерах, например Slack или Matrix.

Мы отметили возможность использования готовых решений OpsDroid, которые могут быть адаптированы и интегрированы для использования в VK Teams или других мессенджерах. Это позволяет разработчикам использовать уже существующие возможности и навыки для управления операциями и взаимодействия с ботами.

В целом благодаря OpsDroid и интеграции с VK Teams команды могут создавать эффективные и гибкие ChatOps-решения, улучшая коммуникацию, автоматизируя рутинные задачи.


ссылка на оригинал статьи https://habr.com/ru/articles/750208/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *