231 lines
9.2 KiB
YAML
231 lines
9.2 KiB
YAML
openapi: 3.0.3
|
||
|
||
info:
|
||
title: Mapper Service API
|
||
version: "1.0.0"
|
||
description: |
|
||
REST API сервиса **mapper** (flows mapper) — mini-HTTP-сервис, который
|
||
объединяет (мапит) данные нескольких сервисов Sarex: документы дисков из
|
||
сервиса документации (`documentations`) обогащаются review-данными из
|
||
сервиса процессов (`flows`); заметки из сервиса `notes` обогащаются
|
||
связями (target-links) из Django-бэкенда.
|
||
|
||
Сервис написан на Python (**FastAPI**), приложение создаётся в
|
||
`src/app/main.py` (`app = FastAPI()`), маршруты — в `src/app/routers.py`
|
||
с префиксом `API_PREFIX` (по умолчанию `/api/v1`).
|
||
|
||
### Аутентификация
|
||
Оба эндпоинта требуют заголовок `Authorization`. Опциональный заголовок
|
||
`Identity` включает режим Zitadel. Подпись JWT **не проверяется**
|
||
(`verify_signature=False`, `src/app/dependensies.py`) — доверие к токену
|
||
обеспечивается сетевым слоем (Istio/ingress). Из токена извлекается
|
||
`user_id`, который используется как часть ключа кеша Redis.
|
||
|
||
### Агрегация и кеш
|
||
Каждый запрос обращается к двум внешним сервисам через `ServiceManager`
|
||
(`src/app/utils.py`). При `REDIS_USE=True` успешные (200) ответы апстрима
|
||
кешируются в Redis (ключ `"{user_id}_{url}"`, TTL `REDIS_EXPIRE_DAYS`
|
||
суток), а при ошибке апстрима отдаётся кеш. Если хотя бы один апстрим
|
||
вернул ошибку и кеша нет — сервис отвечает `400 Bad Request`.
|
||
|
||
Схемы ответов заданы как свободные JSON-структуры (`object`/`array`),
|
||
так как сервис проксирует и объединяет ответы внешних сервисов без
|
||
фиксированной модели.
|
||
|
||
servers:
|
||
- url: https://api.sarex.io/mapper
|
||
description: production (Sarex)
|
||
- url: https://stage-api.sarex.io/mapper
|
||
description: stage (Sarex)
|
||
- url: https://cde.brusnika.ru/mapper
|
||
description: production (Brusnika)
|
||
- url: https://test.sarex.brusnika.tech/mapper
|
||
description: stage (Brusnika)
|
||
|
||
tags:
|
||
- name: documents
|
||
description: Документы дисков, обогащённые review-данными процессов
|
||
- name: notes
|
||
description: Заметки, обогащённые связями (target-links)
|
||
|
||
paths:
|
||
/api/v1/disks/{disk}/documents/:
|
||
get:
|
||
tags:
|
||
- documents
|
||
summary: Документы диска с review-данными
|
||
operationId: get_documents
|
||
description: |
|
||
Возвращает документы диска из сервиса документации, обогащённые
|
||
review-данными из сервиса процессов. Внутри выполняются запросы
|
||
`GET {DOCUMENTATION_HOST}/disks/{disk}/documents` и
|
||
`GET {FLOW_HOST}/documents/?full=true`, после чего review-данные
|
||
добавляются в поле `review_data` соответствующих бандлов документов
|
||
(`modify_pdm_data`).
|
||
security:
|
||
- bearerAuth: []
|
||
parameters:
|
||
- name: disk
|
||
in: path
|
||
required: true
|
||
description: Идентификатор диска
|
||
schema:
|
||
type: string
|
||
- name: Authorization
|
||
in: header
|
||
required: true
|
||
description: Токен доступа (пробрасывается во внешние сервисы)
|
||
schema:
|
||
type: string
|
||
- name: Identity
|
||
in: header
|
||
required: false
|
||
description: Identity-токен (включает режим Zitadel)
|
||
schema:
|
||
type: string
|
||
responses:
|
||
"200":
|
||
description: Успешный ответ
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/DocumentsResponse"
|
||
"400":
|
||
description: Один из внешних сервисов недоступен и данных в кеше нет
|
||
"401":
|
||
description: Отсутствует заголовок Authorization
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
/api/v1/notes/{service}/{entity}/{instance_id}/:
|
||
get:
|
||
tags:
|
||
- notes
|
||
summary: Заметки сущности со связями (target-links)
|
||
operationId: get_notes
|
||
description: |
|
||
Возвращает заметки сущности из сервиса `notes`, у которых поле `links`
|
||
заменено на объекты связей (target-links) из Django-бэкенда. Внутри
|
||
выполняются запросы
|
||
`GET {NOTE_HOST}/notes/{service}/{entity}/{instance_id}/?full=true`
|
||
(с проброской всех query-параметров запроса) и
|
||
`GET {DJANGO_HOST}/core/target-links/`, после чего выполняется
|
||
объединение (`modify_notes_data`).
|
||
security:
|
||
- bearerAuth: []
|
||
parameters:
|
||
- name: service
|
||
in: path
|
||
required: true
|
||
description: Логическое имя сервиса-владельца сущности
|
||
schema:
|
||
type: string
|
||
- name: entity
|
||
in: path
|
||
required: true
|
||
description: Тип сущности
|
||
schema:
|
||
type: string
|
||
- name: instance_id
|
||
in: path
|
||
required: true
|
||
description: Идентификатор экземпляра сущности
|
||
schema:
|
||
type: string
|
||
- name: Authorization
|
||
in: header
|
||
required: true
|
||
description: Токен доступа (пробрасывается во внешние сервисы)
|
||
schema:
|
||
type: string
|
||
- name: Identity
|
||
in: header
|
||
required: false
|
||
description: Identity-токен (включает режим Zitadel)
|
||
schema:
|
||
type: string
|
||
responses:
|
||
"200":
|
||
description: |
|
||
Успешный ответ — список заметок. Все дополнительные query-параметры
|
||
запроса проксируются в сервис заметок.
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/NotesResponse"
|
||
"400":
|
||
description: Один из внешних сервисов недоступен и данных в кеше нет
|
||
"401":
|
||
description: Отсутствует заголовок Authorization
|
||
"422":
|
||
$ref: "#/components/responses/ValidationError"
|
||
|
||
components:
|
||
securitySchemes:
|
||
bearerAuth:
|
||
type: http
|
||
scheme: bearer
|
||
bearerFormat: JWT
|
||
description: |
|
||
Токен передаётся заголовком `Authorization`. Подпись не проверяется
|
||
приложением. Для режима Zitadel дополнительно передаётся заголовок
|
||
`Identity`.
|
||
|
||
responses:
|
||
ValidationError:
|
||
description: Ошибка валидации параметров запроса
|
||
content:
|
||
application/json:
|
||
schema:
|
||
$ref: "#/components/schemas/HTTPValidationError"
|
||
|
||
schemas:
|
||
DocumentsResponse:
|
||
type: object
|
||
description: |
|
||
Ответ агрегатора документов. Структура повторяет ответ сервиса
|
||
документации, где в бандлы добавлено поле `review_data` с данными
|
||
из сервиса процессов.
|
||
properties:
|
||
documents:
|
||
type: array
|
||
items:
|
||
type: object
|
||
additionalProperties: true
|
||
additionalProperties: true
|
||
|
||
NotesResponse:
|
||
type: array
|
||
description: |
|
||
Список заметок сервиса `notes`, где поле `links` каждой заметки
|
||
заменено на объекты связей (target-links).
|
||
items:
|
||
type: object
|
||
additionalProperties: true
|
||
|
||
ValidationErrorItem:
|
||
type: object
|
||
properties:
|
||
loc:
|
||
type: array
|
||
items:
|
||
anyOf:
|
||
- type: string
|
||
- type: integer
|
||
msg:
|
||
type: string
|
||
type:
|
||
type: string
|
||
required:
|
||
- loc
|
||
- msg
|
||
- type
|
||
|
||
HTTPValidationError:
|
||
type: object
|
||
properties:
|
||
detail:
|
||
type: array
|
||
items:
|
||
$ref: "#/components/schemas/ValidationErrorItem"
|