RMDC系统设计文档 整体转换为SKILL
This commit is contained in:
224
8-CMII-RMDC/1-rmdc-system/1-rmdc-PRD.md
Normal file
224
8-CMII-RMDC/1-rmdc-system/1-rmdc-PRD.md
Normal file
@@ -0,0 +1,224 @@
|
||||
# RMDC 产品需求文档 (PRD)
|
||||
|
||||
**产品名称**: RMDC (Runtime Management & DevOps Center)
|
||||
**版本**: v1.0
|
||||
**编制日期**: 2026-01-06
|
||||
|
||||
---
|
||||
|
||||
## 1. 产品背景
|
||||
|
||||
### 1.1 业务背景
|
||||
|
||||
在复杂的混合云/边缘计算环境中,运维团队面临以下挑战:
|
||||
- **网络隔离**: 多个项目部署在不同网络环境(内网、边缘、公网)
|
||||
- **权限分散**: Jenkins、K8S、主机等资源权限管理分散
|
||||
- **状态不可见**: 无法统一查看各项目的运行状态
|
||||
- **操作复杂**: 跨网络的操作需要繁琐的VPN/跳板机流程
|
||||
|
||||
### 1.2 痛点总结
|
||||
|
||||
| 痛点 | 当前方案 | 问题 |
|
||||
|------|----------|------|
|
||||
| 跨网络访问 | VPN + 跳板机 | 效率低,依赖人工 |
|
||||
| 分支权限管理 | Jenkins原生 | 粒度粗,无法精细控制 |
|
||||
| 项目状态监控 | 分散的监控系统 | 无统一视图 |
|
||||
| 自动化部署 | 手动脚本 | 可靠性差,无审计 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 产品定位
|
||||
|
||||
RMDC是**以项目(K8s Namespace)为核心维度**的统一运维与交付平台,通过"边缘代理 + 消息总线"架构打通网络边界,提供:
|
||||
|
||||
- **统一入口**: 一个平台管理所有项目
|
||||
- **精细权限**: 分支级别的构建权限控制
|
||||
- **实时可见**: 项目状态、构建进度、监控数据统一展示
|
||||
- **全程审计**: 所有操作可追溯
|
||||
|
||||
---
|
||||
|
||||
## 3. 目标用户
|
||||
|
||||
| 用户角色 | 关键诉求 |
|
||||
|----------|----------|
|
||||
| **超级管理员(SuperAdmin)** | 管理所有项目、用户、权限 |
|
||||
| **管理员(Admin)** | 管理负责的项目,分配权限给普通用户 |
|
||||
| **普通人员(Normal)** | 查看项目信息,触发被授权的构建 |
|
||||
| **第三方人员(Third)** | 有限度地查看被授权的内容 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 功能范围
|
||||
|
||||
### 4.1 核心功能模块
|
||||
|
||||
```mermaid
|
||||
mindmap
|
||||
root((RMDC))
|
||||
Jenkins模块
|
||||
组织/仓库/分支管理
|
||||
分支级权限控制(DAC)
|
||||
构建触发与追踪
|
||||
镜像打包(DCU)
|
||||
项目管理模块
|
||||
项目信息CRUD
|
||||
部署信息管理
|
||||
授权管理(一级)
|
||||
消息网关模块
|
||||
MQTT消息中继
|
||||
指令生命周期
|
||||
同步/异步指令
|
||||
边缘代理模块
|
||||
K8S操作代理
|
||||
主机操作代理
|
||||
二级授权管理
|
||||
监控日志模块
|
||||
实时日志查看
|
||||
监控数据采集
|
||||
告警通知
|
||||
用户权限模块
|
||||
用户管理
|
||||
角色管理
|
||||
权限分配
|
||||
审计模块
|
||||
操作审计
|
||||
日志查询
|
||||
导出功能
|
||||
```
|
||||
|
||||
### 4.2 第一期功能(MVP)
|
||||
|
||||
| 模块 | 功能 | 优先级 |
|
||||
|------|------|--------|
|
||||
| Jenkins | 组织/仓库/分支查询 | P0 |
|
||||
| Jenkins | 构建触发与状态追踪 | P0 |
|
||||
| Jenkins | 分支级权限控制 | P0 |
|
||||
| 项目管理 | 项目信息CRUD | P0 |
|
||||
| 项目管理 | 授权密钥生成 | P0 |
|
||||
| 用户权限 | RBAC权限管理 | P0 |
|
||||
| 审计 | 基础操作审计 | P1 |
|
||||
| DCU | 镜像下载压缩上传 | P1 |
|
||||
|
||||
### 4.3 第二期功能
|
||||
|
||||
| 模块 | 功能 | 优先级 |
|
||||
|------|------|--------|
|
||||
| 消息网关 | MQTT消息中继 | P0 |
|
||||
| 消息网关 | 指令生命周期管理 | P0 |
|
||||
| 边缘代理 | K8S操作代理 | P0 |
|
||||
| 边缘代理 | 主机操作代理 | P1 |
|
||||
| 监控日志 | 实时日志查看 | P1 |
|
||||
| 监控日志 | 监控数据展示 | P2 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 用户故事
|
||||
|
||||
### 5.1 Jenkins构建
|
||||
|
||||
**作为** 开发人员
|
||||
**我需要** 在RMDC平台触发指定分支的构建
|
||||
**以便于** 快速验证代码变更,无需登录Jenkins
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 能够查看被授权的分支列表
|
||||
- [ ] 能够触发分支构建
|
||||
- [ ] 能够查看构建进度和结果
|
||||
- [ ] 能够查看构建日志
|
||||
|
||||
### 5.2 权限管理
|
||||
|
||||
**作为** 管理员
|
||||
**我需要** 为团队成员分配分支级构建权限
|
||||
**以便于** 确保只有授权人员能够构建特定分支
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 能够按组织/仓库/分支粒度分配权限
|
||||
- [ ] 权限支持继承(组织→仓库→分支)
|
||||
- [ ] 能够一键复制其他用户的权限
|
||||
|
||||
### 5.3 项目管理
|
||||
|
||||
**作为** 超级管理员
|
||||
**我需要** 创建和管理项目信息
|
||||
**以便于** 统一维护各项目的基本信息和授权配置
|
||||
|
||||
**验收标准**:
|
||||
- [ ] 能够创建项目并录入基本信息
|
||||
- [ ] 能够管理项目的部署信息和中间件配置
|
||||
- [ ] 能够生成项目授权密钥
|
||||
- [ ] 能够导出项目信息
|
||||
|
||||
---
|
||||
|
||||
## 6. 非功能性需求
|
||||
|
||||
### 6.1 性能要求
|
||||
|
||||
| 指标 | 要求 |
|
||||
|------|------|
|
||||
| API响应时间 | P90 < 300ms |
|
||||
| 构建状态同步延迟 | < 15s |
|
||||
| MQTT消息传输延迟 | < 5s |
|
||||
| 系统可用性 | 99.9% |
|
||||
|
||||
### 6.2 安全要求
|
||||
|
||||
| 类别 | 要求 |
|
||||
|------|------|
|
||||
| 认证 | JWT Token,有效期可配置 |
|
||||
| 授权 | RBAC + 资源级ACL |
|
||||
| 传输 | HTTPS/TLS加密 |
|
||||
| 存储 | 敏感字段AES-256加密 |
|
||||
| 审计 | 所有写操作记录审计日志 |
|
||||
|
||||
### 6.3 兼容性
|
||||
|
||||
- **前端**: Chrome 80+, Edge 80+, Firefox 75+
|
||||
- **后端**: Go 1.21+
|
||||
- **数据库**: PostgreSQL 13+
|
||||
|
||||
---
|
||||
|
||||
## 7. 系统边界
|
||||
|
||||
### 7.1 与外部系统的关系
|
||||
|
||||
| 外部系统 | 交互方式 | 说明 |
|
||||
|----------|----------|------|
|
||||
| Jenkins | REST API | 构建管理、状态同步 |
|
||||
| MinIO | S3 API | 镜像包存储 |
|
||||
| MQTT Broker | MQTT协议 | 消息中继 |
|
||||
| K8S | K8S API | 容器编排 |
|
||||
|
||||
### 7.2 不在范围内
|
||||
|
||||
- 源代码管理(由GitLab/GitHub负责)
|
||||
- CI/CD编排逻辑(由Jenkins Pipeline负责)
|
||||
- 容器镜像仓库(由Harbor负责)
|
||||
- 基础设施管理(由IaaS平台负责)
|
||||
|
||||
---
|
||||
|
||||
## 8. 约束和假设
|
||||
|
||||
### 8.1 约束
|
||||
|
||||
1. 必须兼容现有Jenkins配置,不修改Jenkinsfile
|
||||
2. 边缘项目通过公网MQTT通信,需考虑弱网环境
|
||||
3. 授权密钥离线部署,不通过网络传输
|
||||
|
||||
### 8.2 假设
|
||||
|
||||
1. 所有边缘项目均部署在K8S环境
|
||||
2. 各项目有独立的K8S Namespace
|
||||
3. MQTT Broker可从公网访问
|
||||
|
||||
---
|
||||
|
||||
## 9. 版本历史
|
||||
|
||||
| 版本 | 日期 | 修改内容 |
|
||||
|------|------|----------|
|
||||
| v1.0 | 2026-01-06 | 初始版本 |
|
||||
170
8-CMII-RMDC/1-rmdc-system/1-system-overview-prompt.md
Normal file
170
8-CMII-RMDC/1-rmdc-system/1-system-overview-prompt.md
Normal file
@@ -0,0 +1,170 @@
|
||||
# RMDC系统架构提示词
|
||||
|
||||
> 本文档为大模型(AI助手)提供RMDC系统的全面上下文,帮助AI理解系统架构并协助开发工作。
|
||||
|
||||
---
|
||||
|
||||
## 系统定位
|
||||
|
||||
**RMDC (Runtime Management & DevOps Center)** 是一个以项目(K8s Namespace)为核心维度的统一运维与交付平台。通过"边缘代理(Watchdog) + 消息总线(Exchange-Hub)"架构打通内外网,提供从代码构建、分支权限控制、自动化部署到实时监控日志的全生命周期管理。
|
||||
|
||||
---
|
||||
|
||||
## 核心模块清单
|
||||
|
||||
| 模块 | 职责 | 关键技术 |
|
||||
|------|------|----------|
|
||||
| **rmdc-core** | API Gateway、鉴权、路由 | Go + Gin |
|
||||
| **rmdc-jenkins-branch-dac** | Jenkins分支权限(DAC)、构建管理 | Jenkins API, MinIO |
|
||||
| **rmdc-exchange-hub** | MQTT消息网关、指令生命周期 | MQTT, PostgreSQL |
|
||||
| **rmdc-watchdog** | 边缘代理、K8S操作、二级授权 | K8S API, TOTP |
|
||||
| **rmdc-project-management** | 项目管理、一级授权中心 | PostgreSQL |
|
||||
| **rmdc-audit-log** | 审计日志 | PostgreSQL |
|
||||
| **rmdc-user-auth** | 用户认证、权限管理 | JWT, RBAC |
|
||||
|
||||
---
|
||||
|
||||
## 系统架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "RMDC平台 (内网)"
|
||||
Portal[前端门户<br/>Vue3+Vuetify3]
|
||||
Core[rmdc-core<br/>API Gateway]
|
||||
|
||||
subgraph "业务模块"
|
||||
Jenkins[jenkins-branch-dac]
|
||||
Project[project-management]
|
||||
Audit[audit-log]
|
||||
UserAuth[user-auth]
|
||||
end
|
||||
|
||||
ExHub[exchange-hub<br/>消息网关]
|
||||
MQTT[(MQTT Broker)]
|
||||
end
|
||||
|
||||
subgraph "外部项目环境"
|
||||
WD[rmdc-watchdog<br/>边缘代理]
|
||||
Node[watchdog-node]
|
||||
Agent[watchdog-agent]
|
||||
end
|
||||
|
||||
Portal --> Core --> Jenkins & Project & Audit & UserAuth
|
||||
Project --> ExHub <--> MQTT <-.公网.-> WD <--> Node & Agent
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 通信架构
|
||||
|
||||
### MQTT Topic设计
|
||||
|
||||
| 方向 | Topic | 用途 |
|
||||
|------|-------|------|
|
||||
| **上行** | `wdd/RDMC/command/up` | Watchdog发送指令 |
|
||||
| **上行** | `wdd/RDMC/message/up` | Watchdog发送数据 |
|
||||
| **下行** | `wdd/RDMC/command/down/{project_id}` | 下发指令 |
|
||||
| **下行** | `wdd/RDMC/message/down/{project_id}` | 下发数据 |
|
||||
|
||||
### 安全机制
|
||||
|
||||
```
|
||||
一级授权: rmdc-project-management ↔ rmdc-watchdog (8位码, 30分钟有效)
|
||||
二级授权: rmdc-watchdog ↔ watchdog-agent/node (6位码, 30秒有效)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API设计规范
|
||||
|
||||
> **重要**: RMDC API遵循以下规范
|
||||
|
||||
1. **RESTful风格**:使用标准HTTP方法语义
|
||||
2. **优先POST+RequestBody**:复杂查询和所有写操作使用POST
|
||||
3. **避免PathVariables**:资源标识放入RequestBody
|
||||
4. **避免RequestParams**:查询参数放入RequestBody
|
||||
5. **统一响应格式**:
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {...}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 开发规范
|
||||
|
||||
### 后端规范(Go)
|
||||
|
||||
```
|
||||
项目结构:
|
||||
├── cmd/ # 入口
|
||||
├── configs/ # 配置
|
||||
├── internal/
|
||||
│ ├── config/ # 配置结构
|
||||
│ ├── dao/ # 数据访问层
|
||||
│ ├── handler/ # HTTP处理器
|
||||
│ ├── model/
|
||||
│ │ ├── dto/ # 请求/响应DTO
|
||||
│ │ └── entity/ # 数据库实体
|
||||
│ └── service/ # 业务逻辑层
|
||||
└── pkg/ # 公共包
|
||||
```
|
||||
|
||||
**关键约束**:
|
||||
- 禁止在Handler层写业务逻辑
|
||||
- 所有SQL在DAO层
|
||||
- 使用GORM进行ORM操作
|
||||
|
||||
### 前端规范(Vue3)
|
||||
|
||||
- 技术栈: Vue3 + TypeScript + Vuetify3
|
||||
- 使用Composition API
|
||||
- 组件销毁时断开WebSocket连接
|
||||
|
||||
---
|
||||
|
||||
## 核心业务流程
|
||||
|
||||
### 项目注册流程
|
||||
|
||||
```
|
||||
1. project-management创建项目 → 生成密钥
|
||||
2. 部署watchdog(携带配置文件)
|
||||
3. watchdog连接MQTT → 发送注册请求(含TOTP)
|
||||
4. exchange-hub验证 → 发送挑战码
|
||||
5. watchdog回复挑战码 → 注册成功
|
||||
```
|
||||
|
||||
### 构建触发流程
|
||||
|
||||
```
|
||||
1. 用户调用 POST /builds/trigger
|
||||
2. jenkins-branch-dac 调用 Jenkins API
|
||||
3. BuildTracker开始追踪构建状态
|
||||
4. 前端轮询构建详情
|
||||
5. 构建完成 → 可触发DCU打包镜像
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 文档索引
|
||||
|
||||
| 文档路径 | 内容 |
|
||||
|----------|------|
|
||||
| `1-基本框架/2-rmdc-DDS.md` | 系统PRD/DDS |
|
||||
| `2-Jenkins模块/1-jenkins-branch-dac-DDS.md` | Jenkins模块DDS |
|
||||
| `3-rmdc-exchange-hub/1-rmdc-exchange-hub-DDS.md` | Exchange-Hub DDS |
|
||||
| `4-rmdc-project-management/1-rmdc-project-management-DDS.md` | 项目管理DDS |
|
||||
| `6-rmdc-watchdog/1-rmdc-watchdog-DDS.md` | Watchdog DDS |
|
||||
|
||||
---
|
||||
|
||||
## 如何使用本提示词
|
||||
|
||||
1. **理解系统**: 阅读架构说明和业务流程
|
||||
2. **定位模块**: 确定涉及的模块
|
||||
3. **查阅详细文档**: 参考模块DDS
|
||||
4. **遵循规范**: 按照API和开发规范编码
|
||||
150
8-CMII-RMDC/1-rmdc-system/2-module-interaction-prompt.md
Normal file
150
8-CMII-RMDC/1-rmdc-system/2-module-interaction-prompt.md
Normal file
@@ -0,0 +1,150 @@
|
||||
# 模块交互流程提示词
|
||||
|
||||
> 本文档描述RMDC系统各模块之间的交互流程,帮助大模型理解数据流和调用关系。
|
||||
|
||||
---
|
||||
|
||||
## 模块调用关系
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
FE[Vue3 Frontend] --> Core[rmdc-core]
|
||||
Core --> Jenkins[jenkins-branch-dac]
|
||||
Core --> Project[project-management]
|
||||
Core --> Audit[audit-log]
|
||||
Core --> UserAuth[user-auth]
|
||||
Core --> ExHub[exchange-hub]
|
||||
|
||||
ExHub <--> MQTT[(MQTT)]
|
||||
MQTT <--> WD[watchdog]
|
||||
WD <--> Node[watchdog-node]
|
||||
WD <--> Agent[watchdog-agent]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心交互流程
|
||||
|
||||
### 1. 用户请求处理
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant FE as 前端
|
||||
participant Core as rmdc-core
|
||||
participant Auth as AuthMiddleware
|
||||
participant Perm as PermMiddleware
|
||||
participant Biz as 业务模块
|
||||
|
||||
FE->>Core: HTTP Request (JWT)
|
||||
Core->>Auth: 验证Token
|
||||
Auth->>Perm: 权限校验
|
||||
Perm->>Biz: 处理业务
|
||||
Biz-->>FE: HTTP Response
|
||||
```
|
||||
|
||||
### 2. Jenkins构建触发
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户
|
||||
participant Handler as BuildHandler
|
||||
participant Service as BuildService
|
||||
participant Jenkins as Jenkins API
|
||||
participant Tracker as BuildTracker
|
||||
|
||||
User->>Handler: POST /builds/trigger
|
||||
Handler->>Service: TriggerBuild()
|
||||
Service->>Jenkins: 触发构建
|
||||
Service->>Tracker: TrackBuild()
|
||||
Service-->>User: 返回构建号
|
||||
```
|
||||
|
||||
### 3. 项目注册授权
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant PM as project-management
|
||||
participant ExHub as exchange-hub
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as watchdog
|
||||
|
||||
Note over PM: 创建项目,生成密钥
|
||||
WD->>MQTT: 发送注册请求(TOTP)
|
||||
MQTT->>ExHub: 转发
|
||||
ExHub->>PM: 验证项目
|
||||
PM-->>ExHub: 返回结果
|
||||
ExHub->>MQTT: 发送挑战码
|
||||
MQTT->>WD: 推送
|
||||
WD->>MQTT: 回复挑战
|
||||
ExHub->>ExHub: 验证成功,项目上线
|
||||
```
|
||||
|
||||
### 4. K8S指令执行
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户
|
||||
participant API as rmdc-core
|
||||
participant ExHub as exchange-hub
|
||||
participant MQTT as MQTT
|
||||
participant WD as watchdog
|
||||
participant K8S as K8S API
|
||||
|
||||
User->>API: 发起K8S操作
|
||||
API->>ExHub: 发送指令
|
||||
ExHub->>MQTT: 发布command
|
||||
MQTT->>WD: 推送指令
|
||||
WD->>K8S: 执行操作
|
||||
K8S-->>WD: 返回结果
|
||||
WD->>MQTT: 发布result
|
||||
MQTT->>ExHub: 接收结果
|
||||
ExHub->>API: 返回结果
|
||||
API->>User: 展示结果
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 数据流向
|
||||
|
||||
### 下行数据流
|
||||
|
||||
```
|
||||
用户操作 → rmdc-core → 业务模块 → exchange-hub → MQTT → watchdog → 执行目标
|
||||
```
|
||||
|
||||
### 上行数据流
|
||||
|
||||
```
|
||||
执行目标 → watchdog → MQTT → exchange-hub → 业务模块 → 持久化/展示
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 接口契约
|
||||
|
||||
### MQTT消息格式
|
||||
|
||||
```json
|
||||
{
|
||||
"message_id": "uuid",
|
||||
"type": "command|message",
|
||||
"project_id": "namespace_xxx",
|
||||
"command_type": "k8s_exec|host_exec|...",
|
||||
"timestamp": 1704501234567,
|
||||
"payload": {...},
|
||||
"signature": "hmac-sha256"
|
||||
}
|
||||
```
|
||||
|
||||
### 执行结果格式
|
||||
|
||||
```json
|
||||
{
|
||||
"command_id": "原指令ID",
|
||||
"status": "success|failure|timeout",
|
||||
"exit_code": 0,
|
||||
"output": "执行输出",
|
||||
"error": "",
|
||||
"duration": 1111
|
||||
}
|
||||
```
|
||||
244
8-CMII-RMDC/1-rmdc-system/2-rmdc-DDS.md
Normal file
244
8-CMII-RMDC/1-rmdc-system/2-rmdc-DDS.md
Normal file
@@ -0,0 +1,244 @@
|
||||
# RMDC 详细设计说明书 (DDS)
|
||||
|
||||
**产品名称**: RMDC (Runtime Management & DevOps Center)
|
||||
**版本**: v1.0
|
||||
**编制日期**: 2026-01-06
|
||||
|
||||
---
|
||||
|
||||
## 1. 系统架构
|
||||
|
||||
### 1.1 整体架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "前端层"
|
||||
Portal[RMDC Portal<br/>Vue3 + Vuetify3]
|
||||
end
|
||||
|
||||
subgraph "网关层"
|
||||
Core[rmdc-core<br/>API Gateway + 鉴权]
|
||||
end
|
||||
|
||||
subgraph "业务层"
|
||||
Jenkins[rmdc-jenkins-branch-dac<br/>构建管理]
|
||||
Project[rmdc-project-management<br/>项目管理]
|
||||
Audit[rmdc-audit-log<br/>审计日志]
|
||||
UserAuth[rmdc-user-auth<br/>用户权限]
|
||||
ExHub[rmdc-exchange-hub<br/>消息网关]
|
||||
end
|
||||
|
||||
subgraph "通信层"
|
||||
MQTT[(MQTT Broker)]
|
||||
end
|
||||
|
||||
subgraph "边缘层"
|
||||
WD[rmdc-watchdog<br/>边缘代理]
|
||||
Node[watchdog-node<br/>主机代理]
|
||||
Agent[watchdog-agent<br/>业务启动器]
|
||||
end
|
||||
|
||||
subgraph "外部服务"
|
||||
JenkinsS[(Jenkins)]
|
||||
MinIO[(MinIO)]
|
||||
PG[(PostgreSQL)]
|
||||
end
|
||||
|
||||
Portal --> Core
|
||||
Core --> Jenkins & Project & Audit & UserAuth & ExHub
|
||||
|
||||
Jenkins --> JenkinsS & MinIO
|
||||
Project & Jenkins & Audit --> PG
|
||||
ExHub <--> MQTT
|
||||
MQTT <-.公网.-> WD
|
||||
WD <--> Node & Agent
|
||||
```
|
||||
|
||||
### 1.2 技术栈
|
||||
|
||||
| 层级 | 技术 |
|
||||
|------|------|
|
||||
| 前端 | Vue3, TypeScript, Vuetify3 |
|
||||
| 后端 | Go 1.21+, Gin, GORM |
|
||||
| 数据库 | PostgreSQL 13+ |
|
||||
| 消息 | MQTT (Eclipse Mosquitto) |
|
||||
| 存储 | MinIO |
|
||||
| 容器 | Docker, Kubernetes |
|
||||
|
||||
---
|
||||
|
||||
## 2. 模块职责
|
||||
|
||||
### 2.1 模块清单
|
||||
|
||||
| 模块 | 职责 | 关键能力 |
|
||||
|------|------|----------|
|
||||
| **rmdc-core** | API网关 | 路由、鉴权、限流 |
|
||||
| **rmdc-jenkins-branch-dac** | Jenkins管理 | 分支权限、构建触发、DCU |
|
||||
| **rmdc-project-management** | 项目管理 | CRUD、一级授权 |
|
||||
| **rmdc-exchange-hub** | 消息网关 | MQTT中继、指令管理 |
|
||||
| **rmdc-watchdog** | 边缘代理 | K8S操作、二级授权 |
|
||||
| **rmdc-audit-log** | 审计日志 | 日志记录、查询导出 |
|
||||
| **rmdc-user-auth** | 用户权限 | RBAC、权限分配 |
|
||||
|
||||
### 2.2 模块依赖关系
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
Core[rmdc-core] --> Jenkins & Project & Audit & UserAuth & ExHub
|
||||
|
||||
Jenkins --> Common
|
||||
Project --> Common
|
||||
ExHub --> Common
|
||||
UserAuth --> Common
|
||||
|
||||
Common[rmdc-common<br/>公共接口]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 通信架构
|
||||
|
||||
### 3.1 MQTT Topic设计
|
||||
|
||||
| Topic | 方向 | 用途 |
|
||||
|-------|------|------|
|
||||
| `wdd/RDMC/command/up` | 上行 | Watchdog发送指令 |
|
||||
| `wdd/RDMC/message/up` | 上行 | Watchdog发送数据 |
|
||||
| `wdd/RDMC/command/down/{project_id}` | 下行 | 下发指令 |
|
||||
| `wdd/RDMC/message/down/{project_id}` | 下行 | 下发数据 |
|
||||
|
||||
### 3.2 消息格式
|
||||
|
||||
```json
|
||||
{
|
||||
"message_id": "uuid",
|
||||
"type": "command|message",
|
||||
"project_id": "namespace_xxx",
|
||||
"command_type": "k8s_exec|host_exec|register|...",
|
||||
"timestamp": 1704501234567,
|
||||
"version": "1.0",
|
||||
"signature": "hmac-sha256",
|
||||
"payload": {...}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 安全架构
|
||||
|
||||
### 4.1 认证授权
|
||||
|
||||
| 层级 | 机制 |
|
||||
|------|------|
|
||||
| 用户认证 | JWT Token |
|
||||
| API授权 | RBAC + 资源ACL |
|
||||
| MQTT认证 | 用户名密码 + TLS |
|
||||
| 数据加密 | AES-256-GCM |
|
||||
|
||||
### 4.2 TOTP双层授权
|
||||
|
||||
```
|
||||
一级授权: project-management ↔ watchdog
|
||||
- 8位验证码
|
||||
- 30分钟有效期
|
||||
- SHA256算法
|
||||
|
||||
二级授权: watchdog ↔ agent/node
|
||||
- 6位验证码
|
||||
- 30秒有效期
|
||||
- SHA1算法
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 数据模型
|
||||
|
||||
### 5.1 核心实体
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
users ||--o{ user_permissions : has
|
||||
projects ||--o{ auth_info : has
|
||||
jenkins_organizations ||--o{ jenkins_repositories : contains
|
||||
jenkins_repositories ||--o{ jenkins_branches : contains
|
||||
jenkins_branches ||--o{ jenkins_builds : contains
|
||||
|
||||
users {
|
||||
int64 id PK
|
||||
string username UK
|
||||
string password
|
||||
string role
|
||||
}
|
||||
|
||||
projects {
|
||||
int64 id PK
|
||||
string project_id UK
|
||||
string name
|
||||
string namespace UK
|
||||
string status
|
||||
}
|
||||
|
||||
jenkins_organizations {
|
||||
int64 id PK
|
||||
string name UK
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. API设计规范
|
||||
|
||||
### 6.1 设计原则
|
||||
|
||||
1. **使用POST + RequestBody**: 所有API优先使用POST
|
||||
2. **避免PathVariables**: 资源标识放入RequestBody
|
||||
3. **避免RequestParams**: 查询参数放入RequestBody
|
||||
4. **统一响应格式**: `{code, message, data}`
|
||||
|
||||
### 6.2 接口命名规范
|
||||
|
||||
| 操作 | 后缀 | 示例 |
|
||||
|------|------|------|
|
||||
| 列表 | `/list` | `/api/projects/list` |
|
||||
| 详情 | `/detail` | `/api/projects/detail` |
|
||||
| 创建 | `/create` | `/api/projects/create` |
|
||||
| 更新 | `/update` | `/api/projects/update` |
|
||||
| 删除 | `/delete` | `/api/projects/delete` |
|
||||
|
||||
---
|
||||
|
||||
## 7. 部署架构
|
||||
|
||||
### 7.1 K8S部署
|
||||
|
||||
```yaml
|
||||
# 核心服务
|
||||
rmdc-core: Deployment (replicas: 2)
|
||||
rmdc-jenkins-branch-dac: 集成在rmdc-core
|
||||
rmdc-project-management: 集成在rmdc-core
|
||||
rmdc-exchange-hub: Deployment (replicas: 1)
|
||||
rmdc-frontend: Deployment (replicas: 2)
|
||||
|
||||
# 边缘服务
|
||||
rmdc-watchdog: Deployment (replicas: 1, 每项目独立)
|
||||
rmdc-watchdog-node: DaemonSet (每节点一个)
|
||||
```
|
||||
|
||||
### 7.2 网络架构
|
||||
|
||||
```
|
||||
内网 ←→ MQTT Broker (公网暴露) ←→ 边缘网络
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 相关文档
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| [1-rmdc-PRD.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/1-rmdc-system/1-rmdc-PRD.md) | 产品需求文档 |
|
||||
| [1-jenkins-branch-dac-DDS.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/1-jenkins-branch-dac-DDS.md) | Jenkins模块DDS |
|
||||
| [prompts/1-system-overview-prompt.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/1-rmdc-system/prompts/1-system-overview-prompt.md) | 系统架构提示词 |
|
||||
| [prompts/3-api-development-prompt.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/1-rmdc-system/prompts/3-api-development-prompt.md) | API开发规范 |
|
||||
| [prompts/4-postman-testing-prompt.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/1-rmdc-system/prompts/4-postman-testing-prompt.md) | Postman测试用例 |
|
||||
294
8-CMII-RMDC/1-rmdc-system/3-rmdc-系统设计图.md
Normal file
294
8-CMII-RMDC/1-rmdc-system/3-rmdc-系统设计图.md
Normal file
@@ -0,0 +1,294 @@
|
||||
# RDMC 系统架构设计图
|
||||
|
||||
## 1. RDMC 整体系统架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "RDMC 平台核心 (内网环境)"
|
||||
Portal["前端门户<br/>Vue3+Vuetify3+TypeScript"]
|
||||
|
||||
subgraph "核心业务模块"
|
||||
JenkinsDAC["jenkins-branch-dac<br/>Jenkins分支管理"]
|
||||
LogCenter["log-center<br/>日志中心"]
|
||||
MonitorCenter["monitor-center<br/>监控中心"]
|
||||
DeliveryUpdate["delivery-update<br/>业务更新"]
|
||||
Notice["notice-center<br/>消息通知中心"]
|
||||
Operator["octopus-operator<br/>执行中心"]
|
||||
ProjectMgmt["project-management<br/>项目管理"]
|
||||
Audit["audit-log<br/>审计模块"]
|
||||
end
|
||||
|
||||
subgraph "基础设施层"
|
||||
WatchdogCenter["watchdog-center<br/>一级授权中心"]
|
||||
ExchangeHub["exchange-hub<br/>消息网关"]
|
||||
UserAuth["user-auth<br/>用户认证"]
|
||||
Core["rmdc-core<br/>API Gateway<br/>Go+Gin+GORM"]
|
||||
DB[(PostgreSQL<br/>业务数据库)]
|
||||
end
|
||||
|
||||
MQTT[(MQTT Broker<br/>EMQX/Mosquitto)]
|
||||
end
|
||||
|
||||
subgraph "外部系统"
|
||||
Jenkins[Jenkins CI/CD]
|
||||
DingTalk[钉钉告警]
|
||||
MinIO[MinIO 对象存储]
|
||||
end
|
||||
|
||||
subgraph "项目环境 A (外网/隔离网络)"
|
||||
K8sA[Kubernetes Cluster A]
|
||||
|
||||
subgraph "Namespace: project-a"
|
||||
WatchdogA["rmdc-watchdog<br/>二级授权中心<br/>K8s Operator"]
|
||||
|
||||
subgraph "微服务Pod"
|
||||
ServiceA1["业务A1<br/>watchdog-agent"]
|
||||
ServiceA2["业务A2<br/>watchdog-agent"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "主机层"
|
||||
HostA1["主机A1<br/>watchdog-node<br/>DaemonSet"]
|
||||
HostA2["主机A2<br/>watchdog-node<br/>DaemonSet"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "项目环境 B (外网/隔离网络)"
|
||||
K8sB[Kubernetes Cluster B]
|
||||
|
||||
subgraph "Namespace: project-b"
|
||||
WatchdogB["rmdc-watchdog<br/>二级授权中心"]
|
||||
ServiceB1["业务B1<br/>watchdog-agent"]
|
||||
end
|
||||
|
||||
HostB1["主机B1<br/>watchdog-node"]
|
||||
end
|
||||
|
||||
%% 前端到后端连接
|
||||
Portal --> Core
|
||||
|
||||
%% 核心模块连接
|
||||
Core --> JenkinsDAC
|
||||
Core --> LogCenter
|
||||
Core --> MonitorCenter
|
||||
Core --> DeliveryUpdate
|
||||
Core --> Notice
|
||||
Core --> Operator
|
||||
Core --> ProjectMgmt
|
||||
Core --> Audit
|
||||
Core --> UserAuth
|
||||
|
||||
%% 项目管理与授权中心
|
||||
ProjectMgmt -.项目创建/授权.-> WatchdogCenter
|
||||
WatchdogCenter -.授权信息.-> ExchangeHub
|
||||
|
||||
%% Exchange-Hub与MQTT
|
||||
ExchangeHub <==订阅/发布==> MQTT
|
||||
|
||||
%% 业务模块到Exchange-Hub
|
||||
LogCenter -.指令下发.-> ExchangeHub
|
||||
MonitorCenter -.指令下发.-> ExchangeHub
|
||||
DeliveryUpdate -.指令下发.-> ExchangeHub
|
||||
Operator -.指令下发.-> ExchangeHub
|
||||
|
||||
%% MQTT到外部项目 (跨公网)
|
||||
MQTT <=="Command/Message<br/>公网"==> WatchdogA
|
||||
MQTT <=="Command/Message<br/>公网"==> WatchdogB
|
||||
|
||||
%% 项目内部通信
|
||||
WatchdogA <--"授权心跳<br/>TOTP验证"--> ServiceA1
|
||||
WatchdogA <--"授权心跳<br/>TOTP验证"--> ServiceA2
|
||||
WatchdogA <--"主机信息<br/>指令执行"--> HostA1
|
||||
WatchdogA <--"主机信息<br/>指令执行"--> HostA2
|
||||
|
||||
WatchdogB <--授权心跳--> ServiceB1
|
||||
WatchdogB <--主机信息--> HostB1
|
||||
|
||||
%% 数据持久化
|
||||
Core --> DB
|
||||
ExchangeHub --> DB
|
||||
|
||||
%% 外部系统集成
|
||||
JenkinsDAC --> Jenkins
|
||||
Notice --> DingTalk
|
||||
DeliveryUpdate --> MinIO
|
||||
|
||||
style ExchangeHub fill:#ff6b6b,stroke:#c92a2a,stroke-width:3px
|
||||
style MQTT fill:#ffd43b,stroke:#f08c00,stroke-width:2px
|
||||
style WatchdogA fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
|
||||
style WatchdogB fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
|
||||
style WatchdogCenter fill:#ff8787,stroke:#c92a2a,stroke-width:2px
|
||||
style Portal fill:#845ef7,stroke:#5f3dc4
|
||||
style ProjectMgmt fill:#a9e34b,stroke:#5c940d,stroke-width:2px
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 模块层级架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "用户层"
|
||||
User["用户/管理员"]
|
||||
end
|
||||
|
||||
subgraph "表现层 (Presentation)"
|
||||
Frontend["Vue3 + Vuetify3<br/>SPA应用"]
|
||||
end
|
||||
|
||||
subgraph "网关层 (Gateway)"
|
||||
APIGateway["rmdc-core<br/>API Gateway<br/>路由 | 鉴权 | 限流"]
|
||||
end
|
||||
|
||||
subgraph "业务层 (Business)"
|
||||
subgraph "业务模块"
|
||||
M1["jenkins-branch-dac"]
|
||||
M2["log-center"]
|
||||
M3["monitor-center"]
|
||||
M4["delivery-update"]
|
||||
M5["notice-center"]
|
||||
M6["octopus-operator"]
|
||||
M7["project-management"]
|
||||
end
|
||||
|
||||
subgraph "基础模块"
|
||||
Auth["user-auth<br/>用户认证授权"]
|
||||
AuditLog["audit-log<br/>审计日志"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "通信层 (Communication)"
|
||||
ExHub["exchange-hub<br/>消息网关"]
|
||||
end
|
||||
|
||||
subgraph "消息中间件层"
|
||||
MQTT["MQTT Broker"]
|
||||
end
|
||||
|
||||
subgraph "边缘层 (Edge)"
|
||||
direction LR
|
||||
WD["rmdc-watchdog<br/>二级授权中心"]
|
||||
WDNode["watchdog-node<br/>主机守护"]
|
||||
WDAgent["watchdog-agent<br/>业务代理"]
|
||||
end
|
||||
|
||||
subgraph "数据层 (Data)"
|
||||
PG[(PostgreSQL)]
|
||||
end
|
||||
|
||||
User --> Frontend
|
||||
Frontend --> APIGateway
|
||||
|
||||
APIGateway --> M1
|
||||
APIGateway --> M2
|
||||
APIGateway --> M3
|
||||
APIGateway --> M4
|
||||
APIGateway --> M5
|
||||
APIGateway --> M6
|
||||
APIGateway --> M7
|
||||
APIGateway --> Auth
|
||||
APIGateway --> AuditLog
|
||||
|
||||
M2 --> ExHub
|
||||
M3 --> ExHub
|
||||
M4 --> ExHub
|
||||
M6 --> ExHub
|
||||
M7 --> ExHub
|
||||
|
||||
ExHub <--> MQTT
|
||||
MQTT <--> WD
|
||||
|
||||
WD --> WDNode
|
||||
WD --> WDAgent
|
||||
|
||||
M1 --> PG
|
||||
Auth --> PG
|
||||
AuditLog --> PG
|
||||
ExHub --> PG
|
||||
M3 --> PG
|
||||
M7 --> PG
|
||||
|
||||
style ExHub fill:#ff6b6b,stroke:#c92a2a
|
||||
style MQTT fill:#ffd43b,stroke:#f08c00
|
||||
style WD fill:#4ecdc4,stroke:#087f5b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 通信架构图
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "RMDC平台"
|
||||
Portal["前端门户"]
|
||||
API["API Gateway"]
|
||||
ExHub["Exchange-Hub"]
|
||||
Modules["业务模块"]
|
||||
end
|
||||
|
||||
subgraph "消息通道"
|
||||
MQTT["MQTT Broker"]
|
||||
end
|
||||
|
||||
subgraph "外部项目"
|
||||
WD["Watchdog"]
|
||||
Node["Node"]
|
||||
Agent["Agent"]
|
||||
end
|
||||
|
||||
Portal ==HTTP/REST==> API
|
||||
API ==内部调用==> Modules
|
||||
Modules ==指令请求==> ExHub
|
||||
ExHub ==MQTT Publish==> MQTT
|
||||
MQTT ==MQTT Subscribe==> WD
|
||||
|
||||
WD ==执行结果==> MQTT
|
||||
MQTT ==结果推送==> ExHub
|
||||
ExHub ==结果返回==> Modules
|
||||
|
||||
WD <==内网通信==> Node
|
||||
WD <==内网通信==> Agent
|
||||
|
||||
style MQTT fill:#ffd43b,stroke:#f08c00,stroke-width:2px
|
||||
style ExHub fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据流向图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
subgraph "指令下行流程"
|
||||
direction TB
|
||||
U1[用户操作] --> F1[前端请求]
|
||||
F1 --> A1[API Gateway]
|
||||
A1 --> M1[业务模块]
|
||||
M1 --> E1[Exchange-Hub]
|
||||
E1 --> Q1[MQTT Broker]
|
||||
Q1 --> W1[Watchdog]
|
||||
W1 --> T1{目标类型}
|
||||
T1 -->|K8S| K1[K8S API]
|
||||
T1 -->|主机| N1[watchdog-node]
|
||||
T1 -->|业务| G1[watchdog-agent]
|
||||
end
|
||||
|
||||
subgraph "数据上行流程"
|
||||
direction BT
|
||||
K2[K8S执行结果] --> W2[Watchdog]
|
||||
N2[主机执行结果] --> W2
|
||||
G2[业务状态] --> W2
|
||||
W2 --> Q2[MQTT Broker]
|
||||
Q2 --> E2[Exchange-Hub]
|
||||
E2 --> D1{数据类型}
|
||||
D1 -->|执行结果| M2[Operator]
|
||||
D1 -->|监控数据| M3[Monitor]
|
||||
D1 -->|日志数据| M4[LogCenter]
|
||||
D1 -->|告警数据| M5[Notice]
|
||||
end
|
||||
|
||||
style E1 fill:#ff6b6b,stroke:#c92a2a
|
||||
style E2 fill:#ff6b6b,stroke:#c92a2a
|
||||
style Q1 fill:#ffd43b,stroke:#f08c00
|
||||
style Q2 fill:#ffd43b,stroke:#f08c00
|
||||
```
|
||||
693
8-CMII-RMDC/1-rmdc-system/4-审计日志架构设计.md
Normal file
693
8-CMII-RMDC/1-rmdc-system/4-审计日志架构设计.md
Normal file
@@ -0,0 +1,693 @@
|
||||
# RMDC 审计日志架构设计
|
||||
|
||||
## 1. 审计日志模块整体架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "前端 Frontend"
|
||||
Vue[Vue3 前端应用]
|
||||
end
|
||||
|
||||
subgraph "rmdc-core 核心模块"
|
||||
Router[Gin Router]
|
||||
CORS[CORS 中间件]
|
||||
Audit[审计中间件<br/>AuditMiddleware]
|
||||
Auth[认证中间件<br/>AuthMiddleware]
|
||||
end
|
||||
|
||||
subgraph "业务模块层"
|
||||
Jenkins[rmdc-jenkins-branch-dac<br/>Jenkins模块]
|
||||
UserAuth[rmdc-user-auth<br/>用户认证模块]
|
||||
Watchdog[rmdc-watchdog-center<br/>Watchdog模块]
|
||||
end
|
||||
|
||||
subgraph "rmdc-audit-log 审计模块"
|
||||
AuditWriter[AuditWriter 接口]
|
||||
AuditService[AuditService<br/>审计服务]
|
||||
DAOManager[AuditLogDAOManager<br/>DAO管理器]
|
||||
CoreDAO[AuditLogDao<br/>核心模块DAO]
|
||||
JenkinsDAO[JenkinsAuditLogDao<br/>Jenkins模块DAO]
|
||||
end
|
||||
|
||||
subgraph "数据持久层 - rmdc_audit 数据库"
|
||||
DB[(PostgreSQL)]
|
||||
CoreTable[core_audit_logs]
|
||||
JenkinsTable[jenkins_audit_logs]
|
||||
WatchdogTable[watchdog_audit_logs]
|
||||
UserAuthTable[user_auth_audit_logs]
|
||||
end
|
||||
|
||||
Vue -->|HTTP Request| Router
|
||||
Router --> CORS
|
||||
CORS --> Audit
|
||||
Audit -->|记录审计日志| AuditWriter
|
||||
AuditWriter --> AuditService
|
||||
Audit --> Auth
|
||||
Auth --> Jenkins
|
||||
Auth --> UserAuth
|
||||
Auth --> Watchdog
|
||||
|
||||
Jenkins -.->|WriteJenkinsLog| AuditWriter
|
||||
|
||||
AuditService --> DAOManager
|
||||
DAOManager --> CoreDAO
|
||||
DAOManager --> JenkinsDAO
|
||||
CoreDAO --> DB
|
||||
JenkinsDAO --> DB
|
||||
DB --> CoreTable
|
||||
DB --> JenkinsTable
|
||||
DB --> WatchdogTable
|
||||
DB --> UserAuthTable
|
||||
|
||||
style Audit fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px
|
||||
style AuditService fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
|
||||
style DAOManager fill:#74c0fc,stroke:#1864ab,stroke-width:2px
|
||||
style DB fill:#ffd43b,stroke:#f08c00,stroke-width:2px
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. Jenkins 模块审计日志写入流程
|
||||
|
||||
以触发 Jenkins 构建为例,展示一条请求如何被正确写入 `jenkins_audit_logs` 表:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户浏览器
|
||||
participant F as Vue3 前端
|
||||
participant R as Gin Router
|
||||
participant AM as AuditMiddleware
|
||||
participant Auth as AuthMiddleware
|
||||
participant JH as Jenkins Handler
|
||||
participant JS as Jenkins Service
|
||||
participant AS as AuditService
|
||||
participant JenkinsDAO as JenkinsAuditLogDao
|
||||
participant DB as PostgreSQL
|
||||
|
||||
rect rgb(220, 240, 255)
|
||||
Note over U,DB: 阶段1: 请求发起与审计捕获
|
||||
end
|
||||
|
||||
U->>F: 点击"触发构建"按钮
|
||||
F->>R: POST /api/builds/trigger<br/>{organization, repository, branch}
|
||||
|
||||
R->>AM: 请求进入中间件链
|
||||
activate AM
|
||||
AM->>AM: 记录开始时间 startTime
|
||||
AM->>AM: 读取并缓存 RequestBody
|
||||
AM->>AM: 提取 QueryParams
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over AM,Auth: 阶段2: 认证与业务处理
|
||||
end
|
||||
|
||||
AM->>Auth: c.Next() 继续处理
|
||||
Auth->>Auth: 验证JWT Token
|
||||
Auth->>Auth: 提取 user_id, username
|
||||
Auth->>JH: 路由到 Jenkins Handler
|
||||
JH->>JS: TriggerBuild(org, repo, branch)
|
||||
JS->>JS: 调用 Jenkins API
|
||||
JS-->>JH: 返回构建结果
|
||||
JH-->>Auth: 响应 200 OK
|
||||
Auth-->>AM: 返回控制权
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over AM,DB: 阶段3: 审计日志异步写入
|
||||
end
|
||||
|
||||
AM->>AM: 计算 duration = time.Since(startTime)
|
||||
AM->>AM: 从 context 提取 user_id, username
|
||||
AM->>AM: 提取 resourceType=jenkins_project
|
||||
AM->>AM: determineAction() → "TRIGGER_BUILD"
|
||||
AM->>AM: sanitizeSensitiveData(requestBody)
|
||||
|
||||
AM->>AS: WriteLog(auditLog) 写入Jenkins缓冲区
|
||||
deactivate AM
|
||||
|
||||
activate AS
|
||||
AS->>AS: 判断 Module="jenkins"
|
||||
AS->>AS: 放入 jenkinsLogBuffer
|
||||
AS->>AS: jenkinsBatchWriter 批量处理
|
||||
AS->>JenkinsDAO: BatchCreate(ctx, logs)
|
||||
JenkinsDAO->>DB: INSERT INTO jenkins_audit_logs
|
||||
DB-->>JenkinsDAO: 写入成功
|
||||
deactivate AS
|
||||
|
||||
Note over DB: jenkins_audit_logs 表中新增一条记录:<br/>action=TRIGGER_BUILD<br/>organization=Backend<br/>repository=cmii-fly-center<br/>branch=feature-xxx
|
||||
```
|
||||
|
||||
### 关键代码路径
|
||||
|
||||
| 步骤 | 文件 | 函数/方法 | 说明 |
|
||||
|------|------|-----------|------|
|
||||
| 1 | `pkg/middleware/audit_middleware.go` | `AuditMiddleware()` | 中间件入口,捕获请求信息 |
|
||||
| 2 | `pkg/middleware/audit_middleware.go` | `determineAction()` | 根据 HTTP 方法和路径确定操作类型 |
|
||||
| 3 | `pkg/middleware/audit_middleware.go` | `extractResourceInfo()` | 提取资源类型和资源ID |
|
||||
| 4 | `pkg/middleware/audit_middleware.go` | `sanitizeSensitiveData()` | 脱敏处理敏感数据 |
|
||||
| 5 | `internal/service/audit_service.go` | `WriteLog()` | 实现 AuditWriter 接口,按模块路由到不同缓冲区 |
|
||||
| 6 | `internal/service/audit_service.go` | `jenkinsBatchWriter()` | Jenkins专用批量写入协程 |
|
||||
| 7 | `internal/dao/jenkins_audit_log_dao.go` | `BatchCreate()` | Jenkins审计日志批量插入 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 多模块审计日志记录方式
|
||||
|
||||
### 3.1 审计日志表结构
|
||||
|
||||
RMDC 采用**分表存储**策略,每个业务模块有独立的审计日志表,继承公共基础字段并扩展模块特定字段:
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
AuditLog {
|
||||
int64 id PK
|
||||
string module
|
||||
int64 user_id FK
|
||||
string username
|
||||
string action
|
||||
string resource_type
|
||||
string resource_id
|
||||
text details
|
||||
string ip_address
|
||||
string status
|
||||
text error_message
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
JenkinsAuditLog {
|
||||
int64 id PK
|
||||
string organization
|
||||
string repository
|
||||
string branch
|
||||
int build_number
|
||||
string artifact_name
|
||||
int64 artifact_size
|
||||
string artifact_type
|
||||
}
|
||||
|
||||
WatchdogAuditLog {
|
||||
int64 id PK
|
||||
string project_id
|
||||
string project_name
|
||||
text host_info
|
||||
}
|
||||
|
||||
UserAuthAuditLog {
|
||||
int64 id PK
|
||||
string login_type
|
||||
string device_info
|
||||
}
|
||||
|
||||
AuditLog ||--|| JenkinsAuditLog : "继承"
|
||||
AuditLog ||--|| WatchdogAuditLog : "继承"
|
||||
AuditLog ||--|| UserAuthAuditLog : "继承"
|
||||
```
|
||||
|
||||
### 3.2 模块与表的对应关系
|
||||
|
||||
| 模块 | 表名 | 扩展字段 | 典型操作 |
|
||||
|------|------|----------|----------|
|
||||
| Core | `core_audit_logs` | 无 | 系统配置修改、审计日志清理 |
|
||||
| Jenkins | `jenkins_audit_logs` | organization, repository, branch, build_number, artifact_name, artifact_size, artifact_type | 触发构建、同步Jenkins、DCU任务、交付物构建 |
|
||||
| Watchdog | `watchdog_audit_logs` | project_id, project_name, host_info | 主机授权、项目注册 |
|
||||
| UserAuth | `user_auth_audit_logs` | login_type, device_info | 用户创建、角色修改 |
|
||||
|
||||
### 3.3 DAO 管理器架构
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class AuditLogDAOManager {
|
||||
+Core *AuditLogDao
|
||||
+Jenkins *JenkinsAuditLogDao
|
||||
+GetDAO(module string) interface{}
|
||||
}
|
||||
|
||||
class AuditLogDao {
|
||||
-db *gorm.DB
|
||||
+Create(ctx, log) error
|
||||
+BatchCreate(ctx, logs) error
|
||||
+List(ctx, module, page, pageSize) ([]*AuditLog, int64, error)
|
||||
}
|
||||
|
||||
class JenkinsAuditLogDao {
|
||||
-db *gorm.DB
|
||||
+Create(ctx, log) error
|
||||
+BatchCreate(ctx, logs) error
|
||||
+List(ctx, page, pageSize) ([]*JenkinsAuditLog, int64, error)
|
||||
+ListByOrganization(ctx, org, page, pageSize) ([]*JenkinsAuditLog, int64, error)
|
||||
}
|
||||
|
||||
AuditLogDAOManager --> AuditLogDao
|
||||
AuditLogDAOManager --> JenkinsAuditLogDao
|
||||
```
|
||||
|
||||
### 3.4 Jenkins 审计日志写入流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[HTTP 请求到达] --> B{路径包含 /jenkins/ 或 /builds/ 或 /dcu/?}
|
||||
B -->|是| C[AuditMiddleware 捕获请求]
|
||||
B -->|否| D[其他模块处理]
|
||||
|
||||
C --> E[提取 JWT 中的 user_id, username]
|
||||
E --> F[解析路径参数: org, repo, branch]
|
||||
F --> G[determineAction: TRIGGER_BUILD / SYNC_JENKINS / DCU_START]
|
||||
G --> H[构建 audit.AuditLog 对象]
|
||||
|
||||
H --> I[调用 AuditWriter.WriteLog]
|
||||
I --> J[AuditService.WriteLog]
|
||||
|
||||
J --> K{判断模块类型 + DAOManager存在?}
|
||||
K -->|jenkins + 有DAOManager| L[构建 JenkinsAuditLog]
|
||||
K -->|其他| M[构建 AuditLog]
|
||||
|
||||
L --> N[放入 jenkinsLogBuffer]
|
||||
N --> O[jenkinsBatchWriter 批量处理]
|
||||
O --> P[JenkinsAuditLogDao.BatchCreate]
|
||||
P --> Q[(写入 jenkins_audit_logs 表)]
|
||||
|
||||
M --> R[放入 logBuffer]
|
||||
R --> S[batchWriter 批量处理]
|
||||
S --> T[AuditLogDao.BatchCreate]
|
||||
T --> U[(写入 core_audit_logs 表)]
|
||||
|
||||
style C fill:#ff6b6b,stroke:#c92a2a
|
||||
style I fill:#4ecdc4,stroke:#087f5b
|
||||
style Q fill:#ffd43b,stroke:#f08c00
|
||||
style U fill:#ffd43b,stroke:#f08c00
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. AuditWriter 接口实现
|
||||
|
||||
### 4.1 接口定义
|
||||
|
||||
位置: `rmdc-audit-log/pkg/audit/interface.go`
|
||||
|
||||
```go
|
||||
// AuditLog 审计日志结构(公共接口)
|
||||
type AuditLog struct {
|
||||
UserID int64 `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
Action string `json:"action"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
ResourceID string `json:"resource_id"`
|
||||
IPAddress string `json:"ip_address"`
|
||||
Method string `json:"method"`
|
||||
Path string `json:"path"`
|
||||
QueryParams string `json:"query_params"`
|
||||
RequestBody string `json:"request_body"`
|
||||
Duration int64 `json:"duration"`
|
||||
Module string `json:"module,omitempty"` // 显式指定模块(可选)
|
||||
}
|
||||
|
||||
// AuditWriter 审计日志写入接口
|
||||
type AuditWriter interface {
|
||||
// WriteLog 写入审计日志(通用方法,根据Path自动判断模块)
|
||||
WriteLog(log *AuditLog)
|
||||
|
||||
// WriteJenkinsLog 写入Jenkins模块审计日志
|
||||
// 用于需要记录Jenkins专属字段的场景
|
||||
WriteJenkinsLog(log *JenkinsAuditLogInput)
|
||||
}
|
||||
|
||||
// JenkinsAuditLogInput Jenkins审计日志输入结构
|
||||
type JenkinsAuditLogInput struct {
|
||||
// 通用字段
|
||||
UserID int64 `json:"user_id"`
|
||||
Username string `json:"username"`
|
||||
Action string `json:"action"`
|
||||
ResourceType string `json:"resource_type"`
|
||||
ResourceID string `json:"resource_id"`
|
||||
IPAddress string `json:"ip_address"`
|
||||
Details string `json:"details"`
|
||||
|
||||
// Jenkins专属字段
|
||||
Organization string `json:"organization"`
|
||||
Repository string `json:"repository"`
|
||||
Branch string `json:"branch"`
|
||||
BuildNumber int `json:"build_number"`
|
||||
|
||||
// 交付物相关字段
|
||||
ArtifactName string `json:"artifact_name"`
|
||||
ArtifactSize int64 `json:"artifact_size"`
|
||||
ArtifactType string `json:"artifact_type"` // docker_image, gzip, jar等
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 模块判断逻辑
|
||||
|
||||
```go
|
||||
func (s *AuditService) determineModule(path string) string {
|
||||
switch {
|
||||
case strings.Contains(path, "/jenkins/") ||
|
||||
strings.Contains(path, "/builds/") ||
|
||||
strings.Contains(path, "/projects/") ||
|
||||
strings.Contains(path, "/dcu/"):
|
||||
return "jenkins"
|
||||
case strings.Contains(path, "/users/") ||
|
||||
strings.Contains(path, "/auth/") ||
|
||||
strings.Contains(path, "/permissions/"):
|
||||
return "user_auth"
|
||||
case strings.Contains(path, "/watchdog/"):
|
||||
return "watchdog"
|
||||
default:
|
||||
return "core"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 新模块审计日志表添加指南
|
||||
|
||||
如需为新模块添加审计日志表,请按以下步骤操作:
|
||||
|
||||
### 5.1 步骤概览
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[1. 定义Entity] --> B[2. 创建DAO]
|
||||
B --> C[3. 更新DAOManager]
|
||||
C --> D[4. 扩展Service]
|
||||
D --> E[5. 更新模块判断]
|
||||
E --> F[6. 数据库迁移]
|
||||
```
|
||||
|
||||
### 5.2 详细步骤
|
||||
|
||||
#### 步骤1: 定义实体 (Entity)
|
||||
|
||||
位置: `rmdc-audit-log/internal/model/entity/audit_log.go`
|
||||
|
||||
```go
|
||||
// NewModuleAuditLog 新模块审计日志
|
||||
type NewModuleAuditLog struct {
|
||||
AuditLog // 嵌入基础审计日志
|
||||
// 添加模块专属字段
|
||||
CustomField1 string `gorm:"size:255" json:"custom_field_1"`
|
||||
CustomField2 int64 `json:"custom_field_2"`
|
||||
}
|
||||
|
||||
// TableName 指定表名
|
||||
func (NewModuleAuditLog) TableName() string {
|
||||
return "new_module_audit_logs"
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤2: 创建DAO
|
||||
|
||||
位置: `rmdc-audit-log/internal/dao/new_module_audit_log_dao.go`
|
||||
|
||||
```go
|
||||
type NewModuleAuditLogDao struct {
|
||||
db *gorm.DB
|
||||
}
|
||||
|
||||
func NewNewModuleAuditLogDao(db *gorm.DB) *NewModuleAuditLogDao {
|
||||
return &NewModuleAuditLogDao{db: db}
|
||||
}
|
||||
|
||||
func (d *NewModuleAuditLogDao) Create(ctx context.Context, log *entity.NewModuleAuditLog) error {
|
||||
log.Module = "new_module"
|
||||
return d.db.WithContext(ctx).Create(log).Error
|
||||
}
|
||||
|
||||
func (d *NewModuleAuditLogDao) BatchCreate(ctx context.Context, logs []*entity.NewModuleAuditLog) error {
|
||||
if len(logs) == 0 {
|
||||
return nil
|
||||
}
|
||||
for i := range logs {
|
||||
logs[i].Module = "new_module"
|
||||
}
|
||||
return d.db.WithContext(ctx).CreateInBatches(logs, len(logs)).Error
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤3: 更新DAOManager
|
||||
|
||||
位置: `rmdc-audit-log/internal/dao/audit_log_dao_manager.go`
|
||||
|
||||
```go
|
||||
type AuditLogDAOManager struct {
|
||||
Core *AuditLogDao
|
||||
Jenkins *JenkinsAuditLogDao
|
||||
NewModule *NewModuleAuditLogDao // 新增
|
||||
}
|
||||
|
||||
func InitAuditLogDAOManager(db *gorm.DB) (*AuditLogDAOManager, error) {
|
||||
// ...
|
||||
daoManagerInstance = &AuditLogDAOManager{
|
||||
Core: NewAuditLogDao(db),
|
||||
Jenkins: NewJenkinsAuditLogDao(db),
|
||||
NewModule: NewNewModuleAuditLogDao(db), // 新增
|
||||
}
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤4: 扩展Service
|
||||
|
||||
位置: `rmdc-audit-log/internal/service/audit_service.go`
|
||||
|
||||
1. 添加新模块的日志缓冲区
|
||||
2. 添加新模块的批量写入协程
|
||||
3. 在 `WriteLog` 中添加新模块的路由逻辑
|
||||
|
||||
#### 步骤5: 更新模块判断逻辑
|
||||
|
||||
```go
|
||||
func (s *AuditService) determineModule(path string) string {
|
||||
switch {
|
||||
// ... 现有逻辑 ...
|
||||
case strings.Contains(path, "/new-module/"):
|
||||
return "new_module"
|
||||
default:
|
||||
return "core"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 步骤6: 数据库迁移
|
||||
|
||||
位置: `rmdc-core/scripts/init_postgresql.sql`
|
||||
|
||||
```sql
|
||||
-- 新模块审计日志表
|
||||
CREATE TABLE IF NOT EXISTS new_module_audit_logs (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
module VARCHAR(50) DEFAULT 'new_module',
|
||||
user_id INTEGER,
|
||||
username VARCHAR(64),
|
||||
action VARCHAR(64) NOT NULL,
|
||||
resource_type VARCHAR(50),
|
||||
resource_id VARCHAR(255),
|
||||
details JSONB,
|
||||
ip_address INET,
|
||||
status VARCHAR(20),
|
||||
error_message TEXT,
|
||||
created_at TIMESTAMP WITH TIME ZONE DEFAULT CURRENT_TIMESTAMP,
|
||||
-- 模块专属字段
|
||||
custom_field_1 VARCHAR(255),
|
||||
custom_field_2 BIGINT
|
||||
);
|
||||
|
||||
CREATE INDEX idx_new_module_audit_created ON new_module_audit_logs (created_at DESC);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. Jenkins 交付物构建审计日志使用示例
|
||||
|
||||
### 6.1 触发构建时记录审计日志
|
||||
|
||||
位置: `rmdc-jenkins-branch-dac/internal/service/build_service.go`
|
||||
|
||||
```go
|
||||
func (s *BuildService) TriggerBuild(ctx context.Context, req *dto.TriggerBuildRequest) (*dto.TriggerBuildResponse, error) {
|
||||
// ... 构建触发逻辑 ...
|
||||
|
||||
// 记录Jenkins审计日志
|
||||
if s.auditWriter != nil {
|
||||
s.auditWriter.WriteJenkinsLog(&audit.JenkinsAuditLogInput{
|
||||
UserID: getUserIDFromContext(ctx),
|
||||
Username: getUsernameFromContext(ctx),
|
||||
Action: "TRIGGER_BUILD",
|
||||
ResourceType: "jenkins_build",
|
||||
ResourceID: fmt.Sprintf("%s/%s/%s", req.OrganizationFolder, req.RepositoryName, req.BranchName),
|
||||
Organization: req.OrganizationFolder,
|
||||
Repository: req.RepositoryName,
|
||||
Branch: req.BranchName,
|
||||
BuildNumber: latestBuild.Number,
|
||||
})
|
||||
}
|
||||
|
||||
return response, nil
|
||||
}
|
||||
```
|
||||
|
||||
### 6.2 DCU任务完成时记录交付物审计日志
|
||||
|
||||
```go
|
||||
func (s *DCUService) OnDCUTaskComplete(ctx context.Context, task *DCUTask) {
|
||||
// 记录交付物构建完成审计日志
|
||||
if s.auditWriter != nil {
|
||||
s.auditWriter.WriteJenkinsLog(&audit.JenkinsAuditLogInput{
|
||||
UserID: task.UserID,
|
||||
Username: task.Username,
|
||||
Action: "DCU_COMPLETE",
|
||||
ResourceType: "dcu_artifact",
|
||||
ResourceID: task.TaskID,
|
||||
Organization: task.Organization,
|
||||
Repository: task.Repository,
|
||||
Branch: task.Branch,
|
||||
BuildNumber: task.BuildNumber,
|
||||
// 交付物信息
|
||||
ArtifactName: task.ArtifactGzipName,
|
||||
ArtifactSize: task.ArtifactSize,
|
||||
ArtifactType: "gzip",
|
||||
})
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 6.3 获取AuditWriter实例
|
||||
|
||||
在模块初始化时获取 AuditWriter:
|
||||
|
||||
```go
|
||||
import (
|
||||
auditHandler "wdd.io/RMDC/rmdc-audit-log/pkg/handler"
|
||||
"wdd.io/RMDC/rmdc-audit-log/pkg/audit"
|
||||
)
|
||||
|
||||
// 初始化时获取AuditWriter
|
||||
func InitBuildService(auditDB *gorm.DB, ...) *BuildService {
|
||||
auditWriter, err := auditHandler.InitAuditWriter(auditDB)
|
||||
if err != nil {
|
||||
wdd_log.Debug("[WARN] Failed to init audit writer: %v", err)
|
||||
}
|
||||
|
||||
return &BuildService{
|
||||
auditWriter: auditWriter,
|
||||
// ...
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 设计决策与优化
|
||||
|
||||
### 7.1 异步批量写入
|
||||
|
||||
审计日志采用**缓冲区 + 批量写入**策略,不阻塞业务请求:
|
||||
|
||||
```
|
||||
请求处理时间 = 业务逻辑时间
|
||||
审计日志写入 = 后台协程异步批量处理
|
||||
```
|
||||
|
||||
- `logBuffer`: 核心模块日志缓冲区 (容量: 100)
|
||||
- `jenkinsLogBuffer`: Jenkins模块日志缓冲区 (容量: 50)
|
||||
- `userAuthLogBuffer`: 用户认证模块日志缓冲区 (容量: 50)
|
||||
- 批量写入阈值: 10条
|
||||
- 定时刷新间隔: 2秒
|
||||
|
||||
### 7.2 敏感数据脱敏
|
||||
|
||||
`sanitizeSensitiveData()` 函数自动脱敏以下字段:
|
||||
- `password`
|
||||
- `token`
|
||||
- `secret`
|
||||
- `api_key`
|
||||
|
||||
### 7.3 日志清理策略
|
||||
|
||||
通过 `/api/audit/cleanup` 接口支持按保留天数清理旧日志,防止磁盘空间占用过大。
|
||||
|
||||
### 7.4 回退机制
|
||||
|
||||
如果 DAOManager 初始化失败,系统会自动回退到单一 DAO 模式,所有日志写入 `core_audit_logs` 表,保证审计功能可用性。
|
||||
|
||||
---
|
||||
|
||||
## 8. 前端审计日志查询界面
|
||||
|
||||
### 8.1 模块Tab切换
|
||||
|
||||
前端页面通过模块 Tab 切换查询不同表的审计日志:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[All Modules] -->|GET /api/audit/logs| B[(core_audit_logs)]
|
||||
C[Core] -->|GET /api/audit/logs?module=core| B
|
||||
D[Jenkins] -->|GET /api/audit/logs/jenkins| E[(jenkins_audit_logs)]
|
||||
F[User Auth] -->|GET /api/audit/logs/user-auth| G[(user_auth_audit_logs)]
|
||||
```
|
||||
|
||||
### 8.2 API 端点列表
|
||||
|
||||
| 端点 | 方法 | 描述 | 查询表 |
|
||||
|------|------|------|--------|
|
||||
| `/api/audit/logs` | GET | 通用审计日志查询 | core_audit_logs |
|
||||
| `/api/audit/logs/jenkins` | GET | Jenkins专属日志(含专属字段) | jenkins_audit_logs |
|
||||
| `/api/audit/logs/user-auth` | GET | 用户认证专属日志(含专属字段) | user_auth_audit_logs |
|
||||
| `/api/audit/modules/stats` | GET | 各模块日志数量统计 | 所有表 |
|
||||
| `/api/audit/logs/stats` | GET | 审计日志统计(大小、最旧记录) | core_audit_logs |
|
||||
| `/api/audit/cleanup` | DELETE | 清理旧日志 | 所有表 |
|
||||
|
||||
### 8.3 模块专属响应字段
|
||||
|
||||
#### Jenkins 模块
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"module": "jenkins",
|
||||
"username": "admin",
|
||||
"action": "TRIGGER_BUILD",
|
||||
"organization": "Backend",
|
||||
"repository": "cmii-fly-center",
|
||||
"branch": "master",
|
||||
"build_number": 123,
|
||||
"artifact_name": "cmii-fly-center-1.0.0.tar.gz",
|
||||
"artifact_size": 52428800,
|
||||
"artifact_type": "gzip"
|
||||
}
|
||||
```
|
||||
|
||||
#### UserAuth 模块
|
||||
|
||||
```json
|
||||
{
|
||||
"id": 1,
|
||||
"module": "user_auth",
|
||||
"username": "admin",
|
||||
"action": "LOGIN",
|
||||
"login_type": "password",
|
||||
"device_info": "Chrome/Windows"
|
||||
}
|
||||
```
|
||||
|
||||
### 8.4 前端页面功能
|
||||
|
||||
1. **模块Tab切换** - 点击 Tab 动态切换查询不同模块的日志
|
||||
2. **动态表头** - 根据选中模块显示不同列(Jenkins: Organization/Repository/Branch; UserAuth: LoginType)
|
||||
3. **模块筛选** - 当选择特定模块时,显示该模块专属的筛选条件
|
||||
4. **详情弹窗** - 点击日志条目显示完整详情,包含模块专属字段
|
||||
|
||||
---
|
||||
|
||||
**文档版本**: v2.1
|
||||
**编制日期**: 2025-12-12
|
||||
**编制人**: System Architect
|
||||
**更新内容**:
|
||||
- 新增 UserAuth 模块审计日志支持
|
||||
- 新增模块专属审计日志表分表写入架构
|
||||
- 新增 AuditLogDAOManager DAO管理器
|
||||
- 新增 WriteJenkinsLog/WriteUserAuthLog 接口
|
||||
- 新增模块审计日志表添加指南
|
||||
- 新增 Jenkins 交付物构建审计日志使用示例
|
||||
- 新增前端审计日志查询界面设计
|
||||
|
||||
292
8-CMII-RMDC/1-rmdc-system/login-api-specification.md
Normal file
292
8-CMII-RMDC/1-rmdc-system/login-api-specification.md
Normal file
@@ -0,0 +1,292 @@
|
||||
# 登录接口统一定义文档
|
||||
|
||||
## 版本信息
|
||||
- **版本**: v1.0
|
||||
- **创建日期**: 2026-01-15
|
||||
- **最后更新**: 2026-01-15
|
||||
|
||||
## 概述
|
||||
本文档定义了 RMDC 系统登录接口的统一结构体规范,确保前端和后端之间的数据交互一致性。
|
||||
|
||||
## 后端定义 (Go)
|
||||
|
||||
### 文件位置
|
||||
`rmdc-user-auth/internal/model/dto/auth_dto.go`
|
||||
|
||||
### 结构体定义
|
||||
|
||||
#### LoginRequest - 登录请求
|
||||
```go
|
||||
type LoginRequest struct {
|
||||
Username string `json:"username" binding:"required"` // 用户名(中文真实姓名)
|
||||
Password string `json:"password"` // 明文密码(已废弃,保持兼容)
|
||||
EncryptedPassword string `json:"encrypted_password" binding:"required"` // RSA加密后的密码
|
||||
}
|
||||
```
|
||||
|
||||
#### LoginResponse - 登录响应
|
||||
```go
|
||||
type LoginResponse struct {
|
||||
Token string `json:"token"` // JWT令牌
|
||||
User *UserDTO `json:"user"` // 用户信息
|
||||
MustChangePassword bool `json:"must_change_password"` // 是否必须修改密码
|
||||
PasswordExpireDays int `json:"password_expire_days"` // 密码剩余天数(7天内提醒)
|
||||
}
|
||||
```
|
||||
|
||||
#### UserDTO - 用户信息传输对象
|
||||
```go
|
||||
type UserDTO struct {
|
||||
ID int64 `json:"id"` // 用户ID
|
||||
Username string `json:"username"` // 中文真实姓名
|
||||
EnglishUsername string `json:"english_username"` // 英文用户名
|
||||
AvatarID string `json:"avatar_id"` // 头像ID
|
||||
AvatarFrameID string `json:"avatar_frame_id"` // 头像框ID
|
||||
Gender string `json:"gender"` // 性别: male/female
|
||||
Email string `json:"email"` // 邮箱
|
||||
Phone string `json:"phone"` // 手机号
|
||||
ShortNumber string `json:"short_number,omitempty"` // 短号
|
||||
WorkID string `json:"work_id,omitempty"` // 工号
|
||||
GroupName string `json:"group_name,omitempty"` // 所属小组
|
||||
Company string `json:"company"` // 公司名称
|
||||
DevRole string `json:"dev_role"` // 开发角色: backend/frontend/testing/devops
|
||||
Role string `json:"role"` // RMDC系统角色: superadmin/admin/normal/third
|
||||
Status string `json:"status"` // 状态: active/locked/disabled
|
||||
RegisteredByID int64 `json:"registered_by_id"` // 注册人ID
|
||||
CreatedAt time.Time `json:"created_at"` // 注册时间
|
||||
UpdatedAt time.Time `json:"updated_at"` // 更新时间
|
||||
DeletedAt *time.Time `json:"deleted_at,omitempty"` // 删除时间
|
||||
LastLoginAt *time.Time `json:"last_login_at,omitempty"` // 最后登录时间
|
||||
PasswordExpires *time.Time `json:"password_expires,omitempty"` // 密码过期时间
|
||||
}
|
||||
```
|
||||
|
||||
## 前端定义 (TypeScript)
|
||||
|
||||
### 文件位置
|
||||
`frontend/src/types/api.ts`
|
||||
|
||||
### 接口定义
|
||||
|
||||
#### LoginResponse - 登录响应
|
||||
```typescript
|
||||
export interface LoginResponse {
|
||||
token: string // JWT令牌
|
||||
user: User // 用户信息
|
||||
must_change_password: boolean // 是否必须修改密码
|
||||
password_expire_days: number // 密码剩余天数(7天内提醒)
|
||||
}
|
||||
```
|
||||
|
||||
#### User - 用户信息
|
||||
```typescript
|
||||
export interface User {
|
||||
id: number
|
||||
username: string // 中文真实姓名
|
||||
english_username: string // 英文用户名
|
||||
avatar_id: string // 头像ID
|
||||
avatar_frame_id: string // 头像框ID
|
||||
gender: string // 性别: male/female
|
||||
email: string // 邮箱
|
||||
phone: string // 手机号
|
||||
short_number?: string // 短号
|
||||
work_id?: string // 工号
|
||||
group_name?: string // 所属小组
|
||||
company: string // 公司名称
|
||||
dev_role: string // 开发角色: backend/frontend/testing/devops
|
||||
role: string // 用户角色: superadmin/admin/normal/third
|
||||
status: string // 用户状态: active/locked/disabled
|
||||
registered_by_id: number // 注册人ID
|
||||
created_at: string // 注册时间
|
||||
updated_at: string // 更新时间
|
||||
deleted_at?: string // 删除时间
|
||||
last_login_at?: string // 最后登录时间
|
||||
password_expires?: string // 密码过期时间
|
||||
}
|
||||
```
|
||||
|
||||
## API 接口规范
|
||||
|
||||
### 请求端点
|
||||
```
|
||||
POST /api/auth/login
|
||||
```
|
||||
|
||||
### 请求体示例
|
||||
```json
|
||||
{
|
||||
"username": "张三",
|
||||
"encrypted_password": "RSA加密后的密码字符串"
|
||||
}
|
||||
```
|
||||
|
||||
### 响应示例
|
||||
|
||||
#### 成功响应 (HTTP 200)
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"status": 200,
|
||||
"timestamp": "2026-01-15T17:40:00Z",
|
||||
"message": "success",
|
||||
"data": {
|
||||
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
|
||||
"user": {
|
||||
"id": 1,
|
||||
"username": "张三",
|
||||
"english_username": "zhangsan",
|
||||
"avatar_id": "default_1",
|
||||
"avatar_frame_id": "default",
|
||||
"gender": "male",
|
||||
"email": "zhangsan@example.com",
|
||||
"phone": "13800138000",
|
||||
"company": "示例公司",
|
||||
"dev_role": "backend",
|
||||
"role": "admin",
|
||||
"status": "active",
|
||||
"registered_by_id": 1,
|
||||
"created_at": "2026-01-01T00:00:00Z",
|
||||
"updated_at": "2026-01-15T17:40:00Z"
|
||||
},
|
||||
"must_change_password": false,
|
||||
"password_expire_days": 30
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
#### 失败响应 (HTTP 401)
|
||||
```json
|
||||
{
|
||||
"code": 10003,
|
||||
"status": 401,
|
||||
"timestamp": "2026-01-15T17:40:00Z",
|
||||
"message": "用户名或密码错误",
|
||||
"data": null,
|
||||
"error": "invalid credentials"
|
||||
}
|
||||
```
|
||||
|
||||
## 字段映射对照表
|
||||
|
||||
| 后端字段 (Go) | 前端字段 (TypeScript) | 字段说明 | 必填 |
|
||||
|--------------|---------------------|----------|------|
|
||||
| ID | id | 用户ID | ✓ |
|
||||
| Username | username | 中文真实姓名 | ✓ |
|
||||
| EnglishUsername | english_username | 英文用户名 | ✓ |
|
||||
| AvatarID | avatar_id | 头像ID | ✓ |
|
||||
| AvatarFrameID | avatar_frame_id | 头像框ID | ✓ |
|
||||
| Gender | gender | 性别 | ✓ |
|
||||
| Email | email | 邮箱 | ✓ |
|
||||
| Phone | phone | 手机号 | ✓ |
|
||||
| ShortNumber | short_number | 短号 | × |
|
||||
| WorkID | work_id | 工号 | × |
|
||||
| GroupName | group_name | 所属小组 | × |
|
||||
| Company | company | 公司名称 | ✓ |
|
||||
| DevRole | dev_role | 开发角色 | ✓ |
|
||||
| Role | role | 用户角色 | ✓ |
|
||||
| Status | status | 用户状态 | ✓ |
|
||||
| RegisteredByID | registered_by_id | 注册人ID | ✓ |
|
||||
| CreatedAt | created_at | 注册时间 | ✓ |
|
||||
| UpdatedAt | updated_at | 更新时间 | ✓ |
|
||||
| DeletedAt | deleted_at | 删除时间 | × |
|
||||
| LastLoginAt | last_login_at | 最后登录时间 | × |
|
||||
| PasswordExpires | password_expires | 密码过期时间 | × |
|
||||
|
||||
## 关键改进点
|
||||
|
||||
### 1. 统一命名规范
|
||||
- **前后端一致性**: 所有字段名统一使用 snake_case (下划线命名)
|
||||
- **修正**: `avatar_frame` → `avatar_frame_id`(与后端保持一致)
|
||||
|
||||
### 2. 新增字段
|
||||
- `short_number`: 短号(可选)
|
||||
- `work_id`: 工号(可选)
|
||||
- `password_expires`: 密码过期时间(可选)
|
||||
|
||||
### 3. 标准化响应结构
|
||||
- **后端**: 使用 `dto.LoginResponse` 替代 `gin.H` 直接返回
|
||||
- **前端**: 从 `ApiResponse<LoginResponse>` 中提取 `data` 字段
|
||||
|
||||
### 4. 类型安全
|
||||
- 后端使用强类型 DTO 结构体
|
||||
- 前端使用 TypeScript 接口定义
|
||||
- 消除了隐式类型转换的风险
|
||||
|
||||
### 5. 密码安全
|
||||
- 统一使用 RSA 加密传输密码
|
||||
- 移除明文密码支持(保持向后兼容)
|
||||
|
||||
## 使用示例
|
||||
|
||||
### 后端 Handler 实现
|
||||
```go
|
||||
func (h *AuthHandler) Login(c *gin.Context) {
|
||||
var req dto.LoginRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
wdd_res.ResponseErrorWithDetail(c, wdd_res.CodeValidationFail, "请求参数错误", err)
|
||||
return
|
||||
}
|
||||
|
||||
// ... 业务逻辑 ...
|
||||
|
||||
resp := dto.LoginResponse{
|
||||
Token: token,
|
||||
User: userDTO,
|
||||
MustChangePassword: mustChangePassword,
|
||||
PasswordExpireDays: passwordExpireDays,
|
||||
}
|
||||
|
||||
wdd_res.ResponseSuccess(c, resp)
|
||||
}
|
||||
```
|
||||
|
||||
### 前端 Store 实现
|
||||
```typescript
|
||||
async login(username: string, password: string): Promise<boolean> {
|
||||
const requestBody = {
|
||||
username,
|
||||
encrypted_password: await encryptPasswordWithPublicKey(password)
|
||||
}
|
||||
|
||||
const apiResponse = await api.post<LoginResponse>('/auth/login', requestBody)
|
||||
|
||||
if (apiResponse.code !== 0) {
|
||||
console.error('Login failed:', apiResponse.message)
|
||||
return false
|
||||
}
|
||||
|
||||
const response = apiResponse.data
|
||||
this.token = response.token
|
||||
this.user = response.user
|
||||
this.mustChangePassword = response.must_change_password
|
||||
this.passwordExpireDays = response.password_expire_days
|
||||
|
||||
localStorage.setItem('token', this.token)
|
||||
localStorage.setItem('user', JSON.stringify(this.user))
|
||||
|
||||
return true
|
||||
}
|
||||
```
|
||||
|
||||
## 相关文件清单
|
||||
|
||||
### 后端文件
|
||||
- `rmdc-user-auth/internal/model/dto/auth_dto.go` - 登录相关 DTO 定义
|
||||
- `rmdc-user-auth/internal/handler/auth_handler.go` - 登录处理器
|
||||
- `rmdc-user-auth/internal/model/entity/user.go` - 用户实体
|
||||
|
||||
### 前端文件
|
||||
- `frontend/src/types/api.ts` - API 类型定义
|
||||
- `frontend/src/store/auth.ts` - 认证状态管理
|
||||
- `frontend/src/api/index.ts` - API 请求封装
|
||||
|
||||
## 遵循的规范文档
|
||||
- `3-api-development-prompt.md` - API 开发规范
|
||||
- `go-gin-gorm-style.md` - Go/Gin/GORM 编码规范
|
||||
- `vue3-typescript-stye.md` - Vue3/TypeScript 编码规范
|
||||
|
||||
## 版本历史
|
||||
|
||||
| 版本 | 日期 | 变更说明 |
|
||||
|------|------|----------|
|
||||
| v1.0 | 2026-01-15 | 初始版本,统一前后端登录接口定义 |
|
||||
114
8-CMII-RMDC/19-deploy/1-rmdc-deploy.md
Normal file
114
8-CMII-RMDC/19-deploy/1-rmdc-deploy.md
Normal file
@@ -0,0 +1,114 @@
|
||||
## RMDC-K8S 部署方案
|
||||
|
||||
### 构建
|
||||
1. 前提条件
|
||||
1. 已经存在k8s集群
|
||||
2. 已经存在harbor仓库 harbor.wdd.io:8033
|
||||
3. 构建主机 192.168.35.80 已经存在go环境 node环境 docker环境
|
||||
|
||||
|
||||
2. 需要实现的内容,在windwos实现powershell脚本,实现如下的功能
|
||||
1. 将本地的代码通过rsync推送至192.168.35.80的工作目录
|
||||
2. 在192.168.35.80实现代码的编译工作
|
||||
1. 前端使用node构建
|
||||
2. 后端使用go构建
|
||||
3. 构建产物放置于项目目录 rmdc-k8s-deploy/build目录下
|
||||
3. 在192.168.35.80实现dockerfile构建,以下为不同的模块
|
||||
1. 构建的dockerfile放置于项目目录 rmdc-k8s-deploy/dockerfile目录下
|
||||
2. 构建RMDC-Frontend前端代码
|
||||
1. 基础镜像为 harbor.wdd.io:8033/rmdc/nginx:1.27.0
|
||||
2. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-frontend:${日期}
|
||||
3. 前端代码构建需要有生产环境构建的配置
|
||||
4. 前端代码的API调用的HOST 需要根据实际访问的域名进行配置
|
||||
3. 基础后端镜像构建
|
||||
1. 基础镜像为 harbor.wdd.io:8033/rmdc/alpine:3.23.0
|
||||
2. 指定docker的环境变量,时区等信息
|
||||
3. 安装常用的基础工具 ping curl telnet netcat nmap mtr traceroute
|
||||
4. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-backend-base:1.0
|
||||
4. 构建RMDC-Backend后端代码
|
||||
1. 基础镜像为 harbor.wdd.io:8033/rmdc/rmdc-backend-base:1.0
|
||||
2. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-backend:${日期}
|
||||
5. 构建RMDC-watchdog镜像
|
||||
1. 基础镜像使用 harbor.wdd.io:8033/rmdc/rmdc-watchdog-base:1.0
|
||||
1. 参考[Dockerfile.backend-base](rmdc-k8s-deploy/dockerfile/Dockerfile.backend-base), 安装必要的工具
|
||||
2. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-watchdog:${日期}
|
||||
6. 构建RMDC-watchdog-node镜像
|
||||
1. 基础镜像使用 harbor.wdd.io:8033/rmdc/rmdc-watchdog-base:1.0
|
||||
2. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-watchdog-node:${日期}
|
||||
4. 在192.168.35.80实现harbor推送,将构建好的镜像推送至harbor仓库
|
||||
5. 此脚本能够通过参数,指定需要构建的模块
|
||||
1. 前端
|
||||
2. 后端
|
||||
3. RMDC-watchdog
|
||||
4. RMDC-watchdog-node
|
||||
5. RMDC-watchdog-agent
|
||||
|
||||
### K8S-YAML文件
|
||||
1. RMDC组件需要实现的内容
|
||||
1. 部署文件需要放置于项目目录 rmdc-k8s-deploy/rmdc-app目录下
|
||||
2. 命名空间为 cmii-rmdc
|
||||
3. 为RMDC-frontend实现Deployment和Service如果此模块构建,则需要更新该yaml中的Tag如果此模块构建,则需要更新该yaml
|
||||
2. 镜像为 harbor.wdd.io:8033/rmdc/rmdc-frontend:${日期}
|
||||
3. 副本数量为1
|
||||
4. 端口暴露及Service端口
|
||||
3. 为RMDC-backend实现Deployment和Service
|
||||
1. 如果此模块构建,则需要更新该yaml中的Tag
|
||||
2. 镜像为 harbor.wdd.io:8033/rmdc/rmdc-backend:${日期}
|
||||
3. 副本数量为1
|
||||
4. 端口暴露及Service端口
|
||||
5. 如果此模块构建,则需要更新该yaml
|
||||
4. 实现Ingress部分
|
||||
1. Ingress的域名均采用 rmdc.titanium-bullhorses.io
|
||||
2. 最好在一个Ingress文件中实现
|
||||
3. 前端Ingress
|
||||
4. API接口的Ingress
|
||||
2. RMDC-watchdog组件需要实现的内容
|
||||
1. 部署文件需要放置于项目目录 rmdc-k8s-deploy/rmdc-watchdog目录下
|
||||
2. 命名空间为 cmii-rmdc
|
||||
3. 为RMDC-watchdog实现Deployment和Service
|
||||
1. 如果此模块构建,则需要更新该yaml中的Tag
|
||||
2. 镜像为 harbor.wdd.io:8033/rmdc/rmdc-watchdog:${日期}
|
||||
3. 副本数量为1
|
||||
4. 端口暴露及Service端口
|
||||
4. RMDC-watchdog-node组件需要实现的内容
|
||||
1. 如果此模块构建,则需要更新该yaml中的Tag
|
||||
2. 镜像为 harbor.wdd.io:8033/rmdc/rmdc-watchdog-node:${日期}
|
||||
3. 副本数量为1
|
||||
4. 端口暴露及Service端口
|
||||
|
||||
|
||||
## RMDC-watchdog-agent部分
|
||||
部署文件需要放置于项目目录 rmdc-k8s-deploy/rmdc-uav目录下
|
||||
|
||||
### uav后端JAVA的基础镜像
|
||||
1. 提供基于openjdk11 17 21的版本
|
||||
2. 需要能够正确的显示中文日志及字符
|
||||
3. 安装尽可能丰富的基础工具类
|
||||
4. 需要指定JVM的时区为Asia/Shanghai
|
||||
5. 需要设置java的PATH环境变量
|
||||
6. 需要设置JAVA_HOME环境变量
|
||||
7. 端口暴露为 EXPOSE 8080
|
||||
8. 参考为 [Dockerfile-base-java17](rmdc-k8s-deploy/rmdc-uav/base-image/Dockerfile-base-java17)
|
||||
9. 基础镜像需要尽可能的小
|
||||
10. 需要修改使用国内的镜像源
|
||||
11. 最好基于 harbor.wdd.io:8033/rmdc/alpine:3.23.0
|
||||
|
||||
|
||||
#### 不嵌入RMDC-watchdog-agent的时候,
|
||||
1. 使用传统的start_up.sh 即为ENTRYPOINT ["./start_up.sh"]
|
||||
2. 需要构建 镜像名为 harbor.wdd.io:8033/rmdc/openjdk17-base-tools:1.0
|
||||
3. 需要同时 进行Tag为harbor.cdcyy.com.cn/cmii/openjdk17-base-tools:3.0 并且推送该镜像
|
||||
|
||||
|
||||
#### 当嵌入RMDC-watchdog-agent时候
|
||||
1. 需要go进行build 得到RMDC-watchdog-agent的压缩包
|
||||
1. 需要记录构建出来二级制文件,命名规则为 rmdc-watchdog-agent-${日期}
|
||||
2. 构建RMDC-watchdog-agent镜像
|
||||
1. 需要内嵌rmdc-watchdog-agent版本信息的环境变量 RMDC_WATCHDOG_AGENT_VERSION=${日期}
|
||||
2. OpenJDK-17版本
|
||||
1. 基础镜像使用 harbor.wdd.io:8033/rmdc/openjdk17-base-tools:1.0
|
||||
2. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-watchdog-agent-jdk17:1.0
|
||||
3. OpenJDK-11版本
|
||||
1. 基础镜像使用 harbor.wdd.io:8033/rmdc/openjdk11-base-tools:1.0
|
||||
2. 镜像命名为 harbor.wdd.io:8033/rmdc/rmdc-watchdog-agent-jdk11:1.0
|
||||
3. 内嵌RMDC-watchdog-agent的时候, uav后端程序需要使用ENTRYPOINT ["/cmii/cmii-watchdog-agent", "-business-program-type", "java", "-business-program-path", "/cmii/jarfile.jar"]进行启动
|
||||
479
8-CMII-RMDC/19-deploy/RMDC-Postman-Collection.json
Normal file
479
8-CMII-RMDC/19-deploy/RMDC-Postman-Collection.json
Normal file
@@ -0,0 +1,479 @@
|
||||
{
|
||||
"info": {
|
||||
"_postman_id": "rmdc-api-collection-2026",
|
||||
"name": "RMDC API Collection",
|
||||
"description": "RMDC系统API测试集合\n\n## 使用说明\n\n1. 导入此Collection后,首先运行 `Auth > 1. 获取RSA公钥` 请求\n2. 然后运行 `Auth > 2. RSA加密登录` 请求\n3. 登录成功后Token会自动保存,其他请求无需手动配置认证\n\n## 环境变量\n- `baseUrl`: API基础地址,默认 http://localhost:8080\n- `username`: 登录用户名\n- `password`: 登录密码",
|
||||
"schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json"
|
||||
},
|
||||
"auth": {
|
||||
"type": "bearer",
|
||||
"bearer": [
|
||||
{
|
||||
"key": "token",
|
||||
"value": "{{token}}",
|
||||
"type": "string"
|
||||
}
|
||||
]
|
||||
},
|
||||
"event": [
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"type": "text/javascript",
|
||||
"exec": [
|
||||
"// Collection级别的预处理脚本",
|
||||
"// 自动检查token是否存在"
|
||||
]
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"type": "text/javascript",
|
||||
"exec": [
|
||||
"// Collection级别的测试脚本"
|
||||
]
|
||||
}
|
||||
}
|
||||
],
|
||||
"variable": [
|
||||
{
|
||||
"key": "baseUrl",
|
||||
"value": "http://localhost:8080",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "username",
|
||||
"value": "admin",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "password",
|
||||
"value": "supercyy.1",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "token",
|
||||
"value": "",
|
||||
"type": "string"
|
||||
},
|
||||
{
|
||||
"key": "rsaPublicKey",
|
||||
"value": "",
|
||||
"type": "string"
|
||||
}
|
||||
],
|
||||
"item": [
|
||||
{
|
||||
"name": "Auth",
|
||||
"description": "认证相关接口",
|
||||
"item": [
|
||||
{
|
||||
"name": "1. 获取RSA公钥",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"pm.test('获取公钥成功', function () {",
|
||||
" pm.response.to.have.status(200);",
|
||||
"});",
|
||||
"",
|
||||
"var jsonData = pm.response.json();",
|
||||
"if (jsonData.public_key) {",
|
||||
" pm.collectionVariables.set('rsaPublicKey', jsonData.public_key);",
|
||||
" console.log('RSA公钥已保存');",
|
||||
"}"
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/auth/rsa/public-key",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"auth",
|
||||
"rsa",
|
||||
"public-key"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "2. RSA加密登录",
|
||||
"event": [
|
||||
{
|
||||
"listen": "prerequest",
|
||||
"script": {
|
||||
"exec": [
|
||||
"// RSA加密函数 (使用PKCS1v15填充)",
|
||||
"const forge = require('node-forge');",
|
||||
"",
|
||||
"const publicKeyPem = pm.collectionVariables.get('rsaPublicKey');",
|
||||
"const password = pm.collectionVariables.get('password');",
|
||||
"",
|
||||
"if (!publicKeyPem) {",
|
||||
" console.error('请先运行\"获取RSA公钥\"请求');",
|
||||
" throw new Error('RSA公钥未获取');",
|
||||
"}",
|
||||
"",
|
||||
"try {",
|
||||
" // 解析PEM格式的公钥",
|
||||
" const publicKey = forge.pki.publicKeyFromPem(publicKeyPem);",
|
||||
" ",
|
||||
" // 使用RSA-OAEP加密 (SHA-256)",
|
||||
" const encrypted = publicKey.encrypt(password, 'RSA-OAEP', {",
|
||||
" md: forge.md.sha256.create()",
|
||||
" });",
|
||||
" ",
|
||||
" // 转换为Base64",
|
||||
" const encryptedBase64 = forge.util.encode64(encrypted);",
|
||||
" ",
|
||||
" pm.collectionVariables.set('encryptedPassword', encryptedBase64);",
|
||||
" console.log('密码加密成功');",
|
||||
"} catch (e) {",
|
||||
" console.error('RSA加密失败:', e);",
|
||||
" throw e;",
|
||||
"}"
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
},
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"pm.test('登录成功', function () {",
|
||||
" pm.response.to.have.status(200);",
|
||||
"});",
|
||||
"",
|
||||
"var jsonData = pm.response.json();",
|
||||
"",
|
||||
"if (jsonData.token) {",
|
||||
" pm.collectionVariables.set('token', jsonData.token);",
|
||||
" console.log('Token已保存到Collection变量');",
|
||||
" console.log('用户:', jsonData.user?.username);",
|
||||
"}",
|
||||
"",
|
||||
"if (jsonData.must_change_password) {",
|
||||
" console.warn('警告: 密码已过期,需要修改');",
|
||||
"}",
|
||||
"",
|
||||
"if (jsonData.password_expire_days > 0) {",
|
||||
" console.warn('提示: 密码将在 ' + jsonData.password_expire_days + ' 天后过期');",
|
||||
"}"
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"username\": \"{{username}}\",\n \"encrypted_password\": \"{{encryptedPassword}}\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/auth/login",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"auth",
|
||||
"login"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "3. 明文密码登录(备用)",
|
||||
"event": [
|
||||
{
|
||||
"listen": "test",
|
||||
"script": {
|
||||
"exec": [
|
||||
"pm.test('登录成功', function () {",
|
||||
" pm.response.to.have.status(200);",
|
||||
"});",
|
||||
"",
|
||||
"var jsonData = pm.response.json();",
|
||||
"",
|
||||
"if (jsonData.token) {",
|
||||
" pm.collectionVariables.set('token', jsonData.token);",
|
||||
" console.log('Token已保存');",
|
||||
"}"
|
||||
],
|
||||
"type": "text/javascript"
|
||||
}
|
||||
}
|
||||
],
|
||||
"request": {
|
||||
"auth": {
|
||||
"type": "noauth"
|
||||
},
|
||||
"method": "POST",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"username\": \"{{username}}\",\n \"password\": \"{{password}}\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/auth/login",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"auth",
|
||||
"login"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Contacts",
|
||||
"description": "通信录接口",
|
||||
"item": [
|
||||
{
|
||||
"name": "获取通信录列表",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/contacts?page=1&size=20",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"contacts"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "page",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"key": "size",
|
||||
"value": "20"
|
||||
},
|
||||
{
|
||||
"key": "search",
|
||||
"value": "",
|
||||
"disabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "获取联系人详情",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/contacts/1",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"contacts",
|
||||
"1"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Users",
|
||||
"description": "用户管理接口 (需要Admin权限)",
|
||||
"item": [
|
||||
{
|
||||
"name": "获取用户列表",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/users?page=1&size=20",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"users"
|
||||
],
|
||||
"query": [
|
||||
{
|
||||
"key": "page",
|
||||
"value": "1"
|
||||
},
|
||||
{
|
||||
"key": "size",
|
||||
"value": "20"
|
||||
},
|
||||
{
|
||||
"key": "status",
|
||||
"value": "active",
|
||||
"disabled": true
|
||||
},
|
||||
{
|
||||
"key": "search",
|
||||
"value": "",
|
||||
"disabled": true
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "获取用户详情",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/users/1",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"users",
|
||||
"1"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "User Profile",
|
||||
"description": "用户个人接口",
|
||||
"item": [
|
||||
{
|
||||
"name": "修改密码",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"current_password\": \"{{password}}\",\n \"new_password\": \"NewPassword123\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/user/password",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"user",
|
||||
"password"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "更新个人资料",
|
||||
"request": {
|
||||
"method": "PUT",
|
||||
"header": [
|
||||
{
|
||||
"key": "Content-Type",
|
||||
"value": "application/json"
|
||||
}
|
||||
],
|
||||
"body": {
|
||||
"mode": "raw",
|
||||
"raw": "{\n \"avatar_id\": \"default_1\",\n \"avatar_frame_id\": \"default\"\n}"
|
||||
},
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/user/profile",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"user",
|
||||
"profile"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"name": "Permissions",
|
||||
"description": "权限管理接口",
|
||||
"item": [
|
||||
{
|
||||
"name": "获取我的权限树",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/permissions/my-tree/full",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"permissions",
|
||||
"my-tree",
|
||||
"full"
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"name": "获取我的组织列表",
|
||||
"request": {
|
||||
"method": "GET",
|
||||
"header": [],
|
||||
"url": {
|
||||
"raw": "{{baseUrl}}/api/permissions/my-tree/organizations",
|
||||
"host": [
|
||||
"{{baseUrl}}"
|
||||
],
|
||||
"path": [
|
||||
"api",
|
||||
"permissions",
|
||||
"my-tree",
|
||||
"organizations"
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
308
8-CMII-RMDC/2-rmdc-jenkins-dac/1-jenkins-branch-dac-DDS.md
Normal file
308
8-CMII-RMDC/2-rmdc-jenkins-dac/1-jenkins-branch-dac-DDS.md
Normal file
@@ -0,0 +1,308 @@
|
||||
# rmdc-jenkins-branch-dac 详细设计说明书(DDS)
|
||||
|
||||
**模块名称**: rmdc-jenkins-branch-dac
|
||||
**版本**: v1.0
|
||||
**编制日期**: 2026-01-06
|
||||
|
||||
---
|
||||
|
||||
## 1. 模块概述
|
||||
|
||||
### 1.1 模块定位
|
||||
|
||||
rmdc-jenkins-branch-dac 是 RMDC 平台的**Jenkins分支级权限控制与构建管理模块**,负责:
|
||||
|
||||
1. **分支级权限控制(DAC)**:基于自主访问控制模型,实现Organization→Repository→Branch三级资源权限管理
|
||||
2. **Jenkins集成**:封装Jenkins REST API,提供统一的构建触发、状态查询、日志获取等能力
|
||||
3. **构建产物管理**:管理Docker镜像的下载、压缩、上传(DCU)流程,集成MinIO对象存储
|
||||
4. **构建状态追踪**:实时追踪构建进度,提供状态同步和超时检测机制
|
||||
|
||||
### 1.2 核心用户角色
|
||||
|
||||
| 角色 | 权限说明 |
|
||||
|------|----------|
|
||||
| **SuperAdmin** | 全量访问,可管理所有Organization/Repository/Branch |
|
||||
| **Admin** | 拥有分配的权限,可将自有权限分配给Normal/Third用户 |
|
||||
| **Normal** | 拥有分配的权限,只能查看和触发被授权的分支构建 |
|
||||
| **Third** | 第三方人员,权限最受限,仅能查看被授权内容 |
|
||||
|
||||
### 1.3 技术栈
|
||||
|
||||
- **后端**: Go + Gin + GORM
|
||||
- **数据库**: PostgreSQL (主库) + SQLite (DCU模块独立库)
|
||||
- **外部服务**: Jenkins REST API, MinIO对象存储
|
||||
|
||||
---
|
||||
|
||||
## 2. 系统架构
|
||||
|
||||
### 2.1 模块架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "rmdc-core 网关层"
|
||||
Router[Gin Router]
|
||||
AuthMW[AuthMiddleware]
|
||||
PermMW[PermissionMiddleware]
|
||||
end
|
||||
|
||||
subgraph "rmdc-jenkins-branch-dac 模块"
|
||||
subgraph "Handler层"
|
||||
OrgH[OrgHandler]
|
||||
RepoH[RepoHandler]
|
||||
BranchH[BranchHandler]
|
||||
BuildH[BuildHandler]
|
||||
DCUH[DCUHandler]
|
||||
end
|
||||
|
||||
subgraph "Service层"
|
||||
JenkinsS[JenkinsService]
|
||||
BuildS[BuildService]
|
||||
SyncS[SyncService]
|
||||
DCUS[DCUService]
|
||||
TrackerS[BuildTracker]
|
||||
end
|
||||
|
||||
subgraph "DAO层"
|
||||
OrgDAO[OrganizationDAO]
|
||||
RepoDAO[RepositoryDAO]
|
||||
BranchDAO[BranchDAO]
|
||||
BuildDAO[BuildDAO]
|
||||
end
|
||||
|
||||
JenkinsC[JenkinsClient]
|
||||
MinioC[MinioClient]
|
||||
end
|
||||
|
||||
subgraph "外部服务"
|
||||
Jenkins[(Jenkins Server)]
|
||||
MinIO[(MinIO Storage)]
|
||||
end
|
||||
|
||||
Router --> AuthMW --> PermMW
|
||||
PermMW --> OrgH & RepoH & BranchH & BuildH & DCUH
|
||||
|
||||
BuildH --> BuildS --> JenkinsS --> JenkinsC --> Jenkins
|
||||
DCUH --> DCUS --> MinioC --> MinIO
|
||||
|
||||
JenkinsS --> OrgDAO & RepoDAO & BranchDAO & BuildDAO
|
||||
```
|
||||
|
||||
### 2.2 Jenkins层级结构
|
||||
|
||||
```
|
||||
Organization Folder(组织)
|
||||
└── Repository/Project(仓库)
|
||||
└── Branch(分支)
|
||||
└── Build(构建)
|
||||
```
|
||||
|
||||
**URL路径模式**:
|
||||
```
|
||||
/job/{ORG} # 组织
|
||||
/job/{ORG}/job/{REPO} # 仓库
|
||||
/job/{ORG}/job/{REPO}/job/{BRANCH} # 分支
|
||||
/job/{ORG}/job/{REPO}/job/{BRANCH}/{NUM} # 构建
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据模型设计
|
||||
|
||||
### 3.1 核心实体
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
jenkins_organizations ||--o{ jenkins_repositories : contains
|
||||
jenkins_repositories ||--o{ jenkins_branches : contains
|
||||
jenkins_branches ||--o{ jenkins_builds : contains
|
||||
|
||||
jenkins_organizations {
|
||||
int64 id PK
|
||||
string name UK
|
||||
string display_name
|
||||
string url
|
||||
datetime last_sync_at
|
||||
}
|
||||
|
||||
jenkins_repositories {
|
||||
int64 id PK
|
||||
int64 organization_id FK
|
||||
string name
|
||||
string url
|
||||
}
|
||||
|
||||
jenkins_branches {
|
||||
int64 id PK
|
||||
int64 repository_id FK
|
||||
string name
|
||||
int last_build_number
|
||||
string last_build_result
|
||||
}
|
||||
|
||||
jenkins_builds {
|
||||
int64 id PK
|
||||
int64 branch_id FK
|
||||
int build_number
|
||||
string result
|
||||
int64 timestamp
|
||||
int64 duration
|
||||
int64 estimated_duration
|
||||
bool is_building
|
||||
string artifact_docker_image
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API接口规范
|
||||
|
||||
> **设计原则**: 使用RESTful风格,优先使用POST + RequestBody,避免PathVariables和RequestParams
|
||||
|
||||
### 4.1 组织管理接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/jenkins/organizations/list` | POST | 获取组织列表 |
|
||||
| `/api/jenkins/organizations/detail` | POST | 获取组织详情 |
|
||||
| `/api/jenkins/organizations/sync` | POST | 同步Jenkins组织数据 |
|
||||
|
||||
### 4.2 仓库管理接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/jenkins/repositories/list` | POST | 获取仓库列表 |
|
||||
| `/api/jenkins/repositories/detail` | POST | 获取仓库详情 |
|
||||
| `/api/jenkins/repositories/sync` | POST | 同步仓库数据 |
|
||||
| `/api/jenkins/repositories/scan` | POST | 触发仓库扫描 |
|
||||
|
||||
### 4.3 分支管理接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/jenkins/branches/list` | POST | 获取分支列表 |
|
||||
| `/api/jenkins/branches/detail` | POST | 获取分支详情 |
|
||||
| `/api/jenkins/branches/sync` | POST | 同步分支数据 |
|
||||
|
||||
### 4.4 构建管理接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/jenkins/builds/list` | POST | 获取构建列表 |
|
||||
| `/api/jenkins/builds/detail` | POST | 获取构建详情 |
|
||||
| `/api/jenkins/builds/trigger` | POST | 触发构建 |
|
||||
| `/api/jenkins/builds/console` | POST | 获取构建日志 |
|
||||
| `/api/jenkins/builds/sync` | POST | 同步构建数据 |
|
||||
|
||||
### 4.5 DCU接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/dcu/start` | POST | 启动DCU任务 |
|
||||
| `/api/dcu/status` | POST | 查询任务状态 |
|
||||
| `/api/dcu/list` | POST | 查询任务列表 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 分支权限(DAC)设计
|
||||
|
||||
### 5.1 权限模型
|
||||
|
||||
DAC采用**资源-用户-权限**三元组模型,支持三级权限继承:
|
||||
|
||||
| 授权层级 | 继承规则 |
|
||||
|----------|----------|
|
||||
| Organization级 | 自动继承到该组织下所有Repository和Branch |
|
||||
| Repository级 | 自动继承到该仓库下所有Branch |
|
||||
| Branch级 | 最细粒度,不继承 |
|
||||
|
||||
### 5.2 权限类型
|
||||
|
||||
| 权限 | 说明 |
|
||||
|------|------|
|
||||
| `can_view` | 查看权限 |
|
||||
| `can_build` | 构建权限 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 构建状态追踪
|
||||
|
||||
### 6.1 BuildTracker设计
|
||||
|
||||
BuildTracker负责追踪正在进行中的构建,提供超时检测和状态同步:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant User as 用户
|
||||
participant Handler as BuildHandler
|
||||
participant Service as BuildService
|
||||
participant Tracker as BuildTracker
|
||||
participant Jenkins as Jenkins API
|
||||
|
||||
User->>Handler: POST /builds/trigger
|
||||
Handler->>Service: TriggerBuild()
|
||||
Service->>Jenkins: 触发构建
|
||||
Service->>Tracker: TrackBuild(buildId, timeout)
|
||||
Service-->>User: 返回构建号
|
||||
|
||||
loop 后台超时检测(每10秒)
|
||||
Tracker->>Tracker: checkTimeouts()
|
||||
alt 超时
|
||||
Tracker->>Jenkins: 查询最新状态
|
||||
Tracker->>Tracker: 更新数据库
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. DCU(Download-Compress-Upload)流程
|
||||
|
||||
### 7.1 状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> idle: 创建任务
|
||||
idle --> downloading: StartTask()
|
||||
downloading --> compressing: Pull成功
|
||||
compressing --> uploading: 压缩成功
|
||||
uploading --> completed: 上传成功
|
||||
|
||||
downloading --> failed: Pull失败
|
||||
compressing --> failed: 压缩失败
|
||||
uploading --> failed: 上传失败
|
||||
```
|
||||
|
||||
### 7.2 流程说明
|
||||
|
||||
1. **Download**: 从Docker Registry拉取镜像
|
||||
2. **Compress**: 使用gzip压缩镜像tar包
|
||||
3. **Upload**: 上传到MinIO对象存储
|
||||
|
||||
---
|
||||
|
||||
## 8. 错误码定义
|
||||
|
||||
| 错误码 | 说明 |
|
||||
|--------|------|
|
||||
| `JENKINS-001` | Jenkins服务不可用 |
|
||||
| `JENKINS-002` | Jenkins认证失败 |
|
||||
| `JENKINS-003` | Jenkins资源不存在 |
|
||||
| `JENKINS-004` | 构建触发失败 |
|
||||
| `JENKINS-005` | 构建超时 |
|
||||
| `DCU-001` | Docker Pull失败 |
|
||||
| `DCU-002` | 压缩失败 |
|
||||
| `DCU-003` | MinIO上传失败 |
|
||||
| `PERM-001` | 无权限访问该资源 |
|
||||
| `PERM-002` | 无权限执行该操作 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 相关文档
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| [5-RMDC项目权限设计方案.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/5-RMDC项目权限设计方案.md) | 权限设计 |
|
||||
| [8-jenkins项目层级.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/8-jenkins项目层级.md) | Jenkins层级结构 |
|
||||
| [9-JenkinsBuild-流程图.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/9-JenkinsBuild-流程图.md) | 构建流程图 |
|
||||
| [9-rmdc-dcu模块设计方案.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/9-rmdc-dcu模块设计方案.md) | DCU模块设计 |
|
||||
336
8-CMII-RMDC/2-rmdc-jenkins-dac/2-jenkins-branch-dac-prompt.md
Normal file
336
8-CMII-RMDC/2-rmdc-jenkins-dac/2-jenkins-branch-dac-prompt.md
Normal file
@@ -0,0 +1,336 @@
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
请严格遵循系统的详细设计说明书[3-详细设计说明书.md](0-设计方案/3-详细设计说明书.md)
|
||||
|
||||
实现完成前端部分的管理页面-权限管理页面,能够为角色为user的用户设置可以访问,构建的分支
|
||||
1 后端实现接口,查询角色为user的所有用户
|
||||
2 后端需要定期维护一份,最小颗粒度到Organization Folder-Repository-Branch的权限结构,供前端直接调用
|
||||
3 前端设计经典的权限分配页面,可以为角色分配权限
|
||||
4 需要查询展示用户已具备的权限
|
||||
4 需要将用户权限保存至数据库中
|
||||
|
||||
前端-用户页面
|
||||
1 属于该用户权限的Organization Folder-Repository-Branch
|
||||
2 具有查看 构建的权限
|
||||
3 可以针对特定Branch触发构建任务
|
||||
|
||||
上述说明只是基础要求,请丰富功能,增强设计
|
||||
|
||||
|
||||
jenkins的项目层级及调用说明如[5-jenkins项目层级.md](0-设计方案/5-jenkins项目层级.md)所以,其中python的调用代码是正常运行符合要求的。
|
||||
请完全重构项目中Jenkins部分的代码,请完全重构项目中Jenkins部分的代码
|
||||
在本项目中,类似CMII-UAV-Cloud-Backend-GITLAB这类从Gitlab同步过来的Organization Folder是主要来源,获取项目详情需要,仿照python代码进行改造。
|
||||
|
||||
## 修改Jenkins存储的数据结构
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
Jenkins官方的项目层级及调用说明见[5-jenkins项目层级.md](0-设计方案/5-jenkins项目层级.md),采用Organization Folder-Repository-Branch的权限结构,请进行如下的项目修改
|
||||
1 修改数据库jenkins_projects表为 jenkins_organization_folders
|
||||
2 将目前jenkins_repositories表中的repository_name转换存储,转换规则为 cmlc%2FCMII-UAV-Cloud-Web%2Fcloud-platform-armypeople 去除掉 %2F之前的内容,转换为cloud-platform-armypeople
|
||||
3 修改jenkins_branches表中的repository_name字段,转换规则同上
|
||||
4 修改jenkins_builds表中的repository_name字段,转换规则同上
|
||||
5 从JenkinsAPI新获取的数据均需要进行如上的转换修改
|
||||
6 需要修改现有数据库中的数据
|
||||
|
||||
## Jenkins权限
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
目前Jenkins的权限绑定不够精细,需要进行重构修改
|
||||
1. 前提条件,新增或者修改查询接口,能够分层快速获取到特定项目的branch,避免数据爆炸
|
||||
1. 查询所有的Organization Folder
|
||||
2. 查询特定Organization Folder下的所有Repository
|
||||
3. 查询特定Repository下的所有Branch
|
||||
2. 角色具备的最小权限层级 应该到branch级别
|
||||
3. 优化现有的角色权限存储数据库结构
|
||||
1. 能够快速查询出角色拥有的全部权限树结构
|
||||
2. 能够快速判定角色是否拥有特定Organization Folder-Repository-Branch的权限
|
||||
4. 前端获取全量的权限树应该是分层获取的,禁止一次性获取
|
||||
1. 接口见前文所述的查询接口
|
||||
2. 默认获取全部的Organization Folder
|
||||
3. 展开特定Organization Folder权限分支之后,获取特定Organization Folder下的所有Repository
|
||||
4. 展开特定Repository权限分支之后,获取特定Repository下的所有Branch
|
||||
5. 前端权限支持层级权限赋予
|
||||
1. 如可以直接赋予特定Organization Folder的全部权限,前端无需加载之下的Repository和Branch,直接传递给后端,后端检测到该Organization Folder权限时,自动加载之下的Repository和Branch,然后存储至数据库中
|
||||
2. 同理,如可以直接赋予特定Repository的全部权限,前端无需加载之下的Branch,直接传递给后端,后端检测到该Repository权限时,自动加载之下的Branch,然后存储至数据库中
|
||||
6. 权限模板
|
||||
1. 支持将另一个用户的权限一键复制到当前用户
|
||||
2. 后端提供权限复制接口
|
||||
3. 前端页面需要有相应的设计
|
||||
7. 前端页面-管理-用户权限页面
|
||||
1. 双向选择布局
|
||||
1. 左侧面板 - 所有可用权限
|
||||
1. 完整的Jenkins三层树结构(Org→Repo→Branch)
|
||||
2. 可多选分支进行批量添加
|
||||
3. 独立搜索框快速定位
|
||||
2. 中间操作区
|
||||
1. ➡️ 添加权限:选中左侧分支,设置View/Build权限级别后添加
|
||||
2. ⬅️ 移除权限:从右侧移除选中的权限
|
||||
3. 💾 保存:一键保存所有权限变更
|
||||
3. 右侧面板 - 用户已有权限
|
||||
1. 仅显示用户当前拥有的权限
|
||||
2. 显示每个分支的View/Build权限状态
|
||||
3. 支持多选批量移除
|
||||
|
||||
#### 前端编程规范
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
针对@PermissionManager.vue 在此页面中Existing Permissions中,现有的逻辑需要进行修改
|
||||
|
||||
1. 后端权限部分的路由,需要新增接口
|
||||
1. 前端-用户部分-分支项目页面
|
||||
2. 前端-管理部分-用户权限页面
|
||||
3. 需要根据用户拥有的权限,查询出属于自己的Organization Folder-Repository-Branch层级结构
|
||||
2. 此部分权限-分支部分的接口
|
||||
1. 需要认证
|
||||
2. 需要分层获取
|
||||
|
||||
## 用户页面
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
针对前端页面的用户页面部分,进行如下的修改
|
||||
1. 路径为 localhost:5173/user/builds
|
||||
2. 使用如下的API接口,后端的接口已经实现了一部分
|
||||
1. permissions.GET("/my-tree/organizations", permissionHandler.GetMyOrganizations)
|
||||
2. permissions.GET("/my-tree/organizations/:org/repositories", permissionHandler.GetMyRepositories)
|
||||
3. permissions.GET("/my-tree/organizations/:org/repositories/:repo/branches", permissionHandler.GetMyBranches)
|
||||
4. permissions.GET("/my-tree/organizations/:org/repositories/:repo/branches/:branch/builds", permissionHandler.GetMyBranchBuilds)
|
||||
3. 能够仿照Jenkins的客户端,按照层级展示,一层一层知道查看分支的所有构建,单次构建的详情
|
||||
4. 页面设计要美观
|
||||
|
||||
|
||||
### Jenkins构建及日志API
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
Jenkins的构建及日志API的调用说明见[6-jenkins-api-2.md](0-设计方案/6-jenkins-api-2.md),请参考该文档实现如下的内容
|
||||
1. 构建API
|
||||
1. 后端需要实现从Jenkins获取构建信息
|
||||
2. 需要实现触发构建(参数化构建)
|
||||
3. 在本项目中, 后端和前端支持的构建参数均有限
|
||||
2. 日志API
|
||||
1. 后端需要实现从Jenkins获取历史构建日志(全部日志)
|
||||
2. 后端需要实现从Jenkins获取实时构建日志(流式日志)
|
||||
3. 构建状态API
|
||||
1. 后端需要实现从Jenkins获取构建状态,触发构建后,需要实时获取构建状态,直到构建完成或者异常
|
||||
4. 前端 用户页面@UserDashboard.vue
|
||||
1. 实时构建状态
|
||||
1. 构建层级
|
||||
1. Organization Folder
|
||||
2. Repository
|
||||
3. Branch --此级别若展开, 可以实时查看最新Build的构建状态,是构建中,还是构建完成。需要标识构建成功还是构建失败
|
||||
4. Build --此级别若展开, 可以实时查看最新Build的构建状态 可以查看构建的完整日志
|
||||
2. Build 构建详情页面
|
||||
1. 可以实时查看最新Build的构建状态,是构建中,还是构建完成。
|
||||
2. 需要标识构建成功还是构建失败
|
||||
3. 如果是在构建中,需要能够可以查看实时的构建日志
|
||||
4. 如果是构建完成,需要能够查看构建的完整日志
|
||||
5. 日志显示模块
|
||||
1. 需要能够快速清晰的显示日志内容
|
||||
2. 通常情况一个build的完整日志内容大小为100KB,需要能够快速的显示
|
||||
3. 日志内容需要能够快速的滚动
|
||||
4. 日志的字体大小支持调节
|
||||
5. 日志内容支持下载
|
||||
6. 日志显示支持彩色字体显示
|
||||
7. 日志显示支持搜索
|
||||
8. 日志显示支持复制
|
||||
4. Branch页面展开 可以触发构建
|
||||
1. 在特定的分支页面,点击进入构建触发页面
|
||||
2. 构建触发页面,可以查看当前分支的构建参数
|
||||
3. 构建触发页面,可以触发构建
|
||||
4. 触发构建之后,自动调转到Build详情页面
|
||||
|
||||
|
||||
### Jenkins参数化构建
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)
|
||||
为了实现Jenkins的参数化构建,需要实现如下的功能
|
||||
1. 根据Organization Folder名称中包含的关键字,区分加载的参数化构建参数
|
||||
1. Backend
|
||||
2. Web
|
||||
3. Algorithm
|
||||
2. Backend的参数化构建参数
|
||||
"parameters": {
|
||||
"DEPLOY_MODE_STD": "deploy",
|
||||
"DEPLOY_NAME": "cmii-fly-center",
|
||||
"DEPLOY_VERSION": "5.7.0-snapshot",
|
||||
"DEPLOY_BUILD_TARGET": "x86",
|
||||
"DEPLOY_BUILD_LICENCE": "no",
|
||||
"SYS_K8S_NAMESPACE": "dev-flight",
|
||||
"TARGET_JAVA_BASE_IMAGE": "jdk11-base-simple:2.0",
|
||||
"TARGET_JAVA_OPTS": "-Xms256m-Xmx512m-Dlog4j2.formatMsgNoLookups=true"
|
||||
}
|
||||
3. Web的参数化构建参数
|
||||
"parameters": {
|
||||
"DEPLOY_MODE_STD": "deploy",
|
||||
"DEPLOY_NAME": "cmii-uav-platform-lite",
|
||||
"DEPLOY_VERSION": "5.7.0-snapshot",
|
||||
"DEPLOY_BUILD_TARGET": "x86",
|
||||
"DEPLOY_BUILD_LICENCE": "no",
|
||||
"SYS_K8S_NAMESPACE": "dev-flight",
|
||||
"TARGET_JS_THEME": "default",
|
||||
"TARGET_JS_ENV": "dev"
|
||||
}
|
||||
4. 针对上述的构建参数说明如下
|
||||
1. DEPLOY_MODE_STD是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为deploy,用户只能选择一个
|
||||
2. [build image]: 仅执行镜像构建
|
||||
3. [deploy]: = [build image] + [reinstall]
|
||||
4. [reinstall]: 重新安装应用(不会执行镜像的构建)
|
||||
5. [upgrade]: 更新应用(不会执行镜像的构建,仅更新有变化的部分)
|
||||
6. [uninstall]: 卸载应用
|
||||
7. [only dry run]: 测试部署配置,而不真正执行
|
||||
2. DEPLOY_NAME是只读选项,只做显示
|
||||
1. 数据库维护一张表,每一个org repository 对应一个 deploy_name
|
||||
2. 实现后端的查询,参数化构建,自动获取该参数
|
||||
3. 需要实现这个表
|
||||
3. DEPLOY_VERSION是输入框,用户输入
|
||||
4. DEPLOY_BUILD_TARGET是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为x86,用户只能选择一个
|
||||
2. [x86]: x86 架构
|
||||
3. [arm]: arm 架构
|
||||
5. DEPLOY_BUILD_LICENCE是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为no,用户只能选择一个
|
||||
2. [no]: 不需要许可证
|
||||
3. [yes]: 需要许可证
|
||||
6. SYS_K8S_NAMESPACE是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为dev-flight,用户只能选择一个
|
||||
2. [dev-flight]: 开发环境
|
||||
3. [dev]: 开发环境-2
|
||||
4. [dev-operation]: 开发环境-3
|
||||
5. [test]: 测试环境
|
||||
6. [validation]: 测试环境-2
|
||||
7. [feature]: 测试环境-3
|
||||
7. TARGET_JAVA_BASE_IMAGE是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为jdk11-base-simple:2.0,用户只能选择一个
|
||||
2. [jdk11-base-simple:2.0]: jdk11-base-simple:2.0
|
||||
3. [jdk17-base-simple:2.0]: jdk17-base-simple:2.0
|
||||
8. TARGET_JAVA_OPTS是输入框,但是有默认值
|
||||
9. TARGET_JS_THEME是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为default,用户只能选择一个
|
||||
2. [default]: default
|
||||
3. [dark]: dark
|
||||
10. TARGET_JS_ENV是固定的几个可选选项,前端需要做成下拉选择框,唯一选择
|
||||
1. 可选项如下,默认为dev,用户只能选择一个
|
||||
2. [dev]: dev
|
||||
3. [test]: test
|
||||
4. [validation]: validation
|
||||
5. [feature]: feature
|
||||
6. [prod]: prod
|
||||
|
||||
### 用户页面 分支搜索
|
||||
|
||||
### 分支同步 高可用
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md),针对 @[jenkins_servers.go](../backend/internal/service/jenkins_service.go)
|
||||
目前syncRepository()方法 采用的是单线程的同步方式,导致一次分支同步的时间非常长,进行如下修改
|
||||
1. 修改为并发的形式请求,限制并发的请求速率
|
||||
2. 存储数据库,请进行采用单例或者减少数据库操作的次数
|
||||
1. 实际情况,有大量的用户使用会操作数据库,可能导致数据库locked
|
||||
2. 尽量减少数据库的插入次数
|
||||
|
||||
|
||||
## 审计日志
|
||||
编程规范请遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md),针对 @[jenkins_servers.go](../backend/internal/service/jenkins_service.go)
|
||||
请针对系统的审计日志部分,进行如下的修改
|
||||
1. 精简原则
|
||||
1. 只记录操作类日志,修改,新增,删除
|
||||
1. 后期业务会进行拓展,如Jenkins构建,微服务更新,
|
||||
2. 请求参数,quryParm requestbody等均需要被记录
|
||||
2. 不记录登录,查看等普通操作日志
|
||||
3. 不记录user_agent
|
||||
4. 修改detail为path,只记录访问路径
|
||||
2. 性能原则
|
||||
1. 考虑到sqlite3的并发性能
|
||||
2. 考虑到多用户实际使用导致的并发问题
|
||||
3. 审计日志的写入需要考虑不要影响到其他的正常业务
|
||||
3. 功能设计
|
||||
1. 管理页面,能够筛选查询特定用户,特定操作(如Jenkins构建)的详细操作信息
|
||||
2. 能够查看审计日志占用的数据库空间
|
||||
3. 能够删除如3个月、1个月之前的所有审计日志
|
||||
|
||||
#### 页面美化
|
||||
请参考[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)的编程规范,使用vutify的样式对 @PermissionManager.vue 页面进行美化
|
||||
1. 页面功能重构
|
||||
1. 支持筛选框,快速筛选用户
|
||||
1. 获取全部用户的列表
|
||||
2. 分支搜索定位
|
||||
1. @jenkins_service.go 执行全量项目同步时,应该维护一张完整的Organization Folder-Repository-Branch树状结构
|
||||
2. 前端搜索框能够从树接口,快速查找到 Organization Folder-Repository-Branch的定位
|
||||
3. 通用模块,前端有多个地方需要用到此搜索
|
||||
4. @PermissionManager.vue 页面搜索定位到分支之后,权限框应该能依次查询Org-Repo-Branch,然后定位
|
||||
显示到此处
|
||||
5. @UserDashboard.vue 页面应该页 新增搜索框
|
||||
1. 用户登录页面,会加载一次自身拥有权限的 树状结构
|
||||
2. 此页面搜索框,从部分树状结构能够快速定位查找
|
||||
3. 此页面能够根据查找到的定位 快速展示响应的层级
|
||||
6. @ProjectsManagement.vue 页面 也应该新增此搜索方法
|
||||
1. 此页面搜索框,从部分树状结构能够快速定位查找
|
||||
2. 此页面能够根据查找到的定位 快速展示响应的层级
|
||||
7. 考虑复用 /permissions/my-tree/* 接口
|
||||
1. 若可以复用, 请修改为requestBody的形式,不要用路径变量
|
||||
2. 美化页面布局
|
||||
1. 美化Organization Folder-Repository-Branch项目的图标
|
||||
2. 美化此页面的布局,使用vuetify的元素
|
||||
|
||||
|
||||
请参考[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md)的编程规范,使用vutify的样式对 @ProjectsManagement.vue 页面进行修改
|
||||
1. 可以直接使用 @UserDashboard 那一套项目查看体系,可以直接搬过来
|
||||
2. 项目结构优化,可以将通用的模块放置于一起
|
||||
3. 管理员和普通用户,只是可以操作的org-repo-branch的数量不同而已
|
||||
|
||||
|
||||
### 角色信息及注册页面
|
||||
请严格遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md),对用户部分进行如下的修改
|
||||
1. 用户表结构字段
|
||||
1. 用户名 -中文真实姓名
|
||||
2. 英文用户名 - 前端自动通过中文真实姓名转换而来
|
||||
3. 头像ID - 注册页面需要选择头像
|
||||
4. 角色 - 见下文 用户体系
|
||||
4. 性别 - 男/女
|
||||
5. 邮箱 - 和公司VPN注册邮箱相同
|
||||
6. 手机号 - 必填
|
||||
7. 密码 - 自己设定
|
||||
7. 状态 - active locked disabled
|
||||
8. 注册时间 - 自动生成,前端不展示
|
||||
8. 删除时间
|
||||
9. 注册人ID - 由谁注册
|
||||
8. 公司名称
|
||||
9. 开发角色-前端工程师/后端工程师/测试工程师/运维工程师
|
||||
2. 注册页面
|
||||
1. 注册页面注册之后,用户状态默认是locked状态,提示需要管理员审批才能使用
|
||||
2. 注册页面,需要选择头像
|
||||
1. 提供默认的头像svg
|
||||
2. 头像svg保存在前端底层
|
||||
3. 不同角色层级,能够使用的头像不同,高等级的头像更加炫酷
|
||||
3. 不要使用在线头像
|
||||
4. 选择头像之后,前端需要将头像svg对应的ID保存到数据库
|
||||
3. 性别为 下拉选择框
|
||||
4. 邮箱需要检测邮箱格式
|
||||
5. 公司名称
|
||||
6. 开发角色
|
||||
3. 用户体系修改-修改为如下的四个等级
|
||||
1. SuperAdmin 超级管理员
|
||||
1. 程序初始化创建的唯一超级管理员
|
||||
2. 超级管理员头像带有太阳头像框
|
||||
2. Admin 管理员
|
||||
1. 管理员头像带有星星头像框
|
||||
3. Normal 普通用户
|
||||
4. Third 三方人员
|
||||
1. 权限最低
|
||||
4. 管理-用户管理页面 @UserManagement.vue页面
|
||||
1. 需要展示用户完整的信息
|
||||
2. SuperAdmin Admin可以修改角色的信息
|
||||
3. SuperAdmin Admin可以修改用户的状态
|
||||
4. SuperAdmin 可以修改用户的角色
|
||||
|
||||
## 消息中心
|
||||
请严格遵守[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md)和[vue3-typescript-stye.md](0-设计方案/vue3-typescript-stye.md),按照下文的要求设计详细中心模块
|
||||
|
||||
|
||||
# 项目迁移
|
||||
完整的系统设计方案见[2-rmdc-DDS.md](0-设计方案\1-基本框架\2-rmdc-DDS.md) 项目系统架构图见[3-系统设计图-sonnet4.5.md](0-设计方案/3-系统设计图-sonnet4.5.md) 当前项目的结构已经降级为RMDC-jenkins-branch-dac子模块
|
||||
|
||||
后端代码的编程规范说明见[go-gin-gorm-style.md](0-设计方案/go-gin-gorm-style.md),请严格遵守
|
||||
|
||||
请按照项目设计,重构当前的代码结构,要求如下
|
||||
1. 后端项目模块采用的模块名称示例
|
||||
1. wdd.io/RMDC/jenkins-branch-dac
|
||||
2. wdd.io/RMDC/exchange-hub
|
||||
3. wdd.io/RMDC/watchdog-center
|
||||
2. 后端项目模块之间采用replace的方式互引用
|
||||
2. 我已经将之前实现的cmii-uav-watchdog模块复制过来,请按照项目设计说明,进行重构
|
||||
1. C:\Users\wddsh\Documents\IdeaProjects\RMDC\cmii-uav-watchdog 相对独立
|
||||
2. C:\Users\wddsh\Documents\IdeaProjects\RMDC\cmii-uav-watchdog-center 请融合进入RMDC
|
||||
3. 所有的代码我已经重构保存,请放心操作
|
||||
4. 请勿操作.gitignore覆盖的文件
|
||||
330
8-CMII-RMDC/2-rmdc-jenkins-dac/5-RMDC项目权限设计方案.md
Normal file
330
8-CMII-RMDC/2-rmdc-jenkins-dac/5-RMDC项目权限设计方案.md
Normal file
@@ -0,0 +1,330 @@
|
||||
# RMDC 项目权限设计方案
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本文档描述RMDC平台统一权限系统的设计方案,涵盖:
|
||||
- 权限系统架构设计
|
||||
- 模块依赖关系
|
||||
- 接口抽象层设计
|
||||
- 权限校验流程
|
||||
|
||||
---
|
||||
|
||||
## 2. 模块依赖关系
|
||||
|
||||
### 2.1 设计原则
|
||||
|
||||
- **单向依赖**:业务模块不依赖权限模块,权限模块通过接口访问业务数据
|
||||
- **接口抽象**:公共接口定义在 `rmdc-common`,各模块实现具体接口
|
||||
- **依赖注入**:`rmdc-core` 负责注入所有依赖
|
||||
|
||||
### 2.2 依赖关系图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "公共层"
|
||||
Common[rmdc-common<br/>公共接口定义]
|
||||
end
|
||||
|
||||
subgraph "权限层"
|
||||
UserAuth[rmdc-user-auth<br/>权限中心<br/>实现PermissionChecker]
|
||||
end
|
||||
|
||||
subgraph "业务层"
|
||||
Jenkins[rmdc-jenkins-branch-dac<br/>实现ResourceProvider]
|
||||
Watchdog[rmdc-watchdog-center<br/>实现ResourceProvider]
|
||||
Monitor[rmdc-monitor-center<br/>实现ResourceProvider]
|
||||
Delivery[rmdc-delivery-update<br/>实现ResourceProvider]
|
||||
end
|
||||
|
||||
subgraph "核心层"
|
||||
Core[rmdc-core<br/>网关 + 依赖注入]
|
||||
end
|
||||
|
||||
UserAuth --> Common
|
||||
Jenkins --> Common
|
||||
Watchdog --> Common
|
||||
Monitor --> Common
|
||||
Delivery --> Common
|
||||
|
||||
Core --> UserAuth
|
||||
Core --> Jenkins
|
||||
Core --> Watchdog
|
||||
Core --> Monitor
|
||||
Core --> Delivery
|
||||
|
||||
style Common fill:#4ecdc4,stroke:#087f5b
|
||||
style Core fill:#ffd43b,stroke:#f08c00
|
||||
style UserAuth fill:#ff6b6b,stroke:#c92a2a
|
||||
```
|
||||
|
||||
### 2.3 依赖关系表
|
||||
|
||||
| 模块 | 依赖 | 实现接口 |
|
||||
|------|------|----------|
|
||||
| `rmdc-common` | 无 | 定义接口 |
|
||||
| `rmdc-user-auth` | `rmdc-common` | `PermissionChecker` |
|
||||
| `rmdc-jenkins-branch-dac` | `rmdc-common` | `ResourceProvider` |
|
||||
| `rmdc-watchdog-center` | `rmdc-common` | `ResourceProvider` |
|
||||
| `rmdc-core` | 所有上述模块 | - |
|
||||
|
||||
---
|
||||
|
||||
## 3. 权限接口抽象层
|
||||
|
||||
### 3.1 PermissionChecker 接口
|
||||
|
||||
```go
|
||||
// 位置: rmdc-common/pkg/permission/interface.go
|
||||
package permission
|
||||
|
||||
import "context"
|
||||
|
||||
// PermissionChecker 统一权限检查接口
|
||||
type PermissionChecker interface {
|
||||
// CheckPermission 检查用户对资源的权限
|
||||
// @param userID 用户ID
|
||||
// @param resourceType 资源类型: "jenkins_branch", "watchdog_project", "watchdog_host"
|
||||
// @param resource 资源路径: "org/repo/branch" 或 "project_id"
|
||||
// @param action 操作类型: "view", "build", "exec", "manage"
|
||||
CheckPermission(ctx context.Context, userID int64, resourceType, resource, action string) (bool, error)
|
||||
|
||||
// IsSuperAdmin 检查是否为超级管理员
|
||||
IsSuperAdmin(ctx context.Context, userID int64) (bool, error)
|
||||
|
||||
// GetUserRole 获取用户角色
|
||||
GetUserRole(ctx context.Context, userID int64) (string, error)
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 ResourceProvider 接口
|
||||
|
||||
```go
|
||||
// 位置: rmdc-common/pkg/resource/interface.go
|
||||
package resource
|
||||
|
||||
import "context"
|
||||
|
||||
// ResourceProvider 资源提供者接口(各业务模块实现)
|
||||
type ResourceProvider interface {
|
||||
// GetResourceType 返回资源类型标识
|
||||
GetResourceType() string
|
||||
|
||||
// ListResources 列出所有资源(用于权限分配UI)
|
||||
ListResources(ctx context.Context) ([]Resource, error)
|
||||
|
||||
// ListResourcesForUser 列出用户有权限的资源
|
||||
ListResourcesForUser(ctx context.Context, userID int64) ([]Resource, error)
|
||||
|
||||
// ValidateResource 验证资源是否存在
|
||||
ValidateResource(ctx context.Context, resourcePath string) (bool, error)
|
||||
}
|
||||
|
||||
// Resource 资源结构
|
||||
type Resource struct {
|
||||
Type string `json:"type"` // 资源类型
|
||||
Name string `json:"name"` // 资源名称
|
||||
Path string `json:"path"` // 完整路径
|
||||
Children []Resource `json:"children,omitempty"`
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 统一权限校验流程
|
||||
|
||||
### 4.1 校验流程图
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph "请求入口"
|
||||
Request[API请求<br/>携带JWT Token]
|
||||
end
|
||||
|
||||
subgraph "rmdc-core 网关层"
|
||||
Router[Gin Router]
|
||||
AuthMW[AuthMiddleware<br/>1. JWT解析<br/>2. 提取user_id/role]
|
||||
PermMW[PermissionMiddleware<br/>1. SuperAdmin跳过<br/>2. 权限检查]
|
||||
end
|
||||
|
||||
subgraph "rmdc-user-auth 权限中心"
|
||||
PermService[PermissionService]
|
||||
|
||||
subgraph "模块权限检查器"
|
||||
JenkinsChecker[JenkinsPermissionChecker<br/>Jenkins分支权限]
|
||||
WatchdogChecker[WatchdogPermissionChecker<br/>项目/主机权限]
|
||||
end
|
||||
|
||||
subgraph "缓存层"
|
||||
L1[L1: 内存缓存<br/>sync.Map]
|
||||
L2[L2: 数据库缓存<br/>user_permission_trees]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "业务模块"
|
||||
JenkinsHandler[JenkinsHandler<br/>无权限检查逻辑]
|
||||
WatchdogHandler[WatchdogHandler<br/>无权限检查逻辑]
|
||||
end
|
||||
|
||||
subgraph "数据库"
|
||||
PermDB[(user_permissions)]
|
||||
end
|
||||
|
||||
Request --> Router --> AuthMW --> PermMW
|
||||
PermMW -->|SuperAdmin| JenkinsHandler
|
||||
PermMW -->|SuperAdmin| WatchdogHandler
|
||||
PermMW -->|其他角色| PermService
|
||||
|
||||
PermService --> L1
|
||||
L1 -->|未命中| L2
|
||||
L2 -->|未命中| PermDB
|
||||
|
||||
PermService -->|有权限| JenkinsHandler
|
||||
PermService -->|有权限| WatchdogHandler
|
||||
PermService -->|无权限| Request
|
||||
|
||||
style PermMW fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px
|
||||
style PermService fill:#ffd43b,stroke:#f08c00,stroke-width:2px
|
||||
```
|
||||
|
||||
### 4.2 权限检查算法
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start[开始权限检查] --> GetRole[获取用户角色]
|
||||
GetRole --> IsSuperAdmin{superadmin?}
|
||||
|
||||
IsSuperAdmin -->|是| Allow[✅ 允许访问]
|
||||
IsSuperAdmin -->|否| CheckL1[检查L1内存缓存]
|
||||
|
||||
CheckL1 --> L1Hit{缓存命中?}
|
||||
L1Hit -->|是| CheckPerm[检查权限树]
|
||||
L1Hit -->|否| CheckL2[检查L2数据库缓存]
|
||||
|
||||
CheckL2 --> L2Hit{缓存命中?}
|
||||
L2Hit -->|是| UpdateL1[更新L1缓存]
|
||||
L2Hit -->|否| BuildTree[从权限表构建权限树]
|
||||
|
||||
UpdateL1 --> CheckPerm
|
||||
BuildTree --> SaveL2[保存到L2缓存]
|
||||
SaveL2 --> UpdateL1
|
||||
|
||||
CheckPerm --> HasPerm{有权限?}
|
||||
HasPerm -->|是| Allow
|
||||
HasPerm -->|否| Deny[❌ 拒绝访问]
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 角色权限模型
|
||||
|
||||
### 5.1 角色定义
|
||||
|
||||
| 角色 | 常量 | 说明 |
|
||||
|------|------|------|
|
||||
| **超级管理员** | `superadmin` | 拥有全部权限,可管理所有用户和资源 |
|
||||
| **管理员** | `admin` | 拥有分配的权限,可将自有权限分配给normal/third |
|
||||
| **普通人员** | `normal` | 拥有分配的权限,无分配能力 |
|
||||
| **三方人员** | `third` | 拥有分配的权限,无分配能力,权限受限最严格 |
|
||||
|
||||
### 5.2 模块级权限
|
||||
|
||||
#### Jenkins分支权限
|
||||
|
||||
| 资源类型 | 权限类型 | 说明 |
|
||||
|----------|----------|------|
|
||||
| Organization | can_view, can_build | 组织级权限,自动继承到子仓库/分支 |
|
||||
| Repository | can_view, can_build | 仓库级权限,自动继承到子分支 |
|
||||
| Branch | can_view, can_build | 分支级权限,最细粒度 |
|
||||
|
||||
#### Watchdog项目权限
|
||||
|
||||
| 资源类型 | 权限类型 | 说明 |
|
||||
|----------|----------|------|
|
||||
| Project | can_view, can_manage | 项目级权限 |
|
||||
| Host | can_view, can_exec | 主机操作权限 |
|
||||
| Namespace | can_view, can_deploy | K8s命名空间权限 |
|
||||
|
||||
### 5.3 权限分配规则
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
SuperAdmin[SuperAdmin] -->|可分配| Admin
|
||||
SuperAdmin -->|可分配| Normal
|
||||
SuperAdmin -->|可分配| Third
|
||||
|
||||
Admin -->|可分配自有权限| Normal
|
||||
Admin -->|可分配自有权限| Third
|
||||
|
||||
style SuperAdmin fill:#ff6b6b
|
||||
style Admin fill:#ffd43b
|
||||
style Normal fill:#4ecdc4
|
||||
style Third fill:#a9e34b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据库设计
|
||||
|
||||
### 6.1 统一权限表
|
||||
|
||||
```sql
|
||||
CREATE TABLE user_permissions (
|
||||
id BIGSERIAL PRIMARY KEY,
|
||||
user_id BIGINT NOT NULL,
|
||||
resource_type VARCHAR(50) NOT NULL, -- 'jenkins_branch', 'watchdog_project'
|
||||
resource_path VARCHAR(255) NOT NULL, -- 'org/repo/branch' or 'project_id'
|
||||
permission_level VARCHAR(20), -- 'org', 'repo', 'branch', 'project'
|
||||
can_view BOOLEAN DEFAULT FALSE,
|
||||
can_build BOOLEAN DEFAULT FALSE, -- Jenkins特有
|
||||
can_exec BOOLEAN DEFAULT FALSE, -- Watchdog特有
|
||||
can_manage BOOLEAN DEFAULT FALSE,
|
||||
granted_by BIGINT,
|
||||
created_at TIMESTAMP DEFAULT NOW(),
|
||||
updated_at TIMESTAMP DEFAULT NOW(),
|
||||
|
||||
UNIQUE(user_id, resource_type, resource_path),
|
||||
INDEX idx_user_resource (user_id, resource_type)
|
||||
);
|
||||
```
|
||||
|
||||
### 6.2 权限树缓存表
|
||||
|
||||
```sql
|
||||
CREATE TABLE user_permission_trees (
|
||||
user_id BIGINT PRIMARY KEY,
|
||||
tree JSON NOT NULL, -- 完整权限树JSON
|
||||
version BIGINT DEFAULT 0, -- 版本号
|
||||
updated_at TIMESTAMP DEFAULT NOW()
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. API设计
|
||||
|
||||
### 7.1 用户权限查询API
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/permissions/my-tree/organizations` | GET | 获取当前用户的组织列表 |
|
||||
| `/api/permissions/my-tree/repositories` | POST | 获取当前用户的仓库列表 |
|
||||
| `/api/permissions/my-tree/branches` | POST | 获取当前用户的分支列表 |
|
||||
| `/api/permissions/my-tree/full` | GET | 获取完整权限树 |
|
||||
|
||||
### 7.2 权限管理API (Admin)
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/permissions/tree` | GET | 获取系统权限树 |
|
||||
| `/api/permissions/:userId` | GET | 获取用户权限详情 |
|
||||
| `/api/permissions/assign` | POST | 分配权限 |
|
||||
| `/api/permissions/copy` | POST | 复制权限 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 文档版本
|
||||
|
||||
| 版本 | 日期 | 修改内容 |
|
||||
|------|------|----------|
|
||||
| v1.0 | 2025-12-10 | 初始版本 |
|
||||
165
8-CMII-RMDC/2-rmdc-jenkins-dac/8-jenkins-api-2.md
Normal file
165
8-CMII-RMDC/2-rmdc-jenkins-dac/8-jenkins-api-2.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Jenkins Organization Folder REST API 接口文档
|
||||
|
||||
Organization Folder 是 Jenkins 中用于自动扫描整个组织(如 GitHub Organization、GitLab Group、Bitbucket Team)并为每个仓库自动创建 Multibranch Pipeline 的项目类型 。[1]
|
||||
|
||||
***
|
||||
|
||||
## URL 层级结构
|
||||
|
||||
Organization Folder 比普通 Multibranch Pipeline 多一层嵌套,其层级结构为 :[2][3]
|
||||
|
||||
```
|
||||
{JENKINS_URL}
|
||||
└── /job/{ORG_FOLDER_NAME} ← Organization Folder 层
|
||||
└── /job/{REPO_NAME} ← Multibranch Pipeline 层(仓库)
|
||||
└── /job/{BRANCH_NAME} ← 分支层
|
||||
└── /{BUILD_NUMBER} ← 构建层
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
## 一、获取组织与仓库信息
|
||||
|
||||
### 1.1 获取 Organization Folder 下所有仓库
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/api/json` |
|
||||
| **返回内容** | 该组织下所有已扫描的仓库列表(即 Multibranch Pipeline 列表)|
|
||||
|
||||
**常用参数**:
|
||||
```
|
||||
?tree=jobs[name,url,_class]&depth=1
|
||||
```
|
||||
|
||||
### 1.2 获取某仓库下所有分支
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/api/json` |
|
||||
| **返回内容** | 该仓库下所有分支及其 Job 信息 |
|
||||
|
||||
**示例请求**:
|
||||
```
|
||||
GET {JENKINS_URL}/job/my-github-org/job/my-repo/api/json?tree=jobs[name,url,lastBuild[number,result]]
|
||||
```
|
||||
|
||||
### 1.3 获取某分支的所有构建信息
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/job/{BRANCH_NAME}/api/json` |
|
||||
| **常用参数** | `?tree=builds[number,result,timestamp,duration]&depth=1` |
|
||||
|
||||
> **注意**:分支名中的 `/` 需要编码为 `%2F`,例如 `feature/login` → `feature%2Flogin`
|
||||
|
||||
***
|
||||
|
||||
## 二、触发分支构建
|
||||
|
||||
### 2.1 无参数构建
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `POST {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/job/{BRANCH_NAME}/build` |
|
||||
| **认证** | 需要 Basic Auth(用户名 + API Token)|
|
||||
|
||||
### 2.2 带参数构建
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `POST {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/job/{BRANCH_NAME}/buildWithParameters` |
|
||||
| **参数传递** | Query String 或 Form Data |
|
||||
|
||||
**示例**:
|
||||
```
|
||||
POST {JENKINS_URL}/job/my-github-org/job/my-repo/job/main/buildWithParameters?ENV=production&VERSION=1.0.0
|
||||
```
|
||||
|
||||
### 2.3 获取构建号
|
||||
|
||||
构建触发后,从 `Location` Header 获取队列 ID,再查询实际构建号:
|
||||
|
||||
| 步骤 | 请求地址 |
|
||||
|-----|---------|
|
||||
| 获取队列项 | 响应 Header `Location` → `{JENKINS_URL}/queue/item/{QUEUE_ID}/` |
|
||||
| 查询构建号 | `GET {JENKINS_URL}/queue/item/{QUEUE_ID}/api/json` |
|
||||
| 返回字段 | `executable.number` 即为构建号 |
|
||||
|
||||
***
|
||||
|
||||
## 三、实时查看 Console 输出
|
||||
|
||||
### 3.1 获取完整日志
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/job/{BRANCH_NAME}/{BUILD_NUMBER}/consoleText` |
|
||||
| **返回格式** | 纯文本 |
|
||||
|
||||
### 3.2 增量实时获取
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **请求地址** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/job/{BRANCH_NAME}/{BUILD_NUMBER}/logText/progressiveText?start={OFFSET}` |
|
||||
| **响应 Header** | `X-Text-Size`(下次偏移量)、`X-More-Data`(是否继续)|
|
||||
|
||||
***
|
||||
|
||||
## 四、组织扫描操作
|
||||
|
||||
### 4.1 触发组织扫描(发现新仓库/分支)
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **扫描整个组织** | `POST {JENKINS_URL}/job/{ORG_FOLDER_NAME}/build` |
|
||||
| **扫描单个仓库** | `POST {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/build` |
|
||||
|
||||
扫描操作会检测新增/删除的仓库和分支,并自动更新 Jenkins Job 结构 。[1]
|
||||
|
||||
### 4.2 查看扫描日志
|
||||
|
||||
| 项目 | 说明 |
|
||||
|-----|------|
|
||||
| **组织扫描日志** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/computation/consoleText` |
|
||||
| **仓库扫描日志** | `GET {JENKINS_URL}/job/{ORG_FOLDER_NAME}/job/{REPO_NAME}/indexing/consoleText` |
|
||||
|
||||
***
|
||||
|
||||
## 五、完整 URL 路径汇总
|
||||
|
||||
| 功能 | 请求方法 | URL 模板 |
|
||||
|-----|---------|---------|
|
||||
| 组织下所有仓库 | GET | `/job/{ORG}/api/json` |
|
||||
| 仓库下所有分支 | GET | `/job/{ORG}/job/{REPO}/api/json` |
|
||||
| 分支构建列表 | GET | `/job/{ORG}/job/{REPO}/job/{BRANCH}/api/json` |
|
||||
| 单次构建详情 | GET | `/job/{ORG}/job/{REPO}/job/{BRANCH}/{NUM}/api/json` |
|
||||
| 触发分支构建 | POST | `/job/{ORG}/job/{REPO}/job/{BRANCH}/build` |
|
||||
| 带参数构建 | POST | `/job/{ORG}/job/{REPO}/job/{BRANCH}/buildWithParameters` |
|
||||
| 完整日志 | GET | `/job/{ORG}/job/{REPO}/job/{BRANCH}/{NUM}/consoleText` |
|
||||
| 增量日志 | GET | `/job/{ORG}/job/{REPO}/job/{BRANCH}/{NUM}/logText/progressiveText?start={OFFSET}` |
|
||||
| 扫描组织 | POST | `/job/{ORG}/build` |
|
||||
| 扫描仓库 | POST | `/job/{ORG}/job/{REPO}/build` |
|
||||
|
||||
> **特殊字符处理**:分支名中的 `/` 编码为 `%2F`,`#` 编码为 `%23`
|
||||
|
||||
[1](https://www.jenkins.io/doc/book/pipeline/pipeline-as-code/)
|
||||
[2](https://plugins.jenkins.io/branch-api/)
|
||||
[3](https://github.com/jenkinsci/branch-api-plugin)
|
||||
[4](https://www.jenkins.io/doc/book/using/remote-access-api/)
|
||||
[5](https://note.com/wa_k77/n/nad2af1ac6d95)
|
||||
[6](https://stackoverflow.com/questions/55260693/jenkins-create-folder-with-rest-api-in-groovy-script)
|
||||
[7](https://www.postman.com/api-evangelist/jenkins/folder/cu1b5xc/organization)
|
||||
[8](https://www.kaizenprogrammer.com/entry/2017/03/20/130721)
|
||||
[9](https://stackoverflow.com/questions/51428735/list-all-folders-under-jenkins-with-their-path)
|
||||
[10](https://jenkins-job-builder.readthedocs.io/en/latest/project_githuborg.html)
|
||||
[11](https://stackoverflow.com/questions/44054789/in-jenkins-how-to-build-job-which-is-inside-folder-using-rest-api)
|
||||
[12](https://www.youtube.com/watch?v=BcUSfG4A9AI)
|
||||
[13](https://stackoverflow.com/questions/38507358/how-to-use-jenkins-github-organization-folder-with-github-protected-branches)
|
||||
[14](https://github.com/jenkinsci/folder-auth-plugin/blob/master/docs/rest-api.adoc)
|
||||
[15](https://plugins.jenkins.io/cloudbees-folder/)
|
||||
[16](https://community.jenkins.io/t/failing-to-build-in-an-github-organization-folder-repo/31760)
|
||||
[17](https://qiita.com/Sho2010@github/items/2a9c13d2f67e754cfb4f)
|
||||
[18](https://stackoverflow.com/questions/37615638/specify-the-git-url-location-of-jenkinsfile-in-a-github-organization-job)
|
||||
[19](https://github.com/jenkinsci/branch-api-plugin/blob/master/src/main/java/jenkins/branch/OrganizationFolder.java)
|
||||
[20](https://jenkinsci.github.io/job-dsl-plugin/)
|
||||
208
8-CMII-RMDC/2-rmdc-jenkins-dac/8-jenkins项目层级.md
Normal file
208
8-CMII-RMDC/2-rmdc-jenkins-dac/8-jenkins项目层级.md
Normal file
@@ -0,0 +1,208 @@
|
||||
根据Jenkins官方文档,Jenkins的实际层级组织结构如下:
|
||||
|
||||
## Jenkins的实际层级结构
|
||||
|
||||
Jenkins在使用**Organization Folder**(组织文件夹)功能时,采用的层级结构为:
|
||||
|
||||
```
|
||||
Organization Folder(组织)
|
||||
└── Repository/Project(仓库/项目)
|
||||
└── Branch(分支)
|
||||
└── Build(构建)
|
||||
```
|
||||
|
||||
官方文档中明确展示的层级示例:
|
||||
|
||||
```
|
||||
+--- GitHub Organization
|
||||
+--- Project 1
|
||||
+--- master
|
||||
+--- feature-branch-a
|
||||
+--- feature-branch-b
|
||||
+--- Project 2
|
||||
+--- master
|
||||
+--- pull-request-1
|
||||
```
|
||||
|
||||
## 关键区别
|
||||
|
||||
"Projects → Repository"实际上在Jenkins中是同一层级的概念。 Jenkins使用以下术语:
|
||||
|
||||
- **Organization Folder**:对应GitHub Organization、Bitbucket Team、GitLab Organization等组织级别
|
||||
- **Multibranch Pipeline Project**:对应单个代码仓库,会自动为该仓库的所有包含Jenkinsfile的分支创建构建任务
|
||||
- **Branch**:具体的分支或Pull Request
|
||||
- **Build**:针对某个分支的具体构建执行
|
||||
|
||||
## 实现逻辑
|
||||
|
||||
Jenkins通过以下机制实现这种层级:
|
||||
|
||||
1. **Multibranch Pipeline**自动扫描单个仓库,为每个包含Jenkinsfile的分支创建Pipeline任务
|
||||
2. **Organization Folder**自动扫描整个组织,为每个符合条件的仓库创建Multibranch Pipeline项目
|
||||
3. 当分支或仓库被创建/删除时,可以通过webhook或定期扫描自动更新Jenkins中的任务结构
|
||||
|
||||
因此,准确的表述应该是:**Organization → Repository(Project) → Branch → Build**,其中Repository和Project是等价的概念。
|
||||
|
||||
|
||||
根据Jenkins官方文档和API最佳实践,您可以通过以下方式获取GitLab Organization Folder的所有分支和构建信息:
|
||||
|
||||
## 推荐方案:使用Tree参数的单次API调用
|
||||
|
||||
最高效的方式是使用`tree`参数,通过一次API调用获取所有数据:
|
||||
|
||||
```bash
|
||||
https://<JENKINS_HOST>/job/<ORGANIZATION_FOLDER_NAME>/api/json?tree=jobs[name,url,jobs[name,url,builds[number,result,timestamp,duration,url]]]
|
||||
```
|
||||
|
||||
### 参数说明
|
||||
|
||||
- **第一层`jobs`**:Organization Folder下的所有Repository(Multibranch Pipeline项目)
|
||||
- **第二层`jobs`**:每个Repository下的所有Branch(分支作为子job存在)
|
||||
- **`builds`**:每个Branch的构建历史
|
||||
|
||||
### 限制返回的构建数量
|
||||
|
||||
如果构建历史过多,可以限制返回数量(例如最近50次):
|
||||
|
||||
```bash
|
||||
https://<JENKINS_HOST>/job/<ORGANIZATION_FOLDER_NAME>/api/json?tree=jobs[name,url,jobs[name,url,builds[number,result,timestamp,duration,url]{0,50}]]
|
||||
```
|
||||
|
||||
`{0,50}`表示只返回最近50次构建。
|
||||
|
||||
## API调用结构层次
|
||||
|
||||
基于Organization Folder的结构,API调用路径遵循以下层级:
|
||||
|
||||
1. **Organization Folder** → `/job/<FOLDER_NAME>`
|
||||
2. **Repository (Multibranch Pipeline)** → `/job/<FOLDER_NAME>/job/<REPO_NAME>`
|
||||
3. **Branch** → `/job/<FOLDER_NAME>/job/<REPO_NAME>/job/<BRANCH_NAME>`
|
||||
4. **Build** → `/job/<FOLDER_NAME>/job/<REPO_NAME>/job/<BRANCH_NAME>/<BUILD_NUMBER>`
|
||||
|
||||
## 完整示例
|
||||
|
||||
假设您的Organization Folder名为`CMII-UAV-Cloud-Backend-GITLAB`:
|
||||
|
||||
```bash
|
||||
# 获取所有仓库、分支和最近50次构建
|
||||
curl -u username:api_token \
|
||||
"https://<JENKINS_HOST>/job/CMII-UAV-Cloud-Backend-GITLAB/api/json?tree=jobs[name,url,jobs[name,url,builds[number,result,timestamp,duration,url]{0,50}]]"
|
||||
```
|
||||
|
||||
## 性能优化建议
|
||||
|
||||
1. **避免使用`depth`参数**:`depth`会返回大量不必要的数据,建议使用`tree`参数精确指定所需字段
|
||||
2. **限制构建数量**:使用`{0,N}`语法限制每个分支返回的构建数量
|
||||
3. **按需获取字段**:只请求必要的字段,减少数据传输量
|
||||
|
||||
|
||||
分析您的API调用性能问题,主要原因是**Jenkins需要遍历整个Organization Folder的所有仓库、分支和构建数据**,即使您只请求了前3条记录。 以下是性能瓶颈和优化方案:
|
||||
|
||||
## 性能瓶颈分析
|
||||
|
||||
### 主要问题
|
||||
|
||||
1. **一次性加载所有数据**:Jenkins API的`tree`参数在返回前必须先遍历整个数据树结构,即使使用`{0,3}`限制构建数量
|
||||
2. **Organization Folder扫描开销**:每个多分支项目的分支发现和元数据加载都会产生大量I/O操作
|
||||
3. **深层嵌套查询**:三层嵌套(Organization → Repository → Branch → Builds)导致指数级的数据查询
|
||||
|
||||
### 为什么`{0,3}`不起作用
|
||||
|
||||
`{0,3}`只限制**每个分支**返回的构建数量,但Jenkins仍需要:
|
||||
- 遍历所有Repository
|
||||
- 扫描每个Repository的所有分支
|
||||
- 为每个分支加载元数据
|
||||
|
||||
## 高效解决方案
|
||||
|
||||
### 方案1:分层逐级获取(推荐)
|
||||
|
||||
不要一次性获取所有层级,而是分步骤获取:
|
||||
|
||||
#### 步骤1:获取所有Repository
|
||||
|
||||
```bash
|
||||
curl -g -u username:token \
|
||||
"http://192.168.34.41:27081/job/CMII-UAV-Cloud-Backend-GITLAB/api/json?tree=jobs[name,url]"
|
||||
```
|
||||
|
||||
返回速度快,只获取Repository列表。
|
||||
|
||||
#### 步骤2:并行获取每个Repository的分支
|
||||
|
||||
```bash
|
||||
# 对每个Repository
|
||||
curl -g -u username:token \
|
||||
"http://192.168.34.41:27081/job/CMII-UAV-Cloud-Backend-GITLAB/job/<REPO_NAME>/api/json?tree=jobs[name,url,lastBuild[number,result,timestamp,duration]]"
|
||||
```
|
||||
|
||||
使用`lastBuild`只获取最新构建,而非所有构建历史。
|
||||
|
||||
#### 步骤3:按需获取具体分支的构建历史
|
||||
|
||||
```bash
|
||||
curl -g -u username:token \
|
||||
"http://192.168.34.41:27081/job/CMII-UAV-Cloud-Backend-GITLAB/job/<REPO_NAME>/job/<BRANCH_NAME>/api/json?tree=builds[number,result,timestamp,duration]{0,10}"
|
||||
```
|
||||
|
||||
### 方案2:只获取关键信息
|
||||
|
||||
如果只需要统计数据,使用最小化字段:
|
||||
|
||||
```bash
|
||||
curl -g -u username:token \
|
||||
"http://192.168.34.41:27081/job/CMII-UAV-Cloud-Backend-GITLAB/api/json?tree=jobs[name,jobs[name,lastBuild[number,result,timestamp]]]"
|
||||
```
|
||||
|
||||
关键优化点:
|
||||
- 移除`url`字段(可自行构造)
|
||||
- 只用`lastBuild`替代`builds[]`
|
||||
- 减少返回字段数量
|
||||
|
||||
### 方案3:使用Python脚本异步并发获取
|
||||
|
||||
```python
|
||||
import asyncio
|
||||
import aiohttp
|
||||
from aiohttp import BasicAuth
|
||||
|
||||
async def fetch_repos(session, base_url, auth):
|
||||
url = f"{base_url}/api/json?tree=jobs[name]"
|
||||
async with session.get(url, auth=auth) as resp:
|
||||
data = await resp.json()
|
||||
return [job['name'] for job in data.get('jobs', [])]
|
||||
|
||||
async def fetch_repo_branches(session, base_url, repo_name, auth):
|
||||
url = f"{base_url}/job/{repo_name}/api/json?tree=jobs[name,lastBuild[number,result,timestamp]]"
|
||||
async with session.get(url, auth=auth) as resp:
|
||||
data = await resp.json()
|
||||
return {
|
||||
'repo': repo_name,
|
||||
'branches': data.get('jobs', [])
|
||||
}
|
||||
|
||||
async def main():
|
||||
base_url = "http://192.168.34.41:27081/job/CMII-UAV-Cloud-Backend-GITLAB"
|
||||
auth = BasicAuth('zeaslity', '114f14f0c48fd9dfb4d3092426b0f72913')
|
||||
|
||||
async with aiohttp.ClientSession() as session:
|
||||
# 1. 获取所有仓库
|
||||
repos = await fetch_repos(session, base_url, auth)
|
||||
print(f"找到 {len(repos)} 个仓库")
|
||||
|
||||
# 2. 并发获取所有仓库的分支信息
|
||||
tasks = [fetch_repo_branches(session, base_url, repo, auth) for repo in repos]
|
||||
results = await asyncio.gather(*tasks)
|
||||
|
||||
# 3. 输出结果
|
||||
for result in results:
|
||||
print(f"\n仓库: {result['repo']}")
|
||||
for branch in result['branches']:
|
||||
build = branch.get('lastBuild', {})
|
||||
if build != None:
|
||||
print(f" 分支: {branch['name']}, 最新构建: #{build.get('number', 'N/A')}")
|
||||
|
||||
asyncio.run(main())
|
||||
```
|
||||
|
||||
这个脚本将3分钟的串行请求压缩到数秒内。
|
||||
192
8-CMII-RMDC/2-rmdc-jenkins-dac/9-JenkinsBuild-流程图.md
Normal file
192
8-CMII-RMDC/2-rmdc-jenkins-dac/9-JenkinsBuild-流程图.md
Normal file
@@ -0,0 +1,192 @@
|
||||
# Jenkins Build Flow - 构建流程图
|
||||
|
||||
此文档描述了完整的Jenkins构建触发、状态轮询、数据库持久化以及前端状态展示流程。
|
||||
|
||||
## 构建任务完整流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant FE as Frontend
|
||||
participant BE as Backend (Handler)
|
||||
participant SVC as Service
|
||||
participant DB as Database
|
||||
participant JK as Jenkins
|
||||
participant BT as BuildTracker
|
||||
|
||||
Note over FE,BT: 1. 触发构建
|
||||
FE->>BE: POST /build/trigger
|
||||
BE->>SVC: TriggerBuild()
|
||||
SVC->>JK: TriggerBuildInOrg()
|
||||
JK-->>SVC: Success
|
||||
SVC->>JK: GetBranchBuildsInOrg() (get build number)
|
||||
SVC->>DB: SaveBuild (is_building=true)
|
||||
SVC->>BT: TrackBuild(estimatedDuration + 20s)
|
||||
SVC-->>FE: Build Number
|
||||
|
||||
Note over FE,BT: 2. 跳转构建详情页
|
||||
FE->>FE: 显示JenkinsBuildStatusCard
|
||||
FE->>BE: GET /builds/details
|
||||
BE->>SVC: GetBuildDetails()
|
||||
SVC->>DB: GetBuildByNumber()
|
||||
SVC->>JK: GetBuildDetailsInOrg()
|
||||
SVC->>BT: UpdateQueryTime()
|
||||
alt 构建已完成/失败
|
||||
SVC->>JK: GetBuildArtifactDockerImage() (仅SUCCESS)
|
||||
BT->>DB: UpdateBuild (async)
|
||||
BT->>BT: RemoveTask
|
||||
end
|
||||
SVC-->>FE: Build Details
|
||||
|
||||
Note over FE,BT: 3. 前端等待轮询
|
||||
FE->>FE: 计算 waitTime = estimatedDuration - elapsed - 20s
|
||||
FE->>FE: JenkinsBuildStatusCard显示倒计时
|
||||
|
||||
Note over FE,BT: 4. 开始轮询
|
||||
loop 每3秒 (直到超时或完成)
|
||||
FE->>FE: 检查超时 (elapsed > estimated + 30s?)
|
||||
alt 超时
|
||||
FE->>FE: 停止轮询
|
||||
else 未超时
|
||||
FE->>BE: GET /builds/details
|
||||
BE->>SVC: GetBuildDetails()
|
||||
alt 构建完成/失败
|
||||
SVC->>DB: Update (async)
|
||||
SVC->>BT: Remove from tracker
|
||||
SVC-->>FE: result != ""
|
||||
FE->>FE: 停止轮询,更新UI
|
||||
else 仍在构建
|
||||
SVC-->>FE: is_building=true
|
||||
FE->>FE: 更新燃尽进度条
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Note over FE,BT: 5. 后台超时检查
|
||||
BT->>BT: checkBuildTimeouts() (每10秒)
|
||||
alt 超时 (estimatedDuration + 20s)
|
||||
BT->>JK: GetBuildDetailsInOrg()
|
||||
BT->>DB: UpdateBuild
|
||||
BT->>BT: RemoveTask
|
||||
end
|
||||
```
|
||||
|
||||
## 关键流程说明
|
||||
|
||||
### 1. 触发构建 (TriggerBuild)
|
||||
|
||||
1. 前端调用 `POST /build/trigger` 触发构建
|
||||
2. 后端调用 Jenkins API 触发构建
|
||||
3. 等待1秒后查询最新构建号
|
||||
4. 将构建初始信息保存到 `jenkins_builds` 表 (is_building=true)
|
||||
5. 启动 BuildTracker 追踪此构建任务
|
||||
|
||||
### 2. 构建详情查询 (GetBuildDetails)
|
||||
|
||||
1. 前端调用 `GET /builds/details` 获取构建详情
|
||||
2. 后端优先从数据库获取已有信息(DCU相关)
|
||||
3. 调用 Jenkins API 获取最新状态
|
||||
4. **仅当构建成功时**才查询 ArtifactDockerImage(避免不必要的日志解析)
|
||||
5. 通知 BuildTracker 更新查询时间
|
||||
6. 如果构建已完成,异步更新数据库并从Tracker移除
|
||||
|
||||
### 3. 前端轮询策略
|
||||
|
||||
**等待时间算法**:
|
||||
```
|
||||
waitTime = max(0, estimatedDuration - (currentTime - buildStartTime) - 20000ms)
|
||||
```
|
||||
|
||||
- 考虑用户刷新页面的情况,使用已经过的时间计算剩余等待时间
|
||||
- 提前20秒开始轮询,确保及时获取最终状态
|
||||
|
||||
**超时停止**:
|
||||
```
|
||||
if (currentTime - buildStartTime > estimatedDuration + 30000ms) {
|
||||
停止轮询
|
||||
}
|
||||
```
|
||||
|
||||
### 4. 后端超时保障
|
||||
|
||||
- BuildTracker 每10秒检查一次超时任务
|
||||
- 超时时间 = estimatedDuration + 20秒
|
||||
- 超时后主动查询Jenkins并更新数据库
|
||||
- 确保即使前端未轮询,构建状态也能被正确记录
|
||||
|
||||
---
|
||||
|
||||
## JenkinsBuildStatusCard 组件
|
||||
|
||||
### 功能说明
|
||||
|
||||
位于 `BuildDetails.vue` 中,产物信息卡片和DCU状态卡片之间,用于展示Jenkins构建进度。
|
||||
|
||||
### 显示状态
|
||||
|
||||
| 状态 | 说明 |
|
||||
|------|------|
|
||||
| 等待查询 | 构建刚启动,显示轮询倒计时 |
|
||||
| 构建中 | 显示燃尽进度条和实时duration |
|
||||
| 超时运行中 | 构建时间已超过预估 |
|
||||
| 成功/失败 | 构建完成,显示最终状态 |
|
||||
|
||||
### 燃尽进度条算法
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[开始] --> B{duration >= estimatedDuration?}
|
||||
B -->|No| C{duration >= estimatedDuration - 20s?}
|
||||
B -->|Yes| D{duration >= estimatedDuration + 20s?}
|
||||
|
||||
C -->|No| E[绿色进度条 = 0%<br/>显示'等待中...']
|
||||
C -->|Yes| F[绿色燃尽<br/>显示'预计完成 Xs']
|
||||
|
||||
D -->|No| G[红色增长<br/>显示'已超时 Xs']
|
||||
D -->|Yes| H[红色 100%<br/>停止增长]
|
||||
```
|
||||
|
||||
**进度条计算公式:**
|
||||
|
||||
1. **等待阶段** (`duration < estimated - 20s`):
|
||||
- 颜色: 绿色
|
||||
- 进度: 0%
|
||||
- 文本: "等待中..."
|
||||
|
||||
2. **燃尽阶段** (`estimated - 20s <= duration < estimated`):
|
||||
- 颜色: 绿色
|
||||
- 进度: `100 - (estimated - duration) / 20s * 100`
|
||||
- 文本: "预计完成 Xs"
|
||||
|
||||
3. **超时阶段** (`estimated <= duration < estimated + 20s`):
|
||||
- 颜色: 红色
|
||||
- 进度: `(duration - estimated) / 20s * 100`
|
||||
- 文本: "已超时 Xs"
|
||||
|
||||
4. **停止阶段** (`duration >= estimated + 20s`):
|
||||
- 颜色: 红色
|
||||
- 进度: 100%
|
||||
- 持续更新duration显示
|
||||
|
||||
### Duration 实时计算
|
||||
|
||||
> **注意**: Jenkins在构建进行中时返回 `duration: 0`,只有构建完成后才返回真实duration。
|
||||
|
||||
**解决方案**: 在组件中实时计算:
|
||||
```typescript
|
||||
realTimeDuration = Date.now() - new Date(build.timestamp).getTime()
|
||||
```
|
||||
|
||||
使用 `setInterval` 每秒更新 `now` 值,驱动 `realTimeDuration` 计算属性更新。
|
||||
|
||||
---
|
||||
|
||||
## 相关文件
|
||||
|
||||
| 文件 | 作用 |
|
||||
|------|------|
|
||||
| `build_tracker.go` | 后端构建状态追踪,超时检测 |
|
||||
| `jenkins_service.go` | GetBuildDetails,异步DB更新 |
|
||||
| `UserDashboard.vue` | 用户端轮询逻辑 |
|
||||
| `ProjectsManagement.vue` | 管理端轮询逻辑 |
|
||||
| `BuildDetails.vue` | 构建详情页,集成状态卡片 |
|
||||
| `JenkinsBuildStatusCard.vue` | 构建状态展示组件 |
|
||||
433
8-CMII-RMDC/2-rmdc-jenkins-dac/9-rmdc-dcu模块设计方案.md
Normal file
433
8-CMII-RMDC/2-rmdc-jenkins-dac/9-rmdc-dcu模块设计方案.md
Normal file
@@ -0,0 +1,433 @@
|
||||
# DCU 模块设计文档
|
||||
|
||||
> Docker镜像打包压缩服务模块,负责执行 Download-Compress-Upload (DCU) 工作流。
|
||||
|
||||
## 1. 模块概述
|
||||
|
||||
DCU模块是一个独立运行的服务,专门处理Docker镜像的下载、压缩和上传任务。该模块采用Gin+GORM+SQLite3技术栈,通过状态机管理任务流程,支持异步执行和定时清理。
|
||||
|
||||
### 1.1 核心特性
|
||||
|
||||
| 特性 | 说明 |
|
||||
|------|------|
|
||||
| 独立部署 | 完全独立运行,通过HTTP API接收请求 |
|
||||
| 状态管理 | 基于状态机的任务状态管理,支持持久化 |
|
||||
| 异步执行 | DCU流程异步执行,不阻塞API响应 |
|
||||
| 定时清理 | 支持定时清理本地gzip文件和MinIO对象 |
|
||||
| 错误追踪 | 完整的错误信息记录和查询功能 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 架构设计
|
||||
|
||||
### 2.1 系统架构图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "外部系统"
|
||||
JB[rmdc-jenkins-branch-dac] -->|HTTP Request| API
|
||||
DR[Docker Registry]
|
||||
MIO[(MinIO对象存储)]
|
||||
end
|
||||
|
||||
subgraph "rmdc-dcu 模块"
|
||||
API[REST API Handler]
|
||||
|
||||
subgraph "Service Layer"
|
||||
DCU[DCU Service]
|
||||
DS[Docker Service]
|
||||
CS[Compress Service]
|
||||
MS[MinIO Service]
|
||||
SCH[Scheduler]
|
||||
end
|
||||
|
||||
subgraph "Core"
|
||||
SM[State Machine]
|
||||
DAO[DCU Task DAO]
|
||||
end
|
||||
|
||||
DB[(SQLite3)]
|
||||
end
|
||||
|
||||
API --> DCU
|
||||
DCU --> SM
|
||||
DCU --> DS
|
||||
DCU --> CS
|
||||
DCU --> MS
|
||||
SM --> DAO
|
||||
DAO --> DB
|
||||
DS -->|docker pull/save| DR
|
||||
MS -->|upload/delete| MIO
|
||||
SCH --> CS
|
||||
SCH --> MS
|
||||
```
|
||||
|
||||
### 2.2 分层架构
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────┐
|
||||
│ Handler Layer │
|
||||
│ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │
|
||||
│ │ StartTask │ │ GetStatus │ │ QueryTasks │ │
|
||||
│ └─────────────┘ └──────────────┘ └────────────┘ │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ Service Layer │
|
||||
│ ┌─────────────┐ ┌──────────────┐ ┌────────────┐ │
|
||||
│ │ DCUService │ │ DockerSvc │ │ CompressSvc│ │
|
||||
│ ├─────────────┤ ├──────────────┤ ├────────────┤ │
|
||||
│ │ MinIOSvc │ │ Scheduler │ │ │ │
|
||||
│ └─────────────┘ └──────────────┘ └────────────┘ │
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ State Machine Layer │
|
||||
│ ┌─────────────────────────────────────────────────┐│
|
||||
│ │ StateMachine (状态转换 + 持久化回调) ││
|
||||
│ └─────────────────────────────────────────────────┘│
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ DAO Layer │
|
||||
│ ┌─────────────────────────────────────────────────┐│
|
||||
│ │ DCUTaskDAO (CRUD + 分页查询 + 清理) ││
|
||||
│ └─────────────────────────────────────────────────┘│
|
||||
├─────────────────────────────────────────────────────┤
|
||||
│ Entity Layer │
|
||||
│ ┌─────────────────────────────────────────────────┐│
|
||||
│ │ DCUTask (任务实体 + GORM映射) ││
|
||||
│ └─────────────────────────────────────────────────┘│
|
||||
└─────────────────────────────────────────────────────┘
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 状态机设计
|
||||
|
||||
### 3.1 状态定义
|
||||
|
||||
| 状态 | 常量值 | 说明 | 进度 |
|
||||
|------|--------|------|------|
|
||||
| 等待中 | `idle` | 任务已创建,等待开始 | 0% |
|
||||
| 下载中 | `downloading` | 正在执行docker pull | 25% |
|
||||
| 压缩中 | `compressing` | 正在gzip压缩镜像 | 50% |
|
||||
| 上传中 | `uploading` | 正在上传到MinIO | 75% |
|
||||
| 已完成 | `completed` | 任务成功完成 | 100% |
|
||||
| 失败 | `failed` | 任务执行失败 | -1 |
|
||||
|
||||
### 3.2 状态转换图
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> idle: 创建任务
|
||||
|
||||
idle --> downloading: StartTask()
|
||||
idle --> failed: 初始化失败
|
||||
|
||||
downloading --> compressing: Pull成功
|
||||
downloading --> failed: Pull失败
|
||||
|
||||
compressing --> uploading: 压缩成功
|
||||
compressing --> failed: 压缩失败
|
||||
|
||||
uploading --> completed: 上传成功
|
||||
uploading --> failed: 上传失败
|
||||
|
||||
completed --> [*]
|
||||
failed --> [*]
|
||||
```
|
||||
|
||||
### 3.3 状态持久化
|
||||
|
||||
状态机通过回调函数实现状态持久化:
|
||||
|
||||
```go
|
||||
// 状态转换时自动调用
|
||||
func (s *DCUService) onStateTransition(taskID, fromState, toState, errMsg string) error {
|
||||
return s.taskDAO.UpdateState(ctx, taskID, toState, errMsg)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. DCU 工作流程
|
||||
|
||||
### 4.1 完整流程图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant Client as 调用方
|
||||
participant API as REST API
|
||||
participant DCU as DCU Service
|
||||
participant SM as State Machine
|
||||
participant Docker as Docker CLI
|
||||
participant Compress as Compress Service
|
||||
participant MinIO as MinIO Service
|
||||
participant DB as SQLite
|
||||
|
||||
Client->>API: POST /api/dcu/start
|
||||
API->>DCU: StartTask(username, imageName)
|
||||
DCU->>DB: Create task record
|
||||
DCU->>SM: RegisterTask(taskID)
|
||||
DCU-->>API: Return taskID
|
||||
API-->>Client: Response {task_id, state: "idle"}
|
||||
|
||||
Note over DCU: 异步执行DCU流程
|
||||
|
||||
DCU->>SM: Transition(downloading)
|
||||
SM->>DB: Update state
|
||||
DCU->>Docker: docker pull image
|
||||
Docker-->>DCU: Pull完成
|
||||
DCU->>Docker: docker save -o image.tar
|
||||
Docker-->>DCU: Save完成
|
||||
|
||||
DCU->>SM: Transition(compressing)
|
||||
SM->>DB: Update state
|
||||
DCU->>Compress: CompressFile(tar → gzip)
|
||||
Compress-->>DCU: 压缩完成
|
||||
DCU->>DB: Update gzip_file_name
|
||||
|
||||
DCU->>SM: Transition(uploading)
|
||||
SM->>DB: Update state
|
||||
DCU->>MinIO: Upload(objectName, gzipPath)
|
||||
MinIO-->>DCU: 上传完成
|
||||
DCU->>DB: Update minio_object_name
|
||||
|
||||
DCU->>SM: Transition(completed)
|
||||
SM->>DB: Update state + end_time
|
||||
|
||||
Client->>API: GET /api/dcu/status/{task_id}
|
||||
API->>DCU: GetTaskStatus(taskID)
|
||||
DCU->>DB: Query task
|
||||
DB-->>DCU: Task entity
|
||||
DCU-->>API: TaskStatusResponse
|
||||
API-->>Client: Response with progress
|
||||
```
|
||||
|
||||
### 4.2 错误处理流程
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[开始DCU] --> B{Docker Pull}
|
||||
B -->|成功| C{Docker Save}
|
||||
B -->|失败| F[记录错误信息]
|
||||
C -->|成功| D{Gzip压缩}
|
||||
C -->|失败| F
|
||||
D -->|成功| E{MinIO上传}
|
||||
D -->|失败| F
|
||||
E -->|成功| G[状态: completed]
|
||||
E -->|失败| F
|
||||
F --> H[状态: failed]
|
||||
G --> I[结束]
|
||||
H --> I
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. API 接口说明
|
||||
|
||||
### 5.1 启动DCU任务
|
||||
|
||||
```
|
||||
POST /api/dcu/start
|
||||
```
|
||||
|
||||
**请求体:**
|
||||
```json
|
||||
{
|
||||
"username": "test_user",
|
||||
"docker_image_name": "nginx:latest"
|
||||
}
|
||||
```
|
||||
|
||||
**响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"status": 200,
|
||||
"message": "任务已启动",
|
||||
"data": {
|
||||
"task_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"state": "idle"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.2 查询任务状态
|
||||
|
||||
```
|
||||
GET /api/dcu/status/{task_id}
|
||||
```
|
||||
|
||||
**响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"status": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"task_id": "550e8400-e29b-41d4-a716-446655440000",
|
||||
"state": "compressing",
|
||||
"state_display": "压缩镜像中",
|
||||
"docker_image_name": "nginx:latest",
|
||||
"gzip_file_name": "./data/gzip/nginx_latest.tar.gz",
|
||||
"progress": 50,
|
||||
"duration": 12345,
|
||||
"username": "test_user",
|
||||
"start_time": "2025-12-10 20:25:00"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.3 查询任务列表
|
||||
|
||||
```
|
||||
GET /api/dcu/query?docker_image_name=nginx&page=1&page_size=10
|
||||
```
|
||||
|
||||
**查询参数:**
|
||||
| 参数 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| docker_image_name | string | 镜像名称(模糊匹配) |
|
||||
| username | string | 用户名 |
|
||||
| state | string | 状态筛选 |
|
||||
| page | int | 页码 |
|
||||
| page_size | int | 每页数量 |
|
||||
|
||||
**响应:**
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"status": 200,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"total": 42,
|
||||
"items": [...]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
### 5.4 健康检查
|
||||
|
||||
```
|
||||
GET /api/dcu/health
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 数据库设计
|
||||
|
||||
### 6.1 DCU任务表 (dcu_tasks)
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| id | INTEGER | 主键,自增 |
|
||||
| task_id | VARCHAR(100) | 任务UUID,唯一索引 |
|
||||
| username | VARCHAR(100) | 用户名,索引 |
|
||||
| docker_image_name | VARCHAR(500) | Docker镜像名,索引 |
|
||||
| gzip_file_name | VARCHAR(500) | Gzip文件路径 |
|
||||
| minio_object_name | VARCHAR(500) | MinIO对象名 |
|
||||
| state | VARCHAR(50) | 状态,索引 |
|
||||
| error_message | VARCHAR(2000) | 错误信息 |
|
||||
| start_time | DATETIME | 开始时间,索引 |
|
||||
| end_time | DATETIME | 结束时间 |
|
||||
| duration | INTEGER | 持续时间(毫秒) |
|
||||
| created_at | DATETIME | 创建时间 |
|
||||
| updated_at | DATETIME | 更新时间 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 定时任务
|
||||
|
||||
| 任务 | 默认Cron | 说明 |
|
||||
|------|----------|------|
|
||||
| Gzip清理 | `0 0 * * *` | 每天凌晨清理过期gzip文件 |
|
||||
| MinIO清理 | `0 0 * * 0` | 每周日凌晨清理过期MinIO对象 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 配置说明
|
||||
|
||||
配置文件位置:`configs/config.yaml`
|
||||
|
||||
```yaml
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8090
|
||||
mode: debug
|
||||
|
||||
database:
|
||||
path: ./data/dcu.db
|
||||
|
||||
storage:
|
||||
gzip_path: ./data/gzip
|
||||
cleanup_gzip_cron: "0 0 * * *"
|
||||
cleanup_minio_cron: "0 0 * * 0"
|
||||
gzip_retention_days: 1
|
||||
minio_retention_days: 7
|
||||
|
||||
minio:
|
||||
endpoint: 192.168.40.50:9000
|
||||
access_key: your_access_key
|
||||
secret_key: your_secret_key
|
||||
bucket: dcu-artifacts
|
||||
use_ssl: false
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 目录结构
|
||||
|
||||
```
|
||||
rmdc-dcu/
|
||||
├── cmd/
|
||||
│ └── main.go # 应用入口
|
||||
├── configs/
|
||||
│ └── config.yaml # 配置文件
|
||||
├── internal/
|
||||
│ ├── config/
|
||||
│ │ └── config.go # 配置结构
|
||||
│ ├── dao/
|
||||
│ │ ├── database.go # 数据库初始化
|
||||
│ │ └── dcu_task_dao.go # 任务DAO
|
||||
│ ├── handler/
|
||||
│ │ ├── dcu_handler.go # API处理器
|
||||
│ │ └── router.go # 路由注册
|
||||
│ ├── model/
|
||||
│ │ ├── dto/
|
||||
│ │ │ └── dcu_dto.go # 请求/响应DTO
|
||||
│ │ └── entity/
|
||||
│ │ └── dcu_task.go # 任务实体
|
||||
│ ├── service/
|
||||
│ │ ├── compress_service.go # 压缩服务
|
||||
│ │ ├── dcu_service.go # DCU编排服务
|
||||
│ │ ├── docker_service.go # Docker服务
|
||||
│ │ ├── minio_service.go # MinIO服务
|
||||
│ │ └── scheduler.go # 定时调度器
|
||||
│ └── statemachine/
|
||||
│ ├── machine.go # 状态机实现
|
||||
│ └── state.go # 状态定义
|
||||
├── go.mod
|
||||
└── go.sum
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 10. 运行要求
|
||||
|
||||
- **Go**: 1.24+
|
||||
- **Docker**: 已安装并配置Docker CLI
|
||||
- **MinIO**: 可访问的MinIO服务器
|
||||
- **SQLite3**: 自动创建(通过GORM)
|
||||
|
||||
---
|
||||
|
||||
## 11. 启动命令
|
||||
|
||||
```bash
|
||||
cd rmdc-dcu
|
||||
go run ./cmd/main.go
|
||||
```
|
||||
|
||||
服务将在 `http://0.0.0.0:8090` 启动。
|
||||
@@ -0,0 +1,837 @@
|
||||
# JenBranchRBAC 系统详细设计说明书
|
||||
|
||||
**Jenkins 分支级权限管理系统架构设计文档**
|
||||
|
||||
***
|
||||
|
||||
## 1. 系统架构设计
|
||||
|
||||
### 1.1 总体架构
|
||||
|
||||
JenBranchRBAC 采用前后端分离的三层架构设计,通过 RESTful API 与 WebSocket 实现前后端通信,后端通过 Jenkins REST API 实现与 Jenkins 系统的集成。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "展现层 Presentation Layer"
|
||||
A[Vue3 + TypeScript]
|
||||
B[Vuetify 3 UI]
|
||||
C[Pinia State Management]
|
||||
end
|
||||
|
||||
subgraph "网络通信层 Network Layer"
|
||||
D[RESTful API]
|
||||
E[WebSocket]
|
||||
F[Nginx Reverse Proxy]
|
||||
end
|
||||
|
||||
subgraph "业务逻辑层 Business Layer"
|
||||
G[Gin Web Framework]
|
||||
H[JWT Authentication]
|
||||
I[RBAC Middleware]
|
||||
J[Jenkins API Client]
|
||||
K[Cron Job Scheduler]
|
||||
end
|
||||
|
||||
subgraph "数据持久层 Data Layer"
|
||||
L[GORM ORM]
|
||||
M[SQLite3 WAL Mode]
|
||||
N[Backup Service]
|
||||
end
|
||||
|
||||
subgraph "外部系统 External Systems"
|
||||
O[Jenkins Server]
|
||||
P[SMTP Server]
|
||||
Q[Webhook Endpoints]
|
||||
end
|
||||
|
||||
A --> D
|
||||
A --> E
|
||||
B --> A
|
||||
C --> A
|
||||
D --> F
|
||||
E --> F
|
||||
F --> G
|
||||
G --> H
|
||||
G --> I
|
||||
G --> J
|
||||
G --> K
|
||||
G --> L
|
||||
L --> M
|
||||
M --> N
|
||||
J --> O
|
||||
G --> P
|
||||
G --> Q
|
||||
```
|
||||
|
||||
### 1.2 系统分层职责
|
||||
|
||||
| 层次 | 组件 | 职责边界 |
|
||||
|------|------|----------|
|
||||
| 展现层 | Vue3 + Vuetify | 用户界面渲染、表单验证、状态管理、路由控制 |
|
||||
| 网络层 | Nginx + API Gateway | 静态资源托管、请求路由、负载均衡、SSL终止 |
|
||||
| 业务层 | Gin + 业务逻辑模块 | 认证授权、权限校验、业务流程编排、Jenkins API封装 |
|
||||
| 数据层 | GORM + SQLite | 数据持久化、事务管理、查询优化、备份恢复 |
|
||||
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 2. 核心模块设计
|
||||
|
||||
### 2.1 认证授权模块
|
||||
|
||||
#### 2.1.1 认证流程设计
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户浏览器
|
||||
participant F as Vue Frontend
|
||||
participant N as Nginx
|
||||
participant B as Gin Backend
|
||||
participant D as Database
|
||||
participant J as Jenkins API
|
||||
|
||||
U->>F: 输入用户名/密码
|
||||
F->>F: RSA公钥加密密码
|
||||
F->>N: POST /api/auth/login
|
||||
N->>B: 转发请求
|
||||
B->>B: RSA私钥解密密码
|
||||
B->>D: 查询用户记录
|
||||
D-->>B: 返回用户信息
|
||||
B->>B: bcrypt验证密码
|
||||
B->>B: 检查账户状态
|
||||
alt 验证成功
|
||||
B->>B: 生成JWT Token
|
||||
B->>D: 记录登录日志
|
||||
B-->>F: 返回Token + 用户信息
|
||||
F->>F: 存储Token到LocalStorage
|
||||
F-->>U: 跳转到项目列表页
|
||||
else 验证失败
|
||||
B->>D: 累计失败次数
|
||||
alt 失败次数>=5
|
||||
B->>D: 锁定账户30分钟
|
||||
end
|
||||
B-->>F: 返回错误信息
|
||||
F-->>U: 显示错误提示
|
||||
end
|
||||
```
|
||||
|
||||
#### 2.1.2 权限校验中间件设计
|
||||
|
||||
**RBAC 中间件实现逻辑**:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[HTTP请求到达] --> B{提取JWT Token}
|
||||
B -->|Token不存在| C[返回401 Unauthorized]
|
||||
B -->|Token存在| D[验证Token签名]
|
||||
D -->|签名无效| C
|
||||
D -->|签名有效| E{检查Token过期时间}
|
||||
E -->|已过期| F{在刷新窗口内?}
|
||||
F -->|是| G[生成新Token并返回]
|
||||
F -->|否| C
|
||||
E -->|未过期| H[解析用户ID和角色]
|
||||
H --> I{检查接口权限}
|
||||
I -->|超级管理员| J[放行请求]
|
||||
I -->|项目管理员| K{验证项目权限}
|
||||
K -->|有权限| J
|
||||
K -->|无权限| L[返回403 Forbidden]
|
||||
I -->|普通用户| M{验证分支权限}
|
||||
M -->|有权限| J
|
||||
M -->|无权限| L
|
||||
J --> N[继续处理业务逻辑]
|
||||
```
|
||||
|
||||
|
||||
***
|
||||
|
||||
### 2.2 Jenkins 数据同步模块
|
||||
|
||||
#### 2.2.1 定时同步机制
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant C as Cron Scheduler
|
||||
participant S as Sync Service
|
||||
participant J as Jenkins API
|
||||
participant Cache as Local Cache
|
||||
participant DB as Database
|
||||
participant WS as WebSocket Server
|
||||
|
||||
C->>S: 触发定时任务(每5分钟)
|
||||
S->>J: GET /api/json?tree=jobs[name,url]
|
||||
J-->>S: 返回项目列表
|
||||
loop 遍历多分支项目
|
||||
S->>J: GET /job/{name}/api/json
|
||||
J-->>S: 返回分支列表
|
||||
end
|
||||
S->>S: 差异检测(对比Cache)
|
||||
S->>DB: 更新项目/分支元数据
|
||||
S->>Cache: 更新本地缓存
|
||||
alt 发现新增/删除
|
||||
S->>WS: 推送通知给在线管理员
|
||||
end
|
||||
S->>DB: 记录同步日志
|
||||
```
|
||||
|
||||
#### 2.2.2 手动同步机制
|
||||
|
||||
管理员触发立即同步时,后端启动异步 Goroutine 执行同步任务,前端通过 WebSocket 订阅同步进度:
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Idle: 系统空闲
|
||||
Idle --> Syncing: 点击"立即同步"
|
||||
Syncing --> FetchingProjects: 获取项目列表
|
||||
FetchingProjects --> FetchingBranches: 项目获取完成
|
||||
FetchingBranches --> DiffDetecting: 分支获取完成
|
||||
DiffDetecting --> Updating: 差异检测完成
|
||||
Updating --> Success: 更新完成
|
||||
Updating --> Failed: 更新失败
|
||||
Success --> Idle: 返回空闲
|
||||
Failed --> Idle: 返回空闲
|
||||
|
||||
note right of Syncing
|
||||
WebSocket推送: progress=0%
|
||||
end note
|
||||
note right of FetchingBranches
|
||||
WebSocket推送: progress=50%
|
||||
end note
|
||||
note right of Success
|
||||
WebSocket推送: progress=100%
|
||||
end note
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### 2.3 权限管理模块
|
||||
|
||||
#### 2.3.1 权限分配流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant A as 管理员
|
||||
participant F as 前端界面
|
||||
participant B as 后端API
|
||||
participant D as 数据库
|
||||
participant C as 缓存层
|
||||
|
||||
A->>F: 选择用户
|
||||
F->>B: GET /api/users/{id}/permissions
|
||||
B->>D: 查询现有权限
|
||||
D-->>B: 返回权限列表
|
||||
B-->>F: 返回权限数据
|
||||
F->>F: 渲染左右穿梭框
|
||||
A->>F: 选择项目/分支并提交
|
||||
F->>B: POST /api/permissions/assign
|
||||
B->>B: 验证管理员权限范围
|
||||
B->>D: 批量插入/更新权限记录
|
||||
B->>D: 记录审计日志
|
||||
B->>C: 清除用户权限缓存
|
||||
B-->>F: 返回操作结果
|
||||
F-->>A: 显示成功提示
|
||||
```
|
||||
|
||||
#### 2.3.2 权限模板应用
|
||||
|
||||
权限模板设计用于快速批量授权相同角色的用户:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[创建权限模板] --> B[选择项目-分支组合]
|
||||
B --> C[保存为JSON格式]
|
||||
C --> D[存储到permission_templates表]
|
||||
D --> E[应用模板到用户]
|
||||
E --> F[解析JSON权限定义]
|
||||
F --> G[批量插入permissions表]
|
||||
G --> H[记录审计日志]
|
||||
```
|
||||
|
||||
***
|
||||
|
||||
### 2.4 构建管理模块
|
||||
|
||||
#### 2.4.1 构建触发流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as 用户
|
||||
participant F as 前端
|
||||
participant B as 后端
|
||||
participant D as 数据库
|
||||
participant J as Jenkins
|
||||
|
||||
U->>F: 点击"构建"按钮
|
||||
F->>B: POST /api/build/trigger
|
||||
B->>D: 查询用户权限
|
||||
D-->>B: 返回权限信息
|
||||
B->>B: 二次校验构建权限
|
||||
alt 有构建权限
|
||||
B->>J: 获取Jenkins Crumb
|
||||
J-->>B: 返回Crumb Token
|
||||
B->>J: POST /job/{job}/job/{branch}/build
|
||||
J-->>B: 返回Queue ID
|
||||
B->>D: 记录构建审计日志
|
||||
B-->>F: 返回Queue ID
|
||||
F->>F: 建立WebSocket连接
|
||||
F->>B: 订阅构建日志
|
||||
else 无权限
|
||||
B-->>F: 返回403错误
|
||||
F-->>U: 显示权限不足提示
|
||||
end
|
||||
```
|
||||
|
||||
#### 2.4.2 实时日志推送
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant F as 前端WebSocket客户端
|
||||
participant W as 后端WebSocket服务
|
||||
participant J as Jenkins API
|
||||
participant L as 日志缓冲区
|
||||
|
||||
F->>W: 连接WS /ws/build-log/{buildId}
|
||||
W->>W: 验证JWT Token
|
||||
W->>J: GET logText/progressiveText?start=0
|
||||
J-->>W: 返回日志片段 + nextOffset
|
||||
W->>L: 写入缓冲区
|
||||
W->>F: 推送日志数据(JSON格式)
|
||||
loop 每2秒轮询
|
||||
W->>J: GET logText/progressiveText?start={nextOffset}
|
||||
J-->>W: 返回增量日志
|
||||
W->>F: 推送增量数据
|
||||
end
|
||||
alt 构建完成
|
||||
W->>F: 推送完成标识
|
||||
W->>W: 关闭连接
|
||||
end
|
||||
```
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 3. 数据库设计
|
||||
|
||||
### 3.1 E-R 关系图
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
USERS ||--o{ PERMISSIONS : has
|
||||
USERS ||--o{ AUDIT_LOGS : generates
|
||||
USERS ||--o{ PERMISSION_TEMPLATES : creates
|
||||
USERS ||--o{ PERMISSIONS_GRANTED : grants
|
||||
|
||||
USERS {
|
||||
int id PK
|
||||
string username UK
|
||||
string password_hash
|
||||
string role
|
||||
string status
|
||||
datetime password_expires_at
|
||||
int failed_login_attempts
|
||||
datetime locked_until
|
||||
string mfa_secret
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
datetime last_login_at
|
||||
}
|
||||
|
||||
PERMISSIONS {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string project_name
|
||||
string branch_name
|
||||
bool can_view
|
||||
bool can_build
|
||||
int granted_by FK
|
||||
datetime granted_at
|
||||
}
|
||||
|
||||
AUDIT_LOGS {
|
||||
int id PK
|
||||
int user_id FK
|
||||
string action
|
||||
string resource_type
|
||||
string resource_id
|
||||
text details
|
||||
string ip_address
|
||||
text user_agent
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
PERMISSION_TEMPLATES {
|
||||
int id PK
|
||||
string name UK
|
||||
text description
|
||||
text permissions_json
|
||||
int created_by FK
|
||||
datetime created_at
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 索引优化策略
|
||||
|
||||
| 表名 | 索引字段 | 索引类型 | 优化目标 |
|
||||
|------|----------|----------|----------|
|
||||
| users | username | UNIQUE | 登录查询加速 |
|
||||
| permissions | (user_id, project_name, branch_name) | UNIQUE | 防止重复授权 |
|
||||
| permissions | user_id | BTREE | 用户权限列表查询 |
|
||||
| audit_logs | (user_id, created_at) | COMPOSITE | 用户操作历史查询 |
|
||||
| audit_logs | action | BTREE | 操作类型统计分析 |
|
||||
| audit_logs | created_at | BTREE | 日志归档清理 |
|
||||
|
||||
***
|
||||
|
||||
## 4. 接口设计规范
|
||||
|
||||
### 4.1 RESTful API 设计
|
||||
|
||||
#### 4.1.1 认证授权接口
|
||||
|
||||
| 接口路径 | 方法 | 功能 | 请求体 | 响应体 |
|
||||
|---------|------|------|--------|--------|
|
||||
| /api/auth/login | POST | 用户登录 | `{username, encrypted_password}` | `{token, refresh_token, user_info}` |
|
||||
| /api/auth/logout | POST | 用户登出 | - | `{message}` |
|
||||
| /api/auth/refresh | POST | 刷新Token | `{refresh_token}` | `{token}` |
|
||||
| /api/auth/reset-password | POST | 重置密码 | `{user_id, new_password}` | `{message}` |
|
||||
|
||||
#### 4.1.2 用户管理接口
|
||||
|
||||
| 接口路径 | 方法 | 功能 | 权限要求 | 请求参数 |
|
||||
|---------|------|------|----------|----------|
|
||||
| /api/users | GET | 用户列表 | 管理员 | `page, size, role, status` |
|
||||
| /api/users | POST | 创建用户 | 管理员 | `{username, password, role}` |
|
||||
| /api/users/{id} | GET | 用户详情 | 管理员 | - |
|
||||
| /api/users/{id} | PUT | 更新用户 | 管理员 | `{role, status}` |
|
||||
| /api/users/{id} | DELETE | 删除用户 | 超级管理员 | - |
|
||||
| /api/users/batch | POST | 批量导入 | 管理员 | `CSV文件` |
|
||||
| /api/users/export | GET | 导出用户 | 管理员 | `format=csv/excel` |
|
||||
|
||||
#### 4.1.3 权限管理接口
|
||||
|
||||
| 接口路径 | 方法 | 功能 | 请求体 |
|
||||
|---------|------|------|--------|
|
||||
| /api/permissions/assign | POST | 分配权限 | `{user_id, permissions:[{project, branch, can_view, can_build}]}` |
|
||||
| /api/permissions/{user_id} | GET | 查询用户权限 | - |
|
||||
| /api/permissions/templates | GET | 权限模板列表 | - |
|
||||
| /api/permissions/templates | POST | 创建权限模板 | `{name, description, permissions_json}` |
|
||||
|
||||
#### 4.1.4 Jenkins 同步接口
|
||||
|
||||
| 接口路径 | 方法 | 功能 | 响应体 |
|
||||
|---------|------|------|--------|
|
||||
| /api/jenkins/sync | POST | 手动同步 | `{task_id, status}` |
|
||||
| /api/jenkins/projects | GET | 项目列表 | `{projects:[{name, branches:[]}]}` |
|
||||
| /api/jenkins/sync/status | GET | 同步状态 | `{status, progress, message}` |
|
||||
|
||||
#### 4.1.5 构建管理接口
|
||||
|
||||
| 接口路径 | 方法 | 功能 | 请求体 |
|
||||
|---------|------|------|--------|
|
||||
| /api/build/trigger | POST | 触发构建 | `{project, branch, parameters}` |
|
||||
| /api/build/{build_id}/log | GET | 获取构建日志 | - |
|
||||
| /api/build/{build_id}/artifacts | GET | 获取构建产物 | - |
|
||||
| /api/build/history | GET | 历史构建记录 | `project, branch, page, size` |
|
||||
|
||||
***
|
||||
|
||||
### 4.2 WebSocket 接口设计
|
||||
|
||||
| 连接路径 | 事件类型 | 数据格式 | 用途 |
|
||||
|---------|---------|---------|------|
|
||||
| /ws/build-log/{build_id} | log_chunk | `{offset, content, is_complete}` | 实时日志推送 |
|
||||
| /ws/sync-progress | sync_status | `{progress, current_project, message}` | 同步进度通知 |
|
||||
| /ws/notifications | notification | `{type, title, message, timestamp}` | 系统通知推送 |
|
||||
|
||||
***
|
||||
|
||||
## 5. 安全设计方案
|
||||
|
||||
### 5.1 密码安全策略
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[用户创建密码] --> B{密码强度校验}
|
||||
B -->|不符合| C[返回错误提示]
|
||||
B -->|符合| D[bcrypt哈希 cost=12]
|
||||
D --> E[存储密码哈希]
|
||||
E --> F[设置过期时间180天]
|
||||
F --> G[定时检查过期状态]
|
||||
G -->|距过期7天| H[发送邮件提醒]
|
||||
G -->|已过期| I[强制修改密码]
|
||||
```
|
||||
|
||||
**密码策略配置**:
|
||||
- 最小长度: 8 位
|
||||
- 必须包含: 大写字母、小写字母、数字、特殊字符
|
||||
- 历史密码限制: 不能与最近 3 次密码相同
|
||||
- 加密算法: bcrypt (cost factor = 12)
|
||||
- 有效期: 180 天
|
||||
|
||||
### 5.2 防暴力破解机制
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Normal: 正常状态
|
||||
Normal --> Failed1: 登录失败1次
|
||||
Failed1 --> Failed2: 登录失败2次
|
||||
Failed2 --> Failed3: 登录失败3次
|
||||
Failed3 --> Failed4: 登录失败4次
|
||||
Failed4 --> Locked: 登录失败5次
|
||||
Locked --> Normal: 30分钟后自动解锁
|
||||
Failed1 --> Normal: 登录成功
|
||||
Failed2 --> Normal: 登录成功
|
||||
Failed3 --> Normal: 登录成功
|
||||
Failed4 --> Normal: 登录成功
|
||||
|
||||
note right of Locked
|
||||
账户锁定30分钟
|
||||
记录审计日志
|
||||
发送告警邮件
|
||||
end note
|
||||
```
|
||||
|
||||
|
||||
### 5.3 API 安全防护
|
||||
|
||||
| 安全措施 | 实现方案 | 防护对象 |
|
||||
|---------|---------|---------|
|
||||
| SQL 注入防护 | GORM 参数化查询 | 所有数据库操作 |
|
||||
| XSS 防护 | Vue 自动转义 + Gin SecureJSON | 前后端输出 |
|
||||
| CSRF 防护 | Jenkins Crumb Token | Jenkins API 调用 |
|
||||
| 请求限流 | Gin 限流中间件 | 所有 API 端点 |
|
||||
| 数据加密传输 | RSA 加密密码 + HTTPS | 敏感数据传输 |
|
||||
| JWT Token 安全 | 8 小时过期 + 刷新机制 | 用户会话管理 |
|
||||
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 6. 性能优化方案
|
||||
|
||||
### 6.1 后端性能优化
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
A[性能优化策略] --> B[并发优化]
|
||||
A --> C[缓存优化]
|
||||
A --> D[数据库优化]
|
||||
A --> E[网络优化]
|
||||
|
||||
B --> B1[Goroutine处理异步任务]
|
||||
B --> B2[连接池复用]
|
||||
B --> B3[请求限流防止雪崩]
|
||||
|
||||
C --> C1[本地缓存Jenkins数据]
|
||||
C --> C2[用户权限缓存]
|
||||
C --> C3[Redis缓存热点数据可选]
|
||||
|
||||
D --> D1[SQLite WAL模式]
|
||||
D --> D2[复合索引优化]
|
||||
D --> D3[定期清理审计日志]
|
||||
|
||||
E --> E1[HTTP/2启用]
|
||||
E --> E2[Jenkins API tree参数]
|
||||
E --> E3[WebSocket长连接复用]
|
||||
```
|
||||
|
||||
### 6.2 前端性能优化
|
||||
|
||||
| 优化项 | 实现方案 | 性能收益 |
|
||||
|--------|---------|---------|
|
||||
| 路由懒加载 | Vue Router 动态 import | 减少首屏加载时间 |
|
||||
| 组件按需加载 | Vuetify Treeshaking | 减小打包体积 30% |
|
||||
| 虚拟滚动 | DataGrid 虚拟列表 | 大数据量渲染优化 |
|
||||
| 请求防抖 | Lodash debounce 搜索 | 减少 API 调用次数 |
|
||||
| 日志分页加载 | 滚动加载历史日志 | 避免内存溢出 |
|
||||
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 7. 部署架构设计
|
||||
|
||||
### 7.1 单机部署方案
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Docker Container"
|
||||
A[Nginx:alpine] -->|静态资源| B[Vue3 Dist]
|
||||
A -->|反向代理 :8080| C[Gin Backend]
|
||||
C --> D[SQLite3 WAL DB]
|
||||
C --> E[(/data Volume Mount)]
|
||||
D --> E
|
||||
end
|
||||
|
||||
F[External Client] -->|HTTPS :443| A
|
||||
C -->|Jenkins API| G[Jenkins Server]
|
||||
C -->|SMTP :587| H[Mail Server]
|
||||
|
||||
```
|
||||
|
||||
**Dockerfile 示例**:
|
||||
|
||||
```dockerfile
|
||||
# Stage 1: 前端构建
|
||||
FROM node:20-alpine AS frontend-builder
|
||||
WORKDIR /app/frontend
|
||||
COPY frontend/package*.json ./
|
||||
RUN npm ci
|
||||
COPY frontend/ ./
|
||||
RUN npm run build
|
||||
|
||||
# Stage 2: 后端构建
|
||||
FROM golang:1.24-alpine AS backend-builder
|
||||
WORKDIR /app/backend
|
||||
COPY backend/go.* ./
|
||||
RUN go mod download
|
||||
COPY backend/ ./
|
||||
RUN CGO_ENABLED=1 GOOS=linux go build -a -installsuffix cgo -o jenbranchrbac .
|
||||
|
||||
# Stage 3: 运行时镜像
|
||||
FROM alpine:latest
|
||||
RUN apk --no-cache add ca-certificates nginx
|
||||
WORKDIR /app
|
||||
COPY --from=backend-builder /app/backend/jenbranchrbac .
|
||||
COPY --from=frontend-builder /app/frontend/dist /usr/share/nginx/html
|
||||
COPY nginx.conf /etc/nginx/nginx.conf
|
||||
EXPOSE 80 8080
|
||||
CMD nginx && ./jenbranchrbac
|
||||
```
|
||||
|
||||
|
||||
### 7.2 高可用部署方案
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "负载均衡层"
|
||||
A[Nginx/HAProxy]
|
||||
end
|
||||
|
||||
subgraph "应用层"
|
||||
B1[JenBranchRBAC Instance 1]
|
||||
B2[JenBranchRBAC Instance 2]
|
||||
B3[JenBranchRBAC Instance N]
|
||||
end
|
||||
|
||||
subgraph "数据层"
|
||||
C[PostgreSQL Primary]
|
||||
D[PostgreSQL Standby]
|
||||
E[Redis Cluster]
|
||||
end
|
||||
|
||||
A -->|Round Robin| B1
|
||||
A --> B2
|
||||
A --> B3
|
||||
B1 --> C
|
||||
B2 --> C
|
||||
B3 --> C
|
||||
C -->|主从复制| D
|
||||
B1 --> E
|
||||
B2 --> E
|
||||
B3 --> E
|
||||
```
|
||||
|
||||
**扩展建议**:
|
||||
- 当并发用户超过 500 人时,建议从 SQLite 迁移到 PostgreSQL
|
||||
- 引入 Redis 作为分布式缓存层,存储用户会话和权限信息
|
||||
- 使用 Kubernetes 部署多实例,实现水平扩展
|
||||
|
||||
***
|
||||
|
||||
## 8. 监控与运维设计
|
||||
|
||||
### 8.1 日志分级策略
|
||||
|
||||
| 日志级别 | 记录场景 | 示例 |
|
||||
|---------|---------|------|
|
||||
| DEBUG | 详细调试信息 | Jenkins API 请求参数、SQL 查询语句 |
|
||||
| INFO | 正常业务流程 | 用户登录成功、构建触发成功 |
|
||||
| WARN | 潜在问题告警 | API 调用超时重试、缓存未命中 |
|
||||
| ERROR | 错误但可恢复 | Jenkins 连接失败、数据库锁超时 |
|
||||
| FATAL | 系统致命错误 | 数据库文件损坏、配置文件缺失 |
|
||||
|
||||
### 8.2 监控指标设计
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
A[监控指标体系] --> B[系统指标]
|
||||
A --> C[业务指标]
|
||||
A --> D[安全指标]
|
||||
|
||||
B --> B1[CPU使用率]
|
||||
B --> B2[内存占用]
|
||||
B --> B3[磁盘IO]
|
||||
B --> B4[Goroutine数量]
|
||||
|
||||
C --> C1[API响应时间]
|
||||
C --> C2[Jenkins同步耗时]
|
||||
C --> C3[构建触发成功率]
|
||||
C --> C4[WebSocket连接数]
|
||||
|
||||
D --> D1[登录失败次数]
|
||||
D --> D2[异常IP访问]
|
||||
D --> D3[权限拒绝次数]
|
||||
D --> D4[Token刷新频率]
|
||||
```
|
||||
|
||||
**Prometheus 集成方案**:
|
||||
- 使用 `gin-prometheus` 中间件暴露 `/metrics` 端点
|
||||
- 监控指标包括:HTTP 请求计数、延迟分布、数据库连接池状态、Goroutine 泄漏检测
|
||||
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 9. 备选技术方案
|
||||
|
||||
### 9.1 数据库迁移路径
|
||||
|
||||
| 数据库类型 | 适用场景 | 迁移工具 |
|
||||
|-----------|---------|---------|
|
||||
| SQLite3 | 单机部署 < 500 用户 | 内置方案 |
|
||||
| PostgreSQL | 生产环境 > 500 用户 | GORM AutoMigrate |
|
||||
| MySQL 8.0 | 已有 MySQL 基础设施 | GORM AutoMigrate |
|
||||
|
||||
**迁移步骤**:
|
||||
1. 使用 GORM `AutoMigrate` 在目标数据库创建表结构
|
||||
2. 通过 SQL 脚本导出 SQLite 数据并转换为目标数据库格式
|
||||
3. 修改配置文件中的 `database.type` 参数
|
||||
4. 重启服务并验证数据一致性
|
||||
|
||||
### 9.2 认证方案扩展
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[认证方式扩展] --> B[本地认证]
|
||||
A --> C[LDAP/AD集成]
|
||||
A --> D[OAuth2.0]
|
||||
A --> E[SAML SSO]
|
||||
|
||||
B --> B1[当前实现方案]
|
||||
C --> C1[企业内部用户统一认证]
|
||||
D --> D1[GitHub/GitLab账户登录]
|
||||
E --> E1[企业级SSO集成]
|
||||
```
|
||||
|
||||
**实现优先级**:
|
||||
1. **Phase 1**: 本地认证 + MFA (已设计)
|
||||
2. **Phase 2**: LDAP 集成 (企业高需求)
|
||||
3. **Phase 3**: OAuth2.0 (开源社区版)
|
||||
|
||||
***
|
||||
|
||||
## 10. 技术风险与缓解措施
|
||||
|
||||
| 风险项 | 影响等级 | 缓解措施 |
|
||||
|--------|---------|---------|
|
||||
| Jenkins API 结构变更 | 中 | 使用松散类型解析 + 版本兼容性测试 |
|
||||
| SQLite 并发写入冲突 | 中 | WAL 模式 + 写操作重试机制 + 升级 PostgreSQL |
|
||||
| Go 类型系统学习曲线 | 低 | 代码规范文档 + Code Review |
|
||||
| TypeScript 类型定义复杂 | 低 | 提供 `*.d.ts` 类型文件 + ESLint 规则 |
|
||||
| WebSocket 连接稳定性 | 中 | 心跳检测 + 自动重连机制 |
|
||||
| 密钥文件泄露 | 高 | 密钥文件权限控制 (chmod 600) + 密钥轮换机制 |
|
||||
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 11. 实施时间表
|
||||
|
||||
```mermaid
|
||||
gantt
|
||||
title JenBranchRBAC 实施路线图
|
||||
dateFormat YYYY-MM-DD
|
||||
section Phase 1 - MVP
|
||||
Go项目脚手架与GORM模型 :a1, 2025-11-22, 7d
|
||||
JWT认证与RBAC中间件 :a2, after a1, 7d
|
||||
Jenkins API封装与同步 :a3, after a2, 7d
|
||||
Vue3前端框架与登录页 :a4, after a1, 14d
|
||||
|
||||
section Phase 2 - 增强功能
|
||||
WebSocket实时日志推送 :b1, after a3, 7d
|
||||
前端日志组件与ANSI渲染 :b2, after a4, 7d
|
||||
构建产物解析与下载 :b3, after b1, 7d
|
||||
审计日志中间件完善 :b4, after b1, 7d
|
||||
|
||||
section Phase 3 - 企业特性
|
||||
TOTP MFA认证集成 :c1, after b3, 7d
|
||||
Webhook通知模块 :c2, after b4, 7d
|
||||
压力测试与性能优化 :c3, after c2, 7d
|
||||
Docker镜像与CI/CD流水线 :c4, after c3, 7d
|
||||
```
|
||||
|
||||
|
||||
***
|
||||
|
||||
## 12. 附录
|
||||
|
||||
### 12.1 关键技术栈版本
|
||||
|
||||
| 组件 | 版本 | 说明 |
|
||||
|------|------|------|
|
||||
| Go | 1.24+ | 后端开发语言 |
|
||||
| Gin | v1.10+ | Web 框架 |
|
||||
| GORM | v2.0+ | ORM 框架 |
|
||||
| Vue | 3.4+ | 前端框架 |
|
||||
| TypeScript | 5.0+ | 类型系统 |
|
||||
| Vuetify | 3.5+ | UI 组件库 |
|
||||
| SQLite | 3.45+ | 嵌入式数据库 |
|
||||
| Nginx | 1.26+ | 反向代理服务器 |
|
||||
|
||||
### 12.2 配置文件示例
|
||||
|
||||
**c.yaml**:
|
||||
|
||||
```yaml
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8080
|
||||
mode: release # debug/release
|
||||
|
||||
database:
|
||||
type: sqlite3
|
||||
path: ./data/jenbranchrbac.db
|
||||
max_idle_conns: 10
|
||||
max_open_conns: 100
|
||||
conn_max_lifetime: 3600
|
||||
|
||||
security:
|
||||
jwt_secret: CHANGE_THIS_SECRET_IN_PRODUCTION
|
||||
jwt_expiry: 8h
|
||||
rsa_private_key: ./keys/private.pem
|
||||
rsa_public_key: ./keys/public.pem
|
||||
bcrypt_cost: 12
|
||||
|
||||
jenkins:
|
||||
url: https://jenkins.example.com
|
||||
username: api_user
|
||||
token: YOUR_JENKINS_API_TOKEN
|
||||
sync_interval: 300 # seconds
|
||||
timeout: 30
|
||||
|
||||
logging:
|
||||
level: info # debug/info/warn/error
|
||||
format: json
|
||||
output: ./logs/app.log
|
||||
max_size: 100 # MB
|
||||
max_backups: 10
|
||||
max_age: 30 # days
|
||||
```
|
||||
|
||||
|
||||
### 12.3 参考文档
|
||||
|
||||
- Jenkins REST API 官方文档: https://www.jenkins.io/doc/book/using/remote-access-api/
|
||||
- Gin Web Framework 文档: https://gin-gonic.com/docs/
|
||||
- GORM ORM 文档: https://gorm.io/docs/
|
||||
- Vue 3 官方文档: https://vuejs.org/guide/
|
||||
- Vuetify 3 组件库: https://vuetifyjs.com/en/components/all/
|
||||
- JWT 认证最佳实践: https://datatracker.ietf.org/doc/html/rfc7519
|
||||
|
||||
***
|
||||
|
||||
**文档版本**: v1.0
|
||||
**编制日期**: 2025-11-21
|
||||
**编制人**: 系统架构师
|
||||
**审核状态**: 待评审
|
||||
165
8-CMII-RMDC/2-rmdc-jenkins-dac/jenkins-dac-prompt.md
Normal file
165
8-CMII-RMDC/2-rmdc-jenkins-dac/jenkins-dac-prompt.md
Normal file
@@ -0,0 +1,165 @@
|
||||
# Jenkins模块开发提示词
|
||||
|
||||
> 本文档为大模型提供rmdc-jenkins-branch-dac模块的开发上下文。
|
||||
|
||||
---
|
||||
|
||||
## 模块概述
|
||||
|
||||
**rmdc-jenkins-branch-dac** 是RMDC平台的Jenkins分支级权限控制与构建管理模块。
|
||||
|
||||
### 核心能力
|
||||
|
||||
1. **分支级权限控制(DAC)**: Organization → Repository → Branch 三级权限管理
|
||||
2. **Jenkins API封装**: 组织/仓库/分支/构建的CRUD操作
|
||||
3. **构建状态追踪**: 实时追踪构建进度,超时检测
|
||||
4. **DCU流程**: Docker镜像的下载、压缩、上传到MinIO
|
||||
|
||||
---
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
rmdc-jenkins-branch-dac/
|
||||
├── internal/
|
||||
│ ├── config/ # 配置
|
||||
│ ├── dao/ # 数据访问
|
||||
│ ├── handler/ # HTTP处理器
|
||||
│ ├── model/
|
||||
│ │ ├── dto/ # 请求/响应
|
||||
│ │ └── entity/ # 数据库实体
|
||||
│ └── service/ # 业务逻辑
|
||||
└── pkg/
|
||||
└── jenkins/
|
||||
└── client.go # Jenkins HTTP Client
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## API设计规范
|
||||
|
||||
> **重要**: 使用POST + RequestBody,避免PathVariables
|
||||
|
||||
### 请求示例
|
||||
|
||||
```go
|
||||
// ✅ 正确方式
|
||||
type GetBuildRequest struct {
|
||||
OrganizationFolder string `json:"organization_folder"`
|
||||
RepositoryName string `json:"repository_name"`
|
||||
BranchName string `json:"branch_name"`
|
||||
BuildNumber int `json:"build_number"`
|
||||
}
|
||||
|
||||
// ❌ 避免使用
|
||||
// GET /api/jenkins/organizations/{org}/repositories/{repo}/branches/{branch}/builds/{number}
|
||||
```
|
||||
|
||||
### 接口清单
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/jenkins/organizations/list` | POST | 获取组织列表 |
|
||||
| `/api/jenkins/repositories/list` | POST | 获取仓库列表 |
|
||||
| `/api/jenkins/branches/list` | POST | 获取分支列表 |
|
||||
| `/api/jenkins/builds/list` | POST | 获取构建列表 |
|
||||
| `/api/jenkins/builds/trigger` | POST | 触发构建 |
|
||||
| `/api/jenkins/builds/detail` | POST | 获取构建详情 |
|
||||
| `/api/dcu/start` | POST | 启动DCU任务 |
|
||||
| `/api/dcu/status` | POST | 查询DCU状态 |
|
||||
|
||||
---
|
||||
|
||||
## 核心数据结构
|
||||
|
||||
```go
|
||||
// Organization Jenkins组织
|
||||
type Organization struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
Name string `gorm:"uniqueIndex"`
|
||||
DisplayName string
|
||||
URL string
|
||||
LastSyncAt time.Time
|
||||
}
|
||||
|
||||
// Repository Jenkins仓库
|
||||
type Repository struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
OrganizationID int64 `gorm:"index"`
|
||||
Name string
|
||||
URL string
|
||||
}
|
||||
|
||||
// Branch Jenkins分支
|
||||
type Branch struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
RepositoryID int64 `gorm:"index"`
|
||||
Name string
|
||||
LastBuildNumber int
|
||||
LastBuildResult string
|
||||
}
|
||||
|
||||
// Build Jenkins构建
|
||||
type Build struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
BranchID int64 `gorm:"index"`
|
||||
BuildNumber int
|
||||
Result string
|
||||
Timestamp int64
|
||||
Duration int64
|
||||
EstimatedDuration int64
|
||||
IsBuilding bool
|
||||
ArtifactDockerImage string
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Jenkins API调用
|
||||
|
||||
### URL路径规则
|
||||
|
||||
```
|
||||
{JENKINS_URL}/job/{ORG}/api/json # 获取组织信息
|
||||
{JENKINS_URL}/job/{ORG}/job/{REPO}/api/json # 获取仓库信息
|
||||
{JENKINS_URL}/job/{ORG}/job/{REPO}/job/{BRANCH}/api/json # 获取分支信息
|
||||
{JENKINS_URL}/job/{ORG}/job/{REPO}/job/{BRANCH}/build # 触发构建
|
||||
```
|
||||
|
||||
### 分支名编码
|
||||
|
||||
- `/` → `%2F` (例: `feature/login` → `feature%2Flogin`)
|
||||
|
||||
---
|
||||
|
||||
## 权限校验
|
||||
|
||||
权限通过中间件校验,Handler无需处理:
|
||||
|
||||
```go
|
||||
func (h *BuildHandler) TriggerBuild(c *gin.Context) {
|
||||
// 此时已通过权限校验
|
||||
var req dto.TriggerBuildRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, err)
|
||||
return
|
||||
}
|
||||
|
||||
resp, err := h.buildService.TriggerBuild(c.Request.Context(), &req)
|
||||
if err != nil {
|
||||
response.Error(c, err)
|
||||
return
|
||||
}
|
||||
response.Success(c, resp)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| [1-jenkins-branch-dac-DDS.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/1-jenkins-branch-dac-DDS.md) | 完整详细设计 |
|
||||
| [5-RMDC项目权限设计方案.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/5-RMDC项目权限设计方案.md) | 权限设计 |
|
||||
| [9-rmdc-dcu模块设计方案.md](file:///c:/Users/wddsh/Documents/IdeaProjects/ProjectAGiPrompt/8-CMII-RMDC/2-Jenkins模块/9-rmdc-dcu模块设计方案.md) | DCU模块设计 |
|
||||
230
8-CMII-RMDC/3-rmdc-exchange-hub/1-rmdc-exchange-hub-DDS.md
Normal file
230
8-CMII-RMDC/3-rmdc-exchange-hub/1-rmdc-exchange-hub-DDS.md
Normal file
@@ -0,0 +1,230 @@
|
||||
# RMDC-exchange-hub Detailed Design Specification
|
||||
|
||||
### 项目划分说明
|
||||
|
||||
1. RMDC-exchange-hub(MQTTX) 是Server端
|
||||
2. RMDC-watchdog是Client
|
||||
1. RMDC-watchdog RMDC-watchdog-agent RMDC-watchdog-node三者运行在外部环境,作为单个项目
|
||||
2. 下文简称RMDC-watchdog代表的是一个项目,单个项目与 RMDC-exchange-hub(MQTTX)不在同一个网络中,需要跨越公网交互
|
||||
3. 考虑到兼容性,假设所有的项目均只能单方面跨公网访问RMDC-exchange-hub(MQTTX)
|
||||
4. 有部分项目无法访问RMDC-exchange-hub(MQTTX),是纯内网的环境
|
||||
3. MQTTX是消息中间件
|
||||
1. 借用现有的消息中间件,处理单向网络环境下的指令 信息处理问题
|
||||
2. 解决队列消息持久化问题
|
||||
3. 整体信息流程为 RMDC-exchange-hub <-- MQTTX <-- RMDC-watchdog
|
||||
4. MQTTX <-- RMDC-watchdog是弱网络环境,保证信息传递的准确性
|
||||
5. RMDC-exchange-hub <-- MQTTX是网络质量很好
|
||||
|
||||
## 指令数据处理流程
|
||||
|
||||
### 指令数据流向说明
|
||||
|
||||
1. RMDC-watchdog向RMDC-exchange-hub(MQTTX)发送信息成为 上行
|
||||
2. RMDC-exchange-hub(MQTTX)向RMDC-watchdog发送信息成为 下行
|
||||
|
||||
### 指令数据消息说明
|
||||
|
||||
1. RMDC-watchdog需要接收、上传多种不同模块的信息,并作出相应的解析
|
||||
1. 接收下行的command指令
|
||||
1. 授权信息
|
||||
2. 日志指令
|
||||
3. 主机执行
|
||||
4. k8s执行指令
|
||||
5. 业务更新指令
|
||||
2. 发送上行的消息message类别
|
||||
1. 监控信息
|
||||
2. 日志内容
|
||||
3. 主机执行结果
|
||||
4. k8s执行结果
|
||||
5. 业务更新结果
|
||||
2. mqtt是明文传输的,敏感信息需要进行加密处理
|
||||
3. RMDC-exchange-hub 维护项目在线状态,超时未心跳自动标记离线并告警
|
||||
|
||||
### 项目启动注册流程
|
||||
|
||||
#### 项目信息注册流程
|
||||
|
||||
1. 需要从 rmdc-project-management 创建项目的信息
|
||||
1. 项目的名称
|
||||
2. 项目的命名空间
|
||||
3. 项目ID Project_ID
|
||||
1. 生成规则为 命名空间_<8位小写字符数字随机数>
|
||||
4. 项目的一级授权密钥 tier_one_secret
|
||||
5. 项目的一级授权密钥时间偏移值 time_offset_allowed 单位秒
|
||||
6. 项目的授权有效期 authorization_duration 单位天
|
||||
7. 项目的授权类型 authorization_type 永久授权或者时效授权
|
||||
8. 项目的二级授权密钥 tier_two_secret
|
||||
|
||||
#### 正常的rmdc-watchdog启动流程
|
||||
|
||||
1. 需要根据 rmdc-project-management 创建的信息启动程序
|
||||
1. 见上文
|
||||
2. 项目ID使用项目信息中的,不在rmdc-watchdog中生成
|
||||
2. 采用“挑战-应答”机制,确保边缘节点合法性 正常的流程如下
|
||||
1. 尝试连接MQTTX,创建如下的Topic
|
||||
1. 发送Topic
|
||||
1. wdd/RDMC/command/up
|
||||
2. wdd/RDMC/message/up
|
||||
2. 接收Topic
|
||||
1. wdd/RDMC/command/down/<project_id>
|
||||
2. wdd/RDMC/message/down/<project_id>
|
||||
2. 发送上行注册command信息, 到wdd/RDMC/command/up,包含项目的所有信息
|
||||
1. 信息需要加密
|
||||
3. RMDC-exchange-hub(MQTTX)解析注册command
|
||||
1. 需要调用 rmdc-project-management 的接口
|
||||
1. 验证项目信息的合法性
|
||||
2. 验证项目的一级TOTP密码是否正确 (开关功能,可以不强制)
|
||||
2. 发送下行 注册成功message到 wdd/RDMC/message/down/<project_id>
|
||||
1. 附加 随机信息, 32位随机小写字母+数字
|
||||
3. 发送下行 注册command到 wdd/RDMC/command/down/<project_id>
|
||||
1. 验证项目的一级TOTP密码是否正确 (开关功能,可以不强制)
|
||||
4. RMDC-watchdog获取下行的注册 command和message
|
||||
1. 成功接收到message,解析其中的随机信息
|
||||
2. 接收到command之后
|
||||
1. 组装message中的随机信息为新的上行Message
|
||||
2. 发送上行Message到 wdd/RDMC/message/up
|
||||
5. RMDC-exchange-hub(MQTTX)解析到该项目的注册成功Message
|
||||
1. 验证随机信息的正确性
|
||||
2. 代表该项目初始化连接成功
|
||||
|
||||
#### rmdc-watchdog无法连接到MQTTX的流程
|
||||
|
||||
1. 仍然保持项目信息注册流程
|
||||
|
||||
### Command Message 生命周期与持久化流程
|
||||
|
||||
#### Command生命周期
|
||||
|
||||
1. 指令的生命周期流程指的是
|
||||
1. 指令从从业务模块来,包含模块名称,包含指令类型,包含业务下发人
|
||||
2. 指令包装成command消息,生成指令唯一ID
|
||||
3. 指令发送至MQTTX,记录指令下发时间戳
|
||||
4. 指令从MQTTX下发到RMDC-watchdog,记录指令接收时间戳
|
||||
5. 指令从RMDC-watchdog下发到执行体
|
||||
6. 指令从执行体返回到RMDC-watchdog
|
||||
7. RMDC-watchdog将指令转换为Message消息
|
||||
8. 消息从RMDC-watchdog返回到MQTTX, 记录消息上行时间戳
|
||||
9. 消息从MQTTX返回到RMDC-exchange-hub,记录消息返回时间戳
|
||||
10. 追踪计算每一阶段的耗时
|
||||
1. 指令下发耗时 = 指令接收时间戳 - 指令下发时间戳
|
||||
2. 指令执行耗时 = 消息上行时间戳 - 指令接收时间戳
|
||||
3. 指令上行耗时 = 消息返回时间戳 - 消息上行时间戳
|
||||
11. 消息从RMDC-exchange-hub返回到业务模块
|
||||
2. 利用类似状态机的形式追踪指令的生命周期
|
||||
3. 指令消息生命周期生命体
|
||||
1. 业务模块名称
|
||||
2. 指令类型
|
||||
3. 项目ID
|
||||
4. 指令下发人
|
||||
5. 指令下发时间
|
||||
6. 指令唯一ID,构建方式为 <指令类型>-<项目ID>-<时间格式 yyMMddHHmmss>
|
||||
7. 异步或者同步指令
|
||||
4. 异步和同步指令,如果实现困难,与现有架构冲突,暂时不用实现
|
||||
1. 异步指令
|
||||
1. 指令下发之后,不等待回复
|
||||
2. 指令消息返回之后
|
||||
1. 直接入库
|
||||
2. 可以通过 rmdc-notice-center 进行消息通知
|
||||
2. 同步指令
|
||||
1. 指令下发之后,等待回复
|
||||
2. 指令消息返回之后
|
||||
1. 直接返回给调用的业务模块
|
||||
2. 入库
|
||||
3. 也可以进行消息通知
|
||||
|
||||
#### Command 生命周期持久化
|
||||
1. 指令的生命周期持久化
|
||||
1. 负责指令生命周期的持久化
|
||||
1. 指令的完整信息保存
|
||||
2. 指令对应回复Message信息保存
|
||||
2. 优化数据库存储结构
|
||||
1. 能够快速查询到指令的完整信息 以及 指令对应的Message回复信息
|
||||
2. 能够快速查询到指令的回复信息
|
||||
3. 指令回复消息需要持久化
|
||||
2. 下行指令 Command 持久化
|
||||
1. 每条下发的指令Command 都应该持久化保存
|
||||
3. 接收上行 Message 持久化
|
||||
1. 每条接收的上行Message 都应该持久化保存
|
||||
2. 优化Message的存储
|
||||
1. 日志类型信息上行,不保存日志的详细内容
|
||||
2. 监控类型信息上行,不保存监控的详细内容,由rmdc-monitor-center进行持久化
|
||||
|
||||
### 指令下行 处理流程
|
||||
|
||||
1. 参考Command生命周期
|
||||
|
||||
### 消息上行 处理流程
|
||||
|
||||
1. 消息上行存在两种情况
|
||||
1. 指令回复消息
|
||||
2. 心跳及监视消息上行
|
||||
2. 指令回复消息
|
||||
1. 指令回复消息需要持久化
|
||||
2. 此类消息需要与指令生命周期进行关联
|
||||
3. 此类消息处理之后,需要返回至原业务调用模块
|
||||
3. 项目心跳消息上行
|
||||
1. 项目心跳消息需要持久化,参考 MQTTX状态及项目在线状态
|
||||
4. 监视消息上行
|
||||
1. 监视消息上行需要发送给 rmdc-monitor-center
|
||||
|
||||
### 模块前端展示
|
||||
|
||||
1. 指令查询展示,支持筛选,查询,导出
|
||||
1. 指令的生命周期展示
|
||||
2. 指令的执行结果展示
|
||||
3. 指令的执行日志展示
|
||||
|
||||
## MQTTX状态及项目在线状态
|
||||
|
||||
1. 需要提供项目在线状态查询接口,特定时间段的在线状态
|
||||
2. 需要提供MQTTX在线状态查询接口,特定时间段的在线状态
|
||||
|
||||
### 存活连接状态持久化
|
||||
|
||||
1. 采用时序数据存储类型
|
||||
2. MQTTX状态持久化展示
|
||||
1. rmdc-exchange-hub项目启动时候,创建MQTTX在线状态表
|
||||
2. rmdc-exchange-hub需要每5分钟检查MQTTX的状态
|
||||
3. 检测到MQTTX在线,则更新MQTTX在线状态表
|
||||
4. MQTTX离线,不需要更新,状态表应该默认该时间点不在线
|
||||
3. 项目在线状态持久化展示
|
||||
1. rmdc-watchdog项目注册时候,为该项目创建项目在线状态表
|
||||
2. rmdc-watchdog需要定期发送心跳存活信息
|
||||
3. 检测到心跳信息,则更新项目在线状态表
|
||||
4. 项目离线,不需要更新,状态表应该默认该时间点不在线
|
||||
|
||||
### 模块前端展示
|
||||
|
||||
1. 所有项目的连接状态查看
|
||||
1. 能够查看单个项目的具体连接内容
|
||||
2. 展示能够查看所有项目的连接状态
|
||||
3. 能够统计单个项目的离线次数
|
||||
4. 可以利用时序数据存储,然后做成uptime的前端监视页面
|
||||
1. 展示一段历史时间内的在线状态,在线就是绿色,离线就是红色
|
||||
2. 展示在线时间段支持调节
|
||||
2. 查看MQTTX的状态
|
||||
1. 查看MQTTX的历史存活状态
|
||||
2. 查看MQTTX的历史消息数量
|
||||
3. 查看MQTTX的实时消息数量
|
||||
4. 查看MQTTX的队列数量等
|
||||
5.
|
||||
|
||||
## 消息报文与安全要求
|
||||
|
||||
1. **统一报文包装**:`message_id`(UUID)、`type`(command/data)、`project_id`、`timestamp`(ms)、`version`、`payload`(JSON)、`signature`(HMAC-SHA256)、`encrypted`(bool)、`retry_no`(int)。
|
||||
2. **敏感字段加密**:授权文件/TOTP/主机账号/业务密钥使用 AES-256-GCM,加密后仍需签名。
|
||||
3. **幂等与去重**:按 `message_id + project_id` 去重,重复上行直接 ACK,不重复写库。
|
||||
4. **访问控制**:所有下行指令需验证调用方权限(业务模块→exchange-hub),所有上行需验证签名+TOTP(开关)。
|
||||
|
||||
## 可靠性与重试策略
|
||||
|
||||
1. **QoS**:上下行默认至少一次(At-Least-Once),前端/业务模块需幂等。
|
||||
2. **ACK/超时**:指令下发等待 watchdog ACK,默认超时 30 秒、重试 3 次,超时进入告警并记录审计。
|
||||
3. **指令追踪**:`command_tracker` 记录 sent_at/acked_at/started_at/completed_at,`command_result` 记录 start_time/end_time/duration/received_at,缺失字段展示为 NA。
|
||||
4. **断线补传**:watchdog 缓存最近 N 条结果,重连后批量上报;exchange-hub 支持批量 up 消息,需按 message_id 去重。
|
||||
|
||||
## 异常与降级
|
||||
|
||||
1. **错误码**:`EXH-4xx`(参数/鉴权),`EXH-5xx`(内部错误),`EXH-MQTT-xxx`(MQTT 通道异常),`EXH-AUTH-xxx`(授权/签名/TOTP 异常)。
|
||||
2. **降级通道**:MQTT 不可用时开启 HTTP 临时通道(同样签名+TOTP),仅允许 register/auth/exec_result,其他指令暂停。
|
||||
3. **安全告警**:签名/TOTP 失败触发 notice-center 告警并写审计。
|
||||
@@ -0,0 +1,475 @@
|
||||
# RDMC Exchange Hub 架构流程图
|
||||
|
||||
## 1. Exchange Hub 模块架构总览
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "RDMC平台 (内网)"
|
||||
subgraph "rmdc-exchange-hub 模块"
|
||||
MQTTSvc["MQTTService<br/>消息服务层<br/>(Paho MQTT Client)"]
|
||||
MsgRouter["MessageRouter<br/>消息路由器"]
|
||||
|
||||
subgraph "消息处理器 Handlers"
|
||||
RegHandler["RegisterHandler<br/>注册处理"]
|
||||
AuthHandler["AuthHandler<br/>授权处理"]
|
||||
ExecHandler["ExecHandler<br/>执行处理"]
|
||||
LogHandler["LogHandler<br/>日志处理"]
|
||||
MonitorHandler["MonitorHandler<br/>监控处理"]
|
||||
AlertHandler["AlertHandler<br/>告警处理"]
|
||||
end
|
||||
|
||||
subgraph "状态管理"
|
||||
ConnMgr["ConnectionManager<br/>连接管理"]
|
||||
StateMgr["StateManager<br/>状态机管理"]
|
||||
CmdTracker["CommandTracker<br/>指令追踪"]
|
||||
end
|
||||
|
||||
subgraph "同步指令支持"
|
||||
SyncMgr["SyncCommandManager<br/>同步指令管理"]
|
||||
ResultCache["ResultCache<br/>结果缓存"]
|
||||
end
|
||||
end
|
||||
|
||||
subgraph "业务模块集成"
|
||||
ProjectMgmt["project-management<br/>项目管理"]
|
||||
WDCenter["watchdog-center<br/>一级授权中心"]
|
||||
LogCenter["日志中心"]
|
||||
MonitorCenter["监控中心"]
|
||||
Operator["执行中心"]
|
||||
Notice["通知中心"]
|
||||
Audit["审计模块"]
|
||||
end
|
||||
|
||||
DB[(PostgreSQL<br/>数据持久化)]
|
||||
end
|
||||
|
||||
MQTT[(MQTT Broker<br/>消息中间件)]
|
||||
|
||||
subgraph "外部项目环境"
|
||||
Watchdog["rmdc-watchdog<br/>边缘代理"]
|
||||
WDNode["watchdog-node<br/>主机守护"]
|
||||
WDAgent["watchdog-agent<br/>业务代理"]
|
||||
end
|
||||
|
||||
%% MQTT 连接
|
||||
MQTTSvc <=="订阅/发布"==> MQTT
|
||||
MQTT <=="跨公网"==> Watchdog
|
||||
|
||||
%% 内部路由
|
||||
MQTTSvc --> MsgRouter
|
||||
MsgRouter --> RegHandler
|
||||
MsgRouter --> AuthHandler
|
||||
MsgRouter --> ExecHandler
|
||||
MsgRouter --> LogHandler
|
||||
MsgRouter --> MonitorHandler
|
||||
MsgRouter --> AlertHandler
|
||||
|
||||
%% 注册与授权流程
|
||||
RegHandler --> ProjectMgmt
|
||||
AuthHandler --> WDCenter
|
||||
ProjectMgmt -.项目信息.-> RegHandler
|
||||
WDCenter -.授权信息.-> AuthHandler
|
||||
|
||||
%% 处理器到业务模块
|
||||
ExecHandler --> Operator
|
||||
LogHandler --> LogCenter
|
||||
MonitorHandler --> MonitorCenter
|
||||
AlertHandler --> Notice
|
||||
|
||||
%% 状态管理
|
||||
RegHandler --> ConnMgr
|
||||
MsgRouter --> StateMgr
|
||||
ExecHandler --> CmdTracker
|
||||
|
||||
%% 同步指令支持
|
||||
ExecHandler --> SyncMgr
|
||||
LogHandler --> SyncMgr
|
||||
SyncMgr --> ResultCache
|
||||
|
||||
%% 数据持久化
|
||||
ConnMgr --> DB
|
||||
StateMgr --> DB
|
||||
CmdTracker --> DB
|
||||
Audit --> DB
|
||||
|
||||
%% Watchdog 内部
|
||||
Watchdog <--> WDNode
|
||||
Watchdog <--> WDAgent
|
||||
|
||||
style MQTTSvc fill:#ff6b6b,stroke:#c92a2a,stroke-width:3px
|
||||
style MQTT fill:#ffd43b,stroke:#f08c00,stroke-width:2px
|
||||
style Watchdog fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
|
||||
style SyncMgr fill:#a9e34b,stroke:#5c940d,stroke-width:2px
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 2. 消息分类与 Topic 设计
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "上行通道 (Watchdog → Exchange Hub)"
|
||||
direction TB
|
||||
WD1[Watchdog Client]
|
||||
|
||||
CmdUp["📤 wdd/RDMC/command/up<br/>指令上行"]
|
||||
MsgUp["📤 wdd/RDMC/message/up<br/>数据上行"]
|
||||
|
||||
WD1 -->|Publish| CmdUp
|
||||
WD1 -->|Publish| MsgUp
|
||||
|
||||
subgraph "上行指令类型"
|
||||
UCR[register - 项目注册]
|
||||
UCA[auth_request - 授权请求]
|
||||
end
|
||||
|
||||
subgraph "上行数据类型"
|
||||
UDM[monitor - 监控数据]
|
||||
UDL[log_result - 日志结果]
|
||||
UDE[exec_result - 执行结果]
|
||||
UDA[alert - 告警信息]
|
||||
UDH[heartbeat - 心跳数据]
|
||||
UDC[register_complete - 注册完成]
|
||||
end
|
||||
|
||||
CmdUp -.- UCR
|
||||
CmdUp -.- UCA
|
||||
MsgUp -.- UDM
|
||||
MsgUp -.- UDL
|
||||
MsgUp -.- UDE
|
||||
MsgUp -.- UDA
|
||||
MsgUp -.- UDH
|
||||
MsgUp -.- UDC
|
||||
end
|
||||
|
||||
subgraph "下行通道 (Exchange Hub → Watchdog)"
|
||||
direction TB
|
||||
EH1[Exchange Hub]
|
||||
|
||||
CmdDown["📥 wdd/RDMC/command/down/{project_id}<br/>指令下行"]
|
||||
MsgDown["📥 wdd/RDMC/message/down/{project_id}<br/>数据下行"]
|
||||
|
||||
EH1 -->|Publish| CmdDown
|
||||
EH1 -->|Publish| MsgDown
|
||||
|
||||
subgraph "下行指令类型"
|
||||
DCA[auth_response - 授权响应]
|
||||
DCL[log_query - 日志查询]
|
||||
DCE[host_exec - 主机执行]
|
||||
DCK[k8s_exec - K8s执行]
|
||||
DCU[update - 业务更新]
|
||||
DCR[auth_revoke - 授权撤销]
|
||||
end
|
||||
|
||||
subgraph "下行数据类型"
|
||||
DDR[register_ack - 注册确认]
|
||||
DDA[auth_info - 授权信息]
|
||||
end
|
||||
|
||||
CmdDown -.- DCA
|
||||
CmdDown -.- DCL
|
||||
CmdDown -.- DCE
|
||||
CmdDown -.- DCK
|
||||
CmdDown -.- DCU
|
||||
CmdDown -.- DCR
|
||||
MsgDown -.- DDR
|
||||
MsgDown -.- DDA
|
||||
end
|
||||
|
||||
style CmdUp fill:#ffd43b,stroke:#f08c00
|
||||
style MsgUp fill:#74c0fc,stroke:#1c7ed6
|
||||
style CmdDown fill:#ff8787,stroke:#c92a2a
|
||||
style MsgDown fill:#a9e34b,stroke:#5c940d
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 消息结构设计
|
||||
|
||||
### 3.1 基础消息结构
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class BaseMessage {
|
||||
+string MessageID
|
||||
+string Type
|
||||
+string ProjectID
|
||||
+int64 Timestamp
|
||||
+string Version
|
||||
}
|
||||
|
||||
class CommandMessage {
|
||||
+CommandType CommandType
|
||||
+any Payload
|
||||
+string Signature
|
||||
}
|
||||
|
||||
class DataMessage {
|
||||
+DataType DataType
|
||||
+any Payload
|
||||
+bool Encrypted
|
||||
}
|
||||
|
||||
BaseMessage <|-- CommandMessage
|
||||
BaseMessage <|-- DataMessage
|
||||
```
|
||||
|
||||
### 3.2 执行模块消息结构
|
||||
|
||||
```mermaid
|
||||
classDiagram
|
||||
class K8sExecCommand {
|
||||
+string CommandID
|
||||
+string Namespace
|
||||
+string Resource
|
||||
+string Name
|
||||
+string Action
|
||||
+string Container
|
||||
+[]string Command
|
||||
+int Timeout
|
||||
+int TailLines
|
||||
+bool FollowLogs
|
||||
}
|
||||
|
||||
class HostExecCommand {
|
||||
+string CommandID
|
||||
+string HostID
|
||||
+string Action
|
||||
+string Script
|
||||
+[]string Args
|
||||
+int Timeout
|
||||
}
|
||||
|
||||
class ExecResult {
|
||||
+string CommandID
|
||||
+string Status
|
||||
+int ExitCode
|
||||
+string Output
|
||||
+string Error
|
||||
+int64 StartTime
|
||||
+int64 EndTime
|
||||
+int64 Duration
|
||||
}
|
||||
|
||||
class CommandMessage {
|
||||
+CommandType CommandType
|
||||
+any Payload
|
||||
}
|
||||
|
||||
CommandMessage --> K8sExecCommand : Payload (k8s_exec)
|
||||
CommandMessage --> HostExecCommand : Payload (host_exec)
|
||||
|
||||
class DataMessage {
|
||||
+DataType DataType
|
||||
+any Payload
|
||||
}
|
||||
|
||||
DataMessage --> ExecResult : Payload (exec_result)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 指令生命周期状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Pending: 创建指令
|
||||
|
||||
Pending --> Sent: 发送到MQTT
|
||||
Sent --> Delivered: Watchdog确认接收
|
||||
Delivered --> Running: 开始执行
|
||||
|
||||
Running --> Success: 执行成功
|
||||
Running --> Failed: 执行失败
|
||||
Running --> Timeout: 执行超时
|
||||
|
||||
Sent --> Timeout: 未送达超时
|
||||
Delivered --> Timeout: 未执行超时
|
||||
|
||||
Success --> [*]
|
||||
Failed --> [*]
|
||||
Timeout --> [*]
|
||||
|
||||
note right of Pending: 状态持久化到数据库<br/>记录指令下发时间戳
|
||||
note right of Running: 可查询实时输出<br/>支持同步等待
|
||||
note right of Timeout: 触发告警通知<br/>记录超时原因
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 项目连接状态管理
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Offline: 初始状态
|
||||
|
||||
Offline --> Connecting: 收到注册请求
|
||||
Connecting --> Verifying: 发送挑战随机数
|
||||
Verifying --> Online: 完成挑战-应答验证
|
||||
|
||||
Online --> Online: 心跳刷新
|
||||
Online --> Offline: 心跳超时<br/>(默认30秒)
|
||||
|
||||
Online --> Disconnecting: 主动下线
|
||||
Disconnecting --> Offline: 确认下线
|
||||
|
||||
note right of Connecting: 解析项目信息<br/>验证TOTP
|
||||
note right of Verifying: 挑战-应答机制<br/>32位随机数验证
|
||||
note right of Online: 定期心跳(5秒)<br/>监控数据上报
|
||||
note right of Offline: 触发离线告警<br/>通知相关用户
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. MQTT Client 架构对比
|
||||
|
||||
### 6.1 Exchange Hub (Server 端)
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Exchange Hub MQTT 架构"
|
||||
Config[MQTTConfig<br/>连接配置]
|
||||
Client[MQTT Client<br/>Paho v3]
|
||||
|
||||
subgraph "订阅 (Subscribe)"
|
||||
SubCmd[wdd/RDMC/command/up]
|
||||
SubMsg[wdd/RDMC/message/up]
|
||||
end
|
||||
|
||||
subgraph "发布 (Publish)"
|
||||
PubCmd["wdd/RDMC/command/down/{project_id}"]
|
||||
PubMsg["wdd/RDMC/message/down/{project_id}"]
|
||||
end
|
||||
|
||||
Router[消息路由器<br/>MessageRouter]
|
||||
HandlerPool[Handler Pool<br/>处理器池]
|
||||
|
||||
Config --> Client
|
||||
Client --> SubCmd
|
||||
Client --> SubMsg
|
||||
SubCmd --> Router
|
||||
SubMsg --> Router
|
||||
Router --> HandlerPool
|
||||
|
||||
HandlerPool --> Client
|
||||
Client --> PubCmd
|
||||
Client --> PubMsg
|
||||
end
|
||||
|
||||
style Client fill:#ff6b6b,stroke:#c92a2a,stroke-width:2px
|
||||
```
|
||||
|
||||
### 6.2 Watchdog (Client 端)
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "Watchdog MQTT 架构"
|
||||
Config[MQTTConfig<br/>连接配置]
|
||||
Client[MQTT Client<br/>Paho v3]
|
||||
ProjectID[ProjectID]
|
||||
|
||||
subgraph "订阅 (Subscribe)"
|
||||
SubCmd["wdd/RDMC/command/down/{project_id}"]
|
||||
SubMsg["wdd/RDMC/message/down/{project_id}"]
|
||||
end
|
||||
|
||||
subgraph "发布 (Publish)"
|
||||
PubCmd[wdd/RDMC/command/up]
|
||||
PubMsg[wdd/RDMC/message/up]
|
||||
end
|
||||
|
||||
CmdExecutor[CommandExecutor<br/>指令执行器]
|
||||
DataCollector[DataCollector<br/>数据采集器]
|
||||
|
||||
Config --> Client
|
||||
ProjectID --> Client
|
||||
Client --> SubCmd
|
||||
Client --> SubMsg
|
||||
SubCmd --> CmdExecutor
|
||||
SubMsg --> CmdExecutor
|
||||
|
||||
DataCollector --> Client
|
||||
Client --> PubCmd
|
||||
Client --> PubMsg
|
||||
end
|
||||
|
||||
style Client fill:#4ecdc4,stroke:#087f5b,stroke-width:2px
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 安全设计
|
||||
|
||||
```mermaid
|
||||
graph LR
|
||||
subgraph "安全机制"
|
||||
TLS["TLS/SSL加密<br/>传输层安全"]
|
||||
Auth["MQTT认证<br/>用户名/密码"]
|
||||
Sign["消息签名<br/>HMAC-SHA256"]
|
||||
Encrypt["敏感数据加密<br/>AES-256-GCM"]
|
||||
TOTP["TOTP验证<br/>时间戳校验"]
|
||||
end
|
||||
|
||||
subgraph "应用场景"
|
||||
Conn[连接建立] --> TLS
|
||||
Conn --> Auth
|
||||
|
||||
Cmd[指令传输] --> Sign
|
||||
Cmd --> Encrypt
|
||||
|
||||
Reg[项目注册] --> TOTP
|
||||
Reg --> Sign
|
||||
end
|
||||
|
||||
style TLS fill:#a5d8ff,stroke:#1c7ed6
|
||||
style Auth fill:#a5d8ff,stroke:#1c7ed6
|
||||
style Sign fill:#ffd8a8,stroke:#f08c00
|
||||
style Encrypt fill:#ffd8a8,stroke:#f08c00
|
||||
style TOTP fill:#d3f9d8,stroke:#087f5b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 8. 与业务模块集成架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "业务模块层"
|
||||
PM["project-management<br/>项目管理"]
|
||||
WC["watchdog-center<br/>一级授权中心"]
|
||||
LC["log-center<br/>日志中心"]
|
||||
MC["monitor-center<br/>监控中心"]
|
||||
OP["octopus-operator<br/>执行中心"]
|
||||
NC["notice-center<br/>通知中心"]
|
||||
end
|
||||
|
||||
subgraph "Exchange-Hub 接口层"
|
||||
RegAPI["RegisterAPI<br/>注册接口"]
|
||||
AuthAPI["AuthAPI<br/>授权接口"]
|
||||
CmdAPI["CommandAPI<br/>指令接口"]
|
||||
QueryAPI["QueryAPI<br/>查询接口"]
|
||||
end
|
||||
|
||||
subgraph "Exchange-Hub 核心"
|
||||
MQTTSvc["MQTTService"]
|
||||
Handlers["Handlers"]
|
||||
StateDB["StateDB"]
|
||||
end
|
||||
|
||||
PM --> RegAPI
|
||||
WC --> AuthAPI
|
||||
LC --> CmdAPI
|
||||
MC --> CmdAPI
|
||||
OP --> CmdAPI
|
||||
NC <-- QueryAPI
|
||||
|
||||
RegAPI --> MQTTSvc
|
||||
AuthAPI --> MQTTSvc
|
||||
CmdAPI --> MQTTSvc
|
||||
QueryAPI --> StateDB
|
||||
|
||||
MQTTSvc --> Handlers
|
||||
Handlers --> StateDB
|
||||
|
||||
style MQTTSvc fill:#ff6b6b,stroke:#c92a2a
|
||||
```
|
||||
@@ -0,0 +1,232 @@
|
||||
# RMDC-Exchange-Hub 指令执行时间计算规范
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本文档定义了 RMDC-Exchange-Hub 模块中指令执行全生命周期的时间追踪与计算规范。
|
||||
|
||||
---
|
||||
|
||||
## 2. 时间点定义
|
||||
|
||||
### 2.1 指令生命周期时间点
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant BM as 业务模块
|
||||
participant EH as Exchange Hub
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as Watchdog
|
||||
participant EX as 执行体
|
||||
|
||||
Note over EH: ① created_at<br/>指令创建时间
|
||||
BM->>EH: 发起指令请求
|
||||
|
||||
Note over EH: ② sent_at<br/>发送到MQTT时间
|
||||
EH->>MQTT: Publish指令
|
||||
|
||||
Note over WD: ③ acked_at<br/>Watchdog确认接收
|
||||
MQTT->>WD: 推送指令
|
||||
WD-->>EH: (可选) ACK确认
|
||||
|
||||
Note over WD: ④ started_at<br/>开始执行时间
|
||||
WD->>EX: 调用执行体
|
||||
|
||||
Note over EX: ⑤ start_time (ms)<br/>执行体内部开始
|
||||
EX->>EX: 执行指令...
|
||||
Note over EX: ⑥ end_time (ms)<br/>执行体内部结束
|
||||
|
||||
EX->>WD: 返回结果
|
||||
|
||||
Note over WD: ⑦ 消息上行
|
||||
WD->>MQTT: ExecResult上行
|
||||
|
||||
Note over EH: ⑧ received_at<br/>Exchange Hub接收
|
||||
MQTT->>EH: 推送结果
|
||||
|
||||
Note over EH: ⑨ completed_at<br/>指令完成时间
|
||||
```
|
||||
|
||||
### 2.2 时间点存储位置
|
||||
|
||||
| 时间点 | 字段名 | 存储表 | 类型 | 说明 |
|
||||
|-------|-------|-------|------|------|
|
||||
| 指令创建 | `created_at` | command_trackers | TIMESTAMP | 自动记录 |
|
||||
| 发送到MQTT | `sent_at` | command_trackers | TIMESTAMP | 调用MQTT Publish时记录 |
|
||||
| Watchdog确认 | `acked_at` | command_trackers | TIMESTAMP | 收到ACK消息时记录 |
|
||||
| 开始执行 | `started_at` | command_trackers | TIMESTAMP | 收到running状态时记录 |
|
||||
| 执行开始(内部) | `start_time` | command_results | INT64 (ms) | Watchdog侧记录 |
|
||||
| 执行结束(内部) | `end_time` | command_results | INT64 (ms) | Watchdog侧记录 |
|
||||
| 结果接收 | `received_at` | command_results | TIMESTAMP | Exchange Hub接收结果时记录 |
|
||||
| 指令完成 | `completed_at` | command_trackers | TIMESTAMP | 更新为终态时记录 |
|
||||
|
||||
---
|
||||
|
||||
## 3. 时间耗时计算公式
|
||||
|
||||
### 3.1 核心耗时指标
|
||||
|
||||
| 指标名称 | 计算公式 | 单位 | 含义 |
|
||||
|---------|---------|------|------|
|
||||
| **指令下发耗时** | `acked_at - sent_at` | ms | 指令从Exchange Hub到达Watchdog的网络耗时 |
|
||||
| **指令执行耗时** | `end_time - start_time` (或 `duration`) | ms | 指令在执行体内的实际执行时间 |
|
||||
| **指令上行耗时** | `received_at - end_time` | ms | 执行结果从Watchdog返回Exchange Hub的耗时 |
|
||||
| **总体耗时** | `completed_at - sent_at` | ms | 从发送到完成的总时间 |
|
||||
|
||||
### 3.2 扩展耗时指标
|
||||
|
||||
| 指标名称 | 计算公式 | 单位 | 含义 |
|
||||
|---------|---------|------|------|
|
||||
| 排队耗时 | `sent_at - created_at` | ms | 指令在Exchange Hub等待发送的时间 |
|
||||
| 处理准备耗时 | `started_at - acked_at` | ms | Watchdog接收到开始执行的准备时间 |
|
||||
|
||||
---
|
||||
|
||||
## 4. 数据结构定义
|
||||
|
||||
### 4.1 CommandTracker 时间字段
|
||||
|
||||
```go
|
||||
type CommandTracker struct {
|
||||
// ... 其他字段 ...
|
||||
|
||||
// 时间追踪字段
|
||||
SentAt *time.Time // 发送到MQTT时间戳
|
||||
AckedAt *time.Time // Watchdog确认接收时间戳
|
||||
StartedAt *time.Time // 开始执行时间戳
|
||||
CompletedAt *time.Time // 完成时间戳
|
||||
CreatedAt time.Time // 创建时间
|
||||
TimeoutAt *time.Time // 超时时间
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 CommandResult 时间字段
|
||||
|
||||
```go
|
||||
type CommandResult struct {
|
||||
// ... 其他字段 ...
|
||||
|
||||
// 执行时间字段 (来自Watchdog)
|
||||
StartTime int64 // 执行开始时间戳(ms)
|
||||
EndTime int64 // 执行结束时间戳(ms)
|
||||
Duration int64 // 执行时长(ms)
|
||||
|
||||
// 上行时间字段 (Exchange Hub记录)
|
||||
ReceivedAt time.Time // 结果接收时间
|
||||
UploadDuration int64 // 上行耗时(ms) = ReceivedAt - EndTime
|
||||
}
|
||||
```
|
||||
|
||||
### 4.3 时间详情DTO
|
||||
|
||||
```go
|
||||
// CommandTimeDurations 指令时间耗时详情
|
||||
type CommandTimeDurations struct {
|
||||
DeliveryDuration int64 `json:"delivery_duration"` // 下发耗时(ms)
|
||||
ExecDuration int64 `json:"exec_duration"` // 执行耗时(ms)
|
||||
UploadDuration int64 `json:"upload_duration"` // 上行耗时(ms)
|
||||
TotalDuration int64 `json:"total_duration"` // 总体耗时(ms)
|
||||
QueueDuration int64 `json:"queue_duration,omitempty"` // 排队耗时(ms)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. API响应格式
|
||||
|
||||
### 5.1 查询指令响应增强
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"command_id": "k8s_exec-proj_001-241222114530",
|
||||
"project_id": "proj_001",
|
||||
"status": "success",
|
||||
"created_at": "2024-12-22 11:45:30",
|
||||
"completed_at": "2024-12-22 11:45:35",
|
||||
"time_durations": {
|
||||
"delivery_duration": 150,
|
||||
"exec_duration": 4500,
|
||||
"upload_duration": 120,
|
||||
"total_duration": 4850
|
||||
},
|
||||
"result": { ... }
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 同步指令响应
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"command_id": "k8s_exec-proj_001-241222114530",
|
||||
"status": "success",
|
||||
"exit_code": 0,
|
||||
"output": "...",
|
||||
"duration": 4500,
|
||||
"time_durations": {
|
||||
"delivery_duration": 150,
|
||||
"exec_duration": 4500,
|
||||
"upload_duration": 120,
|
||||
"total_duration": 4850
|
||||
}
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 6. 计算实现伪代码
|
||||
|
||||
```go
|
||||
// CalculateCommandDurations 计算指令时间耗时
|
||||
func CalculateCommandDurations(
|
||||
tracker *entity.CommandTracker,
|
||||
result *entity.CommandResult,
|
||||
) *dto.CommandTimeDurations {
|
||||
durations := &dto.CommandTimeDurations{}
|
||||
|
||||
// 1. 下发耗时
|
||||
if tracker.SentAt != nil && tracker.AckedAt != nil {
|
||||
durations.DeliveryDuration = tracker.AckedAt.Sub(*tracker.SentAt).Milliseconds()
|
||||
}
|
||||
|
||||
// 2. 执行耗时 (优先使用Watchdog计算值)
|
||||
if result != nil && result.Duration > 0 {
|
||||
durations.ExecDuration = result.Duration
|
||||
} else if result != nil && result.StartTime > 0 && result.EndTime > 0 {
|
||||
durations.ExecDuration = result.EndTime - result.StartTime
|
||||
}
|
||||
|
||||
// 3. 上行耗时
|
||||
if result != nil && result.EndTime > 0 {
|
||||
receivedAtMs := result.ReceivedAt.UnixMilli()
|
||||
durations.UploadDuration = receivedAtMs - result.EndTime
|
||||
}
|
||||
|
||||
// 4. 总体耗时
|
||||
if tracker.SentAt != nil && tracker.CompletedAt != nil {
|
||||
durations.TotalDuration = tracker.CompletedAt.Sub(*tracker.SentAt).Milliseconds()
|
||||
}
|
||||
|
||||
// 5. 排队耗时 (可选)
|
||||
if tracker.SentAt != nil {
|
||||
durations.QueueDuration = tracker.SentAt.Sub(tracker.CreatedAt).Milliseconds()
|
||||
}
|
||||
|
||||
return durations
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 注意事项
|
||||
|
||||
1. **时区统一**: 所有时间必须使用统一时区 (Asia/Shanghai, UTC+8)
|
||||
2. **精度要求**: 毫秒级精度,int64存储
|
||||
3. **空值处理**: 计算时需检查时间字段是否为nil
|
||||
4. **Watchdog时间**: `start_time`/`end_time` 由Watchdog本地时间生成,可能存在时钟偏差
|
||||
354
8-CMII-RMDC/3-rmdc-exchange-hub/exchange-hub-prompt.md
Normal file
354
8-CMII-RMDC/3-rmdc-exchange-hub/exchange-hub-prompt.md
Normal file
@@ -0,0 +1,354 @@
|
||||
# Exchange-Hub模块开发提示词
|
||||
|
||||
> 本文档为大模型提供rmdc-exchange-hub模块的开发上下文。
|
||||
|
||||
---
|
||||
|
||||
## 模块概述
|
||||
|
||||
**rmdc-exchange-hub** 是RMDC平台的消息网关模块,负责:
|
||||
|
||||
1. **MQTT消息中继**: 连接内网业务模块与外网Watchdog
|
||||
2. **指令生命周期管理**: 追踪指令从下发到执行完成的全过程
|
||||
3. **项目在线状态管理**: 维护各项目的连接状态
|
||||
4. **同步/异步指令支持**: 支持两种指令执行模式
|
||||
|
||||
---
|
||||
|
||||
## 核心概念
|
||||
|
||||
### 消息方向
|
||||
|
||||
| 方向 | 描述 | Topic |
|
||||
|------|------|-------|
|
||||
| **上行** | Watchdog → Exchange-Hub | `wdd/RDMC/command/up`, `wdd/RDMC/message/up` |
|
||||
| **下行** | Exchange-Hub → Watchdog | `wdd/RDMC/command/down/{project_id}`, `wdd/RDMC/message/down/{project_id}` |
|
||||
|
||||
### 消息类型
|
||||
|
||||
| 类型 | 描述 |
|
||||
|------|------|
|
||||
| **Command** | 指令消息,需要执行的操作 |
|
||||
| **Message** | 数据消息,执行结果/心跳/监控等 |
|
||||
|
||||
---
|
||||
|
||||
## 技术栈
|
||||
|
||||
| 组件 | 技术 |
|
||||
|------|------|
|
||||
| MQTT客户端 | Eclipse Paho |
|
||||
| Web框架 | Gin |
|
||||
| ORM | GORM |
|
||||
| 数据库 | PostgreSQL |
|
||||
|
||||
---
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
rmdc-exchange-hub/
|
||||
├── internal/
|
||||
│ ├── config/
|
||||
│ │ └── config.go
|
||||
│ ├── dao/
|
||||
│ │ ├── command_tracker_dao.go # 指令追踪
|
||||
│ │ ├── command_result_dao.go # 执行结果
|
||||
│ │ └── project_status_dao.go # 项目状态
|
||||
│ ├── handler/
|
||||
│ │ ├── router.go
|
||||
│ │ ├── command_handler.go
|
||||
│ │ └── status_handler.go
|
||||
│ ├── model/
|
||||
│ │ ├── dto/
|
||||
│ │ │ └── exchange_dto.go
|
||||
│ │ └── entity/
|
||||
│ │ ├── command_tracker.go
|
||||
│ │ ├── command_result.go
|
||||
│ │ └── project_status.go
|
||||
│ └── service/
|
||||
│ ├── mqtt_service.go # MQTT客户端
|
||||
│ ├── message_router.go # 消息路由
|
||||
│ ├── command_service.go # 指令管理
|
||||
│ ├── sync_command_manager.go # 同步指令
|
||||
│ └── state_manager.go # 状态管理
|
||||
└── pkg/
|
||||
└── mqtt/
|
||||
└── client.go
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心数据结构
|
||||
|
||||
### 统一消息格式
|
||||
|
||||
```go
|
||||
// BaseMessage 基础消息结构
|
||||
type BaseMessage struct {
|
||||
MessageID string `json:"message_id"` // UUID
|
||||
Type string `json:"type"` // "command" or "message"
|
||||
ProjectID string `json:"project_id"`
|
||||
Timestamp int64 `json:"timestamp"` // 毫秒时间戳
|
||||
Version string `json:"version"`
|
||||
}
|
||||
|
||||
// CommandMessage 指令消息
|
||||
type CommandMessage struct {
|
||||
BaseMessage
|
||||
CommandType string `json:"command_type"` // register, k8s_exec, host_exec...
|
||||
Payload interface{} `json:"payload"`
|
||||
Signature string `json:"signature"` // HMAC-SHA256签名
|
||||
}
|
||||
|
||||
// DataMessage 数据消息
|
||||
type DataMessage struct {
|
||||
BaseMessage
|
||||
DataType string `json:"data_type"` // exec_result, heartbeat, monitor...
|
||||
Payload interface{} `json:"payload"`
|
||||
Encrypted bool `json:"encrypted"`
|
||||
}
|
||||
```
|
||||
|
||||
### 指令追踪实体
|
||||
|
||||
```go
|
||||
// CommandTracker 指令追踪器
|
||||
type CommandTracker struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
CommandID string `gorm:"uniqueIndex;size:100"`
|
||||
ProjectID string `gorm:"index;size:100"`
|
||||
CommandType string `gorm:"size:50"`
|
||||
Module string `gorm:"size:50"` // 来源模块
|
||||
OperatorID int64 // 操作人
|
||||
Status string `gorm:"size:20"` // pending, sent, acked, completed, failed, timeout
|
||||
SentAt time.Time // 发送时间
|
||||
AckedAt *time.Time // 确认时间
|
||||
StartedAt *time.Time // 开始执行
|
||||
CompletedAt *time.Time // 完成时间
|
||||
TimeoutAt time.Time // 超时时间
|
||||
IsSync bool // 是否同步指令
|
||||
CreatedAt time.Time
|
||||
UpdatedAt time.Time
|
||||
}
|
||||
|
||||
// CommandResult 指令执行结果
|
||||
type CommandResult struct {
|
||||
ID int64 `gorm:"primaryKey"`
|
||||
CommandID string `gorm:"index;size:100"`
|
||||
Status string `gorm:"size:20"` // success, failure, timeout
|
||||
ExitCode int
|
||||
Output string `gorm:"type:text"`
|
||||
Error string `gorm:"type:text"`
|
||||
StartTime int64
|
||||
EndTime int64
|
||||
Duration int64
|
||||
ReceivedAt time.Time
|
||||
CreatedAt time.Time
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MQTT Topic设计
|
||||
|
||||
### 上行Topic(Watchdog → Exchange-Hub)
|
||||
|
||||
```
|
||||
wdd/RDMC/command/up # 指令上行(注册、授权请求)
|
||||
wdd/RDMC/message/up # 数据上行(心跳、执行结果、监控)
|
||||
```
|
||||
|
||||
### 下行Topic(Exchange-Hub → Watchdog)
|
||||
|
||||
```
|
||||
wdd/RDMC/command/down/{project_id} # 指令下行
|
||||
wdd/RDMC/message/down/{project_id} # 数据下行
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 关键业务流程
|
||||
|
||||
### 指令下发流程
|
||||
|
||||
```go
|
||||
func (s *CommandService) SendCommand(ctx context.Context, projectID string, cmdType string, payload interface{}) (*CommandTracker, error) {
|
||||
// 1. 构造消息
|
||||
msg := &common.CommandMessage{
|
||||
BaseMessage: common.BaseMessage{
|
||||
MessageID: uuid.New().String(),
|
||||
Type: "command",
|
||||
ProjectID: projectID,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
Version: "1.0",
|
||||
},
|
||||
CommandType: cmdType,
|
||||
Payload: payload,
|
||||
}
|
||||
|
||||
// 2. 签名
|
||||
msg.Signature = s.sign(msg)
|
||||
|
||||
// 3. 记录追踪
|
||||
tracker := &entity.CommandTracker{
|
||||
CommandID: msg.MessageID,
|
||||
ProjectID: projectID,
|
||||
CommandType: cmdType,
|
||||
Status: "pending",
|
||||
SentAt: time.Now(),
|
||||
TimeoutAt: time.Now().Add(30 * time.Second),
|
||||
}
|
||||
s.trackerDAO.Create(ctx, tracker)
|
||||
|
||||
// 4. 发布到MQTT
|
||||
topic := fmt.Sprintf("wdd/RDMC/command/down/%s", projectID)
|
||||
s.mqttService.Publish(topic, msg)
|
||||
|
||||
// 5. 更新状态
|
||||
tracker.Status = "sent"
|
||||
s.trackerDAO.Update(ctx, tracker)
|
||||
|
||||
return tracker, nil
|
||||
}
|
||||
```
|
||||
|
||||
### 同步指令实现
|
||||
|
||||
```go
|
||||
// SyncCommandManager 同步指令管理器
|
||||
type SyncCommandManager struct {
|
||||
waitChannels sync.Map // map[commandID]chan *ExecResult
|
||||
}
|
||||
|
||||
func (m *SyncCommandManager) SendAndWait(ctx context.Context, projectID string, cmd *CommandMessage, timeout time.Duration) (*ExecResult, error) {
|
||||
// 1. 创建等待通道
|
||||
waitChan := make(chan *ExecResult, 1)
|
||||
m.waitChannels.Store(cmd.MessageID, waitChan)
|
||||
defer m.waitChannels.Delete(cmd.MessageID)
|
||||
|
||||
// 2. 发送指令
|
||||
if err := m.mqttService.PublishCommand(projectID, cmd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 等待结果或超时
|
||||
select {
|
||||
case result := <-waitChan:
|
||||
return result, nil
|
||||
case <-time.After(timeout):
|
||||
return nil, errors.New("command execution timeout")
|
||||
case <-ctx.Done():
|
||||
return nil, ctx.Err()
|
||||
}
|
||||
}
|
||||
|
||||
// OnResult 接收结果回调
|
||||
func (m *SyncCommandManager) OnResult(result *ExecResult) {
|
||||
if ch, ok := m.waitChannels.Load(result.CommandID); ok {
|
||||
ch.(chan *ExecResult) <- result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 消息路由处理
|
||||
|
||||
```go
|
||||
func (r *MessageRouter) handleUpMessage(msg *common.DataMessage) {
|
||||
switch msg.DataType {
|
||||
case "exec_result":
|
||||
r.handleExecResult(msg)
|
||||
case "heartbeat":
|
||||
r.handleHeartbeat(msg)
|
||||
case "monitor":
|
||||
r.handleMonitor(msg)
|
||||
case "log_result":
|
||||
r.handleLogResult(msg)
|
||||
case "alert":
|
||||
r.handleAlert(msg)
|
||||
case "register_complete":
|
||||
r.handleRegisterComplete(msg)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *MessageRouter) handleExecResult(msg *common.DataMessage) {
|
||||
result := msg.Payload.(*ExecResult)
|
||||
|
||||
// 1. 更新指令追踪状态
|
||||
r.trackerService.Complete(result.CommandID, result.Status)
|
||||
|
||||
// 2. 保存执行结果
|
||||
r.resultDAO.Create(result)
|
||||
|
||||
// 3. 通知同步等待者
|
||||
r.syncManager.OnResult(result)
|
||||
|
||||
// 4. 推送给业务模块(如需要)
|
||||
// ...
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 项目状态管理
|
||||
|
||||
### 状态机
|
||||
|
||||
```
|
||||
offline → connecting → verifying → online → disconnecting → offline
|
||||
↑
|
||||
└── heartbeat刷新
|
||||
```
|
||||
|
||||
### 心跳策略
|
||||
|
||||
| 参数 | 默认值 | 说明 |
|
||||
|------|--------|------|
|
||||
| 心跳间隔 | 5秒 | Watchdog发送心跳的频率 |
|
||||
| 超时时间 | 30秒 | 无心跳多久判定为离线 |
|
||||
|
||||
|
||||
|
||||
---
|
||||
|
||||
## API接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/exchange-hub/command/send` | POST | 发送异步指令 |
|
||||
| `/api/exchange-hub/command/sync` | POST | 发送同步指令(等待结果) |
|
||||
| `/api/exchange-hub/command/:id` | GET | 查询指令状态 |
|
||||
| `/api/exchange-hub/project/:id/status` | GET | 查询项目在线状态 |
|
||||
| `/api/exchange-hub/projects/online` | GET | 获取所有在线项目 |
|
||||
|
||||
---
|
||||
|
||||
## 常见开发任务
|
||||
|
||||
### 1. 添加新的指令类型
|
||||
|
||||
1. 在`common`包定义Payload结构
|
||||
2. 在Watchdog端添加Handler处理
|
||||
3. 在业务模块调用`CommandService.SendCommand`
|
||||
|
||||
### 2. 添加新的数据类型
|
||||
|
||||
1. 在`MessageRouter.handleUpMessage`添加case分支
|
||||
2. 实现对应的处理函数
|
||||
3. 如需持久化,添加Entity和DAO
|
||||
|
||||
### 3. 修改消息格式
|
||||
|
||||
1. 修改`common`包的消息结构
|
||||
2. 同步修改Watchdog端的解析逻辑
|
||||
3. 考虑版本兼容性
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| `1-rmdc-exchange-hub-DDS.md` | 详细设计 |
|
||||
| `4-rmdc-exchange-hub-architecture.md` | 架构图 |
|
||||
| `5-rmdc-exchange-hub-command-time.md` | 指令耗时计算 |
|
||||
@@ -0,0 +1,296 @@
|
||||
# 项目管理模块 - RMDC-project-management
|
||||
|
||||
1. 单个k8s-namespace作为一个项目
|
||||
2. 本模块是rmdc项目的核心模块
|
||||
|
||||
## 项目权限
|
||||
1. 项目的权限颗粒度
|
||||
1. 查看权限
|
||||
1. 用户可以查看自己拥有权限的所有项目的列表
|
||||
2. 超级管理员能够查看全部内容
|
||||
3. 数据权限,分配权限需要精细到项目详情的特定模块
|
||||
2. 新建(创建)权限
|
||||
1. 只有超级管理员可以创建项目信息填写工单
|
||||
3. 修改(编辑)权限
|
||||
1. 项目详情填写人,自动具备修改权限
|
||||
2. 由于有工单系统
|
||||
1. 用户不能直接修改项目信息,只能发起修改工单
|
||||
2. 具备查看权限的用户具备修改权限
|
||||
3. 超级管理员可以查看全部项目信息,具备修改权限
|
||||
4. 删除权限
|
||||
1. 非超级管理员用户不具备删除权限
|
||||
5. 导出权限
|
||||
1. 具有查看权限的用户可以导出项目信息
|
||||
2. 项目创建权限
|
||||
1. 项目创建只能由超级管理员进行
|
||||
2. 项目有唯一字段(项目名称 namespace命名空间),需要判定数据库是否存在该项目
|
||||
3. 用户/管理
|
||||
1. 用户端能够查看部分内容
|
||||
2. 超级管理员能够查看全部内容
|
||||
3. 管理员能够查看部分内容
|
||||
1. 管理员可以授权自己拥有权限的内容给普通用户
|
||||
4. 访问控制列表(ACL)由管理员授权,遵循项目的颗粒度进行授权
|
||||
|
||||
### 项目权限管理分配页面
|
||||
1. 只有超级管理员可以访问
|
||||
2. 后端接口只有超级管理员具备权限
|
||||
1. 权限检验
|
||||
2. 审计日志记录
|
||||
3. 超级管理员可以为特定用户分配项目权限
|
||||
1. 分配权限只有查看权限,编辑权限(通过工单系统审批)
|
||||
2. 分配权限可以按照项目颗粒度进行分配
|
||||
3. 分配权限可以按照用户颗粒度进行分配
|
||||
4. 分配权限需要精细到 项目详情的特定模块(数据权限)
|
||||
1. 项目基本信息模块
|
||||
2. 部署业务模块
|
||||
3. 部署环境模块
|
||||
4. 部署中间件模块
|
||||
5. 项目授权模块(只有超级管理员具备权限)
|
||||
4. 用户系统使用 rmdc-user-auth 的用户系统
|
||||
5. 权限分配管理 使用 rmdc-user-auth 模块
|
||||
6. 权限分配需要记录审计日志
|
||||
7. 审计日志使用 rmdc-audit-log 模块
|
||||
|
||||
|
||||
## 项目管理的生命周期
|
||||
1. 项目创建
|
||||
1. 超级管理员填写项目基本信息,分派给项目填写人
|
||||
1. 项目处于 未发布状态(草稿状态)
|
||||
2. 项目填写人填写项目信息
|
||||
3. 项目填写人提交项目信息给超级管理员审核
|
||||
4. 超级管理员审核项目信息
|
||||
5. 超级管理员审批通过之后
|
||||
1. 项目信息作为master主分支
|
||||
2. 项目处于已发布状态
|
||||
2. 项目编辑
|
||||
1. 非超级管理员用户可以编辑项目信息
|
||||
2. 非超级管理员用户可以发起修改工单
|
||||
1. 项目对于 非超级管理员用户 处于编辑状态
|
||||
3. 非超级管理员用户可以在超级管理员审批之前 撤销修改工单
|
||||
1. 项目对于 非超级管理员用户 处于已发布状态
|
||||
4. 超级管理员审批通过之后
|
||||
1. 项目对于 非超级管理员用户 处于已发布状态
|
||||
5. 超级管理员审批拒绝之后
|
||||
1. 项目对于 非超级管理员用户 处于编辑状态
|
||||
3. 项目删除
|
||||
1. 只有超级管理员 可以修改项目状态为删除状态
|
||||
2. 项目采用软删除的策略
|
||||
|
||||
### 项目详情页面与项目详情工单之间的关系
|
||||
1. 项目详情工单分为如下的两种
|
||||
1. 项目创建时候,项目详情的填写工单
|
||||
2. 项目正常过程中,项目详情的编辑工单
|
||||
2. 项目详情工单和项目详情页面之间需要互相能够跳转
|
||||
1. 项目详情填写工单是唯一的,只能同时存在一个项目详情填写工单
|
||||
2. 超级管理员的项目详情编辑工单不是唯一的,可以同时存在多个项目详情编辑工单
|
||||
3. 对于非超级管理员,项目详情编辑工单是唯一的,只能同时存在一个项目详情编辑工单
|
||||
3. 超级管理员的非正式发布状态的项目详情页面,只能跳转至一个项目详情填写工单
|
||||
4. 超级管理员的正式发布状态的项目详情页面,可以跳转至多个项目详情编辑工单
|
||||
|
||||
## 项目查看
|
||||
1. 所有项目页面
|
||||
1. 用户可以查看自己拥有权限的所有项目的列表
|
||||
2. 支持列表显示,卡片显示
|
||||
3. 点击项目之后,进入项目详情页面
|
||||
2. 项目详情页面
|
||||
1. 展示项目概览信息
|
||||
2. 具备查看权限,可以进行页面信息修改提交,发起修改工单,修改工单需要超级管理员审核
|
||||
3. 项目信息导出
|
||||
1. 支持按照YAML格式模板 导出项目信息
|
||||
3. 项目模块详情页面
|
||||
1. 部署业务信息、部署环境信息、部署中间件信息属于特定模块
|
||||
2. 作为TAB页签显示各个模块
|
||||
3. 授权信息页面
|
||||
1. 只有超级管理员可以访问
|
||||
2. 后端接口只有超级管理员具备权限
|
||||
1. 权限检验
|
||||
2. 审计日志记录
|
||||
3. 具体功能详见 项目授权管理
|
||||
|
||||
### 项目详情页面
|
||||
1. 查看状态
|
||||
1. 默认状态
|
||||
2. 项目详情页面有导出按钮,点击之后可以导出项目的详情
|
||||
3. 项目详情页面的字段具备快捷粘贴的功能
|
||||
2. 编辑状态
|
||||
1. 项目详情页面显示编辑按钮,点击之后进入编辑状态
|
||||
2. 编辑状态没有导出按钮
|
||||
3. 编辑状态具备 保存草稿 提交审核 放弃编辑的按钮
|
||||
4. 保存草稿按钮,触发项目详情的草稿保存功能,保存至数据库中
|
||||
5. 项目详情的编辑草稿 应该与非超级管理员用户产生关联
|
||||
6. 编辑状态,应该能够类似GIT DIFF显示草稿与正式版本的差异
|
||||
1. 在编辑页面,需要定期获取最新的版本
|
||||
7. 放弃编辑按钮,触发项目详情的草稿删除功能,删除数据库中的草稿,退出编辑状态
|
||||
8. 提交审核按钮,触发项目详情的草稿提交审核功能,可以复用项目详情填写工单流程(TODO 考虑与rmdc-work-procedure模块进行整合)
|
||||
9. 字段校验
|
||||
1. IP地址字段
|
||||
1. 公网IP地址 内网IP地址 如果不为空值,需要进行IP校验
|
||||
2. IP的空值处理,前端显示默认空值填充为 无
|
||||
2. 命名空间字段
|
||||
1. 前端创建项目时候,命名空间名称必须符合RFC 1123 DNS标签规范,具体要求包括:
|
||||
1. 不能超过253个字符
|
||||
2. 只能包含小写字母、数字以及'-'和'.'字符
|
||||
3. 必须以字母开头
|
||||
4. 必须以字母数字结尾
|
||||
2. 前端显示默认空值填充为 无
|
||||
10. 密码字段
|
||||
1. 项目填写人 需要填写密码字段
|
||||
2. 数据库加密存储,应该使用项目的TierOneScret进行加密
|
||||
11. 部署人姓名
|
||||
1. 非超级管理员也可以通过用户接口查找到系统中的用户 /api/user
|
||||
2. 部署人姓名字段,用于显示部署人姓名
|
||||
3. 超级管理员页面的项目详情页面
|
||||
1. 超级管理员的项目详情页面,默认显示主线版本分支的内容
|
||||
2. 超级管理员可以直接修改项目的master主分支,直接修改入库,不需要工单审批
|
||||
3. 超级管理员的项目详情页面,具备查看所有版本的功能
|
||||
1. 超级管理员可以查看所有版本的项目详情
|
||||
2. 可以查看页面的修订历史,类似GIT的历史提交记录
|
||||
3. 每一个版本可以查看到 修改的内容
|
||||
4. 超级管理员的项目详情页面,可以跳转至工单详情页面
|
||||
1. 超级管理员可以跳转至工单详情页面,查看与此项目关联的工单内容
|
||||
5. 超级管理员的项目详情页面,可以查看到授权信息模块的内容
|
||||
4. 非超级管理员左侧导航栏 显示 项目管理
|
||||
1. 默认展示其具备的全部访问权限的项目列表
|
||||
1. 支持列表、卡片显示
|
||||
2. 点击项目可以进入项目详情页面
|
||||
|
||||
## 项目创建
|
||||
|
||||
### 项目创建的流程说明
|
||||
1. 项目详情展示与填写类似于GIT的分支
|
||||
2. 项目查看,是由超级管理员审核维护的master主分支
|
||||
4. 项目创建流程,超级管理员分配一个用户进行项目信息登记
|
||||
5. 当项目初始信息被登记完成,超级管理员审批通过之后,项目信息作为初始的master主分支
|
||||
6. 项目编辑,是每个用户都具备的临时分支(每个用户都具备草稿),然后提交审核合并入master主分支(需要被超级管理员审核)
|
||||
|
||||
### 项目信息登记页面
|
||||
1. 项目创建只能由超级管理员进行
|
||||
1. 填写必要的信息,不需要考虑空值
|
||||
2. 考虑到数据库字段限制, 数据库不为空字段,填充默认值
|
||||
2. 项目创建中,需要按照管理权限,分配给特定的用户进行信息登记
|
||||
1. 特定用户填写时候, 前端自动过滤掉默认值
|
||||
3. 支持草稿功能,项目信息填写比较耗时,需要支持草稿功能
|
||||
4. 必填字段
|
||||
1. 填满才可以提交项目信
|
||||
2. 不填满只能保存草稿
|
||||
5. 信息审核
|
||||
1. 普通用户填写项目信息之后,需要超级管理员审核修改项目信息认证
|
||||
|
||||
### 项目详情填写审批工单
|
||||
1. 详情见 rmdc-work-procedure
|
||||
2. 当前阶段已经实现
|
||||
|
||||
### 项目详情填写页面
|
||||
1. 复用 项目详情页面 的编辑状态
|
||||
|
||||
#### 特殊字段说明
|
||||
1. 前端创建项目时候,命名空间名称必须符合RFC 1123 DNS标签规范,具体要求包括:
|
||||
1. 不能超过253个字符
|
||||
2. 只能包含小写字母、数字以及'-'和'.'字符
|
||||
3. 必须以字母开头
|
||||
4. 必须以字母数字结尾
|
||||
2. 省份和城市字段 请参照[3-china-province-city.md](3-china-province-city.md)解析
|
||||
1. 后端和前端都应该维护一份枚举表
|
||||
2. 前端项目创建时,后端应该校验相应的省份和城市
|
||||
3. 前端应该实现级联选择
|
||||
|
||||
#### 项目基本信息结构体
|
||||
1. 项目名称
|
||||
2. 命名空间(唯一)
|
||||
3. 项目ID project_id (唯一)
|
||||
4. 省份 (枚举 中国的省份是固定的)
|
||||
5. 城市(枚举 中国的城市是固定的)
|
||||
6. 行业组人员
|
||||
7. 行业组人员电话
|
||||
8. 项目性质 (科研、测试、试用、市场化、二级平台)
|
||||
9. 项目信息认证 (草稿,正式)
|
||||
1. 由超级管理员修改
|
||||
10. 部署业务结构体
|
||||
11. 部署环境结构体
|
||||
12. 部署中间件结构体
|
||||
|
||||
#### 项目部署业务结构体
|
||||
1. 部署人姓名
|
||||
2. 部署人电话
|
||||
3. 部署开始时间
|
||||
4. 部署完成时间
|
||||
5. 部署系统的版本
|
||||
6. 部署系统(business老行业平台 fly-control新飞控平台 supervisor监管平台)
|
||||
7. 业务主要入口
|
||||
8. 系统超级管理员用户
|
||||
9. 系统超级管理员密码(需要加密存储)
|
||||
|
||||
#### 项目部署环境结构体
|
||||
1. 主机信息结构体 (与rmdc-watchdog-common中保持一致)
|
||||
1. 此部分信息理论来自 rmdc-watchdog -> rmdc-exchange-hub 上报
|
||||
2. 新增字段
|
||||
1. 公网IP
|
||||
2. 能够访问公网
|
||||
3. SSH端口
|
||||
4. SSH用户名
|
||||
5. SSH密码 (需要加密存储)
|
||||
6. 主机角色(master worker storage)
|
||||
2. 网络环境 (完全内网、单主机公网、全访问公网)
|
||||
3. 主要公网IP地址
|
||||
4. 域名URL
|
||||
5. 是否开启SSL
|
||||
6. 主机管理方式(堡垒机、白名单、)
|
||||
7. 管理后台URL
|
||||
8. 管理后台用户名
|
||||
9. 管理后台密码(需要加密存储)
|
||||
10. 主机台数
|
||||
11. 主机CPU总数
|
||||
12. 主机CPU型号
|
||||
13. 主机内存总大小
|
||||
14. 主机存储总大小
|
||||
|
||||
#### 项目部署中间件结构体
|
||||
1. MySQL结构体
|
||||
2. Redis结构体
|
||||
3. EMQX结构体
|
||||
4. MINIO结构体
|
||||
5. InfluxDB结构体
|
||||
6. Nacos结构体
|
||||
7. K8S Dashboard结构体
|
||||
8. 上述结构体的字段均有如下字段
|
||||
1. 公网IP
|
||||
2. 公网端口
|
||||
3. 内网IP
|
||||
4. 内网端口
|
||||
5. k8s访问地址
|
||||
6. k8s访问端口
|
||||
7. 超级管理员用户名
|
||||
8. 超级管理员密码 (需要加密存储)
|
||||
|
||||
|
||||
#### 项目授权信息结构体
|
||||
1. 项目一级TOTP授权密钥
|
||||
2. 一级授权允许时间偏移
|
||||
3. 开启TOTP验证
|
||||
4. 项目二级TOTP授权密钥
|
||||
5. 是否开启授权
|
||||
6. 授权类型: permanent/time
|
||||
7. 授权有效期(天)
|
||||
8. 授权时间
|
||||
9. 撤销授权时间
|
||||
|
||||
## 项目授权功能
|
||||
1. 集成之前 rmdc-wathchdog-center部分的功能
|
||||
2. 需要与 rmdc-exchange-hub rmdc-watchdog 交互
|
||||
1. 只有SuperAdmin具备此权限
|
||||
2. 接收来自 rmdc-exchange-hub 关于项目注册的信息
|
||||
1. 项目注册实际来自rmdc-watchdog
|
||||
2. 项目信息应该持久化保存
|
||||
3. 能够对全部项目进行授权
|
||||
1. 正常情况是从rmdc-exchange-hub接收的注册项目
|
||||
2. 处理来自 rmdc-exchange-hub 的授权信息
|
||||
3. 调用RMDC-watchdog-center的授权接口
|
||||
4. 存储项目的授权文件信息
|
||||
5. 授权时间也可以进行管理
|
||||
4. 有特殊的项目,无法访问公网
|
||||
1. 可以手动添加离线项目的相关信息
|
||||
2. 可以离线进行项目授权
|
||||
5. 能够取消对一个项目的授权
|
||||
1. 同样是通过rmdc-exchange-hub的在线方式
|
||||
2. 可以离线取消项目授权
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
361
8-CMII-RMDC/4-rmdc-project-management/3-china-province-city.md
Normal file
361
8-CMII-RMDC/4-rmdc-project-management/3-china-province-city.md
Normal file
@@ -0,0 +1,361 @@
|
||||
## 省份及地级市列表
|
||||
|
||||
**河北省**
|
||||
河北省-石家庄市
|
||||
河北省-唐山市
|
||||
河北省-秦皇岛市
|
||||
河北省-邯郸市
|
||||
河北省-邢台市
|
||||
河北省-保定市
|
||||
河北省-张家口市
|
||||
河北省-承德市
|
||||
河北省-沧州市
|
||||
河北省-廊坊市
|
||||
河北省-衡水市
|
||||
|
||||
**山西省**
|
||||
山西省-太原市
|
||||
山西省-大同市
|
||||
山西省-阳泉市
|
||||
山西省-长治市
|
||||
山西省-晋城市
|
||||
山西省-朔州市
|
||||
山西省-晋中市
|
||||
山西省-运城市
|
||||
山西省-忻州市
|
||||
山西省-临汾市
|
||||
山西省-吕梁市
|
||||
|
||||
**内蒙古自治区**
|
||||
内蒙古自治区-呼和浩特市
|
||||
内蒙古自治区-包头市
|
||||
内蒙古自治区-乌海市
|
||||
内蒙古自治区-赤峰市
|
||||
内蒙古自治区-通辽市
|
||||
内蒙古自治区-鄂尔多斯市
|
||||
内蒙古自治区-呼伦贝尔市
|
||||
内蒙古自治区-巴彦淖尔市
|
||||
内蒙古自治区-乌兰察布市
|
||||
|
||||
**辽宁省**
|
||||
辽宁省-沈阳市
|
||||
辽宁省-大连市
|
||||
辽宁省-鞍山市
|
||||
辽宁省-抚顺市
|
||||
辽宁省-本溪市
|
||||
辽宁省-丹东市
|
||||
辽宁省-锦州市
|
||||
辽宁省-营口市
|
||||
辽宁省-阜新市
|
||||
辽宁省-辽阳市
|
||||
辽宁省-盘锦市
|
||||
辽宁省-铁岭市
|
||||
辽宁省-朝阳市
|
||||
辽宁省-葫芦岛市
|
||||
|
||||
**吉林省**
|
||||
吉林省-长春市
|
||||
吉林省-吉林市
|
||||
吉林省-四平市
|
||||
吉林省-辽源市
|
||||
吉林省-通化市
|
||||
吉林省-白山市
|
||||
吉林省-松原市
|
||||
吉林省-白城市
|
||||
|
||||
**黑龙江省**
|
||||
黑龙江省-哈尔滨市
|
||||
黑龙江省-齐齐哈尔市
|
||||
黑龙江省-鸡西市
|
||||
黑龙江省-鹤岗市
|
||||
黑龙江省-双鸭山市
|
||||
黑龙江省-大庆市
|
||||
黑龙江省-伊春市
|
||||
黑龙江省-佳木斯市
|
||||
黑龙江省-七台河市
|
||||
黑龙江省-牡丹江市
|
||||
黑龙江省-黑河市
|
||||
黑龙江省-绥化市
|
||||
|
||||
**江苏省**
|
||||
江苏省-南京市
|
||||
江苏省-无锡市
|
||||
江苏省-徐州市
|
||||
江苏省-常州市
|
||||
江苏省-苏州市
|
||||
江苏省-南通市
|
||||
江苏省-连云港市
|
||||
江苏省-淮安市
|
||||
江苏省-盐城市
|
||||
江苏省-扬州市
|
||||
江苏省-镇江市
|
||||
江苏省-泰州市
|
||||
江苏省-宿迁市
|
||||
|
||||
**浙江省**
|
||||
浙江省-杭州市
|
||||
浙江省-宁波市
|
||||
浙江省-温州市
|
||||
浙江省-嘉兴市
|
||||
浙江省-湖州市
|
||||
浙江省-绍兴市
|
||||
浙江省-金华市
|
||||
浙江省-衢州市
|
||||
浙江省-舟山市
|
||||
浙江省-台州市
|
||||
浙江省-丽水市
|
||||
|
||||
**安徽省**
|
||||
安徽省-合肥市
|
||||
安徽省-芜湖市
|
||||
安徽省-蚌埠市
|
||||
安徽省-淮南市
|
||||
安徽省-马鞍山市
|
||||
安徽省-淮北市
|
||||
安徽省-铜陵市
|
||||
安徽省-安庆市
|
||||
安徽省-黄山市
|
||||
安徽省-滁州市
|
||||
安徽省-阜阳市
|
||||
安徽省-宿州市
|
||||
安徽省-六安市
|
||||
安徽省-亳州市
|
||||
安徽省-池州市
|
||||
安徽省-宣城市
|
||||
|
||||
**福建省**
|
||||
福建省-福州市
|
||||
福建省-厦门市
|
||||
福建省-三明市
|
||||
福建省-莆田市
|
||||
福建省-泉州市
|
||||
福建省-漳州市
|
||||
福建省-南平市
|
||||
福建省-龙岩市
|
||||
福建省-宁德市
|
||||
|
||||
**江西省**
|
||||
江西省-南昌市
|
||||
江西省-景德镇市
|
||||
江西省-萍乡市
|
||||
江西省-九江市
|
||||
江西省-新余市
|
||||
江西省-鹰潭市
|
||||
江西省-赣州市
|
||||
江西省-吉安市
|
||||
江西省-宜春市
|
||||
江西省-抚州市
|
||||
江西省-上饶市
|
||||
|
||||
**山东省**
|
||||
山东省-济南市
|
||||
山东省-青岛市
|
||||
山东省-淄博市
|
||||
山东省-枣庄市
|
||||
山东省-东营市
|
||||
山东省-烟台市
|
||||
山东省-潍坊市
|
||||
山东省-济宁市
|
||||
山东省-泰安市
|
||||
山东省-威海市
|
||||
山东省-日照市
|
||||
山东省-临沂市
|
||||
山东省-德州市
|
||||
山东省-聊城市
|
||||
山东省-滨州市
|
||||
山东省-菏泽市
|
||||
|
||||
**河南省**
|
||||
河南省-郑州市
|
||||
河南省-开封市
|
||||
河南省-洛阳市
|
||||
河南省-平顶山市
|
||||
河南省-安阳市
|
||||
河南省-鹤壁市
|
||||
河南省-新乡市
|
||||
河南省-焦作市
|
||||
河南省-濮阳市
|
||||
河南省-许昌市
|
||||
河南省-漯河市
|
||||
河南省-三门峡市
|
||||
河南省-南阳市
|
||||
河南省-商丘市
|
||||
河南省-信阳市
|
||||
河南省-周口市
|
||||
河南省-驻马店市
|
||||
|
||||
**湖北省**
|
||||
湖北省-武汉市
|
||||
湖北省-黄石市
|
||||
湖北省-十堰市
|
||||
湖北省-宜昌市
|
||||
湖北省-襄阳市
|
||||
湖北省-鄂州市
|
||||
湖北省-荆门市
|
||||
湖北省-孝感市
|
||||
湖北省-荆州市
|
||||
湖北省-黄冈市
|
||||
湖北省-咸宁市
|
||||
湖北省-随州市
|
||||
|
||||
**湖南省**
|
||||
湖南省-长沙市
|
||||
湖南省-株洲市
|
||||
湖南省-湘潭市
|
||||
湖南省-衡阳市
|
||||
湖南省-邵阳市
|
||||
湖南省-岳阳市
|
||||
湖南省-常德市
|
||||
湖南省-张家界市
|
||||
湖南省-益阳市
|
||||
湖南省-郴州市
|
||||
湖南省-永州市
|
||||
湖南省-怀化市
|
||||
湖南省-娄底市
|
||||
|
||||
**广东省**
|
||||
广东省-广州市
|
||||
广东省-韶关市
|
||||
广东省-深圳市
|
||||
广东省-珠海市
|
||||
广东省-汕头市
|
||||
广东省-佛山市
|
||||
广东省-江门市
|
||||
广东省-湛江市
|
||||
广东省-茂名市
|
||||
广东省-肇庆市
|
||||
广东省-惠州市
|
||||
广东省-梅州市
|
||||
广东省-汕尾市
|
||||
广东省-河源市
|
||||
广东省-阳江市
|
||||
广东省-清远市
|
||||
广东省-东莞市
|
||||
广东省-中山市
|
||||
广东省-潮州市
|
||||
广东省-揭阳市
|
||||
广东省-云浮市
|
||||
|
||||
**广西壮族自治区**
|
||||
广西壮族自治区-南宁市
|
||||
广西壮族自治区-柳州市
|
||||
广西壮族自治区-桂林市
|
||||
广西壮族自治区-梧州市
|
||||
广西壮族自治区-北海市
|
||||
广西壮族自治区-防城港市
|
||||
广西壮族自治区-钦州市
|
||||
广西壮族自治区-贵港市
|
||||
广西壮族自治区-玉林市
|
||||
广西壮族自治区-百色市
|
||||
广西壮族自治区-贺州市
|
||||
广西壮族自治区-河池市
|
||||
广西壮族自治区-来宾市
|
||||
广西壮族自治区-崇左市
|
||||
|
||||
**海南省**
|
||||
海南省-海口市
|
||||
海南省-三亚市
|
||||
海南省-三沙市
|
||||
海南省-儋州市
|
||||
|
||||
**四川省**
|
||||
四川省-成都市
|
||||
四川省-自贡市
|
||||
四川省-攀枝花市
|
||||
四川省-泸州市
|
||||
四川省-德阳市
|
||||
四川省-绵阳市
|
||||
四川省-广元市
|
||||
四川省-遂宁市
|
||||
四川省-内江市
|
||||
四川省-乐山市
|
||||
四川省-南充市
|
||||
四川省-眉山市
|
||||
四川省-宜宾市
|
||||
四川省-广安市
|
||||
四川省-达州市
|
||||
四川省-雅安市
|
||||
四川省-巴中市
|
||||
四川省-资阳市
|
||||
|
||||
**贵州省**
|
||||
贵州省-贵阳市
|
||||
贵州省-六盘水市
|
||||
贵州省-遵义市
|
||||
贵州省-安顺市
|
||||
贵州省-毕节市
|
||||
贵州省-铜仁市
|
||||
|
||||
**云南省**
|
||||
云南省-昆明市
|
||||
云南省-曲靖市
|
||||
云南省-玉溪市
|
||||
云南省-保山市
|
||||
云南省-昭通市
|
||||
云南省-丽江市
|
||||
云南省-普洱市
|
||||
云南省-临沧市
|
||||
|
||||
**西藏自治区**
|
||||
西藏自治区-拉萨市
|
||||
西藏自治区-日喀则市
|
||||
西藏自治区-昌都市
|
||||
西藏自治区-林芝市
|
||||
西藏自治区-山南市
|
||||
西藏自治区-那曲市
|
||||
|
||||
**陕西省**
|
||||
陕西省-西安市
|
||||
陕西省-铜川市
|
||||
陕西省-宝鸡市
|
||||
陕西省-咸阳市
|
||||
陕西省-渭南市
|
||||
陕西省-汉中市
|
||||
陕西省-延安市
|
||||
陕西省-榆林市
|
||||
陕西省-安康市
|
||||
陕西省-商洛市
|
||||
|
||||
**甘肃省**
|
||||
甘肃省-兰州市
|
||||
甘肃省-嘉峪关市
|
||||
甘肃省-金昌市
|
||||
甘肃省-白银市
|
||||
甘肃省-天水市
|
||||
甘肃省-武威市
|
||||
甘肃省-张掖市
|
||||
甘肃省-平凉市
|
||||
甘肃省-酒泉市
|
||||
甘肃省-庆阳市
|
||||
甘肃省-定西市
|
||||
甘肃省-陇南市
|
||||
|
||||
**青海省**
|
||||
青海省-西宁市
|
||||
青海省-海东市
|
||||
|
||||
**宁夏回族自治区**
|
||||
宁夏回族自治区-银川市
|
||||
宁夏回族自治区-石嘴山市
|
||||
宁夏回族自治区-吴忠市
|
||||
宁夏回族自治区-固原市
|
||||
宁夏回族自治区-中卫市
|
||||
|
||||
**新疆维吾尔自治区**
|
||||
新疆维吾尔自治区-乌鲁木齐市
|
||||
新疆维吾尔自治区-克拉玛依市
|
||||
新疆维吾尔自治区-吐鲁番市
|
||||
新疆维吾尔自治区-哈密市
|
||||
|
||||
**直辖市(与省平级)**
|
||||
北京市
|
||||
天津市
|
||||
上海市
|
||||
重庆市
|
||||
|
||||
**特别行政区**
|
||||
香港特别行政区
|
||||
澳门特别行政区
|
||||
|
||||
**台湾省**
|
||||
台湾省
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,251 @@
|
||||
# 项目管理模块 - HTTP回调设计方案(备选方案)
|
||||
|
||||
> **文档状态**: 备选方案存档
|
||||
> **当前实现**: 接口注入方式(参见 `2-rmdc-project-management-DDS.md` 第3.4节)
|
||||
> **适用场景**: 未来微服务化部署时可考虑迁移到此方案
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
本文档描述项目与工单模块之间基于 **HTTP 回调** 的状态同步机制。当系统需要分布式部署时,可考虑从当前的"接口注入"方式迁移到此方案。
|
||||
|
||||
### 1.1 设计原则
|
||||
|
||||
项目模块(`rmdc-project-management`)调用工单模块(`rmdc-work-procedure`)创建和管理工单,工单状态变更需要同步更新项目的生命周期状态。采用 **HTTP 回调机制 + 领域事件** 的设计模式实现状态同步。
|
||||
|
||||
> **核心思想**:工单状态变更时,由工单模块主动 HTTP 回调项目模块,项目模块根据事件类型更新自身的生命周期状态。
|
||||
|
||||
---
|
||||
|
||||
## 2. 架构设计
|
||||
|
||||
### 2.1 时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant PM as rmdc-project-management
|
||||
participant WP as rmdc-work-procedure
|
||||
participant DB as Database
|
||||
|
||||
Note over PM,WP: 回调机制:工单状态变更 → 回调业务模块 → 更新项目状态
|
||||
|
||||
PM->>WP: 1. 创建工单 (携带回调配置)
|
||||
WP->>DB: 2. 存储工单 + 回调配置
|
||||
WP-->>PM: 3. 返回 workflow_id
|
||||
|
||||
Note over WP: 工单状态变更事件发生...
|
||||
|
||||
WP->>WP: 4. 状态机转换 (pending_review → approved)
|
||||
WP->>PM: 5. HTTP回调 /api/project/workflow-callback
|
||||
PM->>PM: 6. 解析事件,更新项目 lifecycle_status
|
||||
PM-->>WP: 7. 确认回调成功
|
||||
WP->>DB: 8. 标记回调已完成
|
||||
```
|
||||
|
||||
### 2.2 为什么不算循环依赖
|
||||
|
||||
虽然调用关系形成了"环",但这是 **松耦合的事件通知模式**,不是真正的循环依赖:
|
||||
|
||||
| 依赖类型 | 说明 | 是否存在 | 问题程度 |
|
||||
|:---|:---|:---|:---|
|
||||
| **编译依赖** | 模块A的代码import模块B | ❌ 不存在 | - |
|
||||
| **启动依赖** | 模块A启动必须依赖模块B先启动 | ⚠️ 单向 | 低 |
|
||||
| **运行时调用** | 模块A在运行时调用模块B的API | ✅ 双向 | 需设计 |
|
||||
| **逻辑依赖** | 模块A的业务逻辑依赖模块B的存在 | ⚠️ 单向 | 低 |
|
||||
|
||||
**关键点**:工单模块不import项目模块任何代码,只知道一个回调URL字符串,两个模块在代码层面完全解耦。
|
||||
|
||||
---
|
||||
|
||||
## 3. 回调配置设计
|
||||
|
||||
### 3.1 创建工单时注册回调
|
||||
|
||||
```go
|
||||
// 项目模块创建工单时,注册回调配置
|
||||
type CreateWorkflowRequest struct {
|
||||
ModuleCode string `json:"module_code"` // "project_management"
|
||||
WorkflowType string `json:"workflow_type"` // "project_detail" / "project_modify"
|
||||
// ... 其他字段 ...
|
||||
|
||||
// 回调配置
|
||||
CallbackConfig *CallbackConfig `json:"callback_config"`
|
||||
}
|
||||
|
||||
type CallbackConfig struct {
|
||||
// 回调URL(工单状态变更时调用)
|
||||
CallbackURL string `json:"callback_url"` // "/api/project/workflow-callback"
|
||||
|
||||
// 关注的事件列表(只回调这些事件)
|
||||
SubscribedEvents []string `json:"subscribed_events"` // ["submit", "approve", "return", "revoke"]
|
||||
|
||||
// 业务上下文(回调时原样返回)
|
||||
BusinessContext map[string]interface{} `json:"business_context"` // {"project_id": "xxx"}
|
||||
}
|
||||
```
|
||||
|
||||
### 3.2 回调请求结构
|
||||
|
||||
```go
|
||||
// 工单模块发起的回调请求
|
||||
type WorkflowCallbackRequest struct {
|
||||
WorkflowID string `json:"workflow_id"`
|
||||
WorkflowType string `json:"workflow_type"`
|
||||
Event string `json:"event"` // "approve", "return", "submit" 等
|
||||
FromStatus string `json:"from_status"`
|
||||
ToStatus string `json:"to_status"`
|
||||
OperatorID int64 `json:"operator_id"`
|
||||
OperatorName string `json:"operator_name"`
|
||||
BusinessContext map[string]interface{} `json:"business_context"`
|
||||
Timestamp time.Time `json:"timestamp"`
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 回调处理实现
|
||||
|
||||
### 4.1 项目模块接收回调
|
||||
|
||||
```go
|
||||
// 项目模块 - 接收工单回调并更新项目状态
|
||||
func (h *ProjectHandler) WorkflowCallback(c *gin.Context) {
|
||||
var req WorkflowCallbackRequest
|
||||
if err := c.ShouldBindJSON(&req); err != nil {
|
||||
response.Error(c, errcode.InvalidParams)
|
||||
return
|
||||
}
|
||||
|
||||
// 幂等性检查
|
||||
idempotencyKey := fmt.Sprintf("%s:%s:%d", req.WorkflowID, req.Event, req.Timestamp.Unix())
|
||||
if h.cache.Exists(idempotencyKey) {
|
||||
response.Success(c, nil) // 幂等返回成功
|
||||
return
|
||||
}
|
||||
|
||||
projectID := req.BusinessContext["project_id"].(string)
|
||||
|
||||
// 根据工单事件映射项目生命周期状态
|
||||
newLifecycleStatus := h.mapWorkflowEventToLifecycle(req.Event, req.ToStatus, req.WorkflowType)
|
||||
|
||||
if newLifecycleStatus != "" {
|
||||
err := h.projectService.UpdateLifecycleStatus(c, projectID, newLifecycleStatus)
|
||||
if err != nil {
|
||||
response.Error(c, errcode.InternalError)
|
||||
return
|
||||
}
|
||||
}
|
||||
|
||||
// 标记已处理(设置24小时过期)
|
||||
h.cache.Set(idempotencyKey, "1", 24*time.Hour)
|
||||
|
||||
response.Success(c, nil)
|
||||
}
|
||||
```
|
||||
|
||||
### 4.2 事件到生命周期状态的映射
|
||||
|
||||
```go
|
||||
// 事件到生命周期状态的映射
|
||||
func (h *ProjectHandler) mapWorkflowEventToLifecycle(event, toStatus, workflowType string) string {
|
||||
// 填写工单
|
||||
if workflowType == "project_detail" {
|
||||
switch event {
|
||||
case "create": // 创建工单
|
||||
return "DRAFTING"
|
||||
case "submit": // 提交审核
|
||||
return "REVIEWING"
|
||||
case "return": // 审核打回
|
||||
return "DRAFTING"
|
||||
case "approve": // 审核通过
|
||||
return "RELEASED"
|
||||
case "revoke": // 撤销工单
|
||||
return "INIT"
|
||||
}
|
||||
}
|
||||
|
||||
// 修改工单
|
||||
if workflowType == "project_modify" {
|
||||
switch event {
|
||||
case "create": // 发起修改
|
||||
return "MODIFYING"
|
||||
case "submit": // 提交审核
|
||||
return "REVIEWING"
|
||||
case "return": // 审核打回
|
||||
return "MODIFYING"
|
||||
case "approve": // 审核通过
|
||||
return "RELEASED"
|
||||
case "revoke": // 撤销工单
|
||||
return "RELEASED" // 撤销后恢复为 RELEASED
|
||||
}
|
||||
}
|
||||
|
||||
return ""
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 风险处理
|
||||
|
||||
| 风险 | 解决方案 |
|
||||
|:---|:---|
|
||||
| **回调再次调用工单API导致死循环** | 回调处理中只更新项目状态,不调用工单API |
|
||||
| **回调失败导致状态不一致** | 工单模块实现重试机制(3次重试 + 指数退避) |
|
||||
| **回调请求超时阻塞工单流程** | 设置短超时(5秒)或完全异步化 |
|
||||
| **重复回调导致重复处理** | 使用 `workflow_id + event + timestamp` 作为幂等键 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 回调失败重试表
|
||||
|
||||
```go
|
||||
// 工单模块 - 回调失败时存储待重试
|
||||
type CallbackRetry struct {
|
||||
ID int64 `gorm:"primaryKey;autoIncrement" json:"id"`
|
||||
WorkflowID string `gorm:"type:varchar(64);index" json:"workflow_id"`
|
||||
CallbackURL string `gorm:"type:varchar(256)" json:"callback_url"`
|
||||
Payload string `gorm:"type:text" json:"payload"` // JSON
|
||||
RetryCount int `gorm:"default:0" json:"retry_count"` // 已重试次数
|
||||
MaxRetries int `gorm:"default:3" json:"max_retries"` // 最大重试次数
|
||||
NextRetryAt time.Time `json:"next_retry_at"` // 下次重试时间
|
||||
Status string `gorm:"type:varchar(16);default:'pending'" json:"status"` // pending/success/failed
|
||||
LastError string `gorm:"type:text" json:"last_error"` // 最后一次错误信息
|
||||
CreatedAt time.Time `json:"created_at"`
|
||||
UpdatedAt time.Time `json:"updated_at"`
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 与接口注入方式的对比
|
||||
|
||||
| 特性 | HTTP回调(本方案) | 接口注入(当前实现) |
|
||||
|:---|:---|:---|
|
||||
| **模块解耦** | ✅ 完全解耦(仅URL字符串) | ⚠️ 接口级解耦 |
|
||||
| **分布式支持** | ✅ 支持 | ❌ 不支持 |
|
||||
| **性能** | ⚠️ 网络开销 | ✅ 进程内调用 |
|
||||
| **复杂度** | ⚠️ 需要重试/幂等处理 | ✅ 简单直接 |
|
||||
| **事务一致性** | ⚠️ 最终一致性 | ✅ 强一致性 |
|
||||
| **适用场景** | 微服务架构 | 模块化单体架构 |
|
||||
|
||||
---
|
||||
|
||||
## 8. 迁移指南
|
||||
|
||||
如果未来需要从"接口注入"迁移到"HTTP回调",需要:
|
||||
|
||||
1. **工单模块**:
|
||||
- 实现 HTTP 客户端发起回调
|
||||
- 添加回调配置存储
|
||||
- 实现重试机制和 `callback_retries` 表
|
||||
|
||||
2. **项目模块**:
|
||||
- 实现 `/api/project/workflow-callback` 接口
|
||||
- 添加幂等性检查(Redis/缓存)
|
||||
- 删除 `ProjectLifecycleUpdater` 接口注入逻辑
|
||||
|
||||
3. **rmdc-core**:
|
||||
- 删除 `ProjectWorkflowCallback` 适配器
|
||||
- 删除 `workflowSvc.SetProjectLifecycleUpdater()` 调用
|
||||
229
8-CMII-RMDC/6-rmdc-watchdog/1-rmdc-watchdog-DDS.md
Normal file
229
8-CMII-RMDC/6-rmdc-watchdog/1-rmdc-watchdog-DDS.md
Normal file
@@ -0,0 +1,229 @@
|
||||
# RMDC-watchdog详细设计说明书
|
||||
|
||||
### 项目归属模块
|
||||
|
||||
1. 包含的模块及对应的目录
|
||||
1. wdd.io/RMDC/rmdc-project-management
|
||||
2. wdd.io/RMDC/rmdc-watchdog
|
||||
3. wdd.io/RMDC/rmdc-watchdog-agent
|
||||
4. wdd.io/RMDC/rmdc-watchdog-node
|
||||
|
||||
## 授权系统说明
|
||||
|
||||
```概述```
|
||||
|
||||
1. rmdc-project-management是一级授权中心
|
||||
1. 授权所有二级授权中心
|
||||
2. 维护二级授权中心的授权信息
|
||||
3. 该模块之前为 rmdc-watchdog-center
|
||||
1. 但是由于功能单一并且与rmdc-project-management功能冲突
|
||||
2. 该模块已被移除,并且功能完全移动至rmdc-project-management中实现
|
||||
2. RMDC-watchdog作为项目授权中心(二级授权中心)
|
||||
1. 接受来自RMDC-watchdog-node的主机信息,唯一主机信息加密
|
||||
2. 将授权文件上传至rmdc-project-management
|
||||
3. 接受来自rmdc-project-management的授权文件,并解析授权信息
|
||||
4. 接受来自RMDC-watchdog-agent的心跳查询是否授权信息
|
||||
5. 向RMDC-watchdog-agent发送已授权信息,避免agent自毁
|
||||
3. RMDC-watchdog-agent是嵌入到业务运行的启动器
|
||||
1. 监控业务运行的一切
|
||||
2. 向RMDC-watchdog发送心跳查询是否授权信息
|
||||
3. 若长时间未被授权,则自毁
|
||||
4. 解析RMDC-watchdog的心跳回复,确保不会自毁
|
||||
5. 设计方案类似于 死手系统
|
||||
4. RMDC-watchdog-node是以daemonset运行
|
||||
1. 只暴露有限的、经过审计的操作接口(重启服务、收集日志、健康检查等),通过严格认证与授权调用,只能接受来自RMDC-watchdog的调用
|
||||
2. 可以收集每台主机的运行状态信息
|
||||
1. CPU
|
||||
2. 内存
|
||||
3. 磁盘
|
||||
4. 网络
|
||||
5. 授权系统防篡改核心
|
||||
1. TOTP算法防止信息篡改
|
||||
2. 每个项目的二级授权中心密钥均不同
|
||||
3. 每个项目的一级授权中心密钥均不同
|
||||
4. rmdc-project-management和RMDC-watchdog之间交互信息需要加密
|
||||
5. RMDC-watchdog和RMDC-watchdog-agent之间交互信息不需要加密,但是首先需要验证TOTP码
|
||||
6. 取消授权
|
||||
1. rmdc-project-management应该可以取消对一个项目的授权
|
||||
2. RMDC-watchdog应该有相应的接口,能够接收取消授权
|
||||
1. 取消特定主机的授权
|
||||
7. 授权时间
|
||||
1. rmdc-project-management应该能够设置授权时间
|
||||
2. RMDC-watchdog应该新增授权时间管理功能,
|
||||
1. 在解析授权文件中,应该解析授权时间,并设置授权时间
|
||||
|
||||
## Octopus Operator说明
|
||||
|
||||
### 运行环境说明
|
||||
|
||||
1. 有网络情况,通过RMDC-Exchange-Hub进行信息交互
|
||||
1. 正常情况,需要通过MQTT接收指令,上传指令
|
||||
2. 正常情况需要通过此种方式交互,无需认证
|
||||
2. 无网络情况
|
||||
1. 不正常情况,无法接收MQTT指令,无法上传指令
|
||||
2. 预留HTTP端口暴露,用于特殊情况访问
|
||||
3. 通过此种方式调用,复用二级授权中心的TOTP密钥,进行认证
|
||||
|
||||
### K8S Operator
|
||||
|
||||
``` 功能模块归属 rmdc-watchdog ```
|
||||
|
||||
#### 业务信息管理
|
||||
|
||||
1. 能够获取命名空间内的所有如下信息
|
||||
1. StatefulSet
|
||||
2. Deployment
|
||||
3. DaemonSet
|
||||
4. Pod
|
||||
5. ReplicaSet
|
||||
6. Service
|
||||
7. ConfigMap
|
||||
8. Secret
|
||||
2. 上述的内容均支持筛选查询
|
||||
3. 上述内容均支持yaml文件编辑
|
||||
4. 上述内容均支持删除
|
||||
5. 上述内容均支持创建
|
||||
6. 上述内容均支持复制
|
||||
|
||||
#### K8S信息管理
|
||||
|
||||
1. 能够获取k8s的所有如下信息
|
||||
1. 主机节点信息
|
||||
2. Ingress信息
|
||||
|
||||
#### 业务详情
|
||||
|
||||
1. 业务的部署模式为Deployment,能够获取到业务的详情
|
||||
2. 针对下面的内容均有 查看和编辑能力
|
||||
1. 副本数量
|
||||
2. 镜像版本
|
||||
3. 环境变量
|
||||
4. JVM参数
|
||||
3. 该业务的历史版本信息
|
||||
1. 通过同名的ReplicaSets获取
|
||||
2. 历史版本创建时间
|
||||
4. 业务镜像的运行环境变量
|
||||
1. 在镜像构建的时候, GIT_BRANCH GIT_COMMIT信息保存在docker image中
|
||||
2. 业务镜像的运行环境变量包含GIT_BRANCH GIT_COMMIT信息,此部分需要能够一键获取到
|
||||
|
||||
#### 中间件详情
|
||||
|
||||
1. 中间件的部署模式为StatefulSet
|
||||
2. 针对特定的中间件,需要有监视、信息查看、编辑、删除、重启等能力
|
||||
1. MySQL
|
||||
2. Redis
|
||||
3. MQTTX
|
||||
4. InfluxDB
|
||||
|
||||
### 向上-信息交互 wdd.io/RMDC/rmdc-exchange-hub
|
||||
|
||||
请参照 [1-rmdc-exchange-hub-DDS.md](0-设计方案\3-信息交换ExchangeHub\1-rmdc-exchange-hub-DDS.md)
|
||||
中项目启动注册流程-正常的rmdc-watchdog启动流程的详细流程
|
||||
|
||||
### 向下-信息交互 rmdc-watchdog-agent rmdc-watchdog-node
|
||||
|
||||
#### 集群信息收集
|
||||
|
||||
1. 收集主机运行状态信息
|
||||
1. from rmdc-watchdog-node
|
||||
2. 收集简单信息
|
||||
1. 主机名称
|
||||
2. 主机IP
|
||||
3. 主机CPU使用率
|
||||
4. 主机内存使用率
|
||||
5. 主机磁盘使用率
|
||||
6. 主机网络使用率
|
||||
3. 收集详细信息
|
||||
1. 主机磁盘的详细使用情况,包含每个目录,排除linux系统的特殊目录
|
||||
2. 主机内存的详细使用情况
|
||||
3. 主机CPU的详细使用情况
|
||||
4. 主机网络的详细使用情况
|
||||
2. 收集k8s集群运行状态信息
|
||||
1. from 自身
|
||||
2. 收集简单信息
|
||||
1. k8s集群名称
|
||||
2. k8s集群版本
|
||||
3. k8s集群节点数量
|
||||
4. k8s集群CPU使用率
|
||||
5. k8s集群内存使用率
|
||||
6. k8s节点状态
|
||||
7. k8s存活状态
|
||||
8. k8s存活时间
|
||||
|
||||
2. 收集业务运行状态信息
|
||||
1. from rmdc-watchdog-agent
|
||||
2. 业务如果重启, agent需要向watchdog发送故障信息
|
||||
1. 故障信息包括 业务名称, 运行主机信息,重启次数, 重启时间, 重启日志结存300行
|
||||
2. 需要持久化
|
||||
3. 收集简单信息
|
||||
1. 业务名称
|
||||
2. 业务存活状态
|
||||
3. 业务存活时间
|
||||
4. 业务CPU使用率
|
||||
5. 业务内存使用率
|
||||
4. 业务详细运行信息
|
||||
1. JAVA 内存分析
|
||||
2. JAVA 线程分析
|
||||
3. JAVA GC分析
|
||||
4. JAVA 类加载分析
|
||||
5. JAVA 类卸载分析
|
||||
|
||||
#### 主机指令下发
|
||||
|
||||
1. 下发主机指令
|
||||
1. to rmdc-watchdog-node
|
||||
2. 下发业务指令
|
||||
1. to rmdc-watchdog-agent
|
||||
3. 下发K8S指令
|
||||
1. to 自身
|
||||
|
||||
### 信息持久化
|
||||
|
||||
1. 上文中存在的说明的信息,需要持久化保存
|
||||
2. 支持时间段所有信息导出
|
||||
1. 提供HTTP端口,能够导出指定时间段的所有信息
|
||||
3. 业务系统存在如下的中间件,可以考虑使用
|
||||
1. MySQL数据库
|
||||
2. Redis数据库
|
||||
3. InfluxDB数据库
|
||||
|
||||
## Node Operator说明
|
||||
|
||||
```功能模块归属 rmdc-watchdog-node```
|
||||
|
||||
### DLTU - Download Load Tag Upload
|
||||
|
||||
1. 功能模块归属 rmdc-watchdog-node
|
||||
2. 接收来自wdd.io/RMDC/rmdc-watchdog的指令
|
||||
3. Download 下载镜像 从指定的url下载镜像压缩包至特定的目录保存
|
||||
1. 需要考虑无公网的异常情况
|
||||
2. 人工将压缩包防止在规定的目录中
|
||||
3. 应该检测本地的镜像压缩包,判定是否存在
|
||||
4. Load 加载镜像 从指定的目录加载镜像压缩包
|
||||
5. Tag 标签镜像 为镜像打标签
|
||||
6. Upload 上传镜像 将镜像推送到指定的Harbor仓库
|
||||
|
||||
|
||||
## 运行状态与心跳策略
|
||||
|
||||
1. **状态机**:`offline -> connecting -> verifying -> online -> disconnecting -> offline`,对应 exchange-hub 的在线状态表;心跳超时默认 30 秒转 offline。
|
||||
2. **心跳频率**:watchdog→exchange-hub 默认 5 秒;agent/node→watchdog 默认 10 秒;支持配置,超时触发 notice-center 告警。
|
||||
3. **缓存与补传**:指令结果、监控、日志上报在弱网下先写本地队列(容量 N,按时间/大小回收),重连后批量补传。
|
||||
|
||||
## 安全与授权细化
|
||||
|
||||
1. **授权校验**:watchdog 启动需验证一级 TOTP;agent/node 请求需验证二级 TOTP;授权文件到期需自动降级并通知项目管理。
|
||||
2. **接口暴露**:仅开放受审计的操作接口(重启、日志收集、健康检查、DLTU);默认拒绝除名单外的命令类型。
|
||||
3. **防篡改**:所有下行指令校验签名 + TOTP;agent 自毁前需等待 N 次连续授权失败确认。
|
||||
|
||||
## 监控与告警
|
||||
|
||||
1. **采集项**:主机 CPU/内存/磁盘/网络、Pod 状态、业务 JVM 指标、重启次数、上报延迟。
|
||||
2. **指标维度**:按项目/主机/Pod 维度聚合,暴露给 monitor-center;上报失败/延迟写入本地并告警。
|
||||
3. **日志截断**:业务故障日志仅回传最近 300 行;超长日志切片上传,避免 MQTT/HTTP 负载过大。
|
||||
|
||||
## 数据留存与导出
|
||||
|
||||
1. **持久化**:主机/业务指标可选本地 InfluxDB 或 SQLite(弱网时);周期性清理过期数据(默认 30 天)。
|
||||
2. **导出**:提供 HTTP 端口导出指定时间段信息,需签名 + TOTP 校验;导出操作写审计。
|
||||
|
||||
699
8-CMII-RMDC/6-rmdc-watchdog/2-rmdc-watchdog-业务流程图.md
Normal file
699
8-CMII-RMDC/6-rmdc-watchdog/2-rmdc-watchdog-业务流程图.md
Normal file
@@ -0,0 +1,699 @@
|
||||
# RMDC-Watchdog 业务流程图
|
||||
|
||||
## 一、项目注册流程
|
||||
|
||||
### 1.1 完整的注册时序流程图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Admin as 管理员<br/>(RMDC Portal)
|
||||
participant PM as rmdc-project-management<br/>(项目管理)
|
||||
participant ExHub as rmdc-exchange-hub<br/>(消息网关)
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant Node as watchdog-node<br/>(主机守护)
|
||||
participant Agent as watchdog-agent<br/>(业务代理)
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over Admin,Agent: ===== 阶段1: 项目创建 (RMDC平台侧) =====
|
||||
end
|
||||
|
||||
Admin->>PM: 1. 创建新项目
|
||||
PM->>PM: 2. 生成项目信息<br/>project_id = namespace_<8位随机数>
|
||||
PM->>PM: 3. 生成一级授权密钥<br/>tier_one_secret = generateSecret()
|
||||
PM->>PM: 4. 生成二级授权密钥<br/>tier_two_secret = generateSecret()
|
||||
PM->>PM: 5. 生成时间偏移值<br/>time_offset_allowed
|
||||
PM->>PM: 6. 持久化项目信息<br/>{project_id, namespace,<br/>tier_one_secret, tier_two_secret,<br/>auth_duration, time_offset_allowed}
|
||||
PM-->>Admin: 7. 返回项目配置文件<br/>(包含tier_one_secret和tier_two_secret<br/>用于部署Watchdog)
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over Admin,Agent: ===== 阶段2: Watchdog启动与MQTT连接 =====
|
||||
end
|
||||
|
||||
Note over WD: 使用项目配置文件部署<br/>本地已有tier_one_secret和tier_two_secret<br/>(密钥不通过公网传输)
|
||||
WD->>MQTT: 8. 连接MQTT Broker
|
||||
WD->>WD: 9. 创建MQTT订阅<br/>订阅: wdd/RDMC/command/down/<project_id><br/>订阅: wdd/RDMC/message/down/<project_id>
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over Admin,Agent: ===== 阶段3: 项目注册 - 挑战应答机制 =====
|
||||
end
|
||||
|
||||
WD->>WD: 10. 生成Tier-One TOTP验证码<br/>(8位, 30分钟有效)<br/>使用本地tier_one_secret
|
||||
WD->>MQTT: 11. 发布注册Command到<br/>wdd/RDMC/command/up<br/>{type:"register", project_id,<br/>namespace, totp_code, env_info}
|
||||
MQTT->>ExHub: 12. 转发注册Command
|
||||
|
||||
ExHub->>PM: 13. 验证项目信息合法性<br/>GetProjectInfo(project_id)
|
||||
PM-->>ExHub: 14. 返回项目密钥等信息<br/>{tier_one_secret, tier_two_secret}
|
||||
|
||||
ExHub->>ExHub: 15. 验证TOTP验证码 (可配置开关)<br/>VerifyTierOneTOTP(totp_code, tier_one_secret)
|
||||
|
||||
alt TOTP验证成功 或 验证已关闭
|
||||
ExHub->>ExHub: 16. 生成32位随机挑战码<br/>challenge = randomString(32)
|
||||
ExHub->>ExHub: 17. 生成服务端TOTP响应码<br/>server_totp = GenerateTierOneTOTP(tier_one_secret)
|
||||
ExHub->>ExHub: 18. 记录挑战码到缓存<br/>cache[project_id] = challenge
|
||||
ExHub->>MQTT: 19. 发布注册确认Message到<br/>wdd/RDMC/message/down/<project_id><br/>{type:"register_ack", challenge, server_totp}
|
||||
ExHub->>MQTT: 20. 发布授权Command到<br/>wdd/RDMC/command/down/<project_id><br/>{type:"auth_response", success:true}<br/>(不传输密钥,密钥已在本地)
|
||||
else TOTP验证失败
|
||||
ExHub->>MQTT: 发布注册拒绝<br/>{type:"register_reject", reason}
|
||||
end
|
||||
|
||||
MQTT->>WD: 21. 推送注册确认Message
|
||||
MQTT->>WD: 22. 推送授权Command
|
||||
|
||||
WD->>WD: 23. 验证服务端TOTP (可配置开关)<br/>VerifyTierOneTOTP(server_totp, tier_one_secret)
|
||||
|
||||
alt 服务端TOTP验证成功 或 验证已关闭
|
||||
WD->>WD: 24. 确认tier_two_secret有效<br/>(使用本地已有的密钥)
|
||||
WD->>WD: 25. 解析challenge挑战码
|
||||
WD->>MQTT: 26. 发布注册完成Message到<br/>wdd/RDMC/message/up<br/>{type:"register_complete",<br/>project_id, challenge}
|
||||
else 服务端TOTP验证失败
|
||||
Note over WD: 注册失败,服务端验证不通过<br/>可能是中间人攻击
|
||||
end
|
||||
|
||||
MQTT->>ExHub: 27. 转发注册完成Message
|
||||
ExHub->>ExHub: 28. 验证challenge匹配<br/>cache[project_id] == received_challenge
|
||||
|
||||
alt 挑战验证成功
|
||||
ExHub->>ExHub: 29. 更新项目状态为Online<br/>UpdateProjectState(project_id, "online")
|
||||
ExHub->>PM: 30. 通知项目上线
|
||||
PM->>PM: 31. 更新项目在线状态
|
||||
Note over WD: 注册成功,开始正常工作
|
||||
else 挑战验证失败
|
||||
ExHub->>MQTT: 发布验证失败消息
|
||||
Note over WD: 注册失败,等待重试
|
||||
end
|
||||
|
||||
rect rgb(220, 240, 255)
|
||||
Note over Admin,Agent: ===== 阶段4: 心跳维持 =====
|
||||
end
|
||||
|
||||
loop 每5秒
|
||||
WD->>MQTT: 发布心跳Message到<br/>wdd/RDMC/message/up<br/>{type:"heartbeat", metrics}
|
||||
MQTT->>ExHub: 转发心跳
|
||||
ExHub->>ExHub: 刷新项目在线状态
|
||||
end
|
||||
```
|
||||
|
||||
### 1.2 注册流程关键设计说明
|
||||
|
||||
| 设计要点 | 说明 |
|
||||
|----------|------|
|
||||
| **密钥生成时机** | tier_one_secret 和 tier_two_secret 均在 rmdc-project-management 创建项目时生成 |
|
||||
| **密钥传输方式** | 密钥通过项目配置文件离线部署到 Watchdog,**不通过公网MQTT传输** |
|
||||
| **双向TOTP验证** | Watchdog 发送 TOTP 给 ExHub 验证,ExHub 返回 TOTP 给 Watchdog 验证 (可配置开关) |
|
||||
| **挑战应答机制** | 32位随机挑战码确保通信双方身份真实性 |
|
||||
| **安全增强** | 即使 MQTT 被监听,攻击者也无法伪造有效的 TOTP 验证码 |
|
||||
|
||||
---
|
||||
|
||||
## 二、授权系统完整流程
|
||||
|
||||
### 2.1 授权系统总览架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "RMDC平台 (内网)"
|
||||
PM["rmdc-project-management<br/>项目管理"]
|
||||
CENTER["rmdc-watchdog-center<br/>一级授权中心"]
|
||||
EXHUB["rmdc-exchange-hub<br/>消息网关"]
|
||||
DB[(授权数据库)]
|
||||
end
|
||||
|
||||
subgraph "项目环境 (外网/隔离网络)"
|
||||
WATCHDOG["rmdc-watchdog<br/>二级授权中心"]
|
||||
AGENT1["watchdog-agent<br/>业务A"]
|
||||
AGENT2["watchdog-agent<br/>业务B"]
|
||||
NODE1["watchdog-node<br/>主机1"]
|
||||
NODE2["watchdog-node<br/>主机2"]
|
||||
end
|
||||
|
||||
PM --"1.项目创建"--> CENTER
|
||||
CENTER --"2.授权配置"--> PM
|
||||
CENTER <--"3.授权申请/下发<br/>Tier-One TOTP"--> EXHUB
|
||||
EXHUB <==" 4.MQTT公网"==> WATCHDOG
|
||||
|
||||
NODE1 --"5.主机信息上报"--> WATCHDOG
|
||||
NODE2 --"5.主机信息上报"--> WATCHDOG
|
||||
|
||||
AGENT1 <--"6.心跳/授权<br/>Tier-Two TOTP"--> WATCHDOG
|
||||
AGENT2 <--"6.心跳/授权<br/>Tier-Two TOTP"--> WATCHDOG
|
||||
|
||||
CENTER --> DB
|
||||
PM --> DB
|
||||
|
||||
style CENTER fill:#ff6b6b
|
||||
style WATCHDOG fill:#4ecdc4
|
||||
style EXHUB fill:#ffd43b
|
||||
style PM fill:#a9e34b
|
||||
```
|
||||
|
||||
### 2.2 授权申请与下发流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Node as rmdc-watchdog-node<br/>(主机)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant MQTT as Exchange-Hub<br/>(MQTT)
|
||||
participant Center as rmdc-watchdog-center<br/>(一级授权中心)
|
||||
participant DB as 授权数据库
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over Node,DB: ===== 阶段1: 主机信息收集 =====
|
||||
end
|
||||
|
||||
Note over Node: 项目启动,以DaemonSet运行
|
||||
Node->>Watchdog: 1. 上报主机硬件信息<br/>{MachineID, CPU, Memory, Serial, IP}
|
||||
Watchdog->>Watchdog: 2. 加密主机信息<br/>EncryptHostInfo(hostInfo, tierOneSecret)
|
||||
Watchdog->>Watchdog: 3. 生成授权申请文件<br/>GenerateAuthorizationFile()
|
||||
|
||||
Note over Watchdog: 授权文件包含:<br/>- EncryptedHostMap<br/>- TOTPCode (8位,30分钟有效)<br/>- EncryptedNamespace
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over Node,DB: ===== 阶段2: 授权申请 =====
|
||||
end
|
||||
|
||||
Watchdog->>MQTT: 4. 发布授权申请Command到<br/>wdd/RDMC/command/up<br/>{type:"auth_request", AuthorizationFile}
|
||||
MQTT->>Center: 5. 转发授权申请
|
||||
|
||||
Center->>Center: 6. 解密项目命名空间<br/>Decrypt(EncryptedNamespace)
|
||||
Center->>DB: 7. 获取项目信息<br/>GetProjectInfo(namespace)
|
||||
DB-->>Center: 返回项目密钥等信息
|
||||
|
||||
Center->>Center: 8. 验证TOTP验证码<br/>VerifyTierOneTOTPCode()
|
||||
Center->>Center: 9. 验证主机信息完整性<br/>DecryptHostInfo() 逐个验证
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over Node,DB: ===== 阶段3: 授权下发 =====
|
||||
end
|
||||
|
||||
alt 验证成功
|
||||
Center->>Center: 10. 生成新TOTP验证码
|
||||
Center->>Center: 11. 构造授权码<br/>{authorized_hosts, expire_time, tier_two_secret}
|
||||
Center->>DB: 12. 持久化授权记录
|
||||
Center->>MQTT: 13. 发布授权码到<br/>wdd/RDMC/command/down/{project_id}<br/>{type:"auth_response", AuthorizationCode}
|
||||
else 验证失败
|
||||
Center->>MQTT: 发布授权拒绝消息<br/>{type:"auth_reject", reason}
|
||||
end
|
||||
|
||||
MQTT->>Watchdog: 14. 推送授权码
|
||||
|
||||
Watchdog->>Watchdog: 15. 验证返回的TOTP
|
||||
Watchdog->>Watchdog: 16. 解密并验证命名空间
|
||||
Watchdog->>Watchdog: 17. 解密每个主机信息
|
||||
Watchdog->>Watchdog: 18. 计算时间偏移<br/>timeOffset = now - firstAuthTime
|
||||
Watchdog->>Watchdog: 19. 持久化保存授权信息<br/>saveAuthorizationInfo()
|
||||
|
||||
Note over Watchdog: 授权存储包含:<br/>- EncryptedAuthorizationCode<br/>- FirstAuthTime<br/>- TimeOffset<br/>- AuthorizedHostMap<br/>- TierTwoTOTPSecret
|
||||
```
|
||||
|
||||
### 2.3 Agent授权心跳流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Agent as rmdc-watchdog-agent<br/>(业务启动器)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant Business as 业务进程<br/>(Java/Python)
|
||||
|
||||
rect rgb(200, 255, 200)
|
||||
Note over Agent,Business: ===== 首次连接 - 获取密钥 =====
|
||||
end
|
||||
|
||||
Agent->>Agent: 1. 收集主机信息<br/>GetAllInfo()
|
||||
Agent->>Watchdog: 2. 发送心跳请求<br/>{HostInfo, EnvInfo, Timestamp, TOTPCode=""}
|
||||
|
||||
Watchdog->>Watchdog: 3. 验证时间戳有效性<br/>|now - timestamp| < 5分钟
|
||||
Watchdog->>Watchdog: 4. 添加主机到集合<br/>AddHostInfo()
|
||||
Watchdog-->>Agent: 5. 返回响应<br/>{Authorized:false, TierTwoSecret:secret}
|
||||
|
||||
Agent->>Agent: 6. 保存TOTP密钥<br/>tierTwoTotpSecret = secret
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over Agent,Business: ===== 后续心跳 - 授权验证 =====
|
||||
end
|
||||
|
||||
loop 心跳循环 (成功后2小时,失败后1小时)
|
||||
Agent->>Agent: 7. 生成TOTP验证码<br/>GenerateTierTwoTOTPCode(secret)<br/>6位,30秒有效
|
||||
Agent->>Watchdog: 8. 发送心跳请求<br/>{HostInfo, Timestamp, TOTPCode}
|
||||
|
||||
Watchdog->>Watchdog: 9. 验证TOTP验证码<br/>VerifyTierTwoTOTPCode()
|
||||
|
||||
alt TOTP验证成功
|
||||
Watchdog->>Watchdog: 10. 检查主机授权状态<br/>IsHostAuthorized(hostInfo)
|
||||
Watchdog->>Watchdog: 11. 生成响应TOTP
|
||||
Watchdog-->>Agent: 12. 返回{Authorized:true/false, TOTPCode}
|
||||
|
||||
Agent->>Agent: 13. 验证服务端TOTP<br/>双向验证
|
||||
|
||||
alt 授权成功
|
||||
Agent->>Agent: 14. failCount = 1<br/>等待2小时
|
||||
else 授权失败
|
||||
Agent->>Agent: 15. failCount++<br/>等待1小时
|
||||
end
|
||||
else TOTP验证失败
|
||||
Watchdog-->>Agent: 返回错误:无效的TOTP验证码
|
||||
Agent->>Agent: failCount++
|
||||
end
|
||||
|
||||
alt failCount >= 12
|
||||
Agent->>Business: 16. 发送SIGTERM信号
|
||||
Note over Business: 业务进程终止<br/>(死手系统触发)
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### 2.4 授权撤销流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Admin as 管理员<br/>(RMDC Portal)
|
||||
participant PM as project-management
|
||||
participant Center as rmdc-watchdog-center<br/>(一级授权中心)
|
||||
participant MQTT as Exchange-Hub<br/>(MQTT)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant Agent as rmdc-watchdog-agent
|
||||
participant Business as 业务进程
|
||||
|
||||
rect rgb(255, 220, 220)
|
||||
Note over Admin,Business: ===== 授权撤销流程 =====
|
||||
end
|
||||
|
||||
Admin->>PM: 1. 发起撤销授权请求<br/>{project_id, reason}
|
||||
PM->>Center: 2. 请求撤销项目授权
|
||||
Center->>Center: 3. 更新项目授权状态<br/>status = revoked
|
||||
Center->>Center: 4. 生成撤销Command<br/>{type:"auth_revoke", project_id, totp}
|
||||
|
||||
Center->>MQTT: 5. 发布撤销Command到<br/>wdd/RDMC/command/down/{project_id}
|
||||
MQTT->>Watchdog: 6. 推送撤销指令
|
||||
|
||||
Watchdog->>Watchdog: 7. 验证撤销指令TOTP
|
||||
Watchdog->>Watchdog: 8. 清除本地授权存储<br/>deleteAuthorizationInfo()
|
||||
Watchdog->>Watchdog: 9. 设置授权状态为未授权<br/>initialized = false
|
||||
|
||||
Note over Agent: 下次心跳时...
|
||||
Agent->>Watchdog: 10. 发送心跳请求
|
||||
Watchdog-->>Agent: 11. 返回{Authorized:false}
|
||||
|
||||
Agent->>Agent: 12. failCount++
|
||||
Note over Agent: 连续失败12次后...
|
||||
|
||||
Agent->>Business: 13. 发送SIGTERM信号<br/>触发业务进程终止
|
||||
Note over Business: 业务自毁<br/>死手系统生效
|
||||
|
||||
Watchdog->>MQTT: 14. 上报撤销完成消息<br/>{type:"auth_revoke_ack"}
|
||||
MQTT->>Center: 15. 转发撤销确认
|
||||
Center->>PM: 16. 更新项目状态
|
||||
PM->>Admin: 17. 通知撤销成功
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 三、K8S指令执行流程
|
||||
|
||||
### 3.1 K8S指令业务流程图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant User as 用户<br/>(RMDC Portal)
|
||||
participant Api as rmdc-core<br/>(API Gateway)
|
||||
participant Operator as octopus-operator<br/>(执行中心)
|
||||
participant ExHub as rmdc-exchange-hub<br/>(消息网关)
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as rmdc-watchdog<br/>(K8s Operator)
|
||||
participant K8s as Kubernetes API
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over User,K8s: ===== 阶段1: 指令发起 =====
|
||||
end
|
||||
|
||||
User->>Api: 1. 发起K8S操作请求<br/>{project_id, action, resource, name}
|
||||
Api->>Api: 2. 验证用户权限<br/>CheckPermission(user, project, action)
|
||||
Api->>Operator: 3. 调用执行中心API
|
||||
|
||||
Operator->>Operator: 4. 构造K8S执行指令<br/>K8sExecCommand{<br/> command_id, namespace,<br/> resource, name, action,<br/> command, timeout<br/>}
|
||||
Operator->>ExHub: 5. 调用指令下发API<br/>POST /api/command/send
|
||||
|
||||
ExHub->>ExHub: 6. 生成唯一CommandID<br/>记录指令到数据库<br/>状态: Pending
|
||||
ExHub->>MQTT: 7. 发布K8S执行Command到<br/>wdd/RDMC/command/down/{project_id}<br/>{type:"k8s_exec", payload}
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over User,K8s: ===== 阶段2: 指令执行 =====
|
||||
end
|
||||
|
||||
MQTT->>WD: 8. 推送K8S执行指令
|
||||
WD->>WD: 9. 解析指令<br/>路由到K8sHandler
|
||||
WD->>WD: 10. 记录开始时间<br/>status = running
|
||||
|
||||
alt action == "logs"
|
||||
WD->>K8s: 11a. 调用K8S API<br/>GetPodLogs(namespace, name, container)
|
||||
else action == "exec"
|
||||
WD->>K8s: 11b. 调用K8S API<br/>ExecCommand(pod, container, command)
|
||||
else action == "scale"
|
||||
WD->>K8s: 11c. 调用K8S API<br/>ScaleDeployment(name, replicas)
|
||||
else action == "restart"
|
||||
WD->>K8s: 11d. 调用K8S API<br/>RolloutRestart(deployment)
|
||||
else action == "delete"
|
||||
WD->>K8s: 11e. 调用K8S API<br/>DeleteResource(resource, name)
|
||||
end
|
||||
|
||||
K8s-->>WD: 12. 返回执行结果
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over User,K8s: ===== 阶段3: 结果返回 =====
|
||||
end
|
||||
|
||||
WD->>WD: 13. 构造执行结果<br/>ExecResult{command_id, status,<br/>exit_code, output, error, duration}
|
||||
WD->>MQTT: 14. 发布结果Message到<br/>wdd/RDMC/message/up<br/>{type:"exec_result", payload}
|
||||
|
||||
MQTT->>ExHub: 15. 转发执行结果
|
||||
ExHub->>ExHub: 16. 更新指令状态<br/>记录执行时长
|
||||
ExHub->>Operator: 17. 推送结果给执行中心
|
||||
Operator->>Api: 18. 返回执行结果
|
||||
Api->>User: 19. 展示执行结果
|
||||
```
|
||||
|
||||
### 3.2 K8S支持的操作类型
|
||||
|
||||
| Action | 说明 | 目标资源 | 参数 |
|
||||
|--------|------|----------|------|
|
||||
| `logs` | 获取日志 | Pod | container, tail_lines, follow |
|
||||
| `exec` | 执行命令 | Pod | container, command[], timeout |
|
||||
| `scale` | 扩缩容 | Deployment/StatefulSet | scale_count |
|
||||
| `restart` | 滚动重启 | Deployment/StatefulSet | - |
|
||||
| `delete` | 删除资源 | Pod/Deployment/Service等 | - |
|
||||
| `get` | 获取信息 | 任意资源 | output_format |
|
||||
| `apply` | 应用配置 | 任意资源 | yaml_content |
|
||||
|
||||
---
|
||||
|
||||
## 四、主机指令执行流程
|
||||
|
||||
### 4.1 主机指令业务流程图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant User as 用户<br/>(RMDC Portal)
|
||||
participant Api as rmdc-core<br/>(API Gateway)
|
||||
participant Operator as octopus-operator<br/>(执行中心)
|
||||
participant ExHub as rmdc-exchange-hub<br/>(消息网关)
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant Node as watchdog-node<br/>(主机守护)
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over User,Node: ===== 阶段1: 指令发起 =====
|
||||
end
|
||||
|
||||
User->>Api: 1. 发起主机操作请求<br/>{project_id, host_id, action, script}
|
||||
Api->>Api: 2. 验证用户权限<br/>CheckPermission(user, project, "host_exec")
|
||||
Api->>Operator: 3. 调用执行中心API
|
||||
|
||||
Operator->>Operator: 4. 构造主机执行指令<br/>HostExecCommand{<br/> command_id, host_id,<br/> action, script, args, timeout<br/>}
|
||||
Operator->>ExHub: 5. 调用指令下发API<br/>POST /api/command/send
|
||||
|
||||
ExHub->>ExHub: 6. 生成唯一CommandID<br/>记录指令到数据库<br/>状态: Pending
|
||||
ExHub->>MQTT: 7. 发布主机执行Command到<br/>wdd/RDMC/command/down/{project_id}<br/>{type:"host_exec", payload}
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over User,Node: ===== 阶段2: 指令转发与执行 =====
|
||||
end
|
||||
|
||||
MQTT->>WD: 8. 推送主机执行指令
|
||||
WD->>WD: 9. 解析指令<br/>路由到HostHandler
|
||||
WD->>WD: 10. 验证目标主机在线<br/>CheckHostOnline(host_id)
|
||||
|
||||
alt 主机在线
|
||||
WD->>Node: 11. 转发执行指令到目标Node<br/>HTTP POST /api/exec<br/>(内网通信,TOTP验证)
|
||||
Node->>Node: 12. 验证请求合法性<br/>VerifyTOTP()
|
||||
Node->>Node: 13. 执行命令/脚本<br/>ExecuteScript(script, args)
|
||||
Node-->>WD: 14. 返回执行结果<br/>{exit_code, stdout, stderr}
|
||||
else 主机离线
|
||||
WD->>WD: 构造错误结果<br/>error = "目标主机离线"
|
||||
end
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over User,Node: ===== 阶段3: 结果返回 =====
|
||||
end
|
||||
|
||||
WD->>WD: 15. 构造执行结果<br/>ExecResult{command_id, status,<br/>exit_code, output, error, duration}
|
||||
WD->>MQTT: 16. 发布结果Message到<br/>wdd/RDMC/message/up<br/>{type:"exec_result", payload}
|
||||
|
||||
MQTT->>ExHub: 17. 转发执行结果
|
||||
ExHub->>ExHub: 18. 更新指令状态<br/>记录执行时长
|
||||
ExHub->>Operator: 19. 推送结果给执行中心
|
||||
Operator->>Api: 20. 返回执行结果
|
||||
Api->>User: 21. 展示执行结果
|
||||
```
|
||||
|
||||
### 4.2 Watchdog到Node的通信架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "rmdc-watchdog"
|
||||
WD_Router[消息路由器]
|
||||
WD_HostH[HostHandler]
|
||||
WD_NodeClient[NodeClient<br/>HTTP Client]
|
||||
end
|
||||
|
||||
subgraph "watchdog-node (DaemonSet)"
|
||||
Node_Server[HTTP Server<br/>:8081]
|
||||
Node_Auth[TOTP验证中间件]
|
||||
Node_Exec[命令执行器]
|
||||
Node_Info[信息收集器]
|
||||
end
|
||||
|
||||
WD_Router --> WD_HostH
|
||||
WD_HostH --> WD_NodeClient
|
||||
WD_NodeClient ==HTTP/TOTP==> Node_Server
|
||||
Node_Server --> Node_Auth
|
||||
Node_Auth --> Node_Exec
|
||||
Node_Auth --> Node_Info
|
||||
|
||||
style WD_NodeClient fill:#4ecdc4,stroke:#087f5b
|
||||
style Node_Server fill:#a9e34b,stroke:#5c940d
|
||||
```
|
||||
|
||||
### 4.3 主机支持的操作类型
|
||||
|
||||
| Action | 说明 | 参数 |
|
||||
|--------|------|------|
|
||||
| `exec` | 执行Shell命令 | script, args[], timeout |
|
||||
| `info` | 获取主机信息 | info_type (cpu/memory/disk/network) |
|
||||
| `service` | 服务管理 | service_name, operation (start/stop/restart) |
|
||||
| `file` | 文件操作 | path, operation (read/write/delete) |
|
||||
| `dltu` | 镜像操作 | operation (download/load/tag/upload), params |
|
||||
|
||||
---
|
||||
|
||||
## 五、同步指令设计方案
|
||||
|
||||
### 5.1 同步指令可行性分析
|
||||
|
||||
#### 适用场景分析
|
||||
|
||||
| 场景 | 当前模式 | 同步需求 | 实现建议 |
|
||||
|------|----------|----------|----------|
|
||||
| **日志查看** | 异步 | 高 - 需要实时看到日志输出 | 长轮询或推送 |
|
||||
| **主机命令执行** | 异步 | 中 - 交互式命令需要实时 | 超时等待机制 |
|
||||
| **K8S资源查询** | 异步 | 中 - 查询操作期望快速返回 | 超时等待机制 |
|
||||
| **业务更新** | 异步 | 低 - 长时间操作适合异步 | 保持异步 + 通知 |
|
||||
| **监控数据** | 异步 | 低 - 定期上报即可 | 保持异步 |
|
||||
|
||||
#### 技术挑战
|
||||
|
||||
1. **网络延迟**: 跨公网MQTT通信存在不确定延迟
|
||||
2. **超时处理**: 需要合理设置超时时间避免长时间阻塞
|
||||
3. **连接保持**: 长时间等待需要保持连接不断开
|
||||
4. **资源占用**: 同步等待会占用服务器连接资源
|
||||
|
||||
### 5.2 基于现有架构的同步指令实现方案
|
||||
|
||||
#### 方案设计 (基于Go Channel + HTTP长轮询)
|
||||
|
||||
根据项目现有的Go技术栈,建议采用**HTTP长轮询 + 结果缓存**方案:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant User as 用户
|
||||
participant Api as API Gateway
|
||||
participant ExHub as Exchange-Hub
|
||||
participant Cache as ResultCache<br/>(sync.Map)
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as Watchdog
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over User,WD: ===== 同步指令发送 =====
|
||||
end
|
||||
|
||||
User->>Api: 1. POST /api/command/sync<br/>{project_id, type, payload, timeout:30s}
|
||||
Api->>ExHub: 2. 调用同步指令API
|
||||
ExHub->>ExHub: 3. 生成CommandID
|
||||
ExHub->>Cache: 4. 创建等待通道<br/>waitChan[cmdId] = make(chan Result)
|
||||
ExHub->>MQTT: 5. 发布指令
|
||||
MQTT->>WD: 6. 推送到Watchdog
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over User,WD: ===== 执行与等待 =====
|
||||
end
|
||||
|
||||
WD->>WD: 7. 执行指令
|
||||
WD->>MQTT: 8. 返回结果
|
||||
MQTT->>ExHub: 9. 接收结果
|
||||
ExHub->>Cache: 10. 发送结果到通道<br/>waitChan[cmdId] <- result
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over User,WD: ===== 结果返回 =====
|
||||
end
|
||||
|
||||
ExHub->>ExHub: 11. select等待结果或超时
|
||||
ExHub->>Api: 12. 返回执行结果
|
||||
Api->>User: 13. 返回结果给用户
|
||||
```
|
||||
|
||||
#### Exchange-Hub同步指令管理器设计
|
||||
|
||||
```go
|
||||
// SyncCommandManager 同步指令管理器
|
||||
type SyncCommandManager struct {
|
||||
waitChannels sync.Map // map[commandID]chan *ExecResult
|
||||
timeout time.Duration
|
||||
}
|
||||
|
||||
// SendAndWait 发送指令并等待结果
|
||||
func (m *SyncCommandManager) SendAndWait(projectID string, cmd *CommandMessage, timeout time.Duration) (*ExecResult, error) {
|
||||
// 1. 创建等待通道
|
||||
waitChan := make(chan *ExecResult, 1)
|
||||
m.waitChannels.Store(cmd.MessageID, waitChan)
|
||||
defer m.waitChannels.Delete(cmd.MessageID)
|
||||
|
||||
// 2. 发送指令
|
||||
mqttService := GetMQTTService()
|
||||
if err := mqttService.PublishCommand(projectID, cmd); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 3. 等待结果或超时
|
||||
select {
|
||||
case result := <-waitChan:
|
||||
return result, nil
|
||||
case <-time.After(timeout):
|
||||
return nil, errors.New("command execution timeout")
|
||||
}
|
||||
}
|
||||
|
||||
// OnResult 接收结果回调
|
||||
func (m *SyncCommandManager) OnResult(result *ExecResult) {
|
||||
if ch, ok := m.waitChannels.Load(result.CommandID); ok {
|
||||
ch.(chan *ExecResult) <- result
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 5.3 日志实时查看方案
|
||||
|
||||
对于日志实时查看场景,建议采用**流式日志推送**方案:
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant User as 用户
|
||||
participant Frontend as 前端
|
||||
participant Api as API Gateway
|
||||
participant ExHub as Exchange-Hub
|
||||
participant MQTT as MQTT Broker
|
||||
participant WD as Watchdog
|
||||
participant K8s as K8S API
|
||||
|
||||
User->>Frontend: 1. 点击查看实时日志
|
||||
Frontend->>Api: 2. POST /api/logs/stream<br/>{project_id, pod, container, follow:true}
|
||||
Api->>ExHub: 3. 创建日志流会话<br/>sessionId = uuid()
|
||||
ExHub->>MQTT: 4. 发布日志查询指令<br/>{type:"log_query", follow:true, session_id}
|
||||
MQTT->>WD: 5. 推送指令
|
||||
WD->>K8s: 6. 调用K8S Logs API (follow=true)
|
||||
|
||||
loop 日志流
|
||||
K8s-->>WD: 7. 返回日志行
|
||||
WD->>MQTT: 8. 发布日志Message<br/>{type:"log_result", session_id, lines, is_complete:false}
|
||||
MQTT->>ExHub: 9. 转发日志
|
||||
ExHub->>ExHub: 10. 根据session_id路由
|
||||
ExHub->>Api: 11. 推送到API会话
|
||||
Api->>Frontend: 12. SSE/轮询返回日志
|
||||
Frontend->>User: 13. 实时显示日志
|
||||
end
|
||||
|
||||
User->>Frontend: 14. 停止查看
|
||||
Frontend->>Api: 15. DELETE /api/logs/stream/{session_id}
|
||||
Api->>ExHub: 16. 关闭日志流会话
|
||||
ExHub->>MQTT: 17. 发布停止指令
|
||||
```
|
||||
|
||||
#### 前端实现建议
|
||||
|
||||
```typescript
|
||||
// 使用Server-Sent Events (SSE) 接收实时日志
|
||||
async function streamLogs(projectId: string, pod: string, container: string) {
|
||||
const response = await fetch(`/api/logs/stream`, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ project_id: projectId, pod, container, follow: true })
|
||||
});
|
||||
|
||||
const sessionId = (await response.json()).session_id;
|
||||
|
||||
// 使用SSE或长轮询接收日志
|
||||
const eventSource = new EventSource(`/api/logs/stream/${sessionId}`);
|
||||
|
||||
eventSource.onmessage = (event) => {
|
||||
const logData = JSON.parse(event.data);
|
||||
appendLogToUI(logData.lines);
|
||||
};
|
||||
|
||||
return {
|
||||
stop: () => {
|
||||
eventSource.close();
|
||||
fetch(`/api/logs/stream/${sessionId}`, { method: 'DELETE' });
|
||||
}
|
||||
};
|
||||
}
|
||||
```
|
||||
---
|
||||
|
||||
## 六、数据结构与安全机制汇总
|
||||
|
||||
### 6.1 MQTT Topic与消息类型对照表
|
||||
|
||||
| 方向 | Topic | 消息类型 | 说明 |
|
||||
|------|-------|----------|------|
|
||||
| **上行** | `wdd/RDMC/command/up` | `register` | 项目注册 |
|
||||
| **上行** | `wdd/RDMC/command/up` | `auth_request` | 授权申请 |
|
||||
| **上行** | `wdd/RDMC/message/up` | `register_complete` | 注册完成确认 |
|
||||
| **上行** | `wdd/RDMC/message/up` | `heartbeat` | 心跳数据 |
|
||||
| **上行** | `wdd/RDMC/message/up` | `monitor` | 监控数据上报 |
|
||||
| **上行** | `wdd/RDMC/message/up` | `exec_result` | 指令执行结果 |
|
||||
| **上行** | `wdd/RDMC/message/up` | `log_result` | 日志查询结果 |
|
||||
| **上行** | `wdd/RDMC/message/up` | `alert` | 告警信息 |
|
||||
| **下行** | `wdd/RDMC/command/down/{id}` | `auth_response` | 授权响应 |
|
||||
| **下行** | `wdd/RDMC/command/down/{id}` | `auth_revoke` | 授权撤销 |
|
||||
| **下行** | `wdd/RDMC/command/down/{id}` | `log_query` | 日志查询指令 |
|
||||
| **下行** | `wdd/RDMC/command/down/{id}` | `host_exec` | 主机执行指令 |
|
||||
| **下行** | `wdd/RDMC/command/down/{id}` | `k8s_exec` | K8S执行指令 |
|
||||
| **下行** | `wdd/RDMC/command/down/{id}` | `update` | 业务更新指令 |
|
||||
| **下行** | `wdd/RDMC/message/down/{id}` | `register_ack` | 注册确认消息 |
|
||||
|
||||
### 6.2 安全机制汇总
|
||||
|
||||
| 场景 | 安全机制 | 参数 |
|
||||
|------|----------|------|
|
||||
| Center ↔ Watchdog | Tier-One TOTP + AES-GCM | 8位码, 30分钟有效期, SHA256 |
|
||||
| Watchdog ↔ Agent | Tier-Two TOTP | 6位码, 30秒有效期, SHA1 |
|
||||
| Watchdog ↔ Node | Tier-Two TOTP复用 | 内网HTTP + TOTP认证 |
|
||||
| HTTP备用接口 | 复用Tier-Two TOTP密钥 | 需要TOTP认证 |
|
||||
| 主机信息 | 硬件指纹绑定 | MachineID+CPU+Memory+Serial |
|
||||
| 死手系统 | 心跳失败自毁 | 连续12次失败触发 |
|
||||
| 消息传输 | TLS加密 | MQTT over TLS |
|
||||
| 敏感数据 | AES-256-GCM加密 | 授权码、密钥等 |
|
||||
336
8-CMII-RMDC/6-rmdc-watchdog/3-rmdc-watchdog-内部交互流程.md
Normal file
336
8-CMII-RMDC/6-rmdc-watchdog/3-rmdc-watchdog-内部交互流程.md
Normal file
@@ -0,0 +1,336 @@
|
||||
# RMDC-Watchdog 内部交互流程
|
||||
|
||||
## 一、交互流程总览
|
||||
|
||||
本文档详细描述了RMDC-Watchdog系统内部各组件之间的交互流程,包括Agent心跳上报、Node信息上报以及项目级别(二级授权中心)的完整业务流程。
|
||||
|
||||
### 1.1 组件关系图
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "项目环境 (K8S集群)"
|
||||
WATCHDOG["rmdc-watchdog<br/>(二级授权中心)<br/>Port: 8990"]
|
||||
AGENT1["rmdc-watchdog-agent<br/>业务Pod A"]
|
||||
AGENT2["rmdc-watchdog-agent<br/>业务Pod B"]
|
||||
NODE1["rmdc-watchdog-node<br/>节点1 (DaemonSet)"]
|
||||
NODE2["rmdc-watchdog-node<br/>节点2 (DaemonSet)"]
|
||||
end
|
||||
|
||||
NODE1 --"POST /api/node/info<br/>主机信息+运行指标"--> WATCHDOG
|
||||
NODE2 --"POST /api/node/info<br/>主机信息+运行指标"--> WATCHDOG
|
||||
|
||||
AGENT1 <--"POST /api/heartbeat<br/>心跳+TOTP验证"--> WATCHDOG
|
||||
AGENT2 <--"POST /api/heartbeat<br/>心跳+TOTP验证"--> WATCHDOG
|
||||
|
||||
style WATCHDOG fill:#4ecdc4
|
||||
style AGENT1 fill:#ff8787
|
||||
style AGENT2 fill:#ff8787
|
||||
style NODE1 fill:#a9e34b
|
||||
style NODE2 fill:#a9e34b
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 二、Agent心跳上报流程
|
||||
|
||||
Agent是嵌入到业务Pod中的启动器,负责向Watchdog发送心跳请求进行授权验证。
|
||||
|
||||
### 2.1 首次连接流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Agent as rmdc-watchdog-agent<br/>(业务启动器)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
|
||||
rect rgb(200, 255, 200)
|
||||
Note over Agent,Watchdog: ===== 首次连接 - 获取TOTP密钥 =====
|
||||
end
|
||||
|
||||
Agent->>Agent: 1. 收集环境信息<br/>GetEnvInfo()
|
||||
Agent->>Agent: 2. 收集主机信息<br/>host_info.GetAllInfo()
|
||||
|
||||
Agent->>Watchdog: 3. POST /api/heartbeat<br/>{HostInfo, EnvInfo, Timestamp, TOTPCode=""}
|
||||
|
||||
Watchdog->>Watchdog: 4. 验证时间戳有效性<br/>|now - timestamp| < 5分钟
|
||||
Watchdog->>Watchdog: 5. 添加主机信息到集合<br/>AddHostInfo()
|
||||
Watchdog->>Watchdog: 6. 检测TOTPCode为空<br/>返回TOTP密钥
|
||||
|
||||
Watchdog-->>Agent: 7. 返回响应<br/>{Authorized:false, SecondTOTPSecret:secret}
|
||||
|
||||
Agent->>Agent: 8. 保存TOTP密钥<br/>tierTwoTotpSecret = secret
|
||||
|
||||
Note over Agent: 密钥保存在内存中<br/>后续心跳使用此密钥
|
||||
```
|
||||
|
||||
### 2.2 后续心跳流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Agent as rmdc-watchdog-agent<br/>(业务启动器)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant Business as 业务进程<br/>(Java/Python)
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over Agent,Business: ===== 心跳循环 - 授权验证 =====
|
||||
end
|
||||
|
||||
loop 心跳循环 (成功后2小时, 失败后1小时)
|
||||
Agent->>Agent: 1. 生成TOTP验证码<br/>GenerateTierTwoTOTPCode(secret)<br/>6位, 30秒有效
|
||||
|
||||
Agent->>Watchdog: 2. POST /api/heartbeat<br/>{HostInfo, EnvInfo, Timestamp, TOTPCode}
|
||||
|
||||
Watchdog->>Watchdog: 3. 验证时间戳有效性
|
||||
Watchdog->>Watchdog: 4. 验证TOTP验证码<br/>VerifyTierTwoTOTPCode()
|
||||
|
||||
alt TOTP验证成功
|
||||
Watchdog->>Watchdog: 5. 检查主机授权状态<br/>IsHostAuthorized(hostInfo)
|
||||
Watchdog->>Watchdog: 6. 生成响应TOTP验证码<br/>(双向验证)
|
||||
Watchdog-->>Agent: 7. 返回{Authorized:true/false, TOTPCode}
|
||||
|
||||
Agent->>Agent: 8. 验证服务端TOTP<br/>双向验证确保安全
|
||||
|
||||
alt 授权成功
|
||||
Agent->>Agent: 9. failCount = 1<br/>等待2小时
|
||||
else 授权失败
|
||||
Agent->>Agent: 9. failCount++<br/>等待1小时
|
||||
end
|
||||
else TOTP验证失败
|
||||
Watchdog-->>Agent: 返回错误:无效的TOTP验证码
|
||||
Agent->>Agent: failCount++
|
||||
end
|
||||
|
||||
alt failCount >= 12
|
||||
Note over Agent,Business: 死手系统触发
|
||||
Agent->>Business: 10. 发送SIGTERM信号
|
||||
Note over Business: 业务进程终止
|
||||
end
|
||||
end
|
||||
```
|
||||
|
||||
### 2.3 心跳请求/响应数据结构
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| **HeartbeatRequest** | | |
|
||||
| host_info | HostInfo | 主机硬件信息 |
|
||||
| env_info | EnvInfo | 环境信息(K8S_NAMESPACE, APPLICATION_NAME等) |
|
||||
| timestamp | int64 | 请求时间戳 |
|
||||
| totp_code | string | TOTP验证码(首次为空) |
|
||||
| **HeartbeatResponse** | | |
|
||||
| authorized | bool | 是否已授权 |
|
||||
| totp_code | string | 响应TOTP验证码(双向验证) |
|
||||
| timestamp | int64 | 响应时间戳 |
|
||||
| second_totp_secret | string | 二级TOTP密钥(首次连接时返回) |
|
||||
|
||||
---
|
||||
|
||||
## 三、Node主机信息上报流程
|
||||
|
||||
Node以DaemonSet方式运行在每个K8S节点上,负责收集主机硬件信息和运行指标。
|
||||
|
||||
### 3.1 Node上报流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Node as rmdc-watchdog-node<br/>(DaemonSet)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over Node,Watchdog: ===== 首次上报 - 获取TOTP密钥 =====
|
||||
end
|
||||
|
||||
Node->>Node: 1. 收集主机硬件信息<br/>CollectHostInfo()
|
||||
Node->>Node: 2. 收集运行指标<br/>CollectMetrics()
|
||||
|
||||
Node->>Watchdog: 3. POST /api/node/info<br/>{NodeID, HostInfo, Metrics, Timestamp, TOTPCode=""}
|
||||
|
||||
Watchdog->>Watchdog: 4. 验证时间戳
|
||||
Watchdog->>Watchdog: 5. 存储Node信息
|
||||
Watchdog->>Watchdog: 6. 同步更新AuthService<br/>AddHostInfo()
|
||||
Watchdog-->>Node: 7. 返回{Success:true, SecondTOTPSecret:secret}
|
||||
|
||||
Node->>Node: 8. 保存TOTP密钥
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over Node,Watchdog: ===== 定时上报 (默认60秒) =====
|
||||
end
|
||||
|
||||
loop 定时上报
|
||||
Node->>Node: 9. 生成TOTP验证码
|
||||
Node->>Node: 10. 收集最新指标
|
||||
|
||||
Node->>Watchdog: 11. POST /api/node/info<br/>{NodeID, HostInfo, Metrics, Timestamp, TOTPCode}
|
||||
|
||||
Watchdog->>Watchdog: 12. 验证TOTP
|
||||
Watchdog->>Watchdog: 13. 更新Node信息
|
||||
Watchdog->>Watchdog: 14. 生成响应TOTP
|
||||
Watchdog-->>Node: 15. 返回{Success:true, TOTPCode}
|
||||
|
||||
Node->>Node: 16. 验证响应TOTP(双向)
|
||||
end
|
||||
```
|
||||
|
||||
### 3.2 Node信息数据结构
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|------|------|------|
|
||||
| **NodeInfoRequest** | | |
|
||||
| node_id | string | 节点唯一标识(MachineID) |
|
||||
| host_info | HostInfo | 主机硬件信息 |
|
||||
| metrics | NodeRuntimeMetrics | 运行指标 |
|
||||
| timestamp | int64 | 请求时间戳 |
|
||||
| totp_code | string | TOTP验证码 |
|
||||
| **NodeRuntimeMetrics** | | |
|
||||
| cpu_usage | float64 | CPU使用率(%) |
|
||||
| memory_usage | float64 | 内存使用率(%) |
|
||||
| disk_usage | float64 | 磁盘使用率(%) |
|
||||
| network_rx_kb | uint64 | 网络接收KB |
|
||||
| network_tx_kb | uint64 | 网络发送KB |
|
||||
| collect_time | int64 | 采集时间戳 |
|
||||
|
||||
---
|
||||
|
||||
## 四、项目级别(二级授权中心)完整业务流程
|
||||
|
||||
### 4.1 完整授权流程
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
participant Node as rmdc-watchdog-node<br/>(DaemonSet)
|
||||
participant Agent as rmdc-watchdog-agent<br/>(业务启动器)
|
||||
participant Watchdog as rmdc-watchdog<br/>(二级授权中心)
|
||||
participant MQTT as Exchange-Hub<br/>(MQTT Server)
|
||||
participant Center as rmdc-watchdog-center<br/>(一级授权中心)
|
||||
|
||||
rect rgb(200, 220, 255)
|
||||
Note over Node,Center: ===== 阶段1: 信息收集与初始化 =====
|
||||
end
|
||||
|
||||
Note over Node: 项目部署后<br/>DaemonSet启动
|
||||
Node->>Watchdog: 1. 上报主机信息<br/>POST /api/node/info
|
||||
Watchdog-->>Node: 2. 返回TOTP密钥
|
||||
|
||||
Note over Agent: 业务Pod启动
|
||||
Agent->>Watchdog: 3. 发送首次心跳<br/>POST /api/heartbeat
|
||||
Watchdog-->>Agent: 4. 返回TOTP密钥
|
||||
|
||||
rect rgb(220, 255, 220)
|
||||
Note over Node,Center: ===== 阶段2: 授权申请 =====
|
||||
end
|
||||
|
||||
Watchdog->>Watchdog: 5. 生成授权文件<br/>GenerateAuthorizationFile()
|
||||
Note over Watchdog: 授权文件包含:<br/>- EncryptedHostMap<br/>- TOTPCode (8位,30分钟)<br/>- EncryptedNamespace
|
||||
|
||||
Watchdog->>MQTT: 6. 发布授权申请Command<br/>wdd/RDMC/command/up
|
||||
MQTT->>Center: 7. 转发授权申请
|
||||
|
||||
rect rgb(255, 240, 220)
|
||||
Note over Node,Center: ===== 阶段3: 授权验证与下发 =====
|
||||
end
|
||||
|
||||
Center->>Center: 8. 解密项目命名空间
|
||||
Center->>Center: 9. 验证Tier-One TOTP验证码
|
||||
Center->>Center: 10. 验证主机信息完整性
|
||||
|
||||
alt 验证成功
|
||||
Center->>Center: 11. 生成新TOTP验证码
|
||||
Center->>Center: 12. 构造授权码
|
||||
Center->>MQTT: 13. 发布授权码<br/>wdd/RDMC/command/down/{project_id}
|
||||
else 验证失败
|
||||
Center->>MQTT: 发布授权拒绝消息
|
||||
end
|
||||
|
||||
MQTT->>Watchdog: 14. 推送授权码
|
||||
|
||||
rect rgb(230, 230, 255)
|
||||
Note over Node,Center: ===== 阶段4: 授权存储与生效 =====
|
||||
end
|
||||
|
||||
Watchdog->>Watchdog: 15. 验证返回的TOTP
|
||||
Watchdog->>Watchdog: 16. 解密并验证命名空间
|
||||
Watchdog->>Watchdog: 17. 解密每个主机信息
|
||||
Watchdog->>Watchdog: 18. 计算时间偏移<br/>timeOffset = now - firstAuthTime
|
||||
Watchdog->>Watchdog: 19. 加密并持久化保存
|
||||
|
||||
rect rgb(200, 255, 200)
|
||||
Note over Node,Center: ===== 阶段5: 授权使用 =====
|
||||
end
|
||||
|
||||
loop Agent心跳循环
|
||||
Agent->>Watchdog: 20. 发送心跳请求
|
||||
Watchdog->>Watchdog: 21. 检查主机授权状态
|
||||
Watchdog-->>Agent: 22. 返回{Authorized:true}
|
||||
end
|
||||
|
||||
Note over Agent: 授权成功<br/>业务正常运行
|
||||
```
|
||||
|
||||
### 4.2 授权状态机
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> 未初始化: 项目部署
|
||||
|
||||
未初始化 --> 收集主机信息: Node/Agent连接
|
||||
收集主机信息 --> 等待授权: 生成授权文件
|
||||
|
||||
等待授权 --> 已授权: 收到有效授权码
|
||||
等待授权 --> 未授权: 授权被拒绝
|
||||
|
||||
已授权 --> 已授权: 心跳成功
|
||||
已授权 --> 授权过期: 时间篡改检测
|
||||
已授权 --> 未授权: 授权撤销
|
||||
|
||||
未授权 --> 等待授权: 重新申请
|
||||
授权过期 --> 未授权: 需重新授权
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 五、API接口清单
|
||||
|
||||
### 5.1 Watchdog API (Port: 8990)
|
||||
|
||||
| 路径 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/heartbeat` | POST | Agent心跳接口 |
|
||||
| `/api/heartbeat/hosts` | GET | 获取所有心跳主机 |
|
||||
| `/api/node/info` | POST | Node信息上报接口 |
|
||||
| `/api/node/list` | GET | 获取所有Node列表 |
|
||||
| `/api/node/metrics/:node_id` | GET | 获取指定Node的运行指标 |
|
||||
| `/api/authorization/generate` | GET | 生成授权文件 |
|
||||
| `/api/authorization/auth` | POST | 接收授权码 |
|
||||
| `/api/authorization/hosts` | GET | 获取所有已授权主机 |
|
||||
|
||||
---
|
||||
|
||||
## 六、安全机制
|
||||
|
||||
### 6.1 TOTP验证机制
|
||||
|
||||
| 场景 | 验证方式 | 参数 |
|
||||
|------|----------|------|
|
||||
| Agent ↔ Watchdog | Tier-Two TOTP | 6位码, 30秒有效, SHA1 |
|
||||
| Node ↔ Watchdog | Tier-Two TOTP | 6位码, 30秒有效, SHA1 |
|
||||
| Watchdog ↔ Center | Tier-One TOTP | 8位码, 30分钟有效, SHA256 |
|
||||
|
||||
### 6.2 双向验证流程
|
||||
|
||||
1. **客户端(Agent/Node)** 生成TOTP验证码并发送请求
|
||||
2. **服务端(Watchdog)** 验证客户端TOTP后,生成新的TOTP验证码返回
|
||||
3. **客户端** 验证服务端返回的TOTP验证码
|
||||
4. 双向验证确保通信双方身份合法
|
||||
|
||||
### 6.3 死手系统
|
||||
|
||||
Agent内置死手系统,当连续12次心跳失败后,将发送SIGTERM信号终止业务进程。
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
|------|------|------|
|
||||
| maxRetryCount | 12 | 最大重试次数 |
|
||||
| defaultHeartbeatInterval | 2小时 | 成功后心跳间隔 |
|
||||
| failWaitInterval | 1小时 | 失败后等待间隔 |
|
||||
468
8-CMII-RMDC/6-rmdc-watchdog/watchdog-prompt.md
Normal file
468
8-CMII-RMDC/6-rmdc-watchdog/watchdog-prompt.md
Normal file
@@ -0,0 +1,468 @@
|
||||
# Watchdog模块开发提示词
|
||||
|
||||
> 本文档为大模型提供rmdc-watchdog模块的开发上下文。
|
||||
|
||||
---
|
||||
|
||||
## 模块概述
|
||||
|
||||
**rmdc-watchdog** 是部署在外部项目环境的边缘代理模块,负责:
|
||||
|
||||
1. **二级授权中心**: 管理项目内业务和主机的授权
|
||||
2. **K8S操作代理**: 执行K8S API操作(CRUD资源、日志获取等)
|
||||
3. **指令接收与执行**: 接收Exchange-Hub下发的指令并执行
|
||||
4. **监控数据上报**: 收集并上报主机/业务运行状态
|
||||
|
||||
---
|
||||
|
||||
## 组件架构
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "rmdc-watchdog 组件"
|
||||
MQTT[MQTT Client]
|
||||
Router[消息路由器]
|
||||
|
||||
subgraph "Handler"
|
||||
AuthH[授权Handler]
|
||||
K8sH[K8S Handler]
|
||||
HostH[主机Handler]
|
||||
LogH[日志Handler]
|
||||
end
|
||||
|
||||
subgraph "Service"
|
||||
AuthS[授权服务]
|
||||
K8sS[K8S服务]
|
||||
NodeS[Node通信服务]
|
||||
end
|
||||
|
||||
K8sClient[K8S Client]
|
||||
NodeClient[Node HTTP Client]
|
||||
end
|
||||
|
||||
subgraph "watchdog-node (DaemonSet)"
|
||||
NodeServer[HTTP Server :8081]
|
||||
NodeInfo[信息采集]
|
||||
NodeExec[命令执行]
|
||||
end
|
||||
|
||||
subgraph "watchdog-agent (业务启动器)"
|
||||
AgentHB[心跳模块]
|
||||
AgentBiz[业务进程管理]
|
||||
end
|
||||
|
||||
MQTT --> Router
|
||||
Router --> AuthH & K8sH & HostH & LogH
|
||||
|
||||
AuthH --> AuthS
|
||||
K8sH --> K8sS --> K8sClient
|
||||
HostH --> NodeS --> NodeClient --> NodeServer
|
||||
|
||||
NodeServer --> NodeInfo & NodeExec
|
||||
|
||||
AgentHB <--> AuthS
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 关联组件说明
|
||||
|
||||
| 组件 | 运行位置 | 职责 |
|
||||
|------|----------|------|
|
||||
| **rmdc-watchdog** | K8S Deployment | 二级授权中心、K8S操作、指令调度 |
|
||||
| **rmdc-watchdog-node** | K8S DaemonSet | 主机信息采集、主机命令执行 |
|
||||
| **rmdc-watchdog-agent** | 业务Pod Sidecar | 业务进程管理、授权心跳、死手系统 |
|
||||
|
||||
---
|
||||
|
||||
## 项目结构
|
||||
|
||||
```
|
||||
rmdc-watchdog/
|
||||
├── cmd/
|
||||
│ └── main.go
|
||||
├── configs/
|
||||
│ └── config.yaml
|
||||
├── internal/
|
||||
│ ├── config/
|
||||
│ │ └── config.go
|
||||
│ ├── dao/
|
||||
│ │ ├── auth_dao.go
|
||||
│ │ └── host_dao.go
|
||||
│ ├── handler/
|
||||
│ │ ├── router.go
|
||||
│ │ ├── auth_handler.go
|
||||
│ │ ├── heartbeat_handler.go
|
||||
│ │ ├── k8s_handler.go
|
||||
│ │ └── node_handler.go
|
||||
│ ├── model/
|
||||
│ │ ├── dto/
|
||||
│ │ │ └── watchdog_dto.go
|
||||
│ │ └── entity/
|
||||
│ │ └── auth_info.go
|
||||
│ └── service/
|
||||
│ ├── mqtt_service.go
|
||||
│ ├── auth_service.go
|
||||
│ ├── k8s_service.go
|
||||
│ ├── node_service.go
|
||||
│ └── message_router.go
|
||||
└── pkg/
|
||||
├── k8s/
|
||||
│ └── client.go # K8S API封装
|
||||
└── totp/
|
||||
└── totp.go # TOTP工具
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 核心数据结构
|
||||
|
||||
### 心跳请求/响应
|
||||
|
||||
```go
|
||||
// HeartbeatRequest Agent心跳请求
|
||||
type HeartbeatRequest struct {
|
||||
HostInfo common.HostInfo `json:"host_info"`
|
||||
EnvInfo common.EnvInfo `json:"env_info"`
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
TOTPCode string `json:"totp_code"`
|
||||
}
|
||||
|
||||
// HeartbeatResponse 心跳响应
|
||||
type HeartbeatResponse struct {
|
||||
Authorized bool `json:"authorized"`
|
||||
TOTPCode string `json:"totp_code"` // 服务端TOTP(双向验证)
|
||||
Timestamp int64 `json:"timestamp"`
|
||||
SecondTOTPSecret string `json:"second_totp_secret,omitempty"` // 首次连接返回
|
||||
}
|
||||
```
|
||||
|
||||
### K8S执行指令
|
||||
|
||||
```go
|
||||
// K8sExecCommand K8S执行指令
|
||||
type K8sExecCommand struct {
|
||||
CommandID string `json:"command_id"`
|
||||
Namespace string `json:"namespace"`
|
||||
Resource string `json:"resource"` // deployment, pod, statefulset...
|
||||
Name string `json:"name"`
|
||||
Action string `json:"action"` // logs, exec, scale, restart, delete, get, apply
|
||||
Container string `json:"container,omitempty"`
|
||||
Command []string `json:"command,omitempty"`
|
||||
Timeout int `json:"timeout"`
|
||||
TailLines int `json:"tail_lines,omitempty"`
|
||||
FollowLogs bool `json:"follow_logs,omitempty"`
|
||||
}
|
||||
|
||||
// ExecResult 执行结果
|
||||
type ExecResult struct {
|
||||
CommandID string `json:"command_id"`
|
||||
Status string `json:"status"` // success, failure, timeout
|
||||
ExitCode int `json:"exit_code"`
|
||||
Output string `json:"output"`
|
||||
Error string `json:"error"`
|
||||
StartTime int64 `json:"start_time"`
|
||||
EndTime int64 `json:"end_time"`
|
||||
Duration int64 `json:"duration"`
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## TOTP双层授权机制
|
||||
|
||||
### 层级说明
|
||||
|
||||
```
|
||||
一级授权(Tier-One): project-management ↔ watchdog
|
||||
- 8位验证码
|
||||
- 30分钟有效期
|
||||
- SHA256算法
|
||||
|
||||
二级授权(Tier-Two): watchdog ↔ agent/node
|
||||
- 6位验证码
|
||||
- 30秒有效期
|
||||
- SHA1算法
|
||||
```
|
||||
|
||||
### 授权流程
|
||||
|
||||
```go
|
||||
// 验证Agent心跳
|
||||
func (s *AuthService) VerifyHeartbeat(req *HeartbeatRequest) (*HeartbeatResponse, error) {
|
||||
// 1. 验证时间戳
|
||||
if abs(time.Now().Unix() - req.Timestamp/1000) > 300 {
|
||||
return nil, errors.New("timestamp expired")
|
||||
}
|
||||
|
||||
// 2. 首次连接(无TOTP码)
|
||||
if req.TOTPCode == "" {
|
||||
s.addHost(req.HostInfo)
|
||||
return &HeartbeatResponse{
|
||||
Authorized: false,
|
||||
SecondTOTPSecret: s.tierTwoSecret,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
|
||||
// 3. 验证TOTP
|
||||
if !s.verifyTierTwoTOTP(req.TOTPCode) {
|
||||
return nil, errors.New("invalid totp code")
|
||||
}
|
||||
|
||||
// 4. 检查主机授权状态
|
||||
authorized := s.isHostAuthorized(req.HostInfo)
|
||||
|
||||
// 5. 生成响应TOTP(双向验证)
|
||||
responseTOTP := s.generateTierTwoTOTP()
|
||||
|
||||
return &HeartbeatResponse{
|
||||
Authorized: authorized,
|
||||
TOTPCode: responseTOTP,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
}, nil
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## K8S操作封装
|
||||
|
||||
### 支持的操作
|
||||
|
||||
| Action | 说明 | 目标资源 |
|
||||
|--------|------|----------|
|
||||
| `logs` | 获取日志 | Pod |
|
||||
| `exec` | 执行命令 | Pod |
|
||||
| `scale` | 扩缩容 | Deployment/StatefulSet |
|
||||
| `restart` | 滚动重启 | Deployment/StatefulSet |
|
||||
| `delete` | 删除资源 | 任意资源 |
|
||||
| `get` | 获取信息 | 任意资源 |
|
||||
| `apply` | 应用YAML | 任意资源 |
|
||||
|
||||
### K8S客户端使用
|
||||
|
||||
```go
|
||||
func (s *K8sService) ExecuteCommand(cmd *K8sExecCommand) (*ExecResult, error) {
|
||||
startTime := time.Now()
|
||||
result := &ExecResult{
|
||||
CommandID: cmd.CommandID,
|
||||
StartTime: startTime.UnixMilli(),
|
||||
}
|
||||
|
||||
var output string
|
||||
var err error
|
||||
|
||||
switch cmd.Action {
|
||||
case "logs":
|
||||
output, err = s.k8sClient.GetPodLogs(cmd.Namespace, cmd.Name, cmd.Container, cmd.TailLines)
|
||||
case "exec":
|
||||
output, err = s.k8sClient.ExecCommand(cmd.Namespace, cmd.Name, cmd.Container, cmd.Command)
|
||||
case "scale":
|
||||
output, err = s.k8sClient.Scale(cmd.Namespace, cmd.Resource, cmd.Name, cmd.Scale)
|
||||
case "restart":
|
||||
output, err = s.k8sClient.RolloutRestart(cmd.Namespace, cmd.Resource, cmd.Name)
|
||||
case "delete":
|
||||
output, err = s.k8sClient.Delete(cmd.Namespace, cmd.Resource, cmd.Name)
|
||||
}
|
||||
|
||||
result.EndTime = time.Now().UnixMilli()
|
||||
result.Duration = result.EndTime - result.StartTime
|
||||
|
||||
if err != nil {
|
||||
result.Status = "failure"
|
||||
result.Error = err.Error()
|
||||
} else {
|
||||
result.Status = "success"
|
||||
result.Output = output
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Node通信
|
||||
|
||||
### Node HTTP接口
|
||||
|
||||
| 接口 | 方法 | 说明 |
|
||||
|------|------|------|
|
||||
| `/api/exec` | POST | 执行命令 |
|
||||
| `/api/info` | GET | 获取主机信息 |
|
||||
| `/api/metrics` | GET | 获取运行指标 |
|
||||
| `/api/dltu` | POST | 镜像操作(Download-Load-Tag-Upload) |
|
||||
|
||||
### 与Node通信
|
||||
|
||||
```go
|
||||
func (s *NodeService) ExecuteOnNode(nodeID string, script string, args []string) (*ExecResult, error) {
|
||||
// 1. 获取Node地址
|
||||
node := s.getNode(nodeID)
|
||||
if node == nil {
|
||||
return nil, errors.New("node not found")
|
||||
}
|
||||
|
||||
// 2. 生成TOTP
|
||||
totp := s.generateTierTwoTOTP()
|
||||
|
||||
// 3. 发送请求
|
||||
req := &NodeExecRequest{
|
||||
Script: script,
|
||||
Args: args,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
TOTPCode: totp,
|
||||
}
|
||||
|
||||
resp, err := s.httpClient.Post(fmt.Sprintf("http://%s:8081/api/exec", node.IP), req)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// 4. 验证响应TOTP
|
||||
if !s.verifyTierTwoTOTP(resp.TOTPCode) {
|
||||
return nil, errors.New("invalid response totp")
|
||||
}
|
||||
|
||||
return resp.Result, nil
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 死手系统
|
||||
|
||||
Agent内置死手系统,保护业务授权安全:
|
||||
|
||||
| 参数 | 值 | 说明 |
|
||||
|------|------|------|
|
||||
| `maxRetryCount` | 12 | 最大失败次数 |
|
||||
| `successInterval` | 2小时 | 成功后心跳间隔 |
|
||||
| `failInterval` | 1小时 | 失败后心跳间隔 |
|
||||
|
||||
```go
|
||||
// Agent心跳循环
|
||||
func (a *Agent) heartbeatLoop() {
|
||||
failCount := 0
|
||||
|
||||
for {
|
||||
resp, err := a.sendHeartbeat()
|
||||
|
||||
if err != nil || !resp.Authorized {
|
||||
failCount++
|
||||
|
||||
if failCount >= 12 {
|
||||
// 触发死手系统
|
||||
a.killBusiness()
|
||||
return
|
||||
}
|
||||
|
||||
time.Sleep(1 * time.Hour)
|
||||
} else {
|
||||
failCount = 1
|
||||
time.Sleep(2 * time.Hour)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (a *Agent) killBusiness() {
|
||||
// 发送SIGTERM信号终止业务进程
|
||||
a.businessProcess.Signal(syscall.SIGTERM)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## MQTT订阅与发布
|
||||
|
||||
### 启动时订阅
|
||||
|
||||
```go
|
||||
func (s *MQTTService) Start() {
|
||||
// 订阅下行Topic
|
||||
s.client.Subscribe(fmt.Sprintf("wdd/RDMC/command/down/%s", s.projectID), s.onCommand)
|
||||
s.client.Subscribe(fmt.Sprintf("wdd/RDMC/message/down/%s", s.projectID), s.onMessage)
|
||||
}
|
||||
```
|
||||
|
||||
### 发布上行消息
|
||||
|
||||
```go
|
||||
func (s *MQTTService) PublishResult(result *ExecResult) error {
|
||||
msg := &common.DataMessage{
|
||||
BaseMessage: common.BaseMessage{
|
||||
MessageID: uuid.New().String(),
|
||||
Type: "message",
|
||||
ProjectID: s.projectID,
|
||||
Timestamp: time.Now().UnixMilli(),
|
||||
},
|
||||
DataType: "exec_result",
|
||||
Payload: result,
|
||||
}
|
||||
|
||||
return s.client.Publish("wdd/RDMC/message/up", msg)
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 配置项
|
||||
|
||||
```yaml
|
||||
# configs/config.yaml
|
||||
server:
|
||||
host: 0.0.0.0
|
||||
port: 8990
|
||||
|
||||
mqtt:
|
||||
broker: tcp://mqtt-broker:1883
|
||||
client_id: watchdog-${PROJECT_ID}
|
||||
username: ${MQTT_USERNAME}
|
||||
password: ${MQTT_PASSWORD}
|
||||
|
||||
project:
|
||||
id: ${PROJECT_ID}
|
||||
namespace: ${NAMESPACE}
|
||||
|
||||
auth:
|
||||
tier_one_secret: ${TIER_ONE_SECRET}
|
||||
tier_two_secret: ${TIER_TWO_SECRET}
|
||||
time_offset_allowed: 300
|
||||
totp_verification_enabled: true
|
||||
|
||||
k8s:
|
||||
kubeconfig_path: "" # 空则使用InCluster配置
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见开发任务
|
||||
|
||||
### 1. 添加新的K8S操作
|
||||
|
||||
1. 在`pkg/k8s/client.go`添加K8S API调用方法
|
||||
2. 在`internal/service/k8s_service.go`的switch中添加case
|
||||
3. 更新`K8sExecCommand`结构(如需新参数)
|
||||
|
||||
### 2. 添加新的指令类型
|
||||
|
||||
1. 在`message_router.go`添加路由分支
|
||||
2. 创建对应的Handler和Service
|
||||
3. 同步更新Exchange-Hub端的指令下发
|
||||
|
||||
### 3. 修改心跳逻辑
|
||||
|
||||
1. 修改`auth_service.go`的`VerifyHeartbeat`方法
|
||||
2. 同步修改Agent端的心跳发送逻辑
|
||||
3. 如需新增字段,更新DTO结构
|
||||
|
||||
---
|
||||
|
||||
## 相关文档
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| `1-rmdc-watchdog-DDS.md` | 详细设计 |
|
||||
| `2-rmdc-watchdog-业务流程图.md` | 业务流程图 |
|
||||
| `3-rmdc-watchdog-内部交互流程.md` | 内部交互流程 |
|
||||
771
8-CMII-RMDC/7-rmdc-work-procedure/1-rmdc-work-procedure-DDS.md
Normal file
771
8-CMII-RMDC/7-rmdc-work-procedure/1-rmdc-work-procedure-DDS.md
Normal file
@@ -0,0 +1,771 @@
|
||||
# 工单流程模块 DDS (详细设计说明书)
|
||||
|
||||
**产品名称**: RMDC 工单流程模块 (rmdc-work-procedure)
|
||||
**版本**: v2.0
|
||||
**编制日期**: 2026-01-08
|
||||
|
||||
---
|
||||
|
||||
## 1. 概述
|
||||
|
||||
### 1.1 模块定位
|
||||
|
||||
工单流程模块是RMDC系统的核心基础设施模块,为其他业务模块提供统一的工单创建、流转、追踪能力。
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph "业务模块"
|
||||
UA[rmdc-user-auth<br/>用户认证模块]
|
||||
PM[rmdc-project-management<br/>项目管理模块]
|
||||
DU[deliver-update<br/>微服务更新模块]
|
||||
end
|
||||
|
||||
subgraph "工单模块"
|
||||
WP[rmdc-work-procedure<br/>工单流程模块]
|
||||
end
|
||||
|
||||
subgraph "基础设施"
|
||||
NC[rmdc-notice-center<br/>通知中心模块]
|
||||
end
|
||||
|
||||
UA --> WP
|
||||
PM --> WP
|
||||
DU --> WP
|
||||
WP --> NC
|
||||
```
|
||||
|
||||
### 1.2 工单类型
|
||||
|
||||
| 工单类型代码 | 类型名称 | 来源模块 | 流程详情 |
|
||||
|-------------|---------|---------|---------|
|
||||
| `user_registration` | 用户注册工单 | rmdc-user-auth | [用户注册工单流程](diagrams/user-registration-workflow.md) |
|
||||
| `user_management` | 用户管理工单 | rmdc-user-auth | [用户管理工单流程](diagrams/user-management-workflow.md) |
|
||||
| `project_detail` | 项目信息填写工单 | rmdc-project-management | [项目信息填写工单流程](diagrams/project-detail-workflow.md) |
|
||||
| `microservice_update` | 微服务更新工单 | deliver-update | [微服务更新工单流程](diagrams/microservice-update-workflow.md) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 状态机设计
|
||||
|
||||
### 2.1 设计原则
|
||||
|
||||
采用 **"通用状态机 + 类型特化配置"** 的混合方案:
|
||||
- **基础状态层**:所有工单类型共享的10个核心状态
|
||||
- **扩展状态层**:按工单类型配置的特殊状态
|
||||
|
||||
### 2.2 基础状态定义
|
||||
|
||||
| 状态代码 | 状态名称 | 说明 | 是否终态 |
|
||||
|---------|---------|------|---------|
|
||||
| `created` | 已创建 | 工单刚创建,等待分配或自动分配 | 否 |
|
||||
| `pending` | 待分配 | 等待管理员手动分配处理人 | 否 |
|
||||
| `assigned` | 已分配 | 已分配处理人,等待接单 | 否 |
|
||||
| `in_progress` | 处理中 | 处理人正在业务模块中处理 | 否 |
|
||||
| `pending_review` | 待审核 | 处理完成,等待审核 | 否 |
|
||||
| `returned` | 已打回 | 审核未通过,需重新处理 | 否 |
|
||||
| `approved` | 已通过 | 审核通过 | 是 |
|
||||
| `rejected` | 已拒绝 | 审核拒绝,流程终止 | 是 |
|
||||
| `revoked` | 已撤销 | 发起人撤销 | 是 |
|
||||
| `closed` | 已关闭 | 流程完结 | 是 |
|
||||
|
||||
### 2.3 扩展状态定义
|
||||
|
||||
| 工单类型 | 扩展状态 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `microservice_update` | `executing` | 微服务更新执行中 |
|
||||
| `microservice_update` | `monitoring` | 微服务运行状态监控中 |
|
||||
| `microservice_update` | `rollbacked` | 更新失败已回滚 |
|
||||
| `project_detail` | `draft_saved` | 草稿已保存 |
|
||||
|
||||
### 2.4 通用状态转换图
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> created: 工单创建
|
||||
|
||||
created --> pending: submit
|
||||
created --> assigned: auto_assign
|
||||
|
||||
pending --> assigned: assign
|
||||
|
||||
assigned --> in_progress: accept
|
||||
assigned --> assigned: reassign
|
||||
|
||||
in_progress --> pending_review: complete
|
||||
in_progress --> returned: return
|
||||
in_progress --> assigned: reassign
|
||||
|
||||
pending_review --> approved: approve
|
||||
pending_review --> rejected: reject
|
||||
pending_review --> returned: return
|
||||
|
||||
returned --> in_progress: resubmit
|
||||
|
||||
approved --> closed: close
|
||||
rejected --> closed: close
|
||||
|
||||
created --> revoked: revoke
|
||||
pending --> revoked: revoke
|
||||
assigned --> revoked: revoke
|
||||
in_progress --> revoked: revoke(需确认)
|
||||
pending_review --> revoked: revoke(需确认)
|
||||
returned --> revoked: revoke
|
||||
|
||||
revoked --> closed: close
|
||||
|
||||
closed --> [*]
|
||||
```
|
||||
|
||||
### 2.5 状态转换权限矩阵
|
||||
|
||||
| 转换事件 | 触发角色 | 前置条件 |
|
||||
|---------|---------|---------|
|
||||
| `submit` | 创建人 | 状态为 `created` |
|
||||
| `auto_assign` | 系统 | 配置了自动分配规则 |
|
||||
| `assign` | SuperAdmin | 状态为 `pending` |
|
||||
| `accept` | 处理人 | 状态为 `assigned` |
|
||||
| `reassign` | SuperAdmin | 状态为 `assigned`/`in_progress` |
|
||||
| `complete` | 处理人 | 状态为 `in_progress` |
|
||||
| `approve` | SuperAdmin | 状态为 `pending_review` |
|
||||
| `reject` | SuperAdmin | 状态为 `pending_review` |
|
||||
| `return` | SuperAdmin | 状态为 `pending_review`/`in_progress` |
|
||||
| `resubmit` | 创建人/处理人 | 状态为 `returned` |
|
||||
| `revoke` | 创建人 | 状态非终态 |
|
||||
| `close` | 系统/SuperAdmin | 状态为终态或 `revoked` |
|
||||
|
||||
---
|
||||
|
||||
## 3. 数据模型设计
|
||||
|
||||
### 3.1 设计原则
|
||||
|
||||
采用 **"主表统一 + 业务扩展表分离"** 的设计:
|
||||
- **主表**:存储所有工单类型的通用字段
|
||||
- **扩展表**:按工单类型存储特定业务数据
|
||||
|
||||
### 3.2 ER图
|
||||
|
||||
```mermaid
|
||||
erDiagram
|
||||
workflows ||--o{ workflow_steps : contains
|
||||
workflows ||--o{ workflow_track_history : has
|
||||
workflows ||--o| user_registration_ext : extends
|
||||
workflows ||--o| user_management_ext : extends
|
||||
workflows ||--o| project_detail_ext : extends
|
||||
workflows ||--o| microservice_update_ext : extends
|
||||
|
||||
workflows {
|
||||
varchar(64) id PK "工单唯一ID"
|
||||
int version "乐观锁版本号"
|
||||
varchar(32) module_code "来源模块"
|
||||
varchar(32) workflow_type "工单类型"
|
||||
int priority "优先级1-5"
|
||||
varchar(32) status "当前状态"
|
||||
int current_step "当前步骤序号"
|
||||
int total_steps "总步骤数"
|
||||
bigint creator_id FK "发起人ID"
|
||||
varchar(64) creator_name "发起人姓名"
|
||||
bigint assignee_id FK "当前处理人ID"
|
||||
varchar(64) assignee_name "处理人姓名"
|
||||
bigint delegated_by "委派来源"
|
||||
datetime deadline "超时时间"
|
||||
datetime started_at "开始处理时间"
|
||||
datetime completed_at "完成时间"
|
||||
varchar(256) title "工单标题"
|
||||
text description "工单描述"
|
||||
json business_payload "业务模块通用数据"
|
||||
json result_payload "处理结果数据"
|
||||
datetime created_at
|
||||
datetime updated_at
|
||||
}
|
||||
|
||||
workflow_steps {
|
||||
bigint id PK
|
||||
varchar(64) workflow_id FK
|
||||
int step_order "步骤顺序"
|
||||
varchar(64) step_name "步骤名称"
|
||||
varchar(32) step_type "步骤类型"
|
||||
bigint assignee_id FK
|
||||
varchar(64) assignee_name
|
||||
varchar(32) status "步骤状态"
|
||||
varchar(32) result "步骤结果"
|
||||
text remark "处理备注"
|
||||
json input_data "步骤输入"
|
||||
json output_data "步骤输出"
|
||||
datetime started_at
|
||||
datetime completed_at
|
||||
datetime created_at
|
||||
}
|
||||
|
||||
workflow_track_history {
|
||||
bigint id PK
|
||||
varchar(64) workflow_id FK
|
||||
varchar(32) from_status
|
||||
varchar(32) to_status
|
||||
varchar(32) event "触发事件"
|
||||
bigint operator_id
|
||||
varchar(16) operator_type "user/system/timer"
|
||||
varchar(45) operator_ip
|
||||
json change_details "变更详情"
|
||||
text remark
|
||||
datetime created_at
|
||||
}
|
||||
```
|
||||
|
||||
### 3.3 主表DDL (workflows)
|
||||
|
||||
```sql
|
||||
CREATE TABLE workflows (
|
||||
id VARCHAR(64) PRIMARY KEY,
|
||||
version INT NOT NULL DEFAULT 1,
|
||||
|
||||
-- 工单类型与来源
|
||||
module_code VARCHAR(32) NOT NULL,
|
||||
workflow_type VARCHAR(32) NOT NULL,
|
||||
priority INT DEFAULT 3,
|
||||
|
||||
-- 状态与流程
|
||||
status VARCHAR(32) NOT NULL,
|
||||
current_step INT DEFAULT 1,
|
||||
total_steps INT DEFAULT 1,
|
||||
|
||||
-- 人员关联
|
||||
creator_id BIGINT NOT NULL,
|
||||
creator_name VARCHAR(64),
|
||||
assignee_id BIGINT,
|
||||
assignee_name VARCHAR(64),
|
||||
delegated_by BIGINT,
|
||||
|
||||
-- 时间管理
|
||||
deadline DATETIME,
|
||||
started_at DATETIME,
|
||||
completed_at DATETIME,
|
||||
|
||||
-- 业务数据
|
||||
title VARCHAR(256),
|
||||
description TEXT,
|
||||
business_payload JSON,
|
||||
result_payload JSON,
|
||||
|
||||
-- 审计
|
||||
created_at DATETIME NOT NULL,
|
||||
updated_at DATETIME NOT NULL,
|
||||
|
||||
INDEX idx_module_code (module_code),
|
||||
INDEX idx_workflow_type (workflow_type),
|
||||
INDEX idx_status (status),
|
||||
INDEX idx_creator (creator_id),
|
||||
INDEX idx_assignee (assignee_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 3.4 步骤表DDL (workflow_steps)
|
||||
|
||||
```sql
|
||||
CREATE TABLE workflow_steps (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
workflow_id VARCHAR(64) NOT NULL,
|
||||
step_order INT NOT NULL,
|
||||
step_name VARCHAR(64),
|
||||
step_type VARCHAR(32),
|
||||
|
||||
-- 处理信息
|
||||
assignee_id BIGINT,
|
||||
assignee_name VARCHAR(64),
|
||||
status VARCHAR(32),
|
||||
result VARCHAR(32),
|
||||
remark TEXT,
|
||||
input_data JSON,
|
||||
output_data JSON,
|
||||
|
||||
-- 时间
|
||||
started_at DATETIME,
|
||||
completed_at DATETIME,
|
||||
created_at DATETIME NOT NULL,
|
||||
|
||||
INDEX idx_workflow (workflow_id),
|
||||
FOREIGN KEY (workflow_id) REFERENCES workflows(id)
|
||||
);
|
||||
```
|
||||
|
||||
### 3.5 追踪历史表DDL (workflow_track_history)
|
||||
|
||||
```sql
|
||||
CREATE TABLE workflow_track_history (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
workflow_id VARCHAR(64) NOT NULL,
|
||||
|
||||
-- 状态变更
|
||||
from_status VARCHAR(32),
|
||||
to_status VARCHAR(32),
|
||||
event VARCHAR(32),
|
||||
|
||||
-- 操作信息
|
||||
operator_id BIGINT,
|
||||
operator_type VARCHAR(16),
|
||||
operator_ip VARCHAR(45),
|
||||
|
||||
-- 变更详情
|
||||
change_details JSON,
|
||||
remark TEXT,
|
||||
|
||||
created_at DATETIME NOT NULL,
|
||||
|
||||
INDEX idx_workflow (workflow_id),
|
||||
INDEX idx_operator (operator_id)
|
||||
);
|
||||
```
|
||||
|
||||
### 3.6 业务扩展表DDL
|
||||
|
||||
#### 用户注册扩展表
|
||||
|
||||
```sql
|
||||
CREATE TABLE user_registration_ext (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
workflow_id VARCHAR(64) NOT NULL UNIQUE,
|
||||
target_user_id BIGINT NOT NULL,
|
||||
original_status VARCHAR(32),
|
||||
|
||||
FOREIGN KEY (workflow_id) REFERENCES workflows(id)
|
||||
);
|
||||
```
|
||||
|
||||
#### 用户管理扩展表
|
||||
|
||||
```sql
|
||||
CREATE TABLE user_management_ext (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
workflow_id VARCHAR(64) NOT NULL UNIQUE,
|
||||
target_user_id BIGINT NOT NULL,
|
||||
action_type VARCHAR(32) NOT NULL,
|
||||
original_data JSON,
|
||||
modified_data JSON,
|
||||
|
||||
FOREIGN KEY (workflow_id) REFERENCES workflows(id)
|
||||
);
|
||||
```
|
||||
|
||||
#### 项目详情扩展表
|
||||
|
||||
```sql
|
||||
CREATE TABLE project_detail_ext (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
workflow_id VARCHAR(64) NOT NULL UNIQUE,
|
||||
project_id VARCHAR(64) NOT NULL,
|
||||
detail_filler_id BIGINT,
|
||||
detail_filler_name VARCHAR(64),
|
||||
draft_data JSON,
|
||||
|
||||
FOREIGN KEY (workflow_id) REFERENCES workflows(id)
|
||||
);
|
||||
```
|
||||
|
||||
#### 微服务更新扩展表
|
||||
|
||||
```sql
|
||||
CREATE TABLE microservice_update_ext (
|
||||
id BIGINT AUTO_INCREMENT PRIMARY KEY,
|
||||
workflow_id VARCHAR(64) NOT NULL UNIQUE,
|
||||
project_id VARCHAR(64) NOT NULL,
|
||||
namespace VARCHAR(64) NOT NULL,
|
||||
service_name VARCHAR(128) NOT NULL,
|
||||
build_id VARCHAR(128),
|
||||
current_version VARCHAR(64),
|
||||
target_version VARCHAR(64),
|
||||
scheduled_at DATETIME,
|
||||
execute_result VARCHAR(32),
|
||||
rollback_info JSON,
|
||||
|
||||
FOREIGN KEY (workflow_id) REFERENCES workflows(id)
|
||||
);
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. API接口设计
|
||||
|
||||
### 4.1 工单核心接口
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|-----|------|------|
|
||||
| POST | `/api/workflow/create` | 创建工单 |
|
||||
| POST | `/api/workflow/detail` | 获取工单详情 |
|
||||
| POST | `/api/workflow/status` | 获取工单状态(轻量) |
|
||||
| POST | `/api/workflow/update` | 更新工单(需版本号) |
|
||||
| POST | `/api/workflow/transition` | 状态转换 |
|
||||
| POST | `/api/workflow/assign` | 分配处理人 |
|
||||
| POST | `/api/workflow/delegate` | 委派给他人 |
|
||||
| POST | `/api/workflow/revoke` | 撤销工单 |
|
||||
| POST | `/api/workflow/callback` | 业务模块回调 |
|
||||
|
||||
### 4.2 工单列表与查询
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|-----|------|------|
|
||||
| POST | `/api/workflow/list` | 工单列表(分页) |
|
||||
| POST | `/api/workflow/my/created` | 我发起的工单 |
|
||||
| POST | `/api/workflow/my/assigned` | 分配给我的工单 |
|
||||
| POST | `/api/workflow/my/pending` | 待我处理的工单 |
|
||||
| POST | `/api/workflow/history` | 工单历史记录 |
|
||||
| POST | `/api/workflow/diagram` | 工单流程图(mermaid格式) |
|
||||
|
||||
### 4.3 权限管理接口 (仅SuperAdmin)
|
||||
|
||||
| 方法 | 路径 | 说明 |
|
||||
|-----|------|------|
|
||||
| POST | `/api/workflow/permission/grant` | 授予权限 |
|
||||
| POST | `/api/workflow/permission/revoke` | 撤销权限 |
|
||||
| POST | `/api/workflow/permission/list` | 权限列表 |
|
||||
|
||||
---
|
||||
|
||||
## 5. 并发处理机制
|
||||
|
||||
### 5.1 乐观锁实现
|
||||
|
||||
```go
|
||||
// 更新工单时必须校验版本号
|
||||
func (s *WorkflowService) UpdateWorkflow(ctx context.Context, req *UpdateRequest) error {
|
||||
result := s.db.Model(&Workflow{}).
|
||||
Where("id = ? AND version = ?", req.ID, req.Version).
|
||||
Updates(map[string]interface{}{
|
||||
"status": req.Status,
|
||||
"version": gorm.Expr("version + 1"),
|
||||
})
|
||||
|
||||
if result.RowsAffected == 0 {
|
||||
return ErrVersionConflict // 409 Conflict
|
||||
}
|
||||
return nil
|
||||
}
|
||||
```
|
||||
|
||||
### 5.2 并发事件处理
|
||||
|
||||
| 场景 | 处理策略 |
|
||||
|-----|---------|
|
||||
| 工单被委派 | 推送 `WORKFLOW_REASSIGNED` 事件,原处理人页面切换只读模式 |
|
||||
| 工单被撤销 | 推送 `WORKFLOW_REVOKED` 事件,处理人页面自动关闭 |
|
||||
| 工单被修改 | 推送 `WORKFLOW_MODIFIED` 事件,前端提示刷新或自动刷新 |
|
||||
|
||||
---
|
||||
|
||||
## 6. WebSocket事件
|
||||
|
||||
| 事件类型 | 触发时机 | 接收方 |
|
||||
|---------|---------|-------|
|
||||
| `WORKFLOW_CREATED` | 工单创建 | 处理人 |
|
||||
| `WORKFLOW_ASSIGNED` | 工单分配 | 处理人 |
|
||||
| `WORKFLOW_REASSIGNED` | 工单重新委派 | 原处理人、新处理人 |
|
||||
| `WORKFLOW_STATUS_CHANGED` | 状态变更 | 发起人、处理人 |
|
||||
| `WORKFLOW_REVOKED` | 工单撤销 | 处理人 |
|
||||
| `WORKFLOW_MODIFIED` | 工单内容修改 | 处理人 |
|
||||
| `WORKFLOW_TIMEOUT` | 工单超时 | 发起人、处理人 |
|
||||
| `WORKFLOW_COMPLETED` | 工单完成 | 发起人 |
|
||||
|
||||
---
|
||||
|
||||
## 7. 流程图动态生成模块
|
||||
|
||||
### 7.1 模块概述
|
||||
|
||||
流程图动态生成模块负责根据工单状态动态生成Mermaid源码,由后端返回给前端,前端使用Mermaid库完成渲染。
|
||||
|
||||
### 7.2 架构设计
|
||||
|
||||
```mermaid
|
||||
graph TB
|
||||
subgraph 后端 rmdc_work_procedure
|
||||
WS[WorkflowService] --> MG[MermaidGenerator]
|
||||
MG --> MT[Templates]
|
||||
MT --> T1[UserRegistrationTemplate]
|
||||
MT --> T2[UserManagementTemplate]
|
||||
MT --> T3[ProjectDetailTemplate]
|
||||
MT --> T4[DefaultTemplate]
|
||||
end
|
||||
|
||||
subgraph API层
|
||||
H[WorkflowHandler] --> WS
|
||||
end
|
||||
|
||||
subgraph 前端
|
||||
FE[WorkflowDetail.vue] -->|POST /workflow/diagram| H
|
||||
FE --> DM[动态 import mermaid]
|
||||
FE --> VM[VueMermaid<br/>@mermaid-js/mermaid-tiny]
|
||||
DM -. 初始化 .-> VM
|
||||
end
|
||||
|
||||
classDef async stroke:#ff9800,stroke-width:2px,stroke-dasharray: 4 2
|
||||
class DM async
|
||||
|
||||
```
|
||||
|
||||
### 7.3 文件结构
|
||||
|
||||
```
|
||||
rmdc-work-procedure/
|
||||
├── pkg/
|
||||
│ └── mermaid/
|
||||
│ ├── types.go # 数据类型定义
|
||||
│ ├── generator.go # 核心生成器逻辑:仅生成Mermaid源码
|
||||
│ └── templates.go # 工单类型模板
|
||||
└── internal/
|
||||
└── service/
|
||||
└── mermaid_generator.go # Service层封装
|
||||
```
|
||||
|
||||
### 7.4 核心数据结构
|
||||
|
||||
```go
|
||||
// DiagramResponse 流程图响应
|
||||
type DiagramResponse struct {
|
||||
MermaidCode string `json:"mermaid_code"` // Mermaid源代码
|
||||
CurrentNode string `json:"current_node"` // 当前高亮节点ID
|
||||
Nodes []DiagramNode `json:"nodes"` // 节点详细信息
|
||||
}
|
||||
|
||||
// DiagramNode 节点信息
|
||||
type DiagramNode struct {
|
||||
ID string `json:"id"` // 节点ID
|
||||
Label string `json:"label"` // 显示文本
|
||||
Status string `json:"status"` // completed/current/pending/error
|
||||
Assignee string `json:"assignee"` // 处理人
|
||||
CompletedAt string `json:"completed_at"` // 完成时间
|
||||
}
|
||||
```
|
||||
|
||||
### 7.5 支持的工单模板
|
||||
|
||||
| 工单类型 | 模板类 | 说明 |
|
||||
|---------|--------|------|
|
||||
| `user_registration` | UserRegistrationTemplate | 用户注册流程图 |
|
||||
| `user_management` | UserManagementTemplate | 用户管理流程图 |
|
||||
| `project_detail` | ProjectDetailTemplate | 项目详情填写流程图 |
|
||||
| 其他 | DefaultTemplate | 通用默认流程图 |
|
||||
|
||||
### 7.6 API接口详细
|
||||
|
||||
**请求**: `POST /api/workflow/diagram`
|
||||
|
||||
```json
|
||||
{
|
||||
"workflow_id": "project-20260108100000-admin"
|
||||
}
|
||||
```
|
||||
|
||||
**响应**:
|
||||
|
||||
```json
|
||||
{
|
||||
"code": 0,
|
||||
"message": "success",
|
||||
"data": {
|
||||
"mermaid_code": "stateDiagram-v2\n direction LR\n ...",
|
||||
"current_node": "pending_review",
|
||||
"nodes": [
|
||||
{
|
||||
"id": "created",
|
||||
"label": "创建项目",
|
||||
"status": "completed",
|
||||
"assignee": "超级管理员"
|
||||
},
|
||||
{
|
||||
"id": "in_progress",
|
||||
"label": "填写信息",
|
||||
"status": "current",
|
||||
"assignee": "张三"
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
### 7.7 项目详情工单流程图示例
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
direction LR
|
||||
|
||||
[*] --> created: 创建项目
|
||||
created --> assigned: 分配填写人
|
||||
assigned --> in_progress: 开始填写
|
||||
|
||||
in_progress --> draft_saved: 保存草稿
|
||||
draft_saved --> in_progress: 继续填写
|
||||
in_progress --> pending_review: 提交审核
|
||||
|
||||
pending_review --> approved: 审批通过
|
||||
pending_review --> returned: 审批打回
|
||||
|
||||
returned --> in_progress: 重新填写
|
||||
|
||||
approved --> closed: 项目认证完成
|
||||
|
||||
closed --> [*]
|
||||
|
||||
classDef completed fill:#4caf50,color:#fff
|
||||
classDef current fill:#ff9800,color:#fff,stroke-width:3px
|
||||
classDef pending fill:#e0e0e0,color:#666
|
||||
```
|
||||
|
||||
### 7.8 前端渲染方案(Vue)
|
||||
|
||||
- **开源库**:采用 Vue-Mermaid 组件库 `@mermaid-js/mermaid-tiny`,保持与官方 Mermaid 渲染一致。
|
||||
- **渲染流程**:调用 `/api/workflow/diagram` 获取 `mermaid_code`、`current_node`、`nodes` → 前端异步加载 `mermaid` → 将 `mermaid_code` 传入 VueMermaid 组件渲染 → 根据 `current_node`/`nodes` 动态追加 `classDef` 与 `class` 语句实现高亮。
|
||||
- **兼容性**:使用 SVG 与 ES2020 基础能力,在 Chrome、Firefox 通过官方库验证;初始化时开启 `securityLevel: 'strict'`,避免依赖私有 API。
|
||||
- **后端约束**:后端不做 SVG/PNG 渲染,无需配置 Node.js 或 Chrome 运行时,仅生成 Mermaid 源码。
|
||||
|
||||
### 7.9 动态加载与性能优化
|
||||
|
||||
- 通过 `import('mermaid')` 异步加载,避免进入主 bundle,可在组件 `mounted`/`onMounted` 时按需初始化。
|
||||
- 初始化示例:
|
||||
|
||||
```js
|
||||
const { default: mermaid } = await import('mermaid');
|
||||
mermaid.initialize({
|
||||
startOnLoad: false,
|
||||
securityLevel: 'strict',
|
||||
theme: 'default',
|
||||
});
|
||||
```
|
||||
|
||||
- Vue 示例(伪代码):
|
||||
|
||||
```vue
|
||||
<template>
|
||||
<VueMermaid v-if="mermaidReady" :id="`workflow-${id}`" :value="patchedMermaidCode" />
|
||||
<div v-else>流程图加载中…</div>
|
||||
<button @click="prefetch()">预加载Mermaid</button>
|
||||
</template>
|
||||
|
||||
<script setup>
|
||||
import { ref, onMounted } from 'vue';
|
||||
import VueMermaid from '@mermaid-js/mermaid-tiny';
|
||||
|
||||
const props = defineProps({ code: String, currentNode: String, nodes: Array });
|
||||
const mermaidReady = ref(false);
|
||||
const patchedMermaidCode = computed(() => injectClasses(props.code, props.currentNode, props.nodes));
|
||||
|
||||
async function bootstrap() {
|
||||
if (mermaidReady.value) return;
|
||||
await import('mermaid'); // 不进入主 bundle
|
||||
mermaidReady.value = true;
|
||||
}
|
||||
|
||||
function prefetch() {
|
||||
// 悬停/首屏可调用,进一步降低首次渲染等待
|
||||
bootstrap();
|
||||
}
|
||||
|
||||
onMounted(bootstrap);
|
||||
</script>
|
||||
```
|
||||
|
||||
### 7.10 测试方法(项目详情工单)
|
||||
|
||||
目标:渲染项目详情工单在每个状态下的 Mermaid 源码,输出为一个 SVG 文件,人工核验是否与 [project-detail-workflow.md](diagrams/project-detail-workflow.md) 一致。
|
||||
|
||||
1. **准备状态集合**:`['created','assigned','in_progress','draft_saved','pending_review','approved','returned','closed']`。
|
||||
2. **基准 Mermaid 模板**(包含扩展状态 `draft_saved` 与高亮占位符 `__CURRENT__`):
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
direction LR
|
||||
|
||||
[*] --> created: 创建项目
|
||||
created --> assigned: 分配填写人
|
||||
assigned --> in_progress: 用户开始填写
|
||||
|
||||
in_progress --> draft_saved: 保存草稿
|
||||
draft_saved --> in_progress: 继续填写
|
||||
in_progress --> pending_review: 提交审核
|
||||
in_progress --> assigned: 重新分配
|
||||
|
||||
pending_review --> approved: 审批通过
|
||||
pending_review --> returned: 审批打回
|
||||
|
||||
returned --> in_progress: 用户重新填写
|
||||
returned --> pending_review: 重新提交
|
||||
|
||||
approved --> closed: 项目认证完成
|
||||
closed --> [*]
|
||||
|
||||
classDef completed fill:#4caf50,color:#fff
|
||||
classDef current fill:#ff9800,color:#fff,stroke-width:3px
|
||||
classDef pending fill:#e0e0e0,color:#666
|
||||
class __CURRENT__ current
|
||||
```
|
||||
|
||||
3. **浏览器端生成单一 SVG 文件**(在 Chrome/Firefox 打开任意页面按 F12 粘贴执行,需联网获取 `mermaid` 包,满足跨浏览器验证):
|
||||
|
||||
```js
|
||||
const states = ['created','assigned','in_progress','draft_saved','pending_review','approved','returned','closed'];
|
||||
const template = `stateDiagram-v2
|
||||
direction LR
|
||||
|
||||
[*] --> created: 创建项目
|
||||
created --> assigned: 分配填写人
|
||||
assigned --> in_progress: 用户开始填写
|
||||
|
||||
in_progress --> draft_saved: 保存草稿
|
||||
draft_saved --> in_progress: 继续填写
|
||||
in_progress --> pending_review: 提交审核
|
||||
in_progress --> assigned: 重新分配
|
||||
|
||||
pending_review --> approved: 审批通过
|
||||
pending_review --> returned: 审批打回
|
||||
|
||||
returned --> in_progress: 用户重新填写
|
||||
returned --> pending_review: 重新提交
|
||||
|
||||
approved --> closed: 项目认证完成
|
||||
closed --> [*]
|
||||
|
||||
classDef completed fill:#4caf50,color:#fff
|
||||
classDef current fill:#ff9800,color:#fff,stroke-width:3px
|
||||
classDef pending fill:#e0e0e0,color:#666
|
||||
class __CURRENT__ current`;
|
||||
const { default: mermaid } = await import('mermaid');
|
||||
mermaid.initialize({ startOnLoad: false, securityLevel: 'strict' });
|
||||
|
||||
const fragments = [];
|
||||
for (const [index, state] of states.entries()) {
|
||||
const code = template.replace('__CURRENT__', state);
|
||||
const { svg } = await mermaid.render(`project-detail-${state}`, code);
|
||||
const inner = svg.replace(/^<svg[^>]*>|<\/svg>$/g, '');
|
||||
fragments.push(`<g transform="translate(0, ${index * 360})">${inner}</g>`);
|
||||
}
|
||||
const height = states.length * 360 + 40;
|
||||
const combined = `<svg xmlns="http://www.w3.org/2000/svg" width="1200" height="${height}">${fragments.join('\n')}</svg>`;
|
||||
const blob = new Blob([combined], { type: 'image/svg+xml' });
|
||||
const a = document.createElement('a');
|
||||
a.href = URL.createObjectURL(blob);
|
||||
a.download = 'project-detail-states.svg';
|
||||
a.click();
|
||||
```
|
||||
|
||||
4. **人工核验**:打开 `project-detail-states.svg`,逐段确认节点、连线、文案及高亮与流程设计一致;如有差异,调整模板并重新生成。
|
||||
|
||||
---
|
||||
|
||||
## 8. 相关文档
|
||||
|
||||
| 文档 | 内容 |
|
||||
|------|------|
|
||||
| [用户注册工单流程](diagrams/user-registration-workflow.md) | 用户注册工单的状态机、流程图、时序图 |
|
||||
| [用户管理工单流程](diagrams/user-management-workflow.md) | 用户管理工单的状态机、流程图、时序图 |
|
||||
| [项目信息填写工单流程](diagrams/project-detail-workflow.md) | 项目详情工单的状态机、流程图、时序图 |
|
||||
| [微服务更新工单流程](diagrams/microservice-update-workflow.md) | 微服务更新工单的状态机、流程图、时序图 |
|
||||
| [工单流程PRD](2-rmdc-work-procedure-PRD.md) | 产品需求文档 |
|
||||
|
||||
---
|
||||
|
||||
## 9. 参考设计
|
||||
|
||||
设计参考了以下开源项目的最佳实践:
|
||||
|
||||
1. **Ferry** - Go语言工单系统,支持工作流引擎、权限管理、灵活配置
|
||||
2. **Flowable** - Java工作流引擎,乐观锁并发控制机制
|
||||
3. **Camunda** - BPMN工作流引擎,微服务编排
|
||||
4. **NocoBase** - 低代码平台,灵活的数据建模与工作流设计
|
||||
271
8-CMII-RMDC/7-rmdc-work-procedure/2-rmdc-work-procedure-PRD.md
Normal file
271
8-CMII-RMDC/7-rmdc-work-procedure/2-rmdc-work-procedure-PRD.md
Normal file
@@ -0,0 +1,271 @@
|
||||
# 工单流程模块(工单系统)
|
||||
|
||||
** 工单流程在下文中等同于工单 **
|
||||
|
||||
## 工单流程模块与其他模块的关系
|
||||
1. rmdc-project-management依赖本模块
|
||||
2. rmdc-user-auth模块依赖本模块
|
||||
3. deliver-update模块依赖本模块
|
||||
|
||||
## 工单流程说明
|
||||
|
||||
### 工单流程发起与处理
|
||||
1. 工单流程发起
|
||||
1. 工单流程从特定的模块中发起
|
||||
1. 用户模块 rmdc-user-auth
|
||||
2. 项目管理模块 rmdc-project-management
|
||||
2. 不涉及手动创建工单,本项目均通过业务模块直接创建工单
|
||||
2. 工单流程处理
|
||||
1. 所有用户具备工单流程的页面
|
||||
1. 可以查看到自己的发起的工单流程
|
||||
2. 可以查看到自己的被委派(需要处理)的工单流程
|
||||
3. 展示完整的工单流程列表,点击可以查看到工单流程的详情
|
||||
2. 工单流程的详情页面
|
||||
1. 具体的详情页面需要根据各个模块的工单流程逻辑进行定制
|
||||
2. 工单详情页面的模板相同
|
||||
3. 工单详情页面绑定覆盖业务模块的必要信息,可以直接调转到业务模块的详情页面
|
||||
3. **工单流程状态追踪机制**
|
||||
1. **业务回调机制**: 业务模块处理完成后,必须调用工单系统的回调接口 `POST /api/workflow/callback` 更新工单状态
|
||||
2. **状态变更历史表**: 所有状态变更均写入 `workflow_track_history` 表,支持全生命周期审计
|
||||
3. **实时通知推送**: 状态变更时通过通知中心模块向发起人和处理人推送实时通知(WebSocket/App推送)
|
||||
4. **轮询兜底**: 前端可选配置定时轮询接口 `GET /api/workflow/{id}/status` 获取最新状态
|
||||
4. 工单流程通知
|
||||
1. 通过[通知中心模块](0-设计方案/6-rmdc-notice-center)进行消息通知的
|
||||
|
||||
### 工单流程执行策略
|
||||
1. 从非超级管理员用户到超级管理员的工单流程,有如下的策略
|
||||
1. 超级管理员可以自行执行
|
||||
2. 超级管理员可以委派工单执行人,即执行人可以变更
|
||||
3. 超级管理员可以设置自动审批,工单可以自动审批处理
|
||||
4. 超级管理员可以设置定时执行,代表工单审批通过,在未来的特定时间点执行
|
||||
2. 超级管理员到非超级管理员用户的工单流程
|
||||
1. 非超级管理员用户无法委派,即执行人无法变更
|
||||
2. 只能由非超级管理员用户自行操作执行
|
||||
|
||||
### 工单流程的生命周期
|
||||
1. 工单流程的生命周期
|
||||
1. 工单流程的创建
|
||||
2. 工单流程的处理
|
||||
3. 工单流程的完成
|
||||
4. 工单流程的撤销
|
||||
5. 工单流程的拒绝
|
||||
6. 工单流程的超时
|
||||
7. 工单流程的结束
|
||||
2. **并发处理场景** - 当用户正在处理工单流程时的竞态条件处理
|
||||
1. **工单流程被委派给其他用户**
|
||||
- 采用 **乐观锁机制**: 工单表增加 `version` 字段,每次更新必须校验版本号
|
||||
- 委派操作成功后,通过通知中心向原处理人推送 `WORKFLOW_REASSIGNED` 事件
|
||||
- 前端收到事件后显示提示弹窗: "此工单已被重新委派给XXX,您的处理权限已转移"
|
||||
- 原处理人页面切换为只读模式或引导返回列表
|
||||
- 若原处理人仍尝试提交,后端校验版本号不匹配,返回 `409 Conflict`
|
||||
2. **工单流程被撤销**
|
||||
- 撤销操作前校验工单状态: 仅 `pending/assigned` 状态可直接撤销
|
||||
- `in_progress` 状态撤销需要二次确认,并通知处理人
|
||||
- 撤销成功后推送 `WORKFLOW_REVOKED` 事件
|
||||
- 前端收到事件后自动关闭处理页面,引导至工单列表
|
||||
- 已执行的步骤数据保留,状态标记为 `revoked`
|
||||
3. **工单流程被修改**
|
||||
- 修改操作前校验乐观锁版本号
|
||||
- 仅特定状态允许修改: `pending/assigned/returned`
|
||||
- 修改成功后推送 `WORKFLOW_MODIFIED` 事件,携带变更字段摘要
|
||||
- 前端收到事件后提示刷新,或自动刷新表单数据
|
||||
- 如用户本地有未保存的修改,提示冲突并允许手动合并
|
||||
3. 每一个工单流程具备唯一的ID进行全生命周期的追踪处理
|
||||
1. 唯一ID的生成方式, 模块简称+时间戳+发起人英文名称
|
||||
2. 例子 项目管理模块发起的工单流程ID为 project-20260106110303-zeaslity
|
||||
|
||||
|
||||
## 工单流程持久化说明
|
||||
1. 每一个工单流程需要进行持久化保存
|
||||
2. 每一种类型的工单流程的状态机是否应该不同
|
||||
3. 工单流程必须的字段
|
||||
1. 工单流程ID
|
||||
2. 工单流程发起人
|
||||
3. 工单流程发起时间
|
||||
4. 工单流程超时时间 需要在多长时间内完成
|
||||
5. 工单流程处理人
|
||||
6. 工单流程被委派人 工单流程的实际处理人
|
||||
7. 工单流程处理时间
|
||||
8. 工单流程处理状态
|
||||
9. 工单流程处理结果
|
||||
10. 工单流程处理备注
|
||||
11. 工单流程每一步骤的处理时间
|
||||
12. 工单流程每一步骤的处理人
|
||||
13. 工单流程每一步骤的处理状态
|
||||
14. 工单流程每一步骤的处理结果
|
||||
15. 工单流程每一步骤的处理备注 为下一步提供信息
|
||||
16. 工单流程可能需要传递参数给下一步
|
||||
|
||||
|
||||
## 工单流程权限
|
||||
|
||||
### 项目信息填写工单流程权限
|
||||
1. 非超级管理员用户
|
||||
1. 只能查看,处理分配给自己的或者自己创建的项目信息填写工单
|
||||
2. 超级管理员
|
||||
1. 可以查看,处理全部项目信息填写工单
|
||||
|
||||
### 微服务更新流程权限
|
||||
1. 非超级管理员用户
|
||||
1. 只能查看,处理自己创建的微服务更新工单流程
|
||||
2. 超级管理员
|
||||
1. 可以查看,处理全部微服务更新工单流程
|
||||
|
||||
### 用户注册工单流程权限
|
||||
1. 非超级管理员用户
|
||||
1. 只能查看,处理自己创建的用户注册工单流程
|
||||
2. 超级管理员
|
||||
1. 可以查看,处理全部的用户注册工单流程
|
||||
|
||||
### 用户信息管理工单流程权限
|
||||
1. 非超级管理员用户
|
||||
1. 只能查看,处理自己创建的户信息管理工单流程
|
||||
2. 超级管理员
|
||||
1. 可以查看,处理全部的户信息管理工单流程
|
||||
|
||||
|
||||
## 工单流程详情
|
||||
1. 工单流程的每一步均可以附带信息给下一步
|
||||
2. 工单流程可能需要传递参数给下一步
|
||||
|
||||
### 项目信息填写工单流程
|
||||
1. 超级管理员初步创建项目的Metadata数据
|
||||
2. 发起工单分派给普通用户进行项目详情的填写
|
||||
3. 普通用户可以保存草稿,直到可以提交项目审批
|
||||
4. 普通用户提交项目审批
|
||||
5. 自动分配给超级管理员审批
|
||||
6. 超级管理员进行项目的审批
|
||||
1. 审批通过
|
||||
1. 工单结束
|
||||
2. 项目详情表正式上线
|
||||
2. 审批拒绝
|
||||
1. 重新回到普通用户补充项目信息的阶段(项目详情处于草稿状态)
|
||||
2. 用户重新修改项目的详情信息之后
|
||||
3. 用户可以基于此工单重新提交审批
|
||||
3. 超级管理员可以进行项目管理详情的修改,修改完成之后,工单结束
|
||||
7. 当用户的项目信息没有被审批通过
|
||||
1. 草稿状态的项目信息应该绑定唯一工单
|
||||
2. 草稿状态的项目详情应该显示工单号
|
||||
3. 草稿状态的项目信息,提交审批之后可以跳转到 项目详情工单详情页面
|
||||
4. 除非工单的状态进入到closed状态,项目信息才可以重新关联新的工单
|
||||
8. 用户无法取消项目详情工单的流程
|
||||
1. 只有超级管理员可以取消项目详情工单
|
||||
|
||||
### 用户注册工单流程
|
||||
1. 非超级管理员用户的在用户注册之后
|
||||
1. 用户状态默认为 disabled
|
||||
2. 启动用户注册工单流程
|
||||
1. 自动创建用户注册工单
|
||||
2. 自动提交给超级管理员
|
||||
3. 超级管理员审核
|
||||
1. 审核通过
|
||||
1. 自动修改用户状态为 active, 用户启用
|
||||
2. 审核不通过
|
||||
1. 回退到用户注册阶段
|
||||
2. 用户可以重新修改用户注册信息
|
||||
3. 可以在此工单详情中重新发起审批
|
||||
4. 处于注册草稿状态(disable)的用户详情页面
|
||||
1. 草稿状态的用户详情页面,需要关联唯一用户注册工单流程工单
|
||||
2. 草稿状态的用户详情页面,可以发起用户注册审批
|
||||
3. 草稿状态的用户详情页面,提交用户注册审批之后,可以跳转用户注册工单详情页面
|
||||
5. 用户可以撤回用户注册工单申请
|
||||
1. 撤回之后,工单重新进入用户信息注册阶段 created状态
|
||||
2. 撤回之后,用户详情页面仍然处于草稿状态,可以进行草稿状态的操作
|
||||
6. 用户可以取消注册工单流程
|
||||
1. 用户取消用户注册工单之后,工单进入closed状态
|
||||
2. 用户取消用户注册工单之后,无法基于此工单提交审批工作
|
||||
3. 取消之后,从用户数据库中硬删除创建的用户
|
||||
7. 用户可以基于取消的注册工单一键重新创建新的注册工单流程
|
||||
1. 密码等信息不能再前端保存
|
||||
2. 密码需要重新创建
|
||||
|
||||
### 用户管理(修改、删除、 状态(启用、禁用))工单流程
|
||||
1. 用户侧-用户管理页面,用户可以通过编辑按钮、删除按钮进行用户管理
|
||||
2. 启动用户管理工单流程
|
||||
1. 自动创建用户管理工单
|
||||
2. 自动提交给超级管理员进行审批
|
||||
3. 超级管理员审核
|
||||
1. 审核通过
|
||||
1. 根据管理的内容,修改用户相应的信息,更新数据库
|
||||
2. 用户管理工单结束
|
||||
2. 审核不通过
|
||||
1. 回退到用户管理阶段
|
||||
2. 用户可以继续修改相关信息,继续提交审核
|
||||
4. 处于编辑状态的用户详情
|
||||
1. 编辑状态的用户详情页面,需要关联唯一用户管理工单流程工单
|
||||
2. 编辑状态的用户详情页面,可以发起用户管理审批
|
||||
3. 编辑状态的用户详情页面,提交用户管理审批之后,可以跳转用户管理工单详情页面
|
||||
5. 用户可以撤回用户管理工单流程
|
||||
1. 撤回之后的管理工单,处于created状态
|
||||
2. 撤回之后,用户详情页面仍然处于编辑状态
|
||||
3. 撤回之后,仍然可以基于此工单重新发起审批
|
||||
6. 用户可以关闭用户管理工单流程
|
||||
1. 关闭之后的用户管理工单,处于状态机中的closed状态
|
||||
2. 工单的生命周期结束,无法操作该工单的状态(即无法提交审批 审批 拒绝等)
|
||||
3. 关闭之后,相应的用户详情应该退出编辑状态,用户详情页面不显示用户管理工单和相关操作
|
||||
|
||||
### 微服务更新工单流程
|
||||
1. 普通用户在构建详情页面点击微服务更新
|
||||
2. 携带构建物信息跳转至微服务更新详情页面
|
||||
1. 微服务更新页面使用3大竖列的形式,发起微服务升级工单
|
||||
2. 如果正确的跳转,构建物信息应该出现在最左侧一栏
|
||||
3. 中间一栏是微服务更新的表单, 用户可以选择需要更新的项目及微服务, 预期的更新时间
|
||||
4. 最右侧一栏是微服务更新的发起按钮
|
||||
3. 普通用户提交微服务更新工单,进行工单的下一步
|
||||
4. 超级管理员可以自己执行,也可以委派更新任务
|
||||
5. 超级管理员进行微服务更新的审批
|
||||
1. 微服务更新如果满足更新条件,则同意更新,进入工单的下一步
|
||||
2. 微服务更新如果不满足更新条件,则拒绝更新,返回到普通用户修改更新信息的阶段,进行循环直到审批通过
|
||||
3. 针对定期的更新,超级管理员同意更新,进入工单的下一步
|
||||
6. 超级管理员进行微服务更新的执行操作
|
||||
1. 微服务的更新操作,更新状态需要通过 rmdc-exchange-hub rmdc-watchdog模块进行
|
||||
2. 微服务的更新状态可以在工单中展示
|
||||
7. 微服务更新状态
|
||||
1. 微服务更新成功,进入工单的下一步
|
||||
2. 微服务更新失败,回到超级管理员进行微服务更新的执行操作,进行循环直到更新成功
|
||||
8. 微服务运行状态
|
||||
1. 微服务更新后运行状态正常,工单结束
|
||||
2. 微服务更新后运行状态异常, rmdc-watchdog应该自动回滚微服务至更新前的版本, 工单需要记录微服务更新失败的信息, 工单结束
|
||||
|
||||
## 工单详情页面
|
||||
|
||||
### 工单处理流程图
|
||||
1. 工单详情页面应该展示工单处理流程图
|
||||
2. 工单处理流程图应该展示工单的当前状态
|
||||
3. 工单处理流程图应该展示每一步分处理人
|
||||
4. 工单处理流程图应该展示每一步的处理时间
|
||||
5. 工单处理流程图应该展示每一步的处理结果
|
||||
6. 工单处理流程图由后端生成mermaid格式的内容,由前端负责渲染
|
||||
7. 后端需要根据工单的当前状态,生成对应的mermaid格式的内容
|
||||
8. 开源的库实现为Vue-Mermaid @mermaid-js/mermaid-tiny
|
||||
9. 动态加载与性能:为了减小对前端性能的影响,通过异步 import('mermaid') 来加载库,避免它进入主 bundle
|
||||
|
||||
### 工单处理历史
|
||||
1. 工单详情页面应该展示工单处理历史
|
||||
2. 工单处理历史应该展示每一步的处理人
|
||||
3. 工单处理历史应该展示每一步的处理时间
|
||||
4. 工单处理历史应该展示每一步的处理结果
|
||||
5. 工单处理历史应该展示每一步的处理备注
|
||||
|
||||
### 跳转策略
|
||||
1. 工单详情页面 应该可以跳转至业务详情页面
|
||||
2. 工单详情页面 可以返回至工单列表页面
|
||||
|
||||
## 用户注册工单流程详情页面
|
||||
1. 可以跳转至用户注册详情页面
|
||||
2. 用户注册详情页面可以跳转至工单详情页面
|
||||
3. 用户侧 和 管理测的界面有些许不同,但是大部分都可以复用
|
||||
|
||||
## 项目信息填写工单流程详情页面
|
||||
1. 可以跳转至项目详情页面
|
||||
2. 项目详情页面可以跳转至工单详情页面
|
||||
3. 用户侧 和 管理测的界面有些许不同,但是大部分都可以复用
|
||||
|
||||
## 参考的开源工单系统
|
||||
|
||||
设计参考了以下开源项目的最佳实践:
|
||||
|
||||
1. **Ferry** - Go语言工单系统,支持工单流程引擎、权限管理、灵活配置
|
||||
2. **Flowable** - Java工单流程引擎,乐观锁并发控制机制
|
||||
3. **Camunda** - BPMN工单流程引擎,微服务编排
|
||||
4. **NocoBase** - 低代码平台,灵活的数据建模与工单流程设计
|
||||
@@ -0,0 +1,313 @@
|
||||
# 微服务更新工单流程
|
||||
|
||||
**工单类型代码**: `microservice_update`
|
||||
**来源模块**: deliver-update
|
||||
**编制日期**: 2026-01-08
|
||||
|
||||
---
|
||||
|
||||
## 1. 业务场景
|
||||
|
||||
普通用户在构建详情页面发起微服务更新请求,经过超级管理员审批后执行更新操作,并监控微服务运行状态。
|
||||
|
||||
### 1.1 业务规则
|
||||
|
||||
| 规则项 | 说明 |
|
||||
|-------|------|
|
||||
| 发起人 | 普通用户 |
|
||||
| 审批人 | 超级管理员 |
|
||||
| 执行人 | 超级管理员或委派人 |
|
||||
| 支持定时执行 | 是 |
|
||||
| 支持委派 | 是(超管可委派给其他人执行) |
|
||||
| 自动回滚 | 是(更新失败时自动回滚) |
|
||||
|
||||
### 1.2 相关模块
|
||||
|
||||
| 模块 | 职责 |
|
||||
|-----|------|
|
||||
| rmdc-jenkins-branch-dac | 提供构建物信息 |
|
||||
| rmdc-exchange-hub | MQTT消息中继 |
|
||||
| rmdc-watchdog | K8S操作执行、状态监控 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 状态机
|
||||
|
||||
### 2.1 状态定义
|
||||
|
||||
| 状态代码 | 状态名称 | 说明 | 是否扩展状态 |
|
||||
|---------|---------|------|------------|
|
||||
| `created` | 已创建 | 用户发起更新请求 | 否 |
|
||||
| `pending_review` | 待审核 | 等待超级管理员审核 | 否 |
|
||||
| `approved` | 已批准 | 审核通过,等待执行 | 否 |
|
||||
| `returned` | 已打回 | 审核打回,需修改 | 否 |
|
||||
| `rejected` | 已拒绝 | 审核拒绝,流程终止 | 否 |
|
||||
| `executing` | 执行中 | 微服务更新正在执行 | 是 |
|
||||
| `monitoring` | 监控中 | 更新完成,监控运行状态 | 是 |
|
||||
| `rollbacked` | 已回滚 | 更新失败,已自动回滚 | 是 |
|
||||
| `closed` | 已关闭 | 工单生命周期结束 | 否 |
|
||||
| `revoked` | 已撤销 | 用户撤销更新请求 | 否 |
|
||||
|
||||
### 2.2 状态机图
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> created: 发起更新请求
|
||||
|
||||
created --> pending_review: 提交审核
|
||||
created --> revoked: 用户撤销
|
||||
|
||||
pending_review --> approved: 审批通过
|
||||
pending_review --> returned: 审批打回
|
||||
pending_review --> rejected: 审批拒绝
|
||||
pending_review --> revoked: 用户撤销
|
||||
|
||||
returned --> pending_review: 修改后重新提交
|
||||
returned --> revoked: 用户撤销
|
||||
|
||||
approved --> executing: 开始执行
|
||||
approved --> approved: 等待定时执行
|
||||
|
||||
executing --> monitoring: 更新成功
|
||||
executing --> executing: 执行重试
|
||||
executing --> rollbacked: 更新失败回滚
|
||||
|
||||
monitoring --> closed: 运行正常
|
||||
monitoring --> rollbacked: 运行异常回滚
|
||||
|
||||
rollbacked --> closed: 记录失败信息
|
||||
rejected --> closed: 关闭工单
|
||||
revoked --> closed: 关闭工单
|
||||
|
||||
closed --> [*]
|
||||
|
||||
note right of executing: 通过rmdc-watchdog执行
|
||||
note right of monitoring: 监控微服务健康状态
|
||||
note right of rollbacked: 自动回滚到更新前版本
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 流程图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> SelectBuild[用户选择构建物]
|
||||
SelectBuild --> JumpToUpdate[跳转微服务更新页面]
|
||||
|
||||
JumpToUpdate --> ThreeColumns[三栏布局页面]
|
||||
ThreeColumns --> LeftColumn[左栏:构建物信息]
|
||||
ThreeColumns --> MiddleColumn[中栏:更新表单]
|
||||
ThreeColumns --> RightColumn[右栏:发起按钮]
|
||||
|
||||
MiddleColumn --> FillForm[填写更新信息]
|
||||
FillForm --> SelectProject[选择目标项目]
|
||||
SelectProject --> SelectService[选择目标微服务]
|
||||
SelectService --> SetSchedule[设置更新时间]
|
||||
|
||||
SetSchedule --> SubmitRequest[提交更新请求]
|
||||
SubmitRequest --> CreateWorkflow[创建更新工单]
|
||||
|
||||
CreateWorkflow --> PendingReview{待审核}
|
||||
|
||||
PendingReview -->|审批通过| CheckSchedule{是否定时执行?}
|
||||
PendingReview -->|审批打回| Return[打回修改]
|
||||
PendingReview -->|审批拒绝| Reject[拒绝请求]
|
||||
PendingReview -->|用户撤销| Revoke[撤销请求]
|
||||
|
||||
Return --> ModifyRequest[修改更新信息]
|
||||
ModifyRequest --> SubmitRequest
|
||||
|
||||
CheckSchedule -->|立即执行| StartExecute[开始执行更新]
|
||||
CheckSchedule -->|定时执行| WaitSchedule[等待定时触发]
|
||||
WaitSchedule --> StartExecute
|
||||
|
||||
StartExecute --> Executing{执行更新}
|
||||
|
||||
Executing -->|成功| Monitoring[监控运行状态]
|
||||
Executing -->|失败| RetryCheck{重试?}
|
||||
|
||||
RetryCheck -->|是| StartExecute
|
||||
RetryCheck -->|否| Rollback[自动回滚]
|
||||
|
||||
Monitoring --> HealthCheck{健康检查}
|
||||
|
||||
HealthCheck -->|正常| CloseSuccess[工单关闭-成功]
|
||||
HealthCheck -->|异常| Rollback
|
||||
|
||||
Rollback --> RecordFailure[记录失败信息]
|
||||
RecordFailure --> CloseFailure[工单关闭-回滚]
|
||||
|
||||
Reject --> CloseRejected[工单关闭]
|
||||
Revoke --> CloseRevoked[工单关闭]
|
||||
|
||||
CloseSuccess --> End([结束])
|
||||
CloseFailure --> End
|
||||
CloseRejected --> End
|
||||
CloseRevoked --> End
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
|
||||
participant User as 普通用户
|
||||
participant Frontend as 前端
|
||||
participant Jenkins as rmdc-jenkins
|
||||
participant Workflow as rmdc-work-procedure
|
||||
participant SuperAdmin as 超级管理员
|
||||
participant ExHub as rmdc-exchange-hub
|
||||
participant Watchdog as rmdc-watchdog
|
||||
participant Notice as 通知中心
|
||||
|
||||
%% 发起更新请求
|
||||
User->>Frontend: 查看构建详情
|
||||
Frontend->>Jenkins: POST /api/jenkins/build/detail
|
||||
Jenkins-->>Frontend: 返回构建物信息
|
||||
User->>Frontend: 点击微服务更新
|
||||
Frontend->>Frontend: 跳转更新页面(携带构建信息)
|
||||
|
||||
User->>Frontend: 填写更新表单
|
||||
Note over Frontend: 选择项目、微服务、更新时间
|
||||
User->>Frontend: 点击发起更新
|
||||
Frontend->>Workflow: POST /api/workflow/create
|
||||
Note over Workflow: 创建microservice_update工单<br/>保存build_id, target_version
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>SuperAdmin: 微服务更新审批通知
|
||||
|
||||
%% 审批阶段
|
||||
alt 审批通过
|
||||
SuperAdmin->>Frontend: 审批通过
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=approve
|
||||
Workflow->>Workflow: 设置status=approved
|
||||
|
||||
alt 立即执行
|
||||
Workflow->>Workflow: 设置status=executing
|
||||
Workflow->>ExHub: 发送更新指令
|
||||
ExHub->>Watchdog: MQTT下发更新命令
|
||||
|
||||
%% 执行更新
|
||||
Watchdog->>Watchdog: 执行K8S滚动更新
|
||||
|
||||
alt 更新成功
|
||||
Watchdog-->>ExHub: 上报更新成功
|
||||
ExHub->>Workflow: POST /api/workflow/callback
|
||||
Workflow->>Workflow: 设置status=monitoring
|
||||
|
||||
%% 健康监控
|
||||
loop 健康检查(5分钟)
|
||||
Watchdog->>Watchdog: 检查Pod状态
|
||||
end
|
||||
|
||||
alt 运行正常
|
||||
Watchdog-->>ExHub: 上报运行正常
|
||||
ExHub->>Workflow: POST /api/workflow/callback
|
||||
Workflow->>Workflow: 设置status=closed
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 微服务更新成功
|
||||
else 运行异常
|
||||
Watchdog->>Watchdog: 自动回滚
|
||||
Watchdog-->>ExHub: 上报回滚结果
|
||||
ExHub->>Workflow: POST /api/workflow/callback
|
||||
Note over Workflow: 记录rollback_info
|
||||
Workflow->>Workflow: 设置status=rollbacked
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 微服务更新回滚
|
||||
end
|
||||
else 更新失败
|
||||
Watchdog->>Watchdog: 自动回滚
|
||||
Watchdog-->>ExHub: 上报失败+回滚
|
||||
ExHub->>Workflow: POST /api/workflow/callback
|
||||
Workflow->>Workflow: 设置status=rollbacked
|
||||
end
|
||||
|
||||
else 定时执行
|
||||
Note over Workflow: 等待scheduled_at时间
|
||||
Workflow->>Workflow: 定时触发执行
|
||||
end
|
||||
|
||||
else 审批打回
|
||||
SuperAdmin->>Frontend: 打回修改
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=return
|
||||
Workflow->>Workflow: 设置status=returned
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 更新请求被打回
|
||||
|
||||
else 审批拒绝
|
||||
SuperAdmin->>Frontend: 拒绝请求
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=reject
|
||||
Workflow->>Workflow: 设置status=rejected
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 工单步骤定义
|
||||
|
||||
| 步骤序号 | 步骤名称 | 步骤类型 | 处理人 | 操作说明 |
|
||||
|---------|---------|---------|-------|---------|
|
||||
| 1 | 提交更新请求 | `submit` | 普通用户 | 填写更新信息并提交 |
|
||||
| 2 | 审核更新请求 | `approve` | 超级管理员 | 审批通过/打回/拒绝 |
|
||||
| 3 | 执行更新 | `execute` | 超级管理员/委派人 | 执行微服务滚动更新 |
|
||||
| 4 | 监控运行状态 | `monitor` | 系统自动 | 监控微服务健康状态 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 业务扩展字段
|
||||
|
||||
存储于 `microservice_update_ext` 表:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|-----|------|------|
|
||||
| `project_id` | VARCHAR(64) | 目标项目ID |
|
||||
| `namespace` | VARCHAR(64) | K8S命名空间 |
|
||||
| `service_name` | VARCHAR(128) | 微服务名称 |
|
||||
| `build_id` | VARCHAR(128) | 构建物ID |
|
||||
| `current_version` | VARCHAR(64) | 当前版本 |
|
||||
| `target_version` | VARCHAR(64) | 目标版本 |
|
||||
| `scheduled_at` | DATETIME | 计划执行时间 |
|
||||
| `execute_result` | VARCHAR(32) | 执行结果:success/failed/rollbacked |
|
||||
| `rollback_info` | JSON | 回滚信息 |
|
||||
|
||||
### 6.1 rollback_info 示例
|
||||
|
||||
```json
|
||||
{
|
||||
"rollback_reason": "Pod健康检查失败",
|
||||
"rollback_time": "2026-01-08T15:30:00Z",
|
||||
"rollback_version": "v3.1.5",
|
||||
"error_details": {
|
||||
"pod_name": "service-abc-7d8f9c6b5d-xyz",
|
||||
"error_message": "Readiness probe failed: connection refused",
|
||||
"failed_checks": 3
|
||||
}
|
||||
}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 7. 更新页面布局
|
||||
|
||||
```
|
||||
┌─────────────────────────────────────────────────────────────────┐
|
||||
│ 微服务更新 │
|
||||
├─────────────────┬─────────────────────────┬────────────────────┤
|
||||
│ 构建物信息 │ 更新表单 │ 操作区 │
|
||||
│ │ │ │
|
||||
│ 组织: acme │ 目标项目: [下拉选择] │ │
|
||||
│ 仓库: service │ 目标微服务: [下拉选择] │ [发起更新] │
|
||||
│ 分支: main │ 更新时间: [日期选择] │ │
|
||||
│ 构建号: #123 │ ○ 立即执行 │ [取消] │
|
||||
│ 版本: v3.2.0 │ ○ 定时执行 │ │
|
||||
│ │ 备注: [文本框] │ │
|
||||
│ │ │ │
|
||||
└─────────────────┴─────────────────────────┴────────────────────┘
|
||||
```
|
||||
@@ -0,0 +1,258 @@
|
||||
# 项目信息填写工单流程
|
||||
|
||||
**工单类型代码**: `project_detail`
|
||||
**来源模块**: rmdc-project-management
|
||||
**编制日期**: 2026-01-08
|
||||
|
||||
---
|
||||
|
||||
## 1. 业务场景
|
||||
|
||||
超级管理员创建项目元数据后,分配给普通用户填写项目详情信息,填写完成后提交审核。
|
||||
|
||||
### 1.1 业务规则
|
||||
|
||||
| 规则项 | 说明 |
|
||||
|-------|------|
|
||||
| 发起人 | 超级管理员 |
|
||||
| 填写人 | 被分配的普通用户 |
|
||||
| 审批人 | 超级管理员 |
|
||||
| 支持草稿 | 是(可多次保存草稿) |
|
||||
| 可撤销 | 否(仅超级管理员可取消) |
|
||||
| 项目状态关联 | 草稿状态绑定唯一工单 |
|
||||
|
||||
### 1.2 项目状态对应关系
|
||||
|
||||
| 工单状态 | 项目认证状态 |
|
||||
|---------|------------|
|
||||
| `assigned` / `in_progress` | `draft` (草稿) |
|
||||
| `pending_review` | `pending` (待审核) |
|
||||
| `approved` / `closed` | `official` (正式) |
|
||||
| `returned` | `draft` (草稿) |
|
||||
|
||||
---
|
||||
|
||||
## 2. 状态机
|
||||
|
||||
### 2.1 状态定义
|
||||
|
||||
| 状态代码 | 状态名称 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `created` | 已创建 | 项目创建,工单生成 |
|
||||
| `assigned` | 已分配 | 已分配填写人 |
|
||||
| `in_progress` | 填写中 | 用户正在填写项目信息 |
|
||||
| `draft_saved` | 草稿已保存 | 扩展状态:草稿保存成功 |
|
||||
| `pending_review` | 待审核 | 填写完成,等待审核 |
|
||||
| `approved` | 已通过 | 审核通过,项目正式上线 |
|
||||
| `returned` | 已打回 | 审核打回,需重新填写 |
|
||||
| `closed` | 已关闭 | 工单生命周期结束 |
|
||||
|
||||
### 2.2 状态机图
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> created: 创建项目
|
||||
|
||||
created --> assigned: 分配填写人
|
||||
|
||||
assigned --> in_progress: 用户开始填写
|
||||
assigned --> assigned: 重新分配
|
||||
|
||||
in_progress --> in_progress: 保存草稿
|
||||
in_progress --> pending_review: 提交审核
|
||||
in_progress --> assigned: 重新分配
|
||||
|
||||
pending_review --> approved: 审批通过
|
||||
pending_review --> returned: 审批打回
|
||||
|
||||
returned --> in_progress: 用户重新填写
|
||||
returned --> pending_review: 重新提交
|
||||
|
||||
approved --> closed: 关闭工单
|
||||
|
||||
closed --> [*]
|
||||
|
||||
note right of approved: 项目状态变为official
|
||||
note right of in_progress: 支持多次保存草稿
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 流程图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> CreateProject[超管创建项目元数据]
|
||||
CreateProject --> CreateWorkflow[自动创建项目详情工单]
|
||||
CreateWorkflow --> SelectFiller[选择项目信息填写人]
|
||||
SelectFiller --> AssignWorkflow[工单分配给填写人]
|
||||
|
||||
AssignWorkflow --> NotifyFiller[通知填写人]
|
||||
NotifyFiller --> UserAccept[填写人接受任务]
|
||||
|
||||
UserAccept --> FillDetail[填写项目详情信息]
|
||||
FillDetail --> SaveDraft{保存操作}
|
||||
|
||||
SaveDraft -->|保存草稿| DraftSaved[草稿保存成功]
|
||||
DraftSaved --> FillDetail
|
||||
|
||||
SaveDraft -->|提交审核| ValidateRequired{必填项校验}
|
||||
ValidateRequired -->|校验失败| FillDetail
|
||||
ValidateRequired -->|校验通过| SubmitReview[提交审核]
|
||||
|
||||
SubmitReview --> PendingReview{待审核}
|
||||
|
||||
PendingReview -->|审批通过| Approve[审批通过]
|
||||
PendingReview -->|审批打回| Return[打回修改]
|
||||
PendingReview -->|超管直接修改| AdminModify[超管修改信息]
|
||||
|
||||
Approve --> SetOfficial[项目状态设为official]
|
||||
SetOfficial --> CloseWorkflow[关闭工单]
|
||||
CloseWorkflow --> End([结束])
|
||||
|
||||
Return --> BackToFill[回到填写阶段]
|
||||
BackToFill --> FillDetail
|
||||
|
||||
AdminModify --> SetOfficial
|
||||
|
||||
%% 重新分配分支
|
||||
AssignWorkflow --> ReassignCheck{需要重新分配?}
|
||||
ReassignCheck -->|是| SelectFiller
|
||||
ReassignCheck -->|否| NotifyFiller
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
|
||||
participant Admin as 超级管理员
|
||||
participant Frontend as 前端
|
||||
participant Project as rmdc-project-management
|
||||
participant Workflow as rmdc-work-procedure
|
||||
participant User as 填写人
|
||||
participant Notice as 通知中心
|
||||
|
||||
%% 项目创建阶段
|
||||
Admin->>Frontend: 创建项目
|
||||
Frontend->>Project: POST /api/project/create
|
||||
Note over Project: 创建项目元数据<br/>status=draft
|
||||
Project->>Workflow: POST /api/workflow/create
|
||||
Note over Workflow: 创建project_detail工单<br/>保存detail_filler_id
|
||||
Workflow-->>Project: 返回工单ID
|
||||
Project->>Project: 关联工单ID
|
||||
Project-->>Frontend: 项目创建成功
|
||||
|
||||
%% 分配填写人
|
||||
Admin->>Frontend: 选择填写人
|
||||
Frontend->>Workflow: POST /api/workflow/assign
|
||||
Workflow->>Workflow: 设置status=assigned
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 项目信息填写通知
|
||||
|
||||
%% 用户填写阶段
|
||||
User->>Frontend: 进入项目详情页
|
||||
Frontend->>Project: POST /api/project/detail
|
||||
Project-->>Frontend: 返回项目信息+草稿数据
|
||||
|
||||
loop 填写并保存草稿
|
||||
User->>Frontend: 填写项目信息
|
||||
Frontend->>Project: POST /api/project/draft/save
|
||||
Project->>Workflow: 更新draft_data
|
||||
Project-->>Frontend: 草稿保存成功
|
||||
end
|
||||
|
||||
%% 提交审核
|
||||
User->>Frontend: 点击提交审核
|
||||
Frontend->>Project: POST /api/project/submit
|
||||
Note over Project: 校验必填项
|
||||
Project->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=complete
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>Admin: 项目详情审核通知
|
||||
|
||||
%% 审批场景
|
||||
alt 审批通过
|
||||
Admin->>Frontend: 点击通过
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=approve
|
||||
Workflow->>Project: 回调更新项目状态
|
||||
Project->>Project: 设置status=official
|
||||
Workflow->>Workflow: 设置status=approved
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 项目审核通过
|
||||
|
||||
else 审批打回
|
||||
Admin->>Frontend: 点击打回
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=return<br/>附带修改意见
|
||||
Workflow->>Workflow: 设置status=returned
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 项目被打回
|
||||
|
||||
User->>Frontend: 根据意见修改
|
||||
Frontend->>Project: POST /api/project/draft/save
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=resubmit
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
|
||||
else 超管直接修改
|
||||
Admin->>Frontend: 直接修改项目信息
|
||||
Frontend->>Project: POST /api/project/update
|
||||
Project->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=approve<br/>超管直接完成
|
||||
Workflow->>Workflow: 设置status=approved
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 工单步骤定义
|
||||
|
||||
| 步骤序号 | 步骤名称 | 步骤类型 | 处理人 | 操作说明 |
|
||||
|---------|---------|---------|-------|---------|
|
||||
| 1 | 分配填写人 | `assign` | 超级管理员 | 选择项目信息填写人 |
|
||||
| 2 | 填写项目信息 | `execute` | 被分配用户 | 填写项目详情,可保存草稿 |
|
||||
| 3 | 审核项目信息 | `approve` | 超级管理员 | 审批通过/打回 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 业务扩展字段
|
||||
|
||||
存储于 `project_detail_ext` 表:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|-----|------|------|
|
||||
| `project_id` | VARCHAR(64) | 关联项目ID |
|
||||
| `detail_filler_id` | BIGINT | 填写人ID |
|
||||
| `detail_filler_name` | VARCHAR(64) | 填写人姓名 |
|
||||
| `draft_data` | JSON | 草稿数据 |
|
||||
|
||||
### 6.1 draft_data 示例
|
||||
|
||||
```json
|
||||
{
|
||||
"deploy_business": {
|
||||
"deployer_name": "张三",
|
||||
"deployer_phone": "13800138000",
|
||||
"deploy_start_time": "2026-01-01",
|
||||
"system_version": "v3.2.0"
|
||||
},
|
||||
"deploy_env": {
|
||||
"network_type": "internal",
|
||||
"main_public_ip": "10.0.0.1",
|
||||
"host_count": 3
|
||||
},
|
||||
"deploy_middleware": {
|
||||
"mysql": {
|
||||
"internal_ip": "10.0.0.10",
|
||||
"internal_port": 3306
|
||||
}
|
||||
},
|
||||
"last_saved_at": "2026-01-08T10:30:00Z"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,234 @@
|
||||
# 用户管理工单流程
|
||||
|
||||
**工单类型代码**: `user_management`
|
||||
**来源模块**: rmdc-user-auth
|
||||
**编制日期**: 2026-01-08
|
||||
|
||||
---
|
||||
|
||||
## 1. 业务场景
|
||||
|
||||
非超级管理员用户对已注册用户进行管理操作(修改、删除、启用、禁用)时,需要经过超级管理员审批。
|
||||
|
||||
### 1.1 业务规则
|
||||
|
||||
| 规则项 | 说明 |
|
||||
|-------|------|
|
||||
| 发起人 | 管理员、普通用户(只能管理自己注册的用户) |
|
||||
| 默认处理人 | 超级管理员 |
|
||||
| 操作类型 | `modify`(修改)、`delete`(删除)、`enable`(启用)、`disable`(禁用) |
|
||||
| 可撤销 | 是(创建人可撤销) |
|
||||
| 可关闭 | 是(创建人可主动关闭) |
|
||||
|
||||
### 1.2 权限矩阵
|
||||
|
||||
| 操作人角色 | 可管理用户范围 |
|
||||
|-----------|--------------|
|
||||
| 超级管理员 | 所有用户(无需工单) |
|
||||
| 管理员 | 普通用户、三方用户(自己注册的) |
|
||||
| 普通用户 | 三方用户(自己注册的) |
|
||||
| 三方用户 | 无 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 状态机
|
||||
|
||||
### 2.1 状态定义
|
||||
|
||||
| 状态代码 | 状态名称 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `created` | 已创建 | 发起用户管理操作,工单创建 |
|
||||
| `pending_review` | 待审核 | 等待超级管理员审核 |
|
||||
| `approved` | 已通过 | 审核通过,管理操作已执行 |
|
||||
| `rejected` | 已拒绝 | 审核拒绝 |
|
||||
| `returned` | 已打回 | 打回修改 |
|
||||
| `revoked` | 已撤销 | 用户撤销管理操作 |
|
||||
| `closed` | 已关闭 | 工单生命周期结束 |
|
||||
|
||||
### 2.2 状态机图
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> created: 发起管理操作
|
||||
|
||||
created --> pending_review: 提交审核
|
||||
created --> revoked: 用户撤销
|
||||
created --> closed: 用户关闭
|
||||
|
||||
pending_review --> approved: 超管审批通过
|
||||
pending_review --> rejected: 超管审批拒绝
|
||||
pending_review --> returned: 超管打回
|
||||
pending_review --> revoked: 用户撤销(需确认)
|
||||
|
||||
returned --> pending_review: 重新提交
|
||||
returned --> revoked: 用户撤销
|
||||
returned --> closed: 用户关闭
|
||||
|
||||
rejected --> closed: 关闭工单
|
||||
approved --> closed: 关闭工单
|
||||
revoked --> closed: 关闭工单
|
||||
|
||||
closed --> [*]
|
||||
|
||||
note right of approved: 执行管理操作
|
||||
note right of closed: 退出用户编辑状态
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 流程图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> InitiateManage[发起用户管理操作]
|
||||
InitiateManage --> SelectAction{选择操作类型}
|
||||
|
||||
SelectAction -->|修改| ModifyAction[修改用户信息]
|
||||
SelectAction -->|删除| DeleteAction[删除用户]
|
||||
SelectAction -->|启用| EnableAction[启用用户]
|
||||
SelectAction -->|禁用| DisableAction[禁用用户]
|
||||
|
||||
ModifyAction --> CreateWorkflow[创建管理工单]
|
||||
DeleteAction --> CreateWorkflow
|
||||
EnableAction --> CreateWorkflow
|
||||
DisableAction --> CreateWorkflow
|
||||
|
||||
CreateWorkflow --> EnterEditMode[用户进入编辑状态]
|
||||
EnterEditMode --> SubmitReview[提交审核]
|
||||
|
||||
SubmitReview --> PendingReview{待审核}
|
||||
|
||||
PendingReview -->|审批通过| Approve[审批通过]
|
||||
PendingReview -->|审批拒绝| Reject[直接拒绝]
|
||||
PendingReview -->|打回| Return[打回修改]
|
||||
PendingReview -->|用户撤销| Revoke[撤销工单]
|
||||
|
||||
Approve --> ExecuteAction[执行管理操作]
|
||||
ExecuteAction --> UpdateDB[更新数据库]
|
||||
UpdateDB --> ExitEditMode1[退出编辑状态]
|
||||
ExitEditMode1 --> CloseApproved[关闭工单]
|
||||
CloseApproved --> End([结束])
|
||||
|
||||
Return --> UserModify{用户修改操作}
|
||||
UserModify -->|重新提交| SubmitReview
|
||||
UserModify -->|放弃操作| CloseFromReturn[关闭工单]
|
||||
|
||||
Reject --> ExitEditMode2[退出编辑状态]
|
||||
ExitEditMode2 --> ClosedRejected[关闭工单]
|
||||
ClosedRejected --> End
|
||||
|
||||
Revoke --> ExitEditMode3[退出编辑状态]
|
||||
ExitEditMode3 --> ClosedRevoked[关闭工单]
|
||||
ClosedRevoked --> End
|
||||
|
||||
CloseFromReturn --> ExitEditMode4[退出编辑状态]
|
||||
ExitEditMode4 --> End
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
|
||||
participant User as 管理人
|
||||
participant Frontend as 前端
|
||||
participant UserAuth as rmdc-user-auth
|
||||
participant Workflow as rmdc-work-procedure
|
||||
participant SuperAdmin as 超级管理员
|
||||
participant Notice as 通知中心
|
||||
|
||||
%% 发起管理操作
|
||||
User->>Frontend: 点击编辑/删除/启用/禁用
|
||||
Frontend->>UserAuth: 校验管理权限
|
||||
UserAuth-->>Frontend: 权限校验通过
|
||||
Frontend->>Workflow: POST /api/workflow/create
|
||||
Note over Workflow: 创建user_management工单<br/>保存original_data快照
|
||||
Workflow->>UserAuth: 标记用户进入编辑状态
|
||||
Workflow-->>Frontend: 工单创建成功
|
||||
Frontend-->>User: 进入编辑模式
|
||||
|
||||
%% 用户修改并提交
|
||||
User->>Frontend: 修改信息/确认操作
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=submit<br/>保存modified_data
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>SuperAdmin: 用户管理审批通知
|
||||
|
||||
%% 审批通过场景
|
||||
alt 审批通过
|
||||
SuperAdmin->>Frontend: 查看工单详情
|
||||
Frontend->>Workflow: POST /api/workflow/detail
|
||||
Workflow-->>Frontend: 返回工单信息+变更对比
|
||||
SuperAdmin->>Frontend: 点击通过
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=approve
|
||||
Workflow->>UserAuth: 回调执行管理操作
|
||||
UserAuth->>UserAuth: 根据action_type执行操作
|
||||
Workflow->>UserAuth: 清除用户编辑状态
|
||||
Workflow->>Workflow: 设置status=approved
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 管理操作已通过
|
||||
|
||||
%% 打回场景
|
||||
else 打回修改
|
||||
SuperAdmin->>Frontend: 点击打回
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=return<br/>附带修改意见
|
||||
Workflow->>Workflow: 设置status=returned
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 管理操作被打回
|
||||
|
||||
User->>Frontend: 根据意见修改
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=resubmit
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
|
||||
%% 用户关闭场景
|
||||
else 用户主动关闭
|
||||
User->>Frontend: 点击关闭工单
|
||||
Frontend->>Workflow: POST /api/workflow/close
|
||||
Workflow->>UserAuth: 清除用户编辑状态
|
||||
Workflow->>Workflow: 设置status=closed
|
||||
Note over Workflow: 放弃所有修改
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 工单步骤定义
|
||||
|
||||
| 步骤序号 | 步骤名称 | 步骤类型 | 处理人 | 操作说明 |
|
||||
|---------|---------|---------|-------|---------|
|
||||
| 1 | 提交管理操作 | `submit` | 创建人 | 提交管理操作审核 |
|
||||
| 2 | 审核管理操作 | `approve` | 超级管理员 | 审批通过/拒绝/打回 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 业务扩展字段
|
||||
|
||||
存储于 `user_management_ext` 表:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|-----|------|------|
|
||||
| `target_user_id` | BIGINT | 被管理用户ID |
|
||||
| `action_type` | VARCHAR(32) | 操作类型:modify/delete/enable/disable |
|
||||
| `original_data` | JSON | 变更前数据快照 |
|
||||
| `modified_data` | JSON | 期望变更数据 |
|
||||
|
||||
### 6.1 original_data / modified_data 示例
|
||||
|
||||
```json
|
||||
{
|
||||
"username": "zhangsan",
|
||||
"chinese_name": "张三",
|
||||
"email": "zhangsan@example.com",
|
||||
"phone": "13800138000",
|
||||
"group_name": "产品与解决方案组",
|
||||
"dev_role": "backend",
|
||||
"rmdc_role": "normal"
|
||||
}
|
||||
```
|
||||
@@ -0,0 +1,190 @@
|
||||
# 用户注册工单流程
|
||||
|
||||
**工单类型代码**: `user_registration`
|
||||
**来源模块**: rmdc-user-auth
|
||||
**编制日期**: 2026-01-08
|
||||
|
||||
---
|
||||
|
||||
## 1. 业务场景
|
||||
|
||||
非超级管理员用户注册新用户后,需要经过超级管理员审批才能激活用户账号。
|
||||
|
||||
### 1.1 业务规则
|
||||
|
||||
| 规则项 | 说明 |
|
||||
|-------|------|
|
||||
| 发起人 | 管理员、普通用户(根据权限可注册不同角色账号) |
|
||||
| 默认处理人 | 超级管理员 |
|
||||
| 被注册用户初始状态 | `disabled` |
|
||||
| 审批通过后用户状态 | `active` |
|
||||
| 可撤销 | 是(创建人可撤销) |
|
||||
| 撤销后处理 | 硬删除被注册用户 |
|
||||
|
||||
---
|
||||
|
||||
## 2. 状态机
|
||||
|
||||
### 2.1 状态定义
|
||||
|
||||
| 状态代码 | 状态名称 | 说明 |
|
||||
|---------|---------|------|
|
||||
| `created` | 已创建 | 用户注册完成,工单自动创建 |
|
||||
| `pending_review` | 待审核 | 等待超级管理员审核 |
|
||||
| `approved` | 已通过 | 审核通过,用户已激活 |
|
||||
| `rejected` | 已拒绝 | 审核拒绝,需重新修改 |
|
||||
| `revoked` | 已撤销 | 用户取消注册 |
|
||||
| `closed` | 已关闭 | 工单生命周期结束 |
|
||||
|
||||
### 2.2 状态机图
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> created: 用户注册
|
||||
|
||||
created --> pending_review: 自动提交审核
|
||||
created --> revoked: 用户撤销
|
||||
|
||||
pending_review --> approved: 超管审批通过
|
||||
pending_review --> rejected: 超管审批拒绝
|
||||
pending_review --> revoked: 用户撤销(需确认)
|
||||
|
||||
rejected --> pending_review: 用户修改后重新提交
|
||||
rejected --> revoked: 用户撤销
|
||||
|
||||
approved --> closed: 关闭工单
|
||||
rejected --> closed: 关闭工单
|
||||
revoked --> closed: 关闭工单
|
||||
|
||||
closed --> [*]
|
||||
|
||||
note right of approved: 自动激活用户
|
||||
note right of revoked: 硬删除用户
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 3. 流程图
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
Start([开始]) --> Register[用户注册新账号]
|
||||
Register --> CreateWorkflow[自动创建注册工单]
|
||||
CreateWorkflow --> SetDisabled[设置用户状态为disabled]
|
||||
SetDisabled --> AutoSubmit[自动提交给超级管理员]
|
||||
|
||||
AutoSubmit --> PendingReview{待审核}
|
||||
|
||||
PendingReview -->|审批通过| Approve[审批通过]
|
||||
PendingReview -->|审批拒绝| Reject[打回修改]
|
||||
PendingReview -->|用户撤销| RevokeConfirm{确认撤销?}
|
||||
|
||||
Approve --> ActivateUser[激活用户账号]
|
||||
ActivateUser --> CloseApproved[关闭工单]
|
||||
CloseApproved --> End([结束])
|
||||
|
||||
Reject --> UserModify{用户修改信息}
|
||||
UserModify -->|重新提交| AutoSubmit
|
||||
UserModify -->|放弃注册| RevokeFromReject[撤销工单]
|
||||
|
||||
RevokeConfirm -->|确认| Revoke[撤销工单]
|
||||
RevokeConfirm -->|取消| PendingReview
|
||||
|
||||
Revoke --> DeleteUser[硬删除用户]
|
||||
RevokeFromReject --> DeleteUser
|
||||
DeleteUser --> ClosedRevoked[关闭工单]
|
||||
ClosedRevoked --> RestartOption{一键重新创建?}
|
||||
|
||||
RestartOption -->|是| Register
|
||||
RestartOption -->|否| End
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 4. 时序图
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
autonumber
|
||||
|
||||
participant User as 注册人
|
||||
participant Frontend as 前端
|
||||
participant UserAuth as rmdc-user-auth
|
||||
participant Workflow as rmdc-work-procedure
|
||||
participant SuperAdmin as 超级管理员
|
||||
participant Notice as 通知中心
|
||||
|
||||
%% 用户注册阶段
|
||||
User->>Frontend: 填写注册表单
|
||||
Frontend->>UserAuth: POST /api/user/register
|
||||
UserAuth->>UserAuth: 创建用户(status=disabled)
|
||||
UserAuth->>Workflow: POST /api/workflow/create
|
||||
Note over Workflow: 创建user_registration工单
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>SuperAdmin: 新用户注册审批通知
|
||||
UserAuth-->>Frontend: 注册成功,待审批
|
||||
Frontend-->>User: 显示等待审批状态
|
||||
|
||||
%% 审批通过场景
|
||||
alt 审批通过
|
||||
SuperAdmin->>Frontend: 查看工单详情
|
||||
Frontend->>Workflow: POST /api/workflow/detail
|
||||
Workflow-->>Frontend: 返回工单信息
|
||||
SuperAdmin->>Frontend: 点击通过
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=approve
|
||||
Workflow->>UserAuth: 回调更新用户状态
|
||||
UserAuth->>UserAuth: 更新status=active
|
||||
Workflow->>Workflow: 设置status=approved
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 注册已通过通知
|
||||
|
||||
%% 审批拒绝场景
|
||||
else 审批拒绝
|
||||
SuperAdmin->>Frontend: 点击拒绝
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=reject
|
||||
Workflow->>Workflow: 设置status=rejected
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>User: 注册被拒绝通知
|
||||
|
||||
%% 用户重新提交
|
||||
User->>Frontend: 修改注册信息
|
||||
Frontend->>UserAuth: POST /api/user/update
|
||||
Frontend->>Workflow: POST /api/workflow/transition
|
||||
Note over Workflow: event=resubmit
|
||||
Workflow->>Workflow: 设置status=pending_review
|
||||
Workflow->>Notice: 推送通知
|
||||
Notice-->>SuperAdmin: 重新提交审批通知
|
||||
|
||||
%% 用户撤销场景
|
||||
else 用户撤销
|
||||
User->>Frontend: 点击撤销注册
|
||||
Frontend->>Workflow: POST /api/workflow/revoke
|
||||
Workflow->>Workflow: 设置status=revoked
|
||||
Workflow->>UserAuth: 回调删除用户
|
||||
UserAuth->>UserAuth: 硬删除用户记录
|
||||
Workflow->>Workflow: 设置status=closed
|
||||
end
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 工单步骤定义
|
||||
|
||||
| 步骤序号 | 步骤名称 | 步骤类型 | 处理人 | 操作说明 |
|
||||
|---------|---------|---------|-------|---------|
|
||||
| 1 | 提交注册 | `submit` | 系统自动 | 用户注册后自动提交审核 |
|
||||
| 2 | 审核注册 | `approve` | 超级管理员 | 审批通过/拒绝/打回 |
|
||||
|
||||
---
|
||||
|
||||
## 6. 业务扩展字段
|
||||
|
||||
存储于 `user_registration_ext` 表:
|
||||
|
||||
| 字段 | 类型 | 说明 |
|
||||
|-----|------|------|
|
||||
| `target_user_id` | BIGINT | 被注册用户ID |
|
||||
| `original_status` | VARCHAR(32) | 原用户状态(备份) |
|
||||
121
8-CMII-RMDC/8-rmdc-monitor-center/9-user-contact-list.md
Normal file
121
8-CMII-RMDC/8-rmdc-monitor-center/9-user-contact-list.md
Normal file
@@ -0,0 +1,121 @@
|
||||
| 序号 | 姓名 | 工号 | 手机 | 短号 | 邮箱 | 所属小组 |
|
||||
| :--- | :--- | :--- | :--- | :--- | :--- | :--- |
|
||||
| 1 | 周剑 | E0003260015 | 13980000043 | 63802 | zhoujian@cmii.chinamobile.com | 低空经济技术研发运营中心 |
|
||||
| 2 | 李天扬 | E1000119593 | 18200367441 | | litianyang@cmii.chinamobile.com | 低空经济技术研发运营中心 |
|
||||
| 3 | 陈灵美 | E1000119592 | 18884838475 | | chenlingmei@cmii.chinamobile.com | 低空经济技术研发运营中心 |
|
||||
| 4 | 杨子仪 | E1000119468 | 17336343307 | | yangziyi@cmii.chinamobile.com | 低空经济技术研发运营中心 |
|
||||
| 5 | 马建均 | E0003260135 | 18802881983 | 65125 | majianjun@cmii.chinamobile.com | 低空经济技术研发运营中心 |
|
||||
| 6 | 彭国宇 | E1000120189 | 13648063032 | | pengguoyu@cmii.chinamobile.com | 低空经济技术研发运营中心 |
|
||||
| 7 | 韩雨亭 | E1000039626 | 18802880189 | 63810 | hanyuting@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 8 | 张震 | E0003260280 | 18802880227 | 63811 | zhangzhen@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 9 | 黄佳伟 | E1000039533 | 18802880662 | 63824 | huangjiawei@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 10 | 杨瑶 | E1000047533 | 18428381971 | 63822 | yangyao01@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 11 | 刘子扬 | E0003260069 | 18802880817 | 63887 | liuziyang@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 12 | 张淼 | E1000000251 | 18782209849 | 63860 | zhangmiao@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 13 | 徐源林 | E1000041972 | 18382354080 | 63888 | xuyuanlin@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 14 | 何博 | E1000094217 | 13550064201 | 63955 | hebo@cmii.chinamoble.com | 产品与解决方案组 |
|
||||
| 15 | 严朝阳 | E1000041760 | 18802881969 | 65691 | yanchaoyang@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 16 | 童钰辉 | E1000088894 | 18802880389 | 63914 | tongyuhui@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 17 | 刘庭璇 | E1000039627 | 18428359971 | 63932 | liutingxuan@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 18 | 郭忠勇 | E1000042092 | 18224071422 | 63895 | guozhongyong@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 19 | 黄知齐 | E1000111665 | 18380104927 | 63929 | huangzhiqi@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 20 | 傅军 | E1000029753 | 15208325190 | 63842 | fujun@cmii.chinamobile.com | 产品与解决方案组 |
|
||||
| 21 | 牛锐 | E0003811308 | 13910388292 | | niurui@cmii.chinamobile.com | 战略组 |
|
||||
| 22 | 程倩倩 | E1000047233 | 18802880930 | 63865 | chengqianqian@cmii.chinamobile.com | 战略组 |
|
||||
| 23 | 林汲 | E1000094622 | 18884817362 | 63920 | linji@cmii.chinamobile.com | 战略组 |
|
||||
| 24 | 兰盾 | E0003260413 | 13808205185 | 63805 | landun@cmii.chinamobile.com | 监管军团 |
|
||||
| 25 | 唐兵 | E0003260554 | 18202806037 | 63876 | tangbing@cmii.chinamobile.com | 监管军团 |
|
||||
| 26 | 邓玖根 | E1000047135 | 15208489298 | 63877 | dengjiugen@cmii.chinamobile.com | 监管军团 |
|
||||
| 27 | 刘家琛 | E1000093002 | 18215599792 | 63917 | liujiachen@cmii.chinamobile.com | 监管军团 |
|
||||
| 28 | 陈宽 | E1000112978 | 19982088679 | 63931 | chenkuan@cmii.chinamobile.com | 监管军团 |
|
||||
| 29 | 徐晓东 | E0038015091 | 13708024468 | 63892 | xuxiaodong@cmii.chinamobile.com | 监管军团 |
|
||||
| 30 | 李航宇 | E0038009499 | 15881102865 | 63834 | lihangyu@cmii.chinamobile.com | 监管军团 |
|
||||
| 31 | 黄益 | E0003260227 | 18244215251 | 63894 | huangyi01@cmii.chinamobile.com | 监管军团 |
|
||||
| 32 | 张愉菲 | E1000092739 | 18280136310 | 63915 | zhangyufei@cmii.chinamobile.com | 监管军团 |
|
||||
| 33 | 郑文龙 | E1000047230 | 13890436063 | 63878 | zhengwenlong@cmii.chinamobile.com | 监管军团 |
|
||||
| 34 | 何孝游 | E1000041675 | 18380417399 | 63836 | hexiaoyou@cmii.chinamobile.com | 监管军团 |
|
||||
| 35 | 王历 | E1000050130 | 18802881952 | 63875 | wangli02@cmii.chinamobile.com | 监管军团 |
|
||||
| 36 | 彭璐 | E1000030112 | 13688161465 | 63806 | penglu@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 37 | 成均保 | E0003260372 | 18802881118 | 63815 | chengjunbao@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 38 | 管泽鑫 | E1000048417 | 18802881168 | 63882 | guanzexin@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 39 | 左莹莹 | E0003260324 | 18802881112 | 63812 | zuoyingying@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 40 | 王艺霖 | E1000047239 | 18408218668 | 63813 | wangyilin@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 41 | 孔祥 | E1000046205 | 18628265601 | 63884 | kongxiang@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 42 | 李垚 | E1000044408 | 18200532206 | 63883 | liyao@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 43 | 向昱佼 | E0003260048 | 18802880204 | 63885 | xiangyujiao@cmii.chinamobile.com | 创新研究与应用组(PMO) |
|
||||
| 44 | 邱裕鹤 | E0003260241 | 18802880201 | 63803 | qiuyuhe@cmii.chinamobile.com | 云平台系统组 |
|
||||
| 45 | 任一珂 | E1000000224 | 13558770317 | 63833 | renyike@cmii.chinamobile.com | 监视控制组 |
|
||||
| 46 | 吴云江 | E1000029758 | 13679007674 | 63880 | wuyunjiang@cmii.chinamobile.com | 监视控制组 |
|
||||
| 47 | 李煜寒 | E1000041015 | 18802880525 | 63839 | liyuhan@cmii.chinamobile.com | 监视控制组 |
|
||||
| 48 | 王少飞 | E1000042202 | 13438837100 | 63840 | wangshaofei@cmii.chinamobile.com | 监视控制组 |
|
||||
| 49 | 王义元 | E1000042204 | 18802881214 | 63879 | wangyiyuan@cmii.chinamobile.com | 监视控制组 |
|
||||
| 50 | 袁雪波 | E1000030093 | 15281059786 | 63862 | yuanxuebo@cmii.chinamobile.com | 监视控制组 |
|
||||
| 51 | 张聪 | E0003260142 | 18802881839 | 63818 | zhangcong@cmii.chinamobile.com | 监视控制组 |
|
||||
| 52 | 王子文 | E1000047232 | 18802881074 | 63864 | wangziwen@cmii.chinamobile.com | 监视控制组 |
|
||||
| 53 | 罗瑞 | E0003260343 | 18802881217 | 63816 | luorui@cmii.chinamobile.com | 监视控制组 |
|
||||
| 54 | 李松 | E1000000485 | 15882223415 | 63912 | lisong@cmii.chinamobile.com | 监视控制组 |
|
||||
| 55 | 王清 | E1000000225 | 18215575866 | 63858 | wangqing@cmii.chinamobile.com | 智能云网组 |
|
||||
| 56 | 刘喜 | E0003260164 | 15828477091 | 63866 | liuxi@cmii.chinamobile.com | 智能云网组 |
|
||||
| 57 | 何虎 | E1000049890 | 13308059662 | 63841 | hehu@cmii.chinamobile.com | 智能云网组 |
|
||||
| 58 | 罗文 | E1000039988 | 18780009301 | 63846 | luowen@cmii.chinamobile.com | 智能云网组 |
|
||||
| 59 | 唐志梁 | E1000049663 | 18802880517 | 63847 | tangzhiliang@cmii.chinamobile.com | 智能云网组 |
|
||||
| 60 | 钟林林 | E1000029771 | 15208192232 | 63844 | zhonglinlin@cmii.chinamobile.com | 智能云网组 |
|
||||
| 61 | 胡宝顺 | E1000040553 | 15928589640 | 63835 | hubaoshun@cmii.chinamobile.com | 智能云网组 |
|
||||
| 62 | 郝昊 | E1000109766 | 14708066381 | 63927 | haohao@cmii.chinamobile.com | 智能云网组 |
|
||||
| 63 | 张雅洁 | E0003260313 | 18802880806 | 63820 | zhangyajie@cmii.chinamobile.com | 智能云网组 |
|
||||
| 64 | 龙卫 | E1000036080 | 18280096573 | 63838 | longwei@cmii.chinamobile.com | 智能云网组 |
|
||||
| 65 | 冉靖 | E1000103347 | 13540664346 | 63924 | ranjing@cmii.chinamobile.com | 智能云网组 |
|
||||
| 66 | 张睿婧 | E1000103348 | 13689066043 | 63923 | zhangruijing@cmii.chinamobile.com | 智能云网组 |
|
||||
| 67 | 郑岩 | E1000108860 | 18328603976 | 63928 | zhengyan@cmii.chinamobile.com | 智能云网组 |
|
||||
| 68 | 刘芸志 | E1000030098 | 18802881811 | 63825 | liuyunzhi@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 69 | 谭雪敏 | E1000050960 | 13488938986 | 63826 | tanxuemin@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 70 | 王雄飞 | E1000036084 | 15108281409 | 63827 | wangxiongfei@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 71 | 罗婷婷 | E1000030087 | 18802880413 | 63828 | luotingting@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 72 | 李佩哲 | E1000036085 | 18328088043 | 63829 | lipeizhe@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 73 | 杨淳婷 | E0003260183 | 18802880215 | 63830 | yangchunting@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 74 | 李贞 | E0003260187 | 18384166196 | 63831 | lizhen@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 75 | 朱君妍 | E1000049635 | 13980501129 | 63821 | zhujunyan@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 76 | 梁运珠 | E1000049209 | 18200259225 | 63859 | liangyunzhu@cmii.chinamobile.com | 视觉交互组 |
|
||||
| 77 | 汪珂丽 | E1000088899 | 18810909875 | | wangkeli@cmii.chinamobile.com | 空域计算组 |
|
||||
| 78 | 秦正 | E1000029111 | 18802880226 | 63849 | qinzheng@cmii.chinamobile.com | 空域计算组 |
|
||||
| 79 | 周金福 | E0003260323 | 18224495673 | 63855 | zhoujinfu@cmii.chinamobile.com | 空域计算组 |
|
||||
| 80 | 张艾 | E1000029770 | 15208206929 | 63843 | zhangai@cmii.chinamobile.com | 空域计算组 |
|
||||
| 81 | 李志杨 | E1000036309 | 18628380221 | 63845 | lizhiyang@cmii.chinamobile.com | 空域计算组 |
|
||||
| 82 | 杨云猇 | E1000041171 | 13550397849 | 63848 | yangyunxiao@cmii.chinamobile.com | 空域计算组 |
|
||||
| 83 | 赵子瑶 | E0003260332 | 18802880615 | 63817 | zhaoziyao@cmii.chinamobile.com | 空域计算组 |
|
||||
| 84 | 刘晨虹 | E1000103357 | 19827801957 | 63922 | liuchenhong@cmii.chinamobile.com | 空域计算组 |
|
||||
| 85 | 黄滟茹 | E1000103362 | 13693498572 | 63925 | huangyanru@cmii.chinamobile.com | 空域计算组 |
|
||||
| 86 | 杨文彬 | E1000084157 | 15216616583 | 63916 | yangwenbin@cmii.chinamobile.com | 空域计算组 |
|
||||
| 87 | 吴庆洲 | E1000048906 | 13880168124 | 63850 | wuqingzhou@cmii.chinamobile.com | Al+能力组 |
|
||||
| 88 | 崔诚煜 | E1000047244 | 17358568202 | 63851 | cuichengyu@cmii.chinamobile.com | Al+能力组 |
|
||||
| 89 | 段亚康 | E1000041886 | 18802881205 | 63853 | duanyakang@cmii.chinamobile.com | Al+能力组 |
|
||||
| 90 | 米俊桦 | E1000047236 | 18780275860 | 63856 | mijunhua@cmii.chinamobile.com | Al+能力组 |
|
||||
| 91 | 王玲玉 | E1000048430 | 18802880318 | 63857 | wanglingyu@cmii.chinamobile.com | Al+能力组 |
|
||||
| 92 | 王水介 | E1000041170 | 18215623760 | 63837 | wangshuijie@cmii.chinamobile.com | Al+能力组 |
|
||||
| 93 | 陈盛伟 | E0003260259 | 13730884296 | 63804 | chenshengwei@cmii.chinamobile.com | 应急军团 |
|
||||
| 94 | 张雷 | E1000045186 | 13568880613 | 63867 | zhanglei@cmii.chinamobile.com | 应急军团 |
|
||||
| 95 | 阳煦平 | E1000026734 | 18802880109 | 63869 | yangxuping@cmii.chinamobile.com | 应急军团 |
|
||||
| 96 | 谭倩 | E1000040200 | 15198157192 | 63873 | tanqian@cmii.chinamobile.com | 应急军团 |
|
||||
| 97 | 王文靖 | E0003260163 | 18802881201 | 63870 | wangwenjing@cmii.chinamobile.com | 应急军团 |
|
||||
| 98 | 李帆 | E1000047536 | 15008406387 | 63872 | lifan01@cmii.chinamobile.com | 应急军团 |
|
||||
| 99 | 曾辉 | E1000049874 | 18382023722 | 63871 | zenghui@cmii.chinamobile.com | 应急军团 |
|
||||
| 100 | 刘东 | E0003260050 | 13981766521 | 63808 | liudong@cmii.chinamobile.com | 应急军团 |
|
||||
| 101 | 李爽 | E1000029110 | 18683782070 | 63874 | lishuang@cmii.chinamobile.com | 应急军团 |
|
||||
| 102 | 杨光平 | E1000000252 | 13881748089 | 63868 | yangguangping@cmii.chinamobile.com | 应急军团 |
|
||||
| 103 | 袁嵩 | E1000093977 | 18802880885 | 63919 | yuansong@cmii.chinamobile.com | 应急军团 |
|
||||
| 104 | 蔡为 | E1000026733 | 18802881450 | 63898 | caiwei@cmii.chinamobile.com | 应急军团 |
|
||||
| 105 | 陶科翔 | E0038037028 | 13909008628 | 63890 | taokexiang@cmii.chinamobile.com | 行业组南区 |
|
||||
| 106 | 刘桓良 | E0038016245 | 13540246242 | 63893 | liuhuanliang@cmii.chinamobile.com | 行业组南区 |
|
||||
| 107 | 刘绍坤 | E0003901279 | 15828665201 | 63823 | liushaokun@cmii.chinamobile.com | 行业组南区 |
|
||||
| 108 | 张杨 | E0003260053 | 13880606478 | 63809 | zhangyang@cmii.chinamobile.com | 行业组南区 |
|
||||
| 109 | 卢禹杉 | E0003260398 | 18802881163 | 63889 | luyushan@cmii.chinamobile.com | 行业组南区 |
|
||||
| 110 | 邹安洋 | E0003260149 | 15802893337 | 63891 | zouanyang@cmii.chinamobile.com | 行业组南区 |
|
||||
| 111 | 闫少普 | E0003260162 | 18802881206 | 63886 | yanshaopu@cmii.chinamobile.com | 行业组南区 |
|
||||
| 112 | 王佳章 | E1000047237 | 18802880882 | 63881 | wangjiazhang@cmii.chinamobile.com | 行业组南区 |
|
||||
| 113 | 刘长杰 | E0003260049 | 13608177983 | 63807 | liuchangjie@cmii.chinamobile.com | 行业组北区 |
|
||||
| 114 | 何源 | E0003260064 | 13666181777 | 63911 | heyuan@cmii.chinamobile.com | 行业组北区 |
|
||||
| 115 | 覃小龙 | E0003260166 | 18802880145 | 63897 | qinxiaolong@cmii.chinamobile.com | 行业组北区 |
|
||||
| 116 | 陈一溶 | E1000064296 | 15008491662 | 63930 | chenyirong@cmii.chinamobile.com | 行业组北区 |
|
||||
| 117 | 唐飞 | E0003260158 | 18802880112 | 63899 | tangfei@cmii.chinamobile.com | 行业组北区 |
|
||||
| 118 | 杨尧 | E0003260193 | 18802881998 | 63814 | yangyao@cmii.chinamobile.com | 行业组北区 |
|
||||
| 119 | 贾金岩 | E0003260263 | 18802880610 | 63863 | jiajinyan@cmii.chinamobile.com | 行业组北区 |
|
||||
@@ -0,0 +1,76 @@
|
||||
# 用户权限控制逻辑与验证步骤
|
||||
|
||||
## 权限控制逻辑
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
A[用户发起注册] --> B{检查操作人角色}
|
||||
B -->|超级管理员| C[直接创建用户 - 状态 active]
|
||||
B -->|管理员| D{目标角色}
|
||||
B -->|普通用户| E{目标角色}
|
||||
B -->|三方用户| F[拒绝 - 无权限]
|
||||
|
||||
D -->|normal/third| G[创建用户 - 状态 disabled<br/>创建工单等待审批]
|
||||
D -->|其他| F
|
||||
|
||||
E -->|third| G
|
||||
E -->|其他| F
|
||||
|
||||
G --> H[超级管理员审批]
|
||||
H -->|通过| I[用户状态改为 active]
|
||||
H -->|拒绝| J[用户保持 disabled]
|
||||
```
|
||||
|
||||
## 验证步骤
|
||||
|
||||
### 1. 用户注册工单测试
|
||||
|
||||
1. 使用 **非超级管理员** (如 admin 或 normal 用户) 登录。
|
||||
2. 对于 **Normal 用户**:
|
||||
- 侧边栏点击 **用户管理**。
|
||||
- 点击 **新建用户**,应跳转到 `/user/register-user`。
|
||||
- 提交注册后,应跳转到 `/user/workflows` (我的工单)。
|
||||
3. 对于 **Admin 用户**:
|
||||
- 进入 **系统管理 -> 用户管理**。
|
||||
- 点击 **新建用户**,应跳转到 `/admin/users/register`。
|
||||
- 提交注册后,应跳转到 `/admin/workflows` (工单管理)。
|
||||
4. 填写注册信息,点击提交。
|
||||
- 预期:提示“注册申请已提交”,不直接创建可用用户。
|
||||
5. 切换为 **超级管理员** (superadmin) 登录。
|
||||
6. 进入 **我的工单** 或工单管理页面,查看待审批的注册工单。
|
||||
7. 点击工单详情,查看注册信息是否正确显示。
|
||||
8. 审批通过工单。
|
||||
- 预期:工单状态变为 Approved,用户状态变为 active。
|
||||
9. 在用户管理列表中验证新用户已存在且为激活状态。
|
||||
|
||||
### 2. 用户广场与管理功能测试
|
||||
|
||||
1. **用户广场 (User Square)**
|
||||
- 登录普通用户。
|
||||
- 侧边栏点击 **用户广场** (替代原通讯录)。
|
||||
- 验证页面展示是否类似项目列表(支持卡片/表格切换)。
|
||||
- 验证搜索和筛选功能是否正常。
|
||||
- 验证点击用户仅弹出详情,**无**编辑/删除按钮。
|
||||
- **数据验证**:应能看到所有 active 用户(包括其他管理员创建的),但看不到 active 以外的用户。
|
||||
|
||||
2. **用户管理 (User Management)**
|
||||
- 侧边栏点击 **用户管理**。
|
||||
- **普通用户**:验证只能看到 **自己创建的** 用户(包括待审核、已禁用等状态)。不能看到别人创建的用户。
|
||||
- **管理员**:验证能看到所有用户。
|
||||
- 验证 **编辑/删除** 按钮是否出现,并能正常触发工单流程。
|
||||
|
||||
3. **用户注册 (User Registration)**
|
||||
- 侧边栏点击 **用户管理 -> 新建用户**(或通过路由 `/user/register-user`)。
|
||||
- 验证是否进入注册页面。
|
||||
|
||||
### 3. 用户管理工单测试
|
||||
|
||||
1. 使用 **管理员** (admin) 登录。
|
||||
2. 在 **用户管理** 列表中,对一个 **普通用户** (normal) 或 **三方用户** (third) 进行编辑。
|
||||
3. 修改信息并填写 **变更理由**,点击更新。
|
||||
- 预期:提示“修改申请已提交”。
|
||||
4. 对同一用户点击 **删除** 按钮,填写 **删除理由**,点击确认。
|
||||
- 预期:提示“删除申请已提交”。
|
||||
5. 切换为 **超级管理员** (superadmin) 登录。
|
||||
6. 查看相应的管理工单,审批通过。
|
||||
7. 验证用户信息已更新或用户已被删除。
|
||||
112
8-CMII-RMDC/9-rmdc-user-auth/1-user-auth-DDS.md
Normal file
112
8-CMII-RMDC/9-rmdc-user-auth/1-user-auth-DDS.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# 用户认证模块
|
||||
|
||||
## 用户体系
|
||||
### 项目初始化数据
|
||||
1. [公司通信录](0-设计方案\9-rmdc-user-auth\9-user-contact-list.md)应该作为项目数据库初始化的数据导入到数据库中
|
||||
|
||||
|
||||
### 用户结构体
|
||||
1. 用户ID
|
||||
2. 用户中文名 必须要真实姓名
|
||||
1. 默认为[公司通信录]中的姓名
|
||||
3. 用户英文名 也是昵称 可以为任意
|
||||
1. 默认为[公司通信录]中邮箱去除掉@之后的部分
|
||||
4. 用户头像ID avatar_id
|
||||
5. 用户头像框ID avatar_frame_id
|
||||
6. 性别 gender
|
||||
7. 电子邮箱
|
||||
8. 手机号
|
||||
9. 短号
|
||||
10. 工号 work_id
|
||||
11. 所属小组 group_name 产品与解决方案组
|
||||
12. 状态 user_status active, locked, disabled 默认为 locked 删除为 disabled
|
||||
13. 注册人ID registered_by_id 被谁注册的
|
||||
14. 密码 需要保存的是加密后的密码 默认值是 supercyy.1加密后的hash值
|
||||
15. 密码过期时间 password_expires_at
|
||||
16. 开发角色 dev_role 后端开发 backend, 前端开发 frontend, 测试工程师 test, 全干工程师 ops, 行业解决方案专家 seller, 未知 unknown 默认为 unknown
|
||||
17. RMDC系统角色 rmdc_role 超级管理员,管理员,普通用户,三方用户 superadmin, admin, normal, third 默认为normal
|
||||
18. 注册时间
|
||||
19. 更新时间
|
||||
20. 删除时间(设置为disabled的时间)
|
||||
|
||||
## 页面功能
|
||||
### 用户管理
|
||||
1. 只有超级管理员具有此页面的权限
|
||||
1. 管理用户的信息
|
||||
1. 新增用户
|
||||
2. 修改用户信息
|
||||
3. 删除用户
|
||||
4. 启用注册用户
|
||||
2. 开启注册权限
|
||||
1. 开放自己注册的功能
|
||||
2. 用户自行注册之后的状态默认是 locked
|
||||
|
||||
### 通信录页面
|
||||
1. normal用户及以上具有通信录页面的权限
|
||||
2. 展示部分用户的信息,方便联系其他的用户
|
||||
3. 默认使用列表的形式展示,点击用户之后可以查看用户详细信息
|
||||
4. 前端支持搜索,支持通过用户中文名,英文名 手机号 短号 快速搜索到用户
|
||||
|
||||
## 认证体系
|
||||
1. 用户使用默认密码登录之后, 强制要求修改密码
|
||||
2. 用户的密码有效期为3个月,过期需要强制修改密码
|
||||
3. 前端和后端之间密码的传输不能是明文的,需要进行RSA加密传输
|
||||
4. RMDC后端项目启动之后,需要创建一个RSA密钥对,并保存到数据库中
|
||||
1. RSA密钥对的有效期应该设置为30天,启动之后应该解析密钥对,并保存到内存中
|
||||
2. 如果密钥对过期,需要重新创建密钥对,并保存到数据库中
|
||||
5. 前端登录需要调用后端获取RSA公钥,然后使用公钥加密密码,再将加密后的密码发送给后端
|
||||
6. 后端接收到加密后的密码之后,使用自己的私钥解密密码,然后进行密码验证
|
||||
|
||||
## 授权体系
|
||||
1. 各个模块的授权均应该放置在此模块中进行
|
||||
|
||||
## 用户注册、管理功能
|
||||
2026年1月8日 结合工单系统,开发非超级管理员账号的注册功能
|
||||
|
||||
### 用户注册、管理权限
|
||||
1. RMDC角色为管理员的用户
|
||||
1. 可以注册、管理(修改信息、启用、禁用、删除)普通用户权限的账户
|
||||
2. 可以注册、管理(修改信息、启用、禁用、删除)三方用户权限的账户
|
||||
2. RMDC角色为普通用户的用户
|
||||
1. 只能注册三方用户权限的账户
|
||||
2. 不能注册普通用户权限的账户
|
||||
3. 只能管理(修改信息、启用、禁用、删除)自己注册的三方用户权限的账户
|
||||
3. RMDC角色为三方用户的用户
|
||||
1. 不能注册任何权限的账户
|
||||
2. 不能管理(修改信息、启用、禁用、删除)任何用户权限的账户
|
||||
4. RMDC角色为超级管理员的用户
|
||||
1. 可以注册任何权限的账户
|
||||
2. 可以管理(修改信息、启用、禁用、删除)任何用户权限的账户
|
||||
5. 用户管理的原则为:谁注册谁管理
|
||||
1. 用户管理页面的功能
|
||||
2. 注册用户的注册人负责管理被注册用户的生命周期
|
||||
3. 超级管理员负责审核所有用户注册的工单
|
||||
|
||||
### 用户注册工单流程
|
||||
1. 非超级管理员用户的在用户注册之后
|
||||
1. 用户状态默认为disabled
|
||||
2. 启动用户注册工单流程
|
||||
1. 自动创建用户注册工单
|
||||
2. 自动提交给超级管理员
|
||||
3. 超级管理员审核
|
||||
1. 审核通过
|
||||
1. 自动修改用户状态为 active, 用户启用
|
||||
2. 审核不通过
|
||||
1. 回退到用户注册阶段
|
||||
|
||||
### 用户管理工单流程
|
||||
1. 非超级管理员用户的在用户管理之后
|
||||
2. 启动用户管理工单流程
|
||||
1. 自动创建用户管理工单
|
||||
2. 自动提交给超级管理员
|
||||
3. 超级管理员审核
|
||||
1. 审核通过
|
||||
1. 根据管理的内容,修改用户相应的信息
|
||||
2. 审核不通过
|
||||
1. 回退到用户管理阶段
|
||||
|
||||
### 用户注册页面
|
||||
1. 请基于管理用户注册页面进行开发
|
||||
2. 设计的更加好看
|
||||
|
||||
|
||||
Reference in New Issue
Block a user