Files
HY2XS_flamy/orchestrator/src/cli.ts
T

259 lines
7.6 KiB
TypeScript

import { install } from "./commands/install";
import { reconfigure, repair } from "./commands/reconfigure";
import { doctor } from "./commands/doctor";
import { status } from "./commands/status";
import { diagnosticsCollect } from "./commands/diagnostics";
import { redactConfig, type RedactConfigFormat } from "./commands/redact-config";
import type { InstallOptions, ReconfigureOptions } from "./types/context";
function usage(): never {
console.error("Usage:");
console.error(" hy2xs-orchestrator install --package-dir <path> [--config <path>] [--skip-firewall] [--skip-service-start] [--skip-smoke] [--non-interactive]");
console.error(" hy2xs-orchestrator reconfigure --package-dir <path> [--config <path>] [--dry-run|--apply] [--skip-firewall] [--skip-service-start] [--skip-smoke]");
console.error(" hy2xs-orchestrator repair --package-dir <path> [--config <path>] [--skip-firewall] [--skip-service-start] [--skip-smoke]");
console.error(" hy2xs-orchestrator doctor --package-dir <path> [--config <path>] [--skip-firewall] [--skip-service-start] [--skip-smoke]");
console.error(" hy2xs-orchestrator status --package-dir <path> [--config <path>] [--skip-firewall] [--skip-service-start] [--skip-smoke]");
console.error(" hy2xs-orchestrator diagnostics collect --package-dir <path> [--config <path>] [--skip-firewall] [--skip-service-start] [--skip-smoke]");
console.error(" hy2xs-orchestrator redact-config --config <path> [--in-place | --out <path>] [--format auto|env|yaml]");
console.error(" note: --skip-start is deprecated alias for --skip-service-start --skip-smoke");
process.exit(2);
}
function parseRedactConfigOptions(args: string[]): {
configPath: string;
outPath: string;
inPlace: boolean;
format: RedactConfigFormat;
} {
let configPath = "";
let outPath = "";
let inPlace = false;
let format: RedactConfigFormat = "auto";
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
switch (arg) {
case "--config":
configPath = takeValue(args, i, arg);
i += 1;
break;
case "--out":
outPath = takeValue(args, i, arg);
i += 1;
break;
case "--in-place":
inPlace = true;
break;
case "--format": {
const value = takeValue(args, i, arg);
if (value !== "auto" && value !== "env" && value !== "yaml") {
console.error(`invalid --format value: ${value}`);
usage();
}
format = value;
i += 1;
break;
}
default:
console.error(`Unknown argument: ${arg}`);
usage();
}
}
if (!configPath) {
console.error("Missing --config");
usage();
}
if (inPlace === (outPath !== "")) {
console.error("Specify exactly one of --in-place or --out <path>");
usage();
}
return { configPath, outPath, inPlace, format };
}
function takeValue(args: string[], index: number, flag: string): string {
const value = args[index + 1];
if (!value || value.startsWith("--")) {
console.error(`Missing value for ${flag}`);
usage();
}
return value;
}
function parseInstallOptions(args: string[]): InstallOptions {
const options: InstallOptions = {
packageDir: "",
sourceConfigPath: "",
runtimeConfigPath: "/etc/hy2xs/hy2xs.env",
nonInteractive: false,
skipFirewall: false,
skipServiceStart: false,
skipSmoke: false
};
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
switch (arg) {
case "--package-dir":
options.packageDir = takeValue(args, i, arg);
i += 1;
break;
case "--non-interactive":
options.nonInteractive = true;
break;
case "--skip-firewall":
options.skipFirewall = true;
break;
case "--skip-service-start":
options.skipServiceStart = true;
break;
case "--skip-smoke":
options.skipSmoke = true;
break;
case "--skip-start":
console.error("warning: --skip-start is deprecated; use --skip-service-start and/or --skip-smoke");
options.skipServiceStart = true;
options.skipSmoke = true;
break;
case "--config":
options.sourceConfigPath = takeValue(args, i, arg);
i += 1;
break;
default:
console.error(`Unknown argument: ${arg}`);
usage();
}
}
if (!options.packageDir) {
console.error("Missing --package-dir");
usage();
}
if (options.skipSmoke && process.env.HY2XS_BREAK_GLASS !== "1") {
console.error("--skip-smoke is break-glass only. Set HY2XS_BREAK_GLASS=1 to continue.");
usage();
}
return options;
}
function parseReconfigureOptions(args: string[]): ReconfigureOptions {
const options: ReconfigureOptions = {
packageDir: "",
sourceConfigPath: "/etc/hy2xs/hy2xs.env",
runtimeConfigPath: "/etc/hy2xs/hy2xs.env",
nonInteractive: false,
dryRun: false,
apply: false,
skipFirewall: false,
skipServiceStart: false,
skipSmoke: false
};
for (let i = 0; i < args.length; i += 1) {
const arg = args[i];
switch (arg) {
case "--package-dir":
options.packageDir = takeValue(args, i, arg);
i += 1;
break;
case "--config":
options.sourceConfigPath = takeValue(args, i, arg);
i += 1;
break;
case "--dry-run":
options.dryRun = true;
break;
case "--apply":
options.apply = true;
break;
case "--skip-firewall":
options.skipFirewall = true;
break;
case "--skip-service-start":
options.skipServiceStart = true;
break;
case "--skip-smoke":
options.skipSmoke = true;
break;
case "--skip-start":
console.error("warning: --skip-start is deprecated; use --skip-service-start and/or --skip-smoke");
options.skipServiceStart = true;
options.skipSmoke = true;
break;
default:
console.error(`Unknown argument: ${arg}`);
usage();
}
}
if (!options.packageDir) {
console.error("Missing --package-dir");
usage();
}
if (options.dryRun === options.apply) {
console.error("Specify exactly one of --dry-run or --apply");
usage();
}
if (options.skipSmoke && process.env.HY2XS_BREAK_GLASS !== "1") {
console.error("--skip-smoke is break-glass only. Set HY2XS_BREAK_GLASS=1 to continue.");
usage();
}
return options;
}
function parseCommonOptions(args: string[]): InstallOptions {
return parseInstallOptions(args);
}
async function main(): Promise<void> {
const [command, ...args] = Bun.argv.slice(2);
if (command === "install") {
await install(parseInstallOptions(args));
return;
}
if (command === "reconfigure") {
await reconfigure(parseReconfigureOptions(args));
return;
}
if (command === "repair") {
const options = parseReconfigureOptions(["--apply", ...args]);
await repair(options);
return;
}
if (command === "doctor") {
const options = parseReconfigureOptions(["--dry-run", ...args]);
await doctor(options);
return;
}
if (command === "status") {
await status(parseCommonOptions(args));
return;
}
if (command === "diagnostics") {
const [subcommand, ...rest] = args;
if (subcommand !== "collect") {
usage();
}
await diagnosticsCollect(parseCommonOptions(rest));
return;
}
if (command === "redact-config") {
await redactConfig(parseRedactConfigOptions(args));
return;
}
usage();
}
main().catch((error: unknown) => {
const message = error instanceof Error ? error.message : String(error);
console.error(`[hy2xs] ERROR: ${message}`);
process.exit(1);
});