- 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
149 lines
7.5 KiB
Markdown
149 lines
7.5 KiB
Markdown
# 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` со скриптом.
|