1
0
mirror of https://github.com/OpenNebula/one.git synced 2025-03-30 22:50:10 +03:00

F #391: Add CPI API (#400)

Co-authored-by: Jorge Lobo <jlobo@opennebula.systems>
This commit is contained in:
Jorge Miguel Lobo Escalona 2020-11-06 10:41:21 +01:00 committed by GitHub
parent aa78acf67e
commit 514ad55874
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
37 changed files with 2144 additions and 773 deletions

View File

@ -22,7 +22,7 @@ import useOpennebula from 'client/hooks/useOpennebula'
import LoadingScreen from 'client/components/LoadingScreen'
const findRouteByPathname = (endpoints, pathname) => {
const findRouteByPathname = (endpoints=[], pathname='') => {
const routes = endpoints.flatMap(
({ endpoint, ...item }) => endpoint ?? item
)

View File

@ -21,20 +21,22 @@ import { defaultPort } from 'server/utils/constants/defaults'
const ENDPOINT = `http://127.0.0.1:${defaultPort}`
const Webconsole = () => {
const Webconsole = ({ zone }) => {
const [response, setResponse] = useState({})
useEffect(() => {
const socket = io(ENDPOINT, {
path: '/zeromq',
query: {
token: findStorageData(JWT_NAME)
token: findStorageData(JWT_NAME),
zone: 'pepe'
}
})
socket.on('zeroMQ', data => {
setResponse(data)
})
}, [])
return () => { socket.disconnect() }
}, [zone])
console.log('-->', response)
return <p />
}

View File

@ -2,16 +2,16 @@ import httpCodes from 'server/utils/constants/http-codes'
import { httpMethod } from 'server/utils/constants/defaults'
import {
SERVICE,
SERVICE_TEMPLATE,
SERVICE_TEMPLATE_ACTION
SERVICE_TEMPLATE
} from 'server/routes/api/oneflow/string-routes'
import { requestData } from 'client/utils'
import { REQUEST_ACTIONS } from 'client/constants'
const { GET, POST, PUT } = httpMethod
export const getApplication = ({ id }) =>
requestData(`/api/${SERVICE}/${id}`, {
method: httpMethod.GET,
requestData(`/api/${SERVICE}/list/${id}`, {
method: GET,
error: err => err?.message
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
@ -20,9 +20,9 @@ export const getApplication = ({ id }) =>
})
export const getApplications = ({ filter }) =>
requestData(`/api/${SERVICE}`, {
requestData(`/api/${SERVICE}/list`, {
data: { filter },
method: httpMethod.GET,
method: GET,
error: err => err?.message
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
@ -35,8 +35,8 @@ export const createApplication = () => {
}
export const getTemplate = ({ id }) =>
requestData(`/api/${SERVICE_TEMPLATE}/${id}`, {
method: httpMethod.GET,
requestData(`/api/${SERVICE_TEMPLATE}/list/${id}`, {
method: GET,
error: err => err?.message
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
@ -45,9 +45,9 @@ export const getTemplate = ({ id }) =>
})
export const getTemplates = ({ filter }) =>
requestData(`/api/${SERVICE_TEMPLATE}`, {
requestData(`/api/${SERVICE_TEMPLATE}/list`, {
data: { filter },
method: httpMethod.GET,
method: GET,
error: err => err?.message
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
@ -56,9 +56,9 @@ export const getTemplates = ({ filter }) =>
})
export const createTemplate = ({ data = {} }) =>
requestData(`/api/${SERVICE_TEMPLATE}`, {
requestData(`/api/${SERVICE_TEMPLATE}/create`, {
data,
method: httpMethod.POST
method: POST
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
if (!res?.data?.DOCUMENT?.ID) throw new Error('Error')
@ -67,9 +67,9 @@ export const createTemplate = ({ data = {} }) =>
})
export const updateTemplate = ({ id, data = {} }) =>
requestData(`/api/${SERVICE_TEMPLATE}/${id}`, {
requestData(`/api/${SERVICE_TEMPLATE}/update/${id}`, {
data,
method: httpMethod.PUT
method: PUT
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
if (!res?.data?.DOCUMENT?.ID) throw new Error('Error')
@ -78,14 +78,14 @@ export const updateTemplate = ({ id, data = {} }) =>
})
export const instantiateTemplate = ({ id, data = {} }) =>
requestData(`/api/${SERVICE_TEMPLATE_ACTION}/${id}`, {
requestData(`/api/${SERVICE_TEMPLATE}/action/${id}`, {
data: {
action: {
perform: REQUEST_ACTIONS.INSTANTIATE,
params: { merge_template: data }
}
},
method: httpMethod.POST
method: POST
}).then(res => {
if (!res?.id || res?.id !== httpCodes.ok.id) throw res
if (!res?.data?.DOCUMENT?.ID) throw new Error('Error')

View File

@ -52,7 +52,7 @@ const appConfig = getConfig()
const port = appConfig.PORT || defaultPort
const userLog = appConfig.LOG || 'dev'
if (env.NODE_ENV === defaultWebpackMode) {
if (env && env.NODE_ENV && env.NODE_ENV === defaultWebpackMode) {
// eslint-disable-next-line global-require
const config = require('../../webpack.config.dev.client')
const compiler = webpack(config)

View File

@ -13,10 +13,11 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const speakeasy = require('speakeasy');
const qrcode = require('qrcode');
const { httpResponse } = require('server/utils/server'); //'../../../utils/server'
const { getConfig } = require('server/utils/yml'); // '../../../utils/yml'
const speakeasy = require('speakeasy')
const qrcode = require('qrcode')
const { Map } = require('immutable')
const { httpResponse } = require('server/utils/server') // '../../../utils/server'
const { getConfig } = require('server/utils/yml') // '../../../utils/yml'
const {
httpMethod,
defaultMethodUserInfo,
@ -24,27 +25,27 @@ const {
default2FAIssuer,
default2FAOpennebulaVar,
default2FAOpennebulaTmpVar
} = require('server/utils/constants/defaults');
} = require('server/utils/constants/defaults')
const { POST, GET } = httpMethod;
const { POST, GET } = httpMethod
const {
responseOpennebula,
checkOpennebulaCommand,
generateNewTemplate,
check2Fa
} = require('server/utils/opennebula');
const { from: fromData } = require('server/utils/constants/defaults');
} = require('server/utils/opennebula')
const { from: fromData } = require('server/utils/constants/defaults')
const {
ok,
unauthorized,
internalServerError
} = require('server/utils/constants/http-codes');
} = require('server/utils/constants/http-codes')
// user config
const appConfig = getConfig();
const appConfig = getConfig()
const twoFactorAuthIssuer =
appConfig.TWO_FACTOR_AUTH_ISSUER || default2FAIssuer;
appConfig.TWO_FACTOR_AUTH_ISSUER || default2FAIssuer
const getUserInfoAuthenticated = (connect, userId, callback, next) => {
if (
@ -57,17 +58,17 @@ const getUserInfoAuthenticated = (connect, userId, callback, next) => {
typeof next === 'function' &&
defaultMethodUserInfo
) {
const connectOpennebula = connect();
const dataUser = {};
const connectOpennebula = connect()
const dataUser = {}
// empty positions for validate...
dataUser[fromData.resource] = {};
dataUser[fromData.query] = {};
dataUser[fromData.postBody] = {};
dataUser[fromData.resource].id = userId;
dataUser[fromData.resource] = {}
dataUser[fromData.query] = {}
dataUser[fromData.postBody] = {}
dataUser[fromData.resource].id = userId
const getOpennebulaMethod = checkOpennebulaCommand(
defaultMethodUserInfo,
GET
);
)
connectOpennebula(
defaultMethodUserInfo,
getOpennebulaMethod(dataUser),
@ -78,50 +79,50 @@ const getUserInfoAuthenticated = (connect, userId, callback, next) => {
value,
info => {
if (info !== undefined && info !== null) {
callback(info);
callback(info)
} else {
next();
next()
}
},
next
);
)
}
);
)
}
};
}
const generateQR = (req, res, next, connect, userId) => {
const secret = speakeasy.generateSecret({
length: 10,
name: twoFactorAuthIssuer
});
})
if (secret && secret.otpauth_url && secret.base32) {
const { otpauth_url: otpURL, base32 } = secret;
const { otpauth_url: otpURL, base32 } = secret
qrcode.toDataURL(otpURL, (err, dataURL) => {
if (err) {
res.locals.httpCode = httpResponse(internalServerError);
next();
res.locals.httpCode = httpResponse(internalServerError)
next()
} else {
const connectOpennebula = connect();
const connectOpennebula = connect()
getUserInfoAuthenticated(
connect,
userId,
info => {
if (info && info.USER && info.USER.TEMPLATE && req) {
const dataUser = Map(req).toObject();
const emptyTemplate = {};
emptyTemplate[default2FAOpennebulaTmpVar] = base32;
const dataUser = Map(req).toObject()
const emptyTemplate = {}
emptyTemplate[default2FAOpennebulaTmpVar] = base32
dataUser[fromData.resource].id = userId;
dataUser[fromData.resource].id = userId
dataUser[fromData.postBody].template = generateNewTemplate(
info.USER.TEMPLATE.SUNSTONE || {},
emptyTemplate,
[default2FAOpennebulaVar]
);
)
const getOpennebulaMethod = checkOpennebulaCommand(
defaultMethodUserUpdate,
POST
);
)
connectOpennebula(
defaultMethodUserUpdate,
getOpennebulaMethod(dataUser),
@ -134,31 +135,31 @@ const generateQR = (req, res, next, connect, userId) => {
if (pass !== undefined && pass !== null) {
res.locals.httpCode = httpResponse(ok, {
img: dataURL
});
next();
})
next()
} else {
next();
next()
}
},
next
);
)
}
);
)
} else {
next();
next()
}
},
next
);
)
}
});
})
} else {
next();
next()
}
};
}
const twoFactorSetup = (req, res, next, connect, userId) => {
const connectOpennebula = connect();
const connectOpennebula = connect()
getUserInfoAuthenticated(
connect,
userId,
@ -175,24 +176,24 @@ const twoFactorSetup = (req, res, next, connect, userId) => {
req[fromData.postBody] &&
req[fromData.postBody].token
) {
const sunstone = info.USER.TEMPLATE.SUNSTONE;
const token = req[fromData.postBody].token;
const secret = sunstone[default2FAOpennebulaTmpVar];
const sunstone = info.USER.TEMPLATE.SUNSTONE
const token = req[fromData.postBody].token
const secret = sunstone[default2FAOpennebulaTmpVar]
if (check2Fa(secret, token)) {
const emptyTemplate = {};
emptyTemplate[default2FAOpennebulaVar] = secret;
const emptyTemplate = {}
emptyTemplate[default2FAOpennebulaVar] = secret
const dataUser = Map(req).toObject();
dataUser[fromData.resource].id = userId;
const dataUser = Map(req).toObject()
dataUser[fromData.resource].id = userId
dataUser[fromData.postBody].template = generateNewTemplate(
sunstone || {},
emptyTemplate,
[default2FAOpennebulaTmpVar]
);
)
const getOpennebulaMethodUpdate = checkOpennebulaCommand(
defaultMethodUserUpdate,
POST
);
)
connectOpennebula(
defaultMethodUserUpdate,
getOpennebulaMethodUpdate(dataUser),
@ -203,27 +204,27 @@ const twoFactorSetup = (req, res, next, connect, userId) => {
value,
pass => {
if (pass !== undefined && pass !== null) {
res.locals.httpCode = httpResponse(ok);
res.locals.httpCode = httpResponse(ok)
}
next();
next()
},
next
);
)
}
);
)
} else {
res.locals.httpCode = httpResponse(unauthorized);
next();
res.locals.httpCode = httpResponse(unauthorized)
next()
}
} else {
next();
next()
}
},
next
);
};
)
}
const twoFactorDelete = (req, res, next, connect, userId) => {
const connectOpennebula = connect();
const connectOpennebula = connect()
getUserInfoAuthenticated(
connect,
userId,
@ -234,18 +235,18 @@ const twoFactorDelete = (req, res, next, connect, userId) => {
info.USER.TEMPLATE &&
info.USER.TEMPLATE.SUNSTONE
) {
const emptyTemplate = {};
const dataUser = Map(req).toObject();
dataUser[fromData.resource].id = userId;
const emptyTemplate = {}
const dataUser = Map(req).toObject()
dataUser[fromData.resource].id = userId
dataUser[fromData.postBody].template = generateNewTemplate(
info.USER.TEMPLATE.SUNSTONE || {},
emptyTemplate,
[default2FAOpennebulaTmpVar, default2FAOpennebulaVar]
);
)
const getOpennebulaMethodUpdate = checkOpennebulaCommand(
defaultMethodUserUpdate,
POST
);
)
connectOpennebula(
defaultMethodUserUpdate,
getOpennebulaMethodUpdate(dataUser),
@ -256,24 +257,24 @@ const twoFactorDelete = (req, res, next, connect, userId) => {
value,
pass => {
if (pass !== undefined && pass !== null) {
res.locals.httpCode = httpResponse(ok);
res.locals.httpCode = httpResponse(ok)
}
next();
next()
},
next
);
)
}
);
)
} else {
next();
next()
}
},
next
);
};
)
}
module.exports = {
getUserInfoAuthenticated,
generateQR,
twoFactorSetup,
twoFactorDelete
};
}

View File

@ -13,15 +13,15 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const { generateQR, twoFactorSetup, twoFactorDelete } = require('./functions');
const { httpMethod } = require('server/utils/constants/defaults'); // ../../../utils/constants/defaults'
const { generateQR, twoFactorSetup, twoFactorDelete } = require('./functions')
const { httpMethod } = require('server/utils/constants/defaults') // ../../../utils/constants/defaults'
const {
TWO_FACTOR_QR,
TWO_FACTOR_DELETE,
TWO_FACTOR_SETUP
} = require('./string-routes');
} = require('./string-routes')
const { POST, DELETE } = httpMethod;
const { POST, DELETE } = httpMethod
const privateRoutes = [
{
@ -39,13 +39,13 @@ const privateRoutes = [
endpoint: TWO_FACTOR_DELETE,
action: twoFactorDelete
}
];
]
const publicRoutes = [];
const publicRoutes = []
const functionRoutes = {
private: privateRoutes,
public: publicRoutes
};
}
module.exports = functionRoutes;
module.exports = functionRoutes

View File

@ -49,7 +49,7 @@ const auth = (req, res, next, connect) => {
setReq(req)
setRes(res)
setNext(next)
updaterResponse(Map(internalServerError).toObject())
updaterResponse(new Map(internalServerError).toObject())
const getOpennebulaMethod = checkOpennebulaCommand(
defaultMethodLogin,
POST

View File

@ -219,41 +219,7 @@ const setZones = () => {
const userInfo = userData => {
if (user && opennebulaToken && userData && userData.USER) {
const informationUser = userData.USER
// remove opennebula user tokens
if (
informationUser.LOGIN_TOKEN &&
Array.isArray(informationUser.LOGIN_TOKEN)
) {
informationUser.LOGIN_TOKEN.forEach(loginToken => {
if (
loginToken &&
loginToken.TOKEN &&
loginToken.TOKEN !== opennebulaToken
) {
const dataSource = dataSourceWithExpirateDate()
dataSource[fromData.postBody].expire = 0
dataSource[fromData.postBody].token = loginToken.TOKEN
const oneConnect = connectOpennebula()
oneConnect(
defaultMethodLogin,
getOpennebulaMethod(dataSource),
(err, value) => {
responseOpennebula(
() => undefined,
err,
value,
() => {
setZones()
},
next
)
}
)
}
})
} else {
setZones()
}
setZones()
validate2faAuthentication(informationUser)
genJWT(informationUser)
next()

View File

@ -21,7 +21,15 @@ const config = {
color: 'red',
message: 'file not found: %s'
}
const files = ['2fa', 'auth', 'oneflow', 'support', 'vcenter', 'zendesk']
const files = [
'2fa',
'auth',
'oneflow',
'support',
'vcenter',
'zendesk',
'provision'
]
const filesDataPrivate = []
const filesDataPublic = []
files.map(file => {

View File

@ -12,19 +12,13 @@
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const { request } = require('axios')
const { request: axios } = require('axios')
const btoa = require('btoa')
const { Map } = require('immutable')
const { defaultOneFlowServer } = require('server/utils/constants/defaults')
const { getConfig } = require('server/utils/yml')
const { httpMethod } = require('server/utils/constants/defaults')
const { addPrintf } = require('server/utils/general')
const { httpResponse } = require('server/utils/server')
const {
ok,
internalServerError
} = require('server/utils/constants/http-codes')
const { GET, DELETE } = httpMethod
@ -32,99 +26,67 @@ const appConfig = getConfig()
const oneFlowServiceDataConection =
appConfig.ONE_FLOW_SERVER || defaultOneFlowServer
const parsePostData = (postData = {}) => {
const rtn = {}
Object.entries(postData).forEach(([key, value]) => {
try {
rtn[key] = JSON.parse(value, (k, val) => {
try {
return JSON.parse(val)
} catch (error) {
return val
}
})
} catch (error) {
rtn[key] = value
}
})
return rtn
}
const returnSchemaError = (error = []) =>
error
.map(element => (element && element.stack ? element.stack : ''))
.toString()
const conectionOneFlow = (
res,
next = () => undefined,
method = GET,
user = '',
path = '/',
requestData = '',
postData = ''
) => {
if (res && next && method && user) {
const options = {
method,
baseURL: `${oneFlowServiceDataConection.PROTOCOL}://${oneFlowServiceDataConection.HOST}:${oneFlowServiceDataConection.PORT}`,
url: path,
headers: {
Authorization: `Basic ${btoa(user)}`
},
validateStatus: status => status
}
const parseToNumber = validate =>
isNaN(parseInt(validate, 10))
? validate
: parseInt(validate, 10)
if (requestData) {
options.url = addPrintf(path, requestData)
}
if (postData) {
options.data = postData
}
request(options)
.then(response => {
if (response && response.statusText) {
if (response.status >= 200 && response.status < 400) {
if (response.data) {
return response.data
}
if (
response.config.method &&
response.config.method.toUpperCase() === DELETE
) {
const parseToNumber = validate =>
isNaN(parseInt(validate, 10))
? validate
: parseInt(validate, 10)
return Array.isArray(requestData)
? parseToNumber(requestData[0])
: parseToNumber(requestData)
}
} else if (response.data) {
throw Error(response.data)
}
}
throw Error(response.statusText)
})
.then(data => {
res.locals.httpCode = httpResponse(ok, data)
next()
})
.catch(e => {
const codeInternalServerError = Map(internalServerError).toObject()
if (e && e.message) {
codeInternalServerError.data = e.message
}
res.locals.httpCode = httpResponse(internalServerError, e && e.message)
next()
})
const oneFlowConection = (requestData = {}, success = () => undefined, error = () => undefined) => {
const { method, path, user, password, request, post } = requestData
const optionMethod = method || GET
const optionPath = path || '/'
const optionAuth = btoa(`${user || ''}:${password || ''}`)
const options = {
method: optionMethod,
baseURL: `${oneFlowServiceDataConection.PROTOCOL}://${oneFlowServiceDataConection.HOST}:${oneFlowServiceDataConection.PORT}`,
url: request ? addPrintf(optionPath, request || '') : optionPath,
headers: {
Authorization: `Basic ${optionAuth}`
},
validateStatus: status => status
}
if (post) {
options.data = post
}
console.log('axios options: ', options, requestData)
axios(options)
.then(response => {
if (response && response.statusText) {
if (response.status >= 200 && response.status < 400) {
if (response.data) {
return response.data
}
if (
response.config.method &&
response.config.method.toUpperCase() === DELETE
) {
return Array.isArray(request)
? parseToNumber(request[0])
: parseToNumber(request)
}
} else if (response.data) {
throw Error(response.data)
}
}
throw Error(response.statusText)
})
.then(data => {
success(data)
})
.catch(e => {
error(e)
})
}
const functionRoutes = {
conectionOneFlow,
parsePostData,
oneFlowConection,
returnSchemaError
}

View File

@ -12,90 +12,43 @@
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const {
service,
serviceDelete,
serviceAddAction,
serviceAddScale,
serviceAddRoleAction
} = require('./service');
const {
serviceTemplate,
serviceTemplateDelete,
serviceTemplateCreate,
serviceTemplateUpdate,
serviceTemplateAction
} = require('./service_template');
const { httpMethod } = require('server/utils/constants/defaults');
const {
SERVICE,
SERVICE_ACTION,
SERVICE_SCALE,
SERVICE_ROLE_ACTION,
SERVICE_TEMPLATE,
SERVICE_TEMPLATE_ACTION
} = require('./string-routes');
const { GET, POST, DELETE, PUT } = httpMethod;
const { main: service, routes: serviceRoutes } = require('./service')
const { main: serviceTemplate, routes: serviceTemplateRoutes } = require('./service_template')
const privateRoutes = [
{
httpMethod: GET,
endpoint: SERVICE,
action: service
},
{
httpMethod: DELETE,
endpoint: SERVICE,
action: serviceDelete
},
{
httpMethod: POST,
endpoint: SERVICE_ACTION,
action: serviceAddAction
},
{
httpMethod: POST,
endpoint: SERVICE_SCALE,
action: serviceAddScale
},
{
httpMethod: POST,
endpoint: SERVICE_ROLE_ACTION,
action: serviceAddRoleAction
},
{
httpMethod: GET,
endpoint: SERVICE_TEMPLATE,
action: serviceTemplate
},
{
httpMethod: DELETE,
endpoint: SERVICE_TEMPLATE,
action: serviceTemplateDelete
},
{
httpMethod: POST,
endpoint: SERVICE_TEMPLATE,
action: serviceTemplateCreate
},
{
httpMethod: PUT,
endpoint: SERVICE_TEMPLATE,
action: serviceTemplateUpdate
},
{
httpMethod: POST,
endpoint: SERVICE_TEMPLATE_ACTION,
action: serviceTemplateAction
const { SERVICE, SERVICE_TEMPLATE } = require('./string-routes')
const privateRoutes = []
const publicRoutes = []
const fillRoute = (method, endpoint, action) => ({
httpMethod: method,
endpoint,
action
})
const fillPrivateRoutes = (methods = {}, path = '', action = () => undefined) => {
if (Object.keys(methods).length > 0 && methods.constructor === Object) {
Object.keys(methods).forEach((method) => {
privateRoutes.push(
fillRoute(method, path,
(req, res, next, conection, userId, user) => {
action(req, res, next, methods[method], user)
})
)
})
}
];
}
const publicRoutes = [];
const generatePrivateRoutes = () => {
fillPrivateRoutes(serviceRoutes, SERVICE, service)
fillPrivateRoutes(serviceTemplateRoutes, SERVICE_TEMPLATE, serviceTemplate)
return privateRoutes
}
const functionRoutes = {
private: privateRoutes,
private: generatePrivateRoutes(),
public: publicRoutes
};
}
module.exports = functionRoutes;
module.exports = functionRoutes

View File

@ -18,19 +18,25 @@ const action = {
type: 'object',
properties: {
action: {
perform: {
type: 'string',
required: true
},
params: {
merge_template: {
type: 'object',
properties: {
perform: {
type: 'string',
required: true
},
params: {
type: 'object',
required: false
properties: {
merge_template: {
type: 'object',
required: false
}
}
}
}
}
}
};
}
const role = {
id: '/Role',
@ -151,7 +157,7 @@ const role = {
}
}
}
};
}
const service = {
type: 'object',
@ -207,12 +213,12 @@ const service = {
required: false
}
}
};
}
const functionRoutes = {
const schemas = {
action,
role,
service
};
}
module.exports = functionRoutes;
module.exports = schemas

View File

@ -0,0 +1,207 @@
/* Copyright 2002-2019, 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 { Validator } = require('jsonschema')
const { action } = require('./schemas')
const { oneFlowConection } = require('./functions')
const { httpMethod } = require('server/utils/constants/defaults')
const { httpResponse, parsePostData } = require('server/utils/server')
const {
ok,
internalServerError,
methodNotAllowed
} = require('server/utils/constants/http-codes')
const { returnSchemaError } = require('./functions')
const { GET, POST, DELETE } = httpMethod
const service = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (user && password) {
const config = { method: GET, path: '/service', user, password }
if (params && params.id) {
config.path = '/service/{0}'
config.request = params.id
oneFlowConection(config, success, error)
} else {
oneFlowConection(config, success, error)
}
}
}
const serviceDelete = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.id && user && password) {
const config = { method: DELETE, path: '/service/{0}', user, password, request: params.id }
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid id service'
)
next()
}
}
const serviceAddAction = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.id && params.action && user && password) {
const v = new Validator()
const postAction = parsePostData(params.action)
const valSchema = v.validate(postAction, action)
if (valSchema.valid) { // validate if "action" is required
const config = {
method: POST,
path: '/service/{0}/action',
user,
password,
request: params.id,
post: postAction
}
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
)
next()
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid id service'
)
next()
}
}
const serviceAddScale = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.id && params.action && user && password) {
const v = new Validator()
const postAction = parsePostData(params.action)
const valSchema = v.validate(postAction, action)
if (valSchema.valid) { // validate if "action" is required
const config = {
method: POST,
path: '/service/{0}/scale',
user,
password,
request: params.id,
post: postAction
}
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
)
next()
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid id service'
)
next()
}
}
const serviceAddRoleAction = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.role && params.id && params.action && user && password) {
const v = new Validator()
const postAction = parsePostData(params.action)
const valSchema = v.validate(postAction, action)
if (valSchema.valid) { // validate if "action" is required
const config = {
method: POST,
path: '/service/{0}/role/{1}',
user,
password,
request: [params.role, params.id],
post: postAction
}
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
)
next()
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid action, id service or role'
)
next()
}
}
const serviceApi = {
service,
serviceDelete,
serviceAddAction,
serviceAddScale,
serviceAddRoleAction
}
module.exports = serviceApi

View File

@ -12,211 +12,84 @@
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const { Validator } = require('jsonschema');
const { action } = require('./schemas');
const { conectionOneFlow } = require('./functions');
const { httpMethod } = require('server/utils/constants/defaults');
const { from: fromData } = require('server/utils/constants/defaults');
const { httpResponse } = require('server/utils/server');
const { httpMethod, from: fromData } = require('server/utils/constants/defaults')
const { getParamsForObject } = require('server/utils/server')
const {
methodNotAllowed,
internalServerError
} = require('server/utils/constants/http-codes');
const { parsePostData, returnSchemaError } = require('./functions');
const { GET, POST, DELETE } = httpMethod;
const service = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
req[fromData.resource] &&
req[fromData.resource].method
) {
conectionOneFlow(
res,
next,
GET,
user,
`/service/{0}`,
req[fromData.resource].method
);
} else {
conectionOneFlow(res, next, GET, user, '/service');
}
} else {
next();
}
};
const serviceDelete = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
req[fromData.resource] &&
req[fromData.resource].method
) {
conectionOneFlow(res, next, DELETE, user, `/service/{0}`, [
req[fromData.resource].method
]);
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid id service'
);
next();
}
} else {
next();
}
};
const serviceAddAction = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
fromData.postBody &&
req[fromData.resource] &&
req[fromData.postBody] &&
req[fromData.resource].method
) {
const postAction = parsePostData(req[fromData.postBody]);
const v = new Validator();
const valSchema = v.validate(postAction, action);
if (valSchema.valid) {
conectionOneFlow(
res,
next,
POST,
user,
`/service/{0}/action`,
req[fromData.resource].method,
postAction
);
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
);
next();
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid action or id'
);
next();
}
} else {
next();
}
};
const serviceAddScale = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
fromData.postBody &&
req[fromData.resource] &&
req[fromData.postBody] &&
req[fromData.resource].method
) {
const postAction = parsePostData(req[fromData.postBody]);
const v = new Validator();
const valSchema = v.validate(postAction, action);
if (valSchema.valid) {
conectionOneFlow(
res,
next,
POST,
user,
`/service/{0}/action`,
req[fromData.resource].method,
postAction
);
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
);
next();
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid action or id'
);
next();
}
} else {
next();
}
};
const serviceAddRoleAction = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
fromData.postBody &&
req[fromData.resource] &&
req[fromData.postBody] &&
req[fromData.resource].method &&
req[fromData.resource].id
) {
const postAction = parsePostData(req[fromData.postBody]);
const v = new Validator();
const valSchema = v.validate(postAction, action);
if (valSchema.valid) {
conectionOneFlow(
res,
next,
POST,
user,
`/service/{0}/role/{1}`,
[req[fromData.resource].method, req[fromData.resource].id],
postAction
);
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
);
next();
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid action or id'
);
next();
}
} else {
next();
}
};
const serviceApi = {
service,
serviceDelete,
serviceAddAction,
serviceAddScale,
serviceAddRoleAction
};
module.exports = serviceApi;
} = require('./service-functions')
const { GET, POST, DELETE } = httpMethod
const routes = {
[GET]: {
list: {
action: service,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[POST]: {
action: {
action: serviceAddAction,
params: {
id: { from: fromData.resource, name: 'id' },
action: { from: fromData.postBody, front: true }
}
},
scale: {
action: serviceAddScale,
params: {
id: { from: fromData.resource, name: 'id' },
action: { from: fromData.postBody, front: true }
}
},
'role-action': {
action: serviceAddRoleAction,
params: {
role: { from: fromData.resource, name: 'id', front: true },
id: { from: fromData.resource, name: 'id2', front: true },
action: { from: fromData.postBody, front: true }
}
}
},
[DELETE]: {
delete: {
action: serviceDelete,
params: { id: { from: fromData.resource, name: 'id', front: true } }
}
}
}
const main = (req = {}, res = {}, next = () => undefined, routes = {}, user = {}, index = 0) => {
const resources = Object.keys(req[fromData.resource])
if (req && res && next && routes) {
const route = routes[`${req[fromData.resource][resources[index]]}`.toLowerCase()]
if (req && fromData && fromData.resource && req[fromData.resource] && route) {
if (Object.keys(route).length > 0 && route.constructor === Object) {
if (route.action && route.params && typeof route.action === 'function') {
const params = getParamsForObject(route.params, req)
route.action(res, next, params, user)
} else {
main(req, res, next, route, user, index + 1)
}
} else {
next()
}
} else {
next()
}
} else {
next()
}
}
const serviceApi = {
main,
routes
}
module.exports = serviceApi

View File

@ -0,0 +1,206 @@
/* Copyright 2002-2019, 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 { Validator } = require('jsonschema')
const { role, service, action } = require('./schemas')
const { oneFlowConection } = require('./functions')
const { httpMethod } = require('server/utils/constants/defaults')
const { httpResponse, parsePostData } = require('server/utils/server')
const {
ok,
internalServerError,
methodNotAllowed
} = require('server/utils/constants/http-codes')
const { returnSchemaError } = require('./functions')
const { GET, POST, DELETE, PUT } = httpMethod
const serviceTemplate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (user && password) {
const config = { method: GET, path: '/service_template', user, password }
if (params && params.id) {
config.path = '/service_template/{0}'
config.request = params.id
oneFlowConection(config, success, error)
} else {
oneFlowConection(config, success, error)
}
}
}
const serviceTemplateDelete = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.id && user && password) {
const config = { method: DELETE, path: '/service_template/{0}', user, password, request: params.id }
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid id service template'
)
next()
}
}
const serviceTemplateCreate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.template && user && password) {
const v = new Validator()
const template = parsePostData(params.template)
v.addSchema(role, '/Role')
const valSchema = v.validate(template, service)
if (valSchema.valid) {
const config = {
method: POST,
path: '/service_template',
user,
password,
post: template
}
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
)
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid service json'
)
next()
}
}
const serviceTemplateUpdate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.id && params.template && user && password) {
const v = new Validator()
v.addSchema(role, '/Role')
const template = parsePostData(params.template)
const valSchema = v.validate(template, service)
if (valSchema.valid) {
const config = {
method: PUT,
path: '/service_template/{0}',
user,
password,
request: params.id,
post: template
}
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
)
next()
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid service json or id'
)
next()
}
}
const serviceTemplateAction = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const success = data => {
res.locals.httpCode = httpResponse(ok, data)
next()
}
const error = data => {
res.locals.httpCode = httpResponse(internalServerError, data && data.message)
next()
}
if (params && params.id && params.template && user && password) {
const v = new Validator()
const template = parsePostData(params.template)
const valSchema = v.validate(template, action)
if (valSchema.valid) {
const config = {
method: POST,
path: '/service_template/{0}/action',
user,
password,
request: params.id,
post: template
}
oneFlowConection(config, success, error)
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
)
next()
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid action or id'
)
next()
}
}
const serviceTemplateApi = {
serviceTemplate,
serviceTemplateDelete,
serviceTemplateCreate,
serviceTemplateUpdate,
serviceTemplateAction
}
module.exports = serviceTemplateApi

View File

@ -12,199 +12,87 @@
/* See the License for the specific language governing permissions and */
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const { Validator } = require('jsonschema');
const { conectionOneFlow } = require('./functions');
const { role, service, action } = require('./schemas');
const { httpMethod } = require('server/utils/constants/defaults');
const { from: fromData } = require('server/utils/constants/defaults');
const { httpResponse } = require('server/utils/server');
const { httpMethod, from: fromData } = require('server/utils/constants/defaults')
const { getParamsForObject } = require('server/utils/server')
const {
methodNotAllowed,
internalServerError
} = require('server/utils/constants/http-codes');
const { parsePostData, returnSchemaError } = require('./functions');
const { GET, POST, DELETE, PUT } = httpMethod;
const serviceTemplate = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
req[fromData.resource] &&
req[fromData.resource].method
) {
conectionOneFlow(res, next, GET, user, `/service_template/{0}`, [
req[fromData.resource].method
]);
} else {
conectionOneFlow(res, next, GET, user, '/service_template');
}
} else {
next();
}
};
const serviceTemplateDelete = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.resource &&
req[fromData.resource] &&
req[fromData.resource].method
) {
conectionOneFlow(res, next, DELETE, user, `/service_template/{0}`, [
req[fromData.resource].method
]);
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid id service'
);
next();
}
} else {
next();
}
};
const serviceTemplateCreate = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (req && fromData && fromData.postBody && req[fromData.postBody]) {
const postService = parsePostData(req[fromData.postBody]);
const v = new Validator();
v.addSchema(role, '/Role');
const valSchema = v.validate(postService, service);
if (valSchema.valid) {
conectionOneFlow(
res,
next,
POST,
user,
`/service_template`,
'',
postService
);
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
);
next();
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid service json'
);
next();
}
} else {
next();
}
};
const serviceTemplateUpdate = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.postBody &&
fromData.resource &&
req[fromData.postBody] &&
req[fromData.resource] &&
req[fromData.resource].method
) {
const postService = parsePostData(req[fromData.postBody]);
const v = new Validator();
v.addSchema(role, '/Role');
const valSchema = v.validate(postService, service);
if (valSchema.valid) {
conectionOneFlow(
res,
next,
PUT,
user,
`/service_template/{0}`,
[req[fromData.resource].method],
postService
);
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
);
next();
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid service json or id'
);
next();
}
} else {
next();
}
};
const serviceTemplateAction = (req, res, next, connect, zone, user) => {
if (req && res && user && next) {
if (
req &&
fromData &&
fromData.postBody &&
fromData.resource &&
req[fromData.postBody] &&
req[fromData.resource] &&
req[fromData.resource].method
) {
const postAction = parsePostData(req[fromData.postBody]);
const v = new Validator();
const valSchema = v.validate(postAction, action);
if (valSchema.valid) {
conectionOneFlow(
res,
next,
POST,
user,
`/service_template/{0}/action`,
[req[fromData.resource].method],
postAction
);
} else {
res.locals.httpCode = httpResponse(
internalServerError,
'',
`invalid schema ${returnSchemaError(valSchema.errors)}`
);
next();
}
} else {
res.locals.httpCode = httpResponse(
methodNotAllowed,
'',
'invalid action or id'
);
next();
}
} else {
next();
}
};
const serviceTemplateApi = {
serviceTemplate,
serviceTemplateDelete,
serviceTemplateCreate,
serviceTemplateUpdate,
serviceTemplateAction
};
module.exports = serviceTemplateApi;
} = require('./service_template-functions')
const { GET, POST, DELETE, PUT } = httpMethod
const routes = {
[GET]: {
list: {
action: serviceTemplate,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[POST]: {
create: {
action: serviceTemplateCreate,
params: {
template: { from: fromData.postBody, front: true }
}
},
action: {
action: serviceTemplateAction,
params: {
id: { from: fromData.resource, name: 'id', front: true },
template: { from: fromData.postBody, front: true }
}
}
},
[PUT]: {
update: {
action: serviceTemplateUpdate,
params: {
id: { from: fromData.resource, name: 'id', front: true },
template: { from: fromData.postBody, front: true }
}
}
},
[DELETE]: {
delete: {
action: serviceTemplateDelete,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
}
}
const main = (req = {}, res = {}, next = () => undefined, routes = {}, user = {}, index = 0) => {
const resources = Object.keys(req[fromData.resource])
if (req && res && next && routes) {
const route = routes[`${req[fromData.resource][resources[index]]}`.toLowerCase()]
if (req && fromData && fromData.resource && req[fromData.resource] && route) {
if (Object.keys(route).length > 0 && route.constructor === Object) {
if (route.action && route.params && typeof route.action === 'function') {
const params = getParamsForObject(route.params, req)
route.action(res, next, params, user)
} else {
main(req, res, next, route, user, index + 1)
}
} else {
next()
}
} else {
next()
}
} else {
next()
}
}
const serviceTemplateApi = {
main,
routes
}
module.exports = serviceTemplateApi

View File

@ -13,20 +13,12 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const SERVICE = 'service';
const SERVICE_ACTION = 'service-action';
const SERVICE_SCALE = 'service-scale';
const SERVICE_ROLE_ACTION = 'service-role-action';
const SERVICE_TEMPLATE = 'service_template';
const SERVICE_TEMPLATE_ACTION = 'service_template-action';
const SERVICE = 'service'
const SERVICE_TEMPLATE = 'service_template'
const Actions = {
SERVICE,
SERVICE_ACTION,
SERVICE_SCALE,
SERVICE_ROLE_ACTION,
SERVICE_TEMPLATE,
SERVICE_TEMPLATE_ACTION
};
SERVICE_TEMPLATE
}
module.exports = Actions;
module.exports = Actions

View File

@ -0,0 +1,132 @@
/* Copyright 2002-2019, 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 { v4 } = require('uuid')
const { Document } = require('yaml')
const { writeFileSync, removeSync, readdirSync, statSync } = require('fs-extra')
const { spawnSync } = require('child_process')
const { messageTerminal } = require('server/utils/general')
const pathFiles = []
const getFiles = (dir = '', ext = '') => {
if (dir && ext) {
const exp = new RegExp('\\w*\\.' + ext + '+$\\b', 'gi')
try {
const files = readdirSync(dir)
files.forEach(file => {
const name = `${dir}/${file}`
if (statSync(name).isDirectory()) {
getFiles(name)
} else {
if (name.match(exp)) {
pathFiles.push(name)
}
}
})
} catch (error) {
const config = {
color: 'red',
message: 'Error: %s',
type: (error && error.message) || ''
}
messageTerminal(config)
}
}
return pathFiles
}
const createTemporalFile = (path = '', ext = '', content = '') => {
let rtn
const filename = `${path + v4().replace(/-/g, '').toUpperCase() + ext}`
try {
writeFileSync(filename, content)
rtn = filename
} catch (error) {
const config = {
color: 'red',
message: 'Error: %s',
type: (error && error.message) || ''
}
messageTerminal(config)
}
return rtn
}
const createYMLContent = (content = '') => {
let rtn
if (content) {
try {
const doc = new Document({})
doc.directivesEndMarker = true
doc.contents = content
rtn = doc
} catch (error) {
const config = {
color: 'red',
message: 'Error: %s',
type: (error && error.message) || ''
}
messageTerminal(config)
}
}
return rtn
}
const removeFile = (path = '') => {
if (path) {
try {
removeSync(path, { force: true })
} catch (error) {
const config = {
color: 'red',
message: 'Error: %s',
type: (error && error.message) || ''
}
messageTerminal(config)
}
}
}
const executeCommand = (command = '', resource = '') => {
const rsc = Array.isArray(resource) ? resource : [resource]
const rtn = { success: false, data: null }
const execute = spawnSync(command, [...rsc])
if (execute) {
if (execute.stdout) {
rtn.success = true
rtn.data = execute.stdout.toString()
}
if (execute.stderr && execute.stderr.length > 0) {
rtn.data = execute.stderr.toString()
const config = {
color: 'red',
message: 'Error command: %s',
type: execute.stderr.toString()
}
messageTerminal(config)
}
}
return rtn
}
const functionRoutes = {
createYMLContent,
executeCommand,
createTemporalFile,
removeFile,
getFiles
}
module.exports = functionRoutes

View File

@ -0,0 +1,55 @@
/* Copyright 2002-2019, 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 { main: provision, routes: provisionRoutes } = require('./provision')
const { main: provisionTemplate, routes: provisionTemplateRoutes } = require('./provision_template')
const { main: provider, routes: providerRoutes } = require('./provider')
const { PROVIDER, PROVISION, PROVISION_TEMPLATE } = require('./string-routes')
const privateRoutes = []
const publicRoutes = []
const fillRoute = (method, endpoint, action) => ({
httpMethod: method,
endpoint,
action
})
const fillPrivateRoutes = (methods = {}, path = '', action = () => undefined) => {
if (Object.keys(methods).length > 0 && methods.constructor === Object) {
Object.keys(methods).forEach((method) => {
privateRoutes.push(
fillRoute(method, path,
(req, res, next, conection, userId, user) => {
action(req, res, next, methods[method], user)
})
)
})
}
}
const generatePrivateRoutes = () => {
fillPrivateRoutes(provisionRoutes, PROVISION, provision)
fillPrivateRoutes(provisionTemplateRoutes, PROVISION_TEMPLATE, provisionTemplate)
fillPrivateRoutes(providerRoutes, PROVIDER, provider)
return privateRoutes
}
const functionRoutes = {
private: generatePrivateRoutes(),
public: publicRoutes
}
module.exports = functionRoutes

View File

@ -0,0 +1,113 @@
/* Copyright 2002-2019, 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 { parse } = require('yaml')
const { Validator } = require('jsonschema')
const { readdirSync } = require('fs-extra')
const {
ok,
internalServerError
} = require('server/utils/constants/http-codes')
const { httpResponse, existsFile, parsePostData } = require('server/utils/server')
const { executeCommand, getFiles } = require('./functions')
const { provision } = require('./schemas')
const httpInternalError = httpResponse(internalServerError, '', '')
const command = 'oneprovider'
const getListProviders = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (user && password) {
const authCommand = ['--user', user, '--password', password]
let paramsCommand = ['list', ...authCommand, '--json']
if (params && params.id) {
paramsCommand = ['show', `${params.id}`.toLowerCase(), ...authCommand, '--json']
}
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const getProvidersTemplates = (res = {}, next = () => undefined, params = {}, userData = {}) => {
let rtn = httpInternalError
try {
const files = []
getFiles(`${global.CPI}/providers`, 'yaml').map(file =>
existsFile(file, content => files.push(parse(content)))
)
rtn = httpResponse(ok, files)
} catch (error) {
rtn = httpResponse(internalServerError, '', error)
}
res.locals.httpCode = rtn
next()
}
const createProviders = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const authCommand = ['--user', user, '--password', password]
const rtn = httpInternalError
res.locals.httpCode = rtn
next()
}
const updateProviders = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const authCommand = ['--user', user, '--password', password]
const rtn = httpInternalError
res.locals.httpCode = rtn
next()
}
const deleteProvider = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['delete', `${params.id}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const providerFunctionsApi = {
getListProviders,
getProvidersTemplates,
createProviders,
updateProviders,
deleteProvider
}
module.exports = providerFunctionsApi

View File

@ -0,0 +1,96 @@
/* Copyright 2002-2019, 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 { from: fromData } = require('server/utils/constants/defaults')
const { getParamsForObject } = require('server/utils/server')
const {
getListProviders,
getProvidersTemplates,
createProviders,
updateProviders,
deleteProvider
} = require('./provider-functions')
const { httpMethod } = require('server/utils/constants/defaults')
const { GET, POST, PUT, DELETE } = httpMethod
const routes = {
[GET]: {
list: {
action: getListProviders, // oneprovider list || show // creados en opennebula
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
},
template: {
action: getProvidersTemplates, // leer los archivos yamls (todos) en caso de pasar el id se lee la info de uno
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[POST]: {
create: {
action: createProviders, // oneprovider create // yaml
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[PUT]: {
update: {
action: updateProviders, // oneprovider update //yaml
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[DELETE]: {
delete: {
action: deleteProvider, // oneprivider update //yaml
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
}
}
const main = (req = {}, res = {}, next = () => undefined, routes = {}, user = {}, index = 0) => {
const resources = Object.keys(req[fromData.resource])
if (req && res && next && routes) {
const route = routes[`${req[fromData.resource][resources[index]]}`.toLowerCase()]
if (req && fromData && fromData.resource && req[fromData.resource] && route) {
if (Object.keys(route).length > 0 && route.constructor === Object) {
if (route.action && route.params && typeof route.action === 'function') {
const params = getParamsForObject(route.params, req)
route.action(res, next, params, user)
} else {
main(req, res, next, route, user, index + 1)
}
} else {
next()
}
} else {
next()
}
} else {
next()
}
}
const providerApi = {
main,
routes
}
module.exports = providerApi

View File

@ -0,0 +1,241 @@
/* Copyright 2002-2019, 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 { Validator } = require('jsonschema')
const {
ok,
internalServerError
} = require('server/utils/constants/http-codes')
const { httpResponse, parsePostData } = require('server/utils/server')
const { executeCommand, createTemporalFile, createYMLContent, removeFile } = require('./functions')
const { provision } = require('./schemas')
const httpInternalError = httpResponse(internalServerError, '', '')
const command = 'oneprovision'
const getList = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.resource && user && password) {
const authCommand = ['--user', user, '--password', password]
const executedCommand = executeCommand(command, [`${params.resource}`.toLowerCase(), 'list', ...authCommand, '--json'])
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const getListProvisions = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (user && password) {
const authCommand = ['--user', user, '--password', password]
let paramsCommand = ['list', ...authCommand, '--json']
if (params && params.id) {
paramsCommand = ['show', `${params.id}`.toLowerCase(), ...authCommand, '--json']
}
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const deleteResource = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.resource && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = [`${params.resource}`.toLowerCase(), 'delete', `${params.id}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const deleteProvision = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['delete', `${params.id}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const hostCommand = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.action && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['host', `${params.action}`.toLowerCase(), `${params.id}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const hostCommandSSH = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.action && params.id && params.command && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['host', `${params.action}`.toLowerCase(), `${params.id}`.toLowerCase(), `${params.command}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const createProvision = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const authCommand = ['--user', user, '--password', password]
const rtn = httpInternalError
res.locals.httpCode = rtn // debe de ser un websocket
next()
}
const configureProvision = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const authCommand = ['--user', user, '--password', password]
const rtn = httpInternalError
res.locals.httpCode = rtn // debe de ser un websocket
next()
}
const configureHost = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['host', 'configure', `${params.id}`.toLowerCase(), '--debug', '--fail_cleanup', '--batch', ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const validate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.resource && user && password) {
const authCommand = ['--user', user, '--password', password]
const schemaValidator = new Validator()
const resource = parsePostData(params.resource)
const valSchema = schemaValidator.validate(resource, provision)
if (valSchema.valid) {
const content = createYMLContent(resource)
if (content) {
const tmpPath = '/var/tmp/'
const ext = '.yaml'
const file = createTemporalFile(tmpPath, ext, content)
if (file) {
const paramsCommand = ['validate', file, ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
let response = internalServerError
if (executedCommand && executedCommand.success) {
response = ok
removeFile(file)
}
res.locals.httpCode = httpResponse(response)
next()
return
}
}
} else {
const errors = []
if (valSchema && valSchema.errors) {
valSchema.errors.forEach(error => {
console.log('-->', error)
errors.push(error.stack.replace(/^instance./, ''))
})
rtn = httpResponse(internalServerError, '', errors.toString())
}
}
}
res.locals.httpCode = rtn
next()
}
const provisionFunctionsApi = {
getList,
getListProvisions,
deleteResource,
deleteProvision,
hostCommand,
hostCommandSSH,
createProvision,
configureProvision,
configureHost,
validate
}
module.exports = provisionFunctionsApi

View File

@ -0,0 +1,237 @@
/* Copyright 2002-2019, 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 { httpMethod, from: fromData } = require('server/utils/constants/defaults')
const { getParamsForObject } = require('server/utils/server')
const {
getList,
getListProvisions,
deleteResource,
deleteProvision,
hostCommand,
hostCommandSSH,
createProvision,
configureProvision,
configureHost,
validate
} = require('./provision-functions')
const { GET, POST, DELETE, PUT } = httpMethod
const routes = {
[GET]: {
list: {
action: getListProvisions,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
},
cluster: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
},
datastore: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
},
host: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
},
image: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
},
network: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
},
template: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
},
vntemplate: {
action: getList,
params: {
resource: { from: fromData.resource, name: 'method' }
}
}
},
[POST]: {
create: { // create <config> --debug // este puede tardar Websocket //FALTA
action: createProvision, // el comando tiene que ser asincrono
params: {
resource: { from: fromData.resource, name: 'method' }
},
websocket: true
},
validate: {
action: validate,
params: {
resource: { from: fromData.postBody, front: true }
}
},
host: {
poweroff: {
action: hostCommand,
params: {
action: { from: fromData.resource, name: 'id' },
id: { from: fromData.resource, name: 'id2', front: true }
}
},
reboot: {
action: hostCommand,
params: {
action: { from: fromData.resource, name: 'id' },
id: { from: fromData.resource, name: 'id2', front: true }
}
},
resume: {
action: hostCommand,
params: {
action: { from: fromData.resource, name: 'id' },
id: { from: fromData.resource, name: 'id2', front: true }
}
},
ssh: {
action: hostCommandSSH,
params: {
action: { from: fromData.resource, name: 'id' },
id: { from: fromData.resource, name: 'id2', front: true },
command: { from: fromData.postBody, name: 'command', front: true }
}
}
}
},
[DELETE]: {
delete: { // este puede tardar Websocket //FALTA
action: deleteProvision, // el comando tiene que ser asincrono
params: {
id: { from: fromData.resource, name: 'id', front: true }
},
websocket: true
},
datastore: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
flowtemplate: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
host: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
image: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
network: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
vntemplate: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
template: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
},
cluster: {
action: deleteResource,
params: {
resource: { from: fromData.resource, name: 'method' },
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[PUT]: {
configure: { // configure <provisionid> //--debug, --fail_cleanup, --batch // este puede tardar Websocket //FALTA
action: configureProvision, // el comando tiene que ser asincrono
params: {
resource: { from: fromData.resource, name: 'method' }
},
websocket: true
},
host: {
action: configureHost,
params: {
id: { from: fromData.resource, name: 'id' }
}
}
}
}
const main = (req = {}, res = {}, next = () => undefined, routes = {}, user = {}, index = 0) => {
const resources = Object.keys(req[fromData.resource])
if (req && res && next && routes) {
const route = routes[`${req[fromData.resource][resources[index]]}`.toLowerCase()]
if (req && fromData && fromData.resource && req[fromData.resource] && route) {
if (Object.keys(route).length > 0 && route.constructor === Object) {
if (route.action && route.params && typeof route.action === 'function') {
const params = getParamsForObject(route.params, req)
route.action(res, next, params, user)
} else {
main(req, res, next, route, user, index + 1)
}
} else {
next()
}
} else {
next()
}
} else {
next()
}
}
const provisionApi = {
main,
routes
}
module.exports = provisionApi

View File

@ -0,0 +1,115 @@
/* Copyright 2002-2019, 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 { Validator } = require('jsonschema')
const {
ok,
internalServerError
} = require('server/utils/constants/http-codes')
const { httpResponse, parsePostData } = require('server/utils/server')
const { executeCommand } = require('./functions')
const { provision } = require('./schemas')
const httpInternalError = httpResponse(internalServerError, '', '')
const command = 'oneprovision-template'
const getListProvisionTemplates = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (user && password) {
const authCommand = ['--user', user, '--password', password]
let paramsCommand = ['list', ...authCommand, '--json']
if (params && params.id) {
paramsCommand = ['show', `${params.id}`.toLowerCase(), ...authCommand, '--json']
}
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const createProvisionTemplate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const authCommand = ['--user', user, '--password', password]
const rtn = httpInternalError
res.locals.httpCode = rtn
next()
}
const instantiateProvisionTemplate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['instantiate', `${params.id}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const updateProvisionTemplate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
const authCommand = ['--user', user, '--password', password]
const rtn = httpInternalError
res.locals.httpCode = rtn
next()
}
const deleteProvisionTemplate = (res = {}, next = () => undefined, params = {}, userData = {}) => {
const { user, password } = userData
let rtn = httpInternalError
if (params && params.id && user && password) {
const authCommand = ['--user', user, '--password', password]
const paramsCommand = ['delete', `${params.id}`.toLowerCase(), ...authCommand]
const executedCommand = executeCommand(command, paramsCommand)
try {
const response = executedCommand.success ? ok : internalServerError
res.locals.httpCode = httpResponse(response, JSON.parse(executedCommand.data))
next()
return
} catch (error) {
rtn = httpResponse(internalServerError, '', executedCommand.data)
}
}
res.locals.httpCode = rtn
next()
}
const provisionTemplateFunctionsApi = {
getListProvisionTemplates,
createProvisionTemplate,
instantiateProvisionTemplate,
updateProvisionTemplate,
deleteProvisionTemplate
}
module.exports = provisionTemplateFunctionsApi

View File

@ -0,0 +1,96 @@
/* Copyright 2002-2019, 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 { from: fromData } = require('server/utils/constants/defaults')
const { getParamsForObject } = require('server/utils/server')
const {
getListProvisionTemplates,
createProvisionTemplate,
instantiateProvisionTemplate,
updateProvisionTemplate,
deleteProvisionTemplate
} = require('./provision_template-functions')
const { httpMethod } = require('server/utils/constants/defaults')
const { GET, POST, PUT, DELETE } = httpMethod
const routes = {
[GET]: {
list: {
action: getListProvisionTemplates,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[POST]: {
create: {
action: createProvisionTemplate,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
},
instantiate: {
action: instantiateProvisionTemplate,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[PUT]: {
update: {
action: updateProvisionTemplate,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
},
[DELETE]: {
delete: {
action: deleteProvisionTemplate,
params: {
id: { from: fromData.resource, name: 'id', front: true }
}
}
}
}
const main = (req = {}, res = {}, next = () => undefined, routes = {}, user = {}, index = 0) => {
const resources = Object.keys(req[fromData.resource])
if (req && res && next && routes) {
const route = routes[`${req[fromData.resource][resources[index]]}`.toLowerCase()]
if (req && fromData && fromData.resource && req[fromData.resource] && route) {
if (Object.keys(route).length > 0 && route.constructor === Object) {
if (route.action && route.params && typeof route.action === 'function') {
const params = getParamsForObject(route.params, req)
route.action(res, next, params, user)
} else {
main(req, res, next, route, user, index + 1)
}
} else {
next()
}
} else {
next()
}
} else {
next()
}
}
const provisionTemplateApi = {
main,
routes
}
module.exports = provisionTemplateApi

View File

@ -0,0 +1,167 @@
/* Copyright 2002-2019, 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 provision = {
id: '/Provision',
type: 'object',
properties: {
name: {
type: 'string',
required: true
},
defaults: {
type: 'object',
required: true,
properties: {
provision: {
type: 'object',
properties: {
driver: {
type: 'string'
},
packet_token: {
type: 'string',
required: true
},
packet_project: {
type: 'string',
required: true
},
facility: {
type: 'string',
required: true
},
plan: {
type: 'string',
required: true
},
os: {
type: 'string'
}
}
},
configuration: {
type: 'object'
}
}
},
hosts: {
type: 'array',
required: true,
items: {
type: 'object',
properties: {
reserved_cpu: {
type: 'integer',
required: true
},
im_mad: {
type: 'string',
enum: ['kvm', 'firecraker'],
required: true
},
vm_mad: {
type: 'string',
enum: ['kvm', 'firecraker'],
required: true
},
provision: {
type: 'object',
properties: {
hostname: {
type: 'string',
required: true
},
os: {
type: 'string',
required: true
}
},
required: true
}
}
}
},
datastores: {
type: 'array',
required: true,
items: {
type: 'object',
properties: {
name: {
type: 'string',
required: false
},
type: {
type: 'string',
required: false
},
tm_mad: {
type: 'string',
required: false
}
}
}
},
networks: {
type: 'array',
required: true,
items: {
name: {
type: 'string',
required: false
},
vn_mad: {
type: 'string',
required: false
},
bridge: {
type: 'string',
required: false
},
description: {
type: 'string',
required: false
},
ar: {
type: 'array',
items: {
type: 'object',
properties: {
ip: {
type: 'string',
required: true
},
size: {
type: 'integer',
required: true
},
type: {
type: 'string',
required: true
}
}
},
required: false
}
}
}
}
}
const schemas = {
provision
}
module.exports = schemas

View File

@ -0,0 +1,26 @@
/* Copyright 2002-2019, 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 PROVIDER = 'provider'
const PROVISION = 'provision'
const PROVISION_TEMPLATE = 'provision-template'
const Actions = {
PROVIDER,
PROVISION,
PROVISION_TEMPLATE
}
module.exports = Actions

View File

@ -31,7 +31,7 @@ const {
} = require('../../utils')
const {
validateResource,
validateResourceAndSession,
optionalParameters,
optionalQueries,
clearStates,
@ -63,7 +63,7 @@ const paramsToRoutes = () =>
router.all(
paramsToRoutes(),
[validateResource, optionalParameters, optionalQueries],
[validateResourceAndSession, optionalParameters, optionalQueries],
(req, res, next) => {
const { internalServerError, ok, methodNotAllowed } = httpCodes
const { method: httpMethod } = req
@ -96,7 +96,7 @@ router.all(
next,
connectOpennebula,
getIdUserOpennebula(),
`${getUserOpennebula()}:${getPassOpennebula()}`
{ user: getUserOpennebula(), password: getPassOpennebula() }
)
} else {
next()

View File

@ -8,7 +8,7 @@ const thunk = require('redux-thunk').default
const { ServerStyleSheets } = require('@material-ui/core/styles')
const rootReducer = require('client/reducers')
const { getConfig } = require('server/utils/yml')
const { availableLanguages } = require('server/utils/constants/defaults') // '../../utils/constants/defaults'
const { availableLanguages, defaultWebpackMode } = require('server/utils/constants/defaults')
// settings
const appConfig = getConfig()
@ -32,12 +32,10 @@ router.get('*', (req, res) => {
let css = ''
let storeRender = ''
let chunks = ''
if (env.NODE_ENV === 'production') {
if (env && (!env.NODE_ENV || (env.NODE_ENV && env.NODE_ENV !== defaultWebpackMode))) {
app = req.url.split(/\//gi).filter(sub => sub && sub.length > 0)[0]
chunks = `<script src='/client/1.bundle.${app}.js'></script>`
}
if (env && env.NODE_ENV === 'production') {
const composeEnhancer =
// eslint-disable-next-line no-underscore-dangle
(root && root.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__) || compose

View File

@ -18,13 +18,14 @@ const {
private: authenticated,
public: nonAuthenticated
} = require('../../../api')
const { httpCodes, params } = require('server/utils/constants')
const { httpCodes, params, defaults } = require('server/utils/constants')
const {
validateAuth,
getAllowedQueryParams,
createParamsState,
createQueriesState
} = require('server/utils')
const { defaultWebpackMode } = defaults
const defaultParams = Map(createParamsState())
const defaultQueries = Map(createQueriesState())
@ -41,7 +42,7 @@ const getIdUserOpennebula = () => idUserOpennebula
const getUserOpennebula = () => userOpennebula
const getPassOpennebula = () => passOpennebula
const validateResource = (req, res, next) => {
const validateResourceAndSession = (req, res, next) => {
const { badRequest, unauthorized, serviceUnavailable } = httpCodes
let status = badRequest
if (req && req.params && req.params.resource) {
@ -51,18 +52,11 @@ const validateResource = (req, res, next) => {
rtnCommand && rtnCommand.endpoint && rtnCommand.endpoint === resource
if (authenticated.some(finderCommand)) {
const session = validateAuth(req)
if (
session &&
'iss' in session &&
'aud' in session &&
'jti' in session &&
'iat' in session &&
'exp' in session
) {
if (session) {
idUserOpennebula = session.iss
userOpennebula = session.aud
passOpennebula = session.jti
if (env.NODE_ENV === 'production') {
if (env && (!env.NODE_ENV || env.NODE_ENV !== defaultWebpackMode)) {
if (
global &&
global.users &&
@ -145,7 +139,7 @@ const clearStates = () => {
}
module.exports = {
validateResource,
validateResourceAndSession,
optionalParameters,
optionalQueries,
clearStates,

View File

@ -13,7 +13,7 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const {
validateResource,
validateResourceAndSession,
optionalParameters,
optionalQueries,
clearStates,
@ -25,7 +25,7 @@ const {
} = require('./api');
module.exports = {
validateResource,
validateResourceAndSession,
optionalParameters,
optionalQueries,
clearStates,

View File

@ -13,5 +13,5 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const params = ['method', 'id', 'federation'];
module.exports = params;
const params = ['method', 'id', 'id2']
module.exports = params

View File

@ -13,32 +13,32 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const colors = require('colors');
const colors = require('colors')
const messageTerminal = ({ color, type, error, message }) => {
const colorConsole = color || 'red';
const typeConsole = type || '';
const errorConsole = error || '';
const messageConsole = message || 'Message Console ';
const colorConsole = color || 'red'
const typeConsole = type || ''
const errorConsole = error || ''
const messageConsole = message || 'Message Console '
const consoleColor =
colorConsole === 'green'
? colors.green(messageConsole)
: colors.red(messageConsole);
console.log(consoleColor, typeConsole, errorConsole);
};
: colors.red(messageConsole)
console.log(consoleColor, typeConsole, errorConsole)
}
const addPrintf = (string = '', args = '') => {
let rtn = string;
let rtn = string
if (string && args) {
const replacers = Array.isArray(args) ? args : [args];
const replacers = Array.isArray(args) ? args : [args]
rtn = string.replace(/{(\d+)}/g, (match, number) =>
typeof replacers[number] !== 'undefined' ? replacers[number] : match
);
)
}
return rtn;
};
return rtn
}
module.exports = {
messageTerminal,
addPrintf
};
}

View File

@ -67,7 +67,7 @@ const validateAuth = req => {
const config = {
color: 'red',
type: 'ERROR',
error: error.message || "",
error: (error && error.message) || '',
message: 'Error: %s'
}
messageTerminal(config)

View File

@ -119,7 +119,7 @@ const opennebulaConnect = (username = '', password = '', path = '') => {
return
}
}
callback(err.message, value && value[1]) // error call opennebula
callback(err && err.message, value && value[1]) // error call opennebula
}
)
}

View File

@ -25,7 +25,8 @@ const {
defaultVarPath,
defaultKeyFilename,
defaultWebpackMode,
defaultOpennebulaZones
defaultOpennebulaZones,
defaultEtcPath
} = require('./constants/defaults')
let cert = ''
@ -33,7 +34,7 @@ let key = ''
const validateServerIsSecure = () => {
const folder = '../cert/'
const path = process && process.env && process.env.NODE_ENV === defaultWebpackMode ? `${__dirname}/../../${folder}` : `${__dirname}/${folder}`
const path = env && env.NODE_ENV === defaultWebpackMode ? `${__dirname}/../../${folder}` : `${__dirname}/${folder}`
cert = `${path}cert.pem`
key = `${path}key.pem`
return existsSync && key && cert && existsSync(key) && existsSync(cert)
@ -132,6 +133,7 @@ const genPathResources = () => {
const ONE_LOCATION = env && env.ONE_LOCATION
const LOG_LOCATION = !ONE_LOCATION ? defaultLogPath : `${ONE_LOCATION}/var`
const VAR_LOCATION = !ONE_LOCATION ? defaultVarPath : `${ONE_LOCATION}/var`
const ETC_LOCATION = !ONE_LOCATION ? defaultEtcPath : `${ONE_LOCATION}/etc`
const VMRC_LOCATION = !ONE_LOCATION ? defaultVarPath : ONE_LOCATION
if (global) {
@ -144,9 +146,41 @@ const genPathResources = () => {
if (!global.FIREEDGE_KEY_PATH) {
global.FIREEDGE_KEY_PATH = `${VAR_LOCATION}/.one/${defaultKeyFilename}`
}
if (!global.CPI) {
global.CPI = `${ETC_LOCATION}/fireedge`
}
}
}
const getParamsForObject = (params = {}, req = {}) => {
const rtn = {}
if (params && Object.keys(params).length > 0 && params.constructor === Object) {
Object.entries(params).forEach(([param, value]) => {
if (param && value && value.from && req[value.from]) {
rtn[param] = value.name ? req[value.from][value.name] : req[value.from]
}
})
}
return rtn
}
const parsePostData = (postData = {}) => {
const rtn = {}
Object.entries(postData).forEach(([key, value]) => {
try {
rtn[key] = JSON.parse(value, (k, val) => {
try {
return JSON.parse(val)
} catch (error) {
return val
}
})
} catch (error) {
rtn[key] = value
}
})
return rtn
}
module.exports = {
getDataZone,
existsFile,
@ -156,5 +190,7 @@ module.exports = {
genPathResources,
genFireedgeKey,
getCert,
getKey
getKey,
parsePostData,
getParamsForObject
}

View File

@ -13,6 +13,7 @@
/* limitations under the License. */
/* -------------------------------------------------------------------------- */
const { env } = require('process')
const { parse } = require('yaml')
const { defaultConfigFile, defaultWebpackMode } = require('./constants/defaults')
const { existsFile } = require('server/utils/server')
@ -20,7 +21,7 @@ const { messageTerminal } = require('server/utils/general')
const getConfig = () => {
let rtn = {}
const path = process && process.env && process.env.NODE_ENV === defaultWebpackMode ? `${__dirname}/../../../` : `${__dirname}/`
const path = env && env.NODE_ENV === defaultWebpackMode ? `${__dirname}/../../../` : `${__dirname}/`
existsFile(path + defaultConfigFile, filedata => {
rtn = parse(filedata)
}, err => {