- /swagger — Swagger UI (CDN, без pip-зависимостей) - /api/v1/svc/openapi.json — динамическая OpenAPI 3.1.0 спека - Nubes-брендированный topbar (лого + версия) - Bearer-токен предзаполняется автоматически - 17 эндпоинтов с полными схемами, примерами, описаниями - Ссылка «Swagger» на главной странице
176 lines
9.0 KiB
HTML
176 lines
9.0 KiB
HTML
<!DOCTYPE html>
|
|
<html lang="ru">
|
|
<head>
|
|
<meta charset="utf-8">
|
|
<meta name="viewport" content="width=device-width, initial-scale=1">
|
|
<title>Polygon — Mock Nubes API</title>
|
|
<link rel="icon" type="image/svg+xml" href="{{ url_for('static', filename='favicon.svg') }}">
|
|
<link rel="stylesheet" href="{{ url_for('static', filename='style.css') }}">
|
|
</head>
|
|
<body>
|
|
|
|
<!-- ── Header ── -->
|
|
<header class="header">
|
|
<div class="header-top">
|
|
<img src="{{ url_for('static', filename='logo.svg') }}" alt="Nubes" class="logo" width="150" height="33">
|
|
<span class="badge badge-blue">polygon v{{ version }}</span>
|
|
<a href="/swagger" class="swagger-link">📋 Swagger</a>
|
|
</div>
|
|
<div class="header-status">
|
|
<span class="dot dot-green"></span>
|
|
<span class="status-text">Работает</span>
|
|
<span class="sep">·</span>
|
|
<span>Сервисов: <strong>{{ svc_count }}</strong></span>
|
|
<span class="sep">·</span>
|
|
<span>Инстансов: <strong>{{ inst_count }}</strong></span>
|
|
<span class="sep">·</span>
|
|
<span>Задержка: <strong>{{ delay }}s</strong></span>
|
|
</div>
|
|
</header>
|
|
|
|
<main>
|
|
|
|
<!-- ── Что такое Polygon ── -->
|
|
<section class="card">
|
|
<div class="card-header">
|
|
<h2>Что такое Polygon?</h2>
|
|
</div>
|
|
<div class="card-body">
|
|
<p>
|
|
<strong>Polygon</strong> — это эмулятор REST API облачной платформы
|
|
<strong>Nubes</strong> для интеграционных тестов.
|
|
Он полностью повторяет контракты реального API: сервисы, инстансы,
|
|
операции, параметры, валидацию — но работает <strong>без реальной
|
|
инфраструктуры</strong>, в памяти, с мгновенным откликом.
|
|
</p>
|
|
<div class="grid-2col">
|
|
<div>
|
|
<h3 class="h4">Зачем нужен</h3>
|
|
<ul>
|
|
<li>Тестировать создание/изменение/удаление инстансов без реальных ресурсов</li>
|
|
<li>Отлаживать UI автодеплоя (<code>app-autotest</code>) на мок-данных</li>
|
|
<li>Писать интеграционные тесты с детерминированным состоянием</li>
|
|
<li>Проверять краевые случаи (ошибки валидации, сбои операций)</li>
|
|
</ul>
|
|
</div>
|
|
<div>
|
|
<h3 class="h4">Как устроен</h3>
|
|
<ul>
|
|
<li>Flask 3.0 + gunicorn, 1 воркер (состояние в памяти)</li>
|
|
<li>Конфигурация сервисов — из YAML (генерируется из STANDS)</li>
|
|
<li>Все операции — синхронные, с настраиваемой задержкой</li>
|
|
<li>Управляемый сброс состояния через <code>/_mock/reset</code></li>
|
|
</ul>
|
|
</div>
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── Как использовать ── -->
|
|
<section class="card">
|
|
<div class="card-header">
|
|
<h2>Как использовать</h2>
|
|
</div>
|
|
<div class="card-body">
|
|
<h3 class="h4">1. Получить список сервисов</h3>
|
|
<pre class="code-block"><code>curl -s {{ endpoint }}/api/v1/svc/services | python3 -m json.tool</code></pre>
|
|
|
|
<h3 class="h4">2. Создать инстанс</h3>
|
|
<pre class="code-block"><code>curl -s -X POST {{ endpoint }}/api/v1/svc/instances \
|
|
-H "Content-Type: application/json" \
|
|
-d '{"serviceId": "s3", "displayName": "my-bucket"}' | python3 -m json.tool</code></pre>
|
|
|
|
<h3 class="h4">3. Заполнить параметры и запустить операцию</h3>
|
|
<pre class="code-block"><code># Установить параметры операции
|
|
curl -s -X POST {{ endpoint }}/api/v1/svc/instanceOperationCfsParams/<opUid>
|
|
|
|
# Запустить операцию (create/modify/delete)
|
|
curl -s -X POST {{ endpoint }}/api/v1/svc/instanceOperations/<opUid>/run</code></pre>
|
|
|
|
<h3 class="h4">4. Сбросить состояние</h3>
|
|
<pre class="code-block"><code>curl -s -X POST {{ endpoint }}/api/v1/svc/_mock/reset</code></pre>
|
|
|
|
<div class="note">
|
|
<strong>Подсказка:</strong> используйте переменную окружения
|
|
<code>POLYGON_ENDPOINT={{ endpoint }}</code>
|
|
в <code>app-autotest</code> — и все операции пойдут через полигон
|
|
вместо реального API.
|
|
</div>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── API ── -->
|
|
<section class="card">
|
|
<div class="card-header">
|
|
<h2>API эндпоинты</h2>
|
|
</div>
|
|
<div class="card-body table-wrap">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>Метод</th>
|
|
<th>Путь</th>
|
|
<th>Описание</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/health</code></td><td>Healthcheck</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/services</code></td><td>Список сервисов</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/services/<id></code></td><td>Детали сервиса</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/instances</code></td><td>Список инстансов</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/instances/<uid></code></td><td>Детали инстанса</td></tr>
|
|
<tr><td><span class="method method-post">POST</span></td><td><code>/api/v1/svc/instances</code></td><td>Создать инстанс</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/instanceOperations</code></td><td>Список операций</td></tr>
|
|
<tr><td><span class="method method-post">POST</span></td><td><code>/api/v1/svc/instanceOperations/<uid>/run</code></td><td>Запустить операцию</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/instanceOperations/<uid>/status</code></td><td>Статус операции</td></tr>
|
|
<tr><td><span class="method method-post">POST</span></td><td><code>/api/v1/svc/_mock/reset</code></td><td>Сброс состояния</td></tr>
|
|
<tr><td><span class="method method-get">GET</span></td><td><code>/api/v1/svc/_mock/state</code></td><td>Дамп состояния</td></tr>
|
|
<tr><td><span class="method method-post">POST</span></td><td><code>/api/v1/svc/_mock/delay/<s></code></td><td>Задать задержку</td></tr>
|
|
<tr><td><span class="method method-post">POST</span></td><td><code>/api/v1/svc/_mock/fail-next</code></td><td>Следующая операция упадёт</td></tr>
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
<!-- ── Сервисы ── -->
|
|
<section class="card">
|
|
<div class="card-header">
|
|
<h2>Загруженные сервисы <span class="muted">({{ svc_count }})</span></h2>
|
|
</div>
|
|
<div class="card-body table-wrap">
|
|
<table class="table">
|
|
<thead>
|
|
<tr>
|
|
<th>ID</th>
|
|
<th>Название</th>
|
|
<th>Операций</th>
|
|
<th>CfsParams</th>
|
|
<th>StateParams</th>
|
|
<th>StateOut</th>
|
|
</tr>
|
|
</thead>
|
|
<tbody>
|
|
{% for svc in svc_list %}
|
|
<tr>
|
|
<td><code>{{ svc.id }}</code></td>
|
|
<td>{{ svc.display_name }}</td>
|
|
<td>{{ svc.op_count }}</td>
|
|
<td>{% if svc.has_cfs %}<span class="dot dot-green"></span>{% else %}<span class="dot dot-gray"></span>{% endif %}</td>
|
|
<td>{% if svc.has_state %}<span class="dot dot-green"></span>{% else %}<span class="dot dot-gray"></span>{% endif %}</td>
|
|
<td>{% if svc.has_out %}<span class="dot dot-green"></span>{% else %}<span class="dot dot-gray"></span>{% endif %}</td>
|
|
</tr>
|
|
{% endfor %}
|
|
</tbody>
|
|
</table>
|
|
</div>
|
|
</section>
|
|
|
|
</main>
|
|
|
|
<footer class="footer">
|
|
polygon v{{ version }} · Nubes Mock API · Flask + gunicorn
|
|
</footer>
|
|
|
|
</body>
|
|
</html>
|