all repos — ssh-portal @ 4f6d8725ca79cf18bec78f4d71034f4d74a8fda2

SSH abstraction tool to be productive in my work

feat: :sparkles: Group instances by category, improve logging
Tim Izzo tim@octree.ch
Tue, 22 Oct 2024 16:55:01 +0200
commit

4f6d8725ca79cf18bec78f4d71034f4d74a8fda2

parent

de5bc31424daf1e563acc2d8364cba0273548ad6

4 files changed, 43 insertions(+), 14 deletions(-)

jump to
M actions.jsonactions.json

@@ -1,7 +1,7 @@

[ { "name": "Voir les logs en continu", - "cmd": "tail -f /var/log/run.log" + "cmd": "tail -f -n 50 /var/log/run.log" }, { "name": "Voir les derniers logs",
M deno.jsondeno.json

@@ -1,6 +1,6 @@

{ "tasks": { "start": "deno run --allow-net --allow-read main.ts", - "compile": "deno compile --allow-net --allow-read main.ts" + "compile": "deno compile -o $HOME/bin/sp --allow-net --allow-read main.ts" } }
M instances.jsoninstances.json

@@ -1,22 +1,32 @@

[ { "name": "R-21 Client Test", - "username": "82099-616" + "username": "82099-616", + "category": "R-21" }, { "name": "R-21 Admin Test", - "username": "183771-616" + "username": "183771-616", + "category": "R-21" }, { "name": "EVOSPE Test", - "username": "81781-616" + "username": "81781-616", + "category": "SPE" + }, + { + "name": "SPE Data Gateway Test", + "username": "168997-616", + "category": "SPE" }, { "name": "Caroster Test", - "username": "171840-616" + "username": "171840-616", + "category": "Caroster" }, { "name": "Caroster Prod", - "username": "175258-616" + "username": "175258-616", + "category": "Caroster" } ]
M main.tsmain.ts

@@ -20,21 +20,36 @@ port: 3022,

privateKey: Deno.readTextFileSync("/home/tim/.ssh/id_rsa"), }; +const instancesByCategory = Object.groupBy(instances, i => i.category); +const configOptions = Object.entries(instancesByCategory).map( + ([category, instances]) => { + return { + name: category, + options: instances?.map(instance => ({ + name: instance.name, + value: instance, + })), + }; + } +); const selectedConfig = await Select.prompt<(typeof instances)[number]>({ - message: "🚀 Instance", - options: instances.map(c => ({ name: c.name, value: c })), + message: "Instance", + search: true, + groupIcon: "🔵", + options: configOptions, }); const selectedAction = await Select.prompt<(typeof actions)[number]>({ - message: "⚡️ Action", + message: "Action", options: actions.map(c => ({ name: c.name, value: c })), }); const secondaryText = colors.gray; + const client = new Client().connect({ ...selectedConfig, ...baseConfig }); -console.log(`✨ Connecting to ${selectedConfig.name}...`); +console.log(`🚀 Connecting to ${selectedConfig.name}...`); client.on("ready", () => { - tty.eraseScreen(); + tty.cursorTo(0, 0).eraseScreen(); console.log(secondaryText(`✅ Connected to ${selectedConfig.name}`)); console.log(secondaryText(`$ ${selectedAction.cmd}`)); client.exec(selectedAction.cmd, (err: Error, stream: any) => {

@@ -44,10 +59,14 @@ .on("close", () => {

client.end(); }) .on("data", (data: string) => { - console.log("STDOUT" + data); + const date = new Date(); + const dateText = colors.bold.black.bgBlue; + console.log(dateText(`${date.toLocaleString()}\n`) + data); }) .stderr.on("data", (data: string) => { - console.log("STDERR" + data); + const date = new Date(); + const dateText = colors.bold.black.bgRed; + console.log(`${dateText(date.toLocaleString())}) - ERROR\n` + data); }); }); });