fix(core): update
This commit is contained in:
parent
9ef366eee9
commit
5e5a679f99
50
package-lock.json
generated
50
package-lock.json
generated
@ -144,6 +144,23 @@
|
|||||||
"@pushrocks/smartpromise": "^3.0.2"
|
"@pushrocks/smartpromise": "^3.0.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@pushrocks/smartenv": {
|
||||||
|
"version": "4.0.7",
|
||||||
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartenv/-/smartenv-4.0.7.tgz",
|
||||||
|
"integrity": "sha512-ThSJMEcUAF1VIa4vAvn1zGnziEuDY4h8T+EQ5JCiKy2qnUM/F6zqzFogyo495X6rg71gC/7RmktQVQaN06gjWA==",
|
||||||
|
"requires": {
|
||||||
|
"@pushrocks/smartparam": "^1.0.4",
|
||||||
|
"@pushrocks/smartpromise": "^3.0.2",
|
||||||
|
"@types/node": "^12.7.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@types/node": {
|
||||||
|
"version": "12.7.3",
|
||||||
|
"resolved": "https://verdaccio.lossless.one/@types%2fnode/-/node-12.7.3.tgz",
|
||||||
|
"integrity": "sha512-3SiLAIBkDWDg6vFo0+5YJyHPWU9uwu40Qe+v+0MH8wRKYBimHvvAOyk3EzMrD/TrIlLYfXrqDqrg913PynrMJQ=="
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@pushrocks/smartevent": {
|
"@pushrocks/smartevent": {
|
||||||
"version": "2.0.3",
|
"version": "2.0.3",
|
||||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartevent/-/smartevent-2.0.3.tgz",
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartevent/-/smartevent-2.0.3.tgz",
|
||||||
@ -251,7 +268,6 @@
|
|||||||
"version": "1.0.4",
|
"version": "1.0.4",
|
||||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartparam/-/smartparam-1.0.4.tgz",
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartparam/-/smartparam-1.0.4.tgz",
|
||||||
"integrity": "sha512-UAqhnTQGBaJRptTK3qTd47Yt2ZTrAWByteow4auSNZD+k0xrpY9mTPPgKh0IwsURe0cZhj7zYNpGiekhKkL4rA==",
|
"integrity": "sha512-UAqhnTQGBaJRptTK3qTd47Yt2ZTrAWByteow4auSNZD+k0xrpY9mTPPgKh0IwsURe0cZhj7zYNpGiekhKkL4rA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"@pushrocks/smartpromise": "^2.0.5",
|
"@pushrocks/smartpromise": "^2.0.5",
|
||||||
"is-promise": "^2.1.0",
|
"is-promise": "^2.1.0",
|
||||||
@ -261,8 +277,7 @@
|
|||||||
"@pushrocks/smartpromise": {
|
"@pushrocks/smartpromise": {
|
||||||
"version": "2.0.5",
|
"version": "2.0.5",
|
||||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartpromise/-/smartpromise-2.0.5.tgz",
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartpromise/-/smartpromise-2.0.5.tgz",
|
||||||
"integrity": "sha512-9j/chLtIiNkR0MDw7Mpxg9slxAVvAQwUZuiaPYX5KpHdKxQaHLI1VZ8IN0vPhwlfgNO4i4vGXV0wB8BvSDj03g==",
|
"integrity": "sha512-9j/chLtIiNkR0MDw7Mpxg9slxAVvAQwUZuiaPYX5KpHdKxQaHLI1VZ8IN0vPhwlfgNO4i4vGXV0wB8BvSDj03g=="
|
||||||
"dev": true
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
@ -318,6 +333,32 @@
|
|||||||
"which": "^1.3.1"
|
"which": "^1.3.1"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
"@pushrocks/smartsystem": {
|
||||||
|
"version": "2.0.8",
|
||||||
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartsystem/-/smartsystem-2.0.8.tgz",
|
||||||
|
"integrity": "sha512-lBruo1Ikai35oiDMy3Lx1NhddTMynCCd8MTx4dBU22a0HnNYZRKxTITuPAfIDD3VB94ZpEGbAvzblnZpuFFkMQ==",
|
||||||
|
"requires": {
|
||||||
|
"@pushrocks/lik": "^3.0.10",
|
||||||
|
"@pushrocks/smartenv": "^4.0.7",
|
||||||
|
"@pushrocks/smartpromise": "^3.0.2"
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@pushrocks/lik": {
|
||||||
|
"version": "3.0.11",
|
||||||
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2flik/-/lik-3.0.11.tgz",
|
||||||
|
"integrity": "sha512-SDKRPj9+xBTqozlDPcA7O6BcccM1Tw/sXPVP+OnhNxCubDZ/L2kGNpPpqm43NJUoNxSSo5wdBw4N7MAFYCGdVg==",
|
||||||
|
"requires": {
|
||||||
|
"@pushrocks/smartdelay": "^2.0.3",
|
||||||
|
"@pushrocks/smartpromise": "^3.0.2",
|
||||||
|
"@pushrocks/smartrx": "^2.0.3",
|
||||||
|
"@pushrocks/smarttime": "^3.0.12",
|
||||||
|
"@types/minimatch": "^3.0.3",
|
||||||
|
"minimatch": "^3.0.4",
|
||||||
|
"symbol-tree": "^3.2.4"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
"@pushrocks/smarttime": {
|
"@pushrocks/smarttime": {
|
||||||
"version": "3.0.12",
|
"version": "3.0.12",
|
||||||
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmarttime/-/smarttime-3.0.12.tgz",
|
"resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmarttime/-/smarttime-3.0.12.tgz",
|
||||||
@ -898,8 +939,7 @@
|
|||||||
"is-promise": {
|
"is-promise": {
|
||||||
"version": "2.1.0",
|
"version": "2.1.0",
|
||||||
"resolved": "https://verdaccio.lossless.one/is-promise/-/is-promise-2.1.0.tgz",
|
"resolved": "https://verdaccio.lossless.one/is-promise/-/is-promise-2.1.0.tgz",
|
||||||
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=",
|
"integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"is-stream": {
|
"is-stream": {
|
||||||
"version": "1.1.0",
|
"version": "1.1.0",
|
||||||
|
@ -24,6 +24,7 @@
|
|||||||
"@pushrocks/smartlog": "^2.0.19",
|
"@pushrocks/smartlog": "^2.0.19",
|
||||||
"@pushrocks/smartlog-destination-local": "^8.0.2",
|
"@pushrocks/smartlog-destination-local": "^8.0.2",
|
||||||
"@pushrocks/smartshell": "^2.0.25",
|
"@pushrocks/smartshell": "^2.0.25",
|
||||||
|
"@pushrocks/smartsystem": "^2.0.8",
|
||||||
"@types/fs-extra": "^8.0.0",
|
"@types/fs-extra": "^8.0.0",
|
||||||
"fs-extra": "^8.1.0"
|
"fs-extra": "^8.1.0"
|
||||||
},
|
},
|
||||||
|
60
ts/smartdaemon.classes.smartdaemon.ts
Normal file
60
ts/smartdaemon.classes.smartdaemon.ts
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import * as plugins from './smartdaemon.plugins';
|
||||||
|
import { SmartDaemonTemplateManager } from './smartdaemon.classes.templatemanager';
|
||||||
|
|
||||||
|
const smartDaemonNamespace = 'smartdaemon_';
|
||||||
|
|
||||||
|
interface SmartDaemonConstructorOptions {
|
||||||
|
name: string;
|
||||||
|
scriptPath: string;
|
||||||
|
workingDir: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
export class SmartDaemon {
|
||||||
|
private templateManager: SmartDaemonTemplateManager;
|
||||||
|
private smartshellInstance: plugins.smartshell.Smartshell;
|
||||||
|
private smartsystem: plugins.smartsystem.Smartsystem;
|
||||||
|
private shouldExecute: boolean = false;
|
||||||
|
|
||||||
|
constructor() {
|
||||||
|
this.templateManager = new SmartDaemonTemplateManager;
|
||||||
|
this.smartshellInstance = new plugins.smartshell.Smartshell({
|
||||||
|
executor: 'bash'
|
||||||
|
});
|
||||||
|
this.smartsystem = new plugins.smartsystem.Smartsystem();
|
||||||
|
}
|
||||||
|
|
||||||
|
public async checkElegibility () {
|
||||||
|
if (await this.smartsystem.env.isLinuxAsync()) {
|
||||||
|
this.shouldExecute = true;
|
||||||
|
} else {
|
||||||
|
console.log('Smartdaemon can only be used on Linuc systems! Refusing to set up a service.');
|
||||||
|
this.shouldExecute = false;
|
||||||
|
}
|
||||||
|
return this.shouldExecute;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* enables the service
|
||||||
|
*/
|
||||||
|
public async enable() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* disables the service
|
||||||
|
*/
|
||||||
|
public async disable() {
|
||||||
|
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* pauses the service
|
||||||
|
*/
|
||||||
|
public pause() {};
|
||||||
|
|
||||||
|
|
||||||
|
private async execute(commandArg: string) {
|
||||||
|
|
||||||
|
this.smartshellInstance.exec(commandArg);
|
||||||
|
}
|
||||||
|
}
|
34
ts/smartdaemon.classes.templatemanager.ts
Normal file
34
ts/smartdaemon.classes.templatemanager.ts
Normal file
@ -0,0 +1,34 @@
|
|||||||
|
import * as plugins from './smartdaemon.plugins';
|
||||||
|
|
||||||
|
export class SmartDaemonTemplateManager {
|
||||||
|
public generateServiceTemplate = (optionsArg: {
|
||||||
|
serviceName: string;
|
||||||
|
description: string;
|
||||||
|
serviceVersion: string;
|
||||||
|
pathNodeJs: string;
|
||||||
|
pathWorkkingDir;
|
||||||
|
pathJsFileToRun;
|
||||||
|
}) => {
|
||||||
|
return `
|
||||||
|
# servicVersion: ${optionsArg.serviceVersion}
|
||||||
|
[Unit]
|
||||||
|
Description=${optionsArg.description}
|
||||||
|
Requires=network.target
|
||||||
|
After=network.target
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
Type=simple
|
||||||
|
ExecStart=${optionsArg.pathNodeJs} ${optionsArg.pathJsFileToRun}
|
||||||
|
WorkingDirectory=${optionsArg.pathWorkkingDir}
|
||||||
|
Restart=on-failure
|
||||||
|
LimitNOFILE=infinity
|
||||||
|
LimitCORE=infinity
|
||||||
|
StandardInput=null
|
||||||
|
StandardOutput=syslog
|
||||||
|
StandardError=syslog
|
||||||
|
Restart=always
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
|
`;
|
||||||
|
};
|
||||||
|
}
|
4
ts/smartdaemon.paths.ts
Normal file
4
ts/smartdaemon.paths.ts
Normal file
@ -0,0 +1,4 @@
|
|||||||
|
import * as plugins from './smartdaemon.plugins';
|
||||||
|
|
||||||
|
export const packageDir = plugins.path.join(__dirname, '../');
|
||||||
|
export const systemdDir = plugins.path.join('/lib/systemd/system/');
|
@ -7,14 +7,16 @@ export {
|
|||||||
};
|
};
|
||||||
|
|
||||||
// @pushrocks scope
|
// @pushrocks scope
|
||||||
import * as smartshell from '@pushrocks/smartshell';
|
|
||||||
import * as smartlog from '@pushrocks/smartlog';
|
import * as smartlog from '@pushrocks/smartlog';
|
||||||
import * as smartlogDestinationLocal from '@pushrocks/smartlog-destination-local';
|
import * as smartlogDestinationLocal from '@pushrocks/smartlog-destination-local';
|
||||||
|
import * as smartshell from '@pushrocks/smartshell';
|
||||||
|
import * as smartsystem from '@pushrocks/smartsystem';
|
||||||
|
|
||||||
export {
|
export {
|
||||||
smartshell,
|
|
||||||
smartlog,
|
smartlog,
|
||||||
smartlogDestinationLocal
|
smartlogDestinationLocal,
|
||||||
|
smartshell,
|
||||||
|
smartsystem
|
||||||
};
|
};
|
||||||
|
|
||||||
// third party
|
// third party
|
||||||
|
@ -1,174 +0,0 @@
|
|||||||
export const settingsReference = {
|
|
||||||
name: {
|
|
||||||
cli: {
|
|
||||||
short: 'n',
|
|
||||||
long: 'service',
|
|
||||||
value: '[name]',
|
|
||||||
description: 'Service name'
|
|
||||||
},
|
|
||||||
mandatory: true
|
|
||||||
},
|
|
||||||
description: {
|
|
||||||
cli: {
|
|
||||||
short: 'd',
|
|
||||||
long: 'description',
|
|
||||||
value: '[description]',
|
|
||||||
description: 'Service description'
|
|
||||||
},
|
|
||||||
default: '{name} service'
|
|
||||||
},
|
|
||||||
author: {
|
|
||||||
cli: {
|
|
||||||
short: 'k',
|
|
||||||
long: 'author',
|
|
||||||
value: '[author]',
|
|
||||||
description: 'Service author'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
user: {
|
|
||||||
cli: {
|
|
||||||
short: 'u',
|
|
||||||
long: 'user',
|
|
||||||
value: '[user]',
|
|
||||||
description: 'User to run service as'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
group: {
|
|
||||||
cli: {
|
|
||||||
short: 'g',
|
|
||||||
long: 'group',
|
|
||||||
value: '[group]',
|
|
||||||
description: 'Group to run service as'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
app: {
|
|
||||||
cli: {
|
|
||||||
short: 'A',
|
|
||||||
long: 'app',
|
|
||||||
value: '[app]',
|
|
||||||
description: 'Application main file'
|
|
||||||
},
|
|
||||||
default: 'main.js'
|
|
||||||
|
|
||||||
},
|
|
||||||
cwd: {
|
|
||||||
cli: {
|
|
||||||
short: 'c',
|
|
||||||
long: 'cwd',
|
|
||||||
value: '[path]',
|
|
||||||
description: 'Application cwd'
|
|
||||||
},
|
|
||||||
mandatory: true,
|
|
||||||
fs: true
|
|
||||||
},
|
|
||||||
'app.args': {
|
|
||||||
cli: {
|
|
||||||
short: 'p',
|
|
||||||
long: 'app.args',
|
|
||||||
value: '[args]',
|
|
||||||
description: 'Application arguments'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
env: {
|
|
||||||
cli: {
|
|
||||||
short: 'e',
|
|
||||||
long: 'env',
|
|
||||||
value: '[NAME=VALUE]',
|
|
||||||
description: 'Environment variables to set in systemd job',
|
|
||||||
function: (v, vars) => {
|
|
||||||
const _v = v.split('=')
|
|
||||||
vars[_v[0]] = _v[1]; return vars
|
|
||||||
},
|
|
||||||
store: []
|
|
||||||
}
|
|
||||||
},
|
|
||||||
pid: {
|
|
||||||
cli: {
|
|
||||||
short: 'P',
|
|
||||||
long: 'pid',
|
|
||||||
value: '[file]',
|
|
||||||
description: 'Service pid file'
|
|
||||||
},
|
|
||||||
default: '/var/run/{name}.pid'
|
|
||||||
},
|
|
||||||
log: {
|
|
||||||
cli: {
|
|
||||||
short: 'L',
|
|
||||||
long: 'log',
|
|
||||||
value: '[log]',
|
|
||||||
description: 'Service log file'
|
|
||||||
},
|
|
||||||
default: '/var/log/{name}/log'
|
|
||||||
},
|
|
||||||
error: {
|
|
||||||
cli: {
|
|
||||||
short: 'E',
|
|
||||||
long: 'error',
|
|
||||||
value: '[error]',
|
|
||||||
description: 'Service error file'
|
|
||||||
},
|
|
||||||
default: '/var/log/{name}/error'
|
|
||||||
},
|
|
||||||
engine: {
|
|
||||||
cli: {
|
|
||||||
short: 'X',
|
|
||||||
long: 'engine',
|
|
||||||
value: '[node|forever|pm2]',
|
|
||||||
description: 'Service engine (node|forever|pm2)'
|
|
||||||
},
|
|
||||||
default: 'node',
|
|
||||||
mandatory: true
|
|
||||||
},
|
|
||||||
'engine.bin': {
|
|
||||||
cli: {
|
|
||||||
short: 'b',
|
|
||||||
long: 'engine.bin',
|
|
||||||
value: '[bin]',
|
|
||||||
description: 'Service engine bin'
|
|
||||||
},
|
|
||||||
default: '/usr/bin/{engine}',
|
|
||||||
fs: true
|
|
||||||
},
|
|
||||||
'engine.args': {
|
|
||||||
cli: {
|
|
||||||
short: 't',
|
|
||||||
long: 'engine.args',
|
|
||||||
value: '[eargs]',
|
|
||||||
description: 'Service engine args'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
logrotate: {
|
|
||||||
cli: {
|
|
||||||
short: 'l',
|
|
||||||
long: 'logrotate',
|
|
||||||
description: 'Add logrotate config'
|
|
||||||
}
|
|
||||||
// default false
|
|
||||||
},
|
|
||||||
'logrotate.rotate': {
|
|
||||||
cli: {
|
|
||||||
short: 'R',
|
|
||||||
long: 'logrotate.rotate',
|
|
||||||
value: '[rotate]',
|
|
||||||
description: 'Logrotate rotations'
|
|
||||||
},
|
|
||||||
default: 10
|
|
||||||
|
|
||||||
},
|
|
||||||
'logrotate.frequency': {
|
|
||||||
cli: {
|
|
||||||
short: 'F',
|
|
||||||
long: 'logrotate.frequency',
|
|
||||||
value: '[frequency]',
|
|
||||||
description: 'Logrotate frequency'
|
|
||||||
},
|
|
||||||
default: 'daily'
|
|
||||||
},
|
|
||||||
noroot: {
|
|
||||||
cli: {
|
|
||||||
short: 'w',
|
|
||||||
long: 'noroot',
|
|
||||||
description: 'Skip check for root permission'
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
@ -1,259 +0,0 @@
|
|||||||
import * as plugins from './smartdaemon.plugins';
|
|
||||||
|
|
||||||
import { logger } from './smartdamon.logging';
|
|
||||||
import { settingsReference } from './smartdaemon.settings';
|
|
||||||
import { templateReference } from './smartdaemon.templates';
|
|
||||||
|
|
||||||
const smartshellInstance = new plugins.smartshell.Smartshell({
|
|
||||||
executor: 'bash'
|
|
||||||
});
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print success message
|
|
||||||
* @method setup.success
|
|
||||||
* @param {string} message
|
|
||||||
*/
|
|
||||||
export const setupSuccess = (message: string) => {
|
|
||||||
logger.log('success', `service-systemd: ${message}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* print error message
|
|
||||||
* @method setup.fail
|
|
||||||
* @param {string} message
|
|
||||||
*/
|
|
||||||
export const setupFail = (message) => {
|
|
||||||
logger.log('error', `service-systemd ${message}`);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* install the service
|
|
||||||
* can also be used to update the service
|
|
||||||
* @method setup.add
|
|
||||||
* @param {object} settings
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
export const setupAdd = async (settings) => {
|
|
||||||
setupCheckSettings(settings);
|
|
||||||
const contents = setupParse(settings);
|
|
||||||
await setupCheckPaths(settings);
|
|
||||||
await setupAddLog(settings);
|
|
||||||
await setupAddScripts(settings, contents);
|
|
||||||
await setupAddLogrotate(settings, contents);
|
|
||||||
return `service ${settings.name} installed`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* remove the service
|
|
||||||
* @method setup.remove
|
|
||||||
* @param {string} service service name
|
|
||||||
* @return {string}
|
|
||||||
*/
|
|
||||||
export const setupRemove = async (service) => {
|
|
||||||
if (!service) {
|
|
||||||
throw new Error('Missing argument: service name');
|
|
||||||
}
|
|
||||||
|
|
||||||
const cmd = `systemctl disable ${service}.service`;
|
|
||||||
logger.log('info', `service-systemd > ${cmd}`);
|
|
||||||
await smartshellInstance.exec(cmd);
|
|
||||||
|
|
||||||
let file = plugins.path.join('/etc/systemd/system', `${service}.service`);
|
|
||||||
logger.log('info', `service-systemd remove ${file}`);
|
|
||||||
await plugins.fs.unlink(file);
|
|
||||||
|
|
||||||
file = plugins.path.join('/usr/local/bin', `systemd-${service}-start`);
|
|
||||||
logger.log('info', `service-systemd remove ${file}`);
|
|
||||||
await plugins.fs.unlink(file);
|
|
||||||
|
|
||||||
file = plugins.path.join('/etc/logrotate.d', service);
|
|
||||||
logger.log('info', `service-systemd remove ${file}`);
|
|
||||||
await plugins.fs.unlink(file);
|
|
||||||
return `service ${service} uninstalled`;
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check mandatories params and paths
|
|
||||||
* @method setup.checkSettings
|
|
||||||
* @param {object} settings
|
|
||||||
*/
|
|
||||||
export const setupCheckSettings = (settings) => {
|
|
||||||
if (!settings.name) {
|
|
||||||
settings.name = settings.service;
|
|
||||||
}
|
|
||||||
|
|
||||||
delete settings.service;
|
|
||||||
|
|
||||||
const paths = [];
|
|
||||||
for (const optionArg of Object.keys(settingsReference)) {
|
|
||||||
const option = settingsReference[optionArg];
|
|
||||||
if (option.mandatory && !settings[optionArg]) {
|
|
||||||
throw new Error(`Missing ${optionArg} in settings file or arguments`);
|
|
||||||
}
|
|
||||||
if (option.fs) {
|
|
||||||
settings[optionArg] = plugins.path.resolve(settings[optionArg]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* check mandatories params and paths
|
|
||||||
* @method setup.checkPaths
|
|
||||||
* @param {object} settings
|
|
||||||
*/
|
|
||||||
export const setupCheckPaths = async (settings) => {
|
|
||||||
const exists = [];
|
|
||||||
for (const optionArg of Object.keys(settingsReference)) {
|
|
||||||
const option = settingsReference[optionArg];
|
|
||||||
if (option.fs) {
|
|
||||||
exists.push((async () => {
|
|
||||||
const exists2 = await plugins.fs.pathExists(settings[optionArg]);
|
|
||||||
if (!exists2) {
|
|
||||||
throw Error(`path ${settings[optionArg]} (${optionArg}) does not exists`);
|
|
||||||
}
|
|
||||||
})());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await Promise.all(exists);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* merge settings with templates
|
|
||||||
* create scripts contents
|
|
||||||
* @method setup.parse
|
|
||||||
* @param {object} settings
|
|
||||||
*/
|
|
||||||
export const setupParse = (settings) => {
|
|
||||||
|
|
||||||
if (settings.env) {
|
|
||||||
settings.envs = '';
|
|
||||||
for (const key of Object.keys(settings.env)) {
|
|
||||||
settings.envs += 'Environment=' + key + '=' + settings.env[key] + '\n';
|
|
||||||
}
|
|
||||||
}
|
|
||||||
settings.user = settings.user
|
|
||||||
? `User=${settings.user}`
|
|
||||||
: '';
|
|
||||||
settings.group = settings.group
|
|
||||||
? `Group=${settings.group}`
|
|
||||||
: '';
|
|
||||||
|
|
||||||
settings.date = (new Date()).toString();
|
|
||||||
|
|
||||||
for (const key in settings) {
|
|
||||||
if (typeof settings[key] === 'string') {
|
|
||||||
settings[key] = plugins.string.template(settings[key], settings, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
const _service = plugins.string.template(templateReference.engines[settings.engine].service, settings, true);
|
|
||||||
const _start = plugins.string.template(templateReference.engines[settings.engine].start, settings, true);
|
|
||||||
const _stop = plugins.string.template(templateReference.engines[settings.engine].stop, settings, true);
|
|
||||||
const _logrotate = settings.logrotate ? plugins.string.template(templateReference.logrotate, settings, true) : '';
|
|
||||||
|
|
||||||
return {
|
|
||||||
service: _service,
|
|
||||||
start: _start,
|
|
||||||
stop: _stop,
|
|
||||||
logrotate: _logrotate
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* write scripts and run commands to install the service
|
|
||||||
* @method setup.addScripts
|
|
||||||
* @param {object} settings
|
|
||||||
* @param {object} contents scripts contents
|
|
||||||
* @param {string} contents.start
|
|
||||||
* @param {string} contents.stop
|
|
||||||
* @param {string} contents.service
|
|
||||||
*/
|
|
||||||
export const setupAddScripts = async (settings, contents) => {
|
|
||||||
const service = plugins.path.join('/etc/systemd/system', `${settings.name}.service`);
|
|
||||||
const tasks = [];
|
|
||||||
|
|
||||||
if (contents.start) {
|
|
||||||
tasks.push(() => {
|
|
||||||
const start = plugins.path.join('/usr/local/bin', `systemd-${settings.name}-start`);
|
|
||||||
logger.log('info', `service-systemd: write file ${start}`);
|
|
||||||
return plugins.fs.writeFile(start, contents.start, 'utf8');
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contents.stop) {
|
|
||||||
tasks.push(() => {
|
|
||||||
const stop = plugins.path.join('/usr/local/bin', `systemd-${settings.name}-stop`);
|
|
||||||
logger.log('info', `service-systemd: write file ${stop}`);
|
|
||||||
return plugins.fs.writeFile(stop, contents.stop, {
|
|
||||||
encoding: 'utf8'
|
|
||||||
});
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (contents.start || contents.stop) {
|
|
||||||
tasks.push(() => {
|
|
||||||
const cmd = `chmod a+x /usr/local/bin/systemd-${settings.name}*`;
|
|
||||||
logger.log('info', `service-systemd > ${cmd}`);
|
|
||||||
return smartshellInstance.exec(cmd);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
tasks.push(() => {
|
|
||||||
logger.log('info', `service-systemd write file ${service}`);
|
|
||||||
return plugins.fs.writeFile(service, contents.service, 'utf8');
|
|
||||||
});
|
|
||||||
|
|
||||||
tasks.push(() => {
|
|
||||||
const cmd = `systemctl enable ${service};systemctl daemon-reload`;
|
|
||||||
logger.log('info', `service-systemd > ${cmd}`);
|
|
||||||
return smartshellInstance.exec(cmd);
|
|
||||||
});
|
|
||||||
|
|
||||||
for (const task of tasks) {
|
|
||||||
await task();
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* ensure dirs for log files
|
|
||||||
* @method setup.addLog
|
|
||||||
* @param {object} settings
|
|
||||||
*/
|
|
||||||
export const setupAddLog = async (settings) => {
|
|
||||||
const tasks = [];
|
|
||||||
let dirLog;
|
|
||||||
let dirError;
|
|
||||||
|
|
||||||
if (settings.log) {
|
|
||||||
dirLog = plugins.path.dirname(settings.log);
|
|
||||||
logger.log('info', `service-systemd: ensure dir ${dirLog}`);
|
|
||||||
tasks.push(plugins.fs.ensureDir(dirLog));
|
|
||||||
}
|
|
||||||
if (settings.error) {
|
|
||||||
dirError = plugins.path.dirname(settings.error);
|
|
||||||
if (dirError !== dirLog) {
|
|
||||||
logger.log('info', `service-systemd ensure dir ${dirError}`);
|
|
||||||
tasks.push(plugins.fs.ensureDir(dirError));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
await Promise.all(tasks);
|
|
||||||
};
|
|
||||||
|
|
||||||
/**
|
|
||||||
* write logrotate conf script
|
|
||||||
* @method setup.addLogrotate
|
|
||||||
* @param {object} settings
|
|
||||||
* @param {object} contents scripts contents
|
|
||||||
* @param {string} contents.start
|
|
||||||
* @param {string} contents.stop
|
|
||||||
* @param {string} contents.service
|
|
||||||
*/
|
|
||||||
export const setupAddLogrotate = async (settings, contents) => {
|
|
||||||
if (!settings.logrotate) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
const file = plugins.path.join('/etc/logrotate.d/', settings.name);
|
|
||||||
logger.log('info', `service-systemd: write logrotate file ${file}`);
|
|
||||||
await plugins.fs.writeFile(file, contents.logrotate, 'utf8');
|
|
||||||
};
|
|
@ -1,75 +0,0 @@
|
|||||||
export const templateReference = {
|
|
||||||
engines: {
|
|
||||||
node: {
|
|
||||||
service:
|
|
||||||
'# Generated by service-systemd on {{date}}\n' +
|
|
||||||
'[Unit]\n' +
|
|
||||||
'Description={description}\n' +
|
|
||||||
'Requires=network.target\n' +
|
|
||||||
'After=network.target\n' +
|
|
||||||
'\n' +
|
|
||||||
'[Service]\n' +
|
|
||||||
'Type=simple\n' +
|
|
||||||
'ExecStart={engine.bin} {engine.args} {app} {app.args}\n' +
|
|
||||||
'WorkingDirectory={cwd}\n' +
|
|
||||||
'Restart=on-failure\n' +
|
|
||||||
'{envs}\n' +
|
|
||||||
'LimitNOFILE=infinity\n' +
|
|
||||||
'LimitCORE=infinity\n' +
|
|
||||||
'StandardInput=null\n' +
|
|
||||||
'StandardOutput=syslog\n' +
|
|
||||||
'StandardError=syslog\n' +
|
|
||||||
'Restart=always\n' +
|
|
||||||
'SyslogIdentifier={name}\n' +
|
|
||||||
'PIDFile={pid}\n' +
|
|
||||||
'{user}\n' +
|
|
||||||
'{group}\n' +
|
|
||||||
'[Install]\n' +
|
|
||||||
'WantedBy=multi-user.target\n'
|
|
||||||
},
|
|
||||||
forever: {
|
|
||||||
service:
|
|
||||||
'# Generated by service-systemd on {date}\n' +
|
|
||||||
'[Unit]\n' +
|
|
||||||
'Description={description}\n' +
|
|
||||||
'Requires=network.target\n' +
|
|
||||||
'After=network.target\n' +
|
|
||||||
'\n' +
|
|
||||||
'[Service]\n' +
|
|
||||||
'Type=forking\n' +
|
|
||||||
'WorkingDirectory={cwd}\n' +
|
|
||||||
'{envs}\n' +
|
|
||||||
'ExecStart=/usr/local/bin/systemd-{name}-start\n' +
|
|
||||||
'ExecStop=/usr/local/bin/systemd-{name}-stop\n' +
|
|
||||||
'PIDFile={pid}\n' +
|
|
||||||
'{user}\n' +
|
|
||||||
'{group}\n' +
|
|
||||||
'[Install]\n' +
|
|
||||||
'WantedBy=multi-user.target\n',
|
|
||||||
start:
|
|
||||||
'#!/bin/bash\n' +
|
|
||||||
'{engine.bin} start ' +
|
|
||||||
'--pidFile {pid} ' +
|
|
||||||
'--uid {name} ' +
|
|
||||||
'--sourceDir {cwd} ' +
|
|
||||||
'-l {log} ' +
|
|
||||||
'-e {error} ' +
|
|
||||||
'--append --minUptime 5000 --spinSleepTime 2000 ' +
|
|
||||||
'{engine.args} ' +
|
|
||||||
'{app} {app.args}\n' +
|
|
||||||
'exit 0',
|
|
||||||
stop: '#!/bin/bash\n' + '{engine.bin} stop {name}\n' + 'exit 0'
|
|
||||||
}
|
|
||||||
},
|
|
||||||
logrotate:
|
|
||||||
'{log}\n{error} {\n' +
|
|
||||||
' {logrotate.frequency}\n' +
|
|
||||||
' rotate {logrotate.rotate}\n' +
|
|
||||||
' create\n' +
|
|
||||||
' missingok\n' +
|
|
||||||
' notifempty\n' +
|
|
||||||
' compress\n' +
|
|
||||||
' sharedscripts\n' +
|
|
||||||
// ' postrotate\n{restart}\n' +
|
|
||||||
' endscript\n}'
|
|
||||||
};
|
|
Loading…
Reference in New Issue
Block a user