A simple command-line tool to start NetBSD virtual machines using QEMU with sensible defaults.
at main 71 lines 2.0 kB view raw
1import { Data, Effect, pipe } from "effect"; 2import { LOGS_DIR } from "../constants.ts"; 3 4class LogCommandError extends Data.TaggedError("LogCommandError")<{ 5 vmName: string; 6 exitCode: number; 7}> {} 8 9class CommandError extends Data.TaggedError("CommandError")<{ 10 cause?: unknown; 11}> {} 12 13const createLogsDir = () => 14 Effect.tryPromise({ 15 try: () => Deno.mkdir(LOGS_DIR, { recursive: true }), 16 catch: (error) => new CommandError({ cause: error }), 17 }); 18 19const buildLogPath = (name: string) => 20 Effect.succeed(`${LOGS_DIR}/${name}.log`); 21 22const viewLogs = (name: string, follow: boolean, logPath: string) => 23 Effect.tryPromise({ 24 try: async () => { 25 const cmd = new Deno.Command(follow ? "tail" : "cat", { 26 args: [ 27 ...(follow ? ["-n", "100", "-f"] : []), 28 logPath, 29 ], 30 stdin: "inherit", 31 stdout: "inherit", 32 stderr: "inherit", 33 }); 34 35 const status = await cmd.spawn().status; 36 return { name, status }; 37 }, 38 catch: (error) => new CommandError({ cause: error }), 39 }).pipe( 40 Effect.flatMap(({ name, status }) => 41 status.success ? Effect.succeed(undefined) : Effect.fail( 42 new LogCommandError({ 43 vmName: name, 44 exitCode: status.code || 1, 45 }), 46 ) 47 ), 48 ); 49 50const handleError = (error: LogCommandError | CommandError | Error) => 51 Effect.sync(() => { 52 if (error instanceof LogCommandError) { 53 console.error(`Failed to view logs for virtual machine ${error.vmName}.`); 54 Deno.exit(error.exitCode); 55 } else { 56 console.error(`An error occurred: ${error}`); 57 Deno.exit(1); 58 } 59 }); 60 61const logsEffect = (name: string, follow: boolean) => 62 pipe( 63 createLogsDir(), 64 Effect.flatMap(() => buildLogPath(name)), 65 Effect.flatMap((logPath) => viewLogs(name, follow, logPath)), 66 Effect.catchAll(handleError), 67 ); 68 69export default async function (name: string, follow: boolean) { 70 await Effect.runPromise(logsEffect(name, follow)); 71}