Pull Request已成功合入, 合并人@曹玉哲
(感谢 m0u55e 的贡献)变更摘要
本 PR 主要新增了一个可部署的 Service 能力 Demo,并将 Kubernetes Pod 操作抽象为系统能力统一装配到 SystemContext,使 Handler 可以通过 RequestContext 调用 Pod 查询、创建和删除接口。新增的 service/examples/simple_capabilities_app.py 通过 8 个 HTTP 接口演示数据库、Redis、Envelope 与 Kubernetes 能力,并支持通过 .env 配置在本地(SQLite、FakeRedis、Fake Kubernetes)与服务器(MySQL、Redis、kubernetes_asyncio)两种环境下运行。
主要改动
- 新增 Kubernetes 能力模型与协议: 新增
service/openjiuwen_runtime/service/context/kubernetes/模块,定义KubernetesOperations协议以及PodCreateSpec、PodSummary、PodDeleteResult数据模型,并分别提供内存实现FakeKubernetesOperations和基于kubernetes_asyncio的真实实现KubernetesAsyncioOperations。 - 将 Kubernetes 集成进
SystemContext生命周期:SystemContext新增kubernetes属性和set_kubernetes/require_kubernetes方法,并在启动、探活、健康检查(readiness)和资源释放流程中纳入 Kubernetes 的start/ping/close,同时RequestContext暴露kubernetes属性供 Handler 使用。 - 新增错误类型与状态映射: 在
errors.py中新增KubernetesUnavailable(对应 503)和PermissionDenied(对应 403),并新增ErrorCode.KUBERNETES_UNAVAILABLE与ErrorCode.FORBIDDEN,用于 Kubernetes 操作失败和权限不足的场景。 - 新增可部署 Demo 应用及配置模板: 新增
service/examples/simple_capabilities_app.py,提供数据库、Redis、Envelope、Kubernetes 共 8 个接口,并包含DemoConfig配置校验、Swagger/OpenAPI 入口;同时新增本地与服务器两份.env配置模板,pyproject.toml增加kubernetes_asyncio可选依赖。 - 补充单元测试覆盖: 新增
test_kubernetes_operations.py和test_simple_capabilities_example.py,并扩展test_config_bootstrap.py、test_errors.py、test_system_context.py,覆盖 Kubernetes 适配器、配置校验、上下文生命周期以及 8 个 Demo 接口的行为。


代码审查
Closing Summary
已逐一审查全部 8 个变更文件:
service/examples/simple_capabilities.local.env.example— no issuesservice/examples/simple_capabilities.server.env.example— no issues(change-me为占位符,非硬编码真实密钥)service/examples/simple_capabilities_app.py— 1 个问题(P3:模块导入期读取环境变量)service/openjiuwen_runtime/service/__init__.py— no issues(新增导入的符号均已确认存在)service/openjiuwen_runtime/service/bootstrap.py— 1 个问题(P3:kubernetes 所有权未接入)service/openjiuwen_runtime/service/context/__init__.py— no issuesservice/openjiuwen_runtime/service/context/kubernetes/__init__.py— no issuesservice/openjiuwen_runtime/service/context/kubernetes/asyncio_client.py— 1 个问题(P3:ping 就绪检查语义不一致)
问题统计:P0 0 个、P1 0 个、P2 0 个、P3 3 个。
总体风险判断:本次变更整体质量良好,导入/导出接线完整、Kubernetes 适配器的异常映射与 Pod 模板防护基本合理;发现的 3 个问题均为低严重度的一致性与健壮性缺陷,不影响主流程正确性,可在后续迭代中修复。
我已系统审查了全部 11 个变更文件,逐项核对了上下文、调用链与契约一致性。整体结论:该 diff 质量较高,Kubernetes 能力的契约定义、SystemContext 生命周期集成(start/ping/stop/readiness 及反向清理顺序)、错误码/HTTP 状态映射与测试断言彼此一致,未发现 P0–P2 级别的正确性/安全/可靠性问题。仅报告 1 个 P3 级可选清理项。
审查结果汇总(按文件):
| 文件 | 结论 |
|---|---|
service/openjiuwen_runtime/service/context/kubernetes/base.py |
无问题(契约 dataclass 与 Protocol 定义清晰) |
service/openjiuwen_runtime/service/context/kubernetes/fake.py |
1 个 P3(labels 参数存储后从未使用,误导性死代码) |
service/openjiuwen_runtime/service/context/request_context.py |
无问题(kubernetes 属性与 require_kubernetes() 与现有 redis/db 模式一致) |
service/openjiuwen_runtime/service/context/system_context.py |
无问题(start/readiness/stop/from_settings 集成与所有权语义、反向清理顺序均正确) |
service/openjiuwen_runtime/service/errors.py |
无问题(新错误码、异常类与 HTTP 状态映射自洽且已被测试覆盖) |
service/pyproject.toml |
无问题(kubernetes_asyncio==35.0.0 为可选 extra,版本已固定) |
service/tests/unit_tests/test_config_bootstrap.py |
无问题(反向清理顺序断言与实际实现吻合) |
service/tests/unit_tests/test_errors.py |
无问题(断言与 errors.py 一致) |
service/tests/unit_tests/test_kubernetes_operations.py |
无问题(fake 生命周期/CRUD、错误映射、UID 前置条件等断言与实现一致) |
service/tests/unit_tests/test_simple_capabilities_example.py |
无问题(Demo 接口行为断言与实现一致) |
service/tests/unit_tests/test_system_context.py |
无问题(生命周期/所有权/缺失能力三个新测试与实现一致) |
问题计数: P0 = 0,P1 = 0,P2 = 0,P3 = 1。
整体风险判断: 低风险。变更结构清晰、测试覆盖充分、错误处理与所有权语义一致,可合入;唯一建议是清理 FakeKubernetesOperations 中未使用的 labels 参数(可选)。
| 类型 | 数量 |
|---|---|
| 🔴 阻塞 | 1 |
| 🟡 建议 | 0 |
⛔ 需要修改


🟠 High Priority
变更行 system_context.py:70 新增 _owns_kubernetes: bool = False(默认不持有),而 system_context.py:491 新增的 from_settings(kubernetes=...) 只是把 kubernetes 透传给 build_system_context;但 build_system_context(bootstrap.py:195)构造 SystemContext(kubernetes=kubernetes, ...) 时并未传 _owns_kubernetes=True,于是 _owns_kubernetes 恒为 False。
→ 受影响行为:SystemContext.start() 中 kubernetes 分支(system_context.py:221-228)在 _owns_kubernetes 为 False 时跳过 await self.kubernetes.start,直接执行 _ping(self.kubernetes)。
→ 失败模式:FakeKubernetesOperations.ping() 在 start() 被调用前恒返回 False(self._started),KubernetesAsyncioOperations.ping() 在 _core_api 未初始化时直接 raise KubernetesUnavailable(_require_started)。因此 demo(simple_capabilities_app.py:307-318 新建 FakeKubernetesOperations(...) 后经 build_system_context(kubernetes=...) 装配、且从不自行 start)在框架启动探活时必抛 KubernetesUnavailable,即使跳过启动,get_pod/create_pod/delete_pod 也会因未 start 而抛 KubernetesUnavailable,K8s 能力整体不可用。这是本次 diff 引入的 _owns_kubernetes 默认值与既有 build_system_context 未同步的契约断裂。
建议:将 _owns_kubernetes 默认值改为 None(或 True),并在 __init__ 中按 kubernetes is not None 自动探测;同时在 build_system_context/from_settings 中显式传递 _owns_kubernetes,保证经工厂装配的 kubernetes 会被 SystemContext.start() 真正 start()。


Paired: GitHub #50 ↔ GitCode !418
What type of PR is this?
/kind feature
Self-checklist:(请自检,在[ ]内打上x,我们将检视你的完成情况,否则会导致pr无法合入)
Summary
新增可部署的 Service 能力 Demo
service/examples/simple_capabilities_app.py,通过 8 个 HTTP 接口展示数据库、Redis、Envelope 和 Kubernetes 能力。Demo 从
.env文件读取运行配置,本地环境使用 SQLite、FakeRedis 和 Fake Kubernetes,服务器环境使用 MySQL、Redis 和kubernetes_asyncio。将 Kubernetes Pod 操作抽象为系统能力,统一装配到
SystemContext,Handler 可通过RequestContext调用 Pod 查询、创建和删除接口。核心能力
POST /api/db/read和POST /api/db/writePOST /api/redis/read和POST /api/redis/writePOST /api/envelope/inspect,返回 Envelope、Metadata、RequestContext 和服务环境信息POST /api/k8s/pod/read、POST /api/k8s/pod/create和POST /api/k8s/pod/deletekubernetes_asyncio的真实 Kubernetes 实现SystemContext的启动、探活、健康检查和资源释放流程.env配置模板、Swagger/OpenAPI 调试入口、部署说明及 RBAC 配置示例