diff options
author | Minteck <contact@minteck.org> | 2022-04-09 18:38:29 +0200 |
---|---|---|
committer | Minteck <contact@minteck.org> | 2022-04-09 18:38:29 +0200 |
commit | 457c93328f5b51b3fc0aa1600ce8eb8b45a5c2a9 (patch) | |
tree | a899daf11edb7ce6a99700e462a5740e013f5951 /index.js | |
download | snowjail-457c93328f5b51b3fc0aa1600ce8eb8b45a5c2a9.tar.gz snowjail-457c93328f5b51b3fc0aa1600ce8eb8b45a5c2a9.tar.bz2 snowjail-457c93328f5b51b3fc0aa1600ce8eb8b45a5c2a9.zip |
Snowjail v0.1
Diffstat (limited to 'index.js')
-rw-r--r-- | index.js | 140 |
1 files changed, 140 insertions, 0 deletions
diff --git a/index.js b/index.js new file mode 100644 index 0000000..5fe88b0 --- /dev/null +++ b/index.js @@ -0,0 +1,140 @@ + +(async () => { + const fs = require('fs'); + const os = require('os'); + const path = require('path'); + const pkg = require('./package.json'); + const chalk = (await import('chalk')).default; + const YAML = require('yaml'); + const uuid = require('uuid'); + const cp = require('child_process'); + + let p; + + function verbose(message) { + console.log(chalk.cyan("[snowjail] " + message)); + } + + function info(message) { + console.log(chalk.green("[snowjail] " + message)); + } + + function warning(message) { + console.log(chalk.yellow("[snowjail] " + message)); + } + + function fatal(message) { + console.log(chalk.red("[snowjail] " + message)); + process.exit(1); + } + + verbose("Starting Snowjail v" + pkg.version + "..."); + warning("Moving to Podman (instead of Docker) is planned before v1.0.0, made sure you have both installed to keep running your applications smoothly"); + + if (process.argv[2] !== undefined && fs.existsSync(process.argv[2]) && fs.lstatSync(process.argv[2]).isDirectory()) { + global.root = path.resolve(process.argv[2]); + verbose("Loading from " + root + "..."); + } else if (process.argv[2] !== undefined) { + if (fs.existsSync(process.argv[2])) { + fatal(process.argv[2] + ": not a directory"); + } else { + fatal(process.argv[2] + ": not found"); + } + } else { + fatal("missing operand"); + } + + if (!fs.existsSync(root + "/snowjail.yml") || (fs.existsSync(root + "/snowjail.yml") && !fs.lstatSync(root + "/snowjail.yml").isFile())) { + warning("Config not found, creating a default config file"); + try { + fs.writeFileSync(root + "/snowjail.yml", fs.readFileSync(__dirname + "/default.yml").toString().replace("$VERSION$", pkg.version)); + } catch (e) { + fatal("unable to create config: " + e.message); + } + } + + try { + global.config = YAML.parse(fs.readFileSync(root + "/snowjail.yml").toString()); + } catch (e) { + fatal("unable to load config: " + e.message); + } + verbose("Loaded config") + + verbose("Checking config...") + // TODO: Check config for completeness + + verbose("Locking config file...") + if (os.platform() === "darwin") { + cp.spawnSync("chflags", ["uchg", root]); + } else { + cp.spawnSync("chattr", ["+i", root]); + } + + verbose("Creating jail...") + let jid = uuid.v4(); + let hid = jid.replaceAll("-", ""); + let args = ["create", "-h", "snowjail-" + hid, "-v", root + ":/snowjail/" + hid, "--name", "sj-" + jid, "-i", "-t"]; + + if (config.cpu > 0) { + args.push(...["-c", config.cpu]); + } + + if (config.ram > 0) { + if (config.enforce_ram) { + args.push(...["-m", config.ram * 1048576]); + } else { + args.push(...["--memory-reservation", config.ram * 1048576]); + } + } + + if (config.hardware) { + args.push("--privileged"); + } + + for (let port of config.ports) { + if (port.match(/^[0-9]{1,5}:[0-9]{1,5}$/g) !== null) { + args.push(...["-p", port]); + } + } + + args.push(config.image); + + p = cp.spawnSync("docker", args, { stdio: "inherit" }); + if (p.exitCode !== 0 && p.exitCode !== undefined) { + fatal("unable to create jail: subprocess finished with non-zero exit code: " + p.exitCode); + } + + verbose("Starting jail...") + p = cp.spawnSync("docker", ["start", "sj-" + jid], { stdio: "inherit" }); + if (p.exitCode !== 0 && p.exitCode !== undefined) { + fatal("unable to start jail: subprocess finished with non-zero exit code: " + p.exitCode); + } + + let index = 1; + for (let command of config.commands) { + info("Running command " + index + "/" + config.commands.length + ": " + command.join(" ")); + p = cp.spawnSync("docker", ["exec", "-i", "-t", "sj-" + jid, ...command], { stdio: "inherit" }); + if (p.exitCode !== 0 && p.exitCode !== undefined) { + fatal("unable to execute command: subprocess finished with non-zero exit code: " + p.exitCode); + } + + index++; + } + + verbose("Deleting jail...") + p = cp.spawnSync("docker", ["stop", "sj-" + jid], { stdio: "inherit" }); + if (p.exitCode !== 0 && p.exitCode !== undefined) { + fatal("unable to delete jail: subprocess finished with non-zero exit code: " + p.exitCode); + } + p = cp.spawnSync("docker", ["rm", "sj-" + jid], { stdio: "inherit" }); + if (p.exitCode !== 0 && p.exitCode !== undefined) { + fatal("unable to delete jail: subprocess finished with non-zero exit code: " + p.exitCode); + } + + verbose("Unlocking config file...") + if (os.platform() === "darwin") { + cp.spawnSync("chflags", ["nouchg", root]); + } else { + cp.spawnSync("chattr", ["-i", root]); + } +})()
\ No newline at end of file |