Unified requirements.txt
На настоящий момент NOC использует хранит список необходиимых модулей python в нескольких файлах в requirements/*.txt
. Установка происходит в ansible playbook, при этом каждая роль может устанавливать свои зависимости. Необходимость разбиения зависимостей на части обусловлена тем, что
ряд из них требует дополнительных внешних библиотек, которые нецелесообразно устанавливать на все ноды.
Кроме того, тестовый контейнер использует отдельный файл requirements/docker.txt
Проблема
Каноническим месторасположением внешних зависимостей считается файл requirements.txt
в корне проекта. В результате возникает несколько неприятных моментов:
- Внешние инструменты, такие как IDE и Gitlab Security Scanner не распознают файлы зависимостей, расположенных в нестандартном месте
- Тестовый контейнер вынужден использовать отдельный файл зависимостей и может отличаться от продуктива
- Иногда по недосмотру возникает рассинхронизация, когда тесты и продуктив используют разные версии пакетов
- Контринтуитивно для новых разработчиков
- Для того, чтобы понять, в каких случаях подключается какой пакет необходимо смотреть playbook, который на настоящий момент находится в отдельном репозитории и развивается самостоятельно
- Предварительный сбор пакетов становится крайне запутанным
Решение
Свести все зависимости в один requirement.txt и включать их по необходимости
Сложности
PEP-0508 определяет механизм опционального управления зависимостями - Environment Markings
.
К сожалению, количество критериев для проверки очень ограничено, отсутствуют такие очевидные решения, как анализ переменных окружения.
В итоге, в исходном виде они не пригодны для решения проблемы.
Выход
Добавить препроцессор, который обработает requirements.txt, модифицирует его и отдаст pip.
Пакеты python могут иметь опциональные зависимости (extra). К сожалению, pip install
не позволяет передать extra для самого NOC, но соответсвующий признак можно использовать в препроцессоре. Пример условного включения requirements.txt
Coverage[toml]==5.0.3; extra == "testing"
pytest==5.4.1; extra == "testing"
Вызов препроцессора:
./scripts/build/get-noc-requirements.py <role1> .. <roleN>
или
./scripts/build/get-noc-requirements.py --all
Препроцессор обрабатывает общий requirements.txt
и выдает на stdout только то, что проходит проверку. При этом отработавшие environment markings
удаляются.
Таким образом, процесс установки зависимостей упрощается до
./scripts/build/get-noc-requirements.py activator classifier | pip install -r /dev/stdin
Роли
Четко определены в комментариях в заголовке файла requirements.txt
# ----------------------------------------------------------------------
# NOC Python requirements
# Following extras can be set:
# * activator
# * dev
# * login-ldap
# * login-pam
# * login-radius
# * notifier
# * supervisor
# * prod-tools
# * testing
# * classifier
# ----------------------------------------------------------------------
Доработки deploy
- Произвести проверку наличия
requirements.txt
в корне проекта - Если файла нет, проводить установку в старом порядке
- Если файл есть, то проводить установку зависимостей только в роли
node
, сформировав полный список вспомогательных ролей