Реализован production-hardening по fix1: env/reconfigure, IPv4-only, TLS, secrets, firewall, docs
This commit is contained in:
+67
-34
@@ -1,8 +1,11 @@
|
||||
import { install } from "./commands/install";
|
||||
import type { InstallOptions } from "./types/context";
|
||||
import { reconfigure } from "./commands/reconfigure";
|
||||
import type { InstallOptions, ReconfigureOptions } from "./types/context";
|
||||
|
||||
function usage(): never {
|
||||
console.error("Usage: hy2xs-orchestrator install --package-dir <path> [--domain <name>] [--port <udp>] [--ssh-port <tcp>] [--skip-firewall] [--skip-start] [--ui-port <tcp>] [--ui-bind-host <host>] [--non-interactive]");
|
||||
console.error("Usage:");
|
||||
console.error(" hy2xs-orchestrator install --package-dir <path> [--config <path>] [--skip-firewall] [--skip-start] [--non-interactive]");
|
||||
console.error(" hy2xs-orchestrator reconfigure --package-dir <path> [--config <path>] [--dry-run|--apply] [--skip-firewall] [--skip-start]");
|
||||
process.exit(2);
|
||||
}
|
||||
|
||||
@@ -18,14 +21,10 @@ function takeValue(args: string[], index: number, flag: string): string {
|
||||
function parseInstallOptions(args: string[]): InstallOptions {
|
||||
const options: InstallOptions = {
|
||||
packageDir: "",
|
||||
configPath: "/etc/hy2xs/hy2xs.env",
|
||||
nonInteractive: false,
|
||||
domain: "",
|
||||
port: 443,
|
||||
sshPort: 22,
|
||||
skipFirewall: false,
|
||||
skipStart: false,
|
||||
uiPort: 8080,
|
||||
uiBindHost: "127.0.0.1"
|
||||
skipStart: false
|
||||
};
|
||||
|
||||
for (let i = 0; i < args.length; i += 1) {
|
||||
@@ -38,30 +37,14 @@ function parseInstallOptions(args: string[]): InstallOptions {
|
||||
case "--non-interactive":
|
||||
options.nonInteractive = true;
|
||||
break;
|
||||
case "--domain":
|
||||
options.domain = takeValue(args, i, arg);
|
||||
i += 1;
|
||||
break;
|
||||
case "--port":
|
||||
options.port = Number(takeValue(args, i, arg));
|
||||
i += 1;
|
||||
break;
|
||||
case "--ssh-port":
|
||||
options.sshPort = Number(takeValue(args, i, arg));
|
||||
i += 1;
|
||||
break;
|
||||
case "--skip-firewall":
|
||||
options.skipFirewall = true;
|
||||
break;
|
||||
case "--skip-start":
|
||||
options.skipStart = true;
|
||||
break;
|
||||
case "--ui-port":
|
||||
options.uiPort = Number(takeValue(args, i, arg));
|
||||
i += 1;
|
||||
break;
|
||||
case "--ui-bind-host":
|
||||
options.uiBindHost = takeValue(args, i, arg);
|
||||
case "--config":
|
||||
options.configPath = takeValue(args, i, arg);
|
||||
i += 1;
|
||||
break;
|
||||
default:
|
||||
@@ -75,23 +58,73 @@ function parseInstallOptions(args: string[]): InstallOptions {
|
||||
usage();
|
||||
}
|
||||
|
||||
for (const [name, value] of Object.entries({ port: options.port, sshPort: options.sshPort, uiPort: options.uiPort })) {
|
||||
if (!Number.isInteger(value) || value < 1 || value > 65535) {
|
||||
console.error(`Invalid ${name}: ${value}`);
|
||||
usage();
|
||||
return options;
|
||||
}
|
||||
|
||||
function parseReconfigureOptions(args: string[]): ReconfigureOptions {
|
||||
const options: ReconfigureOptions = {
|
||||
packageDir: "",
|
||||
configPath: "/etc/hy2xs/hy2xs.env",
|
||||
nonInteractive: false,
|
||||
dryRun: false,
|
||||
apply: false,
|
||||
skipFirewall: false,
|
||||
skipStart: 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.configPath = 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-start":
|
||||
options.skipStart = 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();
|
||||
}
|
||||
|
||||
return options;
|
||||
}
|
||||
|
||||
async function main(): Promise<void> {
|
||||
const [command, ...args] = Bun.argv.slice(2);
|
||||
if (command !== "install") {
|
||||
usage();
|
||||
if (command === "install") {
|
||||
await install(parseInstallOptions(args));
|
||||
return;
|
||||
}
|
||||
|
||||
await install(parseInstallOptions(args));
|
||||
if (command === "reconfigure") {
|
||||
await reconfigure(parseReconfigureOptions(args));
|
||||
return;
|
||||
}
|
||||
usage();
|
||||
}
|
||||
|
||||
main().catch((error: unknown) => {
|
||||
|
||||
Reference in New Issue
Block a user