296 lines
11 KiB
YAML
296 lines
11 KiB
YAML
openapi: 3.1.0
|
|
info:
|
|
title: Proxy Pool Admin API
|
|
version: 1.0.0
|
|
description: 运维状态与受控变更接口。该入口必须与 Distribution 分端口和权限。
|
|
servers:
|
|
- url: http://127.0.0.1:8082
|
|
tags:
|
|
- name: Status
|
|
- name: Upstreams
|
|
- name: Routing
|
|
- name: Configuration
|
|
security:
|
|
- AdminApiKey: []
|
|
- BasicAuth: []
|
|
- BearerAuth: []
|
|
- {}
|
|
paths:
|
|
/api/v1/status:
|
|
get:
|
|
tags: [Status]
|
|
operationId: getStatus
|
|
summary: 获取控制面摘要状态
|
|
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/upstreams/{name}/enable:
|
|
post:
|
|
tags: [Upstreams]
|
|
operationId: enableUpstream
|
|
summary: 启用 Upstream
|
|
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
|
|
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
|
|
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: 严格校验并原子发布新配置快照
|
|
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:
|
|
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'}
|