fix: render sub2api apply output concisely
This commit is contained in:
@@ -71,7 +71,11 @@ export async function runPlatformInfraCommand(config: UniDeskConfig, args: strin
|
||||
const result = plan(parseTargetOptions(planArgs));
|
||||
return planArgs.includes("--full") || planArgs.includes("--raw") ? result : renderSub2ApiPlan(result);
|
||||
}
|
||||
if (action === "apply") return await apply(config, parseApplyOptions(args.slice(2)));
|
||||
if (action === "apply") {
|
||||
const options = parseApplyOptions(args.slice(2));
|
||||
const result = await apply(config, options);
|
||||
return options.full || options.raw ? result : renderSub2ApiApply(result);
|
||||
}
|
||||
if (action === "status") {
|
||||
const options = parseDisclosureOptions(args.slice(2));
|
||||
const result = await status(config, options);
|
||||
@@ -90,6 +94,8 @@ export interface ApplyOptions {
|
||||
dryRun: boolean;
|
||||
confirm: boolean;
|
||||
wait: boolean;
|
||||
full: boolean;
|
||||
raw: boolean;
|
||||
}
|
||||
|
||||
export interface DisclosureOptions {
|
||||
@@ -207,6 +213,126 @@ function renderSub2ApiStatus(result: Record<string, unknown>): RenderedCliResult
|
||||
return rendered(result, "platform-infra sub2api status", lines);
|
||||
}
|
||||
|
||||
function renderSub2ApiApply(result: Record<string, unknown>): RenderedCliResult {
|
||||
const target = record(result.target);
|
||||
const remote = record(result.remote);
|
||||
const policy = arrayRecords(result.policy);
|
||||
const failedPolicy = policy.filter((item) => item.ok === false);
|
||||
const mode = stringValue(result.mode);
|
||||
const targetId = stringValue(target.id, stringValue(result.target));
|
||||
const route = stringValue(target.route, stringValue(remote.route));
|
||||
const namespace = stringValue(target.namespace, "-");
|
||||
const status = result.ok === false ? "failed" : "ok";
|
||||
const lines = [
|
||||
"PLATFORM-INFRA SUB2API APPLY",
|
||||
...table(["TARGET", "ROUTE", "NAMESPACE", "MODE", "STATUS"], [[targetId, route, namespace, mode, status]]),
|
||||
"",
|
||||
"POLICY",
|
||||
failedPolicy.length === 0 ? "ok" : `failed=${failedPolicy.length}`,
|
||||
];
|
||||
|
||||
if (mode === "policy-blocked") {
|
||||
lines.push(
|
||||
"",
|
||||
"FAILED POLICY",
|
||||
...(failedPolicy.length === 0 ? ["-"] : table(["NAME", "DETAIL"], failedPolicy.map((item) => [stringValue(item.name), stringValue(item.detail)]))),
|
||||
"",
|
||||
"NEXT",
|
||||
` plan: bun scripts/cli.ts platform-infra sub2api plan --target ${targetId}`,
|
||||
` full: bun scripts/cli.ts platform-infra sub2api apply --target ${targetId} --dry-run --full`,
|
||||
);
|
||||
return rendered(result, "platform-infra sub2api apply", lines);
|
||||
}
|
||||
|
||||
if (mode === "async-job") {
|
||||
const job = record(result.job);
|
||||
const next = record(result.next);
|
||||
lines.push(
|
||||
"",
|
||||
"JOB",
|
||||
...table(["ID", "STATUS", "COMMAND"], [[stringValue(job.id), stringValue(job.status, "started"), stringValue(result.statusCommand)]]),
|
||||
"",
|
||||
"NEXT",
|
||||
` status: ${stringValue(next.status, stringValue(result.statusCommand))}`,
|
||||
` rollout: ${stringValue(next.rollout, `bun scripts/cli.ts platform-infra sub2api status --target ${targetId}`)}`,
|
||||
` validate: ${stringValue(next.validate, `bun scripts/cli.ts platform-infra sub2api validate --target ${targetId}`)}`,
|
||||
` full: bun scripts/cli.ts platform-infra sub2api apply --target ${targetId} --confirm --wait --full`,
|
||||
);
|
||||
return rendered(result, "platform-infra sub2api apply", lines);
|
||||
}
|
||||
|
||||
lines.push(
|
||||
"",
|
||||
"REMOTE",
|
||||
...renderApplyRemoteSummary(remote),
|
||||
);
|
||||
|
||||
const pk01Exposure = record(result.pk01Exposure);
|
||||
if (Object.keys(pk01Exposure).length > 0) {
|
||||
lines.push(
|
||||
"",
|
||||
"PK01_EXPOSURE",
|
||||
...table(["CHECK", "VALUE"], [
|
||||
["ok", boolText(pk01Exposure.ok)],
|
||||
["mode", stringValue(pk01Exposure.mode)],
|
||||
["valuesPrinted", "false"],
|
||||
]),
|
||||
);
|
||||
}
|
||||
|
||||
const next = record(result.next);
|
||||
lines.push(
|
||||
"",
|
||||
"NEXT",
|
||||
` status: ${stringValue(next.status, `bun scripts/cli.ts platform-infra sub2api status --target ${targetId}`)}`,
|
||||
` validate: ${stringValue(next.validate, `bun scripts/cli.ts platform-infra sub2api validate --target ${targetId}`)}`,
|
||||
` full: bun scripts/cli.ts platform-infra sub2api apply --target ${targetId} ${mode === "confirmed" ? "--confirm --wait" : "--dry-run"} --full`,
|
||||
"Disclosure: default output is bounded; use --full or --raw for remote stdout/stderr details.",
|
||||
);
|
||||
return rendered(result, "platform-infra sub2api apply", lines);
|
||||
}
|
||||
|
||||
function renderApplyRemoteSummary(remote: Record<string, unknown>): string[] {
|
||||
const steps = record(remote.steps);
|
||||
const stepRows = Object.entries(steps).map(([name, value]) => {
|
||||
const step = record(value);
|
||||
return [name, stringValue(step.exitCode), step.exitCode === 0 ? "ok" : "failed"];
|
||||
});
|
||||
for (const name of ["clientDryRun", "serverDryRun", "accountLocalProxySecretDryRun"]) {
|
||||
const step = record(remote[name]);
|
||||
if (step.exitCode !== undefined) stepRows.push([name, stringValue(step.exitCode), step.exitCode === 0 ? "ok" : "failed"]);
|
||||
}
|
||||
const ports = record(remote.ports);
|
||||
const runtime = stringValue(remote.runtimeMode, record(remote.serverDryRun).exitCode !== undefined ? "k3s" : "-");
|
||||
const rows = [
|
||||
["ok", boolText(remote.ok), "runtime", runtime],
|
||||
["target", stringValue(remote.target), "route", stringValue(remote.route)],
|
||||
];
|
||||
if (remote.namespace !== undefined) rows.push(["namespace", stringValue(remote.namespace), "existsBeforeDryRun", boolText(remote.namespaceExistsBeforeDryRun)]);
|
||||
if (remote.image !== undefined || remote.projectName !== undefined) rows.push(["image", stringValue(remote.image), "project", stringValue(remote.projectName)]);
|
||||
const lines = [
|
||||
...table(["FIELD", "VALUE", "DETAIL", "VALUE"], rows),
|
||||
];
|
||||
if (Object.keys(ports).length > 0) {
|
||||
lines.push(
|
||||
"",
|
||||
"PORTS",
|
||||
...table(["NAME", "VALUE"], [
|
||||
["app", stringValue(ports.app)],
|
||||
["redis", stringValue(ports.redis)],
|
||||
["observed", stringValue(ports.observed).replace(/\s+/gu, " ").trim()],
|
||||
]),
|
||||
);
|
||||
}
|
||||
lines.push(
|
||||
"",
|
||||
"STEPS",
|
||||
...(stepRows.length === 0 ? ["-"] : table(["STEP", "EXIT", "STATUS"], stepRows)),
|
||||
"valuesPrinted=false",
|
||||
);
|
||||
return lines;
|
||||
}
|
||||
|
||||
function rendered(result: Record<string, unknown>, command: string, lines: string[]): RenderedCliResult {
|
||||
return {
|
||||
ok: result.ok !== false,
|
||||
@@ -254,13 +380,16 @@ export function unsupported(args: string[]): Record<string, unknown> {
|
||||
|
||||
export function parseApplyOptions(args: string[]): ApplyOptions {
|
||||
const target = parseTargetOptions(args);
|
||||
validateOptions(args, new Set(["--dry-run", "--confirm", "--wait", "--target"]));
|
||||
validateOptions(args, new Set(["--dry-run", "--confirm", "--wait", "--target", "--full", "--raw"]));
|
||||
if (args.includes("--dry-run") && args.includes("--confirm")) throw new Error("apply accepts only one of --dry-run or --confirm");
|
||||
const raw = args.includes("--raw");
|
||||
return {
|
||||
targetId: target.targetId,
|
||||
dryRun: args.includes("--dry-run") || !args.includes("--confirm"),
|
||||
confirm: args.includes("--confirm"),
|
||||
wait: args.includes("--wait"),
|
||||
full: raw || args.includes("--full"),
|
||||
raw,
|
||||
};
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user