refactor(smoke): цели проверки по назначению — смоук, ClickHouse, службы
- Зачем:
- смоук перестал быть быстрым: 42 секунды из 48 съедали шесть проверок,
которые ждут службу — запуск DAG, вход в Superset, Kafka с машины.
- имена целей врали: смоуком звались и глубокая проверка кластера, и
интеграционные проверки; префикс достался им от общего происхождения.
- нигде не было записано, зачем в репозитории каждая цель и куда класть
новую проверку, — без записи скрипт дорастёт снова.
- Что:
- ось деления — кого спрашивают, а не сколько стоит: make smoke (стенд
собран), make check-clickhouse (спрашивают у ClickHouse), новая
make check-services (службы работают).
- шесть тяжёлых проверок переехали в scripts/stand-services.sh; общее —
счёт, обращение к Compose, зависимости машины и check_containers_survived
— вынесено в scripts/stand-common.sh, копипасты нет.
- smoke-cluster переименована в check-clickhouse; имя файла скрипта не
тронуто (в него встраивается проверка договора со схемой), расхождение
названо в карте.
- смоук и check-services печатают своё время в строке ИТОГ; порога по
времени нет — по доводу ADR 0004.
- docs/architecture/testing.md: карта всех семи целей, правило быстрого
смоука словами, лесенка по частоте и правило про краснеющую проверку,
переехавшее из README; указатель из AGENTS.md.
- README: описания целей сокращены, карта не дублируется; быстрый старт
показывает работающий стенд, а не только собранный.
- планка приёмки этапа в спеке названа поимённо: три цели вместо
«smoke-проверки».
- Проверка:
- make config-test, make smoke (19 проверок, 6 с), make check-clickhouse
(8 проверок, 7 с), make check-services (7 проверок, 44 с) — зелёные.
- 19 + 7 = 25 разных проверок, как и до деления: check_containers_survived
считается дважды намеренно.
- краснеют обе разделённые цели: со снятым prometheus смоук дал три ошибки,
с подменённым UUID подключения Superset покраснел check-services.
Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,108 @@
|
||||
#!/usr/bin/env bash
|
||||
# Общая часть проверок на поднятом стенде: счёт проверок, обращение к Compose,
|
||||
# зависимости машины и вопрос Docker, пережили ли контейнеры прогон. Файл не
|
||||
# запускается сам — его подключают через source из stand-smoke.sh и
|
||||
# stand-services.sh.
|
||||
|
||||
readonly ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
|
||||
read -r -a COMPOSE_CMD <<<"${COMPOSE_BIN:-docker compose}"
|
||||
readonly -a LONG_LIVED_SERVICES=(
|
||||
clickhouse-keeper clickhouse-01 clickhouse-02 kafka postgres-metadata
|
||||
airflow-apiserver airflow-scheduler airflow-dag-processor
|
||||
superset prometheus grafana
|
||||
)
|
||||
|
||||
passed=0
|
||||
failed=0
|
||||
|
||||
compose() {
|
||||
"${COMPOSE_CMD[@]}" --project-directory "$ROOT_DIR" "$@"
|
||||
}
|
||||
|
||||
pass() {
|
||||
passed=$((passed + 1))
|
||||
printf 'ЗЕЛЁНО: %s.\n' "$1"
|
||||
}
|
||||
|
||||
fail() {
|
||||
failed=$((failed + 1))
|
||||
printf 'ОШИБКА: %s.\n' "$1" >&2
|
||||
}
|
||||
|
||||
published_port() {
|
||||
local binding
|
||||
local service="$1"
|
||||
local container_port="$2"
|
||||
binding="$(compose port "$service" "$container_port" 2>/dev/null || true)"
|
||||
printf '%s\n' "${binding##*:}"
|
||||
}
|
||||
|
||||
# Отвечает, есть ли на машине всё, без чего проверкам не с чем работать.
|
||||
# Засчитывать ли этот ответ проверкой, решает вызывающий: смоук печатает за него
|
||||
# ЗЕЛЁНО, потому что вопрос к машине стоит рядом с «стенд собран»; для
|
||||
# check-services это условие запуска, и своего ЗЕЛЁНО у него там нет.
|
||||
require_host_dependencies() {
|
||||
local command
|
||||
local -a missing=()
|
||||
|
||||
for command in docker curl jq awk grep sed tail sleep timeout; do
|
||||
command -v "$command" >/dev/null 2>&1 || missing+=("$command")
|
||||
done
|
||||
if [[ "${#missing[@]}" -gt 0 ]]; then
|
||||
fail "на машине не хватает команд: ${missing[*]}"
|
||||
return 1
|
||||
fi
|
||||
if ! docker compose version >/dev/null 2>&1; then
|
||||
fail 'Docker Compose недоступен; установите модуль compose для Docker'
|
||||
return 1
|
||||
fi
|
||||
if ! docker info >/dev/null 2>&1; then
|
||||
fail 'Docker недоступен; запустите Docker и проверьте доступ к его сокету'
|
||||
return 1
|
||||
fi
|
||||
return 0
|
||||
}
|
||||
|
||||
# Убитый за память контейнер Docker поднимает сам, и проверка здоровья об этом
|
||||
# промолчит. Порога здесь нет: это «да или нет», а не бюджет памяти (ADR 0004).
|
||||
# Проверка стоит в конце обеих целей: нагружает стенд check-services, а увидеть
|
||||
# последствия нужно и тому, кто гонял один смоук.
|
||||
check_containers_survived() {
|
||||
local container_id
|
||||
local service
|
||||
local state
|
||||
local problems=0
|
||||
|
||||
for service in "${LONG_LIVED_SERVICES[@]}"; do
|
||||
container_id="$(compose ps --all --quiet "$service" 2>/dev/null || true)"
|
||||
if [[ -z "$container_id" || "$container_id" == *$'\n'* ]]; then
|
||||
fail "не удалось получить контейнер ${service} для проверки перезапусков"
|
||||
return
|
||||
fi
|
||||
state="$(docker inspect --format '{{.State.OOMKilled}}/{{.RestartCount}}' "$container_id" 2>/dev/null || true)"
|
||||
case "$state" in
|
||||
false/0) ;;
|
||||
# OOMKilled встаёт и когда убит процесс внутри живого контейнера.
|
||||
true/*)
|
||||
fail "в контейнере ${service} ядро убило процесс из-за нехватки памяти"
|
||||
problems=$((problems + 1))
|
||||
;;
|
||||
false/*)
|
||||
fail "контейнер ${service} перезапускался, счётчик Docker — ${state#*/}"
|
||||
problems=$((problems + 1))
|
||||
;;
|
||||
*)
|
||||
fail "Docker не рассказал о состоянии контейнера ${service}"
|
||||
problems=$((problems + 1))
|
||||
;;
|
||||
esac
|
||||
done
|
||||
if [[ "$problems" -eq 0 ]]; then
|
||||
pass 'ни в одном долгоживущем контейнере ядро не убивало процессы за память, и никто не перезапускался сам'
|
||||
fi
|
||||
}
|
||||
|
||||
# Время печатается как замер, а не как порог: смотрит на него человек.
|
||||
print_total() {
|
||||
printf 'ИТОГ: пройдено %d, ошибок %d, время %d с\n' "$passed" "$failed" "$SECONDS"
|
||||
}
|
||||
Reference in New Issue
Block a user