proxy-pool/api/openapi/admin.yaml

373 lines
14 KiB
YAML
Raw Permalink 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.

openapi: 3.1.0
info:
title: Proxy Pool Admin API
version: 1.0.0
description: |
运维状态与受控变更接口。该入口必须与 Distribution 分端口和权限。
已认证凭据可配置 `admin:read`Status、审计和 `admin:write`(变更);
未配置权限的旧凭据保留全权限行为。
servers:
- url: http://127.0.0.1:8082
tags:
- name: Status
description: 不含代理明细与凭据的控制面聚合状态。
- name: Audit
description: 权威管理状态变更的游标审计查询。
- name: Upstreams
description: 上游的启停与受控状态变更。
- name: Routing
description: Routing 当前上游的受控切换。
- name: Configuration
description: 经校验后原子发布的配置重载。
security:
- AdminApiKey: []
- BasicAuth: []
- BearerAuth: []
- {}
paths:
/api/v1/status:
get:
tags: [Status]
operationId: getStatus
summary: 获取控制面摘要状态
description: 需要 `admin:read`。
responses:
'200':
description: 不含 Proxy 地址、Client 标识或 Secret 的聚合状态
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/json:
schema:
$ref: '#/components/schemas/Status'
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'400': {$ref: '#/components/responses/BadRequest'}
'405': {$ref: '#/components/responses/MethodNotAllowed'}
'500': {$ref: '#/components/responses/InternalServerError'}
'503': {$ref: '#/components/responses/ServiceUnavailable'}
/api/v1/audit:
get:
tags: [Audit]
operationId: listAuditRecords
summary: 按 ID 游标读取管理面审计记录
description: |
需要 `admin:read`。
仅返回权威管理面的变更审计记录,按 `id` 升序排列。`afterId` 是排他游标:
后续页面只包含 `id` 大于该值的记录。未传 `limit` 时返回 100 条,单页最多
1000 条。
审计接口不返回 Proxy、Upstream URL、凭据或活动池内容。
parameters:
- name: afterId
in: query
required: false
description: 排他游标;仅返回 ID 大于此值的记录。
schema: {type: integer, minimum: 0, default: 0}
- name: limit
in: query
required: false
description: 单页记录数;默认 100最大 1000。
schema: {type: integer, minimum: 1, maximum: 1000, default: 100}
responses:
'200':
description: 管理面审计记录页
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/json:
schema: {$ref: '#/components/schemas/AuditPage'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'400': {$ref: '#/components/responses/BadRequest'}
'405': {$ref: '#/components/responses/MethodNotAllowed'}
'500': {$ref: '#/components/responses/InternalServerError'}
'503': {$ref: '#/components/responses/ServiceUnavailable'}
/api/v1/upstreams/{name}/enable:
post:
tags: [Upstreams]
operationId: enableUpstream
summary: 启用 Upstream
description: 需要 `admin:write`。
parameters:
- $ref: '#/components/parameters/UpstreamName'
- $ref: '#/components/parameters/RequestID'
responses:
'200': {$ref: '#/components/responses/MutationResult'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
'409': {$ref: '#/components/responses/Conflict'}
'400': {$ref: '#/components/responses/BadRequest'}
'405': {$ref: '#/components/responses/MethodNotAllowed'}
'500': {$ref: '#/components/responses/InternalServerError'}
'503': {$ref: '#/components/responses/ServiceUnavailable'}
/api/v1/upstreams/{name}/disable:
post:
tags: [Upstreams]
operationId: disableUpstream
summary: 禁用 Upstream 并使已有资源自然 Drain
description: 需要 `admin:write`。
parameters:
- $ref: '#/components/parameters/UpstreamName'
- $ref: '#/components/parameters/RequestID'
responses:
'200': {$ref: '#/components/responses/MutationResult'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
'409': {$ref: '#/components/responses/Conflict'}
'400': {$ref: '#/components/responses/BadRequest'}
'405': {$ref: '#/components/responses/MethodNotAllowed'}
'500': {$ref: '#/components/responses/InternalServerError'}
'503': {$ref: '#/components/responses/ServiceUnavailable'}
/api/v1/routing/{name}/switch:
post:
tags: [Routing]
operationId: switchRouting
summary: 原子切换 Sequential Routing 当前 Upstream
description: 需要 `admin:write`。
parameters:
- name: name
in: path
required: true
schema: {type: string, minLength: 1, maxLength: 128}
- $ref: '#/components/parameters/RequestID'
requestBody:
required: true
content:
application/json:
schema:
type: object
additionalProperties: false
required: [expectedCurrent, target]
properties:
expectedCurrent: {type: string}
target: {type: string}
reason: {type: string, maxLength: 512}
responses:
'200': {$ref: '#/components/responses/MutationResult'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'404': {$ref: '#/components/responses/NotFound'}
'409': {$ref: '#/components/responses/Conflict'}
'400': {$ref: '#/components/responses/BadRequest'}
'405': {$ref: '#/components/responses/MethodNotAllowed'}
'413': {$ref: '#/components/responses/RequestEntityTooLarge'}
'415': {$ref: '#/components/responses/UnsupportedMediaType'}
'422': {$ref: '#/components/responses/UnprocessableEntity'}
'500': {$ref: '#/components/responses/InternalServerError'}
'503': {$ref: '#/components/responses/ServiceUnavailable'}
/api/v1/config/reload:
post:
tags: [Configuration]
operationId: reloadConfiguration
summary: 严格校验并原子发布新配置快照
description: 需要 `admin:write`。
parameters:
- $ref: '#/components/parameters/RequestID'
responses:
'200': {$ref: '#/components/responses/MutationResult'}
'401': {$ref: '#/components/responses/Unauthorized'}
'403': {$ref: '#/components/responses/Forbidden'}
'409': {$ref: '#/components/responses/Conflict'}
'400': {$ref: '#/components/responses/BadRequest'}
'405': {$ref: '#/components/responses/MethodNotAllowed'}
'422':
description: 新配置无效,旧配置继续运行
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
'500': {$ref: '#/components/responses/InternalServerError'}
'503': {$ref: '#/components/responses/ServiceUnavailable'}
components:
securitySchemes:
AdminApiKey: {type: apiKey, in: header, name: X-Admin-Key}
BasicAuth: {type: http, scheme: basic}
BearerAuth: {type: http, scheme: bearer}
parameters:
UpstreamName:
name: name
in: path
required: true
schema: {type: string, minLength: 1, maxLength: 128}
RequestID:
name: X-Request-ID
in: header
required: false
schema: {type: string, maxLength: 128}
headers:
RequestID:
description: 服务端最终使用的请求标识。
schema: {type: string, maxLength: 128}
schemas:
AuditPage:
type: object
additionalProperties: false
required: [records]
properties:
records:
type: array
description: 按 ID 升序的审计记录;没有更多记录时为空数组。
items: {$ref: '#/components/schemas/AuditRecord'}
AuditRecord:
type: object
additionalProperties: false
required: [id, requestId, actorId, action, resourceType, resourceName, changed, version, occurredAt]
properties:
id: {type: integer, minimum: 0}
requestId: {type: string}
actorId: {type: string}
sourceIp: {type: string}
action: {type: string}
resourceType: {type: string}
resourceName: {type: string}
changed: {type: boolean}
version: {type: integer, minimum: 0}
reason: {type: string}
occurredAt: {type: string, format: date-time}
Status:
type: object
additionalProperties: false
required: [configVersion, snapshotVersion, upstreams, workers]
properties:
configVersion: {type: string}
snapshotVersion: {type: integer, minimum: 0}
upstreams:
type: array
items:
type: object
additionalProperties: false
required: [name, enabled, available, checking, suspect, draining, extracted]
properties:
name: {type: string}
enabled: {type: boolean}
available: {type: integer, minimum: 0}
checking: {type: integer, minimum: 0}
suspect: {type: integer, minimum: 0}
draining: {type: integer, minimum: 0}
extracted: {type: integer, minimum: 0}
consecutiveEmptyFetch: {type: integer, minimum: 0}
fetchErrorCount: {type: integer, minimum: 0}
workers:
type: array
items:
type: object
additionalProperties: false
required: [id, zone, connected, snapshotVersion]
properties:
id: {type: string}
zone: {type: string}
connected: {type: boolean}
snapshotVersion: {type: integer, minimum: 0}
staleSeconds: {type: integer, minimum: 0}
MutationResult:
type: object
additionalProperties: false
required: [requestId, changed, version]
properties:
requestId: {type: string}
changed: {type: boolean}
version: {type: integer, minimum: 0}
message: {type: string}
Problem:
type: object
required: [type, title, status, code]
properties:
type: {type: string, format: uri}
title: {type: string}
status: {type: integer}
code: {type: string}
detail: {type: string}
requestId: {type: string}
responses:
MutationResult:
description: 操作已提交或目标状态原本已满足
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/json:
schema: {$ref: '#/components/schemas/MutationResult'}
Unauthorized:
description: 管理入口认证失败
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
WWW-Authenticate: {schema: {type: string}}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
Forbidden:
description: 调用主体无该管理权限
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
NotFound:
description: Upstream 或 Routing 不存在
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
Conflict:
description: 预期版本或 expectedCurrent 与权威状态不一致
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
BadRequest:
description: 请求标识或请求体无效
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
MethodNotAllowed:
description: 端点不支持该 HTTP 方法
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
Allow: {schema: {type: string}}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
RequestEntityTooLarge:
description: 请求体超过管理入口限制
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
UnsupportedMediaType:
description: Content-Type 不是 application/json
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
UnprocessableEntity:
description: 命令字段或配置内容违反业务约束
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
InternalServerError:
description: 未分类的控制面错误
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}
ServiceUnavailable:
description: 权威控制面暂时不可用
headers:
X-Request-ID: {$ref: '#/components/headers/RequestID'}
content:
application/problem+json:
schema: {$ref: '#/components/schemas/Problem'}