All checks were successful
CI Trade-In / backend-tests (pull_request) Has been skipped
CI Trade-In / browser-tests (pull_request) Has been skipped
CI / changes (pull_request) Successful in 12s
CI / frontend-tests (pull_request) Has been skipped
CI Trade-In / changes (pull_request) Successful in 10s
CI Trade-In / frontend-checks (pull_request) Has been skipped
CI / openapi-codegen-check (pull_request) Successful in 2m2s
CI / backend-tests (pull_request) Successful in 17m21s
Стек наблюдаемости не поднялся ни на одном хосте после мержа #3099: джоба server упала, agent-apps и agent-infra пропустились как зависимые. Причина (задача 23657, 26.08 08:55): err: ОШИБКА: не нашёл роль с правом CREATE ROLE в gendesign-infra-postgres setup-metrics-grafana-role.sh искал привилегированную роль перебором трёх имён - glitchtip, forgejo, postgres. Ни одно не совпадает ни с одним реальным кластером проекта: infra-postgres -> infra, gendesign-postgres-1 -> gendesign, tradein-postgres -> tradein. Комментарий над перебором сам предупреждал, что "угадывать postgres неверно", и дальше шло угадывание. Замер на живом контейнере 26.08 (read-only, ничего не создавалось): POSTGRES_USER изнутри контейнера: infra glitchtip - отказ, forgejo - отказ, postgres - отказ, infra - 1 Стало: имя берём из POSTGRES_USER самого контейнера - это та переменная, которой роль и создана при initdb, то есть источник истины. Прежний список оставлен ПОСЛЕ него запасным путём для кластера не из образа postgres. Попутно - глоб в paths деплоя. Воркфлоу запускает ТРИ setup-скрипта, а в триггере стоял только setup-metrics-secrets.sh: правка двух остальных не заводила выкат, и на хосте молча оставалась старая версия. Тот же класс, что #2203 закрыл глобом ops/*.sh. Добавлен тест, который сверяет запускаемые скрипты с шаблонами paths - на исходном воркфлоу он краснеет, указывая на setup-metrics-exporter-dsn.sh. Тесты (6) исполняют РЕАЛЬНЫЙ скрипт с подставным docker и проверяют фактический выбор роли, а не наличие правильных слов в комментарии. Фальсификация: на исходном коде краснеют 3 из 5 ролевых тестов; проходят только те два, что фиксируют сохранённое поведение (запасной перебор и громкая ошибка при отсутствии привилегий). tests/ops целиком - 28 passed.
95 lines
5.2 KiB
Bash
95 lines
5.2 KiB
Bash
#!/usr/bin/env bash
|
||
# Заводит read-only роль grafana_ro в базе glitchtip — под датасорс Grafana.
|
||
# Идемпотентен: повторный запуск только досогласует права.
|
||
#
|
||
# ПОЧЕМУ ОТДЕЛЬНАЯ РОЛЬ, А НЕ ВЛАДЕЛЕЦ БАЗЫ. Датасорс Grafana доступен всякому,
|
||
# кто вошёл в интерфейс, и позволяет выполнять произвольный SQL в панелях.
|
||
# Владельческая роль сделала бы витрину способом уронить трекер ошибок. Здесь
|
||
# прав на запись нет вовсе, поэтому худшее, что можно сделать через панель, —
|
||
# медленный SELECT.
|
||
#
|
||
# Запускать на инфраструктурном хосте. Вызывается из deploy-metrics.yml.
|
||
set -euo pipefail
|
||
|
||
CONT=gendesign-infra-postgres
|
||
DB=glitchtip
|
||
ROLE=grafana_ro
|
||
|
||
: "${GLITCHTIP_RO_PASSWORD:?GLITCHTIP_RO_PASSWORD не задан — запусти scripts/setup-metrics-secrets.sh}"
|
||
|
||
if ! docker inspect "$CONT" >/dev/null 2>&1; then
|
||
echo " $CONT не найден — пропускаю создание роли."
|
||
exit 0
|
||
fi
|
||
|
||
# Ищем роль с правом заводить других. Имя суперпользователя в этом кластере
|
||
# нигде не зафиксировано, а угадывать «postgres» неверно: в образе оно задаётся
|
||
# переменной POSTGRES_USER и здесь ею не является.
|
||
#
|
||
# Поэтому НЕ угадываем, а спрашиваем сам контейнер: POSTGRES_USER — это та самая
|
||
# переменная, которой роль и была создана при initdb, то есть источник истины.
|
||
# Прежний список был перебором трёх имён (glitchtip/forgejo/postgres), и ни одно
|
||
# из них не совпадало ни с одним реальным кластером проекта:
|
||
#
|
||
# gendesign-infra-postgres → infra
|
||
# gendesign-postgres-1 → gendesign
|
||
# tradein-postgres → tradein
|
||
#
|
||
# Из-за этого деплой стека падал на первом же прогоне (#3099, задача 23657):
|
||
# ОШИБКА: не нашёл роль с правом CREATE ROLE в gendesign-infra-postgres
|
||
# Замер 26.08 на живом контейнере: glitchtip/forgejo/postgres — отказ,
|
||
# infra — проходит. Список имён оставлен ПОСЛЕ него запасным путём: он
|
||
# пригодится кластеру, поднятому не из образа postgres, где POSTGRES_USER пуст.
|
||
SUPER=""
|
||
_pg_user="$(docker exec "$CONT" sh -c 'printf %s "${POSTGRES_USER:-}"' 2>/dev/null || true)"
|
||
for candidate in $_pg_user glitchtip forgejo postgres; do
|
||
[ -n "$candidate" ] || continue
|
||
if docker exec "$CONT" psql -U "$candidate" -d postgres -tAc \
|
||
"SELECT 1 FROM pg_roles WHERE rolname = CURRENT_USER AND (rolsuper OR rolcreaterole)" 2>/dev/null \
|
||
| grep -q 1; then
|
||
SUPER="$candidate"
|
||
break
|
||
fi
|
||
done
|
||
|
||
if [ -z "$SUPER" ]; then
|
||
echo " ОШИБКА: не нашёл роль с правом CREATE ROLE в $CONT." >&2
|
||
echo " Проверь вручную: docker exec $CONT psql -U <роль> -c '\\du'" >&2
|
||
exit 1
|
||
fi
|
||
echo " привилегированная роль: $SUPER"
|
||
|
||
# Пароль передаётся через переменную окружения psql, а не в тексте запроса —
|
||
# иначе он осел бы в pg_stat_statements и в логе запросов.
|
||
docker exec -e RO_PASS="$GLITCHTIP_RO_PASSWORD" -i "$CONT" \
|
||
psql -U "$SUPER" -d "$DB" -v ON_ERROR_STOP=1 <<'SQL'
|
||
\set ro_pass `echo "$RO_PASS"`
|
||
|
||
DO $$
|
||
BEGIN
|
||
IF NOT EXISTS (SELECT 1 FROM pg_roles WHERE rolname = 'grafana_ro') THEN
|
||
CREATE ROLE grafana_ro LOGIN;
|
||
RAISE NOTICE 'роль grafana_ro создана';
|
||
ELSE
|
||
RAISE NOTICE 'роль grafana_ro уже есть';
|
||
END IF;
|
||
END
|
||
$$;
|
||
|
||
ALTER ROLE grafana_ro WITH PASSWORD :'ro_pass';
|
||
|
||
-- Ограничение на число соединений: панель с автообновлением способна открыть
|
||
-- их десятками, а это тот же кластер, где живёт Forgejo.
|
||
ALTER ROLE grafana_ro CONNECTION LIMIT 8;
|
||
|
||
GRANT CONNECT ON DATABASE glitchtip TO grafana_ro;
|
||
GRANT USAGE ON SCHEMA public TO grafana_ro;
|
||
GRANT SELECT ON ALL TABLES IN SCHEMA public TO grafana_ro;
|
||
|
||
-- Таблицы событий партиционированы по неделям: новые партиции появляются сами,
|
||
-- и без этой строки датасорс начал бы отдавать пустоту на свежих данных,
|
||
-- оставаясь при этом «рабочим». Тихий отказ ровно того сорта, который мы ловим.
|
||
ALTER DEFAULT PRIVILEGES IN SCHEMA public GRANT SELECT ON TABLES TO grafana_ro;
|
||
SQL
|
||
|
||
echo " grafana_ro: права выданы на $DB"
|