From 6cf3ff6e835ad9c65f923d277ef3e494bf001d94 Mon Sep 17 00:00:00 2001 From: Phil Kunz Date: Thu, 5 Sep 2019 11:15:17 +0200 Subject: [PATCH] fix(core): update --- package-lock.json | 51 +++++++++++++++++++++++ package.json | 1 + test/test.ts | 3 +- ts/smartdaemon.classes.service.ts | 27 +++++++----- ts/smartdaemon.classes.smartdaemon.ts | 10 ++--- ts/smartdaemon.classes.systemdmanager.ts | 41 ++++++++++++++---- ts/smartdaemon.classes.templatemanager.ts | 19 +++++---- ts/smartdaemon.plugins.ts | 2 + 8 files changed, 121 insertions(+), 33 deletions(-) diff --git a/package-lock.json b/package-lock.json index 89dad4d..6b7a1b6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -215,6 +215,14 @@ } } }, + "@pushrocks/smartfm": { + "version": "2.0.4", + "resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartfm/-/smartfm-2.0.4.tgz", + "integrity": "sha512-QYxmIGhRfnE57rTCjsDBilPTrO/3VmajDxQt5z14pxAm9CeZypyGc4N6+Ts3KT1VGbs68NzCsGOM5ZYJW0Wmfg==", + "requires": { + "gray-matter": "^4.0.2" + } + }, "@pushrocks/smartlog": { "version": "2.0.19", "resolved": "https://verdaccio.lossless.one/@pushrocks%2fsmartlog/-/smartlog-2.0.19.tgz", @@ -770,6 +778,14 @@ "strip-eof": "^1.0.0" } }, + "extend-shallow": { + "version": "2.0.1", + "resolved": "https://verdaccio.lossless.one/extend-shallow/-/extend-shallow-2.0.1.tgz", + "integrity": "sha1-Ua99YUrZqfYQ6huvu5idaxxWiQ8=", + "requires": { + "is-extendable": "^0.1.0" + } + }, "figures": { "version": "3.0.0", "resolved": "https://verdaccio.lossless.one/figures/-/figures-3.0.0.tgz", @@ -850,6 +866,17 @@ "resolved": "https://verdaccio.lossless.one/graceful-fs/-/graceful-fs-4.2.2.tgz", "integrity": "sha512-IItsdsea19BoLC7ELy13q1iJFNmd7ofZH5+X/pJr90/nRoPEX0DJo1dHDbgtYWOhJhcCgMDTOw84RZ72q6lB+Q==" }, + "gray-matter": { + "version": "4.0.2", + "resolved": "https://verdaccio.lossless.one/gray-matter/-/gray-matter-4.0.2.tgz", + "integrity": "sha512-7hB/+LxrOjq/dd8APlK0r24uL/67w7SkYnfwhNFwg/VDIGWGmduTDYf3WNstLW2fbbmRwrDGCVSJ2isuf2+4Hw==", + "requires": { + "js-yaml": "^3.11.0", + "kind-of": "^6.0.2", + "section-matter": "^1.0.0", + "strip-bom-string": "^1.0.0" + } + }, "has-flag": { "version": "3.0.0", "resolved": "https://verdaccio.lossless.one/has-flag/-/has-flag-3.0.0.tgz", @@ -875,6 +902,11 @@ "integrity": "sha512-wPVv/y/QQ/Uiirj/vh3oP+1Ww+AWehmi1g5fFWGPF6IpCBCDVrhgHRMvrLfdYcwDh3QJbGXDW4JAuzxElLSqKA==", "dev": true }, + "is-extendable": { + "version": "0.1.1", + "resolved": "https://verdaccio.lossless.one/is-extendable/-/is-extendable-0.1.1.tgz", + "integrity": "sha1-YrEQ4omkcUGOPsNqYX1HLjAd/Ik=" + }, "is-fullwidth-code-point": { "version": "2.0.0", "resolved": "https://verdaccio.lossless.one/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", @@ -930,6 +962,11 @@ "graceful-fs": "^4.1.6" } }, + "kind-of": { + "version": "6.0.2", + "resolved": "https://verdaccio.lossless.one/kind-of/-/kind-of-6.0.2.tgz", + "integrity": "sha512-s5kLOcnH0XqDO+FvuaLX8DDjZ18CGFk7VygH40QoKPUQhW4e2rvM0rwUq0t8IQDOwYSeLK01U90OjzBTme2QqA==" + }, "lcid": { "version": "2.0.0", "resolved": "https://verdaccio.lossless.one/lcid/-/lcid-2.0.0.tgz", @@ -1286,6 +1323,15 @@ "resolved": "https://verdaccio.lossless.one/safe-buffer/-/safe-buffer-5.1.2.tgz", "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" }, + "section-matter": { + "version": "1.0.0", + "resolved": "https://verdaccio.lossless.one/section-matter/-/section-matter-1.0.0.tgz", + "integrity": "sha512-vfD3pmTzGpufjScBh50YHKzEu2lxBWhVEHsNGoEXmCmn2hKGfeNLYMzCJpe8cD7gqX7TJluOVpBkAequ6dgMmA==", + "requires": { + "extend-shallow": "^2.0.1", + "kind-of": "^6.0.0" + } + }, "semver": { "version": "5.7.0", "resolved": "https://verdaccio.lossless.one/semver/-/semver-5.7.0.tgz", @@ -1405,6 +1451,11 @@ "strip-bom": "^2.0.0" } }, + "strip-bom-string": { + "version": "1.0.0", + "resolved": "https://verdaccio.lossless.one/strip-bom-string/-/strip-bom-string-1.0.0.tgz", + "integrity": "sha1-5SEekiQ2n7uB1jOi8ABE3IztrZI=" + }, "strip-eof": { "version": "1.0.0", "resolved": "https://verdaccio.lossless.one/strip-eof/-/strip-eof-1.0.0.tgz", diff --git a/package.json b/package.json index b3b7846..5353bb2 100644 --- a/package.json +++ b/package.json @@ -23,6 +23,7 @@ "dependencies": { "@pushrocks/lik": "^3.0.11", "@pushrocks/smartfile": "^7.0.4", + "@pushrocks/smartfm": "^2.0.4", "@pushrocks/smartlog": "^2.0.19", "@pushrocks/smartlog-destination-local": "^8.0.2", "@pushrocks/smartshell": "^2.0.25", diff --git a/test/test.ts b/test/test.ts index 453b7b5..668d51a 100644 --- a/test/test.ts +++ b/test/test.ts @@ -10,9 +10,10 @@ tap.test('should create an instance of smartdaemon', async () => { tap.test('should create a service', async () => { testSmartdaemon.addService({ + name: 'npmversion', + version: 'x.x.x', command: 'npm -v', description: 'displays the npm version', - name: 'npmversion', workingDir: __dirname }); }); diff --git a/ts/smartdaemon.classes.service.ts b/ts/smartdaemon.classes.service.ts index bcf203f..303bbd2 100644 --- a/ts/smartdaemon.classes.service.ts +++ b/ts/smartdaemon.classes.service.ts @@ -2,18 +2,19 @@ import * as plugins from './smartdaemon.plugins'; import * as paths from './smartdaemon.paths'; import { SmartDaemon } from './smartdaemon.classes.smartdaemon'; -export interface SmartDaemonServiceConstructorOptions { +export interface ISmartDaemonServiceConstructorOptions { name: string; description: string; command: string; workingDir: string; + version: string; } /** * represents a service that is being spawned by SmartDaemon */ -export class SmartDaemonService implements SmartDaemonServiceConstructorOptions { - public static async createFromOptions(smartdaemonRef: SmartDaemon, optionsArg: SmartDaemonServiceConstructorOptions) { +export class SmartDaemonService implements ISmartDaemonServiceConstructorOptions { + public static async createFromOptions(smartdaemonRef: SmartDaemon, optionsArg: ISmartDaemonServiceConstructorOptions) { const service = new SmartDaemonService(smartdaemonRef); for (const key of Object.keys(optionsArg)) { service[key] = optionsArg[key]; @@ -21,12 +22,13 @@ export class SmartDaemonService implements SmartDaemonServiceConstructorOptions return service; } - public options: SmartDaemonServiceConstructorOptions; + public options: ISmartDaemonServiceConstructorOptions; public name: string; - public description: string; + public version: string; public command: string; public workingDir: string; + public description: string; public smartdaemonRef: SmartDaemon; @@ -66,16 +68,19 @@ export class SmartDaemonService implements SmartDaemonServiceConstructorOptions // Save and Delete public async save() { - await this.smartdaemonRef.systemdManager.saveService(this.name, this.smartdaemonRef.templateManager.generateServiceTemplate({ + const serviceTemplate = this.smartdaemonRef.templateManager.generateServiceTemplate({ + name: this.name, + version: this.version, command: this.command, + workkingDir: this.workingDir, description: this.description, - pathWorkkingDir: this.workingDir, - serviceName: this.name, - serviceVersion: 'x.x.x' - })); + }); + await this.smartdaemonRef.systemdManager.saveService(this.name, serviceTemplate); } - /** */ + /** + * deletes the service + */ public async delete() { await this.smartdaemonRef.systemdManager.deleteService(this.name); } diff --git a/ts/smartdaemon.classes.smartdaemon.ts b/ts/smartdaemon.classes.smartdaemon.ts index ad58846..53cd889 100644 --- a/ts/smartdaemon.classes.smartdaemon.ts +++ b/ts/smartdaemon.classes.smartdaemon.ts @@ -1,18 +1,15 @@ import * as plugins from './smartdaemon.plugins'; import { SmartDaemonTemplateManager } from './smartdaemon.classes.templatemanager'; -import { SmartDaemonService, SmartDaemonServiceConstructorOptions } from './smartdaemon.classes.service'; +import { SmartDaemonService, ISmartDaemonServiceConstructorOptions } from './smartdaemon.classes.service'; import { SmartDaemonSystemdManager } from './smartdaemon.classes.systemdmanager'; export class SmartDaemon { - - public serviceMap: plugins.lik.Objectmap; public templateManager: SmartDaemonTemplateManager; public systemdManager: SmartDaemonSystemdManager; constructor() { - this.serviceMap = new plugins.lik.Objectmap(); this.templateManager = new SmartDaemonTemplateManager(this); this.systemdManager = new SmartDaemonSystemdManager(this); } @@ -23,9 +20,10 @@ export class SmartDaemon { * @param commandArg * @param workingDirectoryArg */ - public async addService(optionsArg: SmartDaemonServiceConstructorOptions): Promise { + public async addService(optionsArg: ISmartDaemonServiceConstructorOptions): Promise { let serviceToAdd: SmartDaemonService; - const existingService = this.serviceMap.find(serviceArg => { + const existingServices = await this.systemdManager.getServices(); + const existingService = existingServices.find(serviceArg => { return serviceArg.name === optionsArg.name; }); if (!existingService) { diff --git a/ts/smartdaemon.classes.systemdmanager.ts b/ts/smartdaemon.classes.systemdmanager.ts index 3175853..2daab58 100644 --- a/ts/smartdaemon.classes.systemdmanager.ts +++ b/ts/smartdaemon.classes.systemdmanager.ts @@ -1,6 +1,7 @@ import * as plugins from './smartdaemon.plugins'; import * as paths from './smartdaemon.paths'; import { SmartDaemon } from './smartdaemon.classes.smartdaemon'; +import { ISmartDaemonServiceConstructorOptions, SmartDaemonService } from './smartdaemon.classes.service'; export class SmartDaemonSystemdManager { // STATIC @@ -47,23 +48,41 @@ export class SmartDaemonSystemdManager { } } + /** + * gets all services that are already present + */ public async getServices() { + const existingServices = []; if (await this.checkElegibility()) { - const availableServices = plugins.smartfile.fs.listAllItems( + const smartfmInstance = new plugins.smartfm.Smartfm({ + fmType: 'yaml' + }); + const availableServices = await plugins.smartfile.fs.fileTreeToObject( paths.systemdDir, - new RegExp(`${SmartDaemonSystemdManager.smartDaemonNamespace}`) + 'smartdaemon_*.service' ); + for (const serviceFile of availableServices) { + const data = smartfmInstance.parseFromComments('# ', serviceFile.contentBuffer.toString()) + .data as ISmartDaemonServiceConstructorOptions; + const service = SmartDaemonService.createFromOptions(this.smartdaemonRef, data); + existingServices.push(service); + } } + return existingServices; } public async startService(serviceNameArg: string) { if (await this.checkElegibility()) { - await this.execute(`systemctl start ${SmartDaemonSystemdManager.createFilePathFromServiceName(serviceNameArg)}`); + await this.execute( + `systemctl start ${SmartDaemonSystemdManager.createFilePathFromServiceName(serviceNameArg)}` + ); } - }; + } public async stopService(serviceNameArg: string) { if (await this.checkElegibility()) { - await this.execute(`systemctl stop ${SmartDaemonSystemdManager.createFilePathFromServiceName(serviceNameArg)}`); + await this.execute( + `systemctl stop ${SmartDaemonSystemdManager.createFilePathFromServiceName(serviceNameArg)}` + ); } } @@ -78,18 +97,24 @@ export class SmartDaemonSystemdManager { public async deleteService(serviceName: string) { if (await this.checkElegibility()) { - await plugins.smartfile.fs.remove(SmartDaemonSystemdManager.createFilePathFromServiceName(serviceName)); + await plugins.smartfile.fs.remove( + SmartDaemonSystemdManager.createFilePathFromServiceName(serviceName) + ); } } public async enableService(serviceName: string) { if (await this.checkElegibility()) { - await this.execute(`systemctl enable ${SmartDaemonSystemdManager.createFileNameFromServiceName(serviceName)}`); + await this.execute( + `systemctl enable ${SmartDaemonSystemdManager.createFileNameFromServiceName(serviceName)}` + ); } } public async disableService(serviceName: string) { if (await this.checkElegibility()) { - await this.execute(`systemctl disable ${SmartDaemonSystemdManager.createFileNameFromServiceName(serviceName)}`); + await this.execute( + `systemctl disable ${SmartDaemonSystemdManager.createFileNameFromServiceName(serviceName)}` + ); } } diff --git a/ts/smartdaemon.classes.templatemanager.ts b/ts/smartdaemon.classes.templatemanager.ts index 874536c..185bfb4 100644 --- a/ts/smartdaemon.classes.templatemanager.ts +++ b/ts/smartdaemon.classes.templatemanager.ts @@ -9,14 +9,19 @@ export class SmartDaemonTemplateManager { } public generateServiceTemplate = (optionsArg: { - serviceName: string; + name: string; description: string; - serviceVersion: string; + version: string; command: string; - pathWorkkingDir; + workkingDir; }) => { - return ` -# servicVersion: ${optionsArg.serviceVersion} + return `# --- +# name: ${optionsArg.name} +# version: ${optionsArg.version} +# description: ${optionsArg.description} +# command: ${optionsArg.command} +# workingDir: ${optionsArg.workkingDir} +# --- [Unit] Description=${optionsArg.description} Requires=network.target @@ -24,8 +29,8 @@ After=network.target [Service] Type=simple -ExecStart=/bin/bash -c "cd ${optionsArg.pathWorkkingDir} && ${optionsArg.command}" -WorkingDirectory=${optionsArg.pathWorkkingDir} +ExecStart=/bin/bash -c "cd ${optionsArg.workkingDir} && ${optionsArg.command}" +WorkingDirectory=${optionsArg.workkingDir} Restart=on-failure LimitNOFILE=infinity LimitCORE=infinity diff --git a/ts/smartdaemon.plugins.ts b/ts/smartdaemon.plugins.ts index bcd0c15..d51096f 100644 --- a/ts/smartdaemon.plugins.ts +++ b/ts/smartdaemon.plugins.ts @@ -9,6 +9,7 @@ export { // @pushrocks scope import * as lik from '@pushrocks/lik'; import * as smartfile from '@pushrocks/smartfile'; +import * as smartfm from '@pushrocks/smartfm'; import * as smartlog from '@pushrocks/smartlog'; import * as smartlogDestinationLocal from '@pushrocks/smartlog-destination-local'; import * as smartshell from '@pushrocks/smartshell'; @@ -17,6 +18,7 @@ import * as smartsystem from '@pushrocks/smartsystem'; export { lik, smartfile, + smartfm, smartlog, smartlogDestinationLocal, smartshell,