riju/backend/sandbox-k8s.js

83 lines
2.4 KiB
JavaScript

import { spawn } from "child_process";
import { promises as fs } from "fs";
import process from "process";
import pQueue from "p-queue";
const PQueue = pQueue.default;
import { readLangConfig } from "../lib/yaml.js";
import * as k8s from "./k8s.js";
import { deptyify, getUUID } from "./util.js";
function die(msg) {
console.error(msg);
process.exit(1);
}
async function main() {
const sandboxScript = await fs.readFile("backend/sandbox.bash", "utf-8");
const lang = process.env.L;
if (!lang) {
die("environment variable unset: $L");
}
const langConfig = await readLangConfig(lang);
console.log(`Checking for existing sessions`);
const existingSessions = await k8s.listUserSessions();
if (existingSessions.length > 0) {
console.log(`Killing ${existingSessions.length} existing session(s)`);
await k8s.deleteUserSessions(existingSessions);
}
const sessionID = getUUID();
console.log(`Starting session with UUID ${sessionID}`);
const watcher = k8s.watchPods();
const podName = await k8s.createUserSession({
watcher,
sessionID,
langConfig,
revisions: {
agent: "20230104-131916-extensive-aquamarine-crocodile",
ptyify: "20221228-023645-clean-white-gorilla",
langImage: "20221227-195753-forward-harlequin-wolverine",
},
});
const proxyInfo = {
httpProtocol: "https",
wsProtocol: "wss",
host: "k8s.riju.codes",
port: 1869,
username: "admin",
password: process.env.RIJU_PROXY_PASSWORD,
};
console.log(`Waiting for session to become ready`);
const session = await k8s.initUserSession({
watcher,
podName,
proxyInfo,
});
console.log(`Initializing sandbox`);
await new Promise(async (resolve) => {
// Use a queue to resolve the circular dependency between exec and
// pty.
const outputQueue = new PQueue({ concurrency: 1, autoStart: false });
let handlePtyOutput;
const exec = await session.exec(["bash"], {
pty: true,
on: {
stdout: (data) => outputQueue.add(() => handlePtyOutput(data)),
stderr: (data) => process.stderr.write(data),
exit: (status) => process.exit(status),
error: (err) => process.stderr.write(`riju: error: ${err}\n`),
close: () => resolve(),
},
});
const pty = await deptyify({
handlePtyInput: (data) => exec.stdin.write(data),
handlePtyExit: (_status) => {},
});
handlePtyOutput = pty.handlePtyOutput;
outputQueue.start();
});
}
main().catch(die);