Phase 0+1+2 续: 项目骨架 + 配置 + 日志 + 存储层

Phase 0 (项目骨架):
- main.go 改为最小骨架 (config + logging + gin + /healthz + 优雅退出)
- internal/{config,logging,storage,cluster,...}/ 目录占位

Phase 1 (配置 + 日志):
- internal/config: env 解析 + 必填校验 + token 隐藏的 String()
- internal/logging: slog multi-handler 双输出 (终端 text + 主文件 JSON)
  + StartToolCall per-tool 独立文件 (0600), tools 目录 0700

Phase 2 续 (存储层):
- internal/cluster: 16 字段 Cluster struct (AuthPassword json:"-")
- internal/storage: modernc.org/sqlite 接入, WAL 模式, schema 自动迁移
- ClusterRepo CRUD: Create/Get/List/Update/Delete + ErrNotFound
  + AuthPassword 空字符串 = 保留旧密码 (核心约定)
- 7 个单元测试全绿 (:memory: DB)
- created_at/updated_at 改纳秒精度, 消除 List 测试的 sleep 特殊 case

Co-Authored-By: Claude <noreply@anthropic.com>
This commit is contained in:
tao.chen
2026-07-10 12:12:53 +08:00
co-authored by Claude
parent 1dfef0f598
commit a4e2472716
15 changed files with 2648 additions and 15 deletions
+143
View File
@@ -0,0 +1,143 @@
# Progress Log
> 会话日志,记录本项目所有重要进展
---
## 2026-07-10
### Session 1: 初始化 + 架构评审 + 计划编写
**参与**: User + Claude (Linus persona)
#### 进展
1. **仓库状态确认** (1dfef0f init)
- 单 init 提交,只有 GoLand 模板 main.go
- go.mod 已 pin 所有依赖(全是 // indirect)
- 没有任何业务代码、测试、文档
2. **创建 CLAUDE.md**
- 记录项目当前状态
- 列出标准 Go 命令
- 标注 4 个待确认决策
3. **用户提出初版架构方案** (v0.1)
- 5 个 Tool (spark_submit_cli / yarn_manage_job / fetch_spark_metrics / fetch_cluster_env / analyze_spark_log)
- Gin + MongoDB + MCP
- 3 个"底层元工具" (fetch_url / exec_shell / upload_file)
4. **Linus 视角评审** (3 个核心问题)
- **存储选型矛盾**: 文档说 SQLite,go.mod pin MongoDB,.gitignore 还有 data/ → 三选一
- **元工具归属不清**: 内部 Go / 暴露给 LLM / 外部 MCP Server,三种选择对应不同 API
- **Tool 粒度过细**: 5 个 Tool 里 3 个本质是 GET <URL>;analyze_spark_log 混了"抓"和"分析"
- **示例代码 API 不存在**: server.NewStreamableHTTPServer 等在 mcp-go v0.56.0 不存在
5. **用户回答 4 个关键决策** (v0.1 → v0.2)
- 存储: **SQLite** (替换 MongoDB)
- Spark 能力: **纯 RM/SHS 读模式** (不提供 spark-submit)
- MCP 传输: **Streamable HTTP**
- Tool 表面: **list_clusters + yarn_job_manage + fetch_url + upload_file** (4 个 Tool,不暴露 exec_shell)
6. **v0.2 计划编写**
- `task_plan.md` v0.2 — 7 个阶段,30+ 任务
- `findings.md` — 调研发现、风险分析
- `progress.md` (本文件)
7. **范围变更** (v0.2 → v0.3) — 用户中途修正
- **澄清**: `upload_file` 用途是 **spark-submit 时的 python 脚本上传**
- **冲突**: 与"纯 RM/SHS 不支持提交"决策矛盾
- **解决**: 用户确认**加 spark_submit** (使用 spark-submit shell 命令直接提交,在 admin 后台配置 binary 路径)
- **`upload_file` 重新定义**: 从"通用 HTTP 上传"改为"本地文件存储" (LLM 提交 content,Server 写到 `./data/`,返回路径)
- **Cluster 配置新增**: 单一 `spark_submit_execute_bin` (v0.3.1 进一步合并 spark_submit_path + spark2_submit_path)
- **Tool 总数**: 4 → **5** (重新引入 `spark_submit`)
8. **v0.3 计划更新**
- `task_plan.md` 重写,加入 `spark_submit` Tool 详细设计
- `findings.md` 更新: 新增命令注入风险、v0.3 范围变更章节
- 风险矩阵更新
- 决策日志新增 4 条 v0.3 决策
9. **v0.3.1 进一步合并**`spark_submit_path` + `spark2_submit_path``spark_submit_execute_bin` 单一字段
10. **v0.3.2 强化发现入口**`list_clusters` 标为强制入口,Cluster 加 `is_active`
11. **v0.3.3 加回高层 Tool**`fetch_spark_metrics` + `fetch_cluster_env`(内部调 `fetch_url`)
12. **v0.3.4 加回规则引擎**`analyze_spark_log` + 启发式过滤 (data_skew / gc_pressure / bottleneck) + LLM-Ready Prompt。新增 `internal/analyzer/` 包。Tool 总数 5 → **8**
13. **v0.3.5 大改**(用户给参考实现 spark_executor):
-`yarn_job_manage` → 4 个独立 RM Tool: `list_applications` / `get_application_status` / `get_application_logs` / `kill_application`
- 加鉴权层 (`none` / `basic` / `kerberos` 桩) + SSL 配置
- 加 manual redirect following (RM→NM 跨主机 307 必须保留 Authorization)
- `analyze_spark_log` 日志改走 RM `get_application_logs` 降级链
- Cluster struct 加 8 个鉴权/SSL/allowlist 字段
- Tool 总数 8 → **11**
- Phase 5 时间 6-7h → 10-12h
14. **v0.3.6 简化**(用户告知环境用 YARN SimpleAuth):
- 鉴权层去掉 kerberos 桩,改为 `none` / `simple` / `basic`
- `simple` 模式:`user.name` query param(默认 `"yarn"`)
- Hadoop 2.7 兼容性从风险表移除(用户已实测)
- Cluster struct AuthType 注释更新
15. **v0.3.7 用户接受所有 6 项建议**:
- Cluster 加 `default_submit_args` + `rate_limit_per_min`
-`applications` 表(纯读不需要)
- `auth_password` PUT 留空 = 保留旧值
-`audit_log` 表 + 路由
-`AdminTokens` 支持(env 逗号分隔)
- analyzer 阈值改为 env 可配
- 无任何未决项
16. **v0.3.8 日志基础设施** (用户新要求):
-`log/slog` 替换默认 log
- 终端 text handler + 主文件 JSON handler (multi-handler fan-out)
- Per-Tool 独立日志文件: `data/logs/tools/{ts}_{tool}_{id}.log`
- 文件权限 0600 (含敏感 params)
- T1.5 新增 + T5.13 Tool 集成
#### 当前 Tool 表面 (v0.3.8,11 个)
| # | Tool | 类型 | 备注 |
|---|---|---|---|
| 1 | `list_clusters` | **发现入口 (强制)** | 返回 cluster 全部元信息(含鉴权+allowlist) |
| 2 | `spark_submit` | 业务高层 | 本地 `exec.Command` |
| 3 | `list_applications` | **RM (v0.3.5 新)** | `GET /ws/v1/cluster/apps` |
| 4 | `get_application_status` | **RM (v0.3.5 新)** | `GET /ws/v1/cluster/apps/{id}` |
| 5 | `get_application_logs` | **RM (v0.3.5 新)** | 降级链:aggregated-logs → amContainerLogs → NM |
| 6 | `kill_application` | **RM (v0.3.5 新)** | `PUT /ws/v1/cluster/apps/{id}/state` |
| 7 | `fetch_spark_metrics` | 业务高层 SHS | 内部调 `fetch_url` |
| 8 | `fetch_cluster_env` | 业务高层 RM | 内部调 `fetch_url` |
| 9 | `analyze_spark_log` | 业务高层分析 | 规则引擎 + RM 日志降级 + LLM-Ready Prompt |
| 10 | `fetch_url` | HTTP 原语 | SSRF + 鉴权 + manual redirect |
| 11 | `upload_file` | 本地存储 | 路径白名单 |
| 4 | `fetch_url` | 通用 HTTP 原语 |
| 5 | `upload_file` | 本地文件存储 (v0.3 重新定义) |
#### 下一步
- [ ] **用户审阅 v0.3 计划**
- [ ] 用户确认 / 修改后开始 **Phase 0** 执行
- [ ] Phase 0 由 Codex 执行 (Go 依赖操作)
- [ ] 每个 Phase 结束: `go build` + `go test` 全绿才能进入下一 Phase
#### 待用户在执行前澄清的项 (在 task_plan.md "待确认项" 也有)
- `/mcp` 路由前缀是否带 `/*`?
- ADMIN_TOKEN 和 AGENT_TOKEN 是否合并?
- applications 表是否保留?
- 是否需要 Prometheus metrics?
---
## 会话状态
- **当前阶段**: v0.3 计划已写完,等待用户审阅
- **下一步行动**: 用户批准后 → Phase 0 (依赖调整)
- **阻塞项**: 4 个待确认项(可在 Phase 0-2 边做边问)
- **风险**: mcp-go v0.56.0 API 需在 Phase 6 实施前先查;spark_submit 引入的命令注入面需在 Phase 5.5 严格缓解
- **关键设计约束** (v0.3 强调):
- `exec.Command(name, args...)` **绝不**走 shell
- `upload_file` **绝不**做远程 HTTP 上传
- SSRF / 路径白名单 / token 鉴权 三道防线不变