diff --git a/src/fireedge/src/client/components/DebugLog/utils.js b/src/fireedge/src/client/components/DebugLog/utils.js
index 67aef56cef..33873a5c1b 100644
--- a/src/fireedge/src/client/components/DebugLog/utils.js
+++ b/src/fireedge/src/client/components/DebugLog/utils.js
@@ -64,10 +64,15 @@ export const concatNewMessageToLog = (log, message = {}) => {
const { data, command, commandId } = message
- return {
- ...log,
- [command]: {
+ if (log?.[command]?.[commandId] !== undefined) {
+ log[command][commandId]?.push(data)
+ } else if (log?.[command] !== undefined) {
+ log[command][commandId] = [data]
+ } else {
+ log[command] = {
[commandId]: [...(log?.[command]?.[commandId] ?? []), data],
- },
+ }
}
+
+ return { ...log }
}
diff --git a/src/fireedge/src/client/containers/Providers/Create.js b/src/fireedge/src/client/containers/Providers/Create.js
index d1fd2d0934..37535f183d 100644
--- a/src/fireedge/src/client/containers/Providers/Create.js
+++ b/src/fireedge/src/client/containers/Providers/Create.js
@@ -49,7 +49,10 @@ function ProviderCreateForm() {
const { enqueueSuccess, enqueueError } = useGeneralApi()
const [createProvider] = useCreateProviderMutation()
- const [updateProvider] = useUpdateProviderMutation()
+ const [
+ updateProvider,
+ { isSuccess: successUpdate, originalArgs: { id: updatedProviderId } = {} },
+ ] = useUpdateProviderMutation()
const { data: providerConfig, error: errorConfig } =
useGetProviderConfigQuery(undefined, { refetchOnMountOrArgChange: false })
@@ -71,7 +74,6 @@ function ProviderCreateForm() {
if (id !== undefined) {
await updateProvider({ id, data: submitData })
- enqueueSuccess(`Provider updated - ID: ${id}`)
} else {
if (!isValidProviderTemplate(submitData, providerConfig)) {
enqueueError(
@@ -81,7 +83,7 @@ function ProviderCreateForm() {
}
const responseId = await createProvider({ data: submitData }).unwrap()
- enqueueSuccess(`Provider created - ID: ${responseId}`)
+ responseId && enqueueSuccess(`Provider created - ID: ${responseId}`)
}
history.push(PATH.PROVIDERS.LIST)
@@ -93,6 +95,11 @@ function ProviderCreateForm() {
id && getConnection(id)
}, [])
+ useEffect(() => {
+ successUpdate &&
+ enqueueSuccess(`Provider updated - ID: ${updatedProviderId}`)
+ }, [successUpdate])
+
if (errorConfig || errorConnection || errorProvider) {
return
}
diff --git a/src/fireedge/src/client/containers/Providers/index.js b/src/fireedge/src/client/containers/Providers/index.js
index 7904518c7f..ebd3d75f97 100644
--- a/src/fireedge/src/client/containers/Providers/index.js
+++ b/src/fireedge/src/client/containers/Providers/index.js
@@ -49,8 +49,14 @@ function Providers() {
const { enqueueSuccess } = useGeneralApi()
const { data: providerConfig } = useGetProviderConfigQuery()
- const [deleteProvider, { isLoading: isDeleting }] =
- useDeleteProviderMutation()
+ const [
+ deleteProvider,
+ {
+ isLoading: isDeleting,
+ isSuccess: successDelete,
+ originalArgs: { id: deletedProviderId } = {},
+ },
+ ] = useDeleteProviderMutation()
const {
refetch,
@@ -68,10 +74,14 @@ function Providers() {
try {
hide()
await deleteProvider({ id })
- enqueueSuccess(`Provider deleted - ID: ${id}`)
} catch {}
}
+ useEffect(() => {
+ successDelete &&
+ enqueueSuccess(`Provider deleted - ID: ${deletedProviderId}`)
+ }, [successDelete])
+
return (
<>
{
const { enqueueSuccess } = useGeneralApi()
- const [removeResource, { isLoading: loadingRemove }] =
- useRemoveResourceMutation()
+ const [
+ removeResource,
+ {
+ isLoading: loadingRemove,
+ isSuccess: successRemove,
+ originalArgs: { id: deletedDatastoreId } = {},
+ },
+ ] = useRemoveResourceMutation()
const { data } = useGetProvisionQuery(id)
const provisionDatastores =
@@ -42,6 +48,11 @@ const Datastores = memo(
(datastore) => +datastore.id
) ?? []
+ useEffect(() => {
+ successRemove &&
+ enqueueSuccess(`Datastore deleted - ID: ${deletedDatastoreId}`)
+ }, [successRemove])
+
return (
}
diff --git a/src/fireedge/src/client/containers/Provisions/DialogInfo/hosts.js b/src/fireedge/src/client/containers/Provisions/DialogInfo/hosts.js
index 0a742d5905..edcb983406 100644
--- a/src/fireedge/src/client/containers/Provisions/DialogInfo/hosts.js
+++ b/src/fireedge/src/client/containers/Provisions/DialogInfo/hosts.js
@@ -40,7 +40,7 @@ import { T } from 'client/constants'
const Hosts = memo(({ id }) => {
const [amount, setAmount] = useState(() => 1)
- const { enqueueSuccess, enqueueInfo } = useGeneralApi()
+ const { enqueueInfo } = useGeneralApi()
const [addHost, { isLoading: loadingAddHost }] =
useAddHostToProvisionMutation()
@@ -77,7 +77,7 @@ const Hosts = memo(({ id }) => {
isSubmitting={loadingAddHost}
onClick={async () => {
addHost({ id, amount })
- enqueueSuccess(`Host added ${amount}x`)
+ enqueueInfo(`Adding ${amount} Host${amount > 1 ? 's' : ''}`)
}}
/>
@@ -125,7 +125,7 @@ const Hosts = memo(({ id }) => {
id: host.ID,
resource: 'host',
})
- enqueueSuccess(`Host deleted - ID: ${host.ID}`)
+ enqueueInfo(`Deleting Host - ID:${host.ID}`)
}}
/>
>
diff --git a/src/fireedge/src/client/features/OneApi/provision.js b/src/fireedge/src/client/features/OneApi/provision.js
index 7edfed8dc9..97be922b09 100644
--- a/src/fireedge/src/client/features/OneApi/provision.js
+++ b/src/fireedge/src/client/features/OneApi/provision.js
@@ -220,7 +220,7 @@ const provisionApi = oneApi.injectEndpoints({
* @returns {object} Object of document deleted
* @throws Fails when response isn't code 200
*/
- query: ({ provision: _, ...params }) => {
+ query: (params) => {
const name = Actions.PROVISION_DELETE_RESOURCE
const command = { name, ...Commands[name] }
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 f034442946..2f80955798 100644
--- a/src/fireedge/src/server/routes/api/oneprovision/provision/functions.js
+++ b/src/fireedge/src/server/routes/api/oneprovision/provision/functions.js
@@ -15,7 +15,6 @@
* ------------------------------------------------------------------------- */
const { parse } = require('yaml')
-const { v4 } = require('uuid')
const { Validator } = require('jsonschema')
const { createWriteStream } = require('fs-extra')
const { lockSync, checkSync, unlockSync } = require('lockfile')
@@ -24,7 +23,6 @@ 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,
@@ -33,7 +31,6 @@ const {
getDirectories,
getFilesbyEXT,
executeCommand,
- executeCommandAsync,
removeFile,
} = require('server/utils/server')
const { checkEmptyObject } = require('server/utils/general')
@@ -49,230 +46,37 @@ const {
getSpecificConfig,
} = require('server/routes/api/oneprovision/utils')
const { provision } = require('server/routes/api/oneprovision/schemas')
+const {
+ executeWithEmit,
+ logData,
+ addResourceSync,
+ relName,
+ ext,
+ logFile,
+ appendError,
+ executingMessage,
+} = require('server/routes/api/oneprovision/provision/helpers')
const {
defaultFolderTmpProvision,
defaultCommandProvision,
defaultEmptyFunction,
defaultErrorTemplate,
- defaultRegexpStartJSON,
- defaultRegexpEndJSON,
- defaultRegexpSplitLine,
defaultRegexID,
} = defaults
const { ok, notFound, accepted, internalServerError } = httpCodes
const httpInternalError = httpResponse(internalServerError, '', '')
-const logFile = {
- name: 'stdouterr',
- ext: 'log',
-}
const provisionFile = {
name: 'provision',
ext: 'yaml',
}
-const relName = 'provision-mapping'
-const ext = 'yml'
-const appendError = '.ERROR'
+const messageExecuting = 'Executing command:'
+
+const optionalParameters = ['--debug', '--json', '--batch']
/**
- * Execute command Async and emit in WS.
- *
- * @param {string} command - command to execute
- * @param {object} actions - external functions when command emit in stderr, stdout and finalize
- * @param {Function} actions.err - emit when have stderr
- * @param {Function} actions.out - emit when have stdout
- * @param {Function} actions.close - emit when finalize
- * @param {object} dataForLog - data
- * @param {number} dataForLog.id - data id
- * @param {string} dataForLog.command - data command
- * @returns {boolean} check if emmit data
- */
-const executeWithEmit = (command = [], actions = {}, dataForLog = {}) => {
- if (
- command &&
- Array.isArray(command) &&
- command.length > 0 &&
- actions &&
- dataForLog
- ) {
- const { err: externalErr, out: externalOut, close: externalClose } = actions
- const err =
- externalErr && typeof externalErr === 'function'
- ? externalErr
- : defaultEmptyFunction
- const out =
- externalOut && typeof externalOut === 'function'
- ? externalOut
- : defaultEmptyFunction
- const close =
- externalClose && typeof externalClose === 'function'
- ? actions.close
- : defaultEmptyFunction
-
- // data for log
- const id = (dataForLog && dataForLog.id) || ''
- const commandName = (dataForLog && dataForLog.command) || ''
-
- let lastLine = ''
- const uuid = v4()
-
- let pendingMessages = ''
-
- /**
- * Emit data of command.
- *
- * @param {string} message - line of command CLI
- * @param {Function} callback - function when recieve a information
- */
- const emit = (message, callback = defaultEmptyFunction) => {
- /**
- * Publisher data to WS.
- *
- * @param {string} line - command CLI line
- */
- const publisher = (line = '') => {
- const resposeData = callback(line, uuid) || {
- id,
- data: line,
- command: commandName,
- commandId: uuid,
- }
- publish(defaultCommandProvision, resposeData)
- }
-
- message
- .toString()
- .split(defaultRegexpSplitLine)
- .forEach((line) => {
- if (line) {
- if (
- (defaultRegexpStartJSON.test(line) &&
- defaultRegexpEndJSON.test(line)) ||
- (!defaultRegexpStartJSON.test(line) &&
- !defaultRegexpEndJSON.test(line) &&
- pendingMessages.length === 0)
- ) {
- lastLine = line
- publisher(lastLine)
- } else if (
- (defaultRegexpStartJSON.test(line) &&
- !defaultRegexpEndJSON.test(line)) ||
- (!defaultRegexpStartJSON.test(line) &&
- !defaultRegexpEndJSON.test(line) &&
- pendingMessages.length > 0)
- ) {
- pendingMessages += line
- } else {
- lastLine = pendingMessages + line
- publisher(lastLine)
- pendingMessages = ''
- }
- }
- })
- }
-
- executeCommandAsync(
- defaultCommandProvision,
- command,
- getSpecificConfig('oneprovision_prepend_command'),
- {
- err: (message) => {
- emit(message, err)
- },
- out: (message) => {
- emit(message, out)
- },
- close: (success) => {
- close(success, lastLine)
- },
- }
- )
-
- return true
- }
-}
-
-/**
- * Find log data.
- *
- * @param {string} id - id of provision
- * @param {boolean} fullPath - if need return the path of log
- * @returns {object} data of log
- */
-const logData = (id, fullPath = false) => {
- let rtn = false
- if (typeof id !== 'undefined') {
- const basePath = `${global.paths.CPI}/provision`
- const relFile = `${basePath}/${relName}`
- const relFileYML = `${relFile}.${ext}`
- const find = findRecursiveFolder(basePath, id)
-
- /**
- * Not found log.
- */
- const rtnNotFound = () => {
- rtn = false
- }
-
- /**
- * Found log.
- *
- * @param {string} path - path of log
- * @param {string} uuid - uuid of log
- */
- const rtnFound = (path = '', uuid) => {
- if (path) {
- const stringPath = `${path}/${logFile.name}.${logFile.ext}`
- existsFile(
- stringPath,
- (filedata) => {
- rtn = { uuid, log: filedata.split(defaultRegexpSplitLine) }
- if (fullPath) {
- rtn.fullPath = stringPath
- }
- },
- rtnNotFound
- )
- }
- }
-
- if (find) {
- rtnFound(find)
- } else {
- existsFile(
- relFileYML,
- (filedata) => {
- const fileData = parse(filedata) || {}
- if (fileData[id]) {
- const findPending = findRecursiveFolder(basePath, fileData[id])
- if (findPending) {
- rtnFound(findPending, fileData[id])
- } else {
- const findError = findRecursiveFolder(
- basePath,
- fileData[id] + appendError
- )
- if (findError) {
- rtnFound(findError, fileData[id])
- } else {
- rtnNotFound()
- }
- }
- } else {
- rtnNotFound()
- }
- },
- rtnNotFound
- )
- }
- }
-
- return rtn
-}
-
-/**
- * Get default provisions.
+ * Get default provisions (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -289,129 +93,129 @@ const getProvisionDefaults = (
) => {
const extFiles = 'yml'
const { user, password } = userData
- let rtn = httpInternalError
const files = {}
const path = `${global.paths.SHARE_CPI}`
-
const endpoint = getEndpoint()
- if (user && password) {
- const authCommand = ['--user', user, '--password', password]
- const directories = getDirectories(path)
- let description = ''
- let providers = {}
- let provisions = {}
- /**
- * Fill description of provision.
- *
- * @param {string} content - content of description provision
- */
- const fillDescription = (content = '') => {
- if (content) {
- description = content
- }
+ if (!(user && password)) {
+ res.locals.httpCode = httpInternalError
+ next()
+
+ return
+ }
+
+ const authCommand = ['--user', user, '--password', password]
+ const directories = getDirectories(path)
+ let description = ''
+ let providers = {}
+ let provisions = {}
+ /**
+ * Fill description of provision.
+ *
+ * @param {string} content - content of description provision
+ */
+ const fillDescription = (content = '') => {
+ if (content) {
+ description = content
}
- /**
- * Fill providers.
- *
- * @param {string} content - content of provider
- * @param {string} name - name of provider
- */
- const fillProviders = (content = '', name = '') => {
- if (content && name) {
- if (!providers[name]) {
- providers[name] = []
+ }
+ /**
+ * Fill providers.
+ *
+ * @param {string} content - content of provider
+ * @param {string} name - name of provider
+ */
+ const fillProviders = (content = '', name = '') => {
+ if (content && name) {
+ if (!providers[name]) {
+ providers[name] = []
+ }
+ try {
+ providers[name].push(parse(content))
+ } catch (error) {}
+ }
+ }
+ /**
+ * Fill provisions.
+ *
+ * @param {string} content - content of provision
+ * @param {string} filePath - path of provision yamls
+ * @param {string} pathCli - path for command
+ */
+ const fillProvisions = (content = '', filePath = '', pathCli = '') => {
+ if (content && filePath && path) {
+ const name = basename(filePath).replace(`.${extFiles}`, '')
+ const paramsCommand = [
+ 'validate',
+ '--dump',
+ filePath,
+ ...authCommand,
+ ...endpoint,
+ ]
+ const executedCommand = executeCommand(
+ defaultCommandProvision,
+ paramsCommand,
+ getSpecificConfig('oneprovision_prepend_command'),
+ { cwd: pathCli }
+ )
+ if (executedCommand && executedCommand.success) {
+ if (!provisions[name]) {
+ provisions[name] = []
}
try {
- providers[name].push(parse(content))
- } catch (error) {}
+ provisions[name].push(parse(executedCommand.data))
+ } catch (err) {}
}
}
- /**
- * Fill provisions.
- *
- * @param {string} content - content of provision
- * @param {string} filePath - path of provision yamls
- * @param {string} pathCli - path for command
- */
- const fillProvisions = (content = '', filePath = '', pathCli = '') => {
- if (content && filePath && path) {
- const name = basename(filePath).replace(`.${extFiles}`, '')
- const paramsCommand = [
- 'validate',
- '--dump',
- filePath,
- ...authCommand,
- ...endpoint,
- ]
- const executedCommand = executeCommand(
- defaultCommandProvision,
- paramsCommand,
- getSpecificConfig('oneprovision_prepend_command'),
- { cwd: pathCli }
- )
- if (executedCommand && executedCommand.success) {
- if (!provisions[name]) {
- provisions[name] = []
- }
- try {
- provisions[name].push(parse(executedCommand.data))
- } catch (err) {}
- }
- }
- }
-
- directories.forEach((directory = {}) => {
- if (directory.filename && directory.path) {
- // description
- existsFile(`${directory.path}/description.md`, fillDescription)
-
- // providers
- getDirectories(`${directory.path}/providers`).forEach(
- (provider = {}) => {
- if (provider.filename && provider.path) {
- getFilesbyEXT(provider.path, extFiles).forEach((file) => {
- existsFile(file, (content) =>
- fillProviders(content, provider.filename)
- )
- })
- }
- }
- )
-
- // provisions
- getFilesbyEXT(`${directory.path}/provisions`, extFiles).forEach(
- (file) => {
- existsFile(file, (content, filePath) =>
- fillProvisions(content, filePath, dirname(file))
- )
- }
- )
-
- if (
- description &&
- !checkEmptyObject(providers) &&
- !checkEmptyObject(provisions)
- ) {
- files[directory.filename] = {
- description,
- providers,
- provisions,
- }
- // clear
- description = ''
- providers = {}
- provisions = {}
- }
- }
- })
- rtn = httpResponse(ok, files)
}
- res.locals.httpCode = rtn
+
+ directories.forEach((directory = {}) => {
+ if (directory.filename && directory.path) {
+ // description
+ existsFile(`${directory.path}/description.md`, fillDescription)
+
+ // providers
+ getDirectories(`${directory.path}/providers`).forEach((provider = {}) => {
+ if (provider.filename && provider.path) {
+ getFilesbyEXT(provider.path, extFiles).forEach((file) => {
+ existsFile(file, (content) =>
+ fillProviders(content, provider.filename)
+ )
+ })
+ }
+ })
+
+ // provisions
+ getFilesbyEXT(`${directory.path}/provisions`, extFiles).forEach(
+ (file) => {
+ existsFile(file, (content, filePath) =>
+ fillProvisions(content, filePath, dirname(file))
+ )
+ }
+ )
+
+ if (
+ description &&
+ !checkEmptyObject(providers) &&
+ !checkEmptyObject(provisions)
+ ) {
+ files[directory.filename] = {
+ description,
+ providers,
+ provisions,
+ }
+ // clear
+ description = ''
+ providers = {}
+ provisions = {}
+ }
+ }
+ })
+ res.locals.httpCode = httpResponse(ok, files)
next()
}
/**
- * Get list for resource provisions.
+ * Get list for resource provisions (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -429,41 +233,46 @@ const getListResourceProvision = (
) => {
const { user, password } = userData
const { resource } = params
- let rtn = httpInternalError
- if (resource && user && password) {
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const paramsCommand = [
- `${resource}`.toLowerCase(),
- 'list',
- ...authCommand,
- ...endpoint,
- '--json',
- ]
- const executedCommand = executeCommand(
- defaultCommandProvision,
- paramsCommand,
- getSpecificConfig('oneprovision_prepend_command')
- )
- try {
- const response = executedCommand.success ? ok : internalServerError
- res.locals.httpCode = httpResponse(
- response,
- JSON.parse(executedCommand.data)
- )
- next()
+ if (!(resource && user && password)) {
+ res.locals.httpCode = httpInternalError
+ next()
- return
- } catch (error) {
- rtn = httpResponse(internalServerError, '', executedCommand.data)
- }
+ return
+ }
+
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const paramsCommand = [
+ `${resource}`.toLowerCase(),
+ 'list',
+ ...authCommand,
+ ...endpoint,
+ '--json',
+ ]
+ const executedCommand = executeCommand(
+ defaultCommandProvision,
+ paramsCommand,
+ getSpecificConfig('oneprovision_prepend_command')
+ )
+ try {
+ const response = executedCommand.success ? ok : internalServerError
+ res.locals.httpCode = httpResponse(
+ response,
+ JSON.parse(executedCommand.data)
+ )
+ next()
+ } catch (error) {
+ res.locals.httpCode = httpResponse(
+ internalServerError,
+ '',
+ executedCommand.data
+ )
+ next()
}
- res.locals.httpCode = rtn
- next()
}
/**
- * Get list provisions.
+ * Get list provisions (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -481,66 +290,64 @@ const getListProvisions = (
) => {
const { user, password } = userData
const { id } = params
- let rtn = httpInternalError
- if (user && password) {
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- let paramsCommand = ['list', ...authCommand, ...endpoint, '--json']
- if (Number.isInteger(parseInt(id, 10))) {
- paramsCommand = [
- 'show',
- `${id}`.toLowerCase(),
- ...authCommand,
- ...endpoint,
- '--json',
- ]
- }
- const executedCommand = executeCommand(
- defaultCommandProvision,
- paramsCommand,
- getSpecificConfig('oneprovision_prepend_command')
- )
- try {
- const response = executedCommand.success ? ok : internalServerError
- const data = JSON.parse(executedCommand.data)
-
- /**
- * Parse provision.TEMPLATE.BODY to JSON.
- *
- * @param {object} oneProvision - provision
- * @returns {object} provision with TEMPLATE.BODY in JSON
- */
- const parseTemplateBody = (oneProvision) => {
- if (
- oneProvision &&
- oneProvision.TEMPLATE &&
- oneProvision.TEMPLATE.BODY
- ) {
- oneProvision.TEMPLATE.BODY = JSON.parse(oneProvision.TEMPLATE.BODY)
- }
-
- return oneProvision
- }
-
- if (data && data.DOCUMENT_POOL && data.DOCUMENT_POOL.DOCUMENT) {
- data.DOCUMENT_POOL.DOCUMENT = Array.isArray(data.DOCUMENT_POOL.DOCUMENT)
- ? data.DOCUMENT_POOL.DOCUMENT.map(parseTemplateBody)
- : parseTemplateBody(data.DOCUMENT_POOL.DOCUMENT)
- }
- res.locals.httpCode = httpResponse(response, data)
- next()
-
- return
- } catch (error) {
- rtn = httpResponse(internalServerError, '', executedCommand.data)
- }
+ if (!(user && password)) {
+ res.locals.httpCode = httpInternalError
+ next()
+ }
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ let paramsCommand = ['list', ...authCommand, ...endpoint, '--json']
+ if (Number.isInteger(parseInt(id, 10))) {
+ paramsCommand = [
+ 'show',
+ `${id}`.toLowerCase(),
+ ...authCommand,
+ ...endpoint,
+ '--json',
+ ]
+ }
+ const executedCommand = executeCommand(
+ defaultCommandProvision,
+ paramsCommand,
+ getSpecificConfig('oneprovision_prepend_command')
+ )
+ try {
+ const response = executedCommand.success ? ok : internalServerError
+ const data = JSON.parse(executedCommand.data)
+
+ /**
+ * Parse provision.TEMPLATE.BODY to JSON.
+ *
+ * @param {object} oneProvision - provision
+ * @returns {object} provision with TEMPLATE.BODY in JSON
+ */
+ const parseTemplateBody = (oneProvision) => {
+ if (oneProvision?.TEMPLATE?.BODY) {
+ oneProvision.TEMPLATE.BODY = JSON.parse(oneProvision.TEMPLATE.BODY)
+ }
+
+ return oneProvision
+ }
+
+ if (data?.DOCUMENT_POOL?.DOCUMENT) {
+ data.DOCUMENT_POOL.DOCUMENT = Array.isArray(data.DOCUMENT_POOL.DOCUMENT)
+ ? data.DOCUMENT_POOL.DOCUMENT.map(parseTemplateBody)
+ : parseTemplateBody(data.DOCUMENT_POOL.DOCUMENT)
+ }
+ res.locals.httpCode = httpResponse(response, data)
+ next()
+ } catch (error) {
+ res.locals.httpCode = httpResponse(
+ internalServerError,
+ '',
+ executedCommand.data
+ )
+ next()
}
- res.locals.httpCode = rtn
- next()
}
/**
- * Delete resource provisions.
+ * Delete resource provisions (Async route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -558,39 +365,77 @@ const deleteResource = (
userData = {}
) => {
const { user, password } = userData
- const { resource, id } = params
- let rtn = httpInternalError
- if (resource && Number.isInteger(parseInt(id, 10)) && user && password) {
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const paramsCommand = [
- `${resource}`.toLowerCase(),
- 'delete',
- `${id}`.toLowerCase(),
- ...authCommand,
- ...endpoint,
- ]
- const executedCommand = executeCommand(
- defaultCommandProvision,
- paramsCommand,
- getSpecificConfig('oneprovision_prepend_command')
+ const { id, resource, provision: provisionId } = params
+ if (
+ !(
+ resource &&
+ Number.isInteger(parseInt(id, 10)) &&
+ Number.isInteger(parseInt(provisionId, 10)) &&
+ user &&
+ password
)
- try {
- const response = executedCommand.success ? ok : internalServerError
- rtn = httpResponse(
- response,
- executedCommand.data ? JSON.parse(executedCommand.data) : params.id
- )
- } catch (error) {
- rtn = httpResponse(internalServerError, '', executedCommand.data)
- }
+ ) {
+ res.locals.httpCode = httpInternalError
+ next()
+
+ return
}
- res.locals.httpCode = rtn
+
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const paramsCommand = [
+ `${resource}`.toLowerCase(),
+ 'delete',
+ `${id}`.toLowerCase(),
+ ...optionalParameters,
+ ...authCommand,
+ ...endpoint,
+ ]
+ const commandString = `${paramsCommand[0]} ${paramsCommand[1]}`
+ let flagSeparateLog = true
+ const dataLog = logData(provisionId, true)
+ const stream =
+ dataLog?.fullPath && createWriteStream(dataLog.fullPath, { flags: 'a' })
+ const emit = (lastLine, uuid) => {
+ const renderLine = {
+ id: provisionId,
+ data: lastLine,
+ command: commandString,
+ commandId: uuid,
+ }
+ if (flagSeparateLog) {
+ renderLine.data = executingMessage(`${messageExecuting} ${commandString}`)
+ stream?.write?.(`${JSON.stringify(renderLine)}\n`)
+ flagSeparateLog = false
+ renderLine.data = lastLine
+ }
+ stream?.write?.(`${JSON.stringify(renderLine)}\n`)
+
+ return renderLine
+ }
+
+ // execute Async Command
+ const executedCommand = executeWithEmit(
+ paramsCommand,
+ {
+ close: (success, lastLine) => {
+ stream?.end()
+ },
+ out: emit,
+ err: emit,
+ },
+ { id: provisionId, command: commandString }
+ )
+
+ res.locals.httpCode = httpResponse(
+ executedCommand ? accepted : internalServerError,
+ provisionId
+ )
next()
}
/**
- * Delete provision.
+ * Delete provision (Async route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -615,136 +460,126 @@ const deleteProvision = (
const relFileLOCK = `${relFile}.lock`
const { user, password } = userData
const { id, cleanup, force } = params
- const rtn = httpInternalError
- if (Number.isInteger(parseInt(id, 10)) && user && password) {
- const command = 'delete'
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const cleanUpTag = cleanup ? ['--cleanup'] : []
- const forceTag = force ? ['--force'] : []
- const paramsCommand = [
- command,
- id,
- '--batch',
- '--debug',
- '--json',
- ...cleanUpTag,
- ...forceTag,
- ...authCommand,
- ...endpoint,
- ]
-
- // get Log file
- const dataLog = logData(params.id, true)
-
- // create stream for write into file
- const stream =
- dataLog &&
- dataLog.fullPath &&
- createWriteStream(dataLog.fullPath, { flags: 'a' })
-
- /**
- * This function is performed for each command line response.
- *
- * @param {string} lastLine - last line command
- * @param {string} uuid - uuid commnand
- */
- const emit = (lastLine, uuid) => {
- const renderLine = {
- id: params.id,
- data: lastLine,
- command: command,
- commandId: uuid,
- }
- stream && stream.write && stream.write(`${JSON.stringify(renderLine)}\n`)
- }
-
- /**
- * This function is only executed if the command is completed.
- *
- * @param {boolean} success - check in command complete succefully
- * @param {string} lastLine - last line command
- */
- const close = (success, lastLine) => {
- if (success) {
- stream && stream.end && stream.end()
- existsFile(relFileYML, (filedata) => {
- let uuid = ''
- if (!checkSync(relFileLOCK)) {
- lockSync(relFileLOCK)
- const fileData = parse(filedata) || {}
- if (fileData[params.id]) {
- uuid = fileData[params.id]
- delete fileData[params.id]
- createTemporalFile(
- basePath,
- ext,
- createYMLContent(
- Object.keys(fileData).length !== 0 &&
- fileData.constructor === Object &&
- fileData
- ),
- relName
- )
- }
- unlockSync(relFileLOCK)
- if (uuid) {
- // provisions in deploy
- const provisionFolder = findRecursiveFolder(
- `${global.paths.CPI}/provision`,
- uuid
- )
- provisionFolder && removeFile(provisionFolder)
- // provisions in error
- const findFolderERROR = findRecursiveFolder(
- `${global.paths.CPI}/provision`,
- uuid + appendError
- )
- findFolderERROR && removeFile(findFolderERROR)
- }
- }
- })
- const findFolder = findRecursiveFolder(
- `${global.paths.CPI}/provision`,
- params.id
- )
- findFolder && removeFile(findFolder)
- } else {
- const oneConnect = oneConnection(user, password)
- oneConnect({
- action: Actions.DOCUMENT_UPDATE,
- parameters: [
- parseInt(params.id, 10),
- sprintf(defaultErrorTemplate, lastLine),
- 1,
- ],
- callback: defaultEmptyFunction,
- })
- }
- }
-
- // execute Async Command
- const executedCommand = executeWithEmit(
- paramsCommand,
- { close, out: emit, err: emit },
- { id: params.id, command }
- )
-
- // response Http
- res.locals.httpCode = httpResponse(
- executedCommand ? accepted : internalServerError,
- params.id
- )
+ if (!(Number.isInteger(parseInt(id, 10)) && user && password)) {
+ res.locals.httpCode = httpInternalError
next()
return
}
- res.locals.httpCode = rtn
+
+ const command = 'delete'
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const cleanUpTag = cleanup ? ['--cleanup'] : []
+ const forceTag = force ? ['--force'] : []
+ const paramsCommand = [
+ command,
+ id,
+ ...optionalParameters,
+ ...cleanUpTag,
+ ...forceTag,
+ ...authCommand,
+ ...endpoint,
+ ]
+
+ const dataLog = logData(params.id, true) // get Log file
+ const stream =
+ dataLog?.fullPath && createWriteStream(dataLog.fullPath, { flags: 'a' })
+
+ const emit = (lastLine, uuid) => {
+ const renderLine = {
+ id: params.id,
+ data: lastLine,
+ command: command,
+ commandId: uuid,
+ }
+
+ stream?.write?.(`${JSON.stringify(renderLine)}\n`)
+
+ return renderLine
+ }
+
+ /**
+ * This function is only executed if the command is completed.
+ *
+ * @param {boolean} success - check in command complete succefully
+ * @param {string} lastLine - last line command
+ */
+ const close = (success, lastLine) => {
+ if (success) {
+ stream?.end?.()
+ existsFile(relFileYML, (filedata) => {
+ let uuid = ''
+ if (!checkSync(relFileLOCK)) {
+ lockSync(relFileLOCK)
+ const fileData = parse(filedata) || {}
+ if (fileData[params.id]) {
+ uuid = fileData[params.id]
+ delete fileData[params.id]
+ createTemporalFile(
+ basePath,
+ ext,
+ createYMLContent(
+ Object.keys(fileData).length !== 0 &&
+ fileData.constructor === Object &&
+ fileData
+ ),
+ relName
+ )
+ }
+ unlockSync(relFileLOCK)
+ if (uuid) {
+ // provisions in deploy
+ const provisionFolder = findRecursiveFolder(
+ `${global.paths.CPI}/provision`,
+ uuid
+ )
+ provisionFolder && removeFile(provisionFolder)
+ // provisions in error
+ const findFolderERROR = findRecursiveFolder(
+ `${global.paths.CPI}/provision`,
+ uuid + appendError
+ )
+ findFolderERROR && removeFile(findFolderERROR)
+ }
+ }
+ })
+ const findFolder = findRecursiveFolder(
+ `${global.paths.CPI}/provision`,
+ params.id
+ )
+ findFolder && removeFile(findFolder)
+ } else {
+ const oneConnect = oneConnection(user, password)
+ oneConnect({
+ action: Actions.DOCUMENT_UPDATE,
+ parameters: [
+ parseInt(params.id, 10),
+ sprintf(defaultErrorTemplate, lastLine),
+ 1,
+ ],
+ callback: defaultEmptyFunction,
+ })
+ }
+ }
+
+ // execute Async Command
+ const executedCommand = executeWithEmit(
+ paramsCommand,
+ { close, out: emit, err: emit },
+ { id: params.id, command }
+ )
+
+ // response Http
+ res.locals.httpCode = httpResponse(
+ executedCommand ? accepted : internalServerError,
+ params.id
+ )
next()
}
/**
- * Execute command of host into provision.
+ * Execute command of host into provision (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -763,41 +598,46 @@ const hostCommand = (
) => {
const { user, password } = userData
const { action, id } = params
- let rtn = httpInternalError
- if (action && Number.isInteger(parseInt(id, 10)) && user && password) {
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const paramsCommand = [
- 'host',
- `${action}`.toLowerCase(),
- `${id}`.toLowerCase(),
- ...authCommand,
- ...endpoint,
- ]
- const executedCommand = executeCommand(
- defaultCommandProvision,
- paramsCommand,
- getSpecificConfig('oneprovision_prepend_command')
- )
- try {
- const response = executedCommand.success ? ok : internalServerError
- res.locals.httpCode = httpResponse(
- response,
- executedCommand.data ? JSON.parse(executedCommand.data) : id
- )
- next()
+ if (!(action && Number.isInteger(parseInt(id, 10)) && user && password)) {
+ res.locals.httpCode = httpInternalError
+ next()
- return
- } catch (error) {
- rtn = httpResponse(internalServerError, '', executedCommand.data)
- }
+ return
+ }
+
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const paramsCommand = [
+ 'host',
+ `${action}`.toLowerCase(),
+ `${id}`.toLowerCase(),
+ ...authCommand,
+ ...endpoint,
+ ]
+ const executedCommand = executeCommand(
+ defaultCommandProvision,
+ paramsCommand,
+ getSpecificConfig('oneprovision_prepend_command')
+ )
+ try {
+ const response = executedCommand.success ? ok : internalServerError
+ res.locals.httpCode = httpResponse(
+ response,
+ executedCommand.data ? JSON.parse(executedCommand.data) : id
+ )
+ next()
+ } catch (error) {
+ res.locals.httpCode = httpResponse(
+ internalServerError,
+ '',
+ executedCommand.data
+ )
+ next()
}
- res.locals.httpCode = rtn
- next()
}
/**
- * Create a provision.
+ * Create a provision (Async route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -820,179 +660,177 @@ const createProvision = (
const relFileLOCK = `${relFile}.lock`
const { user, password, id } = userData
const { data } = params
- const rtn = httpInternalError
- if (data && user && password) {
- const optionalCommand = addOptionalCreateCommand()
- const content = createYMLContent(parsePostData(data))
+ const optionalCommand = addOptionalCreateCommand()
+ const content = createYMLContent(parsePostData(data))
- if (content) {
- const command = 'create'
- const authCommand = ['--user', user, '--password', password]
- const endpoint = getEndpoint()
- const files = createFolderWithFiles(
- `${global.paths.CPI}/provision/${id}/tmp`,
- [
- { name: logFile.name, ext: logFile.ext },
- { name: provisionFile.name, ext: provisionFile.ext, content },
- ]
- )
- if (files && files.name && files.files) {
- /**
- * Find file in created files.
- *
- * @param {string} val - filename
- * @param {string} extension - file extension
- * @param {Array} arr - array of files
- * @returns {Array} path file
- */
- const find = (val = '', extension = '', arr = files.files) =>
- arr.find(
- (e) =>
- e &&
- e.path &&
- e.ext &&
- e.name &&
- e.name === val &&
- e.ext === extension
- )
+ const responseInternalError = () => {
+ res.locals.httpCode = httpInternalError
+ next()
+ }
+ if (!(data && user && password) || !content) {
+ responseInternalError()
- const config = find(provisionFile.name, provisionFile.ext)
- const log = find(logFile.name, logFile.ext)
- if (config && log) {
- /**
- * Create provision.
- *
- * @param {string} filedata - provision data
- */
- const create = (filedata = '') => {
- const paramsCommand = [
- command,
- config.path,
- '--batch',
- '--debug',
- '--json',
- ...optionalCommand,
- ...authCommand,
- ...endpoint,
- ]
+ return
+ }
- // stream file log
- const stream = createWriteStream(log.path, { flags: 'a' })
+ const command = 'create'
+ const authCommand = ['--user', user, '--password', password]
+ const endpoint = getEndpoint()
+ const files = createFolderWithFiles(
+ `${global.paths.CPI}/provision/${id}/tmp`,
+ [
+ { name: logFile.name, ext: logFile.ext },
+ { name: provisionFile.name, ext: provisionFile.ext, content },
+ ]
+ )
+ if (!(files.name && files.files)) {
+ responseInternalError()
- /**
- * This function is performed for each command line response.
- *
- * @param {string} lastLine - last line command
- * @param {string} uuid - UUID command
- * @returns {object} string line of command
- */
- const emit = (lastLine, uuid) => {
- if (lastLine && uuid) {
- if (defaultRegexID.test(lastLine) && !checkSync(relFileLOCK)) {
- const fileData = parse(filedata) || {}
- const parseID = lastLine.match('\\d+')
- const idResource = parseID[0]
- if (idResource && !fileData[idResource]) {
- lockSync(relFileLOCK)
- fileData[idResource] = files.name
- createTemporalFile(
- basePath,
- ext,
- createYMLContent(fileData),
- relName
- )
- unlockSync(relFileLOCK)
- }
- }
- const renderLine = {
- id: files.name,
- data: lastLine,
- command: command,
- commandId: uuid,
- }
- stream.write(`${JSON.stringify(renderLine)}\n`)
+ return
+ }
- return renderLine
- }
- }
+ /**
+ * Find file in created files.
+ *
+ * @param {string} val - filename
+ * @param {string} extension - file extension
+ * @param {Array} arr - array of files
+ * @returns {Array} path file
+ */
+ const find = (val = '', extension = '', arr = files.files) =>
+ arr.find(
+ (e) =>
+ e && e.path && e.ext && e.name && e.name === val && e.ext === extension
+ )
- /**
- * This function is only executed if the command is completed.
- *
- * @param {boolean} success - check if command finish successfully
- * @param {string} lastLine - last line command finish
- */
- const close = (success, lastLine) => {
- stream.end()
- if (success && defaultRegexID.test(lastLine)) {
- const newPath = renameFolder(
- config.path,
- lastLine.match('\\d+'),
- 'replace'
- )
- if (newPath) {
- existsFile(relFileYML, (file) => {
- if (!checkSync(relFileLOCK)) {
- lockSync(relFileLOCK)
- const fileData = parse(file) || {}
- const findKey = Object.keys(fileData).find(
- (key) => fileData[key] === files.name
- )
- if (findKey) {
- delete fileData[findKey]
- createTemporalFile(
- basePath,
- ext,
- createYMLContent(
- Object.keys(fileData).length !== 0 &&
- fileData.constructor === Object &&
- fileData
- ),
- relName
- )
- }
- unlockSync(relFileLOCK)
- }
- })
- moveToFolder(newPath, '/../../../')
- }
- }
- if (success === false) {
- renameFolder(config.path, appendError, 'append')
- }
- }
- executeWithEmit(
- paramsCommand,
- { close, out: emit, err: emit },
- { command }
+ const config = find(provisionFile.name, provisionFile.ext)
+ const log = find(logFile.name, logFile.ext)
+ if (!(config && log)) {
+ responseInternalError()
+
+ return
+ }
+
+ /**
+ * Create provision.
+ *
+ * @param {string} filedata - provision data
+ */
+ const create = (filedata = '') => {
+ const paramsCommand = [
+ command,
+ config.path,
+ ...optionalParameters,
+ ...optionalCommand,
+ ...authCommand,
+ ...endpoint,
+ ]
+
+ // stream file log
+ const stream = createWriteStream(log.path, { flags: 'a' })
+
+ /**
+ * This function is performed for each command line response.
+ *
+ * @param {string} lastLine - last line command
+ * @param {string} uuid - UUID command
+ * @returns {object} string line of command
+ */
+ const emit = (lastLine, uuid) => {
+ if (lastLine && uuid) {
+ if (defaultRegexID.test(lastLine) && !checkSync(relFileLOCK)) {
+ const fileData = parse(filedata) || {}
+ const parseID = lastLine.match('\\d+')
+ const idResource = parseID[0]
+ if (idResource && !fileData[idResource]) {
+ lockSync(relFileLOCK)
+ fileData[idResource] = files.name
+ createTemporalFile(
+ basePath,
+ ext,
+ createYMLContent(fileData),
+ relName
)
+ unlockSync(relFileLOCK)
}
-
- existsFile(
- relFileYML,
- (filedata) => {
- create(filedata)
- },
- () => {
- createFile(relFileYML, '', (filedata) => {
- create(filedata)
- })
- }
- )
- res.locals.httpCode = httpResponse(accepted, files.name)
- next()
-
- return
}
+ const renderLine = {
+ id: files.name,
+ data: lastLine,
+ command: command,
+ commandId: uuid,
+ }
+ stream.write(`${JSON.stringify(renderLine)}\n`)
+
+ return renderLine
}
}
+
+ /**
+ * This function is only executed if the command is completed.
+ *
+ * @param {boolean} success - check if command finish successfully
+ * @param {string} lastLine - last line command finish
+ */
+ const close = (success, lastLine) => {
+ stream.end()
+ if (success && defaultRegexID.test(lastLine)) {
+ const newPath = renameFolder(
+ config.path,
+ lastLine.match('\\d+'),
+ 'replace'
+ )
+ if (newPath) {
+ existsFile(relFileYML, (file) => {
+ if (!checkSync(relFileLOCK)) {
+ lockSync(relFileLOCK)
+ const fileData = parse(file) || {}
+ const findKey = Object.keys(fileData).find(
+ (key) => fileData[key] === files.name
+ )
+ if (findKey) {
+ delete fileData[findKey]
+ createTemporalFile(
+ basePath,
+ ext,
+ createYMLContent(
+ Object.keys(fileData).length !== 0 &&
+ fileData.constructor === Object &&
+ fileData
+ ),
+ relName
+ )
+ }
+ unlockSync(relFileLOCK)
+ }
+ })
+ moveToFolder(newPath, '/../../../')
+ }
+ }
+ if (success === false) {
+ renameFolder(config.path, appendError, 'append')
+ }
+ }
+ executeWithEmit(paramsCommand, { close, out: emit, err: emit }, { command })
}
- res.locals.httpCode = rtn
+
+ existsFile(
+ relFileYML,
+ (filedata) => {
+ create(filedata)
+ },
+ () => {
+ createFile(relFileYML, '', (filedata) => {
+ create(filedata)
+ })
+ }
+ )
+ res.locals.httpCode = httpResponse(accepted, files.name)
next()
}
/**
- * Configure provision.
+ * Configure provision (Async route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -1011,79 +849,73 @@ const configureProvision = (
const { user, password } = userData
const { id } = params
const rtn = httpInternalError
- if (Number.isInteger(parseInt(id, 10)) && user && password) {
- const command = 'configure'
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const paramsCommand = [
- command,
- id,
- '--debug',
- '--json',
- '--fail_cleanup',
- '--batch',
- '--force',
- ...authCommand,
- ...endpoint,
- ]
- // get Log file
- const dataLog = logData(id, true)
-
- // create stream for write into file
- const stream =
- dataLog &&
- dataLog.fullPath &&
- createWriteStream(dataLog.fullPath, { flags: 'a' })
-
- /**
- * This function is performed for each command line response.
- *
- * @param {string} lastLine - last line command
- * @param {string} uuid - UUID command
- */
- const emit = (lastLine, uuid) => {
- const renderLine = {
- id,
- data: lastLine,
- command: command,
- commandId: uuid,
- }
- stream && stream.write && stream.write(`${JSON.stringify(renderLine)}\n`)
- }
-
- /**
- * This function is only executed if the command is completed.
- *
- * @param {boolean} success - check if command complete without errors
- * @param {string} lastLine - last line command
- */
- const close = (success, lastLine) => {
- stream && stream.end && stream.end()
- }
-
- // execute Async Command
- const executedCommand = executeWithEmit(
- paramsCommand,
- { close, out: emit, err: emit },
- { id, command }
- )
-
- // response Http
- res.locals.httpCode = httpResponse(
- executedCommand ? accepted : internalServerError,
- id
- )
+ if (!(Number.isInteger(parseInt(id, 10)) && user && password)) {
+ res.locals.httpCode = rtn
next()
return
}
- res.locals.httpCode = rtn
+
+ const command = 'configure'
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const paramsCommand = [
+ command,
+ id,
+ '--fail_cleanup',
+ '--force',
+ ...optionalParameters,
+ ...authCommand,
+ ...endpoint,
+ ]
+
+ // get Log file
+ const dataLog = logData(id, true)
+
+ // create stream for write into file
+ const stream =
+ dataLog?.fullPath && createWriteStream(dataLog.fullPath, { flags: 'a' })
+
+ const emit = (lastLine, uuid) => {
+ const renderLine = {
+ id,
+ data: lastLine,
+ command: command,
+ commandId: uuid,
+ }
+ stream?.write?.(`${JSON.stringify(renderLine)}\n`)
+
+ return renderLine
+ }
+
+ /**
+ * This function is only executed if the command is completed.
+ *
+ * @param {boolean} success - check if command complete without errors
+ * @param {string} lastLine - last line command
+ */
+ const close = (success, lastLine) => {
+ stream?.end?.()
+ }
+
+ // execute Async Command
+ const executedCommand = executeWithEmit(
+ paramsCommand,
+ { close, out: emit, err: emit },
+ { id, command }
+ )
+
+ // response Http
+ res.locals.httpCode = httpResponse(
+ executedCommand ? accepted : internalServerError,
+ id
+ )
next()
}
/**
- * Configure host provision.
+ * Configure host provision (Async route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -1101,79 +933,73 @@ const configureHost = (
) => {
const { user, password } = userData
const { id } = params
- const rtn = httpInternalError
- if (Number.isInteger(parseInt(id, 10)) && user && password) {
- const command = 'configure'
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const paramsCommand = [
- 'host',
- command,
- `${id}`.toLowerCase(),
- '--debug',
- '--fail_cleanup',
- '--batch',
- ...authCommand,
- ...endpoint,
- ]
-
- // get Log file
- const dataLog = logData(id, true)
-
- // create stream for write into file
- const stream =
- dataLog &&
- dataLog.fullPath &&
- createWriteStream(dataLog.fullPath, { flags: 'a' })
-
- /**
- * This function is performed for each command line response.
- *
- * @param {string} lastLine - last line command
- * @param {string} uuid - uuid command
- */
- const emit = (lastLine, uuid) => {
- const renderLine = {
- id,
- data: lastLine,
- command: `host ${command}`,
- commandId: uuid,
- }
- stream && stream.write && stream.write(`${JSON.stringify(renderLine)}\n`)
- }
-
- /**
- * This function is only executed if the command is completed.
- *
- * @param {boolean} success - check if command complete without error
- * @param {string} lastLine - last line command
- */
- const close = (success, lastLine) => {
- stream && stream.end && stream.end()
- }
-
- // execute Async Command
- const executedCommand = executeWithEmit(
- paramsCommand,
- { close, out: emit, err: emit },
- { id, command: `host ${command}` }
- )
-
- // response Http
- res.locals.httpCode = httpResponse(
- executedCommand ? accepted : internalServerError,
- id
- )
+ if (!(Number.isInteger(parseInt(id, 10)) && user && password)) {
+ res.locals.httpCode = httpInternalError
next()
return
}
- res.locals.httpCode = rtn
+
+ const command = 'configure'
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const paramsCommand = [
+ 'host',
+ command,
+ `${id}`.toLowerCase(),
+ '--debug',
+ '--fail_cleanup',
+ '--batch',
+ ...authCommand,
+ ...endpoint,
+ ]
+
+ // get Log file
+ const dataLog = logData(id, true)
+
+ // create stream for write into file
+ const stream =
+ dataLog?.fullPath && createWriteStream(dataLog.fullPath, { flags: 'a' })
+
+ const emit = (lastLine, uuid) => {
+ const renderLine = {
+ id,
+ data: lastLine,
+ command: `host ${command}`,
+ commandId: uuid,
+ }
+ stream && stream.write && stream.write(`${JSON.stringify(renderLine)}\n`)
+
+ return renderLine
+ }
+
+ /**
+ * This function is only executed if the command is completed.
+ *
+ * @param {boolean} success - check if command complete without error
+ * @param {string} lastLine - last line command
+ */
+ const close = (success, lastLine) => {
+ stream?.end?.()
+ }
+
+ // execute Async Command
+ const executedCommand = executeWithEmit(
+ paramsCommand,
+ { close, out: emit, err: emit },
+ { id, command: `host ${command}` }
+ )
+
+ // response Http
+ res.locals.httpCode = httpResponse(
+ executedCommand ? accepted : internalServerError,
+ id
+ )
next()
}
/**
- * Validate provision file.
+ * Validate provision file (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -1189,61 +1015,67 @@ const validate = (
) => {
const { user, password } = userData
const { resource } = params
- let rtn = httpInternalError
- if (resource && user && password) {
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const schemaValidator = new Validator()
- const parsedResource = parsePostData(resource)
- const valSchema = schemaValidator.validate(parsedResource, provision)
- if (valSchema.valid) {
- const content = createYMLContent(parsedResource)
- if (content) {
- const file = createTemporalFile(
- `${global.paths.CPI}/${defaultFolderTmpProvision}`,
- 'yaml',
- content
- )
- if (file && file.name && file.path) {
- const paramsCommand = [
- 'validate',
- '--dump',
- file.path,
- ...authCommand,
- ...endpoint,
- ]
- const executedCommand = executeCommand(
- defaultCommandProvision,
- paramsCommand,
- getSpecificConfig('oneprovision_prepend_command')
- )
- let response = internalServerError
- if (executedCommand && executedCommand.success) {
- response = ok
- }
- removeFile(file)
- res.locals.httpCode = httpResponse(response)
- next()
+ const rtn = httpInternalError
+ if (!(resource && user && password)) {
+ res.locals.httpCode = rtn
+ next()
- return
+ return
+ }
+
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const schemaValidator = new Validator()
+ const parsedResource = parsePostData(resource)
+ const valSchema = schemaValidator.validate(parsedResource, provision)
+ if (valSchema?.valid) {
+ const content = createYMLContent(parsedResource)
+ if (content) {
+ const file = createTemporalFile(
+ `${global.paths.CPI}/${defaultFolderTmpProvision}`,
+ 'yaml',
+ content
+ )
+ if (file?.name && file?.path) {
+ const paramsCommand = [
+ 'validate',
+ '--dump',
+ file.path,
+ ...authCommand,
+ ...endpoint,
+ ]
+ const executedCommand = executeCommand(
+ defaultCommandProvision,
+ paramsCommand,
+ getSpecificConfig('oneprovision_prepend_command')
+ )
+ let response = internalServerError
+ if (executedCommand && executedCommand.success) {
+ response = ok
}
- }
- } else {
- const errors = []
- if (valSchema && valSchema.errors) {
- valSchema.errors.forEach((error) => {
- errors.push(error.stack.replace(/^instance./, ''))
- })
- rtn = httpResponse(internalServerError, '', errors.toString())
+ removeFile(file)
+ res.locals.httpCode = httpResponse(response)
+ next()
}
}
+ } else {
+ const errors = []
+ if (valSchema?.errors) {
+ valSchema.errors.forEach((error) => {
+ errors.push(error.stack.replace(/^instance./, ''))
+ })
+ }
+ res.locals.httpCode = httpResponse(
+ internalServerError,
+ '',
+ errors.toString()
+ )
+ next()
}
- res.locals.httpCode = rtn
- next()
}
/**
- * Get provision log.
+ * Get provision log (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -1254,47 +1086,21 @@ const getLogProvisions = (
next = defaultEmptyFunction,
params = {}
) => {
- let rtn = httpInternalError
- if (params && params.id) {
- const foundLogs = logData(params.id)
- if (foundLogs) {
- rtn = httpResponse(ok, foundLogs)
- } else {
- rtn = notFound
- }
+ if (!(params && params.id)) {
+ res.locals.httpCode = httpInternalError
+ next()
+ }
+ const foundLogs = logData(params.id)
+ if (foundLogs) {
+ res.locals.httpCode = httpResponse(ok, foundLogs)
+ } else {
+ res.locals.httpCode = notFound
}
- res.locals.httpCode = rtn
next()
}
/**
- * Execute Command sync and return http response.
- *
- * @param {any[]} params - params for command.
- * @returns {object} httpResponse
- */
-const addResourceSync = (params) => {
- if (params && Array.isArray(params)) {
- const executedCommand = executeCommand(
- defaultCommandProvision,
- params,
- getSpecificConfig('oneprovision_prepend_command')
- )
- try {
- const response = executedCommand.success ? ok : internalServerError
-
- return httpResponse(
- response,
- executedCommand.data ? JSON.parse(executedCommand.data) : params.id
- )
- } catch (error) {
- return httpResponse(internalServerError, '', executedCommand.data)
- }
- }
-}
-
-/**
- * Add Host to provision.
+ * Add Host to provision (Async route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -1311,80 +1117,86 @@ const hostAdd = (
const { user, password } = userData
const { id, amount } = params
if (
- Number.isInteger(parseInt(id, 10)) &&
- Number.isInteger(parseInt(amount, 10)) &&
- user &&
- password
+ !(
+ Number.isInteger(parseInt(id, 10)) &&
+ Number.isInteger(parseInt(amount, 10)) &&
+ user &&
+ password
+ )
) {
- const endpoint = getEndpoint()
- const authCommand = ['--user', user, '--password', password]
- const paramsCommand = [
- 'host',
- 'add',
- id,
- '--amount',
- amount,
- ...authCommand,
- ...endpoint,
- ]
-
- // get Log file
- const dataLog = logData(id, true)
-
- // create stream for write into file
- const stream =
- dataLog &&
- dataLog.fullPath &&
- createWriteStream(dataLog.fullPath, { flags: 'a' })
-
- /**
- * This function is performed for each command line response.
- *
- * @param {string} lastLine - last line command
- * @param {string} uuid - uuid command
- */
- const emit = (lastLine, uuid) => {
- const renderLine = {
- id,
- data: lastLine,
- command: 'add host',
- commandId: uuid,
- }
- stream && stream.write && stream.write(`${JSON.stringify(renderLine)}\n`)
- }
-
- /**
- * This function is only executed if the command is completed.
- *
- * @param {boolean} success - check if command complete without error
- * @param {string} lastLine - last line command
- */
- const close = (success, lastLine) => {
- stream && stream.end && stream.end()
- }
-
- // execute Async Command
- const executedCommand = executeWithEmit(
- paramsCommand,
- { close, out: emit, err: emit },
- { id, command: 'add host' }
- )
-
- // response Http
- res.locals.httpCode = httpResponse(
- executedCommand ? accepted : internalServerError,
- id
- )
+ res.locals.httpCode = httpInternalError
next()
return
}
- res.locals.httpCode = httpInternalError
+
+ const endpoint = getEndpoint()
+ const authCommand = ['--user', user, '--password', password]
+ const paramsCommand = [
+ 'host',
+ 'add',
+ id,
+ '--amount',
+ amount,
+ ...authCommand,
+ ...endpoint,
+ ]
+
+ // get Log file
+ const dataLog = logData(id, true)
+
+ // create stream for write into file
+ const stream =
+ dataLog?.fullPath && createWriteStream(dataLog.fullPath, { flags: 'a' })
+
+ /**
+ * This function is performed for each command line response.
+ *
+ * @param {string} lastLine - last line command
+ * @param {string} uuid - uuid command
+ */
+ let flagSeparateLog = true
+ const emit = (lastLine, uuid) => {
+ const renderLine = {
+ id,
+ data: lastLine,
+ command: 'add host',
+ commandId: uuid,
+ }
+ if (flagSeparateLog) {
+ renderLine.data = executingMessage(`${messageExecuting} host add`)
+ stream?.write?.(`${JSON.stringify(renderLine)}\n`)
+ flagSeparateLog = false
+ renderLine.data = lastLine
+ }
+ stream?.write?.(`${JSON.stringify(renderLine)}\n`)
+
+ return renderLine
+ }
+
+ // execute Async Command
+ const executedCommand = executeWithEmit(
+ paramsCommand,
+ {
+ close: (success, lastLine) => {
+ stream && stream.end && stream.end()
+ },
+ out: emit,
+ err: emit,
+ },
+ { id, command: 'add host' }
+ )
+
+ // response Http
+ res.locals.httpCode = httpResponse(
+ executedCommand ? accepted : internalServerError,
+ id
+ )
next()
}
/**
- * Add Ips to provision.
+ * Add Ips to provision (Sync route).
*
* @param {object} res - http response
* @param {Function} next - express stepper
@@ -1398,34 +1210,38 @@ const ipAdd = (
params = {},
userData = {}
) => {
- let rtn = httpInternalError
const { id, amount } = params
const { user, password } = userData
if (
- Number.isInteger(parseInt(id, 10)) &&
- Number.isInteger(parseInt(amount, 10)) &&
- user &&
- password
+ !(
+ Number.isInteger(parseInt(id, 10)) &&
+ Number.isInteger(parseInt(amount, 10)) &&
+ user &&
+ password
+ )
) {
- const authCommand = ['--user', user, '--password', password]
- const endpoint = getEndpoint()
+ res.locals.httpCode = httpInternalError
+ next()
- rtn =
- addResourceSync([
- 'ip',
- 'add',
- id,
- '--amount',
- amount,
- ...authCommand,
- ...endpoint,
- ]) || httpInternalError
+ return
}
- res.locals.httpCode = rtn
+ const authCommand = ['--user', user, '--password', password]
+ const endpoint = getEndpoint()
+
+ res.locals.httpCode =
+ addResourceSync([
+ 'ip',
+ 'add',
+ id,
+ '--amount',
+ amount,
+ ...authCommand,
+ ...endpoint,
+ ]) || httpInternalError
next()
}
-const provisionFunctionsApi = {
+module.exports = {
getProvisionDefaults,
getLogProvisions,
getListResourceProvision,
@@ -1440,4 +1256,3 @@ const provisionFunctionsApi = {
hostAdd,
ipAdd,
}
-module.exports = provisionFunctionsApi
diff --git a/src/fireedge/src/server/routes/api/oneprovision/provision/helpers.js b/src/fireedge/src/server/routes/api/oneprovision/provision/helpers.js
new file mode 100644
index 0000000000..c954a15a1e
--- /dev/null
+++ b/src/fireedge/src/server/routes/api/oneprovision/provision/helpers.js
@@ -0,0 +1,295 @@
+/* ------------------------------------------------------------------------- *
+ * Copyright 2002-2022, 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 btoa = require('btoa')
+const { parse } = require('yaml')
+const { v4 } = require('uuid')
+const { DateTime } = require('luxon')
+const { publish } = require('server/utils/server')
+const {
+ httpResponse,
+ existsFile,
+ rotateBySize,
+ executeCommand,
+ executeCommandAsync,
+} = require('server/utils/server')
+const { defaults, httpCodes } = require('server/utils/constants')
+const {
+ findRecursiveFolder,
+ getSpecificConfig,
+} = require('server/routes/api/oneprovision/utils')
+
+const {
+ defaultCommandProvision,
+ defaultEmptyFunction,
+ defaultRegexpStartJSON,
+ defaultRegexpEndJSON,
+ defaultRegexpSplitLine,
+ defaultSizeRotate,
+} = defaults
+const { ok, internalServerError } = httpCodes
+const relName = 'provision-mapping'
+const ext = 'yml'
+const logFile = {
+ name: 'stdouterr',
+ ext: 'log',
+}
+const appendError = '.ERROR'
+
+/**
+ * Execute command Async and emit in WS.
+ *
+ * @param {string} command - command to execute
+ * @param {object} actions - external functions when command emit in stderr, stdout and finalize
+ * @param {Function} actions.err - emit when have stderr
+ * @param {Function} actions.out - emit when have stdout
+ * @param {Function} actions.close - emit when finalize
+ * @param {object} dataForLog - data
+ * @param {number} dataForLog.id - data id
+ * @param {string} dataForLog.command - data command
+ * @returns {boolean} check if emmit data
+ */
+const executeWithEmit = (command = [], actions = {}, dataForLog = {}) => {
+ if (
+ !(
+ command &&
+ Array.isArray(command) &&
+ command.length > 0 &&
+ actions &&
+ dataForLog
+ )
+ ) {
+ return
+ }
+
+ const { err: externalErr, out: externalOut, close: externalClose } = actions
+ const err =
+ externalErr && typeof externalErr === 'function'
+ ? externalErr
+ : defaultEmptyFunction
+ const out =
+ externalOut && typeof externalOut === 'function'
+ ? externalOut
+ : defaultEmptyFunction
+ const close =
+ externalClose && typeof externalClose === 'function'
+ ? actions.close
+ : defaultEmptyFunction
+
+ // data for log
+ const id = (dataForLog && dataForLog.id) || ''
+ const commandName = (dataForLog && dataForLog.command) || ''
+
+ let lastLine = ''
+ const uuid = v4()
+
+ let pendingMessages = ''
+
+ /**
+ * Emit data of command.
+ *
+ * @param {string} message - line of command CLI
+ * @param {Function} callback - function when recieve a information
+ */
+ const emit = (message, callback = defaultEmptyFunction) => {
+ /**
+ * Publisher data to WS.
+ *
+ * @param {string} line - command CLI line
+ */
+ const publisher = (line = '') => {
+ const resposeData = callback(line, uuid) || {
+ id,
+ data: line,
+ command: commandName,
+ commandId: uuid,
+ }
+ publish(defaultCommandProvision, resposeData)
+ }
+
+ message
+ .toString()
+ .split(defaultRegexpSplitLine)
+ .forEach((line) => {
+ if (line) {
+ if (
+ (defaultRegexpStartJSON.test(line) &&
+ defaultRegexpEndJSON.test(line)) ||
+ (!defaultRegexpStartJSON.test(line) &&
+ !defaultRegexpEndJSON.test(line) &&
+ pendingMessages.length === 0)
+ ) {
+ lastLine = line
+ publisher(lastLine)
+ } else if (
+ (defaultRegexpStartJSON.test(line) &&
+ !defaultRegexpEndJSON.test(line)) ||
+ (!defaultRegexpStartJSON.test(line) &&
+ !defaultRegexpEndJSON.test(line) &&
+ pendingMessages.length > 0)
+ ) {
+ pendingMessages += line
+ } else {
+ lastLine = pendingMessages + line
+ publisher(lastLine)
+ pendingMessages = ''
+ }
+ }
+ })
+ }
+
+ executeCommandAsync(
+ defaultCommandProvision,
+ command,
+ getSpecificConfig('oneprovision_prepend_command'),
+ {
+ err: (message) => {
+ emit(message, err)
+ },
+ out: (message) => {
+ emit(message, out)
+ },
+ close: (success) => {
+ close(success, lastLine)
+ },
+ }
+ )
+
+ return true
+}
+
+/**
+ * Find log data.
+ *
+ * @param {string} id - id of provision
+ * @param {boolean} fullPath - if need return the path of log
+ * @returns {object} data of log
+ */
+const logData = (id, fullPath = false) => {
+ let rtn = false
+ if (!Number.isInteger(parseInt(id, 10))) {
+ return rtn
+ }
+ const basePath = `${global.paths.CPI}/provision`
+ const relFile = `${basePath}/${relName}`
+ const relFileYML = `${relFile}.${ext}`
+ const find = findRecursiveFolder(basePath, id)
+
+ /**
+ * Found log.
+ *
+ * @param {string} path - path of log
+ * @param {string} uuid - uuid of log
+ */
+ const rtnFound = (path = '', uuid) => {
+ if (!path) {
+ return
+ }
+
+ const stringPath = `${path}/${logFile.name}.${logFile.ext}`
+ existsFile(
+ stringPath,
+ (filedata) => {
+ rotateBySize(stringPath, defaultSizeRotate)
+ rtn = { uuid, log: filedata.split(defaultRegexpSplitLine) }
+ if (fullPath) {
+ rtn.fullPath = stringPath
+ }
+ },
+ defaultEmptyFunction
+ )
+ }
+
+ if (find) {
+ rtnFound(find)
+ } else {
+ // Temporal provision
+ existsFile(
+ relFileYML,
+ (filedata) => {
+ const fileData = parse(filedata) || {}
+ if (!fileData[id]) {
+ return
+ }
+
+ const findPending = findRecursiveFolder(basePath, fileData[id])
+ if (findPending) {
+ rtnFound(findPending, fileData[id])
+ } else {
+ const findError = findRecursiveFolder(
+ basePath,
+ fileData[id] + appendError
+ )
+ findError && rtnFound(findError, fileData[id])
+ }
+ },
+ defaultEmptyFunction
+ )
+ }
+
+ return rtn
+}
+
+/**
+ * Execute Command sync and return http response.
+ *
+ * @param {any[]} params - params for command.
+ * @returns {object} httpResponse
+ */
+const addResourceSync = (params) => {
+ if (!(params && Array.isArray(params))) {
+ return
+ }
+
+ const executedCommand = executeCommand(
+ defaultCommandProvision,
+ params,
+ getSpecificConfig('oneprovision_prepend_command')
+ )
+ try {
+ const response = executedCommand.success ? ok : internalServerError
+
+ return httpResponse(
+ response,
+ executedCommand.data ? JSON.parse(executedCommand.data) : params.id
+ )
+ } catch (error) {
+ return httpResponse(internalServerError, '', executedCommand.data)
+ }
+}
+
+/**
+ * Executing line for provision logs.
+ *
+ * @param {string} message - message to log
+ * @returns {string} line message stringify
+ */
+const executingMessage = (message = '') =>
+ JSON.stringify({
+ timestamp: DateTime.now().toFormat('yyyy-MM-dd HH:mm:ss ZZZ'),
+ severity: 'DEBUG',
+ message: btoa(message),
+ })
+
+module.exports = {
+ executeWithEmit,
+ logData,
+ addResourceSync,
+ executingMessage,
+ relName,
+ ext,
+ logFile,
+ appendError,
+}
diff --git a/src/fireedge/src/server/routes/api/oneprovision/provision/routes.js b/src/fireedge/src/server/routes/api/oneprovision/provision/routes.js
index ea6df607d3..8da6e1b99d 100644
--- a/src/fireedge/src/server/routes/api/oneprovision/provision/routes.js
+++ b/src/fireedge/src/server/routes/api/oneprovision/provision/routes.js
@@ -140,7 +140,7 @@ module.exports = {
},
},
[PROVISION_DELETE_RESOURCE]: {
- path: `${basepath}/resource/:resource/:id`,
+ path: `${basepath}/resource/:resource/:id/:provision`,
httpMethod: DELETE,
auth: true,
params: {
@@ -150,6 +150,9 @@ module.exports = {
id: {
from: resource,
},
+ provision: {
+ from: resource,
+ },
},
},
[PROVISION_HOST_ACTION]: {
diff --git a/src/fireedge/src/server/utils/constants/defaults.js b/src/fireedge/src/server/utils/constants/defaults.js
index 4ecab3c53e..f8f7b08786 100644
--- a/src/fireedge/src/server/utils/constants/defaults.js
+++ b/src/fireedge/src/server/utils/constants/defaults.js
@@ -57,6 +57,7 @@ const defaults = {
defaultRegexID: /^ID: (?\d+)/,
defaultRegexpEndJSON: /}$/,
defaultRegexpSplitLine: /\r|\n/,
+ defaultSizeRotate: '100k',
defaultAppName: appName,
defaultConfigErrorMessage: {
color: 'red',
diff --git a/src/fireedge/src/server/utils/server.js b/src/fireedge/src/server/utils/server.js
index 9be39e35fa..14079e15af 100644
--- a/src/fireedge/src/server/utils/server.js
+++ b/src/fireedge/src/server/utils/server.js
@@ -36,14 +36,17 @@ const {
readdirSync,
statSync,
removeSync,
+ moveSync,
+ ensureFileSync,
} = require('fs-extra')
const { spawnSync, spawn } = require('child_process')
const events = require('events')
+const { DateTime } = require('luxon')
+const { request: axios } = require('axios')
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 { request: axios } = require('axios')
const eventsEmitter = new events.EventEmitter()
const {
@@ -304,6 +307,48 @@ const decrypt = (data = '', decryptKey = '', iv = '') => {
return rtn
}
+const getSize = (limit) => {
+ const size = limit?.toLowerCase?.()?.match(/^((?:0\.)?\d+)([kmg])$/)
+ const limitNumber = parseInt(limit, 10)
+ if (size) {
+ switch (size[2]) {
+ case 'k':
+ return size[1] * 1024
+ case 'm':
+ return size[1] * 1024 ** 2
+ case 'g':
+ return size[1] * 1024 ** 3
+ }
+ } else if (Number.isInteger(limitNumber)) {
+ return limitNumber
+ }
+}
+
+/**
+ * Rotate file by size.
+ *
+ *
+ * @param {string} filepath - file path
+ * @param {number} limit - size to rotate
+ */
+const rotateBySize = (filepath = '', limit) => {
+ try {
+ const fileStats = statSync(filepath)
+ if (fileStats.size >= getSize(limit)) {
+ moveSync(filepath, `${filepath}.${DateTime.now().toSeconds()}`)
+ ensureFileSync(filepath)
+ }
+ } catch (error) {
+ const errorData = (error && error.message) || ''
+ writeInLogger(errorData)
+ messageTerminal({
+ color: 'red',
+ message: 'Error: %s',
+ error: errorData,
+ })
+ }
+}
+
/**
* Check if file exist.
*
@@ -1005,4 +1050,5 @@ module.exports = {
publish,
subscriber,
executeRequest,
+ rotateBySize,
}