Skip to content

feat(config): validate remotely only when validation-relevant fields change#143

Open
Episkey-G wants to merge 1 commit into
fix/config-write-on-validation-failurefrom
fix/config-conditional-validation
Open

feat(config): validate remotely only when validation-relevant fields change#143
Episkey-G wants to merge 1 commit into
fix/config-write-on-validation-failurefrom
fix/config-conditional-validation

Conversation

@Episkey-G

Copy link
Copy Markdown
Collaborator

⚠️ 堆叠 PR:base 指向 fix/config-write-on-validation-failure#142),不是 master。本 PR 依赖 #142 的 fail-closed 结构(守卫包住的正是那些校验调用)。#142 合入后本 PR 自动改指 master;在此之前无法合入。

问题:7 年前的过度校验回归

config update 与主命令 config改存量 profile 时,无条件远程校验 region+project —— 哪怕你只改一个跟它们无关的元数据字段。fail-closed(#142)之后这个代价被放大:

$ ucloud config update --profile p1 --active false   # 只想切个 active
# 离线 / 网络抖动 → 远程 region 校验失败 → 整条命令被拒 → 连 active 都改不了

git 考古:这是回归,不是原始设计

时间 commit 状态
2018-10-24 1cbc80f 单一 config 命令,region 校验有条件if cfg.Region != "" || cfg.Zone != ""
2019-07-04 dffaa8b(0.1.18) add/update守卫丢失 → 无条件校验。回归点
2026-07-17 本 PR 恢复按需校验

守卫在拆分时被平铺掉了。诚实边界:region/zone 当年有条件守卫证据确凿;project 侧 2018 diff 未见对应守卫,「原本也该条件化」属合理推广。

方案:按需校验(只改「何时校验」,不改「校验失败怎么办」)

credsOrEndpointChanged = 改了 public-key / private-key / base-url / channel-key
validateRegion  = 传了 region/zone  || credsOrEndpointChanged   (主命令再 || !ok)
validateProject = 传了 project-id    || credsOrEndpointChanged   (主命令再 || !ok)
  • 只改元数据(--active/--timeout-sec/--max-retry-times/--agree-upload-log) → 两者皆跳过,离线可改
  • 凭据/接入点变更 → region 与 project 都重校验(关键分支,不可省):换 key/网关后存量 region/project 可能失效或新凭据无权访问,配置时当场抓住才是校验的价值;跳过会把「换了坏 key」延迟到下次真正用命令时才暴露。
  • c.Flags().Changed() 而非空值判断:空值是合法输入(清除语义,如 --channel-key "")。
  • 主命令 || !ok:新建 profile 恒校验(新 profile 的 region/project 须从零建立)。

if 体内的 fail-closed returnerrNoDefaultProject 放行原样不动#142 的成果不回退)。跳过时不碰存量 region/zone/project。

config add 不改:新建无「未改动」基线,region/project 必须从零建立(未传 region 时还要拉默认),保持无条件校验。

测试

复用 #142 的 httptest 假网关基础设施,新增 6 个用例 + 适配 2 个既有用例:

  • 毒网关(被调用即 t.Errorf)断言「只改元数据」路径零远程调用(AC1/AC5)。
  • 凭据变更触发双校验(AC4):--public-key 变更下 project 校验确实跑、失败→不落盘。
  • --region 变更仍校验(AC3)、主命令新建仍校验(AC5)。
  • 适配的 2 个 fix(config): reject config writes when remote validation fails #142 用例:纯元数据在新行为下不再触发校验,改用 --region/--public-key 显式触发(其中主命令用例加强了 region 断言)。

验证严格性(本地):

  • 全量回归 go test ./... 全绿;go vet 干净。
  • 复现闸:回退守卫,3 个跳过用例立刻变红 → 证明非空转。
  • 变异测试:去掉 credsOrEndpointChanged,AC4 立刻变红 → 证明「凭据→project 校验」这一关键分支有测试守护。

⚠️ CI 的 test job 不含 ./cmd/...pr-gate.yml:228),本 PR 用例 CI 不跑,请本地 go test ./cmd/... -count=1

行为变更(用户可见,需入发版说明)

命令 场景 变更前 变更后
config update 只改 --active/--timeout 等元数据 远程校验 region+project,离线失败 跳过,离线可改
config update 改 region/project/凭据/base-url/channel-key 校验 校验(不变)
config(主命令) 改存量、只改元数据 校验,离线失败 跳过,离线可改
config(主命令) 新建 profile 校验 校验(不变)
config add 任何 校验 校验(不变)

属能力增强(离线可改元数据),非破坏性。成功路径其余零变化。

不在本 PR 范围

…change

config update 与主命令 config 在改存量 profile 时无条件远程校验 region+project,
导致离线/网络抖动下仅改元数据(--active/--timeout-sec 等)也被拦。该守卫在 0.1.18
(2019-07-04)拆 add/update 时丢失,属7年回归:2018 单一 config 命令曾有
if cfg.Region!=""||cfg.Zone!="" 守卫。fail-closed(#142)放大了其痛。

改为按需校验(仅改「何时校验」,不改「校验失败怎么办」):
  credsOrEndpointChanged = 改了 public-key/private-key/base-url/channel-key
  validateRegion  = 传了 region/zone  || credsOrEndpointChanged  (主命令再 || !ok)
  validateProject = 传了 project-id    || credsOrEndpointChanged  (主命令再 || !ok)
只改元数据则两者皆跳过,离线可改;凭据/接入点变更须同时重校验 region 与 project
(换 key/网关后存量值可能失效或新凭据无权访问,配置时当场抓住才是校验价值)。
if 体内的 fail-closed return 与 errNoDefaultProject 放行原样不动。

config add 不改:新建 profile 无「未改动」基线,region/project 须从零建立(R2)。
主命令新建路径(!ok)恒校验(R3)。

测试:6 个新用例(毒网关证明跳过零远程调用、凭据变更触发双校验、新建仍校验),
2 个 #142 既有用例适配(纯元数据不再触发校验,改用 --region/--public-key 触发)。
已用变异测试验证 AC4 守护「凭据→project 校验」这一关键分支非空转。

CI 不含 ./cmd/...,用例须本地跑。堆叠在 #142 之上,PR 暂以 fix 分支为 base。
@github-actions

Copy link
Copy Markdown

🔴 平台 PR 默认硬拦,需管理员 Approve 放行(或由管理员提交)。判定:改动触及平台/受保护路径(cmd/configure.go, cmd/configure_test.go)

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.

1 participant