Концепции
Это несущие решения в дизайне enodia. Понимание их объясняет многое в поведении инструмента, что иначе выглядело бы произвольным.
Две фазы, намеренно разделяемые
Заголовок раздела «Две фазы, намеренно разделяемые»Сбор данных общается с вашими сервисами. Оценка общается с интернетом (календари жизненного цикла вендоров). В реальной инфраструктуре часто ничто не имеет сетевого доступа сразу к обоим.
collect → inventory.jsonl → evaluate → assessment → render# внутри закрытого контура - интернет не нуженenodia collect --config config.yaml -o inventory.jsonl
# где угодно ещё - доступ к вашим сервисам не нуженenodia check --from inventory.jsonlenodia check без --from — это те же две фазы, объединённые в одном
процессе, а не второй путь в коде: инвентарь, полученный по пути, —
полноценный артефакт (со своей схемой и версией), а не промежуточное
значение в памяти.
Три независимые оси, а не один статус
Заголовок раздела «Три независимые оси, а не один статус»Ветка может быть полностью здоровой, даже если уже вышла более новая мажорная версия — Confluence 10 LTS одновременно актуальна в рамках своей ветки, активно поддерживается, и при этом вышла более новая мажорная версия. Схлопывание этого в один статус выбрасывает именно ту информацию, ради которой всё затевалось.
| Ось | Значения |
|---|---|
| Патч | current · behind · ahead · unknown |
| Жизненный цикл | active · security · eol · unknown |
| Более новая ветка | latest · newer · newer_lts · unknown |
ahead — не экзотика: релиз-кандидаты и лаг между анонсом вендора и
страницей загрузки порождают его регулярно.
Факты и суждение разделены
Заголовок раздела «Факты и суждение разделены»Observation хранит то, что реально было увидено: строку версии,
достижим ли таргет, какая ошибка (если есть) произошла. Assessment
хранит то, что об этих фактах думает политика enodia — severity,
вычисленный поверх, по политике, которую контролируете вы.
Экспорт --format json отдаёт факты. Потребитель с другими приоритетами
может применить поверх свою собственную политику вместо политики enodia.
Зашейте severity прямо в observation — и это стало бы невозможным.
Время — параметр
Заголовок раздела «Время — параметр»Оценка принимает явную временную метку asOf — ничто в пути оценки не
обращается к системным часам напрямую. check --from берёт asOf из
собственного заголовка инвентаря (collectedAt), поэтому месячной
давности инвентарь оценивается на момент своего сбора, а не незаметно
пересуживается относительно сегодняшнего дня. Повторный запуск той же
оценки позже даёт тот же результат.
Пробы вкомпилированы, а не YAML DSL
Заголовок раздела «Пробы вкомпилированы, а не YAML DSL»API каждого вендора отличается настолько, что декларативный язык проб
выглядит достаточно общим ровно до первого вендора за пределами того
набора, под который он был подогнан. Каждая проба — один файл на Go с
одной явной записью в реестре: знание о вендоре, зашитое в код, значит,
что if — это просто if, читаемый и отлаживаемый, а не условие,
переизобретённое в YAML.
Это значит, что добавление нового продукта требует релиза, а не просто
правки вашего собственного конфига. Аварийный выход:
product: generic принимает спецификацию парсера (json / xml /
header / plaintext / regex) прямо из вашего конфига — для
внутренних систем, которые никогда не получат отдельную пробу, см.
Конфигурацию. Словарь generic-пробы
намеренно заморожен: ни условий, ни циклов, ни цепочек запросов.
Таргету, которому нужно что-то из этого, нужна настоящая проба, написанная
на Go.
Сначала HTTPS, credentials никогда не уходят в открытом виде по умолчанию
Заголовок раздела «Сначала HTTPS, credentials никогда не уходят в открытом виде по умолчанию»Резолюция схемы для таргета без явного https:///http:// в адресе:
сначала пробуется https, затем — http, с предупреждением в обоих
случаях. enodia никогда не пробует http первым — первый же запрос уже
понёс бы credential в открытом виде, и последующий редирект на https
этого бы не отменил. http://-таргет с прикреплёнными credentials —
жёсткая ошибка, если для этого конкретного сервиса явно не выставлен
allow_insecure_transport: true.
Никакого встроенного веб-сервера, опрашивающего по запросу
Заголовок раздела «Никакого встроенного веб-сервера, опрашивающего по запросу»И enodia serve, и export --format html показывают последний
готовый снимок — ни один из них никогда не запускает новый сбор данных
в ответ на запрос. Кнопка обновления, опрашивающая весь ваш флот на
каждый клик, — это самостоятельная DoS-атака на собственный продакшен.
Сбор идёт по расписанию (serve --interval, либо cron/systemd-таймер,
пересобирающий HTML-экспорт); HTTP лишь читает то, что произвёл
последний успешный цикл.