Сервис feature-флагов

6 окт. 2021 г.

Всем привет! Сегодня хотел бы рассказать о создании простого сервиса для управления feature-флагами. Feature-флаги позволяют мгновенно включать и выключать определенный функционал в приложении. Для этого не требуется заново выкладывать или откатывать его. Достаточно включить или выключить определенный флаг. В то же время, в ключевых местах в коде добавляются проверки флагов.

К примеру, нужно добавить на сайт форму обратной связи. И в то же время нужно иметь возможность быстро откатить изменения. Для этого можно создать feature-флаг contact-form и проверять его при выводе формы и обработчика.

Имеющиеся сервисы

Существует множество сервисов, которые в том или ином виде реализуют концепцию feature-флагов. Вот несколько примеров:

Среди них есть платные, условно или полностью бесплатные. Проприетарные и opensource. Saas и self-hosted. Кроме управления флагами, такие сервисы могут поддерживать дополнительный функционал, например A/B тестирование.

Свой сервис, self-hosted

Для использования в собственных проектах решил создать свой простой сервис управления feature-флагами. Использование своего сервиса имеет некоторые преимущества:

  • Бесплатно, нет искусственных ограничений. Можно добавлять любое количество флагов.
  • Настраиваемо. Можно реализовать собственную логику, если это необходимо.
  • Просто. Сервис выполняет одну конкретную задачу.
  • Нет зависимости от стороннего сервиса.
  • Можно использовать локально без интернета, в закрытой корпоративной сети и т.д.

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

Структура

Основные сущности - Project(проект), Environment(окружение), Feature(функциональность).

База данных имеет такую структуру:

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

Environment соответствует окружению в котором работает приложение, например prod, dev, staging.

Feature соответствует определенному функционалу. Например, post_comments - для включения комментариев, contact_form - для включения формы обратной связи. Feature-флаг может быть включен или выключен для конкретного окружения. Например, новый функционал сначала нужно протестировать на staging окружении, и только после этого можно включить на production.

Виды доступов

Сервис имеет несколько уровней доступа:

  • Root - позволяет управлять проектами. Создавать, просматривать, редактировать и удалять.
  • Manage - позволяет управлять конкретным проектом. Создавать окружения и feature, менять значения.
  • Read - позволяет только читать значения feature-флагов.

Клиент

Обращаться к сервису можно с помощью Curl, Guzzle или любого другого HTTP клиента. Есть пример реализации клиента для Symfony приложения и unit тест.

Примеры использования, документация

Сервис доступен на github и может быть запущен локально или на собственном сервере. Запуск проекта описан в README.

Также доступно demo. Для ознакомления с возможностями сервиса можно использовать тестовый проект:

{
  "name": "demo",
  "owner": "antonshell",
  "read_key": "demo_read_key",
  "manage_key": "demo_manage_key"
}

Взаимодействие с сервисом осуществляется через API. Структура API описана в Swagger.

Для создания проекта нужно выполнить такой запрос. Root token задается в переменной окружения ROOT_TOKEN. Вместе с проектом создаются 3 окружения: prod, stage, dev. Также создается demo-feature.

curl --request POST \
  --url https://feature-flags.antonshell.me/manage/project \
  --header 'Authorization: bearer root_token' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "project1",
    "description": "project1",
    "owner": "antonshell"
}'

Создание дополнительного окружения:

curl --request POST \
  --url https://feature-flags.antonshell.me/api/environment \
  --header 'Authorization: bearer demo_manage_key' \
  --header 'Project: antonshell/demo' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "qa1",
    "description": "QA1"
}'

Создание feature:

curl --request POST \
  --url https://feature-flags.antonshell.me/api/feature \
  --header 'Authorization: bearer demo_manage_key' \
  --header 'Project: antonshell/demo' \
  --header 'Content-Type: application/json' \
  --data '{
    "name": "feature4",
    "description": "Feature 4"
}'

Включение/выключение feature для определенного окружения:

curl --request POST \
  --url https://feature-flags.antonshell.me/api/feature/feature4/value \
  --header 'Authorization: bearer demo_manage_key' \
  --header 'Project: antonshell/demo' \
  --header 'Content-Type: application/json' \
  --data '{
    "enabled": false,
    "environment": "prod"
}'

Получение значения feature для определенного окружения:

curl --request GET \
  --url https://feature-flags.antonshell.me/feature/antonshell/demo/feature1/prod \
  --header 'Authorization: bearer demo_read_key'

Итоги

В результате получаем простой сервис для управления feature-флагами, который можно развернуть на собственном сервере. Поддерживается разделение feature на проекты и окружения.

Код сервиса доступен на github. Также есть demo. Если возникло желание использовать сервис на моем сервере, пожалуйста, напишите мне в Telegram.

На этом пока все. Спасибо за внимание!

Теги: Mysql, Symfony, PHP, PHPUnit