fix: add code queue kubeconfig fallback
This commit is contained in:
@@ -2,11 +2,16 @@ import assert from "node:assert/strict";
|
||||
import test from "node:test";
|
||||
|
||||
import {
|
||||
buildKubectlCommandPrefix,
|
||||
compareRuntimeIdentityEnv,
|
||||
decideDevTemplateJobReplacement,
|
||||
formatKubeconfigAccessFailure,
|
||||
inspectCodeAgentProviderDesiredState,
|
||||
inspectCodeAgentProviderLiveDeployment,
|
||||
resolveApplySourceCommit
|
||||
parseArgs,
|
||||
redactSensitiveText,
|
||||
resolveApplySourceCommit,
|
||||
resolveDevKubeconfigSelection
|
||||
} from "./dev-deploy-apply.mjs";
|
||||
|
||||
const codeAgentBaseUrl = "http://172.26.26.227:17680/v1/responses";
|
||||
@@ -232,3 +237,122 @@ test("Code Agent live Deployment inspection reads only env metadata", () => {
|
||||
assert.equal(inspection.kubernetesSecretDataRead, false);
|
||||
assert.equal(inspection.validationScope, "deployment-env-and-secretKeyRef-metadata-only");
|
||||
});
|
||||
|
||||
test("DEV kubeconfig selection prefers flag then HWLAB_DEV_KUBECONFIG then KUBECONFIG then D601 default", () => {
|
||||
assert.deepEqual(
|
||||
resolveDevKubeconfigSelection({
|
||||
flagValue: "/tmp/from-flag",
|
||||
env: {
|
||||
HWLAB_DEV_KUBECONFIG: "/tmp/from-hwlab",
|
||||
KUBECONFIG: "/tmp/from-kubeconfig"
|
||||
}
|
||||
}),
|
||||
{
|
||||
kubeconfig: "/tmp/from-flag",
|
||||
source: "flag:--kubeconfig",
|
||||
paths: ["/tmp/from-flag"]
|
||||
}
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
resolveDevKubeconfigSelection({
|
||||
env: {
|
||||
HWLAB_DEV_KUBECONFIG: "/tmp/from-hwlab",
|
||||
KUBECONFIG: "/tmp/from-kubeconfig"
|
||||
}
|
||||
}),
|
||||
{
|
||||
kubeconfig: "/tmp/from-hwlab",
|
||||
source: "env:HWLAB_DEV_KUBECONFIG",
|
||||
paths: ["/tmp/from-hwlab"]
|
||||
}
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
resolveDevKubeconfigSelection({
|
||||
env: {
|
||||
KUBECONFIG: "/tmp/from-kubeconfig"
|
||||
}
|
||||
}),
|
||||
{
|
||||
kubeconfig: "/tmp/from-kubeconfig",
|
||||
source: "env:KUBECONFIG",
|
||||
paths: ["/tmp/from-kubeconfig"]
|
||||
}
|
||||
);
|
||||
|
||||
assert.deepEqual(
|
||||
resolveDevKubeconfigSelection({ env: {} }),
|
||||
{
|
||||
kubeconfig: "/etc/rancher/k3s/k3s.yaml",
|
||||
source: "default:d601-k3s",
|
||||
paths: ["/etc/rancher/k3s/k3s.yaml"]
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
test("DEV kubeconfig selection keeps multi-path KUBECONFIG readable checks explicit", () => {
|
||||
const delimiter = process.platform === "win32" ? ";" : ":";
|
||||
const selection = resolveDevKubeconfigSelection({
|
||||
env: {
|
||||
KUBECONFIG: [`/tmp/one`, `/tmp/two`].join(delimiter)
|
||||
}
|
||||
});
|
||||
|
||||
assert.equal(selection.kubeconfig, [`/tmp/one`, `/tmp/two`].join(delimiter));
|
||||
assert.equal(selection.source, "env:KUBECONFIG");
|
||||
assert.deepEqual(selection.paths, ["/tmp/one", "/tmp/two"]);
|
||||
});
|
||||
|
||||
test("kubectl command prefix quotes kubeconfig paths without exposing contents", () => {
|
||||
assert.equal(
|
||||
buildKubectlCommandPrefix("/var/lib/unidesk/code-queue/kubeconfig"),
|
||||
"KUBECONFIG=/var/lib/unidesk/code-queue/kubeconfig kubectl"
|
||||
);
|
||||
assert.equal(
|
||||
buildKubectlCommandPrefix("/tmp/path with space/kubeconfig"),
|
||||
"KUBECONFIG='/tmp/path with space/kubeconfig' kubectl"
|
||||
);
|
||||
});
|
||||
|
||||
test("kubeconfig access failure names source and path without secret material", () => {
|
||||
const message = formatKubeconfigAccessFailure(
|
||||
{
|
||||
source: "env:HWLAB_DEV_KUBECONFIG"
|
||||
},
|
||||
"/missing/kubeconfig"
|
||||
);
|
||||
|
||||
assert.match(message, /env:HWLAB_DEV_KUBECONFIG/u);
|
||||
assert.match(message, /\/missing\/kubeconfig/u);
|
||||
assert.match(message, /Secret values are never printed/u);
|
||||
assert.equal(message.includes("client-key-data:"), false);
|
||||
});
|
||||
|
||||
test("parseArgs reports a missing kubeconfig path as a blocking error", () => {
|
||||
const args = parseArgs(["--apply", "--kubeconfig"]);
|
||||
assert.equal(args.apply, true);
|
||||
assert.equal(args.kubeconfigSpecified, true);
|
||||
assert.deepEqual(args.errors, ["--kubeconfig requires a non-empty path value"]);
|
||||
});
|
||||
|
||||
test("redaction removes common token and password material from kubectl output", () => {
|
||||
const output = redactSensitiveText(
|
||||
[
|
||||
"Authorization: Bearer abc.def-123",
|
||||
"token: abcdef123456",
|
||||
"password=plain-secret",
|
||||
"client-key-data: LS0tPRIVATE",
|
||||
"postgresql://hwlab:db-secret@example.invalid:5432/hwlab"
|
||||
].join("\n")
|
||||
);
|
||||
|
||||
assert.equal(output.includes("abc.def-123"), false);
|
||||
assert.equal(output.includes("plain-secret"), false);
|
||||
assert.equal(output.includes("LS0tPRIVATE"), false);
|
||||
assert.equal(output.includes("db-secret"), false);
|
||||
assert.match(output, /Bearer <redacted>/u);
|
||||
assert.match(output, /password=<redacted>/u);
|
||||
assert.match(output, /client-key-data: <redacted>/u);
|
||||
assert.match(output, /postgresql:\/\/hwlab:<redacted>@example.invalid/u);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user