Files
pikasTech-HWLAB/scripts/src/dev-runtime-hotfix-audit.test.mjs
T
Lyon 9d143874f8 docs: add DEV runtime hotfix runbook and audit
Refs #462\nRefs #465\nRefs #7\nRefs #239
2026-05-24 20:26:21 +08:00

159 lines
5.8 KiB
JavaScript

import assert from "node:assert/strict";
import test from "node:test";
import {
assertReadonlyKubectlArgs,
buildDevRuntimeHotfixAuditReport,
parseArgs
} from "./dev-runtime-hotfix-audit.mjs";
test("plan mode emits a bounded read-only plan and runs no kubectl commands", async () => {
let commandCount = 0;
const report = await buildDevRuntimeHotfixAuditReport(parseArgs(["--plan"]), {
runCommand: async () => {
commandCount += 1;
throw new Error("plan mode must not execute commands");
}
});
assert.equal(commandCount, 0);
assert.equal(report.mode, "plan");
assert.equal(report.safety.k8sWriteAttempted, false);
assert.deepEqual(report.classifications, [
"source-artifact-expected",
"unknown-needs-manual-readonly-check"
]);
assert.ok(report.commandPlan.readonly.every((command) => command.includes("KUBECONFIG=/etc/rancher/k3s/k3s.yaml")));
assert.ok(report.commandPlan.forbiddenDefaultOperations.some((command) => command.includes("kubectl patch")));
});
test("collect-readonly classifies active ConfigMap mount and pod marker without write verbs", async () => {
const commands = [];
const report = await buildDevRuntimeHotfixAuditReport(parseArgs(["--collect-readonly"]), {
runCommand: async ({ args, displayCommand }) => {
commands.push(displayCommand);
return fixtureResult(args);
}
});
assert.equal(report.mode, "collect-readonly");
assert.equal(report.safety.k8sWriteAttempted, false);
assert.ok(report.classifications.includes("hotfix-configmap-present"));
assert.ok(report.classifications.includes("deployment-mounts-hotfix"));
assert.ok(report.classifications.includes("pod-loads-hotfix-marker"));
assert.ok(report.classifications.includes("rollback-required"));
assert.equal(report.conclusion.status, "hotfix-detected");
assert.ok(commands.length > 0);
assertNoWriteVerbs(commands);
});
test("collect-readonly reports no-hotfix-detected when ConfigMap and mount are absent", async () => {
const report = await buildDevRuntimeHotfixAuditReport(parseArgs(["--collect-readonly"]), {
runCommand: async ({ args }) => fixtureResult(args, { noHotfix: true })
});
assert.deepEqual(report.classifications, [
"source-artifact-expected",
"no-hotfix-detected"
]);
assert.equal(report.conclusion.status, "clear");
});
test("collect-readonly keeps unknown classification when D601 node cannot be proven", async () => {
const report = await buildDevRuntimeHotfixAuditReport(parseArgs(["--collect-readonly"]), {
runCommand: async ({ args }) => {
if (args.includes("nodes")) {
return { ok: false, exitCode: 1, stdout: "", stderr: "unable to connect to the server" };
}
return fixtureResult(args);
}
});
assert.ok(report.classifications.includes("unknown-needs-manual-readonly-check"));
assert.notEqual(report.conclusion.status, "clear");
});
test("kubectl write verbs are rejected by the audit helper", () => {
assert.throws(() => assertReadonlyKubectlArgs(["-n", "hwlab-dev", "patch", "deployment", "hwlab-cloud-api"]), /forbidden/u);
assert.throws(() => assertReadonlyKubectlArgs(["-n", "hwlab-dev", "rollout", "restart", "deployment", "hwlab-cloud-api"]), /forbidden/u);
});
function fixtureResult(args, options = {}) {
const text = args.join(" ");
if (text.includes("get nodes")) {
return okJson({ items: [{ metadata: { name: "d601" } }] });
}
if (text.includes("get configmap")) {
if (options.noHotfix) {
return { ok: false, exitCode: 1, stdout: "", stderr: "Error from server (NotFound): configmaps \"hwlab-cloud-api-code-agent-hotfix\" not found" };
}
return okJson({ data: { "code-agent-chat.mjs": "// runtime-hotfix-pc-gateway-shell" } });
}
if (text.includes("get deployment")) {
return okJson(deploymentFixture({ noHotfix: options.noHotfix }));
}
if (text.includes("get pods")) {
return okJson({
items: [{
metadata: { name: "hwlab-cloud-api-abc", creationTimestamp: "2026-05-24T00:00:00Z" },
status: { phase: "Running" },
spec: { nodeName: "d601" }
}]
});
}
if (text.includes("exec") && text.includes("grep")) {
return options.noHotfix
? { ok: false, exitCode: 1, stdout: "", stderr: "" }
: { ok: true, exitCode: 0, stdout: "1:runtime-hotfix-pc-gateway-shell\n", stderr: "" };
}
if (text.includes("exec") && text.includes("node --check")) {
return { ok: true, exitCode: 0, stdout: "", stderr: "" };
}
throw new Error(`unexpected fixture command: ${text}`);
}
function deploymentFixture({ noHotfix = false } = {}) {
return {
metadata: { generation: 9 },
spec: {
template: {
metadata: {
annotations: noHotfix ? {} : {
"hwlab.pikastech.local/pc-gateway-shell-hotfix": "runtime-hotfix"
}
},
spec: {
volumes: noHotfix ? [] : [{
name: "code-agent-hotfix",
configMap: {
name: "hwlab-cloud-api-code-agent-hotfix",
items: [{ key: "code-agent-chat.mjs", path: "code-agent-chat.mjs" }]
}
}],
containers: [{
name: "hwlab-cloud-api",
image: "127.0.0.1:5000/hwlab/hwlab-cloud-api:dev",
volumeMounts: noHotfix ? [] : [{
name: "code-agent-hotfix",
mountPath: "/app/internal/cloud/code-agent-chat.mjs",
subPath: "code-agent-chat.mjs",
readOnly: true
}]
}]
}
}
}
};
}
function okJson(value) {
return { ok: true, exitCode: 0, stdout: JSON.stringify(value), stderr: "" };
}
function assertNoWriteVerbs(commands) {
const forbidden = /\bkubectl\s+(?:apply|patch|rollout|delete|create|replace|scale|set|edit|annotate|label)\b/u;
for (const command of commands) {
assert.doesNotMatch(command, forbidden, command);
}
}