borrar agent

This commit is contained in:
Cat /dev/Nulo 2023-06-23 17:44:45 -03:00
parent e4302b6c1f
commit 5ed0f62abf
4 changed files with 0 additions and 273 deletions

View file

@ -1,184 +0,0 @@
import { nanoid } from "nanoid";
// import { WebSocketServer } from "ws";
import { execFile as _execFile, spawn } from "node:child_process";
import { open, readFile, rm } from "node:fs/promises";
import { createServer } from "node:http";
import { tmpdir } from "node:os";
import { join } from "node:path";
import { promisify } from "node:util";
const execFile = promisify(_execFile);
// const spawn = promisify(_spawn);
const secret = await parseSecret();
// const wsServer = new WebSocketServer({ noServer: true });
const server = createServer(async (req, res) => {
try {
await handler(req, res);
} catch (error) {
console.error("Error manejando", req.url, error);
res.destroy();
}
});
/** @type {Map<string, {listeners: ((data: Buffer | null) => void)[], prev: Buffer, statusCode: null | number}>} */
let runs = new Map();
// server.on("upgrade", (req, socket, head) => {
// const url = getUrl(req)
// let matches;
// if ((matches = url.pathname.match(runWebSocketRegexp))) {
// const runId = matches[1];
// if (!listeners.has(runId)) {
// return
// }
// wsServer.handleUpgrade(req, socket,head,(client,request)=>{
// })
// }
// });
/**
* @param {string} runId
* @param {Buffer} chunk
*/
function writeToRun(runId, chunk) {
const run = runs.get(runId);
if (!run) throw new Error(`runId ${runId} doesn't exist`);
run.prev = Buffer.concat([run.prev, chunk]);
for (const listener of run.listeners) {
listener(chunk);
}
}
/**
* @param {string} runId
*/
function closeRun(runId) {
const run = runs.get(runId);
if (!run) throw new Error(`runId ${runId} doesn't exist`);
for (const listener of run.listeners) {
listener(null);
}
}
const runWebSocketRegexp = /^\/run\/(.+)$/;
/**
* @param {import("http").IncomingMessage} req
* @param {import("http").ServerResponse<import("http").IncomingMessage> & { req: import("http").IncomingMessage; }} res
*/
async function handler(req, res) {
// prettier-ignore
const url = getUrl(req);
auth(secret, req, res);
let matches;
if (url.pathname === "/hello") {
if (req.method === "GET") {
return res.writeHead(200).end("Ey!");
} else return res.writeHead(405).end("method not allowed");
} else if (url.pathname === "/run") {
if (req.method === "POST") {
const runId = nanoid();
runs.set(runId, {
listeners: [],
prev: Buffer.from([]),
statusCode: null,
});
const execPath = join(tmpdir(), "fireactions-agent-exec-" + nanoid());
{
const execFile = await open(execPath, "w", 0o700);
await new Promise((resolve, reject) =>
req.pipe(execFile.createWriteStream()).addListener("finish", () => {
resolve(void 0);
})
);
}
const proc = spawn(execPath, [], {});
proc.stdout.on("data", async (/** @type {Buffer} */ chunk) => {
writeToRun(runId, chunk);
});
proc.stderr.on("data", async (/** @type {Buffer} */ chunk) => {
writeToRun(runId, chunk);
});
proc.on("close", async (code) => {
const run = runs.get(runId);
if (!run) return panic();
runs.set(runId, { ...run, statusCode: code });
closeRun(runId);
await rm(execPath);
});
return res.writeHead(200).end(JSON.stringify({ runId }));
} else return res.writeHead(405).end("method not allowed");
} else if ((matches = url.pathname.match(runWebSocketRegexp))) {
const runId = matches[1];
const run = runs.get(runId);
if (!run) {
return res.writeHead(404).end("run not found");
}
res.writeHead(200, {
"content-type": "text/event-stream",
Connection: "keep-alive",
"Cache-Control": "no-cache",
"Access-Control-Allow-Origin": "*",
});
const listener = (/** @type {Buffer | null} */ data) => {
if (data === null) return res.end();
res.write(
"event: stdsmth\n" + `data: ${JSON.stringify(data.toString())}\n\n`
);
};
listener(run.prev);
// TODO: remove listener when request closed
runs.set(runId, { ...run, listeners: [...run.listeners, listener] });
} else {
return res.writeHead(404).end("not found");
}
}
/**
* @param {import("http").IncomingMessage} req
*/
function getUrl(req) {
// prettier-ignore
const urlString = /** @type {string} */(req.url);
const url = new URL(urlString, `http://${req.headers.host}`);
return url;
}
/**
* @returns {Promise<string>}
*/
async function parseSecret() {
const cmdline = await readFile("/proc/cmdline", "utf-8");
for (const opt of cmdline.split(" ")) {
const [key, value] = opt.split("=");
if (key === "fireactions.secret") {
if (value.length < 5) throw new Error("valor muy corto");
return value;
}
}
throw new Error("no hay secreto");
}
/**
* @param {string} secret
* @param {import("http").IncomingMessage} req
* @param {import("http").ServerResponse<import("http").IncomingMessage> & { req: import("http").IncomingMessage; }} res
*/
function auth(secret, req, res) {
const url = getUrl(req);
const auth = req.headers.authorization
? req.headers.authorization.slice("Bearer ".length)
: url.searchParams.get("token");
if (auth !== secret) {
res.writeHead(401).end("wrong secret");
throw new Error("unauthorized");
}
}
server.listen("8080");
function panic() {
throw new Error("Function not implemented.");
}

View file

@ -1,22 +0,0 @@
{
"name": "agent",
"type": "module",
"version": "1.0.0",
"description": "",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@tsconfig/node16": "^1.0.4",
"@types/node": "^20.2.5",
"@types/ws": "^8.5.4"
},
"dependencies": {
"nanoid": "^4.0.2",
"ws": "^8.13.0"
}
}

View file

@ -1,59 +0,0 @@
lockfileVersion: '6.1'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
nanoid:
specifier: ^4.0.2
version: 4.0.2
ws:
specifier: ^8.13.0
version: 8.13.0
devDependencies:
'@tsconfig/node16':
specifier: ^1.0.4
version: 1.0.4
'@types/node':
specifier: ^20.2.5
version: 20.2.5
'@types/ws':
specifier: ^8.5.4
version: 8.5.4
packages:
/@tsconfig/node16@1.0.4:
resolution: {integrity: sha512-vxhUy4J8lyeyinH7Azl1pdd43GJhZH/tP2weN8TntQblOY+A0XbT8DJk1/oCPuOOyg/Ja757rG0CgHcWC8OfMA==}
dev: true
/@types/node@20.2.5:
resolution: {integrity: sha512-JJulVEQXmiY9Px5axXHeYGLSjhkZEnD+MDPDGbCbIAbMslkKwmygtZFy1X6s/075Yo94sf8GuSlFfPzysQrWZQ==}
dev: true
/@types/ws@8.5.4:
resolution: {integrity: sha512-zdQDHKUgcX/zBc4GrwsE/7dVdAD8JR4EuiAXiiUhhfyIJXXb2+PrGshFyeXWQPMmmZ2XxgaqclgpIC7eTXc1mg==}
dependencies:
'@types/node': 20.2.5
dev: true
/nanoid@4.0.2:
resolution: {integrity: sha512-7ZtY5KTCNheRGfEFxnedV5zFiORN1+Y1N6zvPTnHQd8ENUvfaDBeuJDZb2bN/oXwXxu3qkTXDzy57W5vAmDTBw==}
engines: {node: ^14 || ^16 || >=18}
hasBin: true
dev: false
/ws@8.13.0:
resolution: {integrity: sha512-x9vcZYTrFPC7aSIbj7sRCYo7L/Xb8Iy+pW0ng0wt2vCJv7M9HOMy0UoN3rr+IFC7hb7vXoqS+P9ktyLLLhO+LA==}
engines: {node: '>=10.0.0'}
peerDependencies:
bufferutil: ^4.0.1
utf-8-validate: '>=5.0.2'
peerDependenciesMeta:
bufferutil:
optional: true
utf-8-validate:
optional: true
dev: false

View file

@ -1,8 +0,0 @@
{
"extends": "@tsconfig/node16/tsconfig.json",
"exclude": ["build.js/", "build/"],
"compilerOptions": {
"allowJs": true,
"checkJs": true
}
}