From 80fc9b2566ffe0e9479189eeae8ace24438d1af4 Mon Sep 17 00:00:00 2001 From: Jorge Miguel Lobo Escalona Date: Mon, 14 Feb 2022 16:15:29 +0100 Subject: [PATCH] F #5631: vCenter import elements (#1772) (cherry picked from commit e9f33231f56e4843db0993e1180d781ec358a21b) --- src/cli/onevcenter | 3 +- src/fireedge/src/server/index.js | 10 +- .../api/oneprovision/provision/functions.js | 26 +- .../server/routes/api/oneprovision/utils.js | 36 -- .../routes/api/vcenter/command-flags.js | 72 ++- .../server/routes/api/vcenter/functions.js | 506 +++++++++++------- .../src/server/routes/api/vcenter/index.js | 42 +- .../src/server/routes/api/vcenter/routes.js | 107 ++-- .../server/routes/entrypoints/Api/xmlrpc.js | 49 +- .../{guacamole/index.js => guacamole.js} | 5 +- .../{hooks/index.js => opennebula/hooks.js} | 4 +- .../websockets/{ => opennebula}/index.js | 10 +- .../opennebula/provision.js} | 44 +- .../index.js => opennebula/vcenter.js} | 15 +- .../websockets/{vmrc/index.js => vmrc.js} | 4 +- .../src/server/utils/constants/defaults.js | 13 +- src/fireedge/src/server/utils/index.worker.js | 28 +- src/fireedge/src/server/utils/opennebula.js | 91 ++-- src/fireedge/src/server/utils/server.js | 54 +- src/fireedge/src/server/utils/worker.js | 74 +++ 20 files changed, 745 insertions(+), 448 deletions(-) rename src/fireedge/src/server/routes/websockets/{guacamole/index.js => guacamole.js} (98%) rename src/fireedge/src/server/routes/websockets/{hooks/index.js => opennebula/hooks.js} (99%) rename src/fireedge/src/server/routes/websockets/{ => opennebula}/index.js (92%) rename src/fireedge/src/server/routes/{api/vcenter/basepath.js => websockets/opennebula/provision.js} (53%) rename src/fireedge/src/server/routes/websockets/{provision/index.js => opennebula/vcenter.js} (88%) rename src/fireedge/src/server/routes/websockets/{vmrc/index.js => vmrc.js} (99%) create mode 100644 src/fireedge/src/server/utils/worker.js diff --git a/src/cli/onevcenter b/src/cli/onevcenter index d05000698f..a391dc1bb7 100755 --- a/src/cli/onevcenter +++ b/src/cli/onevcenter @@ -198,7 +198,8 @@ CommandParser::CmdParser.new(ARGV) do command :list_all, list_desc, - :options => [OBJECT, HOST, DATASTORE, VCENTER, USER, PASS] do + :options => [OBJECT, HOST, DATASTORE, VCENTER, USER, PASS, + CLIHelper::CSV_OPT] do begin args = helper.parse_opts(options) args[:filter] = false diff --git a/src/fireedge/src/server/index.js b/src/fireedge/src/server/index.js index 4307daa59f..5f9b9c20cd 100644 --- a/src/fireedge/src/server/index.js +++ b/src/fireedge/src/server/index.js @@ -29,9 +29,9 @@ import { entrypointApi, entrypointApp, } from './routes/entrypoints' -import { websockets } from './routes/websockets' -import { guacamole } from './routes/websockets/guacamole' -import { vmrc } from './routes/websockets/vmrc' +import opennebulaWebsockets from './routes/websockets/opennebula' +import guacamole from './routes/websockets/guacamole' +import vmrc from './routes/websockets/vmrc' import { getFireedgeConfig } from './utils/yml' import { messageTerminal } from './utils/general' import { @@ -143,7 +143,7 @@ const appServer = validateServerIsSecure() ) : unsecureServer(app) -const sockets = websockets(appServer) || [] +const websockets = opennebulaWebsockets(appServer) || [] let config = { color: 'red', @@ -167,7 +167,7 @@ guacamole(appServer) * Handle sigterm and sigint. */ const handleBreak = () => { - sockets.forEach((socket) => { + websockets.forEach((socket) => { if (socket && socket.close && typeof socket.close === 'function') { socket.close() } diff --git a/src/fireedge/src/server/routes/api/oneprovision/provision/functions.js b/src/fireedge/src/server/routes/api/oneprovision/provision/functions.js index 5f0291b9ea..a0517abc2a 100644 --- a/src/fireedge/src/server/routes/api/oneprovision/provision/functions.js +++ b/src/fireedge/src/server/routes/api/oneprovision/provision/functions.js @@ -24,6 +24,7 @@ const { sprintf } = require('sprintf-js') const { Actions } = require('server/utils/constants/commands/document') const { defaults, httpCodes } = require('server/utils/constants') +const { publish } = require('server/utils/server') const { httpResponse, parsePostData, @@ -43,7 +44,6 @@ const { renameFolder, moveToFolder, findRecursiveFolder, - publish, getEndpoint, addOptionalCreateCommand, getSpecificConfig, @@ -55,6 +55,9 @@ const { defaultCommandProvision, defaultEmptyFunction, defaultErrorTemplate, + defaultRegexpStartJSON, + defaultRegexpEndJSON, + defaultRegexpSplitLine, } = defaults const { ok, notFound, accepted, internalServerError } = httpCodes const httpInternalError = httpResponse(internalServerError, '', '') @@ -68,9 +71,6 @@ const provisionFile = { ext: 'yaml', } const regexp = /^ID: \d+/ -const regexpStartJSON = /^{/ -const regexpEndJSON = /}$/ -const regexpSplitLine = /\r|\n/ const relName = 'provision-mapping' const ext = 'yml' const appendError = '.ERROR' @@ -143,21 +143,23 @@ const executeWithEmit = (command = [], actions = {}, dataForLog = {}) => { message .toString() - .split(regexpSplitLine) + .split(defaultRegexpSplitLine) .forEach((line) => { if (line) { if ( - (regexpStartJSON.test(line) && regexpEndJSON.test(line)) || - (!regexpStartJSON.test(line) && - !regexpEndJSON.test(line) && + (defaultRegexpStartJSON.test(line) && + defaultRegexpEndJSON.test(line)) || + (!defaultRegexpStartJSON.test(line) && + !defaultRegexpEndJSON.test(line) && pendingMessages.length === 0) ) { lastLine = line publisher(lastLine) } else if ( - (regexpStartJSON.test(line) && !regexpEndJSON.test(line)) || - (!regexpStartJSON.test(line) && - !regexpEndJSON.test(line) && + (defaultRegexpStartJSON.test(line) && + !defaultRegexpEndJSON.test(line)) || + (!defaultRegexpStartJSON.test(line) && + !defaultRegexpEndJSON.test(line) && pendingMessages.length > 0) ) { pendingMessages += line @@ -225,7 +227,7 @@ const logData = (id, fullPath = false) => { existsFile( stringPath, (filedata) => { - rtn = { uuid, log: filedata.split(regexpSplitLine) } + rtn = { uuid, log: filedata.split(defaultRegexpSplitLine) } if (fullPath) { rtn.fullPath = stringPath } diff --git a/src/fireedge/src/server/routes/api/oneprovision/utils.js b/src/fireedge/src/server/routes/api/oneprovision/utils.js index ea72a69969..4cae023e59 100644 --- a/src/fireedge/src/server/routes/api/oneprovision/utils.js +++ b/src/fireedge/src/server/routes/api/oneprovision/utils.js @@ -18,7 +18,6 @@ const { v4 } = require('uuid') const { dirname, basename } = require('path') // eslint-disable-next-line node/no-deprecated-api const { parse } = require('url') -const events = require('events') const { Document, scalarOptions, stringify } = require('yaml') const { writeFileSync, @@ -33,39 +32,6 @@ const { getFireedgeConfig, getProvisionConfig } = require('server/utils/yml') const { messageTerminal } = require('server/utils/general') const { defaultError } = require('server/utils/server') -const eventsEmitter = new events.EventEmitter() - -/** - * Create a event emiter. - * - * @param {string} eventName - name event - * @param {object} message - object message - */ -const publish = (eventName = '', message = {}) => { - if (eventName && message) { - eventsEmitter.emit(eventName, message) - } -} - -/** - * Subscriber to event emitter. - * - * @param {string} eventName - event name - * @param {Function} callback - function executed when event is emited - */ -const subscriber = (eventName = '', callback = () => undefined) => { - if ( - eventName && - callback && - typeof callback === 'function' && - eventsEmitter.listenerCount(eventName) < 1 - ) { - eventsEmitter.on(eventName, (message) => { - callback(message) - }) - } -} - /** * Create folder with files. * @@ -322,9 +288,7 @@ const functionRoutes = { renameFolder, moveToFolder, findRecursiveFolder, - publish, addOptionalCreateCommand, - subscriber, getSpecificConfig, } diff --git a/src/fireedge/src/server/routes/api/vcenter/command-flags.js b/src/fireedge/src/server/routes/api/vcenter/command-flags.js index 9d0d2796f9..da2a6fce87 100644 --- a/src/fireedge/src/server/routes/api/vcenter/command-flags.js +++ b/src/fireedge/src/server/routes/api/vcenter/command-flags.js @@ -19,6 +19,14 @@ const TEMPLATES = 'templates' const NETWORKS = 'networks' const IMAGES = 'images' +const LIST = 'list' +const IMPORT = 'import' + +const resourceFromData = { + LIST, + IMPORT, +} + const resources = { DATASTORES, TEMPLATES, @@ -26,45 +34,55 @@ const resources = { IMAGES, } -const questions = { - [DATASTORES]: [], +const params = { + [DATASTORES]: [ + { + param: 'host', + flag: '-h', + for: [LIST, IMPORT], + }, + ], [TEMPLATES]: [ { - question: 'Type', - flag: '--type', + param: 'datastore', + flag: '--datastore', + for: [LIST, IMPORT], }, { - question: 'Folder', + param: 'host', + flag: '-h', + for: [LIST, IMPORT], + }, + { + param: 'folder', flag: '--folder', + for: [IMPORT], }, { - question: 'Linked Clone', - flag: '--linked-clone', + param: 'linked_clone', + flag: '--linked_clone', + for: [IMPORT], }, ], [NETWORKS]: [ { - question: 'Size', - flag: '--size', - }, - { - question: 'Type', - flag: '--type', - }, - { - question: 'MAC', - flag: '--mac', - }, - { - question: 'Cluster(s) to import', - flag: '--cluster-imports', - }, - { - question: 'Unimported Cluster(s)', - flag: '--cluster-unimported', + param: 'host', + flag: '-h', + for: [LIST, IMPORT], + }, + ], + [IMAGES]: [ + { + param: 'host', + flag: '-h', + for: [LIST, IMPORT], + }, + { + param: 'datastore', + flag: '--datastore', + for: [LIST, IMPORT], }, ], - [IMAGES]: [], } -module.exports = { resources, questions } +module.exports = { resourceFromData, resources, params } diff --git a/src/fireedge/src/server/routes/api/vcenter/functions.js b/src/fireedge/src/server/routes/api/vcenter/functions.js index 60e250b6d8..7a722a3f1a 100644 --- a/src/fireedge/src/server/routes/api/vcenter/functions.js +++ b/src/fireedge/src/server/routes/api/vcenter/functions.js @@ -14,83 +14,93 @@ * limitations under the License. * * ------------------------------------------------------------------------- */ const { defaults, httpCodes } = require('server/utils/constants') -const { httpResponse, executeCommand } = require('server/utils/server') +const { + httpResponse, + executeCommand, + executeCommandAsync, + publish, +} = require('server/utils/server') const { consoleParseToString, consoleParseToJSON, } = require('server/utils/opennebula') -const { resources } = require('server/routes/api/vcenter/command-flags') +const { + resourceFromData, + resources, + params: commandParams, +} = require('server/routes/api/vcenter/command-flags') const { getSunstoneConfig } = require('server/utils/yml') -const { defaultEmptyFunction, defaultCommandVcenter } = defaults -const { ok, internalServerError, badRequest } = httpCodes -const httpBadRequest = httpResponse(badRequest, '', '') +const { + defaultEmptyFunction, + defaultCommandVcenter, + defaultRegexpStartJSON, + defaultRegexpEndJSON, + defaultRegexpSplitLine, +} = defaults + +const { ok, internalServerError, badRequest, accepted } = httpCodes +const { LIST, IMPORT } = resourceFromData const appConfig = getSunstoneConfig() const prependCommand = appConfig.vcenter_prepend_command || '' const regexExclude = [ - /^Connecting to.*/gi, - /^Exploring vCenter.*/gi, + /^Connecting to.*/i, + /^Exploring vCenter.*/i, // eslint-disable-next-line no-control-regex - /^\u001b\[.*?m\u001b\[.*?m# vCenter.*/gi, + /^\u001b\[.*?m\u001b\[.*?m# vCenter.*/i, ] +const regexHeader = /^IMID,.*/i + const validObjects = Object.values(resources) /** - * Import the the desired vCenter object. + * Show a list with unimported vCenter objects excluding all filters. * * @param {object} res - http response * @param {Function} next - express stepper * @param {object} params - params of http request - * @param {object} userData - user of http request */ -const importVcenter = ( - res = {}, - next = defaultEmptyFunction, - params = {}, - userData = {} -) => { - let rtn = httpBadRequest - // check params - if ( - params && - params.vobject && - validObjects.includes(params.vobject) && - params.host - ) { - const vobject = `${params.vobject}`.toLowerCase() +const list = (res = {}, next = defaultEmptyFunction, params = {}) => { + const { vobject, host, datastore } = params - let paramsCommand = [params.answers ? 'import' : 'import_defaults'] + const vobjectLowercase = vobject && `${vobject}`.toLowerCase() + if (!(vobjectLowercase && host && validObjects.includes(vobjectLowercase))) { + res.locals.httpCode = badRequest + next() - if (params.id) { - paramsCommand.push(`${params.id}`) - } - - let vobjectAndHost = ['-o', `${vobject}`, '-h', `${params.host}`] - - if (vobject === resources.IMAGES && params.datastore) { - const datastoreParameter = ['-d', params.datastore] - vobjectAndHost = [...vobjectAndHost, ...datastoreParameter] - } - - // flags by questions import command - /* if (params.answers && questions[vobject]) { - const answers = params.answers.split(',') - } */ - - paramsCommand = [...paramsCommand, ...vobjectAndHost] - const executedCommand = executeCommand( - defaultCommandVcenter, - paramsCommand, - prependCommand - ) - const response = executedCommand.success ? ok : internalServerError - let message = '' - if (executedCommand.data) { - message = consoleParseToString(executedCommand.data, regexExclude) - } - rtn = httpResponse(response, message) + return } - res.locals.httpCode = rtn + + let paramsCommand = [ + 'list', + '-o', + `${vobjectLowercase}`, + '-h', + `${host}`, + '--csv', + ] + + if (vobjectLowercase === resources.IMAGES && datastore) { + const newParameters = ['-d', datastore] + paramsCommand = [...paramsCommand, ...newParameters] + } + + const executedCommand = executeCommand( + defaultCommandVcenter, + paramsCommand, + prependCommand + ) + + const response = executedCommand.success ? ok : internalServerError + let message = '' + if (executedCommand.data) { + message = consoleParseToJSON( + consoleParseToString(executedCommand.data, regexExclude), + regexHeader + ) + } + + res.locals.httpCode = httpResponse(response, message) next() } @@ -100,105 +110,46 @@ const importVcenter = ( * @param {object} res - http response * @param {Function} next - express stepper * @param {object} params - params of http request - * @param {object} userData - user of http request */ -const list = ( - res = {}, - next = defaultEmptyFunction, - params = {}, - userData = {} -) => { - let rtn = httpBadRequest - if ( - params && - params.vobject && - validObjects.includes(params.vobject) && - params.host - ) { - const vobject = `${params.vobject}`.toLowerCase() - let paramsCommand = [ - 'list', - '-o', - `${vobject}`, - '-h', - `${params.host}`, - '--csv', - ] - if (vobject === resources.IMAGES && params.datastore) { - const newParameters = ['-d', params.datastore] - paramsCommand = [...paramsCommand, ...newParameters] - } - const executedCommand = executeCommand( - defaultCommandVcenter, - paramsCommand, - prependCommand - ) +const listAll = (res = {}, next = defaultEmptyFunction, params = {}) => { + const { vobject, host, datastore } = params - const response = executedCommand.success ? ok : internalServerError - let message = '' - if (executedCommand.data) { - message = consoleParseToJSON( - consoleParseToString(executedCommand.data, regexExclude), - /^IMID,.*/gi - ) - } - rtn = httpResponse(response, message) + const vobjectLowercase = vobject && `${vobject}`.toLowerCase() + if (!(vobjectLowercase && host && validObjects.includes(vobjectLowercase))) { + res.locals.httpCode = badRequest + next() + + return } - res.locals.httpCode = rtn - next() -} -/** - * Show a list with unimported vCenter objects excluding all filters. - * - * @param {object} res - http response - * @param {Function} next - express stepper - * @param {object} params - params of http request - * @param {object} userData - user of http request - */ -const listAll = ( - res = {}, - next = defaultEmptyFunction, - params = {}, - userData = {} -) => { - let rtn = httpBadRequest - if ( - params && - params.vobject && - validObjects.includes(params.vobject) && - params.host - ) { - const vobject = `${params.vobject}`.toLowerCase() - let paramsCommand = [ - 'list_all', - '-o', - `${vobject}`, - '-h', - `${params.host}`, - '--csv', - ] - if (vobject === resources.IMAGES && params.datastore) { - const newParameters = ['-d', params.datastore] - paramsCommand = [...paramsCommand, ...newParameters] - } - const executedCommand = executeCommand( - defaultCommandVcenter, - paramsCommand, - prependCommand - ) + let paramsCommand = [ + 'list_all', + '-o', + `${vobjectLowercase}`, + '-h', + `${host}`, + '--csv', + ] - const response = executedCommand.success ? ok : internalServerError - let message = '' - if (executedCommand.data) { - message = consoleParseToJSON( - consoleParseToString(executedCommand.data, regexExclude), - /^IMID,.*/gi - ) - } - rtn = httpResponse(response, message) + if (vobjectLowercase === resources.IMAGES && datastore) { + const newParameters = ['-d', datastore] + paramsCommand = [...paramsCommand, ...newParameters] } - res.locals.httpCode = rtn + const executedCommand = executeCommand( + defaultCommandVcenter, + paramsCommand, + prependCommand + ) + + const response = executedCommand.success ? ok : internalServerError + let message = '' + if (executedCommand.data) { + message = consoleParseToJSON( + consoleParseToString(executedCommand.data, regexExclude), + regexHeader + ) + } + res.locals.httpCode = httpResponse(response, message) next() } @@ -208,31 +159,28 @@ const listAll = ( * @param {object} res - http response * @param {Function} next - express stepper * @param {object} params - params of http request - * @param {object} userData - user of http request */ -const cleartags = ( - res = {}, - next = defaultEmptyFunction, - params = {}, - userData = {} -) => { - let rtn = httpBadRequest - // check params - if (params && params.id) { - const paramsCommand = ['cleartags', `${params.id}`] - const executedCommand = executeCommand( - defaultCommandVcenter, - paramsCommand, - prependCommand - ) - const response = executedCommand.success ? ok : internalServerError - let message = '' - if (executedCommand.data) { - message = consoleParseToString(executedCommand.data, regexExclude) - } - rtn = httpResponse(response, message) +const cleartags = (res = {}, next = defaultEmptyFunction, params = {}) => { + const { id } = params + if (!Number.isInteger(parseInt(id))) { + res.locals.httpCode = badRequest + next() + + return } - res.locals.httpCode = rtn + + const paramsCommand = ['cleartags', id] + const executedCommand = executeCommand( + defaultCommandVcenter, + paramsCommand, + prependCommand + ) + const response = executedCommand.success ? ok : internalServerError + let message = '' + if (executedCommand.data) { + message = consoleParseToString(executedCommand.data, regexExclude) + } + res.locals.httpCode = httpResponse(response, message) next() } @@ -242,48 +190,196 @@ const cleartags = ( * @param {object} res - http response * @param {Function} next - express stepper * @param {object} params - params of http request - * @param {object} userData - user of http request */ -const hosts = ( - res = {}, - next = defaultEmptyFunction, - params = {}, - userData = {} -) => { - let rtn = httpBadRequest - // check params - if (params && params.vcenter && params.user && params.pass) { - const paramsCommand = [ - 'hosts', - '--vcenter', - `${params.vcenter}`.toLowerCase(), - '--vuser', - `${params.user}`, - '--vpass', - `${params.pass}`, - '--use-defaults', - ] - const executedCommand = executeCommand( - defaultCommandVcenter, - paramsCommand, - prependCommand - ) - const response = executedCommand.success ? ok : internalServerError - let message = '' - if (executedCommand.data) { - message = consoleParseToString(executedCommand.data, regexExclude) - } - rtn = httpResponse(response, message) +const importHost = (res = {}, next = defaultEmptyFunction, params = {}) => { + /** + * PENDING IMPORT 1 HOST + */ + const { vcenter, user, pass } = params + + if (!(vcenter && user && pass)) { + res.locals.httpCode = badRequest + next() + + return } - res.locals.httpCode = rtn + + const vcenterLowercase = vcenter && `${vcenter}`.toLowerCase() + + const paramsCommand = [ + 'hosts', + '--vcenter', + vcenterLowercase, + '--vuser', + `${user}`, + '--vpass', + `${pass}`, + '--use-defaults', + ] + + const executedCommand = executeCommand( + defaultCommandVcenter, + paramsCommand, + prependCommand + ) + + const response = executedCommand.success ? ok : internalServerError + let message = '' + if (executedCommand.data) { + message = consoleParseToString(executedCommand.data, regexExclude) + } + res.locals.httpCode = httpResponse(response, message) next() } +/** + * Import the desired vCenter object. + * + * @param {object} res - http response + * @param {Function} next - express stepper + * @param {object} params - params of http request + * @param {object} userData - user Data + * @param {Function} oneConnection - xmlrpc function + * @param {'template'|'images'|'datastores'|'networks'} type - type resource + */ +const importVobject = ( + res = {}, + next = defaultEmptyFunction, + params = {}, + userData = {}, + oneConnection = defaultEmptyFunction, + type +) => { + const httpReturn = (httpCode) => { + res.locals.httpCode = httpCode + next() + } + + !(type && validObjects.includes(type)) && httpReturn(badRequest) + + const paramsForCommand = commandParams[type] + + let flagsImport = [] + paramsForCommand + .filter((flag) => flag.for && flag.for.includes(IMPORT)) + .forEach(({ param, flag }) => { + if (params[param]) { + flagsImport = [...flagsImport, flag, params[param]] + } + }) + + const publisher = (line = '') => { + publish(defaultCommandVcenter, { + resource: type, + data: line, + }) + } + + let pendingMessages = '' + const emit = (message) => { + if (message && typeof message.toString === 'function') { + message + .toString() + .split(defaultRegexpSplitLine) + .forEach((line) => { + if (line) { + if ( + (defaultRegexpStartJSON.test(line) && + defaultRegexpEndJSON.test(line)) || + (!defaultRegexpStartJSON.test(line) && + !defaultRegexpEndJSON.test(line) && + pendingMessages.length === 0) + ) { + publisher(line) + } else if ( + (defaultRegexpStartJSON.test(line) && + !defaultRegexpEndJSON.test(line)) || + (!defaultRegexpStartJSON.test(line) && + !defaultRegexpEndJSON.test(line) && + pendingMessages.length > 0) + ) { + pendingMessages += line + } else { + publisher(pendingMessages + line) + pendingMessages = '' + } + } + }) + } + } + + const executeImport = (ref) => { + executeCommandAsync( + defaultCommandVcenter, + ['import_defaults', ref, '-o', type, ...flagsImport], + prependCommand, + { + err: (message) => emit(message), + out: (message) => emit(message), + close: defaultEmptyFunction, + } + ) + } + + const { id } = params + if (id) { + id.split(',').forEach((ref) => { + executeImport(ref) + }) + httpReturn(accepted) + + return + } + + let flagsList = [] + paramsForCommand + .filter((flag) => flag.for && flag.for.includes(LIST)) + .forEach(({ param, flag }) => { + if (params[param]) { + flagsList = [...flagsList, flag, params[param]] + } + }) + + const iterateListAll = (message) => { + if (message && typeof message.toString === 'function') { + const messageString = message.toString() + const listData = consoleParseToJSON( + consoleParseToString(messageString, regexExclude), + regexHeader + ) + + if (listData.length) { + listData.forEach(({ REF }) => { + if (!REF) { + return + } + executeImport(REF) + }) + } else { + publisher(messageString) + } + } + } + + executeCommandAsync( + defaultCommandVcenter, + ['list_all', '-o', type, '--csv', ...flagsList], + prependCommand, + { + err: iterateListAll, + out: iterateListAll, + close: defaultEmptyFunction, + } + ) + + httpReturn(accepted) +} + const functionRoutes = { - importVcenter, list, listAll, cleartags, - hosts, + importHost, + importVobject, } module.exports = functionRoutes diff --git a/src/fireedge/src/server/routes/api/vcenter/index.js b/src/fireedge/src/server/routes/api/vcenter/index.js index 08e6e96719..9dfa5f4034 100644 --- a/src/fireedge/src/server/routes/api/vcenter/index.js +++ b/src/fireedge/src/server/routes/api/vcenter/index.js @@ -16,36 +16,54 @@ const { Actions, Commands } = require('server/routes/api/vcenter/routes') const { - importVcenter, + importVobject, list, listAll, cleartags, - hosts, + importHost, } = require('server/routes/api/vcenter/functions') +const { resources } = require('server/routes/api/vcenter/command-flags') + +const { TEMPLATES, DATASTORES, NETWORKS, IMAGES } = resources const { - VCENTER_CLEARTAGS, - VCENTER_HOSTS, - VCENTER_IMPORT, - VCENTER_LISTALL, + VCENTER_CLEAR_TAGS, + VCENTER_IMPORT_HOSTS, + VCENTER_IMPORT_DATASTORES, + VCENTER_IMPORT_TEMPLATES, + VCENTER_IMPORT_NETWORKS, + VCENTER_IMPORT_IMAGES, + VCENTER_LIST_ALL, VCENTER_LIST, } = Actions module.exports = [ { - ...Commands[VCENTER_CLEARTAGS], + ...Commands[VCENTER_CLEAR_TAGS], action: cleartags, }, { - ...Commands[VCENTER_HOSTS], - action: hosts, + ...Commands[VCENTER_IMPORT_HOSTS], + action: importHost, }, { - ...Commands[VCENTER_IMPORT], - action: importVcenter, + ...Commands[VCENTER_IMPORT_DATASTORES], + action: (...args) => importVobject(...args, DATASTORES), }, { - ...Commands[VCENTER_LISTALL], + ...Commands[VCENTER_IMPORT_NETWORKS], + action: (...args) => importVobject(...args, NETWORKS), + }, + { + ...Commands[VCENTER_IMPORT_IMAGES], + action: (...args) => importVobject(...args, IMAGES), + }, + { + ...Commands[VCENTER_IMPORT_TEMPLATES], + action: (...args) => importVobject(...args, TEMPLATES), + }, + { + ...Commands[VCENTER_LIST_ALL], action: listAll, }, { diff --git a/src/fireedge/src/server/routes/api/vcenter/routes.js b/src/fireedge/src/server/routes/api/vcenter/routes.js index 59074a1469..0db36fc2ab 100644 --- a/src/fireedge/src/server/routes/api/vcenter/routes.js +++ b/src/fireedge/src/server/routes/api/vcenter/routes.js @@ -18,29 +18,34 @@ const { httpMethod, from: fromData, } = require('server/utils/constants/defaults') -const VCENTER = require('server/routes/api/vcenter/basepath') -const basepath = `/${VCENTER}` +const basepath = '/vcenter' const { POST, GET } = httpMethod const { resource, postBody, query } = fromData -const VCENTER_CLEARTAGS = 'vcenter.cleartags' -const VCENTER_HOSTS = 'vcenter.hosts' -const VCENTER_IMPORT = 'vcenter.import' -const VCENTER_LISTALL = 'vcenter.listall' +const VCENTER_CLEAR_TAGS = 'vcenter.cleartags' +const VCENTER_IMPORT_HOSTS = 'vcenter.importhosts' +const VCENTER_IMPORT_DATASTORES = 'vcenter.importdatastores' +const VCENTER_IMPORT_TEMPLATES = 'vcenter.importtemplates' +const VCENTER_IMPORT_NETWORKS = 'vcenter.importnetworks' +const VCENTER_IMPORT_IMAGES = 'vcenter.importimages' +const VCENTER_LIST_ALL = 'vcenter.listall' const VCENTER_LIST = 'vcenter.list' const Actions = { - VCENTER_CLEARTAGS, - VCENTER_HOSTS, - VCENTER_IMPORT, - VCENTER_LISTALL, + VCENTER_CLEAR_TAGS, + VCENTER_IMPORT_HOSTS, + VCENTER_IMPORT_TEMPLATES, + VCENTER_IMPORT_DATASTORES, + VCENTER_IMPORT_NETWORKS, + VCENTER_IMPORT_IMAGES, + VCENTER_LIST_ALL, VCENTER_LIST, } module.exports = { Actions, Commands: { - [VCENTER_CLEARTAGS]: { + [VCENTER_CLEAR_TAGS]: { path: `${basepath}/cleartags/:id`, httpMethod: POST, auth: true, @@ -50,31 +55,79 @@ module.exports = { }, }, }, - [VCENTER_HOSTS]: { - path: `${basepath}/hosts`, + [VCENTER_IMPORT_HOSTS]: { + path: `${basepath}/hosts/:id?`, httpMethod: POST, auth: true, params: { + id: { + from: resource, + }, vcenter: { from: postBody, - name: 'vcenter', }, user: { from: postBody, - name: 'user', }, pass: { from: postBody, - name: 'pass', }, }, }, - [VCENTER_IMPORT]: { - path: `${basepath}/:vobject`, + [VCENTER_IMPORT_DATASTORES]: { + path: `${basepath}/datastores/:id?`, httpMethod: POST, auth: true, params: { - vobject: { + id: { + from: resource, + }, + host: { + from: postBody, + }, + }, + }, + [VCENTER_IMPORT_TEMPLATES]: { + path: `${basepath}/templates/:id?`, + httpMethod: POST, + auth: true, + params: { + id: { + from: resource, + }, + datastore: { + from: postBody, + }, + host: { + from: postBody, + }, + folder: { + from: postBody, + }, + linked_clone: { + from: postBody, + }, + }, + }, + [VCENTER_IMPORT_NETWORKS]: { + path: `${basepath}/networks/:id?`, + httpMethod: POST, + auth: true, + params: { + id: { + from: resource, + }, + host: { + from: postBody, + }, + }, + }, + [VCENTER_IMPORT_IMAGES]: { + path: `${basepath}/images/:id?`, + httpMethod: POST, + auth: true, + params: { + id: { from: resource, }, host: { @@ -83,16 +136,10 @@ module.exports = { datastore: { from: postBody, }, - id: { - from: postBody, - }, - answers: { - from: postBody, - }, }, }, - [VCENTER_LISTALL]: { - path: `${basepath}/listall/:vobject`, + [VCENTER_LIST_ALL]: { + path: `${basepath}/listall/:vobject/:host`, httpMethod: GET, auth: true, params: { @@ -100,7 +147,7 @@ module.exports = { from: resource, }, host: { - from: query, + from: resource, }, datastore: { from: query, @@ -108,7 +155,7 @@ module.exports = { }, }, [VCENTER_LIST]: { - path: `${basepath}/:vobject`, + path: `${basepath}/:vobject/:host`, httpMethod: GET, auth: true, params: { @@ -116,7 +163,7 @@ module.exports = { from: resource, }, host: { - from: query, + from: resource, }, datastore: { from: query, diff --git a/src/fireedge/src/server/routes/entrypoints/Api/xmlrpc.js b/src/fireedge/src/server/routes/entrypoints/Api/xmlrpc.js index a5f7a8618d..f6f3dc9969 100644 --- a/src/fireedge/src/server/routes/entrypoints/Api/xmlrpc.js +++ b/src/fireedge/src/server/routes/entrypoints/Api/xmlrpc.js @@ -13,9 +13,6 @@ * See the License for the specific language governing permissions and * * limitations under the License. * * ------------------------------------------------------------------------- */ -const { resolve } = require('path') -const { env } = require('process') -const Worker = require('tiny-worker') const upcast = require('upcast') const { defaults, @@ -30,15 +27,15 @@ const { } = require('server/routes/entrypoints/Api/middlawares') const { fillResourceforHookConnection } = require('server/utils/opennebula') const { httpResponse, validateHttpMethod } = require('server/utils/server') +const { useWorker, parseReturnWorker } = require('server/utils/worker') const { writeInLogger } = require('server/utils/logger') const { - defaultWebpackMode, defaultEmptyFunction, defaultMessageInvalidZone, from: fromData, } = defaults -const { internalServerError, ok, notFound } = httpCodes +const { internalServerError } = httpCodes const { resource: fromResource, query, postBody } = fromData /** @@ -63,14 +60,7 @@ const executeWorker = ({ res, }) => { if (user && password && rpc && command && paramsCommand) { - let workerPath = [__dirname] - if (env && env.NODE_ENV === defaultWebpackMode) { - workerPath = ['src', 'server', 'utils'] - } else { - require('server/utils/index.worker') - } - const worker = new Worker(resolve(...workerPath, 'index.worker.js')) - + const worker = useWorker() worker.onmessage = function (result) { worker.terminate() const err = result && result.data && result.data.err @@ -78,34 +68,21 @@ const executeWorker = ({ writeInLogger([command, JSON.stringify(value)], 'worker: %s : %s') if (!err) { fillResourceforHookConnection(user, command, paramsCommand) - switch (typeof value) { - case 'string': - try { - res.locals.httpCode = httpResponse(ok, JSON.parse(value)) - } catch (error) { - res.locals.httpCode = httpResponse(notFound, value) - } - break - case 'object': - res.locals.httpCode = httpResponse(ok, value) - break - case 'number': - res.locals.httpCode = httpResponse(ok, value) - break - default: - break - } + res.locals.httpCode = parseReturnWorker(value) } next() } worker.postMessage({ - globalState: (global && global.paths) || {}, - user, - password, - rpc, - command, - paramsCommand, + type: 'xmlrpc', + config: { + globalState: (global && global.paths) || {}, + user, + password, + rpc, + command, + paramsCommand, + }, }) } } diff --git a/src/fireedge/src/server/routes/websockets/guacamole/index.js b/src/fireedge/src/server/routes/websockets/guacamole.js similarity index 98% rename from src/fireedge/src/server/routes/websockets/guacamole/index.js rename to src/fireedge/src/server/routes/websockets/guacamole.js index 3c6a72cf77..7d1417bd84 100644 --- a/src/fireedge/src/server/routes/websockets/guacamole/index.js +++ b/src/fireedge/src/server/routes/websockets/guacamole.js @@ -104,7 +104,4 @@ const guacamole = (appServer) => { } } -module.exports = { - endpointGuacamole, - guacamole, -} +module.exports = guacamole diff --git a/src/fireedge/src/server/routes/websockets/hooks/index.js b/src/fireedge/src/server/routes/websockets/opennebula/hooks.js similarity index 99% rename from src/fireedge/src/server/routes/websockets/hooks/index.js rename to src/fireedge/src/server/routes/websockets/opennebula/hooks.js index 0f28ec7cf9..060fe7b38f 100644 --- a/src/fireedge/src/server/routes/websockets/hooks/index.js +++ b/src/fireedge/src/server/routes/websockets/opennebula/hooks.js @@ -78,6 +78,4 @@ const main = (app = {}, type = '') => { } } -module.exports = { - main, -} +module.exports = main diff --git a/src/fireedge/src/server/routes/websockets/index.js b/src/fireedge/src/server/routes/websockets/opennebula/index.js similarity index 92% rename from src/fireedge/src/server/routes/websockets/index.js rename to src/fireedge/src/server/routes/websockets/opennebula/index.js index 35b85a63ee..9fb6ef4adb 100644 --- a/src/fireedge/src/server/routes/websockets/index.js +++ b/src/fireedge/src/server/routes/websockets/opennebula/index.js @@ -51,10 +51,10 @@ const websockets = (appServer = {}) => { }).listen(appServer) try { // eslint-disable-next-line global-require - const fileInfo = require(`./${filename}`) - if (fileInfo.main && typeof fileInfo.main === 'function') { + const file = require(`./${filename}`) + if (typeof file === 'function') { sockets.push(io) - fileInfo.main(io, filename) + file(io, filename) } } catch (error) { if (error instanceof Error) { @@ -72,6 +72,4 @@ const websockets = (appServer = {}) => { return sockets } -module.exports = { - websockets, -} +module.exports = websockets diff --git a/src/fireedge/src/server/routes/api/vcenter/basepath.js b/src/fireedge/src/server/routes/websockets/opennebula/provision.js similarity index 53% rename from src/fireedge/src/server/routes/api/vcenter/basepath.js rename to src/fireedge/src/server/routes/websockets/opennebula/provision.js index f993aa27bf..d49f709082 100644 --- a/src/fireedge/src/server/routes/api/vcenter/basepath.js +++ b/src/fireedge/src/server/routes/websockets/opennebula/provision.js @@ -14,4 +14,46 @@ * limitations under the License. * * ------------------------------------------------------------------------- */ -module.exports = 'vcenter' +const { + middlewareValidateAuthWebsocket, + subscriber, +} = require('server/utils/server') +const { messageTerminal } = require('server/utils/general') +const { defaults } = require('server/utils/constants') + +const { defaultCommandProvision } = defaults + +/** + * Object http error. + * + * @param {object} error - error message + * @returns {object} param of terminalMessage function + */ +const configErrorProvision = (error = '') => ({ + color: 'red', + error, + message: '%s', +}) + +/** + * Route of websocket Provisions. + * + * @param {object} app - express app + * @param {string} type - type WS + */ +const main = (app = {}, type = '') => { + try { + app.use(middlewareValidateAuthWebsocket).on('connection', (server = {}) => { + server.on('disconnect', () => { + messageTerminal(configErrorProvision('disconnect')) + }) + subscriber(defaultCommandProvision, (data) => { + app.emit(type, data) + }) + }) + } catch (error) { + messageTerminal(configErrorProvision(error)) + } +} + +module.exports = main diff --git a/src/fireedge/src/server/routes/websockets/provision/index.js b/src/fireedge/src/server/routes/websockets/opennebula/vcenter.js similarity index 88% rename from src/fireedge/src/server/routes/websockets/provision/index.js rename to src/fireedge/src/server/routes/websockets/opennebula/vcenter.js index 3ae8dfe16a..f9c0b04f0d 100644 --- a/src/fireedge/src/server/routes/websockets/provision/index.js +++ b/src/fireedge/src/server/routes/websockets/opennebula/vcenter.js @@ -14,9 +14,14 @@ * limitations under the License. * * ------------------------------------------------------------------------- */ -const { middlewareValidateAuthWebsocket } = require('server/utils/server') +const { + middlewareValidateAuthWebsocket, + subscriber, +} = require('server/utils/server') const { messageTerminal } = require('server/utils/general') -const { subscriber } = require('server/routes/api/oneprovision/utils') +const { defaults } = require('server/utils/constants') + +const { defaultCommandVcenter } = defaults /** * Object http error. @@ -42,7 +47,7 @@ const main = (app = {}, type = '') => { server.on('disconnect', () => { messageTerminal(configErrorProvision('disconnect')) }) - subscriber('oneprovision', (data) => { + subscriber(defaultCommandVcenter, (data) => { app.emit(type, data) }) }) @@ -51,6 +56,4 @@ const main = (app = {}, type = '') => { } } -module.exports = { - main, -} +module.exports = main diff --git a/src/fireedge/src/server/routes/websockets/vmrc/index.js b/src/fireedge/src/server/routes/websockets/vmrc.js similarity index 99% rename from src/fireedge/src/server/routes/websockets/vmrc/index.js rename to src/fireedge/src/server/routes/websockets/vmrc.js index 35bd253959..4bc8bd043e 100644 --- a/src/fireedge/src/server/routes/websockets/vmrc/index.js +++ b/src/fireedge/src/server/routes/websockets/vmrc.js @@ -86,6 +86,4 @@ const vmrc = (appServer) => { } } -module.exports = { - vmrc, -} +module.exports = vmrc diff --git a/src/fireedge/src/server/utils/constants/defaults.js b/src/fireedge/src/server/utils/constants/defaults.js index cf7868ee3f..afb6c361a5 100644 --- a/src/fireedge/src/server/utils/constants/defaults.js +++ b/src/fireedge/src/server/utils/constants/defaults.js @@ -52,6 +52,9 @@ const defaults = { defaultSessionExpiration: 180, defaultSessionLimitExpiration: 30, defaultRememberSessionExpiration: 43200, + defaultRegexpStartJSON: /^{/, + defaultRegexpEndJSON: /}$/, + defaultRegexpSplitLine: /\r|\n/, defaultAppName: appName, defaultConfigErrorMessage: { color: 'red', @@ -62,10 +65,14 @@ const defaults = { path: `${baseUrl}${baseUrlWebsockets}hooks`, methods: ['GET', 'POST'], }, - provision: { + [appNameProvision]: { path: `${baseUrl}${baseUrlWebsockets}${appNameProvision}`, methods: ['GET', 'POST'], }, + vcenter: { + path: `${baseUrl}${baseUrlWebsockets}vcenter`, + methods: ['GET', 'POST'], + }, }, defaultApps: apps, httpMethod: { @@ -102,8 +109,8 @@ const defaults = { parseAttributeValue: true, trimValues: true, }, - defaultCommandProvision: 'oneprovision', - defaultCommandProvisionTemplate: 'oneprovision-template', + defaultCommandProvision: `one${appNameProvision}`, + defaultCommandProvisionTemplate: `one${appNameProvision}-template`, defaultCommandProvider: 'oneprovider', defaultCommandVcenter: 'onevcenter', defaultCommandVM: 'onevm', diff --git a/src/fireedge/src/server/utils/index.worker.js b/src/fireedge/src/server/utils/index.worker.js index 3ecc991a55..e07cd96aae 100644 --- a/src/fireedge/src/server/utils/index.worker.js +++ b/src/fireedge/src/server/utils/index.worker.js @@ -18,16 +18,27 @@ const { opennebulaConnect } = require('../../../src/server/utils/opennebula') // eslint-disable-next-line no-undef onmessage = function (ev = {}) { + const { data } = ev let pass = true - const returnData = (data = '') => { + /** + * Return data worker. + * + * @param {any} rtnData - data for worker + */ + const returnDataWorker = (rtnData = '') => { if (pass) { // eslint-disable-next-line no-undef - postMessage(data) + postMessage(rtnData) } } - if (ev && ev.data) { + /** + * Function when the worker is XMLRPC. + * + * @param {object} config - config XMLRPC + */ + const xmlrpc = (config = {}) => { const { globalState = {}, user = '', @@ -35,16 +46,21 @@ onmessage = function (ev = {}) { rpc = '', command = '', paramsCommand = [], - } = ev.data + } = config if (globalState && user && password && rpc && command) { pass = false global.paths = globalState const connect = opennebulaConnect(user, password, rpc) connect(command, paramsCommand, (err, value) => { pass = true - returnData({ err, value }) + returnDataWorker({ err, value }) }) } } - returnData() + + if (data) { + const { type = '', config = '' } = data + type === 'xmlrpc' && xmlrpc(config) + } + returnDataWorker() } diff --git a/src/fireedge/src/server/utils/opennebula.js b/src/fireedge/src/server/utils/opennebula.js index eb4fe37dcf..ef5c2b3942 100644 --- a/src/fireedge/src/server/utils/opennebula.js +++ b/src/fireedge/src/server/utils/opennebula.js @@ -441,32 +441,30 @@ const generateNewResourceTemplate = ( * @returns {string} new console string */ const consoleParseToString = (stringConsole = '', excludeRegexs = []) => { - const rtn = [] - if (stringConsole) { - const lines = stringConsole.split(regexLine) - - lines.forEach((line) => { - let pass = true - - if (Array.isArray(excludeRegexs)) { - excludeRegexs.forEach((rex) => { - if (rex.test(line)) { - pass = false - } - }) - } - - const cleanLine = line - .replace(regexRemoveBlanks, ' ') - .replace(regexANSIColor, '') - .trim() - - if (cleanLine && pass) { - rtn.push(cleanLine) - } - }) + if (!stringConsole) { + return } + const rtn = [] + stringConsole.split(regexLine).forEach((line) => { + let pass = true + if (Array.isArray(excludeRegexs)) { + excludeRegexs.forEach((rex) => { + if (rex.test(line)) { + pass = false + } + }) + } + const cleanLine = line + .replace(regexRemoveBlanks, ' ') + .replace(regexANSIColor, '') + .trim() + + if (cleanLine && pass) { + rtn.push(cleanLine) + } + }) + return rtn } @@ -475,32 +473,35 @@ const consoleParseToString = (stringConsole = '', excludeRegexs = []) => { * * @param {Array} arrayConsole - result of consoleParseToString function * @param {string} regexHeader - regex for find header - * @returns {string} new console string + * @returns {any[]} console string JSON parsed */ const consoleParseToJSON = (arrayConsole = [], regexHeader = '') => { - let rtn = [] + const rtn = [] if ( - regexHeader && - Array.isArray(arrayConsole) && - arrayConsole[0] && - regexHeader.test(arrayConsole[0]) + !( + regexHeader && + Array.isArray(arrayConsole) && + arrayConsole[0] && + regexHeader.test(arrayConsole[0]) + ) ) { - const header = arrayConsole[0].split(',') - arrayConsole.forEach((row = '', i = 0) => { - if (row && i > 0) { - const explodeRow = CSVtoArray(row) - rtn.push( - explodeRow.map((value, index) => ({ - [header[index]]: stringWrappedBrakets.test(value) - ? CSVtoArray(value.replace(brakets, '')) - : value, - })) - ) - } - }) - } else { - rtn = arrayConsole + return rtn } + const header = arrayConsole[0].split(',') + arrayConsole.forEach((row = '', i = 0) => { + if (row && i > 0) { + const explodeRow = CSVtoArray(row) + if (Array.isArray(explodeRow)) { + const newLine = {} + explodeRow.forEach((value, index) => { + newLine[header[index]] = stringWrappedBrakets.test(value) + ? CSVtoArray(value.replace(brakets, '')) + : value + }) + rtn.push(newLine) + } + } + }) return rtn } diff --git a/src/fireedge/src/server/utils/server.js b/src/fireedge/src/server/utils/server.js index 1cddae2197..779df05322 100644 --- a/src/fireedge/src/server/utils/server.js +++ b/src/fireedge/src/server/utils/server.js @@ -35,11 +35,14 @@ const { statSync, removeSync, } = require('fs-extra') +const { spawnSync, spawn } = require('child_process') +const events = require('events') const { defaults, httpCodes } = require('server/utils/constants') const { messageTerminal } = require('server/utils/general') const { validateAuth } = require('server/utils/jwt') const { writeInLogger } = require('server/utils/logger') -const { spawnSync, spawn } = require('child_process') + +const eventsEmitter = new events.EventEmitter() const { httpMethod, defaultApps, @@ -162,18 +165,15 @@ const getQueryData = (server = {}) => { * Validate Authentication for websocket. * * @param {object} server - express app - * @returns {boolean} if token is valid + * @returns {undefined|boolean} if token is valid */ const validateAuthWebsocket = (server = {}) => { - let rtn const { token } = getQueryData(server) if (token) { - rtn = validateAuth({ + return validateAuth({ headers: { authorization: token }, }) } - - return rtn } /** @@ -387,7 +387,14 @@ const genFireedgeKey = () => { createFile( global.paths.FIREEDGE_KEY_PATH, uuidv4.replace(/-/g, ''), - () => undefined, + () => { + writeInLogger(`file ${global.paths.FIREEDGE_KEY_PATH} created`) + messageTerminal({ + color: 'green', + message: 'File %s created', + error: global.paths.FIREEDGE_KEY_PATH, + }) + }, (err) => { const errorData = (err && err.message) || '' writeInLogger(errorData) @@ -885,6 +892,37 @@ const executeCommandAsync = ( } } +/** + * Create a event emiter. + * + * @param {string} eventName - name event + * @param {object} message - object message + */ +const publish = (eventName = '', message = {}) => { + if (eventName && message) { + eventsEmitter.emit(eventName, message) + } +} + +/** + * Subscriber to event emitter. + * + * @param {string} eventName - event name + * @param {Function} callback - function executed when event is emited + */ +const subscriber = (eventName = '', callback = () => undefined) => { + if ( + eventName && + callback && + typeof callback === 'function' && + eventsEmitter.listenerCount(eventName) < 1 + ) { + eventsEmitter.on(eventName, (message) => { + callback(message) + }) + } +} + module.exports = { encrypt, decrypt, @@ -915,4 +953,6 @@ module.exports = { checkValidApp, removeFile, validateHttpMethod, + publish, + subscriber, } diff --git a/src/fireedge/src/server/utils/worker.js b/src/fireedge/src/server/utils/worker.js new file mode 100644 index 0000000000..b489f0008c --- /dev/null +++ b/src/fireedge/src/server/utils/worker.js @@ -0,0 +1,74 @@ +/* ------------------------------------------------------------------------- * + * Copyright 2002-2021, OpenNebula Project, OpenNebula Systems * + * * + * Licensed under the Apache License, Version 2.0 (the "License"); you may * + * not use this file except in compliance with the License. You may obtain * + * a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, software * + * distributed under the License is distributed on an "AS IS" BASIS, * + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * + * See the License for the specific language governing permissions and * + * limitations under the License. * + * ------------------------------------------------------------------------- */ + +const Worker = require('tiny-worker') +const { env } = require('process') +const { resolve } = require('path') + +const { httpResponse } = require('server/utils/server') +const { defaults, httpCodes } = require('server/utils/constants') + +const { internalServerError, ok, notFound } = httpCodes +const { defaultWebpackMode } = defaults + +/** + * Use Tiny worker. + * + * @returns {object} - Worker + */ +const useWorker = () => { + let workerPath = [__dirname] + if (env && env.NODE_ENV === defaultWebpackMode) { + workerPath = ['src', 'server', 'utils'] + } else { + require('server/utils/index.worker') + } + + return new Worker(resolve(...workerPath, 'index.worker.js')) +} + +/** + * Parse Return http worker. + * + * @param {any} value - data from worker. + * @returns {object} http response + */ +const parseReturnWorker = (value) => { + let rtn = httpResponse(internalServerError) + switch (typeof value) { + case 'string': + try { + rtn = httpResponse(ok, JSON.parse(value)) + } catch (error) { + rtn = httpResponse(notFound, value) + } + break + case 'object': + rtn = httpResponse(ok, value) + break + case 'number': + rtn = httpResponse(ok, value) + break + default: + break + } + + return rtn +} +module.exports = { + useWorker, + parseReturnWorker, +}