Skip to content

feature: add uddos cli#118

Merged
Episkey-G merged 4 commits into
ucloud:masterfrom
leas-li:feature/uddos
Jul 14, 2026
Merged

feature: add uddos cli#118
Episkey-G merged 4 commits into
ucloud:masterfrom
leas-li:feature/uddos

Conversation

@leas-li

@leas-li leas-li commented Jul 14, 2026

Copy link
Copy Markdown
Contributor

Features:

Fixes:

@Episkey-G

Copy link
Copy Markdown
Collaborator

接入规范评审:feature: add uddos cli

结论:当前不符合接入规范,无法合入。 存在 2 个必然导致 CI 失败的阻断项、2 个表格模式下功能静默的正确性缺陷,以及若干与《UCloud CLI 产品命令开发与接入规范》约定冲突的结构性/风格问题。骨架方向是对的(薄壳 product.gointernal/<command>/ 分层、cli.NewServiceClient 鉴权、一 verb 一文件、写命令 EmitResult / 读命令 PrintList),但细节偏离较多。

一、概览

新增高防产品 uddos(33 文件 / +2690 行):

  • ucloud uddos mainland {service,ip,rule} <verb> — 国内高防
  • ucloud uddos overseas {service,ip} <verb> — 海外高防

所有调用均通过 uaccount 客户端的 NewGenericRequest() + SetPayload(map) + GenericInvoke() 泛型通道发起(BuyHighProtectGameServiceCreateBGPServiceIP 等 Action)。


二、🔴 阻断项(CI 必挂,必须修)

1. 缺 cmd/products.gen.go 注册 —— check-product job 直接失败

PR 改动清单里没有 cmd/products.gen.go(仓库内被 git 跟踪的注册胶水)。规范 §2.7 步骤 3 要求跑 go run ./hack/gen-products 并提交结果。.github/workflows/pr-gate.ymlcheck-product job 会执行:

go run ./hack/gen-products
if ! git diff --quiet -- cmd/products.gen.go; then  → "cmd/products.gen.go is out of date" → 失败

后果不仅是 CI 挂,而是 uddos 根本没被挂进 CLI(New() 永不会被调用)。
修法:本地 go run ./hack/gen-products,把 cmd/products.gen.go 一并提交。

2. golden 与实际代码 flag 不一致 —— 产品 golden 测试必挂(§2.4)

testdata/cmdtree.golden 明显是从另一版源码生成的,与本 PR 的 .go 对不上。产品进注册表后 go test ./hack/snapshot -run TestProductGoldens/uddos 会红:

命令 golden 里的 flag 实际代码定义的 flag 冲突
mainland ip create block-udpeip-region resource-id/type-ip/remark/tag(mainland/ip/create.gonewCreate) golden 多 2 个
overseas ip create block-udpeip-region resource-id/type-ip/remark/tag(overseas/ip/create.go;EIPRegion 是内部自动解析、无 flag) golden 多 2 个
overseas service create engine-room(required) 用的是 area-line(overseas/service/create.go) 字段名对不上

testdata/testcases.md 也用了代码里不存在的 --block-udp--eip-region、海外 --engine-room(O-SVC-C-01 等)。代码、golden、测试用例三者不同步,说明提交前没跑过 §2.4 的 WRITE_*_GOLDEN=1 重生成。
修法:定稿 flag 后重生成 golden,并同步 testcases.md


三、🟠 正确性缺陷

3. service create 成功时表格模式下零输出

mainland/service/create.gooverseas/service/create.goRun 收尾只调 ctx.EmitResult(...),没有写 ctx.ProgressWriter()。按 §2.5,EmitResult 在 table 模式是 no-op。于是默认表格模式下 service create 成功后屏幕什么都不打印——用户既看不到 ResourceID,也不知道是否成功。对比 ip create 是先 Fprintf(ctx.ProgressWriter(), "BGP IP created: %s")EmitResult,写法正确。两个 service create 应补一行 ProgressWriter 叙述。

叠加风险:BuyHighProtectGameService 是真实计费购买,无 --async、无二次确认、成功还静默;若 payload["ResourceInfo"] 缺失,resourceID 为空串也会当成功 EmitResult,不报错。

4. service create--async / 轮询(§5.2)

购买类异步操作按 §5.2 应支持 --async + ctx.PollerTo(w, describe).Spoll(...) 等到目标状态。当前直接返回,无等待/状态反馈。


四、🟡 规范约定偏离(非 linter 拦截,人工 gate)

5. 4 级命令树,偏离 §7「greenfield 扁平 2 级树」

§7 要求新产品用扁平 <product> <verb>;3 级分组是 udb 这类存量迁移的例外。本 PR 是 uddos mainland ip create = 4 级,比存量例外还深,且 internal/mainland/ip/internal/ 下嵌套两层,不符合 §2.2 的 internal/<command>/ 单层布局。mainland/overseas × service/ip/rule 有域上的合理性,但这属于需平台 owner 明确批准的结构决策,建议在 PR 描述中说明并与平台确认。

6. strVal/intVal 放在 cmd.go,违反 §2.2

strVal/intVal 被复制进 5 个 cmd.go。§2.2 明确规定聚合器 cmd.go「只允许 NewCommand/newCommand……不放任何业务逻辑或 helper」。check-product 规则 10 只拦 helpers.go 文件名和「一文件多个 cobra 构造器」,抓不到这个,但确实违反约定且 5 份重复。根因见第 7 点。

7. 全量 GenericInvoke + map[string]interface{},偏离 §5 / §10

§5 要求「请求一律用 client.NewXxxRequest() 构造再逐字段赋值」。本 PR 借 uaccount 客户端走泛型通道调所有高防 Action。import 白名单(规则 9)、鉴权工厂(规则 3)都过得了,不是 linter 违规;但:

  • 丢失类型安全,才滋生第 6 点的 strVal/intVal 和满屏 payload["X"].(...) 断言;
  • 这些 Action 本质是通过通用通道调未在 SDK 类型化、类高防私有的接口。按 §10,用 private API 必须在仓库里显式声明「用了哪些、命令路径、API owner、兼容性风险」——PR 里没有这份声明。

若高防确实无 SDK service 包,这条需平台评审拍板,并至少补 §10 声明。

8. 死代码:bind.go / unbind.go

overseas/ip/cmd.gonewBind/newUnbind 注释掉了,但 bind.gounbind.go(及仅供其使用的 checkOverseasServicenapInvoker)仍随 PR 提交。testcases.md G-07 也自认「bind/unbind 暂未启用」。Go 能编译,但这是成品树里的死代码,应删除或本 PR 内接好。


五、🔵 次要 / 风格

  • 9. 资源 ID flag 命名:§7 greenfield 默认 --<product>-id(即 --uddos-id),PR 统一用 --resource-id。多资源类型下有可读性理由,但属偏离,建议 PR 描述说明。
  • 10. 无 Go 单测:§13 单测归业务方。PR 只有 testcases.md(人工测试计划),src-bandwidth 步进、area-line→engine-room 映射、defence flow 白名单等纯函数校验逻辑零自动化测试,建议补 _test.go
  • 11. @Brief/@Author/@Email/@Date/@CopyRights:每个文件+每个函数都挂 Javadoc 式头,非 Go 惯用法(样例 examples/product_onboarding/ 用普通 doc 注释),且逐函数嵌入邮箱、噪声大。§8「匹配现有风格」建议改惯用注释。
  • 12. charge-type 手工校验:手写 Month/Year 枚举,未用平台 ctx.BindChargeType(泛型请求下无法反射,是第 7 点的连带影响)。

六、做得好的地方

  • 薄壳 product.go 只委托,Metadata().Commandsproduct.yaml.commands 一致(均 ["uddos"],过 check-product 规则 8);
  • 删除类都有 ctx.Confirm(yes, ...) + --yes/-y 门控(§5.3);
  • 一 verb 一文件、rows.go 拆分到位;输出通道方向正确(写 EmitResult / 读 PrintList);
  • import 全在白名单内,未碰 base/model/cmd,无跨产品 import;
  • 校验错误信息清晰可读。

七、修改清单(按优先级)

  1. go run ./hack/gen-products 并提交 cmd/products.gen.go(否则 CI 挂、产品进不了 CLI);
  2. 定稿 flag → 重生成 cmdtree.golden、同步 testcases.md,消除代码/golden/用例三方不一致;
  3. 两个 service createProgressWriter 叙述,消除表格模式静默;评估是否需要 --async;
  4. 删除或接好 bind.go/unbind.go 死代码;
  5. 与平台确认 4 级命令树结构 & 泛型 GenericInvoke 方案,补 §10 private API 声明;
  6. strVal/intVal 移出 cmd.go;补纯校验函数单测;精简 @ 注释头。

leas.li and others added 3 commits July 14, 2026 15:24
service create(mainland + overseas):
- 成功时经 ProgressWriter 打印叙述,table 模式不再零输出;
  ResourceId 为空时报错,避免静默当成功
- 新增 --async flag;默认同步轮询 DescribeService 直到 DefenceStatus="Started"

overseas ip:移除未启用的 bind/unbind 命令及 checkOverseasService 辅助

同步更新 cmdtree.golden 与 testcases.md

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
@Episkey-G Episkey-G merged commit 270fcff into ucloud:master Jul 14, 2026
11 of 13 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants