2021-02-20 15:13:56 +01:00
|
|
|
#!/usr/bin/env node
|
2021-02-20 23:39:03 +01:00
|
|
|
require('nocamel');
|
|
|
|
const Logger = require('logplease');
|
|
|
|
const express = require('express');
|
|
|
|
const globals = require('./globals');
|
|
|
|
const config = require('./config');
|
|
|
|
const path = require('path');
|
|
|
|
const fs = require('fs/promises');
|
|
|
|
const fss = require('fs');
|
|
|
|
const body_parser = require('body-parser');
|
|
|
|
const runtime = require('./runtime');
|
2021-02-27 01:08:51 +01:00
|
|
|
const {validationResult} = require('express-validator'); //eslint-disable-line snakecasejs/snakecasejs
|
2021-02-20 23:39:03 +01:00
|
|
|
|
|
|
|
const logger = Logger.create('index');
|
2021-02-20 15:13:56 +01:00
|
|
|
const app = express();
|
|
|
|
|
|
|
|
(async () => {
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.info('Setting loglevel to',config.log_level);
|
|
|
|
Logger.setLogLevel(config.log_level); //eslint-disable-line snakecasejs/snakecasejs
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Ensuring data directories exist');
|
2021-02-20 15:13:56 +01:00
|
|
|
Object.values(globals.data_directories).forEach(dir => {
|
2021-02-20 23:39:03 +01:00
|
|
|
var data_path = path.join(config.data_directory, dir);
|
|
|
|
logger.debug(`Ensuring ${data_path} exists`);
|
|
|
|
if(!fss.exists_sync(data_path)){
|
|
|
|
logger.info(`${data_path} does not exist.. Creating..`);
|
2021-02-20 15:13:56 +01:00
|
|
|
try{
|
2021-02-20 23:39:03 +01:00
|
|
|
fss.mkdir_sync(data_path);
|
2021-02-20 15:13:56 +01:00
|
|
|
}catch(err){
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.error(`Failed to create ${data_path}: `, err.message);
|
2021-02-20 15:13:56 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
});
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.info('Loading packages');
|
|
|
|
const pkgdir = path.join(config.data_directory,globals.data_directories.packages);
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-03-05 07:29:09 +01:00
|
|
|
const pkglist = await fs.readdir(pkgdir);
|
|
|
|
const languages = await Promise.all(
|
|
|
|
pkglist.map(lang=>
|
|
|
|
fs.readdir(path.join(pkgdir,lang))
|
|
|
|
.then(x=>x.map(y=>path.join(pkgdir, lang, y)))
|
|
|
|
));
|
|
|
|
const installed_languages = languages.flat()
|
|
|
|
.filter(pkg=>fss.exists_sync(path.join(pkg, globals.pkg_installed_file)));
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-03-05 07:29:09 +01:00
|
|
|
installed_languages.forEach(pkg => new runtime.Runtime(pkg));
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.info('Starting API Server');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Constructing Express App');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Registering custom message wrappers');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
express.response.json_error = function(message, code) {
|
2021-02-20 23:39:03 +01:00
|
|
|
this.status(code);
|
|
|
|
return this.json({success: false, message, code});
|
|
|
|
};
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
express.response.json_success = function(obj) {
|
2021-02-20 23:39:03 +01:00
|
|
|
return this.json({success: true, data: obj});
|
|
|
|
};
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-27 00:58:30 +01:00
|
|
|
logger.debug('Registering middleware');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-27 00:58:30 +01:00
|
|
|
app.use(body_parser.urlencoded({extended: true}));
|
|
|
|
app.use(body_parser.json());
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
|
2021-02-27 00:58:30 +01:00
|
|
|
function validate(req, res, next) {
|
2021-02-27 01:08:51 +01:00
|
|
|
const errors = validationResult(req); //eslint-disable-line snakecasejs/snakecasejs
|
|
|
|
if (!errors.isEmpty()) //eslint-disable-line snakecasejs/snakecasejs
|
2021-02-27 00:58:30 +01:00
|
|
|
return res.json_error(errors.array(), 422);
|
|
|
|
next();
|
|
|
|
}
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-27 00:58:30 +01:00
|
|
|
logger.debug('Registering Routes');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-27 00:58:30 +01:00
|
|
|
const ppman_routes = require('./ppman/routes');
|
2021-03-05 07:29:09 +01:00
|
|
|
const executor_routes = require('./executor/routes');
|
2021-02-27 00:58:30 +01:00
|
|
|
|
2021-03-05 07:29:09 +01:00
|
|
|
|
2021-03-06 07:17:56 +01:00
|
|
|
app.get('/packages',
|
|
|
|
ppman_routes.package_list
|
2021-03-05 07:29:09 +01:00
|
|
|
);
|
|
|
|
|
2021-03-06 07:17:56 +01:00
|
|
|
app.post('/packages/:language/:version',
|
2021-03-05 07:29:09 +01:00
|
|
|
ppman_routes.package_install
|
|
|
|
);
|
|
|
|
|
2021-03-06 07:17:56 +01:00
|
|
|
app.delete('/packages/:language/:version',
|
2021-03-05 07:29:09 +01:00
|
|
|
ppman_routes.package_uninstall
|
|
|
|
);
|
|
|
|
|
|
|
|
app.post('/jobs',
|
|
|
|
executor_routes.run_job_validators,
|
|
|
|
validate,
|
|
|
|
executor_routes.run_job);
|
|
|
|
|
|
|
|
function list_runtimes(_, res){
|
|
|
|
const runtimes = runtime.map(rt => (
|
|
|
|
{
|
|
|
|
language: rt.language,
|
|
|
|
version: rt.version.raw,
|
2021-03-06 07:17:56 +01:00
|
|
|
author: rt.author,
|
|
|
|
aliases: rt.aliases
|
2021-03-05 07:29:09 +01:00
|
|
|
}
|
|
|
|
));
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-03-05 07:29:09 +01:00
|
|
|
return res.json_success({
|
|
|
|
runtimes
|
|
|
|
});
|
|
|
|
}
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-03-05 07:29:09 +01:00
|
|
|
app.get('/runtimes', list_runtimes);
|
2021-02-27 13:25:10 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.debug('Calling app.listen');
|
|
|
|
const [address,port] = config.bind_address.split(':');
|
2021-02-20 15:13:56 +01:00
|
|
|
|
|
|
|
app.listen(port, address, ()=>{
|
2021-02-20 23:39:03 +01:00
|
|
|
logger.info('API server started on', config.bind_address);
|
|
|
|
});
|
2021-02-20 15:13:56 +01:00
|
|
|
|
2021-02-20 23:39:03 +01:00
|
|
|
})();
|