feat(services): add Proxmox VE 8.3.5 service package (issue #103) - #378
feat(services): add Proxmox VE 8.3.5 service package (issue #103)#378MoCh3n wants to merge 19 commits into
Conversation
|
PR Title: Pr proxmox Commit: 本次 PR 新增了一个 Proxmox VE 8.3.5 的 OctoBus 服务包,包含:
整体是一个典型的 OctoBus SDK 服务实现,通过 HTTP REST 调用 Proxmox VE API,暴露为 gRPC 服务。 在审查中发现两个主要问题:
|
|
PR Title: Pr proxmox Commit: 本次变更仅修改了 |
|
PR Title: Pr proxmox Commit: 本次 PR 在 |
|
PR Title: Pr proxmox Commit: 本次变更在 |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本次 PR 对 Proxmox 服务的
这些改动修复了此前确认的历史问题(定时器泄漏、response.text() 异常未捕获、undici Agent 死代码),代码逻辑合理,没有发现由本次变更引入的新缺陷。 |
|
Reviewer note: this PR currently has merge conflicts with the target branch, so it cannot be merged or reviewed safely in its current state. Please rebase or merge the latest base branch, resolve the conflicts, and make sure GitHub Actions pass again. I am marking/keeping this PR as draft until the conflicts are resolved. |
Service L2 自动检查结果:l2:blocked
L2 只验证包结构、mock 测试、80% line/branch/function coverage、打包、构建和 OctoBus smoke 链路;真实设备兼容性仍需人工检查作者提供的脱敏证据。 |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本 PR 新增 Proxmox VE 8.3.5 的 OctoBus 服务包:6 个只读 RPC(ListNodes/ListQemuVMs/GetQemuVMConfig/ListLXCs/ListStorage/GetNodeStatus),核心 handler src/ve-8-3-5.js(约 790 行),配套 proto、config/secret schema、service.json、mock 上游与 749 行单元测试,并注册进 services/package.json 与 octobus-tentacles.js(顺带修复了后者一处多余花括号的语法问题)。 总体质量较好:URL 构造对 node/vmid 做了严格校验(防路径注入),认证头由 tokenId/tokenSecret 拼接且对非法字符有校验,sanitizeHeaders 阻止 authorization/cookie 等危险头,超时通过 AbortController 实现并覆盖响应体读取,TLS 跳过通过 undici dispatcher 实现,响应大小有 1MB 上限,日志不泄露 token。此前审查指出的 fetch 非标准选项问题(timeoutMs/TLS 直接传给 fetch)已在当前 head 修复(改用 signal + dispatcher),并有对应测试断言,不再重复上报。 发现两个问题:1) config.schema.json 将 allowHttp 列为必填,与代码默认值、README 及 offline-test 示例配置(仅用 allowInsecureHttp)矛盾,会导致按文档配置无法通过 schema 校验;2) buildNodeStatus 中 cpu_usage/cpu_count 使用 data.cpu_usage/data.cpu_count,而真实 Proxmox 节点状态接口返回 data.cpu / cpuinfo.cpus(buildNodeInfo 已按 raw.cpu 处理),测试 mock 自行构造了不存在的字段名,接入真实上游后这两个字段将恒为 0。 |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本次变更仅修改 设计意图:GitHub 托管 runner(ubuntu-latest)预置的 google-chrome apt 源偶尔会因镜像不一致导致 评估:变更范围极小且为 CI 基础设施层面,风险低。 |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本次 PR 是提交 dffc3d2「revert: keep L2 runner changes out of service PR」,仅修改 .github/workflows/service-l2-gate.yml 一个文件(+0/-3),删除 "Install system dependencies" 步骤中在 apt-get update 之前清理 /etc/apt/sources.list.d/google-chrome.list 的三行代码(含注释)。该清理步骤原先用于规避 ubuntu-latest runner 自带且与 gate 无关的 google-chrome 第三方 apt 源镜像短暂不一致导致的 apt-get update 间歇性失败。删除后,该 CI gate 可能重新暴露于上述镜像不稳定导致的偶发失败(稳定性回归)。整体改动很小且属于有意的 revert(将 L2 runner 相关改动与 service PR 隔离),但建议评估或保留该可靠性缓解措施。提交了一条关于稳定性回归的中等严重度发现。 |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本次变更新增 Proxmox VE 8.3.5 的 OctoBus 服务包(services/proxmox__ve_8-3-5),提供只读清单 RPC:ListNodes、ListQemuVMs、GetQemuVMConfig、ListLXCs、ListStorage、GetNodeStatus,并完成 service.json/proto/config+secret schema/package.json/bin 接线与单测。核心实现 src/ve-8-3-5.js 质量较高:请求构建与认证头(PVEAPIToken)正确,baseUrl 规范化与 HTTPS 强制(含 loopback/allowInsecureHttp 例外)合理,401/403/4xx/5xx 错误映射与 README 一致,token 不落日志,响应体大小限制、超时中止、header 注入过滤均已覆盖并有测试。审查共提交 3 个低严重度、高置信度发现:1) config.schema.json 强制 required baseUrl 与代码/README 支持的别名(base_url/host/restBaseUrl/url)冲突,仅用别名会被绑定校验拒绝;2) secret.schema.json 未要求 tokenId/tokenSecret 必填,空 secret 可过校验但在运行时才失败(且含冗余 const smoke@pve!token 分支);3) QemuVMInfo/LXCInfo 的 template 字段在 proto 中为 string 且投影为 "0"/"1",非模板 VM 恒为 truthy 的 "0",且与 GetQemuVMConfig 中 bool 类型不一致。整体评估:功能正确、测试充分,未发现高危正确性或安全问题。 |
|
Maintainer deep-repair update ( |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本 PR 新增了一个 Proxmox VE 8.3.5 的 OctoBus 服务包,暴露 6 个只读 RPC(ListNodes、ListQemuVMs、GetQemuVMConfig、ListLXCs、ListStorage、GetNodeStatus),并接入 services/package.json 与 octobus-tentacles.js。 整体质量很高:实现文件对 baseUrl 做了严格校验(拒绝凭据/子路径/非 http(s)),token 与自定义 header 都做了 CRLF 注入防护,响应有 1MB 上限与超时 abort 控制,日志不泄露 token secret,错误映射有明确文档且测试覆盖全面(含 401/403/404/500/超时/超大响应/非 JSON/网络失败等)。历史 finding 中提到的 QemuVMInfo/LXCInfo template 投影为字符串 "0" 的问题已在当前版本修复(proto 已改为 bool,代码用 pickBoolean)。 提交了两个低/中危 finding:一是 5xx(含 Proxmox 对不存在节点返回的 500)统一映射为可重试的 gRPC UNAVAILABLE 且丢弃了上游错误体,导致永久性配置错误被误报为瞬时错误、缺乏诊断信息;二是 tokenId 格式校验正则未真正强制 USER@REALM!TOKENID 形状,畸形 token 会延迟到 API 层才以误导性的 403 失败。 |
Previously if upstream response body read fails, an unhandled exception propagates. Wrap in try/catch and return UNAVAILABLE.
- drop 'import { Agent } from undici' - was never used.
- move clearTimeout(timer) into a finally block so it runs whether
fetch throws or succeeds; previously the post-try line only ran on
success.
Signed-off-by: kingfs <zhenzhen086@126.com>
Signed-off-by: kingfs <zhenzhen086@126.com>
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本 PR 新增 Proxmox VE 8.3.5 只读库存服务包(OctoBus service):proto 契约、config/secret JSON Schema、运行时 handler(src/ve-8-3-5.js,850 行)、mock 上游(test/mock_upstream.js)与 837 行测试,并接线到 services/package.json 与 octobus-tentacles.js。 设计要点:全部 RPC 为 GET /api2/json/ 只读请求,使用 PVEAPIToken 认证;baseUrl 规范化(拒绝带 userinfo/query/path 的 URL)、HTTP(S)/回环地址策略、响应 1MB 上限、超时(默认 5s/上限 60s)、TLS 校验可配置、请求头白名单并禁止 header 注入、错误摘要脱敏、4xx/5xx→gRPC 状态映射。 历史发现核查:agent 功能串(enabled=1,fstrim=1)已由 pickAgentEnabled 正确解析并补测;压力指标键已同时兼容 pressurecpufull 与 pressure-cpu-full;5xx 映射已改为 500+not found→NOT_FOUND、502/503/504→UNAVAILABLE、其余→FAILED_PRECONDITION;tokenId 运行时正则与 schema 已对齐;autostart 已按 onboot 别名处理。以上历史问题均已修复并有测试覆盖。 本次审查报告一条功能性发现:errorSummary 对 Proxmox 风格 |
|
PR Title: feat(services): add Proxmox VE 8.3.5 service packa... Commit: 本次改动聚焦 services/proxmox__ve_8-3-5 的 errorSummary 函数,修复 Proxmox 结构化错误体解析:原实现把 parsed.error / parsed.errors 直接交给 pickFirstString,当 error 为对象或 errors 为对象数组时会被 String() 转成 "[object Object]",导致错误摘要不可读,且 500 响应中的 node-not-found 无法映射为 NOT_FOUND。改动后按 errors 数组(取首元素)、error/errors 对象的 msg/message 字段逐步提取可读字符串;同时新增 |
| typeof errors === 'string' ? errors : errors?.msg, | ||
| errors?.message, | ||
| typeof parsed?.data === 'string' ? parsed.data : '', | ||
| ]) || source; |
There was a problem hiding this comment.
errorSummary 的 || source 回退使无消息字段的合法 JSON 以原始全文作为错误摘要,扩大 500 NOT_FOUND 误判面并可能透出未脱敏字段
新增的 ]) || source 使行为发生可验证的变更:当 JSON 可解析但 message/error/errors/data 均无可提取的非空字符串时(例如 {}、{"foo":1}、{"data":{}}),candidate 从原来的空串变为原始 JSON 全文,errorSummary('{}') 由 '' 变为 '{}'。该摘要在 proxmoxRequest 中会拼入 upstream http ${status}: ${summary} 错误详情:(1) 500/4xx 响应会把原始 JSON body 透出到错误消息,虽然经过脱敏,但仅覆盖传入的 sensitiveValues 精确匹配和 PVEAPIToken=/token/secret/authorization 正则,其它字段(如内部路径、request_id 等)不会被覆盖;(2) isResourceNotFound 会对该原始 JSON 做正则匹配,一个 500 响应只要 body 中任一未被识别字段含 "not found"/"no such"/"does not exist" 字样,状态映射就会从 FAILED_PRECONDITION 变为 NOT_FOUND,可能把一般性上游错误误判为资源不存在。这一行为变更没有测试固化。
Problem code:
Changed code at services/proxmox__ve_8-3-5/src/ve-8-3-5.js:327
Recommendation:
若 || source 回退仅用于保留明文错误信息,建议限定在 JSON.parse 失败分支(catch 内保持 candidate=source),JSON 解析成功但无已识别消息字段时维持返回 '',避免把原始 JSON 全文作为摘要;若保留该回退,请补充测试固化 errorSummary('{}') 的行为,并验证含 "not found" 但非资源不存在语义的 JSON(如 {"foo":"bar not found"})不会被误映射为 NOT_FOUND,同时为新增的 error 对象 msg/message 分支补测试。
Add a new read-only service package for the official public REST API of Proxmox VE 8.3.5.
Resolves issue #103.
Target system
Proxmox VE 8.3.5 — ListNodes, ListQemuVMs, GetQemuVMConfig, ListLXCs, ListStorage, GetNodeStatus.
Interface source
All implementation is sourced exclusively from official public documentation:
apidoc.jsandPVE/API2Tools.pm(public open-source reference)No reverse engineering, packet capture, or authentication bypass was performed.
Third-party SDK
None. Only
@chaitin-ai/octobus-sdk(MIT, GPL-3.0 compatible) and Node.js built-infetch.Credentials
PVE API Token auth via
PVEAPIToken=USER@REALM!TOKENID=TOKENSECRETHTTP header (issued via Datacenter → Permissions → API Tokens in the Proxmox UI).Rate limits & quotas
Subject to upstream REST API rate limits imposed by the Proxmox VE 8.3.5 server. No additional client-side throttling.
High-risk operations
None. All exposed RPCs are read-only (GET endpoints only). No
POST/PUT/DELETEcalls to Proxmox APIs.RPCs exposed
Proxmox_VE_8_3_5.Proxmox_VE_8_3_5/ListNodes—GET /api2/json/nodesProxmox_VE_8_3_5.Proxmox_VE_8_3_5/ListQemuVMs—GET /api2/json/nodes/{node}/qemu(requiresnode)Proxmox_VE_8_3_5.Proxmox_VE_8_3_5/GetQemuVMConfig—GET /api2/json/nodes/{node}/qemu/{vmid}/config(requiresnode+vmid)Proxmox_VE_8_3_5.Proxmox_VE_8_3_5/ListLXCs—GET /api2/json/nodes/{node}/lxc(requiresnode)Proxmox_VE_8_3_5.Proxmox_VE_8_3_5/ListStorage—GET /api2/json/nodes/{node}/storage(requiresnode)Proxmox_VE_8_3_5.Proxmox_VE_8_3_5/GetNodeStatus—GET /api2/json/nodes/{node}/status(requiresnode; includesrootfs,ksm,boot-info,current-kernel)Test approach
node:test+node:assert/stricttests, all passinggofmt -lclean,go vetcleanSample data source
test/mock_upstream.jsuses response shapes traced directly from official API reference response samples for Proxmox VE 8.3.5.Compliance
@chaitin-ai/octobus-sdkLocal mock integration test (real upstream request/response)
Resolves issue #103