From db46e6dd4884a94eb2282d5043263a06b7075422 Mon Sep 17 00:00:00 2001 From: Radon Rosborough Date: Tue, 27 Dec 2022 19:47:46 -0700 Subject: [PATCH] Starting work on a k8s sandbox implementation --- backend/k8s.js | 23 ++++++++----- backend/sandbox-k8s.js | 77 ++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 92 insertions(+), 8 deletions(-) create mode 100644 backend/sandbox-k8s.js diff --git a/backend/k8s.js b/backend/k8s.js index aeb1aa0..c35dbfb 100644 --- a/backend/k8s.js +++ b/backend/k8s.js @@ -5,15 +5,15 @@ kubeconfig.loadFromDefault(); const k8s = kubeconfig.makeApiClient(k8sClient.CoreV1Api); -async function listUserSessions() { +export async function listUserSessions() { return (await k8s.listNamespacedPod("riju-user")).body.items.map((pod) => ({ podName: pod.metadata.name, sessionID: pod.metadata.labels["riju.codes/user-session-id"], })); } -async function createUserSession({ sessionID, langConfig, revisions }) { - await k8s.createNamespacedPod("riju-user", { +export async function createUserSession({ sessionID, langConfig, revisions }) { + const { body: pod } = await k8s.createNamespacedPod("riju-user", { metadata: { name: `riju-user-session-${sessionID}`, labels: { @@ -43,16 +43,16 @@ async function createUserSession({ sessionID, langConfig, revisions }) { name: "download", image: "minio/mc:RELEASE.2022-12-13T00-23-28Z", resources: {}, + command: ["sh", "-c"], args: [ - "sh", - "-c", - `mc cp riju/agent/${revisions.agent} /riju-bin/agent &&` + - `mc cp riju/ptyify/${revisions.ptyify} /riju-bin/ptyify`, + `cp -RT /mc /root/.mc &&` + + `mc cp riju/agent/${revisions.agent} /riju-bin/agent && chmod +x /riju-bin/agent &&` + + `mc cp riju/ptyify/${revisions.ptyify} /riju-bin/ptyify && chmod +x /riju-bin/ptyify`, ], volumeMounts: [ { name: "minio-config", - mountPath: "/root/.mc", + mountPath: "/mc", readOnly: true, }, { @@ -120,4 +120,11 @@ async function createUserSession({ sessionID, langConfig, revisions }) { restartPolicy: "Never", }, }); + console.log(pod); +} + +export async function deleteUserSessions(sessionsToDelete) { + for (const { podName } of sessionsToDelete) { + await k8s.deleteNamespacedPod(podName, "riju-user"); + } } diff --git a/backend/sandbox-k8s.js b/backend/sandbox-k8s.js new file mode 100644 index 0000000..db616a5 --- /dev/null +++ b/backend/sandbox-k8s.js @@ -0,0 +1,77 @@ +import { spawn } from "child_process"; +import { promises as fs } from "fs"; +import process from "process"; + +import { readLangConfig } from "../lib/yaml.js"; +import * as k8s from "./k8s.js"; +import { getUUID, quote } 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}`); + await k8s.createUserSession({ + sessionID, + langConfig, + revisions: { + agent: "20221228-023645-invisible-amaranth-sparrow", + ptyify: "20221228-023645-clean-white-gorilla", + }, + }); + // let buffer = ""; + // await new Promise((resolve) => { + // session.stdout.on("data", (data) => { + // buffer += data.toString(); + // let idx; + // while ((idx = buffer.indexOf("\n")) !== -1) { + // const line = buffer.slice(0, idx); + // buffer = buffer.slice(idx + 1); + // if (line === "riju: container ready") { + // resolve(); + // } else { + // console.error(line); + // } + // } + // }); + // }); + // const args = [].concat.apply( + // ["riju-pty", "-f"], + // privilegedPty( + // { uuid }, + // bash( + // `env L='${lang}' LANG_CONFIG=${quote( + // JSON.stringify(langConfig) + // )} bash --rcfile <(cat <<< ${quote(sandboxScript)})` + // ) + // ) + // ); + // const proc = spawn(args[0], args.slice(1), { + // stdio: "inherit", + // }); + // try { + // await new Promise((resolve, reject) => { + // proc.on("error", reject); + // proc.on("close", resolve); + // }); + // } finally { + // session.kill(); + // } +} + +main().catch(die);