Мы не любим отвлекаться от текущей работы, копаться в трекере задач и почте, чтобы найти нужный тикет или письмо от клиента. Нас беспокоят пропущенные напоминания и недоступные логи. Чат-боты и боты для поддержки процессов разработки популярны у разработчиков именно потому, что избавляют нас от нелюбимой рутины. Боты помогают нам в DevOps-трансформации.  Для разработки ботов удобно использовать serverless-технологии. Одно из преимуществ при работе с приложениями облачного бота, которые тоже размещены в облаке, — моментальный доступ к ним. В докладе на DevopsConf 2021 я подробно рассказал о концепции СhatOps и о том, какие из serverless-технологий стоит взять на вооружение уже сейчас. Кажется, что СhatOps и serverless созданы друг для друга.  Для меня ChatOps открыл прекрасный докладчик Джеймс Фрайман (James Fryman). Про преимущества такой организации инфраструктуры он рассказал в своем докладе еще в 2015 году. За последние годы актуальность ChatOps не только не пропала, но с каждым годом становится более востребованной. В России интерес стал заметен благодаря цифровой трансформации и новым игрокам на рынке IT. ChatOps в России сегодня — это, в первую очередь, боты для Telegram и Slack (один из самых первых шагов, но не последний). Эти платформы лидируют по популярности среди платформ для ботов в России, а Slack входит в топ-3 корпоративных менеджеров в мировом рейтинге.  Давайте разберемся, как за вечер создать своего slack-бота на serverless технологиях. Типичная serverless-архитектура приложения из базового набора сервисов, размещенная рядом с существующими приложениями в облаке выглядит так как показано на рисунке ниже. Такой способ позволяет постепенно переносить необходимую функциональность в serverless экосистему и не переставать оказывать услуги пользователям. Serverless-приложение — это совокупность сервисов и функций, размещенных в облаке. Чтобы скрыть особенности реализации можно воспользоваться сервисом API Gateway. С одной стороны, у нас появляется единая точка доступа к приложению, с другой открываются возможности модификации приложения не сказывающиеся на внешних потребителях. Это удобно при реализации slack-ботов. В нашем случае архитектура нашего приложения весьма примитивна: сервис API Gateway прикрывает несколько функций, одна из которых будет связана с Yandex Database. Начнем создание нашего бота с регистрации нового приложения в Slack. Переходим в панель Slack, при этом вы должны быть авторизованы и обладать соответствующими правами. Нажимаем кнопку Create a Slack App, заполняем начальную информацию о приложении. Позже её можно будет отредактировать. Задаем значение имени ServerlessBotApp и в выпадающем списке выбираем доступный workspace.  В разделе OAuth & Permissions переходим в пункт Scopes и выбираем права для нашего бота. Добавляем в Bot Token Scopes через кнопку Add an OAuth Scope значение chat:write. После того, как мы определили права для бота, можно переходить к установке приложения в workspace.  В разделе OAuth Tokens for Your Workspace нажимаем кнопку Install to Workspace, на открывшейся странице — кнопку Allow. В результате, в этой же секции мы получим Bot User OAuth Token. Токены любят тишину, постарайтесь не светить его, он пригодится чуть позже.  Мы создали в Slack точку доступа, к которой можно подключаться. Осталось создать точку доступа на стороне облака. Для разработки нашего приложения нам потребуется сервисный аккаунта в нашем облаке в Yandex.Cloud. Для оперирования ресурсами в облаке нам понадобится специальный сервисный аккаунт. Чтобы создать его, переходим в консоль облака. В текущем облаке выберем рабочий каталог и перейдем в пункт меню Сервисные аккаунты. Создадим новый сервисный аккаунт serverless-slack для работы приложения и выдадим ему роли в текущем каталоге.   Для сервисного аккаунта задаем роль editor, которая позволит нам реализовать полноценно реализовать serverless-приложение. В обзоре сервисного аккаунта получаем идентификатор. Оставаясь в консоли облака переходим в дашборд текущего каталога и выбираем сервис API Gateway. Нажимаем кнопку Создать API-шлюз используем имя for-slack-bot. После публикации API-шлюза в спецификации появится секция servers со служебным доменом — при любых модификациях оставляем это поле без изменений. Этот адрес и будет точкой входа в приложение. В спецификации будут храниться все правила вызова наших serverless-функций. Возвращаемся в панель Slack, чтобы связать наше приложение с облаком. В меню Basic Information нажимаем кнопку Add features and functionality и в открывшемся поле выбираем значение Event Subscribtions. Здесь нужно проверить, готова ли точка со стороны облака принимать запросы: на post-запрос от Slack мы должны выполнять параметры атрибута  Challenge, то есть отправлять ответ в виде: В облаке создаем функцию, которая будет отвечать на Challenge. в консоли облака переходим в дашборд текущего каталога и выбираем сервис Cloud Functions. Нажимаем кнопку Создать функцию и задаем ей имя for-slack-bot-challenge. Выбираем среду выполнения python3.7. Примечательно, что каждая функция может быть реализована на своем языке программирования.  В веб-редакторе создаем файл requirements.txt, подключаем в нем библиотеки:  Меняем содержимое файла index.py, созданного по умолчанию, в консоли на содержание того же файла в моем репозитории. Указываем точку входа index.handler. Увеличиваем тайм-аут до 5 секунд. Не забываем указываем сервисный аккаунт, созданный на предыдущем шаге. После того как функция будет создана у нее появится идентификатор. Переходим в дашборд текущего каталога и выбираем сервис API Gateway. Выбираем for-slack-bot и редактируем его. Заменяем текущую спецификацию на содержимое из файла for-slack-bot.yml. При этом заменяем IDYOURFUNCTIONCHALLENGE на идентификатор созданной функции, а IDYOURACCOUNT — на идентификатор сервисного аккаунта, созданного ранее. Помним что секцию servers в спецификации ни в коем случае не меняем. После сохранения изменений в спецификации копируем значение url в секции servers  Переходим в панель Slack, выбираем наше приложение ServerlessBotApp. В секции Event Subscriptions указываем только что скопированный адрес в поле Request URL и дожидаемся появления Verified. Когда мы убедились что Slack видит наш API Gateway, настало время реализовать функциональность доступную в чате — команду.  Для начала, в панели Slack получаем token и secret. В разделе OAuth & Permissions копируем Bot User OAuth Token и в дальнейшем используем в качестве значения переменной SLACK_BOT_TOKEN. А в разделе Basic Information в подразделе App Credentials копируем Signing Secret и в дальнейшем используем его в качестве значения переменной SLACK_SIGNING_SECRET. Для любой функции, создаваемой далее обязательно задаем переменные SLACK_BOT_TOKEN и SLACK_SIGNING_SECRET помимо сервисного аккаунта. В консоли облака переходим в дашборд текущего каталога и выбираем сервис Cloud Functions. Нажимаем кнопку Создать функцию. Задаем имя for-slack-bot-hello-from-serverless. Выбираем среду выполнения python3.7.  В веб-редакторе создаем файл requirements.txt, подключаем в нем библиотеки:  Меняем содержимое файла index.py, созданного по умолчанию, в консоли на содержание того же файла в моем репозитории. Указываем точку входа index.handler. Увеличиваем тайм-аут до 5 секунд. Указываем идентификатор сервисного аккаунта и переменные SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET полученные ранее. Жмем кнопку — Создать версию и после копируем идентификатор нашей новой функции. Функция готова и работает, опубликуем ее через сервис API Gateway. Выбираем for-slack-bot и редактируем его. Вставляем секцию /hello-from-serverless со всем ее содержимым из файла for-slack-bot.yml в спецификацию. Заменяем IDYOURFUNCTIONHELLO на идентификатор созданной функции, а  IDYOURACCOUNT — на идентификатор сервисного аккаунта. Сохраняем изменения. Функция опубликована и требуется создать команду в нашем Slack-приложении. В панели Slack выбираем созданное приложение ServerlessBotApp. В секции Slash Commands нажимаем кнопку Create New Command.  В поле Command вводим /hello-from-serverless. В поле Request URL указываем адрес API Gateway, дополнив его /hello-from-serverless. Можем, но не обязаны заполнить поле Short Description. Нажимаем Save. Следуя инструкции, переустанавливаем Slack-приложение. После этого в workspace появится возможность вызвать сконфигурированную команду. Мы уже можем расширять функциональность Slack с помощью команд и реализовать выполнение функции внутри Yandex.Cloud. Но наш бот не совсем бот, он не умеет реагировать на сообщения пользователя. Исправим это. Переходим в сервис Cloud Functions. Нажимаем кнопку Создать функцию. Задаем имя for-slack-bot-small-talk. Выбираем среду выполнения python3.7. Создаем файл requirements.txt с содержимым аналогично предыдущему разу. Меняем содержимое файла index.py созданного по умолчанию, в консоли на содержание того же файла в моем репозитории. Указываем точку входа index.handler. Увеличиваем тайм-аут до 5 секунд. Указываем сервисный аккаунт и переменные SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, полученные ранее. Нажимаем кнопку Создать версию, не забываем скопировать идентификатор. Функция по умолчанию всегда создается приватная и с помощью идентификатора и части спецификации API Gateway можно сделать ее публичной. Для этого отредактируем данные в шлюзе.  В сервисе API Gateway находим шлюз for-slack-bot, отредактируем его содержание: заменим секцию / на аналогичную, содержащуюся в файле for-slack-bot.yml, только заменяем  IDYOURFUNCTIONSMALLTALK на идентификатор вашей функции. Сохраняем. Переходим на панель управления Slack выбираем  созданное приложение ServerlessBotApp. В секции Event Subscriptions передвигаем ползунок Enable Events в положение on. Указываем адрес API Gateway в поле Request URL и дожидаемся появления Verified. В секции Subscribe to bot events на той же странице нажимаем кнопку Add Bot User Event и выбираем message.im. Как только все заработает, возникнет автоматическое взаимодействие. Поток сообщений будет отправляться в API Gateway. На нашей стороне мы уже можем реализовать полноценный диалог с подключением других необходимых ресурсов. Можем расширять функциональность через подписку на определенные типы событий. Сейчас мы подписались только на один тип — получение сообщений.  Через точку доступа Slack отправляет запросы в виде POST-запросов, на стороне Yandex.Cloud вызывается функция. Запрос обрабатывается функцией и генерируется ответ.  Созданная ранее функция реагирует на сообщения пользователя ":wave:" и "knock knock". Теперь у нас уже есть практически полнофункциональный бот, но нам предстоит подключить к нашему serverless-приложению СУБД для хранения данных, для хранения состояния и другой информации. Для работы нашего serverless-приложения будем использовать СУБД Yandex Database, более подробно о ее особенностях можно почитать тут.  В консоли облака переходим в дашборд текущего каталога и выбираем сервис Yandex Database. Нажимаем кнопку Создать базу данных. Создаем базу данных с именем for-slack-bot, выбираем serverless в качестве модели. После создания БД переходим в ее содержимое, выбираем пункт Навигация и нажимаем кнопку SQL-запрос. В веб-редакторе в поле Запроса вставляем следующий текст:   После успешного выполнения запроса в нашей БД появится таблица. В разделе Навигация выберете таблицу coffee и добавьте пару строк. Одну из строк с идентификатором равному 1. Перейдите в раздел Обзор. В интерфейсе вы увидите секцию YDB эндпоинт, в ней содержатся данные для формирования необходимых переменных. Для работы функции с Yandex Database потребуется три переменные. Переменная ENDPOINT будет иметь вид grpcs://ydb.serverless.yandexcloud.net:1234, переменную DATABASE обязательно начинать с /ru-central1/..., а переменная USE_METADATA_CREDENTIALS в нашем случае выставляется равной 1. Оставаясь в рабочем каталоге выбираем сервис Cloud Functions и привычным образом создаем новую функцию с именем for-slack-bot-what-kind-of-coffee. Выбираем среду выполнения python3.7.  Создаем файл requirements.txt с содержимым аналогично предыдущему разу, но в конце добавляем еще одну библиотеку. Меняем содержимое файла index.py созданного по умолчанию, в консоли на содержание того же файла в моем репозитории. Указываем точку входа index.handler. Увеличиваем тайм-аут до 5 секунд. Указываем сервисный аккаунт и переменные SLACK_BOT_TOKEN, SLACK_SIGNING_SECRET, полученные ранее. Добавляем еще три переменные для работы с YDB: ENDPOINT, DATABASE, USE_METADATA_CREDENTIALS. Нажимаем кнопку Создать версию, не забываем скопировать идентификатор. Оставаясь в рабочем каталоге в облаке переходим в сервис API Gateway выбираем for-slack-bot и редактируем его. Вставляем секцию /what-kind-of-coffee со всем ее содержимым из файла for-slack-bot.yml. Заменяем IDYOURFUNCTIONCOFFEE на идентификатор созданной функции, а IDYOURACCOUNT — на идентификатор вашего сервисного аккаунта, созданного ранее. Сохраняем изменения. В этот момент у нас появилась опубликованная функция, способная получить данные из Yandex Database, остается вызвать ее из Slack. В панели управления Slack выбираем созданное приложение ServerlessBotApp. В секции Slash Commands нажимаем Create New Command. Кстати, название команды и запрос URL со стороны Slack всегда можно отредактировать^ что очень удобно.  В поле Command вводим /what-kind-of-coffee, в поле Request URL указываем адрес API Gateway, дополнив его /what-kind-of-coffee. Нажимаем Save. Следуя инструкции, переустанавливаем Slack-приложение. Теперь в workspace можно вызвать новую команду. Мы получили бот, с которым можно работать, расширять его возможности и прокачивать функциональность. Теперь вы можете создавать полноценные диалоги и получать данные.  Полные исходные тексты всех файлов, инструкции и видео шагов для реализации бота есть в репозитории. Первый. Когда вы создаете бота для Slack, рекомендую обратить внимание на реакцию на ввод команды. Эта реакция должна быть меньше 3 секунд. Если вы не укладываетесь в это время, Slack считает это ошибкой и начинает посылать сообщения в чат пользователю о том, что команда недоступна.  Лучше не дожидаться выполнения команды, а записать в базу данных сам факт ее вызова. Затем уже отдельной функцией обработать очередь вызовов команд, а результат вызова команды дослать позже. К тому моменту, как пользователь обратится в чат, вы сможете ему ответить полноценным диалогом.  Второй. В Yandex.Cloud есть активно растущее serverless-коммьюнити Yandex Serverless Ecosystem в Telegram, где можно задавать вопросы, возникающие в процессе создания serverless-ботов и получать ответы от единомышленников и коллег.  И последнее: сейчас действует программа free tier. Вы можете разработать свое приложение, в том числе и slack-бот, при этом сервисы тарифицироваться не будут, если вы уложитесь в лимиты программы. Podcaster & Developer Advocate