Merge pull request #311 from pikasTech/fix/hwlab-1119-d601-pk01-migration
fix: 收敛 D601 HWLAB PK01 migration 路径
This commit is contained in:
@@ -121,6 +121,11 @@ postgres:
|
||||
user: sub2api
|
||||
address: 10.0.8.0/22
|
||||
method: scram-sha-256
|
||||
- type: hostssl
|
||||
database: hwlab_d601_v03
|
||||
user: hwlab_d601_v03_app
|
||||
address: 10.0.8.0/22
|
||||
method: scram-sha-256
|
||||
- type: hostssl
|
||||
database: sub2api
|
||||
user: sub2api
|
||||
@@ -349,7 +354,7 @@ exports:
|
||||
sourceSecretRef: platform-db/hwlab-d601-v03-db.env
|
||||
render:
|
||||
envKey: DATABASE_URL
|
||||
format: postgresql://$(HWLAB_D601_V03_DB_USER):$(HWLAB_D601_V03_DB_PASSWORD)@$(PGHOST):5432/$(HWLAB_D601_V03_DB_NAME)?sslmode=require
|
||||
format: postgresql://$(HWLAB_D601_V03_DB_USER):$(HWLAB_D601_V03_DB_PASSWORD)@$(PGHOST):5432/$(HWLAB_D601_V03_DB_NAME)?sslmode=require&uselibpqcompat=true
|
||||
variables:
|
||||
PGHOST: 82.156.23.220
|
||||
writeToSecretSource:
|
||||
|
||||
@@ -24,6 +24,8 @@ CI/CD、GitOps、rollout、artifact 发布、PR 合并后的 runtime lane 滚动
|
||||
|
||||
`hwlab nodes control-plane infra tools-image status|build|logs --node D601 --lane v03` 是 D601 tools image 的受控入口。Dockerfile 必须由 `config/hwlab-node-control-plane.yaml` 的 `tekton.toolsImage.dockerfileInline` 声明,输入镜像必须列在 `publicBaseImages`,构建参数和网络模式也来自 YAML;confirmed build 只在 D601 后台异步构建并推送到 node-local registry,返回 status/logs 轮询命令。`hwlab nodes control-plane infra argo status|apply|logs --node D601 --lane v03` 是 D601 Argo CD 的声明式安装入口。Argo 版本、官方 manifest URL、镜像 rewrite/preload、field manager、imagePullPolicy、CRD 列表、期望 Deployment/StatefulSet 以及生成的 AppProject/Application 都必须来自同一个 YAML;`argo apply --confirm` 只执行可重复 server-side apply 和后台轮询,不把原生 `kubectl apply`、手工 Argo CLI 或临时 manifest 作为正式安装路径。
|
||||
|
||||
`hwlab nodes control-plane runtime-migration --node <node-id> --lane vNN [--dry-run|--allow-live-db-read --dry-run|--confirm]` 是 node-scoped runtime lane 的受控 schema migration 入口。它只通过目标 runtime namespace 当前 `deployment/hwlab-cloud-api -c hwlab-cloud-api` 内 repo-owned `cmd/hwlab-cloud-api/migrate.ts` 执行,输出 report path、source commit 和有界 stdout/stderr 摘要;不读取或打印 Secret 值、不手写 `psql`、不把 pod 内临时命令沉淀成正式流程。D601 v03 这类由 UniDesk YAML 声明的外置 PK01 PostgreSQL 切换,DB/Secret/bridge 仍以 UniDesk YAML 和 `platform-db postgres ...`、`hwlab nodes control-plane apply|trigger-current` 为 source truth;runtime migration 只负责在已发布 runtime 上补齐应用 schema。
|
||||
|
||||
## Command Model
|
||||
|
||||
- `help` 输出命令索引,适合作为交互式入口。
|
||||
|
||||
@@ -117,6 +117,8 @@ export function hwlabNodeHelp(): Record<string, unknown> {
|
||||
"bun scripts/cli.ts hwlab nodes control-plane refresh --node G14 --lane v03 --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes control-plane sync --node D601 --lane v03 --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes control-plane trigger-current --node G14 --lane v03 --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes control-plane runtime-migration --node D601 --lane v03 --dry-run",
|
||||
"bun scripts/cli.ts hwlab nodes control-plane runtime-migration --node D601 --lane v03 --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes control-plane allow-endpoint-bridge --node G14 --lane v03 --confirm",
|
||||
"bun scripts/cli.ts hwlab nodes git-mirror status --node G14 --lane v03",
|
||||
"bun scripts/cli.ts hwlab nodes secret status --node G14 --lane v03 --name hwlab-v03-openfga",
|
||||
@@ -142,7 +144,7 @@ async function runNodeDelegatedDomain(config: Config, domain: DelegatedNodeDomai
|
||||
}
|
||||
if (domain === "control-plane" && scoped.node !== defaultSpec.nodeId) {
|
||||
if (scoped.action === "status") return nodeRuntimeControlPlaneStatus(scoped);
|
||||
if (scoped.action === "apply" || scoped.action === "trigger-current" || scoped.action === "refresh" || scoped.action === "sync") {
|
||||
if (scoped.action === "apply" || scoped.action === "trigger-current" || scoped.action === "refresh" || scoped.action === "sync" || scoped.action === "runtime-migration") {
|
||||
if (scoped.confirm && !scoped.dryRun && !scoped.wait) return startNodeDelegatedJob(scoped);
|
||||
return nodeRuntimeControlPlaneRun(scoped);
|
||||
}
|
||||
@@ -183,6 +185,7 @@ function parseNodeScopedDelegatedOptions(domain: DelegatedNodeDomain, args: stri
|
||||
dryRun: boolean;
|
||||
wait: boolean;
|
||||
rerun: boolean;
|
||||
allowLiveDbRead: boolean;
|
||||
timeoutSeconds: number;
|
||||
originalArgs: string[];
|
||||
spec: HwlabRuntimeLaneSpec;
|
||||
@@ -206,6 +209,7 @@ function parseNodeScopedDelegatedOptions(domain: DelegatedNodeDomain, args: stri
|
||||
dryRun,
|
||||
wait: args.includes("--wait"),
|
||||
rerun: args.includes("--rerun"),
|
||||
allowLiveDbRead: args.includes("--allow-live-db-read"),
|
||||
timeoutSeconds: positiveIntegerOption(args, "--timeout-seconds", 1800, 3600),
|
||||
originalArgs: [...args],
|
||||
spec,
|
||||
@@ -343,7 +347,7 @@ function nodeRuntimeUnsupportedAction(scoped: ReturnType<typeof parseNodeScopedD
|
||||
lane: scoped.lane,
|
||||
mutation: false,
|
||||
degradedReason: "unsupported-node-scoped-runtime-action",
|
||||
message: "node-scoped runtime currently supports plan/status/apply/refresh/sync/trigger-current",
|
||||
message: "node-scoped runtime currently supports plan/status/apply/refresh/sync/trigger-current/runtime-migration",
|
||||
expected: nodeRuntimeExpected(scoped.spec),
|
||||
};
|
||||
}
|
||||
@@ -558,9 +562,83 @@ function nodeRuntimeControlPlaneRun(scoped: ReturnType<typeof parseNodeScopedDel
|
||||
if (scoped.action === "sync") return nodeRuntimeSync(scoped);
|
||||
if (scoped.action === "apply") return nodeRuntimeApply(scoped);
|
||||
if (scoped.action === "trigger-current") return nodeRuntimeTriggerCurrent(scoped);
|
||||
if (scoped.action === "runtime-migration") return nodeRuntimeMigration(scoped);
|
||||
return nodeRuntimeUnsupportedAction(scoped);
|
||||
}
|
||||
|
||||
function nodeRuntimeMigration(scoped: ReturnType<typeof parseNodeScopedDelegatedOptions>): Record<string, unknown> {
|
||||
const spec = scoped.spec;
|
||||
if (scoped.allowLiveDbRead && scoped.confirm) throw new Error("control-plane runtime-migration accepts --allow-live-db-read only with dry-run/source-check mode, not --confirm");
|
||||
if (!scoped.confirm && !scoped.dryRun) throw new Error("control-plane runtime-migration requires --dry-run or --confirm");
|
||||
const head = resolveNodeRuntimeLaneHead(spec);
|
||||
const sourceCommit = head.sourceCommit;
|
||||
if (sourceCommit === null) {
|
||||
return {
|
||||
ok: false,
|
||||
command: `hwlab nodes control-plane runtime-migration --node ${scoped.node} --lane ${scoped.lane}`,
|
||||
node: scoped.node,
|
||||
lane: scoped.lane,
|
||||
phase: "source-head",
|
||||
mutation: false,
|
||||
degradedReason: "node-runtime-source-head-unresolved",
|
||||
headProbe: compactRuntimeCommand(head.result),
|
||||
};
|
||||
}
|
||||
const reportPath = `/tmp/hwlab-${scoped.node.toLowerCase()}-${scoped.lane}-runtime-migration-${shortSha(sourceCommit)}.json`;
|
||||
const migrationArgs = scoped.dryRun
|
||||
? [
|
||||
...(scoped.allowLiveDbRead ? ["--dry-run", "--allow-live-db-read", "--confirm-dev"] : ["--check"]),
|
||||
"--report",
|
||||
reportPath,
|
||||
]
|
||||
: [
|
||||
"--apply",
|
||||
"--confirm-dev",
|
||||
"--confirmed-non-production",
|
||||
"--report",
|
||||
reportPath,
|
||||
];
|
||||
const result = runNodeK3sArgs(spec, [
|
||||
"kubectl",
|
||||
"exec",
|
||||
"-n",
|
||||
spec.runtimeNamespace,
|
||||
"deployment/hwlab-cloud-api",
|
||||
"-c",
|
||||
"hwlab-cloud-api",
|
||||
"--",
|
||||
"sh",
|
||||
"-lc",
|
||||
`cd /workspace/hwlab-boot/repo && exec bun cmd/hwlab-cloud-api/migrate.ts ${migrationArgs.map(shellQuote).join(" ")}`,
|
||||
], scoped.timeoutSeconds);
|
||||
const ok = isCommandSuccess(result);
|
||||
return {
|
||||
ok,
|
||||
command: `hwlab nodes control-plane runtime-migration --node ${scoped.node} --lane ${scoped.lane}`,
|
||||
node: scoped.node,
|
||||
lane: scoped.lane,
|
||||
mode: scoped.dryRun ? scoped.allowLiveDbRead ? "live-read-dry-run" : "source-check" : "confirmed-apply",
|
||||
sourceCommit,
|
||||
runtimeNamespace: spec.runtimeNamespace,
|
||||
target: "deployment/hwlab-cloud-api -c hwlab-cloud-api",
|
||||
workingDirectory: "/workspace/hwlab-boot/repo",
|
||||
migrationCommand: ["bun", "cmd/hwlab-cloud-api/migrate.ts", ...migrationArgs],
|
||||
reportPath,
|
||||
mutation: !scoped.dryRun && ok,
|
||||
result: compactRuntimeCommand(result),
|
||||
degradedReason: ok ? undefined : "node-runtime-migration-failed",
|
||||
next: scoped.dryRun
|
||||
? {
|
||||
liveReadDryRun: `bun scripts/cli.ts hwlab nodes control-plane runtime-migration --node ${scoped.node} --lane ${scoped.lane} --allow-live-db-read --dry-run`,
|
||||
apply: `bun scripts/cli.ts hwlab nodes control-plane runtime-migration --node ${scoped.node} --lane ${scoped.lane} --confirm`,
|
||||
}
|
||||
: {
|
||||
health: `curl -fsS --max-time 20 ${spec.publicApiUrl}/health/live`,
|
||||
status: `bun scripts/cli.ts hwlab nodes control-plane status --node ${scoped.node} --lane ${scoped.lane}`,
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
function nodeRuntimeApply(scoped: ReturnType<typeof parseNodeScopedDelegatedOptions>): Record<string, unknown> {
|
||||
const spec = scoped.spec;
|
||||
const head = resolveNodeRuntimeLaneHead(spec);
|
||||
|
||||
Reference in New Issue
Block a user