Files
ss-tools/examples/maintenance/README.md
busya 4bc244c228 fix(examples): maintenance API scripts — error handling, JSON safety, docs
- bash: propagate api_call failures (exit 1 on 400/401/403/404/network),
  write diagnostics to stderr, escape message for JSON safety, help without
  API key
- python: argparse options after subcommand (parents), single error message
  per failure, network errors without traceback, idempotent already_completed
- move scripts to examples/maintenance/ with README instructions
- backend: correct stale envelope-shape comment in maintenance schemas
2026-08-10 12:04:50 +03:00

149 lines
7.5 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Maintenance API — примеры интеграции
Примеры внешних вызовов API обслуживания (баннеры «ведутся технические работы»
на дашбордах Superset) из скриптов: CI/CD, cron, Airflow DAG, ad-hoc отладка.
## Содержимое
| Файл | Назначение |
|---|---|
| `maintenance-api-bash.sh` | Пример на bash (curl) — для shell-окружений без Python |
| `maintenance-api-python.py` | Пример на Python (requests) — для ETL-пайплайнов |
## Возможности
- **start** — создать событие обслуживания для таблиц (1..100) с окном
начала/окончания, сообщением баннера и опциональным авто-завершением
(`--auto-end` / `auto_end=true`);
- **end** — завершить конкретное событие (снять баннеры);
- **end-all** — аварийно завершить ВСЕ активные события в окружении.
## API — кратко
- Базовый URL: `{BASE_URL}/api/maintenance`
- Аутентификация: заголовок `X-API-Key: <API_KEY>` (или JWT)
- Разрешения ключа: `maintenance:start`, `maintenance:end`, `maintenance:end_all`
- Все мутационные эндпоинты возвращают **HTTP 202** и `task_id` — операция
выполняется асинхронно через TaskManager.
- Ответы — сырые тела схем (без обёртки), например:
`{ "task_id": "...", "maintenance_id": "...", "status": "pending" }`.
### Эндпоинты
| Метод | Путь | Разрешение | Описание |
|---|---|---|---|
| POST | `/api/maintenance/start` | `maintenance:start` | Создать событие (202) |
| POST | `/api/maintenance/{id}/end` | `maintenance:end` | Завершить событие (202) |
| POST | `/api/maintenance/end-all` | `maintenance:end_all` | Завершить все (202) |
| GET | `/api/maintenance/events` | `maintenance` READ | Активные/завершённые события |
| GET | `/api/maintenance/dashboard-banners` | `maintenance` READ | Баннеры по дашбордам |
| POST | `/api/maintenance/preview-dashboards` | `maintenance` READ | Какие дашборды затронуты |
| GET/PUT | `/api/maintenance/settings` | READ / admin | Настройки обслуживания |
### Параметры `start`
```json
{
"tables": ["public.messages", "public.users"],
"start_time": "2026-08-10T08:00:00Z",
"end_time": "2026-08-10T12:00:00Z",
"environment_id": "ss-dev",
"auto_end": false,
"message": "Плановое обновление данных"
}
```
- `tables` — обязателен (1..100); `start_time`, `environment_id` — обязательны.
- `auto_end` — по умолчанию `false`; если `true` и задан `end_time`,
планировщик сам завершит обслуживание ровно в `end_time`. **Без `auto_end`
событие останется активным до ручного завершения командой `end`.**
- Ошибки: `400` (невалидные данные, `end_time <= start_time`, >100 таблиц),
`401`, `403`, `404` (неизвестное окружение), `409` — идемпотентность
(`status: "already_active"` — такое же окно уже активно).
- `end` идемпотентен: повторное завершение уже завершённого события даёт
`202` с `status: "already_completed"` (считается успехом).
## Использование
### Требования
- **bash**: `curl`, желательно `jq` (форматирование ответов; без него вывод
остаётся сырым JSON).
- **python**: Python 3.10+, `requests` (`pip install requests`).
### Подготовка
1. Создайте API-ключ в superset-tools с разрешениями
`maintenance:start` / `maintenance:end` / `maintenance:end_all`.
2. Задайте переменные окружения (bash) или флаги `--base-url` / `--api-key`
(python).
### Bash
```bash
export SS_TOOLS_URL=http://localhost:8000
export SS_TOOLS_API_KEY=ssk_ваш_ключ
# Обслуживание на 4 часа (без авто-завершения)
./maintenance-api-bash.sh start public.messages 4 ss-dev
# Несколько таблиц, сообщение, автоснятие баннера через 4 часа
./maintenance-api-bash.sh start public.messages,public.users 4 ss-prod \
"Плановый ETL" --auto-end
# Завершить конкретное событие
./maintenance-api-bash.sh end m-abc123
# Аварийно снять ВСЕ баннеры в окружении ss-dev
./maintenance-api-bash.sh end-all ss-dev
```
Выходные коды: `0` — успех; `1` — ошибка (данные, права, ключ, недоступность
сервера). `end-all` в интерактивном режиме запрашивает подтверждение; в
неинтерактивных окружениях (cron/CI) подтверждение пропускается.
### Python
```bash
# Старт (аргументы можно указывать и после подкоманды)
python maintenance-api-python.py start \
--api-key ssk_ваш_ключ \
--base-url https://superset-tools.example.com \
--tables public.messages,public.users \
--environment ss-dev --duration-hours 4 \
--message "Плановый ETL" --auto-end
# Завершить конкретное событие
python maintenance-api-python.py end \
--api-key ssk_ваш_ключ \
--base-url https://superset-tools.example.com \
--event-id m-abc123
# Аварийно завершить всё в окружении
python maintenance-api-python.py end-all \
--api-key ssk_ваш_ключ \
--base-url https://superset-tools.example.com \
--environment ss-dev
```
Функции `start_maintenance` / `end_maintenance` / `end_all_maintenance` можно
импортировать напрямую в свой ETL-пайплайн.
## Безопасность
- **Не передавайте API-ключ аргументами командной строки** (попадает в историю
shell/ps) — используйте переменные окружения или защищённые секреты
(CI/CD secrets, vault).
- Ключ с ограниченным окружением может работать только с этим окружением —
выберите правильный `environment_id`.
- `end-all` снимает баннеры со всех дашбордов — применяйте только в аварийных
сценариях.
## Примеры автоматизации
- **cron** (снятие баннера ровно в конце окна через `auto_end` не нужно —
планировщик сам завершит; `end` пригодится для досрочного завершения).
- **CI/CD pipeline**: после деплоя ETL — `start`; по завершении джобы — `end`.
- **Airflow DAG**: Python-функции из `maintenance-api-python.py` в
`PythonOperator` либо `BashOperator` со скриптом.