feature: Begins work on backend command.
This commit is contained in:
parent
99f76d875b
commit
213455b050
2 changed files with 196 additions and 8 deletions
|
@ -68,6 +68,8 @@ export function route(routeOptions: RouteOptions) {
|
||||||
return {
|
return {
|
||||||
success: true,
|
success: true,
|
||||||
data: prismaBackends.map(i => ({
|
data: prismaBackends.map(i => ({
|
||||||
|
id: i.id,
|
||||||
|
|
||||||
name: i.name,
|
name: i.name,
|
||||||
description: i.description,
|
description: i.description,
|
||||||
|
|
||||||
|
|
|
@ -3,19 +3,31 @@ import type { Axios } from "axios";
|
||||||
import { SSHCommand } from "../libs/patchCommander.js";
|
import { SSHCommand } from "../libs/patchCommander.js";
|
||||||
import type { PrintLine } from "../commands.js";
|
import type { PrintLine } from "../commands.js";
|
||||||
|
|
||||||
|
type BackendLookupSuccess = {
|
||||||
|
success: boolean,
|
||||||
|
data: {
|
||||||
|
id: number,
|
||||||
|
|
||||||
|
name: string,
|
||||||
|
description: string,
|
||||||
|
backend: string,
|
||||||
|
connectionDetails?: string,
|
||||||
|
logs: string[]
|
||||||
|
}[];
|
||||||
|
};
|
||||||
|
|
||||||
export async function run(
|
export async function run(
|
||||||
argv: string[],
|
argv: string[],
|
||||||
println: PrintLine,
|
println: PrintLine,
|
||||||
axios: Axios,
|
axios: Axios,
|
||||||
apiKey: string,
|
token: string,
|
||||||
) {
|
) {
|
||||||
if (argv.length == 1) return println("error: no arguments specified! run %s --help to see commands.\n", argv[0]);
|
|
||||||
|
|
||||||
const program = new SSHCommand(println);
|
const program = new SSHCommand(println);
|
||||||
program.description("Manages backends for NextNet");
|
program.description("Manages backends for NextNet");
|
||||||
program.version("v0.1.0-preprod");
|
program.version("v0.1.0-preprod");
|
||||||
|
|
||||||
const addBackend = new SSHCommand(println, "add");
|
const addBackend = new SSHCommand(println, "add");
|
||||||
|
|
||||||
addBackend.description("Adds a backend");
|
addBackend.description("Adds a backend");
|
||||||
addBackend.argument("<name>", "Name of the backend");
|
addBackend.argument("<name>", "Name of the backend");
|
||||||
|
|
||||||
|
@ -25,7 +37,7 @@ export async function run(
|
||||||
);
|
);
|
||||||
|
|
||||||
addBackend.option(
|
addBackend.option(
|
||||||
"-d, --description",
|
"-d, --description <description>",
|
||||||
"Description for the backend",
|
"Description for the backend",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -35,13 +47,13 @@ export async function run(
|
||||||
);
|
);
|
||||||
|
|
||||||
addBackend.option(
|
addBackend.option(
|
||||||
"-c, --custom-parameters",
|
"-c, --custom-parameters <parameters>",
|
||||||
"Custom parameters. Use this if the backend you're using isn't native to SSH yet, or if you manually turn on -f.",
|
"Custom parameters. Use this if the backend you're using isn't native to SSH yet, or if you manually turn on -f.",
|
||||||
);
|
);
|
||||||
|
|
||||||
// SSH provider
|
// SSH provider
|
||||||
addBackend.option(
|
addBackend.option(
|
||||||
"-k, --ssh-key",
|
"-k, --ssh-key <private-key>",
|
||||||
"(SSH) SSH private key to use to authenticate with the server",
|
"(SSH) SSH private key to use to authenticate with the server",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -62,7 +74,7 @@ export async function run(
|
||||||
);
|
);
|
||||||
|
|
||||||
addBackend.option(
|
addBackend.option(
|
||||||
"-pp, --proxied-port",
|
"-pp, --proxied-port <port>",
|
||||||
"(PassyFire) If you're behind a proxy, and the port is different, specify the port to return",
|
"(PassyFire) If you're behind a proxy, and the port is different, specify the port to return",
|
||||||
);
|
);
|
||||||
|
|
||||||
|
@ -80,15 +92,189 @@ export async function run(
|
||||||
|
|
||||||
const removeBackend = new SSHCommand(println, "rm");
|
const removeBackend = new SSHCommand(println, "rm");
|
||||||
removeBackend.description("Removes a backend");
|
removeBackend.description("Removes a backend");
|
||||||
removeBackend.argument("<id>", "Id of the backend");
|
removeBackend.argument("<id>", "ID of the backend");
|
||||||
|
|
||||||
|
removeBackend.action(async(idStr: string) => {
|
||||||
|
const id: number = parseInt(idStr);
|
||||||
|
|
||||||
|
if (Number.isNaN(id)) {
|
||||||
|
println("ID (%s) is not a number.\n", idStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios.post("/api/v1/backends/remove", {
|
||||||
|
token,
|
||||||
|
id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status != 200) {
|
||||||
|
if (process.env.NODE_ENV != "production") console.log(response);
|
||||||
|
|
||||||
|
if (response.data.error) {
|
||||||
|
println(`Error: ${response.data.error}\n`);
|
||||||
|
} else {
|
||||||
|
println("Error deleting backend!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
println("Backend has been successfully deleted.\n");
|
||||||
|
});
|
||||||
|
|
||||||
const lookupBackend = new SSHCommand(println, "find");
|
const lookupBackend = new SSHCommand(println, "find");
|
||||||
lookupBackend.description("Looks up a backend based on your arguments");
|
lookupBackend.description("Looks up a backend based on your arguments");
|
||||||
|
|
||||||
|
lookupBackend.option("-n, --name <name>", "Name of the backend");
|
||||||
|
|
||||||
|
lookupBackend.option(
|
||||||
|
"-p, --provider <provider>",
|
||||||
|
"Provider of the backend (ex. passyfire, ssh)",
|
||||||
|
);
|
||||||
|
|
||||||
|
lookupBackend.option(
|
||||||
|
"-d, --description <description>",
|
||||||
|
"Description for the backend",
|
||||||
|
);
|
||||||
|
|
||||||
|
lookupBackend.option(
|
||||||
|
"-e, --parse-connection-details",
|
||||||
|
"If specified, we automatically parse the connection details to make them human readable, if standard JSON."
|
||||||
|
);
|
||||||
|
|
||||||
|
lookupBackend.action(async(options: {
|
||||||
|
name?: string,
|
||||||
|
provider?: string,
|
||||||
|
description?: string,
|
||||||
|
parseConnectionDetails?: boolean
|
||||||
|
}) => {
|
||||||
|
const response = await axios.post("/api/v1/backends/lookup", {
|
||||||
|
token,
|
||||||
|
|
||||||
|
name: options.name,
|
||||||
|
description: options.description,
|
||||||
|
|
||||||
|
backend: options.provider
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status != 200) {
|
||||||
|
if (process.env.NODE_ENV != "production") console.log(response);
|
||||||
|
|
||||||
|
if (response.data.error) {
|
||||||
|
println(`Error: ${response.data.error}\n`);
|
||||||
|
} else {
|
||||||
|
println("Error stopping a connection!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data }: BackendLookupSuccess = response.data;
|
||||||
|
|
||||||
|
for (const backend of data) {
|
||||||
|
println("ID: %s:\n", backend.id);
|
||||||
|
println(" - Name: %s\n", backend.name);
|
||||||
|
println(" - Description: %s\n", backend.description);
|
||||||
|
println(" - Using Backend: %s\n", backend.backend);
|
||||||
|
|
||||||
|
if (backend.connectionDetails) {
|
||||||
|
if (options.parseConnectionDetails) {
|
||||||
|
// We don't know what we're recieving. We just try to parse it (hence the any type)
|
||||||
|
// {} is more accurate but TS yells at us if we do that :(
|
||||||
|
|
||||||
|
let parsedJSONData: any | undefined;
|
||||||
|
|
||||||
|
try {
|
||||||
|
parsedJSONData = JSON.parse(backend.connectionDetails);
|
||||||
|
} catch (e) {
|
||||||
|
println(" - Connection Details: %s\n", backend.connectionDetails);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!parsedJSONData) {
|
||||||
|
// Not really an assertion but I don't care right now
|
||||||
|
println("Assertion failed: parsedJSONData should not be undefined\n");
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
println(" - Connection details:\n");
|
||||||
|
|
||||||
|
for (const key of Object.keys(parsedJSONData)) {
|
||||||
|
let value: string | number = parsedJSONData[key];
|
||||||
|
|
||||||
|
if (typeof value == "string") {
|
||||||
|
value = value.replaceAll("\n", "\n" + " ".repeat(16));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (typeof value == "object") {
|
||||||
|
// TODO: implement?
|
||||||
|
value = JSON.stringify(value);
|
||||||
|
}
|
||||||
|
|
||||||
|
println(" - %s: %s\n", key, value);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
println(" - Connection Details: %s\n", backend.connectionDetails);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
println("%s backends found.\n", data.length);
|
||||||
|
});
|
||||||
|
|
||||||
|
const logsCommand = new SSHCommand(println, "logs");
|
||||||
|
logsCommand.description("View logs for a backend");
|
||||||
|
logsCommand.argument("<id>", "ID of the backend");
|
||||||
|
|
||||||
|
logsCommand.action(async(idStr: string) => {
|
||||||
|
const id: number = parseInt(idStr);
|
||||||
|
|
||||||
|
if (Number.isNaN(id)) {
|
||||||
|
println("ID (%s) is not a number.\n", idStr);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await axios.post("/api/v1/backends/lookup", {
|
||||||
|
token,
|
||||||
|
id
|
||||||
|
});
|
||||||
|
|
||||||
|
if (response.status != 200) {
|
||||||
|
if (process.env.NODE_ENV != "production") console.log(response);
|
||||||
|
|
||||||
|
if (response.data.error) {
|
||||||
|
println(`Error: ${response.data.error}\n`);
|
||||||
|
} else {
|
||||||
|
println("Error stopping a connection!\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
const { data }: BackendLookupSuccess = response.data;
|
||||||
|
const ourBackend = data.find((i) => i.id == id);
|
||||||
|
|
||||||
|
if (!ourBackend) return println("Could not find the backend!\n");
|
||||||
|
ourBackend.logs.forEach((log) => println("%s\n", log));
|
||||||
|
});
|
||||||
|
|
||||||
program.addCommand(addBackend);
|
program.addCommand(addBackend);
|
||||||
program.addCommand(removeBackend);
|
program.addCommand(removeBackend);
|
||||||
program.addCommand(lookupBackend);
|
program.addCommand(lookupBackend);
|
||||||
|
program.addCommand(logsCommand);
|
||||||
|
|
||||||
program.parse(argv);
|
program.parse(argv);
|
||||||
|
|
||||||
|
// It would make sense to check this, then parse argv, however this causes issues with
|
||||||
|
// the application name not displaying correctly.
|
||||||
|
|
||||||
|
if (argv.length == 1) {
|
||||||
|
println("No arguments specified!\n\n");
|
||||||
|
program.help();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
await new Promise((resolve) => program.onExit(resolve));
|
await new Promise((resolve) => program.onExit(resolve));
|
||||||
}
|
}
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue