diff --git a/package-lock.json b/package-lock.json index fe25826..6f785d1 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "domcloud-bridge", - "version": "0.50.0", + "version": "0.51.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "domcloud-bridge", - "version": "0.50.0", + "version": "0.51.0", "license": "MIT", "dependencies": { "axios": "^1.6.8", diff --git a/package.json b/package.json index b37e1b7..ab4848a 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "domcloud-bridge", - "version": "0.50.0", + "version": "0.51.0", "description": "Deployment runner for DOM Cloud", "main": "app.js", "engines": { diff --git a/src/controllers/unit.js b/src/controllers/unit.js new file mode 100644 index 0000000..a62ec48 --- /dev/null +++ b/src/controllers/unit.js @@ -0,0 +1,22 @@ + +import express from 'express'; +import { unitExec } from '../executor/unit'; + +export default function () { + var router = express.Router(); + router.get('/', async function (req, res, next) { + try { + res.json(unitExec.get(req.path)); + } catch (error) { + next(error); + } + }); + router.post('/', async function (req, res, next) { + try { + res.json(unitExec.set(req.path, JSON.stringify(req.body))); + } catch (error) { + next(error); + } + }); + return router; +} diff --git a/src/executor/unit.js b/src/executor/unit.js new file mode 100644 index 0000000..899a212 --- /dev/null +++ b/src/executor/unit.js @@ -0,0 +1,31 @@ +import { ShellString } from 'shelljs'; +import path from 'path'; +import { + executeLock, + spawnSudoUtil, +} from '../util.js'; + +const tmpFile = path.join(process.cwd(), '/.tmp/unit') + +class UnitExecutor { + constructor() { + } + /** + * @param {string} path + */ + async get(path) { + return await spawnSudoUtil("UNIT_GET", [path]); + } + /** + * @param {string} path + * @param {string} body + */ + async set(path, body) { + return await executeLock('unit', async () => { + ShellString(body).to(tmpFile); + await spawnSudoUtil("UNIT_SET", [path]); + }); + } +} + +export const unitExec = new UnitExecutor(); diff --git a/src/index.js b/src/index.js index a39d543..6d82f5f 100644 --- a/src/index.js +++ b/src/index.js @@ -13,6 +13,7 @@ import { import runner from './controllers/runner.js'; import virtualmin from './controllers/virtualmin.js'; import docker from './controllers/docker.js'; +import unit from './controllers/unit.js'; const startTime = Date.now(); dotenv.config(); @@ -32,6 +33,7 @@ app.use('/screend', screend()); app.use('/docker', docker()); app.use('/runner', runner()); app.use('/virtualmin', virtualmin()); +app.use('/unit', unit()); app.use(function (err, req, res, next) { if (err instanceof Error) { res.status(500); diff --git a/sudoutil.js b/sudoutil.js index fc5e698..2db922c 100755 --- a/sudoutil.js +++ b/sudoutil.js @@ -4,6 +4,7 @@ import shelljs from 'shelljs' import cli from 'cli' import dotenv from 'dotenv' import path from 'path'; +import http from 'http'; import { chmodSync, chownSync, @@ -47,6 +48,8 @@ const env = Object.assign({}, { NGINX_BIN: 'nginx', NGINX_START: 'systemctl start nginx', NGINX_TMP: path.join(__dirname, '.tmp/nginx'), + UNIT_SOCKET: '/var/run/unit/control.sock', + UNIT_TMP: path.join(__dirname, '.tmp/unit'), IPTABLES_PATH: '/etc/sysconfig/iptables', IPTABLES_OUT: '/etc/sysconfig/iptables', IPTABLES_SAVE: 'iptables-save', @@ -109,6 +112,39 @@ switch (cli.args.shift()) { rm(DEST + '.bak'); exec(`${env.NGINX_BIN} -s reload`); exit(0); + case 'UNIT_GET': + arg = cli.args.shift(); + http.request({ + socketPath: env.UNIT_SOCKET, + path: '/config' + arg, + }, res => { + res.setEncoding('utf8'); + res.on('data', data => process.stdout.write(data)); + res.on('end', () => exit(0)) + res.on('error', data => { console.error(data); exit(1); }); + }); + setTimeout(() => { + // just in case + exit(1); + }, 1000 * 60).unref(); + case 'UNIT_SET': + arg = cli.args.shift(); + http.request({ + socketPath: env.UNIT_SOCKET, + path: '/config' + arg, + method: 'PUT', + }, res => { + res.setEncoding('utf8'); + res.push(cat(env.UNIT_TMP).stdout, 'utf-8'); + res.on('data', data => process.stdout.write(data)); + res.on('end', () => exit(0)) + res.on('error', data => { console.error(data); exit(1); }); + }); + setTimeout(() => { + // just in case + exit(1); + }, 1000 * 60).unref(); + exit(0); case 'VIRTUAL_SERVER_GET': arg = cli.args.shift(); cat(env.VIRTUAL_SERVER_PATH.replace('$', arg)).to(env.VIRTUAL_SERVER_TMP);