From 58a37ca1e5007c2ed29a9a6dc5836972c175c831 Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Tue, 30 Oct 2018 20:30:10 +0300 Subject: [PATCH 01/91] Epankou/feature microservice cli (#294) * microservice validation refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * cli microservice wip * cli microservice wip * microservices cli wip * cli microservices final * microservice cli refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js --- src/cli/microservice.js | 179 +++++++++++++------------ src/helpers/constants.js | 7 +- src/sequelize/managers/flow-manager.js | 18 +++ src/services/flow-service.js | 102 +++++++------- src/services/microservices-service.js | 19 ++- 5 files changed, 172 insertions(+), 153 deletions(-) diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 0b9895f8d..735af77d6 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -80,7 +80,8 @@ class Microservice extends BaseCLIHandler { }, { name: 'microservice-id', alias: 'i', type: String, description: 'Microservice ID', - group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PORT_MAPPING] + group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PORT_MAPPING_CREATE, + constants.CMD_PORT_MAPPING_REMOVE, constants.CMD_PORT_MAPPING_LIST] }, { name: 'name', alias: 'n', type: String, description: 'Microservice name', @@ -123,28 +124,20 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_ADD] }, { - name: 'routes', alias: 't', type: String, description: 'Microservice route(s) (receiving microservices)', multiple: true, - group: [constants.CMD_ADD] - }, - { - name: 'add', alias: 'a', type: String, description: 'Add new route(s)', - group: [constants.CMD_ROUTE] - }, - { - name: 'remove', alias: 'm', type: String, description: 'Delete existing route(s)', - group: [constants.CMD_ROUTE] + name: 'mapping', alias: 'P', type: String, description: 'Container port mapping', + group: [constants.CMD_PORT_MAPPING_CREATE] }, { - name: 'create', alias: 'b', type: String, description: 'Add new port mapping(s)', - group: [constants.CMD_PORT_MAPPING] + name: 'routes', alias: 't', type: String, description: 'Microservice route(s) (receiving microservices)', multiple: true, + group: [constants.CMD_ADD] }, { - name: 'delete', alias: 'B', type: String, description: 'Delete existing port mapping(s)', - group: [constants.CMD_PORT_MAPPING] + name: 'route', alias: 'T', type: String, description: 'Microservice route (receiving microservices)', + group: [constants.CMD_ROUTE_CREATE, constants.CMD_ROUTE_REMOVE] }, { - name: 'list', alias: 'G', type: Boolean, description: 'List port mappings', - group: [constants.CMD_PORT_MAPPING] + name: 'internal-port', alias: 'b', type: String, description: 'Internal port', + group: [constants.CMD_PORT_MAPPING_REMOVE] }, { name: 'rebuild', alias: 'w', type: Boolean, description: 'Rebuild microservice image on fog agent', @@ -165,8 +158,11 @@ class Microservice extends BaseCLIHandler { [constants.CMD_REMOVE]: 'Delete a microservice.', [constants.CMD_LIST]: 'List all microservices.', [constants.CMD_INFO]: 'Get microservice settings.', - [constants.CMD_ROUTE]: 'Add/Remove microservice route.', - [constants.CMD_PORT_MAPPING]: 'Create/Delete/List microservice port mapping.' + [constants.CMD_ROUTE_CREATE]: 'Create microservice route.', + [constants.CMD_ROUTE_REMOVE]: 'Remove microservice route.', + [constants.CMD_PORT_MAPPING_CREATE]: 'Create microservice port mapping.', + [constants.CMD_PORT_MAPPING_REMOVE]: 'Remove microservice port mapping.', + [constants.CMD_PORT_MAPPING_LIST]: 'List microservice port mapping.' } } @@ -175,25 +171,34 @@ class Microservice extends BaseCLIHandler { switch (microserviceCommand.command.command) { case constants.CMD_ADD: - await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice, false); + await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice); break; case constants.CMD_UPDATE: - await _executeCase(microserviceCommand, constants.CMD_UPDATE, _updateMicroservice, false); + await _executeCase(microserviceCommand, constants.CMD_UPDATE, _updateMicroservice); break; case constants.CMD_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_REMOVE, _removeMicroservice, false); + await _executeCase(microserviceCommand, constants.CMD_REMOVE, _removeMicroservice); break; case constants.CMD_LIST: - await _executeCase(microserviceCommand, constants.CMD_LIST, _listMicroservices, false); + await _executeCase(microserviceCommand, constants.CMD_LIST, _listMicroservices); break; case constants.CMD_INFO: - await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice, false); + await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice); + break; + case constants.CMD_ROUTE_CREATE: + await _executeCase(microserviceCommand, constants.CMD_ROUTE_CREATE, _createRoute); + break; + case constants.CMD_ROUTE_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_ROUTE_REMOVE, _removeRoute); break; - case constants.CMD_ROUTE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE, _executeRouteCommand, false); + case constants.CMD_PORT_MAPPING_CREATE: + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_CREATE, _createPortMapping); break; - case constants.CMD_PORT_MAPPING: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING, _executePortMappingCommand, false); + case constants.CMD_PORT_MAPPING_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_REMOVE, _removePortMapping); + break; + case constants.CMD_PORT_MAPPING_LIST: + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_LIST, _listPortMappings); break; case constants.CMD_HELP: default: @@ -229,24 +234,28 @@ class Microservice extends BaseCLIHandler { example: '$ iofog-controller microservice add [other required options] --volumes /host_src:/container_src /host_bin:/container_bin', }, { - desc: '3. Port mapping (internal:external:publicMode)', + desc: '3. Port mapping (80:8080:false - internal port : external port : public mode)', example: '$ iofog-controller microservice add [other required options] --ports 80:8080:false 443:5443:false', }, { - desc: '4. Add routes (sourceMicroserviceId:destMicroserviceId)', - example: '$ iofog-controller microservice route --add ABC:DEF', + desc: '4. Add routes (ABC:DEF - source microservice id : dest microservice id)', + example: '$ iofog-controller microservice add [other required options] --routes ABC:DEF RFG:HJK' + }, + { + desc: '4. Add route (ABC:DEF - source microservice id : dest microservice id)', + example: '$ iofog-controller microservice route-create --route ABC:DEF', }, { - desc: '5. Delete route (sourceMicroserviceId:destMicroserviceId)', - example: '$ iofog-controller microservice route --remove ABC:DEF', + desc: '5. Delete route (ABC:DEF - source microservice id : dest microservice id)', + example: '$ iofog-controller microservice route-remove --route ABC:DEF', }, { - desc: '6. Create port mapping (internal:external:publicMode)', - example: '$ iofog-controller microservice port-mapping --create 80:8080:false -i ABC' + desc: '6. Create port mapping (80:8080:false - internal port : external port : public mode, ABC - microservice)', + example: '$ iofog-controller microservice port-mapping-create --mapping 80:8080:false -i ABC' }, { - desc: '7. Delete port mapping (internal)', - example: '$ iofog-controller microservice port-mapping --delete 80 -i ABC' + desc: '7. Delete port mapping (80 - internal port, ABC - microservice id)', + example: '$ iofog-controller microservice port-mapping-remove --internal-port 80 -i ABC' } ], }, @@ -254,75 +263,67 @@ class Microservice extends BaseCLIHandler { } } -const _executeCase = async function (microserviceCommand, commandName, f, isUserRequired) { +const _executeCase = async function (microserviceCommand, commandName, f) { try { const item = microserviceCommand[commandName] || {}; - - if (isUserRequired) { - const decoratedFunction = AuthDecorator.prepareUserById(f); - await decoratedFunction(item); - } else { - await f(item); - } + await f(item); } catch (error) { logger.error(error.message); } }; -const _executeRouteCommand = async function (obj) { +const _createRoute = async function (obj) { logger.info(JSON.stringify(obj)); - if (obj.add) { - try { - const arr = obj.add.split(':'); - const sourceMicroserviceId = arr[0]; - const destMicroserviceId = arr[1]; - await MicroserviceService.createRouteWithTransaction(sourceMicroserviceId, destMicroserviceId, {}, true); - logger.info(`Microservice route with source microservice ${sourceMicroserviceId} and dest microservice + try { + const arr = obj.route.split(':'); + const sourceMicroserviceId = arr[0]; + const destMicroserviceId = arr[1]; + await MicroserviceService.createRouteWithTransaction(sourceMicroserviceId, destMicroserviceId, {}, true); + logger.info(`Microservice route with source microservice ${sourceMicroserviceId} and dest microservice ${destMicroserviceId} has been created successfully.`) - } catch (e) { - logger.error(ErrorMessages.CLI.INVALID_ROUTE); - } - } else if (obj.remove) { - try { - const arr = obj.add.split(':'); - const sourceMicroserviceId = arr[0]; - const destMicroserviceId = arr[1]; - await MicroserviceService.deleteRouteWithTransaction(sourceMicroserviceId, destMicroserviceId, {}, true); - logger.info(`Microservice route with source microservice ${obj.sourceMicroserviceId} and dest microservice + } catch (e) { + logger.error(ErrorMessages.CLI.INVALID_ROUTE); + } +}; + +const _removeRoute = async function (obj) { + logger.info(JSON.stringify(obj)); + try { + const arr = obj.route.split(':'); + const sourceMicroserviceId = arr[0]; + const destMicroserviceId = arr[1]; + await MicroserviceService.deleteRouteWithTransaction(sourceMicroserviceId, destMicroserviceId, {}, true); + logger.info(`Microservice route with source microservice ${obj.sourceMicroserviceId} and dest microservice ${obj.destMicroserviceId} has been removed successfully.`); - } catch (e) { - logger.error(ErrorMessages.CLI.INVALID_ROUTE); - } - } else if (obj.add && obj.remove) { - logger.info('Please specify either "add" or "remove" operation'); - } else { - logger.info('No operation specified'); + } catch (e) { + logger.error(ErrorMessages.CLI.INVALID_ROUTE); } }; -const _executePortMappingCommand = async function (obj) { +const _createPortMapping = async function (obj) { logger.info(JSON.stringify(obj)); + const mapping = parsePortMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_PORT_MAPPING); + await MicroserviceService.createPortMappingWithTransaction(obj.microserviceId, mapping, {}, true); + logger.info('Port mapping has been create successfully'); +}; - if (obj.create) { - const mapping = parsePortMappingObject(obj.create, ErrorMessages.CLI.INVALID_PORT_MAPPING); - await MicroserviceService.createPortMappingWithTransaction(obj.microserviceId, mapping, {}, true); - logger.info('Port mapping has been create successfully'); - } else if (obj.delete) { - try { - const internalPort = parseInt(obj.delete); - await MicroserviceService.deletePortMappingWithTransaction(obj.microserviceId, internalPort, {}, true); - logger.info('Port mapping has been deleted successfully'); - } catch(e) { - logger.error(ErrorMessages.CLI.INVALID_INTERNAL_PORT); - } - } else if (obj.list) { - await MicroserviceService.getMicroservicePortMappingListWithTransaction(obj.microserviceId, {}, true); - logger.info('Port mappings have been retrieved successfully'); - } else { - logger.info('Incorrect command usage. Please specify only one command at once'); +const _removePortMapping = async function (obj) { + logger.info(JSON.stringify(obj)); + try { + const internalPort = parseInt(obj.internalPort); + await MicroserviceService.deletePortMappingWithTransaction(obj.microserviceId, internalPort, {}, true); + logger.info('Port mapping has been deleted successfully'); + } catch(e) { + logger.error(ErrorMessages.CLI.INVALID_INTERNAL_PORT); } }; +const _listPortMappings = async function (obj) { + const result = await MicroserviceService.getMicroservicePortMappingListWithTransaction(obj.microserviceId, {}, true); + logger.info(JSON.stringify(result)); + logger.info('Port mappings have been retrieved successfully'); +}; + const _removeMicroservice = async function (obj) { logger.info(JSON.stringify(obj)); await MicroserviceService.deleteMicroserviceWithTransaction(obj.microserviceId, obj.cleanUp, {}, true); @@ -331,7 +332,7 @@ const _removeMicroservice = async function (obj) { const _listMicroservices = async function () { const result = await MicroserviceService.listMicroservicesWithTransaction({}, {}, true); - logger.info(JSON.stringify(result, null, 2)); + logger.info(JSON.stringify(result)); logger.info('Microservices have been retrieved successfully.'); }; diff --git a/src/helpers/constants.js b/src/helpers/constants.js index 58964cbbe..3e7eee6d1 100644 --- a/src/helpers/constants.js +++ b/src/helpers/constants.js @@ -36,8 +36,11 @@ module.exports = { CMD_CATALOG: 'catalog', CMD_FLOW: 'flow', CMD_MICROSERVICE: 'microservice', - CMD_ROUTE: 'route', - CMD_PORT_MAPPING: 'port-mapping', + CMD_ROUTE_CREATE: 'route-create', + CMD_ROUTE_REMOVE: 'route-remove', + CMD_PORT_MAPPING_CREATE: 'port-mapping-create', + CMD_PORT_MAPPING_REMOVE: 'port-mapping-remove', + CMD_PORT_MAPPING_LIST: 'port-mapping-list', CMD_REGISTRY: 'registry', CMD_ACTIVATE: 'activate', CMD_SUSPEND: 'suspend', diff --git a/src/sequelize/managers/flow-manager.js b/src/sequelize/managers/flow-manager.js index d993044d3..798d9aa66 100644 --- a/src/sequelize/managers/flow-manager.js +++ b/src/sequelize/managers/flow-manager.js @@ -14,12 +14,30 @@ const BaseManager = require('./base-manager'); const models = require('./../models'); const Flow = models.Flow; +const Microservice = models.Microservice; +const sequelize = require('sequelize'); class FlowManager extends BaseManager { getEntity() { return Flow } + + async findFlowMicroservices(where, transaction) { + return Flow.findOne({ + include: [ + { + model: Microservice, + as: 'microservice', + required: false, + attributes: ['iofogUuid'] + } + ], + where: where, + attributes: ['id'] + }, {transaction: transaction}) + } } + const instance = new FlowManager(); module.exports = instance; \ No newline at end of file diff --git a/src/services/flow-service.js b/src/services/flow-service.js index aa70d1041..9bd5bca6e 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -17,13 +17,14 @@ const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Validation = require('../schemas'); -const MicroserviceService = require('./microservices-service') +// const MicroserviceService = require('./microservices-service') const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager') const _createFlow = async function (flowData, user, isCLI, transaction) { await Validation.validate(flowData, Validation.schemas.flowCreate); await isFlowExist(flowData.name, transaction); + await _checkForDuplicateName(flowData.name, {}, transaction); const flowToCreate = { name: flowData.name, @@ -56,65 +57,59 @@ const _deleteFlow = async function (flowId, user, isCLI, transaction) { }; const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) { - await Validation.validate(flowData, Validation.schemas.flowUpdate); + await Validation.validate(flowData, Validation.schemas.flowUpdate); - const oldFlow = await _getFlow(flowId, user, isCLI, transaction); + const oldFlow = await _getFlow(flowId, user, isCLI, transaction); + if (!oldFlow) { + throw new Errors.NotFoundError(ErrorMessages.INVALID_FLOW_ID) + } + if (flowData.name) { + await _checkForDuplicateName(flowData.name, flowId, transaction); + } - if (!oldFlow) { - throw new Errors.NotFoundError(ErrorMessages.INVALID_FLOW_ID) - } - if (flowData.name !== undefined) { - await isFlowExist(flowData.name, transaction); - } + const flow = { + name: flowData.name, + description: flowData.description, + isActivated: flowData.isActivated, + updatedBy: user.id + }; - const flow = { - name: flowData.name, - description: flowData.description, - isActivated: flowData.isActivated, - updatedBy: user.id - }; - - const updateFlowData = AppHelper.deleteUndefinedFields(flow); - - const where = isCLI ? - { - id: flowId - } - : - { - id: flowId, - userId: user.id + const updateFlowData = AppHelper.deleteUndefinedFields(flow); + + const where = isCLI + ? {id: flowId} + : {id: flowId, userId: user.id}; + + await FlowManager.update(where, updateFlowData, transaction); + + if (oldFlow.isActivated !== flowData.isActivated) { + const flowWithMicroservices = await FlowManager.findFlowMicroservices({id: flowId}, transaction); + const onlyUnique = (value, index, self) => self.indexOf(value) === index; + const iofogUuids = flowWithMicroservices.microservice + .map(obj => obj.iofogUuid) + .filter(onlyUnique) + .filter(val => val !== null); + for (let iofogUuid of iofogUuids) { + const updateChangeTrackingData = { + containerConfig: true, + containerList: true, + routing: true }; - - await FlowManager.update(where, updateFlowData, transaction); - - //TODO: simplify. use manager's join query - if (oldFlow.isActivated !== flowData.isActivated) { - const msList = await MicroserviceService.getListMicroservices({flowId: flowId}, user, isCLI, transaction) - for (const ms of msList) { - const updateChangeTrackingData = { - containerConfig: true, - containerList: true, - routing: true - } - await ChangeTrackingManager.update({iofogUuid: ms.iofogUuid}, updateChangeTrackingData, transaction); - } + await ChangeTrackingManager.update({iofogUuid: iofogUuid}, updateChangeTrackingData, transaction); } + } }; const _getFlow = async function (flowId, user, isCLI, transaction) { - const whereObj = { - id: flowId, - userId: user.id - }; - const where = AppHelper.deleteUndefinedFields(whereObj); + const where = isCLI + ? {id: flowId} + : {id: flowId, userId: user.id}; const flow = await FlowManager.findOne(where, transaction); if (!flow) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)) } - return flow }; @@ -130,13 +125,16 @@ const _getAllFlows = async function (isCLI, transaction) { return await FlowManager.findAll({}, transaction); }; -const isFlowExist = async function (flowName, transaction) { - const flow = await FlowManager.findOne({ - name: flowName - }, transaction); +const _checkForDuplicateName = async function (name, item, transaction) { + if (name) { + const where = item.id + ? {name: name, id: {[Op.ne]: item.id}} + : {name: name}; - if (flow) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, flowName)); + const result = await FlowManager.findOne(where, transaction); + if (result) { + throw new Errors.DuplicatePropertyError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, name)); + } } }; diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 910a56555..de0ce38bc 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -19,17 +19,16 @@ const ConnectorManager = require('../sequelize/managers/connector-manager'); const ConnectorPortManager = require('../sequelize/managers/connector-port-manager'); const MicroservicePublicModeManager = require('../sequelize/managers/microservice-public-mode-manager'); const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); -const FlowService = require('../services/flow-service'); const IoFogService = require('../services/iofog-service'); const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Validation = require('../schemas/index'); const ConnectorService = require('../services/connector-service'); +const FlowService = require('../services/flow-service'); const CatalogService = require('../services/catalog-service'); const RoutingManager = require('../sequelize/managers/routing-manager'); const Op = require('sequelize').Op; -const Sequelize = require('sequelize'); const _listMicroservices = async function (flowId, user, isCLI, transaction) { if (!isCLI) { @@ -103,7 +102,7 @@ const _createMicroserviceOnFog = async function (microserviceData, user, isCLI, const _createMicroservice = async function (microserviceData, user, isCLI, transaction) { - const microserviceToCreate = { + let newMicroservice = { uuid: AppHelper.generateRandomString(32), name: microserviceData.name, config: microserviceData.config, @@ -115,20 +114,20 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans updatedBy: user.id }; - const microserviceDataCreate = AppHelper.deleteUndefinedFields(microserviceToCreate); + newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); - await _checkForDuplicateName(microserviceDataCreate.name, {}, transaction); + await _checkForDuplicateName(newMicroservice.name, {}, transaction); //validate catalog item - await CatalogService.getCatalogItem(microserviceDataCreate.catalogItemId, user, isCLI, transaction); + await CatalogService.getCatalogItem(newMicroservice.catalogItemId, user, isCLI, transaction); //validate flow - await FlowService.getFlow(microserviceDataCreate.flowId, user, isCLI, transaction); + await FlowService.getFlow(newMicroservice.flowId, user, isCLI, transaction); //validate fog node - if (microserviceDataCreate.iofogUuid) { - await IoFogService.getFog({uuid: microserviceDataCreate.iofogUuid}, user, isCLI, transaction); + if (newMicroservice.iofogUuid) { + await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); } - return await MicroserviceManager.create(microserviceDataCreate, transaction); + return await MicroserviceManager.create(newMicroservice, transaction); }; const _createMicroservicePorts = async function (ports, microserviceUuid, transaction) { From 4e8d38802453474325e0b5a95cae915a20233292 Mon Sep 17 00:00:00 2001 From: dbusel Date: Wed, 31 Oct 2018 13:06:05 +0300 Subject: [PATCH 02/91] Epankou/feature microservice cli (#296) * microservice validation refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * cli microservice wip * cli microservice wip * microservices cli wip * cli microservices final * microservice cli refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * removed column need_update from microservices --- ...094923-drop_need_update_col_microservices.js.js | 14 ++++++++++++++ src/sequelize/rebuild_dev_db.sh | 1 - src/services/agent-service.js | 1 - src/services/flow-service.js | 1 - 4 files changed, 14 insertions(+), 3 deletions(-) create mode 100644 src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js diff --git a/src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js b/src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js new file mode 100644 index 000000000..b1d3f82a5 --- /dev/null +++ b/src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('Microservices', 'need_update'); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.addColumn('Microservices', + 'need_update', + Sequelize.BOOLEAN + ); + } +}; diff --git a/src/sequelize/rebuild_dev_db.sh b/src/sequelize/rebuild_dev_db.sh index 65e058695..5999aaba5 100755 --- a/src/sequelize/rebuild_dev_db.sh +++ b/src/sequelize/rebuild_dev_db.sh @@ -1,4 +1,3 @@ -cd src/sequelize rm -rf dev_database.sqlite ../../node_modules/.bin/sequelize db:migrate ../../node_modules/.bin/sequelize db:seed:all \ No newline at end of file diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 4a030f493..189ab7a7a 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -235,7 +235,6 @@ const getAgentMicroservices = async function (fog, transaction) { const responseMicroservice = { uuid: microservice.uuid, imageId: imageId, - needUpdate: microservice.needUpdate, config: microservice.config, rebuild: microservice.rebuild, rootHostAccess: microservice.rootHostAccess, diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 9bd5bca6e..0dea51423 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -17,7 +17,6 @@ const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Validation = require('../schemas'); -// const MicroserviceService = require('./microservices-service') const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager') const _createFlow = async function (flowData, user, isCLI, transaction) { From 5829a64c0a6ec50230dd723f7ab0dac55566e888 Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Wed, 31 Oct 2018 13:53:45 +0300 Subject: [PATCH 03/91] Epankou/feature microservice cli (#297) * microservice validation refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * cli microservice wip * cli microservice wip * microservices cli wip * cli microservices final * microservice cli refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * removed column need_update from microservices * removed column need_update from microservices --- src/sequelize/models/microservice.js | 5 ----- 1 file changed, 5 deletions(-) diff --git a/src/sequelize/models/microservice.js b/src/sequelize/models/microservice.js index 85a3ccb02..df5d29245 100644 --- a/src/sequelize/models/microservice.js +++ b/src/sequelize/models/microservice.js @@ -26,11 +26,6 @@ module.exports = (sequelize, DataTypes) => { field: 'is_network', defaultValue: false }, - needUpdate: { - type: DataTypes.BOOLEAN, - field: 'need_update', - defaultValue: false - }, rebuild: { type: DataTypes.BOOLEAN, field: 'rebuild', From 04d1c316d27cd672fc9b0579687f2d86c9ca3c57 Mon Sep 17 00:00:00 2001 From: Marina Lipnitskaya Date: Wed, 31 Oct 2018 13:55:02 +0300 Subject: [PATCH 04/91] Update README.md (#298) --- README.md | 77 +++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 49 insertions(+), 28 deletions(-) diff --git a/README.md b/README.md index 828089b9a..1f4b885eb 100644 --- a/README.md +++ b/README.md @@ -457,8 +457,11 @@ $ iofog-controller catalog <*command*> <*options*>
remove -- Delete a microservice.
list -- List all microservices.
info -- Get microservice settings.
- route -- Add/Remove microservice route.
- port-mapping -- Create/Delete/List microservice port mapping.
+ route-create -- Create microservice route.
+ route-remove -- Remove microservice route.
+ port-mapping-create -- Create microservice port mapping.
+ port-mapping-remove -- Remove microservice port mapping.
+ port-mapping-list -- List microservice port mapping.
*add -u* <*user-id*> @@ -500,17 +503,25 @@ $ iofog-controller catalog <*command*> <*options*>
-i, --microservice-id string (Microservice ID)
-*route*
+*route-create*
- -a, --add string (Add new route(s))
- -m, --remove string (Delete existing route(s))
+ -T, --route string (Microservice route (receiving microservices))
-*port-mapping*
+*route-remove*
- -i, --microservice-id string (Microservice ID)
- -b, --create (Add new port mapping(s))
- -B, --delete (Delete existing port mapping(s))
- -G, --list (List port mappings)
+ -T, --route string (Microservice route (receiving microservices))
+ +*port-mapping-create*
+ + -i, --microservice-id string (Microservice ID)
+ -P, --mapping string (Container port mapping)
+ +*port-mapping-remove*
+ + -i, --microservice-id string (Microservice ID)
+ -b, --internal-port string (Internal port)
+ +*port-mapping-list* **JSON ADD File Schema**
@@ -560,25 +571,35 @@ $ iofog-controller catalog <*command*> <*options*>
}
**Examples**
- 1. Single mapping ($ iofog-controller microservice add - [other required options] --volumes - /host_src:/container_src) - 2. Multiple mappings ($ iofog-controller microservice add - [other required options] --volumes - /host_src:/container_src - /host_bin:/container_bin) - 3. Port mapping ($ iofog-controller microservice add - (internal:external:publicMode) [other required options] --ports - 80:8080:false 443:5443:false) - 4. Add routes ($ iofog-controller microservice route - --add ABC:DEF) - 5. Delete route ($ iofog-controller microservice route - --remove ABC:DEF) - 6. Create port mapping ($ iofog-controller microservice port- - mapping --create 80:8080:false -i ABC) - 7. Delete port mapping ($ iofog-controller microservice port- - mapping --delete 80 -i ABC) + 1. Single mapping
+ $ iofog-controller microservice add [other required options] --volumes
+ /host_src:/container_src
+ + 2. Multiple mappings
+ $ iofog-controller microservice add [other required options] --volumes
+ /host_src:/container_src
+ /host_bin:/container_bin
+ + 3. Port mapping (80:8080:false - internal port : external port : public mode)
+ $ iofog-controller microservice add [other required options] --ports
+ 80:8080:false 443:5443:false
+ + 4. Add routes (ABC:DEF - source microservice id : dest microservice id)
+ $ iofog-controller microservice add [other required options] --routes
+ ABC:DEF RFG:HJK
+ + 5. Add route (ABC:DEF - source microservice id : dest microservice id)
+ $ iofog-controller microservice route-create --route ABC:DEF
+ + 6. Delete route (ABC:DEF - source microservice id : dest microservice id)
+ $ iofog-controller microservice route-remove --route ABC:DEF
+ + 7. Create port mapping (80:8080:false - internal port : external port : public mode, ABC - microservice)
+ $ iofog-controller microservice port-mapping-create --mapping 80:8080:false -i ABC
+ + 8. Delete port mapping (80 - internal port, ABC - microservice id)
+ $ iofog-controller microservice port-mapping-remove --internal-port 80 -i ABC



From 44fa3727572b64bb28cf5d68b1e5b5bc44046f54 Mon Sep 17 00:00:00 2001 From: Railag Date: Wed, 31 Oct 2018 14:00:48 +0300 Subject: [PATCH 05/91] EWC-279 error messages refactoring (#299) --- specs/swagger.yml | 12 ++++++------ src/helpers/error-messages.js | 20 ++++++++++---------- src/services/iofog-service.js | 16 ++++++++-------- src/services/microservices-service.js | 2 +- 4 files changed, 25 insertions(+), 25 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 69068718e..14c1766fb 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -2757,7 +2757,7 @@ definitions: configExample: type: string images: - $ref: '#/definitions/ElementContainerImages' + $ref: '#/definitions/MicroserviceContainerImages' InfoTypeResponse: type: object properties: @@ -2765,11 +2765,11 @@ definitions: type: string infoFormat: type: string - ElementContainerImages: + MicroserviceContainerImages: type: array items: - $ref: '#/definitions/ElementContainerImage' - ElementContainerImage: + $ref: '#/definitions/MicroserviceContainerImage' + MicroserviceContainerImage: type: object properties: containerImage: @@ -2789,7 +2789,7 @@ definitions: category: type: string images: - $ref: '#/definitions/ElementContainerImages' + $ref: '#/definitions/MicroserviceContainerImages' publisher: type: string diskRequired: @@ -2854,7 +2854,7 @@ definitions: config: type: string images: - $ref: '#/definitions/ElementContainerImages' + $ref: '#/definitions/MicroserviceContainerImages' picture: type: string status: diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index dd3a000bb..61c1c1f0f 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -16,19 +16,19 @@ module.exports = { ALREADY_EXISTS: 'Model already exists', INVALID_CATALOG_ITEM_ID: 'Invalid catalog item id {}', INVALID_FLOW_ID: 'Invalid flow id {}', - INVALID_CONNECTOR_IP: 'Invalid connector ip {}', + INVALID_CONNECTOR_IP: 'Invalid connector IP {}', UNABLE_TO_CREATE_ACTIVATION_CODE: 'Unable to create activation code', UNABLE_TO_GET_ACTIVATION_CODE: 'Unable to create activation code', - INVALID_FOG_NODE_ID: 'Invalid fog node id {}', + INVALID_FOG_NODE_UUID: 'Invalid ioFog UUID {}', INVALID_USER_EMAIL: 'Invalid user email', - INVALID_MICROSERVICE_UUID: 'Invalid microservice uuid {}', + INVALID_MICROSERVICE_UUID: 'Invalid microservice UUID {}', ACTIVATION_CODE_NOT_FOUND: 'Activation code not found', INVALID_OLD_PASSWORD: 'Old password is incorrect', ACCOUNT_NOT_FOUND: 'Account not found', USER_NOT_UPDATED: 'User not updated', EMAIL_NOT_ACTIVATED: 'Email is not activated. Please activate your account first.', REGISTRATION_FAILED: 'Registration failed: There is already an account associated with your email address. Please try logging in instead.', - INVALID_NODE_ID: 'Invalid Node Id', + INVALID_NODE_ID: 'Invalid ioFog UUID', INVALID_PROVISIONING_KEY: 'Invalid Provisioning Key', EMAIL_SENDER_NOT_CONFIGURED: 'Email sender not configured', INVALID_PORT_FORMAT: 'Invalid port format', @@ -36,20 +36,20 @@ module.exports = { PORT_NOT_AVAILABLE: 'Port {} not available', UNABLE_TO_WRITE_STRACE: 'Error while writing strace data to file. File name: {}, err: {}', UNABLE_TO_DELETE_STRACE: 'Error while deleting strace data file. File name: {}, err: {}', - FTP_ERROR: 'Ftp error: {}', + FTP_ERROR: 'FTP error: {}', EXPIRED_PROVISION_KEY: 'Expired provision key', VERSION_COMMAND_NOT_FOUND: 'Version command not found', - STRACE_WITHOUT_FOG: 'Can not run strace for element without fog.', + STRACE_WITHOUT_FOG: "Can't run strace for microservice without ioFog.", INVALID_ACTION_PROPERTY: 'Unknown action property. Action can be "open" or "close"', IMAGE_SNAPSHOT_NOT_FOUND: 'Image snapshot not found', - INVALID_MICROSERVICES_FOG_TYPE: 'Some of microservices haven\'t proper docker images for this fog type. List of invalid microservices:\n', + INVALID_MICROSERVICES_FOG_TYPE: 'Some of microservices haven\'t proper docker images for this ioFog type. List of invalid microservices:\n', INVALID_MICROSERVICE_CONFIG: "Can't create network microservice without appropriate configuration.", - INVALID_MICROSERVICE_USER: 'Invalid microservice user or uuid', + INVALID_MICROSERVICE_USER: 'Invalid microservice user or UUID', ROUTE_NOT_FOUND: 'Route not found', - IMAGE_SNAPSHOT_WITHOUT_FOG: 'Can not run image snapshot for element without fog.', + IMAGE_SNAPSHOT_WITHOUT_FOG: 'Can not run image snapshot for microservice without ioFog.', FILE_DOES_NOT_EXIST: 'File does not exist.', RESTRICTED_PUBLISHER: "You are not allowed to add catalog item as 'Eclipse ioFog' publisher", - REQUIRED_FOG_NODE: 'fog node is required.', + REQUIRED_FOG_NODE: 'ioFog node is required.', CLI: { INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.', INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.', diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 0675c291e..9a91950f0 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -149,7 +149,7 @@ async function _updateFog(fogData, user, isCli, transaction) { const oldFog = await FogManager.findOne(queryFogData, transaction) if (!oldFog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } await FogManager.update(queryFogData, updateFogData, transaction) @@ -232,7 +232,7 @@ async function _deleteFog(fogData, user, isCli, transaction) { const fog = await FogManager.findOne(queryFogData, transaction) if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } await _updateFogsConnectionStatus(fog, transaction) await _processDeleteCommand(fog, transaction) @@ -247,7 +247,7 @@ async function _getFog(fogData, user, isCli, transaction) { const fog = await FogManager.findOne(queryFogData, transaction) if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } await _updateFogsConnectionStatus(fog, transaction) @@ -284,7 +284,7 @@ async function _generateProvisioningKey(fogData, user, isCli, transaction) { const fog = await FogManager.findOne(queryFogData, transaction) if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } const provisioningKeyData = await FogProvisionKeyManager.updateOrCreate({iofogUuid: fogData.uuid}, newProvision, transaction) @@ -315,7 +315,7 @@ async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { const fog = await FogManager.findOne(queryFogData, transaction) if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } await _generateProvisioningKey({uuid: fogVersionData.uuid}, user, isCli, transaction) @@ -337,7 +337,7 @@ async function _setFogRebootCommand(fogData, user, isCli, transaction) { const fog = await FogManager.findOne(queryFogData, transaction) if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, fogData.uuid)) + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, newRebootCommand, transaction) @@ -350,7 +350,7 @@ async function _getHalHardwareInfo(uuidObj, user, isCLI, transaction) { uuid: uuidObj.uuid }, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, uuidObj.uuid)); + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, uuidObj.uuid)); } return await HWInfoManager.findOne({ @@ -365,7 +365,7 @@ async function _getHalUsbInfo(uuidObj, user, isCLI, transaction) { uuid: uuidObj.uuid }, transaction); if (!fog) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_ID, uuidObj.uuid)); + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, uuidObj.uuid)); } return await USBInfoManager.findOne({ diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index de0ce38bc..a7497853f 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -423,7 +423,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u async function _createNetworkMicroserviceForMaster(masterMicroservice, sourceNetwMsConfig, networkCatalogItem, user, transaction) { const sourceNetworkMicroserviceData = { uuid: AppHelper.generateRandomString(32), - name: `Network for Element ${masterMicroservice.uuid}`, + name: `Network for Microservice ${masterMicroservice.uuid}`, config: JSON.stringify(sourceNetwMsConfig), isNetwork: true, catalogItemId: networkCatalogItem.id, From a8f0f2295e31db6e9eb7396f19beb402ff002149 Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Thu, 1 Nov 2018 13:28:52 +0300 Subject: [PATCH 06/91] Epankou/bug flow deactivation ewc 293 (#301) * microservice validation refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into new-fog-controller # Conflicts: # src/services/microservices-service.js * cli microservice wip * cli microservice wip * microservices cli wip * cli microservices final * microservice cli refactoring * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/decorators/transaction-decorator.js # src/helpers/error-messages.js # src/services/microservices-service.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'new-fog-controller' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-microservice-cli # Conflicts: # src/cli/microservice.js * removed column need_update from microservices * removed column need_update from microservices * EWC-293 flow deactivation * EWC-293 flow deactivation * EWC-293 flow deactivation --- src/cli/microservice.js | 8 +-- src/schemas/catalog.js | 2 +- src/sequelize/managers/flow-manager.js | 2 +- .../managers/microservice-manager.js | 52 ++++++++++++++++++- src/sequelize/models/flow.js | 2 +- src/services/agent-service.js | 25 +++------ src/services/flow-service.js | 3 +- 7 files changed, 65 insertions(+), 29 deletions(-) diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 735af77d6..edabe1d2a 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -242,19 +242,19 @@ class Microservice extends BaseCLIHandler { example: '$ iofog-controller microservice add [other required options] --routes ABC:DEF RFG:HJK' }, { - desc: '4. Add route (ABC:DEF - source microservice id : dest microservice id)', + desc: '5. Add route (ABC:DEF - source microservice id : dest microservice id)', example: '$ iofog-controller microservice route-create --route ABC:DEF', }, { - desc: '5. Delete route (ABC:DEF - source microservice id : dest microservice id)', + desc: '6. Delete route (ABC:DEF - source microservice id : dest microservice id)', example: '$ iofog-controller microservice route-remove --route ABC:DEF', }, { - desc: '6. Create port mapping (80:8080:false - internal port : external port : public mode, ABC - microservice)', + desc: '7. Create port mapping (80:8080:false - internal port : external port : public mode, ABC - microservice)', example: '$ iofog-controller microservice port-mapping-create --mapping 80:8080:false -i ABC' }, { - desc: '7. Delete port mapping (80 - internal port, ABC - microservice id)', + desc: '8. Delete port mapping (80 - internal port, ABC - microservice id)', example: '$ iofog-controller microservice port-mapping-remove --internal-port 80 -i ABC' } ], diff --git a/src/schemas/catalog.js b/src/schemas/catalog.js index 61eef26c5..26e19fd1d 100644 --- a/src/schemas/catalog.js +++ b/src/schemas/catalog.js @@ -33,7 +33,7 @@ const catalogItemCreate = { "inputType": {"$ref": "/type"}, "outputType": {"$ref": "/type"} }, - "required": ["name"], + "required": ["name", "registryId", "images"], "additionalProperties": false }; diff --git a/src/sequelize/managers/flow-manager.js b/src/sequelize/managers/flow-manager.js index 798d9aa66..027f4ba86 100644 --- a/src/sequelize/managers/flow-manager.js +++ b/src/sequelize/managers/flow-manager.js @@ -27,7 +27,7 @@ class FlowManager extends BaseManager { include: [ { model: Microservice, - as: 'microservice', + as: 'microservices', required: false, attributes: ['iofogUuid'] } diff --git a/src/sequelize/managers/microservice-manager.js b/src/sequelize/managers/microservice-manager.js index 36d6ae8b2..9808db78f 100644 --- a/src/sequelize/managers/microservice-manager.js +++ b/src/sequelize/managers/microservice-manager.js @@ -23,6 +23,7 @@ const Fog = models.Fog; const Flow = models.Flow; const User = models.User; const Routing = models.Routing; +const Registry = models.Registry; class MicroserviceManager extends BaseManager { getEntity() { @@ -53,7 +54,7 @@ class MicroserviceManager extends BaseManager { { model: CatalogItem, as: 'catalogItem', - required: false, + required: true, include: [{ model: CatalogItemImage, as: 'images', @@ -86,6 +87,55 @@ class MicroserviceManager extends BaseManager { }, {transaction: transaction}) } + findAllActiveFlowMicroservices(iofogUuid, transaction) { + return Microservice.findAll({ + include: [ + { + model: MicroservicePort, + as: 'ports', + required: false, + attributes: ['portInternal', 'portExternal'] + }, + { + model: VolumeMapping, + as: 'volumeMappings', + required: false, + attributes: ['hostDestination', 'containerDestination', 'accessMode'] + }, + { + model: CatalogItem, + as: 'catalogItem', + required: true, + include: [ + { + model: CatalogItemImage, + as: 'images', + required: true, + attributes: ['containerImage', 'fogTypeId'] + }, + { + model: Registry, + as: 'registry', + required: true, + attributes: ['url'] + } + ], + attributes: ['picture'] + }, + { + model: Flow, + as: 'flow', + required: true, + attributes: ['isActivated'] + } + ], + where: { + iofogUuid: iofogUuid, + '$flow.is_activated$': true + } + }, {transaction: transaction}) + } + findOneWithDependencies(where, attributes, transaction) { return Microservice.findOne({ include: [ diff --git a/src/sequelize/models/flow.js b/src/sequelize/models/flow.js index f438dab51..b12f7942f 100644 --- a/src/sequelize/models/flow.js +++ b/src/sequelize/models/flow.js @@ -53,7 +53,7 @@ module.exports = (sequelize, DataTypes) => { name: 'flowId', field: 'flow_id' }, - as: 'microservice' + as: 'microservices' }) }; return Flow; diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 189ab7a7a..45dee62dd 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -207,28 +207,15 @@ const updateAgentStatus = async function (agentStatus, fog, transaction) { }; const getAgentMicroservices = async function (fog, transaction) { - const microservices = await MicroserviceManager.findAllWithDependencies({ - iofogUuid: fog.uuid - }, {}, transaction); + const microservices = await MicroserviceManager.findAllActiveFlowMicroservices(fog.uuid, transaction); const fogTypeId = fog.fogTypeId; const response = []; - for (const microservice of microservices) { - let imageId = ''; + for (let microservice of microservices) { const images = microservice.catalogItem.images; - for (const image of images) { - if (image.fogTypeId === fogTypeId) { - imageId = image.containerImage; - break; - } - } - - const registry = await RegistryManager.findOne({ - id: microservice.catalogItem.registryId - }, transaction); - - const registryUrl = registry.url; + const image = images.find(image => image.fogTypeId === fogTypeId); + const imageId = image ? image.containerImage : ''; const routes = await MicroserviceService.getPhysicalConections(microservice, transaction); @@ -239,7 +226,7 @@ const getAgentMicroservices = async function (fog, transaction) { rebuild: microservice.rebuild, rootHostAccess: microservice.rootHostAccess, logSize: microservice.logSize, - registryUrl: registryUrl, + registryUrl: microservice.catalogItem.registry.url, portMappings: microservice.ports, volumeMappings: microservice.volumeMappings, imageSnapshot: microservice.imageSnapshot, @@ -418,7 +405,7 @@ async function _checkMicroservicesFogType(fog, fogTypeId, transaction) { for (const microservice of microservices) { let exists = false; - for (const image of microservice.catalogItem.images) { + for (let image of microservice.catalogItem.images) { if (image.fogTypeId === fogTypeId) { exists = true; break; diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 0dea51423..47dd1fc85 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -22,7 +22,6 @@ const ChangeTrackingManager = require('../sequelize/managers/change-tracking-man const _createFlow = async function (flowData, user, isCLI, transaction) { await Validation.validate(flowData, Validation.schemas.flowCreate); - await isFlowExist(flowData.name, transaction); await _checkForDuplicateName(flowData.name, {}, transaction); const flowToCreate = { @@ -84,7 +83,7 @@ const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) if (oldFlow.isActivated !== flowData.isActivated) { const flowWithMicroservices = await FlowManager.findFlowMicroservices({id: flowId}, transaction); const onlyUnique = (value, index, self) => self.indexOf(value) === index; - const iofogUuids = flowWithMicroservices.microservice + const iofogUuids = flowWithMicroservices.microservices .map(obj => obj.iofogUuid) .filter(onlyUnique) .filter(val => val !== null); From cbaf033826fd6469134d2ea934d8341401d7187f Mon Sep 17 00:00:00 2001 From: dbusel Date: Thu, 1 Nov 2018 13:32:54 +0300 Subject: [PATCH 07/91] Dbusel/bug ewc 301 Flow get list (#302) * exclude fields on get list * remove useless method --- src/sequelize/managers/flow-manager.js | 12 ++++++++++++ src/services/flow-service.js | 2 +- 2 files changed, 13 insertions(+), 1 deletion(-) diff --git a/src/sequelize/managers/flow-manager.js b/src/sequelize/managers/flow-manager.js index 027f4ba86..7dadd9d42 100644 --- a/src/sequelize/managers/flow-manager.js +++ b/src/sequelize/managers/flow-manager.js @@ -36,6 +36,18 @@ class FlowManager extends BaseManager { attributes: ['id'] }, {transaction: transaction}) } + + async findAllExcludeFields(where, transaction) { + return Flow.findAll({ + where: where, + attributes: { + exclude: [ + 'created_at', + 'updated_at', + 'updatedById', + 'userId' + ]}}, {transaction: transaction}) + } } diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 47dd1fc85..cc537fa18 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -116,7 +116,7 @@ const _getUserFlows = async function (user, isCLI, transaction) { userId: user.id }; - return await FlowManager.findAll(flow, transaction) + return await FlowManager.findAllExcludeFields(flow, transaction) }; const _getAllFlows = async function (isCLI, transaction) { From e48d71404401239cd33677d7c28d1b8452a4904e Mon Sep 17 00:00:00 2001 From: dbusel Date: Thu, 1 Nov 2018 15:23:15 +0300 Subject: [PATCH 08/91] Dbusel/bug ewc 301 flow get (#304) * exclude fields on get list * remove useless method * update get method and swagger --- specs/swagger.yml | 8 -------- src/sequelize/managers/flow-manager.js | 12 ++++++++++++ src/services/flow-service.js | 2 +- 3 files changed, 13 insertions(+), 9 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 14c1766fb..700276fbc 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -2819,18 +2819,10 @@ definitions: type: string name: type: string - updatedBy: - type: number description: type: string isActivated: type: boolean - createdAt: - type: number - updatedAt: - type: number - userId: - type: number NewFlowRequest: type: object properties: diff --git a/src/sequelize/managers/flow-manager.js b/src/sequelize/managers/flow-manager.js index 7dadd9d42..4ff221110 100644 --- a/src/sequelize/managers/flow-manager.js +++ b/src/sequelize/managers/flow-manager.js @@ -48,6 +48,18 @@ class FlowManager extends BaseManager { 'userId' ]}}, {transaction: transaction}) } + + async findOneExcludeFields(where, transaction) { + return Flow.findOne({ + where: where, + attributes: { + exclude: [ + 'created_at', + 'updated_at', + 'updatedById', + 'userId' + ]}}, {transaction: transaction}) + } } diff --git a/src/services/flow-service.js b/src/services/flow-service.js index cc537fa18..c74c99180 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -103,7 +103,7 @@ const _getFlow = async function (flowId, user, isCLI, transaction) { ? {id: flowId} : {id: flowId, userId: user.id}; - const flow = await FlowManager.findOne(where, transaction); + const flow = await FlowManager.findOneExcludeFields(where, transaction); if (!flow) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)) From 9008590d98f708316748723b48c330934804acbe Mon Sep 17 00:00:00 2001 From: dbusel Date: Thu, 1 Nov 2018 16:09:50 +0300 Subject: [PATCH 09/91] Dbusel/bug ewc 304 Microservice get (#305) * exclude fields on get list * remove useless method * remove fields on microservice get * update swagger docs * update methods connected to get * refactoring after pr comments --- specs/swagger.yml | 20 --------- src/sequelize/managers/flow-manager.js | 2 +- .../managers/microservice-manager.js | 44 +++++++++++++++++++ src/services/microservices-service.js | 37 +++++----------- 4 files changed, 57 insertions(+), 46 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 700276fbc..06ba3f0b9 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -2845,28 +2845,8 @@ definitions: type: string config: type: string - images: - $ref: '#/definitions/MicroserviceContainerImages' - picture: - type: string - status: - type: string - ioFogNodeId: - type: string - isNetwork: - type: boolean - needUpdate: - type: boolean - rebuild: - type: boolean rootHostAccess: type: boolean - deleteWithCleanUp: - type: boolean - strace: - type: boolean - imageSnapshot: - type: string logLimit: type: number volumeMappings: diff --git a/src/sequelize/managers/flow-manager.js b/src/sequelize/managers/flow-manager.js index 4ff221110..51e8bf439 100644 --- a/src/sequelize/managers/flow-manager.js +++ b/src/sequelize/managers/flow-manager.js @@ -48,7 +48,7 @@ class FlowManager extends BaseManager { 'userId' ]}}, {transaction: transaction}) } - + async findOneExcludeFields(where, transaction) { return Flow.findOne({ where: where, diff --git a/src/sequelize/managers/microservice-manager.js b/src/sequelize/managers/microservice-manager.js index 9808db78f..4b07377af 100644 --- a/src/sequelize/managers/microservice-manager.js +++ b/src/sequelize/managers/microservice-manager.js @@ -216,6 +216,50 @@ class MicroserviceManager extends BaseManager { attributes: ['uuid'] }, {transaction: transaction}) } + + async findOneExcludeFields(where, transaction) { + return Microservice.findOne({ + where: where, + attributes: { + exclude: [ + 'configLastUpdated', + 'created_at', + 'updated_at', + 'updatedBy', + 'flowId', + 'registryId', + 'isNetwork', + 'rebuild', + 'deleteWithCleanUp', + 'imageSnapshot', + 'catalog_item_id', + 'iofog_uuid', + 'iofogUuid', + 'catalogItemId' + ]}}, {transaction: transaction}) + } + + async findAllExcludeFields(where, transaction) { + return Microservice.findAll({ + where: where, + attributes: { + exclude: [ + 'configLastUpdated', + 'created_at', + 'updated_at', + 'updatedBy', + 'flowId', + 'registryId', + 'isNetwork', + 'rebuild', + 'deleteWithCleanUp', + 'imageSnapshot', + 'catalog_item_id', + 'iofog_uuid', + 'iofogUuid', + 'catalogItemId' + ]}}, {transaction: transaction}) + } } const instance = new MicroserviceManager(); diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index a7497853f..0bd39cdee 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -36,17 +36,7 @@ const _listMicroservices = async function (flowId, user, isCLI, transaction) { } const where = isCLI ? {} : {flowId: flowId}; - return await MicroserviceManager.findAllWithDependencies(where, - { - exclude: [ - 'configLastUpdated', - 'created_at', - 'updated_at', - 'catalogItemId', - 'updatedBy', - 'flowId', - 'registryId' - ]}, transaction); + return await MicroserviceManager.findAllExcludeFields(where, transaction); }; const _getMicroservice = async function (microserviceUuid, user, isCLI, transaction) { @@ -54,18 +44,9 @@ const _getMicroservice = async function (microserviceUuid, user, isCLI, transact await _validateMicroserviceOnGet(user.id, microserviceUuid, transaction); } - const microservice = await MicroserviceManager.findOneWithDependencies({ + const microservice = await MicroserviceManager.findOneExcludeFields({ uuid: microserviceUuid - }, - { - exclude: [ - 'configLastUpdated', - 'created_at', - 'updated_at', - 'updatedBy', - 'flowId', - 'registryId' - ]}, transaction); + }, transaction); if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); @@ -124,7 +105,7 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans await FlowService.getFlow(newMicroservice.flowId, user, isCLI, transaction); //validate fog node if (newMicroservice.iofogUuid) { - await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); + await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); } return await MicroserviceManager.create(newMicroservice, transaction); @@ -174,7 +155,10 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, const microserviceDataUpdate = AppHelper.deleteUndefinedFields(microserviceToUpdate); - const microservice = await _getMicroservice(microserviceUuid, user, isCLI, transaction); + const microservice = await MicroserviceManager.findOne({ + uuid: microserviceUuid, + updatedBy: user.id + }, transaction); if (microserviceDataUpdate.name) { await _checkForDuplicateName(microserviceDataUpdate.name, {id: microserviceUuid}, transaction); @@ -231,7 +215,10 @@ const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, }, transaction); } - const microservice = await _getMicroservice(microserviceUuid, user, isCLI, transaction); + const microservice = await MicroserviceManager.findOne({ + uuid: microserviceUuid, + updatedBy: user.id + }, transaction); const affectedRows = await MicroserviceManager.delete({ uuid: microserviceUuid From f32936a91a243c3e7fe83b965f2e84011d759f99 Mon Sep 17 00:00:00 2001 From: dbusel Date: Thu, 1 Nov 2018 16:30:00 +0300 Subject: [PATCH 10/91] add user check for flow name duplicate (#307) --- src/services/flow-service.js | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/services/flow-service.js b/src/services/flow-service.js index c74c99180..41e7166d9 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -22,7 +22,7 @@ const ChangeTrackingManager = require('../sequelize/managers/change-tracking-man const _createFlow = async function (flowData, user, isCLI, transaction) { await Validation.validate(flowData, Validation.schemas.flowCreate); - await _checkForDuplicateName(flowData.name, {}, transaction); + await _checkForDuplicateName(flowData.name, {}, user.id, transaction); const flowToCreate = { name: flowData.name, @@ -62,7 +62,7 @@ const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) throw new Errors.NotFoundError(ErrorMessages.INVALID_FLOW_ID) } if (flowData.name) { - await _checkForDuplicateName(flowData.name, flowId, transaction); + await _checkForDuplicateName(flowData.name, flowId, user.id, transaction); } const flow = { @@ -123,11 +123,11 @@ const _getAllFlows = async function (isCLI, transaction) { return await FlowManager.findAll({}, transaction); }; -const _checkForDuplicateName = async function (name, item, transaction) { +const _checkForDuplicateName = async function (name, item, userId, transaction) { if (name) { const where = item.id - ? {name: name, id: {[Op.ne]: item.id}} - : {name: name}; + ? {name: name, id: {[Op.ne]: item.id, userId: userId}} + : {name: name, userId: userId}; const result = await FlowManager.findOne(where, transaction); if (result) { From daefc16fa5141603f5e8f357fed406d842ab71d6 Mon Sep 17 00:00:00 2001 From: Railag Date: Thu, 1 Nov 2018 16:35:59 +0300 Subject: [PATCH 11/91] EWC-297 EWC-298 fixed email activation, added user id to signup response (#303) * EWC-297 EWC-298 fixed email activation, added user id to signup response * cleanup * cleanup * cleanup --- src/helpers/errors.js | 12 ++++++++- src/services/user-service.js | 51 +++++++++++++++++++++++------------- 2 files changed, 44 insertions(+), 19 deletions(-) diff --git a/src/helpers/errors.js b/src/helpers/errors.js index 329e1f109..b0eab2afe 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -78,6 +78,15 @@ class FtpError extends Error { } } +class EmailActivationSetupError extends Error { + constructor() { + const message = 'Email activation is not configured on Controller'; + super(message); + this.message = message; + this.name = "EmailActivationSetupError"; + } +} + module.exports = { AuthenticationError: AuthenticationError, TransactionError: TransactionError, @@ -86,5 +95,6 @@ module.exports = { NotFoundError: NotFoundError, ModelNotFoundError: ModelNotFoundError, DuplicatePropertyError: DuplicatePropertyError, - FtpError: FtpError + FtpError: FtpError, + EmailActivationSetupError: EmailActivationSetupError }; \ No newline at end of file diff --git a/src/services/user-service.js b/src/services/user-service.js index f8854b5b8..5ac48b167 100644 --- a/src/services/user-service.js +++ b/src/services/user-service.js @@ -39,11 +39,11 @@ const createUser = async function (user, transaction) { const signUp = async function (user, isCLI, transaction) { - let emailActivation = Config.get("Email:ActivationEnabled") || 'off'; + let isEmailActivationEnabled = Config.get("Email:ActivationEnabled"); - if (emailActivation === 'on') { + if (isEmailActivationEnabled) { - const newUser = await _handleCreateUser(user, emailActivation, transaction); + const newUser = await _handleCreateUser(user, isEmailActivationEnabled, transaction); const activationCodeData = await EmailActivationCodeService.generateActivationCode(transaction); await EmailActivationCodeService.saveActivationCode(newUser.id, activationCodeData, transaction); @@ -53,7 +53,7 @@ const signUp = async function (user, isCLI, transaction) { await _notifyUserAboutActivationCode(user.email, Config.get('Email:HomeUrl'), emailData, activationCodeData, transporter); return newUser; } else { - return await _handleCreateUser(user, emailActivation, transaction); + return await _handleCreateUser(user, isEmailActivationEnabled, transaction); } }; @@ -103,7 +103,7 @@ const resendActivation = async function (emailObj, isCLI, transaction) { const activateUser = async function (codeData, isCLI, transaction) { const updatedObj = { - emailActivated: 1 + emailActivated: true }; if (isCLI) { @@ -196,7 +196,7 @@ const list = async function (isCLI, transaction) { const suspendUser = async function (user, isCLI, transaction) { const updatedObj = { - emailActivated: 0 + emailActivated: false }; await AccessTokenService.removeAccessTokenByUserId(user.id, transaction); @@ -230,8 +230,8 @@ async function _generateAccessToken(transaction) { } function _verifyEmailActivation(emailActivated) { - const emailActivation = Config.get("Email:ActivationEnabled") || 'off'; - if (emailActivation === 'on' && emailActivated === 0) + const isEmailActivationEnabled = Config.get("Email:ActivationEnabled"); + if (isEmailActivationEnabled && !emailActivated) throw new Error(ErrorMessages.EMAIL_NOT_ACTIVATED); } @@ -260,7 +260,7 @@ async function _userEmailSender(emailData) { return transporter } -async function _handleCreateUser(user, emailActivation, transaction) { +async function _handleCreateUser(user, isEmailActivationEnabled, transaction) { const existingUser = await UserManager.findOne({ email: user.email }, transaction); @@ -269,13 +269,18 @@ async function _handleCreateUser(user, emailActivation, transaction) { throw new Errors.ValidationError('Registration failed: There is already an account associated with your email address. Please try logging in instead.'); } - await _createNewUser(user, emailActivation, transaction); - delete user.password; - return user + const newUser = await _createNewUser(user, isEmailActivationEnabled, transaction); + return { + userId: newUser.id, + firstName: newUser.firstName, + lastName: newUser.lastName, + email: newUser.email, + emailActivated: user.emailActivated + } } -async function _createNewUser(user, emailActivation, transaction) { - user.emailActivated = emailActivation === 'on' ? 0 : 1; +async function _createNewUser(user, isEmailActivationEnabled, transaction) { + user.emailActivated = !isEmailActivationEnabled; return await createUser(user, transaction) } @@ -322,11 +327,21 @@ async function _sendEmail(transporter, mailOptions) { } async function _getEmailData() { - return { - email: Config.get("Email:Address"), - password: AppHelper.decryptText(Config.get("Email:Password"), Config.get("Email:Address")), - service: Config.get("Email:Service") + try { + const email = Config.get("Email:Address"); + const password = AppHelper.decryptText(Config.get("Email:Password"), Config.get("Email:Address")); + const service = Config.get("Email:Service"); + + return { + email: email, + password: password, + service: service + } + + } catch(errMsg) { + throw new Errors.EmailActivationSetupError(); } + } module.exports = { From ced30a40637c613847caf1c035b44c71e58f4a06 Mon Sep 17 00:00:00 2001 From: Railag Date: Thu, 1 Nov 2018 17:19:37 +0300 Subject: [PATCH 12/91] EWC-303 fixed microservice create validation & duplicate name for different users (#306) --- specs/swagger.yml | 6 ++-- src/schemas/microservice.js | 7 ++-- src/services/microservices-service.js | 51 ++++++++++++++++----------- 3 files changed, 37 insertions(+), 27 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 06ba3f0b9..2ff37c248 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -1222,8 +1222,8 @@ paths: required: true type: string - in: body - name: NetMicroserviceInfo - description: New Microserviced Info + name: NewMicroserviceInfo + description: New Microservice Info required: true schema: $ref: '#/definitions/NewMicroserviceRequest' @@ -2874,7 +2874,7 @@ definitions: type: string rootHostAccess: type: boolean - logLimit: + logSize: type: number volumeMappings: type: array diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 20012ed3d..05de1f720 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -23,7 +23,7 @@ const microserviceCreate = { "type": "array", "items": {"type": "string"}} }, - "required": ["name"] + "required": ["name", "flowId", "catalogItemId"] }; const microserviceUpdate = { @@ -38,7 +38,7 @@ const microserviceUpdate = { "rebuild": {"type": "boolean"}, "ioFogNodeId": {"type": "string"}, "rootHostAccess": {"type": "boolean"}, - "logSize": {"type": "integer"}, + "logSize": {"type": "integer", "minimum" : 0}, "volumeMappings": { "type": "array", "items": {"$ref": "/volumeMappings"} @@ -75,7 +75,8 @@ const volumeMappings = { "hostDestination": {"type": "string"}, "containerDestination": {"type": "string"}, "accessMode": {"type": "string"} - } + }, + "required": ["hostDestination", "containerDestination", "accessMode"] }; module.exports = { diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 0bd39cdee..31c1bd7ad 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -68,11 +68,11 @@ const _createMicroserviceOnFog = async function (microserviceData, user, isCLI, await _createVolumeMappings(microserviceData.volumeMappings, microservice.uuid, transaction); } - if (microserviceData.routes){ + if (microserviceData.routes) { await _createRoutes(microserviceData.routes, microservice.uuid, user, transaction); } - if(microserviceData.ioFogNodeId) { + if (microserviceData.ioFogNodeId) { await _updateChangeTracking(false, microservice.uuid, microserviceData.ioFogNodeId, user, isCLI, transaction); } @@ -97,7 +97,7 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); - await _checkForDuplicateName(newMicroservice.name, {}, transaction); + await _checkForDuplicateName(newMicroservice.name, {}, user.id, transaction); //validate catalog item await CatalogService.getCatalogItem(newMicroservice.catalogItemId, user, isCLI, transaction); @@ -134,7 +134,7 @@ const _createVolumeMappings = async function (volumeMappings, microserviceUuid, }; const _createRoutes = async function (routes, microserviceUuid, user, transaction) { - for (let route of routes){ + for (let route of routes) { await _createRoute(microserviceUuid, route, user, transaction) } }; @@ -160,9 +160,9 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, updatedBy: user.id }, transaction); - if (microserviceDataUpdate.name) { - await _checkForDuplicateName(microserviceDataUpdate.name, {id: microserviceUuid}, transaction); - } + if (microserviceDataUpdate.name) { + await _checkForDuplicateName(microserviceDataUpdate.name, {id: microserviceUuid}, user.id, transaction); + } //validate fog node if (microserviceDataUpdate.iofogUuid) { @@ -177,7 +177,7 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, await _updateVolumeMappings(microserviceDataUpdate.volumeMappings, microserviceUuid, transaction); } - if (microserviceDataUpdate.ioFogNodeId){ + if (microserviceDataUpdate.ioFogNodeId) { await _deleteRoutes(microserviceData.routes, microserviceUuid, transaction); await _createRoutes(microserviceData.routes, microserviceUuid, user, transaction); await _updateChangeTracking(false, microserviceUuid, microserviceDataUpdate.ioFogNodeId, user, isCLI, transaction) @@ -206,13 +206,13 @@ const _updateChangeTracking = async function (configUpdated, microserviceUuid, f }; const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, user, isCLI, transaction) { - if (deleteWithCleanUp){ + if (deleteWithCleanUp) { return await MicroserviceManager.update({ - uuid: microserviceUuid - }, - { - deleteWithCleanUp: deleteWithCleanUp - }, transaction); + uuid: microserviceUuid + }, + { + deleteWithCleanUp: deleteWithCleanUp + }, transaction); } const microservice = await MicroserviceManager.findOne({ @@ -230,11 +230,20 @@ const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, await _updateChangeTracking(false, microserviceUuid, microservice.ioFogNodeId, user, isCLI, transaction) }; -const _checkForDuplicateName = async function (name, item, transaction) { +const _checkForDuplicateName = async function (name, item, userId, transaction) { if (name) { const where = item.id - ? {name: name, uuid: {[Op.ne]: item.id}} - : {name: name}; + ? + { + name: name, + uuid: {[Op.ne]: item.id}, + updatedBy: userId + } + : + { + name: name, + updatedBy: userId + }; const result = await MicroserviceManager.findOne(where, transaction); if (result) { @@ -243,8 +252,8 @@ const _checkForDuplicateName = async function (name, item, transaction) { } }; -const _deleteRoutes = async function(routes, microserviceUuid, user, transaction){ - for (let route of routes){ +const _deleteRoutes = async function (routes, microserviceUuid, user, transaction) { + for (let route of routes) { await _deleteRoute(microserviceUuid, route, user, transaction) } }; @@ -793,11 +802,11 @@ module.exports = { getMicroserviceWithTransaction: TransactionDecorator.generateTransaction(_getMicroservice), updateMicroserviceWithTransaction: TransactionDecorator.generateTransaction(_updateMicroservice), deleteMicroserviceWithTransaction: TransactionDecorator.generateTransaction(_deleteMicroservice), - createRouteWithTransaction : TransactionDecorator.generateTransaction(_createRoute), + createRouteWithTransaction: TransactionDecorator.generateTransaction(_createRoute), deleteRouteWithTransaction: TransactionDecorator.generateTransaction(_deleteRoute), createPortMappingWithTransaction: TransactionDecorator.generateTransaction(_createPortMapping), getMicroservicePortMappingListWithTransaction: TransactionDecorator.generateTransaction(_getPortMappingList), deletePortMappingWithTransaction: TransactionDecorator.generateTransaction(_deletePortMapping), getPhysicalConections: getPhysicalConections, - getListMicroservices: _listMicroservices + getListMicroservices: _listMicroservices }; From 67fb167d8129515389624700cb885356d5bbfb91 Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Fri, 2 Nov 2018 13:09:31 +0300 Subject: [PATCH 13/91] EWC-298 new registry bug (#308) --- specs/swagger.yml | 6 +++++- src/helpers/error-messages.js | 6 ++++-- src/schemas/registry.js | 4 +++- src/services/registry-service.js | 22 +++++++++++++++++----- 4 files changed, 29 insertions(+), 9 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 2ff37c248..6b21a35cd 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -2715,6 +2715,10 @@ definitions: type: string email: type: string + requiresCert: + type: boolean + certificate: + type: string ActionBody: type: object properties: @@ -3035,4 +3039,4 @@ schemes: - http - https host: 'localhost:54421' -basePath: /api/v3 +basePath: /api/v3 \ No newline at end of file diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 61c1c1f0f..2a7c9c0ec 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -16,6 +16,7 @@ module.exports = { ALREADY_EXISTS: 'Model already exists', INVALID_CATALOG_ITEM_ID: 'Invalid catalog item id {}', INVALID_FLOW_ID: 'Invalid flow id {}', + INVALID_REGISTRY_ID: 'Invalid registry id {}', INVALID_CONNECTOR_IP: 'Invalid connector IP {}', UNABLE_TO_CREATE_ACTIVATION_CODE: 'Unable to create activation code', UNABLE_TO_GET_ACTIVATION_CODE: 'Unable to create activation code', @@ -50,11 +51,12 @@ module.exports = { FILE_DOES_NOT_EXIST: 'File does not exist.', RESTRICTED_PUBLISHER: "You are not allowed to add catalog item as 'Eclipse ioFog' publisher", REQUIRED_FOG_NODE: 'ioFog node is required.', + INVALID_CONNECTOR_DOMAIN: 'Invalid connector domain {}', + CERT_PROPERTY_REQUIRED: 'Property "certificate" is required if property "requiresCert" is set to true', CLI: { INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.', INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.', INVALID_INTERNAL_PORT: 'Internal parsing error. Please provide valid internal port.', INVALID_ROUTE: 'Route parsing error. Please provide valid route.' - }, - INVALID_CONNECTOR_DOMAIN: 'Invalid connector domain {}' + } }; diff --git a/src/schemas/registry.js b/src/schemas/registry.js index 69a2838ca..a69a2e982 100644 --- a/src/schemas/registry.js +++ b/src/schemas/registry.js @@ -19,7 +19,9 @@ const registryCreate = { "isPublic": {"type": "boolean"}, "username": {"type": "string", "minLength": 1}, "password": {"type": "string"}, - "email": {"type": "string"} + "email": {"type": "string"}, + "requiresCert": {"type": "boolean"}, + "certificate": {"type": "string"} }, "required": ["url", "isPublic", "username", "password", "email"], "additionalProperties": false diff --git a/src/services/registry-service.js b/src/services/registry-service.js index a66a10398..eb0d12a84 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -12,24 +12,36 @@ */ const RegistryManager = require('../sequelize/managers/registry-manager'); -const Validator = require('../schemas') -const Errors = require('../helpers/errors') -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager') +const Validator = require('../schemas'); +const Errors = require('../helpers/errors'); +const ErrorMessages = require('../helpers/error-messages'); +const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); const TransactionDecorator = require('../decorators/transaction-decorator'); -const FogManager = require('../sequelize/managers/iofog-manager') +const FogManager = require('../sequelize/managers/iofog-manager'); const Sequelize = require('sequelize'); const Op = Sequelize.Op; +const AppHelper = require('../helpers/app-helper'); + const createRegistry = async function (registry, user, transaction) { await Validator.validate(registry, Validator.schemas.registryCreate); + if (registry.requiresCert && registry.certificate === undefined) { + throw new Errors.ValidationError(ErrorMessages.CERT_PROPERTY_REQUIRED); + } + let registryCreate = { url: registry.url, username: registry.username, password: registry.password, isPublic: registry.isPublic, userEmail: registry.email, + requiresCert: registry.requiresCert, + certificate: registry.certificate, userId: user.id }; + + registryCreate = AppHelper.deleteUndefinedFields(registryCreate); + await RegistryManager.create(registryCreate, transaction) await updateChangeTracking(user, transaction); }; @@ -73,7 +85,7 @@ const deleteRegistry = async function (registryData, user, isCli, transaction) { : {id: registryData.id, userId: user.id}; const registry = await RegistryManager.findOne(queryData, transaction); if (!registry) { - throw new Errors.NotFoundError('Invalid Registry Id'); + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_REGISTRY_ID, registryData.id)); } if (isCli) { user = {id: registry.userId}; From 36a21426e6b7983100e45c3b23d314cf3ce9d456 Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 2 Nov 2018 15:04:09 +0300 Subject: [PATCH 14/91] fixed CLI config email activation update (#309) --- src/cli/config.js | 16 +++------------- src/helpers/app-helper.js | 5 ----- 2 files changed, 3 insertions(+), 18 deletions(-) diff --git a/src/cli/config.js b/src/cli/config.js index 6147b1a00..e2e7c969d 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -121,21 +121,11 @@ const _addConfigOption = async function (options) { } if (options.emailActivationOn != null) { - const emailActivationOn = options.emailActivationOn; - if (!AppHelper.isValidEmailActivation(emailActivationOn)) { - logger.error(ErrorMessages.INVALID_FILE_PATH); - return; - } - config.set('Server:ActivationEnabled', true) + config.set('Email:ActivationEnabled', true) } if (options.emailActivationOff != null) { - const emailActivationOff = options.emailActivationOff; - if (!AppHelper.isValidEmailActivation(emailActivationOff)) { - logger.error(ErrorMessages.INVALID_FILE_PATH); - return; - } - config.set('Server:ActivationEnabled', false) + config.set('Email:ActivationEnabled', false) } if (options.homeUrl != null && config.get('Email:HomeUrl') !== options.homeUrl) { @@ -173,7 +163,7 @@ const _listConfigOptions = function () { 'SSL certificate directory': config.get('Server:SslCert'), 'Intermediate key directory': config.get('Server:IntermediateCert'), 'Home url': config.get('Email:HomeUrl'), - 'Email activation': config.get('Email:ActivationEnabled') ? 'on' : 'off', + 'Email activation': config.get('Email:ActivationEnabled'), 'Email address': config.get('Email:Address'), 'Email password': config.get('Email:Password'), 'Email service': config.get('Email:Service'), diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index 7a01a2f64..e66660f95 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -93,10 +93,6 @@ const isValidPublicIP = function (publicIP) { return re.test(publicIP); } -function isValidEmailActivation(flag) { - return flag === 'on' || flag === 'off'; -} - function generateAccessToken() { let token = '', i; for (i = 0; i < 8; i++) { @@ -154,7 +150,6 @@ module.exports = { isFileExists, isValidPort, isValidDomain, - isValidEmailActivation, checkPortAvailability, generateAccessToken, checkTransaction, From 16e06b52fe5b919324bc1cc94245e51ac69e5b51 Mon Sep 17 00:00:00 2001 From: dbusel Date: Fri, 2 Nov 2018 16:26:59 +0300 Subject: [PATCH 15/91] Update .travis.yml --- .travis.yml | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/.travis.yml b/.travis.yml index 4df1a2e63..98cc7845d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -2,11 +2,14 @@ sudo: true language: node_js node_js: "9" stages: +- name: build + if: branch IN (develop, master) AND type = pull_request - name: package_build - if: branch = develop + if: (branch = develop AND type = cron) OR (branch = master and type = push) jobs: include: + - stage: build - stage: package_build script: - npm run build From 02503c9f44c5ae9574ff10050a1ac3b3cca06379 Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 2 Nov 2018 16:35:01 +0300 Subject: [PATCH 16/91] Running migrations and seeders programmatically (#300) (#311) * Running migrations and seeders programmatically * missing travis script command --- .gitignore | 1 - package-lock.json | 3722 ++++++++++++++++++++++++++++++ package.json | 7 +- src/logger/index.js | 2 - src/main.js | 15 +- src/sequelize/config/config.json | 1 - src/sequelize/models/index.js | 28 +- 7 files changed, 3760 insertions(+), 16 deletions(-) create mode 100644 package-lock.json diff --git a/.gitignore b/.gitignore index e514a865f..f3913bba7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules -package-lock.json .vscode *.sqlite diff --git a/package-lock.json b/package-lock.json new file mode 100644 index 000000000..a72012898 --- /dev/null +++ b/package-lock.json @@ -0,0 +1,3722 @@ +{ + "name": "iofogcontroller", + "version": "0.9.5", + "lockfileVersion": 1, + "requires": true, + "dependencies": { + "@babel/code-frame": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/code-frame/-/code-frame-7.0.0.tgz", + "integrity": "sha512-OfC2uemaknXr87bdLUkWog7nYuliM9Ij5HUcajsVcMCpQrcLmtxRbVFTIqmcSkSeYRBFBRxs2FiUqFJDLdiebA==", + "dev": true, + "requires": { + "@babel/highlight": "^7.0.0" + } + }, + "@babel/highlight": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/@babel/highlight/-/highlight-7.0.0.tgz", + "integrity": "sha512-UFMC4ZeFC48Tpvj7C8UgLvtkaUuovQX+5xNWrsIoMG8o2z+XFKjKaN9iVmS84dPwVN00W4wPmqvYoZF3EGAsfw==", + "dev": true, + "requires": { + "chalk": "^2.0.0", + "esutils": "^2.0.2", + "js-tokens": "^4.0.0" + } + }, + "@types/commander": { + "version": "2.12.2", + "resolved": "https://registry.npmjs.org/@types/commander/-/commander-2.12.2.tgz", + "integrity": "sha512-0QEFiR8ljcHp9bAbWxecjVRuAMr16ivPiGOw6KFQBVrVd0RQIcM3xKdRisH2EDWgVWujiYtHwhSkSUoAAGzH7Q==", + "requires": { + "commander": "*" + } + }, + "@types/geojson": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/@types/geojson/-/geojson-1.0.6.tgz", + "integrity": "sha512-Xqg/lIZMrUd0VRmSRbCAewtwGZiAk3mEUDvV4op1tGl+LvyPcb/MIOSxTl9z+9+J+R4/vpjiCAT4xeKzH9ji1w==" + }, + "@types/node": { + "version": "10.11.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-10.11.6.tgz", + "integrity": "sha512-fnA7yvqg3oKQDb3skBif9w5RRKVKAaeKeNuLzZL37XcSiWL4IoSXQnnbchR3UnBu2EMLHBip7ZVEkqoIVBP8QQ==" + }, + "@types/semver": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/@types/semver/-/semver-5.5.0.tgz", + "integrity": "sha512-41qEJgBH/TWgo5NFSvBCJ1qkoi3Q6ONSF2avrHq1LVEZfYpdHmj0y9SuTK+u9ZhG1sYQKBL1AWXKyLWP4RaUoQ==" + }, + "abbrev": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/abbrev/-/abbrev-1.1.1.tgz", + "integrity": "sha512-nne9/IiQ/hzIhY6pdDnbBtz7DjPTKrY00P/zvPSm5pOFkl6xuGrGnXn/VtTNNfNtAfZ9/1RtehkszU9qcTii0Q==" + }, + "accepts": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/accepts/-/accepts-1.3.5.tgz", + "integrity": "sha1-63d99gEXI6OxTopywIBcjoZ0a9I=", + "requires": { + "mime-types": "~2.1.18", + "negotiator": "0.6.1" + } + }, + "acorn": { + "version": "5.7.3", + "resolved": "https://registry.npmjs.org/acorn/-/acorn-5.7.3.tgz", + "integrity": "sha512-T/zvzYRfbVojPWahDsE5evJdHb3oJoQfFbsrKM7w5Zcs++Tr257tia3BmMP8XYVjp1S9RZXQMh7gao96BlqZOw==", + "dev": true + }, + "acorn-jsx": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/acorn-jsx/-/acorn-jsx-4.1.1.tgz", + "integrity": "sha512-JY+iV6r+cO21KtntVvFkD+iqjtdpRUpGqKWgfkCdZq1R+kbreEl8EcdcJR4SmiIgsIQT33s6QzheQ9a275Q8xw==", + "dev": true, + "requires": { + "acorn": "^5.0.3" + } + }, + "ajv": { + "version": "5.5.2", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-5.5.2.tgz", + "integrity": "sha1-c7Xuyj+rZT49P5Qis0GtQiBdyWU=", + "requires": { + "co": "^4.6.0", + "fast-deep-equal": "^1.0.0", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.3.0" + } + }, + "ajv-keywords": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/ajv-keywords/-/ajv-keywords-3.2.0.tgz", + "integrity": "sha1-6GuBnGAs+IIa1jdBNpjx3sAhhHo=", + "dev": true + }, + "ansi-escapes": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/ansi-escapes/-/ansi-escapes-3.1.0.tgz", + "integrity": "sha512-UgAb8H9D41AQnu/PbWlCofQVcnV4Gs2bBJi9eZPxfU/hgglFh3SMDMENRIqdr7H6XFnXdoknctFByVsCOotTVw==", + "dev": true + }, + "ansi-regex": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-2.1.1.tgz", + "integrity": "sha1-w7M6te42DYbg5ijwRorn7yfWVN8=" + }, + "ansi-styles": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz", + "integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==", + "requires": { + "color-convert": "^1.9.0" + } + }, + "any-promise": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/any-promise/-/any-promise-1.3.0.tgz", + "integrity": "sha1-q8av7tzqUugJzcA3au0845Y10X8=" + }, + "aproba": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/aproba/-/aproba-1.2.0.tgz", + "integrity": "sha512-Y9J6ZjXtoYh8RnXVCMOU/ttDmk1aBjunq9vO0ta5x85WDQiQfUF9sIPBITdbiiIVcBo03Hi3jMxigBtsddlXRw==" + }, + "are-we-there-yet": { + "version": "1.1.5", + "resolved": "https://registry.npmjs.org/are-we-there-yet/-/are-we-there-yet-1.1.5.tgz", + "integrity": "sha512-5hYdAkZlcG8tOLujVDTgCT+uPX0VnpAH28gWsLfzpXYm7wP6mp5Q/gYyR7YQ0cKVJcXJnl3j2kpBan13PtQf6w==", + "requires": { + "delegates": "^1.0.0", + "readable-stream": "^2.0.6" + } + }, + "argparse": { + "version": "1.0.10", + "resolved": "https://registry.npmjs.org/argparse/-/argparse-1.0.10.tgz", + "integrity": "sha512-o5Roy6tNG4SL/FOkCAN6RzjiakZS25RLYFrcMttJqbdd8BWrnA+fGz57iN5Pb06pvBGvl5gQ0B48dJlslXvoTg==", + "dev": true, + "requires": { + "sprintf-js": "~1.0.2" + } + }, + "argv-tools": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/argv-tools/-/argv-tools-0.1.1.tgz", + "integrity": "sha512-Cc0dBvx4dvrjjKpyDA6w8RlNAw8Su30NvZbWl/Tv9ZALEVlLVkWQiHMi84Q0xNfpVuSaiQbYkdmWK8g1PLGhKw==", + "requires": { + "array-back": "^2.0.0", + "find-replace": "^2.0.1" + } + }, + "array-back": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/array-back/-/array-back-2.0.0.tgz", + "integrity": "sha512-eJv4pLLufP3g5kcZry0j6WXpIbzYw9GUB4mVJZno9wfwiBxbizTnHCw3VJb07cBihbFX48Y7oSrW9y+gt4glyw==", + "requires": { + "typical": "^2.6.1" + } + }, + "array-flatten": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/array-flatten/-/array-flatten-1.1.1.tgz", + "integrity": "sha1-ml9pkFGx5wczKPKgCJaLZOopVdI=" + }, + "array-union": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/array-union/-/array-union-1.0.2.tgz", + "integrity": "sha1-mjRBDk9OPaI96jdb5b5w8kd47Dk=", + "dev": true, + "requires": { + "array-uniq": "^1.0.1" + } + }, + "array-uniq": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/array-uniq/-/array-uniq-1.0.3.tgz", + "integrity": "sha1-r2rId6Jcx/dOBYiUdThY39sk/bY=", + "dev": true + }, + "arrify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/arrify/-/arrify-1.0.1.tgz", + "integrity": "sha1-iYUI2iIm84DfkEcoRWhJwVAaSw0=", + "dev": true + }, + "asn1": { + "version": "0.2.4", + "resolved": "https://registry.npmjs.org/asn1/-/asn1-0.2.4.tgz", + "integrity": "sha512-jxwzQpLQjSmWXgwaCZE9Nz+glAG01yF1QnWgbhGwHI5A6FRIEY6IVqtHhIepHqI7/kyEyQEagBC5mBEFlIYvdg==", + "requires": { + "safer-buffer": "~2.1.0" + } + }, + "assert-plus": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/assert-plus/-/assert-plus-1.0.0.tgz", + "integrity": "sha1-8S4PPF13sLHN2RRpQuTpbB5N1SU=" + }, + "async": { + "version": "1.5.2", + "resolved": "http://registry.npmjs.org/async/-/async-1.5.2.tgz", + "integrity": "sha1-7GphrlZIDAw8skHJVhjiCJL5Zyo=" + }, + "async-listener": { + "version": "0.6.9", + "resolved": "https://registry.npmjs.org/async-listener/-/async-listener-0.6.9.tgz", + "integrity": "sha512-E7Z2/QMs0EPt/o9wpYO/J3hmMCDdr1aVDS3ttlur5D5JlZtxhfuOwi4e7S8zbYIxA5qOOYdxfqGj97XAfdNvkQ==", + "requires": { + "semver": "^5.3.0", + "shimmer": "^1.1.0" + } + }, + "asynckit": { + "version": "0.4.0", + "resolved": "https://registry.npmjs.org/asynckit/-/asynckit-0.4.0.tgz", + "integrity": "sha1-x57Zf380y48robyXkLzDZkdLS3k=" + }, + "aws-sign2": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/aws-sign2/-/aws-sign2-0.7.0.tgz", + "integrity": "sha1-tG6JCTSpWR8tL2+G1+ap8bP+dqg=" + }, + "aws4": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/aws4/-/aws4-1.8.0.tgz", + "integrity": "sha512-ReZxvNHIOv88FlT7rxcXIIC0fPt4KZqZbOlivyWtXLt8ESx84zd3kMC6iK5jVeS2qt+g7ftS7ye4fi06X5rtRQ==" + }, + "babel-runtime": { + "version": "6.26.0", + "resolved": "https://registry.npmjs.org/babel-runtime/-/babel-runtime-6.26.0.tgz", + "integrity": "sha1-llxwWGaOgrVde/4E/yM3vItWR/4=", + "requires": { + "core-js": "^2.4.0", + "regenerator-runtime": "^0.11.0" + } + }, + "balanced-match": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/balanced-match/-/balanced-match-1.0.0.tgz", + "integrity": "sha1-ibTRmasr7kneFk6gK4nORi1xt2c=" + }, + "basic-auth": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/basic-auth/-/basic-auth-2.0.1.tgz", + "integrity": "sha512-NF+epuEdnUYVlGuhaxbbq+dvJttwLnGY+YixlXlME5KpQ5W3CnXA5cVTneY3SPbPDRkcjMbifrwmFYcClgOZeg==", + "requires": { + "safe-buffer": "5.1.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "bcrypt-pbkdf": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/bcrypt-pbkdf/-/bcrypt-pbkdf-1.0.2.tgz", + "integrity": "sha1-pDAdOJtqQ/m2f/PKEaP2Y342Dp4=", + "requires": { + "tweetnacl": "^0.14.3" + } + }, + "bluebird": { + "version": "3.5.2", + "resolved": "https://registry.npmjs.org/bluebird/-/bluebird-3.5.2.tgz", + "integrity": "sha512-dhHTWMI7kMx5whMQntl7Vr9C6BvV10lFXDAasnqnrMYhXVCzzk6IO9Fo2L75jXHT07WrOngL1WDXOp+yYS91Yg==" + }, + "body-parser": { + "version": "1.18.3", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.3.tgz", + "integrity": "sha1-WykhmP/dVTs6DyDe0FkrlWlVyLQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.2", + "http-errors": "~1.6.3", + "iconv-lite": "0.4.23", + "on-finished": "~2.3.0", + "qs": "6.5.2", + "raw-body": "2.3.3", + "type-is": "~1.6.16" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "brace-expansion": { + "version": "1.1.11", + "resolved": "https://registry.npmjs.org/brace-expansion/-/brace-expansion-1.1.11.tgz", + "integrity": "sha512-iCuPHDFgrHX7H2vEI/5xpz07zSHB00TpugqhmYtVmMO6518mCuRMoOYFldEBl0g187ufozdaHgWKcYFb61qGiA==", + "requires": { + "balanced-match": "^1.0.0", + "concat-map": "0.0.1" + } + }, + "builtin-modules": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/builtin-modules/-/builtin-modules-1.1.1.tgz", + "integrity": "sha1-Jw8HbFpywC9bZaR9+Uxf46J4iS8=" + }, + "bytes": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/bytes/-/bytes-3.0.0.tgz", + "integrity": "sha1-0ygVQE1olpn4Wk6k+odV3ROpYEg=" + }, + "caller-path": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/caller-path/-/caller-path-0.1.0.tgz", + "integrity": "sha1-lAhe9jWB7NPaqSREqP6U6CV3dR8=", + "dev": true, + "requires": { + "callsites": "^0.2.0" + } + }, + "callsites": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/callsites/-/callsites-0.2.0.tgz", + "integrity": "sha1-r6uWJikQp/M8GaV3WCXGnzTjUMo=", + "dev": true + }, + "camelcase": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-2.1.1.tgz", + "integrity": "sha1-fB0W1nmhu+WcoCys7PsBHiAfWh8=" + }, + "camelize": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/camelize/-/camelize-1.0.0.tgz", + "integrity": "sha1-FkpUg+Yw+kMh5a8HAg5TGDGyYJs=" + }, + "caseless": { + "version": "0.12.0", + "resolved": "https://registry.npmjs.org/caseless/-/caseless-0.12.0.tgz", + "integrity": "sha1-G2gcIf+EAzyCZUMJBolCDRhxUdw=" + }, + "chalk": { + "version": "2.4.1", + "resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.1.tgz", + "integrity": "sha512-ObN6h1v2fTJSmUXoS3nMQ92LbDK9be4TV+6G+omQlGJFdcUX5heKi1LZ1YnRMIgwTLEj3E24bT6tYni50rlCfQ==", + "requires": { + "ansi-styles": "^3.2.1", + "escape-string-regexp": "^1.0.5", + "supports-color": "^5.3.0" + } + }, + "chardet": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/chardet/-/chardet-0.7.0.tgz", + "integrity": "sha512-mT8iDcrh03qDGRRmoA2hmBJnxpllMR+0/0qlzjqZES6NdiWDcZkCNAk4rPFZ9Q85r27unkiNNg8ZOiwZXBHwcA==", + "dev": true + }, + "chownr": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/chownr/-/chownr-1.1.1.tgz", + "integrity": "sha512-j38EvO5+LHX84jlo6h4UzmOwi0UgW61WRyPtJz4qaadK5eY3BTS5TY/S1Stc3Uk2lIM6TPevAlULiEJwie860g==" + }, + "circular-json": { + "version": "0.3.3", + "resolved": "https://registry.npmjs.org/circular-json/-/circular-json-0.3.3.tgz", + "integrity": "sha512-UZK3NBx2Mca+b5LsG7bY183pHWt5Y1xts4P3Pz7ENTwGVnJOUWbRb3ocjvX7hx9tq/yTAdclXm9sZ38gNuem4A==", + "dev": true + }, + "cli-color": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/cli-color/-/cli-color-1.3.0.tgz", + "integrity": "sha512-XmbLr8MzgOup/sPHF4nOZerCOcL7rD7vKWpEl0axUsMAY+AEimOhYva1ksskWqkLGY/bjR9h7Cfbr+RrJRfmTQ==", + "requires": { + "ansi-regex": "^2.1.1", + "d": "1", + "es5-ext": "^0.10.46", + "es6-iterator": "^2.0.3", + "memoizee": "^0.4.14", + "timers-ext": "^0.1.5" + } + }, + "cli-cursor": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cli-cursor/-/cli-cursor-2.1.0.tgz", + "integrity": "sha1-s12sN2R5+sw+lHR9QdDQ9SOP/LU=", + "dev": true, + "requires": { + "restore-cursor": "^2.0.0" + } + }, + "cli-width": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/cli-width/-/cli-width-2.2.0.tgz", + "integrity": "sha1-/xnt6Kml5XkyQUewwR8PvLq+1jk=", + "dev": true + }, + "cliui": { + "version": "3.2.0", + "resolved": "https://registry.npmjs.org/cliui/-/cliui-3.2.0.tgz", + "integrity": "sha1-EgYBU3qRbSmUD5NNo7SNWFo5IT0=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wrap-ansi": "^2.0.0" + } + }, + "cls-bluebird": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/cls-bluebird/-/cls-bluebird-2.1.0.tgz", + "integrity": "sha1-N+8eCAqP+1XC9BZPU28ZGeeWiu4=", + "requires": { + "is-bluebird": "^1.0.2", + "shimmer": "^1.1.0" + } + }, + "co": { + "version": "4.6.0", + "resolved": "https://registry.npmjs.org/co/-/co-4.6.0.tgz", + "integrity": "sha1-bqa989hTrlTMuOR7+gvz+QMfsYQ=" + }, + "code-point-at": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/code-point-at/-/code-point-at-1.1.0.tgz", + "integrity": "sha1-DQcLTQQ6W+ozovGkDi7bPZpMz3c=" + }, + "color": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/color/-/color-3.0.0.tgz", + "integrity": "sha512-jCpd5+s0s0t7p3pHQKpnJ0TpQKKdleP71LWcA0aqiljpiuAkOSUFN/dyH8ZwF0hRmFlrIuRhufds1QyEP9EB+w==", + "requires": { + "color-convert": "^1.9.1", + "color-string": "^1.5.2" + } + }, + "color-convert": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/color-convert/-/color-convert-1.9.3.tgz", + "integrity": "sha512-QfAUtd+vFdAtFQcC8CCyYt1fYWxSqAiK2cSD6zDB8N3cpsEBAvRxp9zOGg6G/SHHJYAT88/az/IuDGALsNVbGg==", + "requires": { + "color-name": "1.1.3" + } + }, + "color-name": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.3.tgz", + "integrity": "sha1-p9BVi9icQveV3UIyj3QIMcpTvCU=" + }, + "color-string": { + "version": "1.5.3", + "resolved": "https://registry.npmjs.org/color-string/-/color-string-1.5.3.tgz", + "integrity": "sha512-dC2C5qeWoYkxki5UAXapdjqO672AM4vZuPGRQfO8b5HKuKGBbKWpITyDYN7TOFKvRW7kOgAn3746clDBMDJyQw==", + "requires": { + "color-name": "^1.0.0", + "simple-swizzle": "^0.2.2" + } + }, + "colornames": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colornames/-/colornames-1.1.1.tgz", + "integrity": "sha1-+IiQMGhcfE/54qVZ9Qd+t2qBb5Y=" + }, + "colors": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/colors/-/colors-1.3.2.tgz", + "integrity": "sha512-rhP0JSBGYvpcNQj4s5AdShMeE5ahMop96cTeDl/v9qQQm2fYClE2QXZRi8wLzc+GmXSxdIqqbOIAhyObEXDbfQ==" + }, + "colorspace": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/colorspace/-/colorspace-1.1.1.tgz", + "integrity": "sha512-pI3btWyiuz7Ken0BWh9Elzsmv2bM9AhA7psXib4anUXy/orfZ/E0MbQwhSOG/9L8hLlalqrU0UhOuqxW1YjmVw==", + "requires": { + "color": "3.0.x", + "text-hex": "1.0.x" + } + }, + "combined-stream": { + "version": "1.0.7", + "resolved": "https://registry.npmjs.org/combined-stream/-/combined-stream-1.0.7.tgz", + "integrity": "sha512-brWl9y6vOB1xYPZcpZde3N9zDByXTosAeMDo4p1wzo6UMOX4vumB+TP1RZ76sfE6Md68Q0NJSrE/gbezd4Ul+w==", + "requires": { + "delayed-stream": "~1.0.0" + } + }, + "command-line-args": { + "version": "5.0.2", + "resolved": "https://registry.npmjs.org/command-line-args/-/command-line-args-5.0.2.tgz", + "integrity": "sha512-/qPcbL8zpqg53x4rAaqMFlRV4opN3pbla7I7k9x8kyOBMQoGT6WltjN6sXZuxOXw6DgdK7Ad+ijYS5gjcr7vlA==", + "requires": { + "argv-tools": "^0.1.1", + "array-back": "^2.0.0", + "find-replace": "^2.0.1", + "lodash.camelcase": "^4.3.0", + "typical": "^2.6.1" + } + }, + "command-line-usage": { + "version": "5.0.5", + "resolved": "https://registry.npmjs.org/command-line-usage/-/command-line-usage-5.0.5.tgz", + "integrity": "sha512-d8NrGylA5oCXSbGoKz05FkehDAzSmIm4K03S5VDh4d5lZAtTWfc3D1RuETtuQCn8129nYfJfDdF7P/lwcz1BlA==", + "requires": { + "array-back": "^2.0.0", + "chalk": "^2.4.1", + "table-layout": "^0.4.3", + "typical": "^2.6.1" + } + }, + "commander": { + "version": "2.19.0", + "resolved": "https://registry.npmjs.org/commander/-/commander-2.19.0.tgz", + "integrity": "sha512-6tvAOO+D6OENvRAh524Dh9jcfKTYDQAqvqezbCW82xj5X0pSrcpxtvRKHLG0yBY6SD7PSDrJaj+0AiOcKVd1Xg==" + }, + "concat-map": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/concat-map/-/concat-map-0.0.1.tgz", + "integrity": "sha1-2Klr13/Wjfd5OnMDajug1UBdR3s=" + }, + "config-chain": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/config-chain/-/config-chain-1.1.12.tgz", + "integrity": "sha512-a1eOIcu8+7lUInge4Rpf/n4Krkf3Dd9lqhljRzII1/Zno/kRtUWnznPO3jOKBmTEktkt3fkxisUcivoj0ebzoA==", + "requires": { + "ini": "^1.3.4", + "proto-list": "~1.2.1" + } + }, + "console-control-strings": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/console-control-strings/-/console-control-strings-1.1.0.tgz", + "integrity": "sha1-PXz0Rk22RG6mRL9LOVB/mFEAjo4=" + }, + "content-disposition": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/content-disposition/-/content-disposition-0.5.2.tgz", + "integrity": "sha1-DPaLud318r55YcOoUXjLhdunjLQ=" + }, + "content-security-policy-builder": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/content-security-policy-builder/-/content-security-policy-builder-2.0.0.tgz", + "integrity": "sha512-j+Nhmj1yfZAikJLImCvPJFE29x/UuBi+/MWqggGGc515JKaZrjuei2RhULJmy0MsstW3E3htl002bwmBNMKr7w==" + }, + "content-type": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/content-type/-/content-type-1.0.4.tgz", + "integrity": "sha512-hIP3EEPs8tB9AT1L+NUqtwOAps4mk2Zob89MWXMHjHWg9milF/j4osnnQLXBCBFBk/tvIG/tUc9mOUJiPBhPXA==" + }, + "continuation-local-storage": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/continuation-local-storage/-/continuation-local-storage-3.2.1.tgz", + "integrity": "sha512-jx44cconVqkCEEyLSKWwkvUXwO561jXMa3LPjTPsm5QR22PA0/mhe33FT4Xb5y74JDvt/Cq+5lm8S8rskLv9ZA==", + "requires": { + "async-listener": "^0.6.0", + "emitter-listener": "^1.1.1" + } + }, + "cookie": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/cookie/-/cookie-0.3.1.tgz", + "integrity": "sha1-5+Ch+e9DtMi6klxcWpboBtFoc7s=" + }, + "cookie-parser": { + "version": "1.4.3", + "resolved": "https://registry.npmjs.org/cookie-parser/-/cookie-parser-1.4.3.tgz", + "integrity": "sha1-D+MfoZ0AC5X0qt8fU/3CuKIDuqU=", + "requires": { + "cookie": "0.3.1", + "cookie-signature": "1.0.6" + } + }, + "cookie-signature": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/cookie-signature/-/cookie-signature-1.0.6.tgz", + "integrity": "sha1-4wOogrNCzD7oylE6eZmXNNqzriw=" + }, + "core-js": { + "version": "2.5.7", + "resolved": "https://registry.npmjs.org/core-js/-/core-js-2.5.7.tgz", + "integrity": "sha512-RszJCAxg/PP6uzXVXL6BsxSXx/B05oJAQ2vkJRjyjrEcNVycaqOmNb5OTxZPE3xa5gwZduqza6L9JOCenh/Ecw==" + }, + "core-util-is": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/core-util-is/-/core-util-is-1.0.2.tgz", + "integrity": "sha1-tf1UIgqivFq1eqtxQMlAdUUDwac=" + }, + "cross-spawn": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-5.1.0.tgz", + "integrity": "sha1-6L0O/uWPz/b4+UUQoKVUu/ojVEk=", + "requires": { + "lru-cache": "^4.0.1", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "d": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/d/-/d-1.0.0.tgz", + "integrity": "sha1-dUu1v+VUUdpppYuU1F9MWwRi1Y8=", + "requires": { + "es5-ext": "^0.10.9" + } + }, + "daemonize2": { + "version": "0.4.2", + "resolved": "https://registry.npmjs.org/daemonize2/-/daemonize2-0.4.2.tgz", + "integrity": "sha1-xuR0B4vs+n16gUACUUxHEvZP4G8=" + }, + "dashdash": { + "version": "1.14.1", + "resolved": "https://registry.npmjs.org/dashdash/-/dashdash-1.14.1.tgz", + "integrity": "sha1-hTz6D3y+L+1d4gMmuN1YEDX24vA=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "dasherize": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dasherize/-/dasherize-2.0.0.tgz", + "integrity": "sha1-bYCcnNDPe7iVLYD8hPoT1H3bEwg=" + }, + "decamelize": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/decamelize/-/decamelize-1.2.0.tgz", + "integrity": "sha1-9lNNFRSCabIDUue+4m9QH5oZEpA=" + }, + "deep-extend": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/deep-extend/-/deep-extend-0.6.0.tgz", + "integrity": "sha512-LOHxIOaPYdHlJRtCQfDIVZtfw/ufM8+rVj649RIHzcm/vGwQRXFt6OPqIFWsm2XEMrNIEtWR64sY1LEKD2vAOA==" + }, + "deep-is": { + "version": "0.1.3", + "resolved": "https://registry.npmjs.org/deep-is/-/deep-is-0.1.3.tgz", + "integrity": "sha1-s2nW+128E+7PUk+RsHD+7cNXzzQ=", + "dev": true + }, + "del": { + "version": "2.2.2", + "resolved": "https://registry.npmjs.org/del/-/del-2.2.2.tgz", + "integrity": "sha1-wSyYHQZ4RshLyvhiz/kw2Qf/0ag=", + "dev": true, + "requires": { + "globby": "^5.0.0", + "is-path-cwd": "^1.0.0", + "is-path-in-cwd": "^1.0.0", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0", + "rimraf": "^2.2.8" + } + }, + "delayed-stream": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delayed-stream/-/delayed-stream-1.0.0.tgz", + "integrity": "sha1-3zrhmayt+31ECqrgsp4icrJOxhk=" + }, + "delegates": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/delegates/-/delegates-1.0.0.tgz", + "integrity": "sha1-hMbhWbgZBP3KWaDvRM2HDTElD5o=" + }, + "depd": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.2.tgz", + "integrity": "sha1-m81S4UwJd2PnSbJ0xDRu0uVgtak=" + }, + "destroy": { + "version": "1.0.4", + "resolved": "https://registry.npmjs.org/destroy/-/destroy-1.0.4.tgz", + "integrity": "sha1-l4hXRCxEdJ5CBmE+N5RiBYJqvYA=" + }, + "detect-libc": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/detect-libc/-/detect-libc-1.0.3.tgz", + "integrity": "sha1-+hN8S9aY7fVc1c0CrFWfkaTEups=" + }, + "diagnostics": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/diagnostics/-/diagnostics-1.1.1.tgz", + "integrity": "sha512-8wn1PmdunLJ9Tqbx+Fx/ZEuHfJf4NKSN2ZBj7SJC/OWRWha843+WsTjqMe1B5E3p28jqBlp+mJ2fPVxPyNgYKQ==", + "requires": { + "colorspace": "1.1.x", + "enabled": "1.0.x", + "kuler": "1.0.x" + } + }, + "dns-prefetch-control": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/dns-prefetch-control/-/dns-prefetch-control-0.1.0.tgz", + "integrity": "sha1-YN20V3dOF48flBXwyrsOhbCzALI=" + }, + "doctrine": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/doctrine/-/doctrine-2.1.0.tgz", + "integrity": "sha512-35mSku4ZXK0vfCuHEDAwt55dg2jNajHZ1odvF+8SSr82EsZY4QmXfuWso8oEd8zRhVObSN18aM0CjSdoBX7zIw==", + "dev": true, + "requires": { + "esutils": "^2.0.2" + } + }, + "dont-sniff-mimetype": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/dont-sniff-mimetype/-/dont-sniff-mimetype-1.0.0.tgz", + "integrity": "sha1-WTKJDcn04vGeXrAqIAJuXl78j1g=" + }, + "dottie": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/dottie/-/dottie-2.0.0.tgz", + "integrity": "sha1-2hkZgci41xPKARXViYzzl8Lw3dA=" + }, + "ecc-jsbn": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/ecc-jsbn/-/ecc-jsbn-0.1.2.tgz", + "integrity": "sha1-OoOpBOVDUyh4dMVkt1SThoSamMk=", + "requires": { + "jsbn": "~0.1.0", + "safer-buffer": "^2.1.0" + } + }, + "editorconfig": { + "version": "0.15.0", + "resolved": "https://registry.npmjs.org/editorconfig/-/editorconfig-0.15.0.tgz", + "integrity": "sha512-j7JBoj/bpNzvoTQylfRZSc85MlLNKWQiq5y6gwKhmqD2h1eZ+tH4AXbkhEJD468gjDna/XMx2YtSkCxBRX9OGg==", + "requires": { + "@types/commander": "^2.11.0", + "@types/semver": "^5.4.0", + "commander": "^2.11.0", + "lru-cache": "^4.1.1", + "semver": "^5.4.1", + "sigmund": "^1.0.1" + } + }, + "ee-first": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/ee-first/-/ee-first-1.1.1.tgz", + "integrity": "sha1-WQxhFWsK4vTwJVcyoViyZrxWsh0=" + }, + "ejs": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/ejs/-/ejs-2.6.1.tgz", + "integrity": "sha512-0xy4A/twfrRCnkhfk8ErDi5DqdAsAqeGxht4xkCUrsvhhbQNs7E+4jV0CN7+NKIY0aHE72+XvqtBIXzD31ZbXQ==" + }, + "emitter-listener": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/emitter-listener/-/emitter-listener-1.1.2.tgz", + "integrity": "sha512-Bt1sBAGFHY9DKY+4/2cV6izcKJUf5T7/gkdmkxzX/qv9CcGH8xSwVRW5mtX03SWJtRTWSOpzCuWN9rBFYZepZQ==", + "requires": { + "shimmer": "^1.2.0" + } + }, + "enabled": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/enabled/-/enabled-1.0.2.tgz", + "integrity": "sha1-ll9lE9LC0cX0ZStkouM5ZGf8L5M=", + "requires": { + "env-variable": "0.0.x" + } + }, + "encodeurl": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/encodeurl/-/encodeurl-1.0.2.tgz", + "integrity": "sha1-rT/0yG7C0CkyL1oCw6mmBslbP1k=" + }, + "env-variable": { + "version": "0.0.5", + "resolved": "https://registry.npmjs.org/env-variable/-/env-variable-0.0.5.tgz", + "integrity": "sha512-zoB603vQReOFvTg5xMl9I1P2PnHsHQQKTEowsKKD7nseUfJq6UWzK+4YtlWUO1nhiQUxe6XMkk+JleSZD1NZFA==" + }, + "error-ex": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/error-ex/-/error-ex-1.3.2.tgz", + "integrity": "sha512-7dFHNmqeFSEt2ZBsCriorKnn3Z2pj+fd9kmI6QoWw4//DL+icEBfc0U7qJCisqrTsKTjw4fNFy2pW9OqStD84g==", + "requires": { + "is-arrayish": "^0.2.1" + } + }, + "es5-ext": { + "version": "0.10.46", + "resolved": "https://registry.npmjs.org/es5-ext/-/es5-ext-0.10.46.tgz", + "integrity": "sha512-24XxRvJXNFwEMpJb3nOkiRJKRoupmjYmOPVlI65Qy2SrtxwOTB+g6ODjBKOtwEHbYrhWRty9xxOWLNdClT2djw==", + "requires": { + "es6-iterator": "~2.0.3", + "es6-symbol": "~3.1.1", + "next-tick": "1" + } + }, + "es6-iterator": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/es6-iterator/-/es6-iterator-2.0.3.tgz", + "integrity": "sha1-p96IkUGgWpSwhUQDstCg+/qY87c=", + "requires": { + "d": "1", + "es5-ext": "^0.10.35", + "es6-symbol": "^3.1.1" + } + }, + "es6-symbol": { + "version": "3.1.1", + "resolved": "https://registry.npmjs.org/es6-symbol/-/es6-symbol-3.1.1.tgz", + "integrity": "sha1-vwDvT9q2uhtG7Le2KbTH7VcVzHc=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "es6-weak-map": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/es6-weak-map/-/es6-weak-map-2.0.2.tgz", + "integrity": "sha1-XjqzIlH/0VOKH45f+hNXdy+S2W8=", + "requires": { + "d": "1", + "es5-ext": "^0.10.14", + "es6-iterator": "^2.0.1", + "es6-symbol": "^3.1.1" + } + }, + "escape-html": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/escape-html/-/escape-html-1.0.3.tgz", + "integrity": "sha1-Aljq5NPQwJdN4cFpGI7wBR0dGYg=" + }, + "escape-string-regexp": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz", + "integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=" + }, + "eslint": { + "version": "5.6.1", + "resolved": "https://registry.npmjs.org/eslint/-/eslint-5.6.1.tgz", + "integrity": "sha512-hgrDtGWz368b7Wqf+v1Z69O3ZebNR0+GA7PtDdbmuz4rInFVUV9uw7whjZEiWyLzCjVb5Rs5WRN1TAS6eo7AYA==", + "dev": true, + "requires": { + "@babel/code-frame": "^7.0.0", + "ajv": "^6.5.3", + "chalk": "^2.1.0", + "cross-spawn": "^6.0.5", + "debug": "^4.0.1", + "doctrine": "^2.1.0", + "eslint-scope": "^4.0.0", + "eslint-utils": "^1.3.1", + "eslint-visitor-keys": "^1.0.0", + "espree": "^4.0.0", + "esquery": "^1.0.1", + "esutils": "^2.0.2", + "file-entry-cache": "^2.0.0", + "functional-red-black-tree": "^1.0.1", + "glob": "^7.1.2", + "globals": "^11.7.0", + "ignore": "^4.0.6", + "imurmurhash": "^0.1.4", + "inquirer": "^6.1.0", + "is-resolvable": "^1.1.0", + "js-yaml": "^3.12.0", + "json-stable-stringify-without-jsonify": "^1.0.1", + "levn": "^0.3.0", + "lodash": "^4.17.5", + "minimatch": "^3.0.4", + "mkdirp": "^0.5.1", + "natural-compare": "^1.4.0", + "optionator": "^0.8.2", + "path-is-inside": "^1.0.2", + "pluralize": "^7.0.0", + "progress": "^2.0.0", + "regexpp": "^2.0.0", + "require-uncached": "^1.0.3", + "semver": "^5.5.1", + "strip-ansi": "^4.0.0", + "strip-json-comments": "^2.0.1", + "table": "^4.0.3", + "text-table": "^0.2.0" + }, + "dependencies": { + "ajv": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dev": true, + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "debug": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/debug/-/debug-4.1.0.tgz", + "integrity": "sha512-heNPJUJIqC+xB6ayLAMHaIrmN9HKa7aQO8MGqKpvCA+uJYVcvR6l5kgdrhRuwPFHU7P5/A1w0BjByPHwpfTDKg==", + "dev": true, + "requires": { + "ms": "^2.1.1" + } + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==", + "dev": true + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "eslint-scope": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/eslint-scope/-/eslint-scope-4.0.0.tgz", + "integrity": "sha512-1G6UTDi7Jc1ELFwnR58HV4fK9OQK4S6N985f166xqXxpjU6plxFISJa2Ba9KCQuFa8RCnj/lSFJbHo7UFDBnUA==", + "dev": true, + "requires": { + "esrecurse": "^4.1.0", + "estraverse": "^4.1.1" + } + }, + "eslint-utils": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/eslint-utils/-/eslint-utils-1.3.1.tgz", + "integrity": "sha512-Z7YjnIldX+2XMcjr7ZkgEsOj/bREONV60qYeB/bjMAqqqZ4zxKyWX+BOUkdmRmA9riiIPVvo5x86m5elviOk0Q==", + "dev": true + }, + "eslint-visitor-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/eslint-visitor-keys/-/eslint-visitor-keys-1.0.0.tgz", + "integrity": "sha512-qzm/XxIbxm/FHyH341ZrbnMUpe+5Bocte9xkmFMzPMjRaZMcXww+MpBptFvtU+79L362nqiLhekCxCxDPaUMBQ==", + "dev": true + }, + "espree": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/espree/-/espree-4.0.0.tgz", + "integrity": "sha512-kapdTCt1bjmspxStVKX6huolXVV5ZfyZguY1lcfhVVZstce3bqxH9mcLzNn3/mlgW6wQ732+0fuG9v7h0ZQoKg==", + "dev": true, + "requires": { + "acorn": "^5.6.0", + "acorn-jsx": "^4.1.1" + } + }, + "esprima": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/esprima/-/esprima-4.0.1.tgz", + "integrity": "sha512-eGuFFw7Upda+g4p+QHvnW0RyTX/SVeJBDM/gCtMARO0cLuT2HcEKnTPvhjV6aGeqrCB/sbNop0Kszm0jsaWU4A==", + "dev": true + }, + "esquery": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/esquery/-/esquery-1.0.1.tgz", + "integrity": "sha512-SmiyZ5zIWH9VM+SRUReLS5Q8a7GxtRdxEBVZpm98rJM7Sb+A9DVCndXfkeFUd3byderg+EbDkfnevfCwynWaNA==", + "dev": true, + "requires": { + "estraverse": "^4.0.0" + } + }, + "esrecurse": { + "version": "4.2.1", + "resolved": "https://registry.npmjs.org/esrecurse/-/esrecurse-4.2.1.tgz", + "integrity": "sha512-64RBB++fIOAXPw3P9cy89qfMlvZEXZkqqJkjqqXIvzP5ezRZjW+lPWjw35UX/3EhUPFYbg5ER4JYgDw4007/DQ==", + "dev": true, + "requires": { + "estraverse": "^4.1.0" + } + }, + "estraverse": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/estraverse/-/estraverse-4.2.0.tgz", + "integrity": "sha1-De4/7TH81GlhjOc0IJn8GvoL2xM=", + "dev": true + }, + "esutils": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/esutils/-/esutils-2.0.2.tgz", + "integrity": "sha1-Cr9PHKpbyx96nYrMbepPqqBLrJs=", + "dev": true + }, + "etag": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/etag/-/etag-1.8.1.tgz", + "integrity": "sha1-Qa4u62XvpiJorr/qg6x9eSmbCIc=" + }, + "event-emitter": { + "version": "0.3.5", + "resolved": "https://registry.npmjs.org/event-emitter/-/event-emitter-0.3.5.tgz", + "integrity": "sha1-34xp7vFkeSPHFXuc6DhAYQsCzDk=", + "requires": { + "d": "1", + "es5-ext": "~0.10.14" + } + }, + "execa": { + "version": "0.7.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-0.7.0.tgz", + "integrity": "sha1-lEvs00zEHuMqY6n68nrVpl/Fl3c=", + "requires": { + "cross-spawn": "^5.0.1", + "get-stream": "^3.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "expect-ct": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/expect-ct/-/expect-ct-0.1.1.tgz", + "integrity": "sha512-ngXzTfoRGG7fYens3/RMb6yYoVLvLMfmsSllP/mZPxNHgFq41TmPSLF/nLY7fwoclI2vElvAmILFWGUYqdjfCg==" + }, + "express": { + "version": "4.16.3", + "resolved": "http://registry.npmjs.org/express/-/express-4.16.3.tgz", + "integrity": "sha1-avilAjUNsyRuzEvs9rWjTSL37VM=", + "requires": { + "accepts": "~1.3.5", + "array-flatten": "1.1.1", + "body-parser": "1.18.2", + "content-disposition": "0.5.2", + "content-type": "~1.0.4", + "cookie": "0.3.1", + "cookie-signature": "1.0.6", + "debug": "2.6.9", + "depd": "~1.1.2", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "finalhandler": "1.1.1", + "fresh": "0.5.2", + "merge-descriptors": "1.0.1", + "methods": "~1.1.2", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "path-to-regexp": "0.1.7", + "proxy-addr": "~2.0.3", + "qs": "6.5.1", + "range-parser": "~1.2.0", + "safe-buffer": "5.1.1", + "send": "0.16.2", + "serve-static": "1.13.2", + "setprototypeof": "1.1.0", + "statuses": "~1.4.0", + "type-is": "~1.6.16", + "utils-merge": "1.0.1", + "vary": "~1.1.2" + }, + "dependencies": { + "body-parser": { + "version": "1.18.2", + "resolved": "https://registry.npmjs.org/body-parser/-/body-parser-1.18.2.tgz", + "integrity": "sha1-h2eKGdhLR9hZuDGZvVm84iKxBFQ=", + "requires": { + "bytes": "3.0.0", + "content-type": "~1.0.4", + "debug": "2.6.9", + "depd": "~1.1.1", + "http-errors": "~1.6.2", + "iconv-lite": "0.4.19", + "on-finished": "~2.3.0", + "qs": "6.5.1", + "raw-body": "2.3.2", + "type-is": "~1.6.15" + } + }, + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "iconv-lite": { + "version": "0.4.19", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.19.tgz", + "integrity": "sha512-oTZqweIP51xaGPI4uPa56/Pri/480R+mo7SeU+YETByQNhDG55ycFyNLIgta9vXhILrxXDmF7ZGhqZIcuN0gJQ==" + }, + "qs": { + "version": "6.5.1", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.1.tgz", + "integrity": "sha512-eRzhrN1WSINYCDCbrz796z37LOe3m5tmW7RQf6oBntukAG1nmovJvhnwHHRMAfeoItc1m2Hk02WER2aQ/iqs+A==" + }, + "raw-body": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.2.tgz", + "integrity": "sha1-vNYMd9Prk83gBQKVw/N5OJvIj4k=", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.2", + "iconv-lite": "0.4.19", + "unpipe": "1.0.0" + }, + "dependencies": { + "depd": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/depd/-/depd-1.1.1.tgz", + "integrity": "sha1-V4O04cRZ8G+lyif5kfPQbnoxA1k=" + }, + "http-errors": { + "version": "1.6.2", + "resolved": "https://registry.npmjs.org/http-errors/-/http-errors-1.6.2.tgz", + "integrity": "sha1-CgAsyFcHGSp+eUbO7cERVfYOxzY=", + "requires": { + "depd": "1.1.1", + "inherits": "2.0.3", + "setprototypeof": "1.0.3", + "statuses": ">= 1.3.1 < 2" + } + }, + "setprototypeof": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.0.3.tgz", + "integrity": "sha1-ZlZ+NwQ+608E2RvWWMDL77VbjgQ=" + } + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "extend": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/extend/-/extend-3.0.2.tgz", + "integrity": "sha512-fjquC59cD7CyW6urNXK0FBufkZcoiGG80wTuPujX590cB5Ttln20E2UB4S/WARVqhXffZl2LNgS+gQdPIIim/g==" + }, + "external-editor": { + "version": "3.0.3", + "resolved": "https://registry.npmjs.org/external-editor/-/external-editor-3.0.3.tgz", + "integrity": "sha512-bn71H9+qWoOQKyZDo25mOMVpSmXROAsTJVVVYzrrtol3d4y+AsKjf4Iwl2Q+IuT0kFSQ1qo166UuIwqYq7mGnA==", + "dev": true, + "requires": { + "chardet": "^0.7.0", + "iconv-lite": "^0.4.24", + "tmp": "^0.0.33" + }, + "dependencies": { + "iconv-lite": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.24.tgz", + "integrity": "sha512-v3MXnZAcvnywkTUEZomIActle7RXXeedOR31wwl7VlyoXO4Qi9arvSenNQWne1TcRwhCL1HwLI21bEqdpj8/rA==", + "dev": true, + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + } + } + }, + "extsprintf": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/extsprintf/-/extsprintf-1.3.0.tgz", + "integrity": "sha1-lpGEQOMEGnpBT4xS48V06zw+HgU=" + }, + "fast-deep-equal": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-1.1.0.tgz", + "integrity": "sha1-wFNHeBfIa1HaqFPIHgWbcz0CNhQ=" + }, + "fast-json-stable-stringify": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/fast-json-stable-stringify/-/fast-json-stable-stringify-2.0.0.tgz", + "integrity": "sha1-1RQsDK7msRifh9OnYREGT4bIu/I=" + }, + "fast-levenshtein": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-levenshtein/-/fast-levenshtein-2.0.6.tgz", + "integrity": "sha1-PYpcZog6FqMMqGQ+hR8Zuqd5eRc=", + "dev": true + }, + "fast-safe-stringify": { + "version": "2.0.6", + "resolved": "https://registry.npmjs.org/fast-safe-stringify/-/fast-safe-stringify-2.0.6.tgz", + "integrity": "sha512-q8BZ89jjc+mz08rSxROs8VsrBBcn1SIw1kq9NjolL509tkABRk9io01RAjSaEv1Xb2uFLt8VtRiZbGp5H8iDtg==" + }, + "feature-policy": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/feature-policy/-/feature-policy-0.1.0.tgz", + "integrity": "sha512-Sq+O5vUN0wQGOLGKzDXY1xCY6dOPic2ufMEF0xpVHIW+Dr8LocJ7Jhnvo5ZBCXKqWUgmGIqcF5AIJR+Wnq2SQw==" + }, + "fecha": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/fecha/-/fecha-2.3.3.tgz", + "integrity": "sha512-lUGBnIamTAwk4znq5BcqsDaxSmZ9nDVJaij6NvRt/Tg4R69gERA+otPKbS86ROw9nxVMw2/mp1fnaiWqbs6Sdg==" + }, + "figures": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/figures/-/figures-2.0.0.tgz", + "integrity": "sha1-OrGi0qYsi/tDGgyUy3l6L84nyWI=", + "dev": true, + "requires": { + "escape-string-regexp": "^1.0.5" + } + }, + "file-entry-cache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/file-entry-cache/-/file-entry-cache-2.0.0.tgz", + "integrity": "sha1-w5KZDD5oR4PYOLjISkXYoEhFg2E=", + "dev": true, + "requires": { + "flat-cache": "^1.2.1", + "object-assign": "^4.0.1" + } + }, + "finalhandler": { + "version": "1.1.1", + "resolved": "http://registry.npmjs.org/finalhandler/-/finalhandler-1.1.1.tgz", + "integrity": "sha512-Y1GUDo39ez4aHAw7MysnUD5JzYX+WaIj8I57kO3aEPT1fFRL4sr7mjei97FgnwhAyyzRYmQZaTHb2+9uZ1dPtg==", + "requires": { + "debug": "2.6.9", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "on-finished": "~2.3.0", + "parseurl": "~1.3.2", + "statuses": "~1.4.0", + "unpipe": "~1.0.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "find-replace": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/find-replace/-/find-replace-2.0.1.tgz", + "integrity": "sha512-LzDo3Fpa30FLIBsh6DCDnMN1KW2g4QKkqKmejlImgWY67dDFPX/x9Kh/op/GK522DchQXEvDi/wD48HKW49XOQ==", + "requires": { + "array-back": "^2.0.0", + "test-value": "^3.0.0" + } + }, + "find-up": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/find-up/-/find-up-2.1.0.tgz", + "integrity": "sha1-RdG35QbHF93UgndaK3eSCjwMV6c=", + "requires": { + "locate-path": "^2.0.0" + } + }, + "flat-cache": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/flat-cache/-/flat-cache-1.3.0.tgz", + "integrity": "sha1-0wMLMrOBVPTjt+nHCfSQ9++XxIE=", + "dev": true, + "requires": { + "circular-json": "^0.3.1", + "del": "^2.0.2", + "graceful-fs": "^4.1.2", + "write": "^0.2.1" + } + }, + "forever-agent": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/forever-agent/-/forever-agent-0.6.1.tgz", + "integrity": "sha1-+8cfDEGt6zf5bFd60e1C2P2sypE=" + }, + "form-data": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/form-data/-/form-data-2.3.3.tgz", + "integrity": "sha512-1lLKB2Mu3aGP1Q/2eCOx0fNbRMe7XdwktwOruhfqqd0rIJWwN4Dh+E3hrPSlDCXnSR7UtZ1N38rVXm+6+MEhJQ==", + "requires": { + "asynckit": "^0.4.0", + "combined-stream": "^1.0.6", + "mime-types": "^2.1.12" + } + }, + "formidable": { + "version": "1.2.1", + "resolved": "https://registry.npmjs.org/formidable/-/formidable-1.2.1.tgz", + "integrity": "sha512-Fs9VRguL0gqGHkXS5GQiMCr1VhZBxz0JnJs4JmMp/2jL18Fmbzvv7vOFRU+U8TBkHEE/CX1qDXzJplVULgsLeg==" + }, + "forwarded": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/forwarded/-/forwarded-0.1.2.tgz", + "integrity": "sha1-mMI9qxF1ZXuMBXPozszZGw/xjIQ=" + }, + "frameguard": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/frameguard/-/frameguard-3.0.0.tgz", + "integrity": "sha1-e8rUae57lukdEs6zlZx4I1qScuk=" + }, + "fresh": { + "version": "0.5.2", + "resolved": "https://registry.npmjs.org/fresh/-/fresh-0.5.2.tgz", + "integrity": "sha1-PYyt2Q2XZWn6g1qx+OSyOhBWBac=" + }, + "fs": { + "version": "0.0.1-security", + "resolved": "https://registry.npmjs.org/fs/-/fs-0.0.1-security.tgz", + "integrity": "sha1-invTcYa23d84E/I4WLV+yq9eQdQ=" + }, + "fs-extra": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/fs-extra/-/fs-extra-5.0.0.tgz", + "integrity": "sha512-66Pm4RYbjzdyeuqudYqhFiNBbCIuI9kgRqLPSHIlXHidW8NIQtVdkM1yeZ4lXwuhbTETv3EUGMNHAAw6hiundQ==", + "requires": { + "graceful-fs": "^4.1.2", + "jsonfile": "^4.0.0", + "universalify": "^0.1.0" + } + }, + "fs-minipass": { + "version": "1.2.5", + "resolved": "https://registry.npmjs.org/fs-minipass/-/fs-minipass-1.2.5.tgz", + "integrity": "sha512-JhBl0skXjUPCFH7x6x61gQxrKyXsxB5gcgePLZCwfyCGGsTISMoIeObbrvVeP6Xmyaudw4TT43qV2Gz+iyd2oQ==", + "requires": { + "minipass": "^2.2.1" + } + }, + "fs.realpath": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/fs.realpath/-/fs.realpath-1.0.0.tgz", + "integrity": "sha1-FQStJSMVjKpA20onh8sBQRmU6k8=" + }, + "ftp": { + "version": "0.3.10", + "resolved": "https://registry.npmjs.org/ftp/-/ftp-0.3.10.tgz", + "integrity": "sha1-kZfYYa2BQvPmPVqDv+TFn3MwiF0=", + "requires": { + "readable-stream": "1.1.x", + "xregexp": "2.0.0" + }, + "dependencies": { + "isarray": { + "version": "0.0.1", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-0.0.1.tgz", + "integrity": "sha1-ihis/Kmo9Bd+Cav8YDiTmwXR7t8=" + }, + "readable-stream": { + "version": "1.1.14", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-1.1.14.tgz", + "integrity": "sha1-fPTFTvZI44EwhMY23SB54WbAgdk=", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.1", + "isarray": "0.0.1", + "string_decoder": "~0.10.x" + } + }, + "string_decoder": { + "version": "0.10.31", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-0.10.31.tgz", + "integrity": "sha1-YuIDvEF2bGwoyfyEMB2rHFMQ+pQ=" + } + } + }, + "functional-red-black-tree": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/functional-red-black-tree/-/functional-red-black-tree-1.0.1.tgz", + "integrity": "sha1-GwqzvVU7Kg1jmdKcDj6gslIHgyc=", + "dev": true + }, + "gauge": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/gauge/-/gauge-2.7.4.tgz", + "integrity": "sha1-LANAXHU4w51+s3sxcCLjJfsBi/c=", + "requires": { + "aproba": "^1.0.3", + "console-control-strings": "^1.0.0", + "has-unicode": "^2.0.0", + "object-assign": "^4.1.0", + "signal-exit": "^3.0.0", + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1", + "wide-align": "^1.1.0" + } + }, + "generic-pool": { + "version": "3.4.2", + "resolved": "https://registry.npmjs.org/generic-pool/-/generic-pool-3.4.2.tgz", + "integrity": "sha512-H7cUpwCQSiJmAHM4c/aFu6fUfrhWXW1ncyh8ftxEPMu6AiYkHw9K8br720TGPZJbk5eOH2bynjZD1yPvdDAmag==" + }, + "get-caller-file": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/get-caller-file/-/get-caller-file-1.0.3.tgz", + "integrity": "sha512-3t6rVToeoZfYSGd8YoLFR2DJkiQrIiUrGcjvFX2mDw3bn6k2OtwHN0TNCLbBO+w8qTvimhDkv+LSscbJY1vE6w==" + }, + "get-stream": { + "version": "3.0.0", + "resolved": "http://registry.npmjs.org/get-stream/-/get-stream-3.0.0.tgz", + "integrity": "sha1-jpQ9E1jcN1VQVOy+LtsFqhdO3hQ=" + }, + "getpass": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/getpass/-/getpass-0.1.7.tgz", + "integrity": "sha1-Xv+OPmhNVprkyysSgmBOi6YhSfo=", + "requires": { + "assert-plus": "^1.0.0" + } + }, + "glob": { + "version": "7.1.3", + "resolved": "https://registry.npmjs.org/glob/-/glob-7.1.3.tgz", + "integrity": "sha512-vcfuiIxogLV4DlGBHIUOwI0IbrJ8HWPc4MU7HzviGeNho/UJDfi6B5p3sHeWIQ0KGIU0Jpxi5ZHxemQfLkkAwQ==", + "requires": { + "fs.realpath": "^1.0.0", + "inflight": "^1.0.4", + "inherits": "2", + "minimatch": "^3.0.4", + "once": "^1.3.0", + "path-is-absolute": "^1.0.0" + } + }, + "globals": { + "version": "11.8.0", + "resolved": "https://registry.npmjs.org/globals/-/globals-11.8.0.tgz", + "integrity": "sha512-io6LkyPVuzCHBSQV9fmOwxZkUk6nIaGmxheLDgmuFv89j0fm2aqDbIXKAGfzCMHqz3HLF2Zf8WSG6VqMh2qFmA==", + "dev": true + }, + "globby": { + "version": "5.0.0", + "resolved": "https://registry.npmjs.org/globby/-/globby-5.0.0.tgz", + "integrity": "sha1-69hGZ8oNuzMLmbz8aOrCvFQ3Dg0=", + "dev": true, + "requires": { + "array-union": "^1.0.1", + "arrify": "^1.0.0", + "glob": "^7.0.3", + "object-assign": "^4.0.1", + "pify": "^2.0.0", + "pinkie-promise": "^2.0.0" + } + }, + "graceful-fs": { + "version": "4.1.11", + "resolved": "https://registry.npmjs.org/graceful-fs/-/graceful-fs-4.1.11.tgz", + "integrity": "sha1-Dovf5NHduIVNZOBOp8AOKgJuVlg=" + }, + "har-schema": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/har-schema/-/har-schema-2.0.0.tgz", + "integrity": "sha1-qUwiJOvKwEeCoNkDVSHyRzW37JI=" + }, + "har-validator": { + "version": "5.1.0", + "resolved": "https://registry.npmjs.org/har-validator/-/har-validator-5.1.0.tgz", + "integrity": "sha512-+qnmNjI4OfH2ipQ9VQOw23bBd/ibtfbVdK2fYbY4acTDqKTW/YDp9McimZdDbG8iV9fZizUqQMD5xvriB146TA==", + "requires": { + "ajv": "^5.3.0", + "har-schema": "^2.0.0" + } + }, + "has-flag": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz", + "integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=" + }, + "has-unicode": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/has-unicode/-/has-unicode-2.0.1.tgz", + "integrity": "sha1-4Ob+aijPUROIVeCG0Wkedx3iqLk=" + }, + "helmet": { + "version": "3.14.0", + "resolved": "https://registry.npmjs.org/helmet/-/helmet-3.14.0.tgz", + "integrity": "sha512-VUOjHxegTX/dIr1KeU4ZrIkP8k0/nKKD6vNBT1LCS2+q5KO1oMFKGMVdMw/pUcxXbn/z8yP9rfyMZSTpxXPPMg==", + "requires": { + "dns-prefetch-control": "0.1.0", + "dont-sniff-mimetype": "1.0.0", + "expect-ct": "0.1.1", + "feature-policy": "0.1.0", + "frameguard": "3.0.0", + "helmet-crossdomain": "0.3.0", + "helmet-csp": "2.7.1", + "hide-powered-by": "1.0.0", + "hpkp": "2.0.0", + "hsts": "2.1.0", + "ienoopen": "1.0.0", + "nocache": "2.0.0", + "referrer-policy": "1.1.0", + "x-xss-protection": "1.1.0" + } + }, + "helmet-crossdomain": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/helmet-crossdomain/-/helmet-crossdomain-0.3.0.tgz", + "integrity": "sha512-YiXhj0E35nC4Na5EPE4mTfoXMf9JTGpN4OtB4aLqShKuH9d2HNaJX5MQoglO6STVka0uMsHyG5lCut5Kzsy7Lg==" + }, + "helmet-csp": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/helmet-csp/-/helmet-csp-2.7.1.tgz", + "integrity": "sha512-sCHwywg4daQ2mY0YYwXSZRsgcCeerUwxMwNixGA7aMLkVmPTYBl7gJoZDHOZyXkqPrtuDT3s2B1A+RLI7WxSdQ==", + "requires": { + "camelize": "1.0.0", + "content-security-policy-builder": "2.0.0", + "dasherize": "2.0.0", + "platform": "1.3.5" + } + }, + "hide-powered-by": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/hide-powered-by/-/hide-powered-by-1.0.0.tgz", + "integrity": "sha1-SoWtZYgfYoV/xwr3F0oRhNzM4ys=" + }, + "hosted-git-info": { + "version": "2.7.1", + "resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.7.1.tgz", + "integrity": "sha512-7T/BxH19zbcCTa8XkMlbK5lTo1WtgkFi3GvdWEyNuc4Vex7/9Dqbnpsf4JMydcfj9HCg4zUWFTL3Za6lapg5/w==" + }, + "hpkp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/hpkp/-/hpkp-2.0.0.tgz", + "integrity": "sha1-EOFCJk52IVpdMMROxD3mTe5tFnI=" + }, + "hsts": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/hsts/-/hsts-2.1.0.tgz", + "integrity": "sha512-zXhh/DqgrTXJ7erTN6Fh5k/xjMhDGXCqdYN3wvxUvGUQvnxcFfUd8E+6vLg/nk3ss1TYMb+DhRl25fYABioTvA==" + }, + "http-errors": { + "version": "1.6.3", + "resolved": "http://registry.npmjs.org/http-errors/-/http-errors-1.6.3.tgz", + "integrity": "sha1-i1VoC7S+KDoLW/TqLjhYC+HZMg0=", + "requires": { + "depd": "~1.1.2", + "inherits": "2.0.3", + "setprototypeof": "1.1.0", + "statuses": ">= 1.4.0 < 2" + } + }, + "http-signature": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/http-signature/-/http-signature-1.2.0.tgz", + "integrity": "sha1-muzZJRFHcvPZW2WmCruPfBj7rOE=", + "requires": { + "assert-plus": "^1.0.0", + "jsprim": "^1.2.2", + "sshpk": "^1.7.0" + } + }, + "httpntlm": { + "version": "1.6.1", + "resolved": "https://registry.npmjs.org/httpntlm/-/httpntlm-1.6.1.tgz", + "integrity": "sha1-rQFScUOi6Hc8+uapb1hla7UqNLI=", + "requires": { + "httpreq": ">=0.4.22", + "underscore": "~1.7.0" + }, + "dependencies": { + "underscore": { + "version": "1.7.0", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.7.0.tgz", + "integrity": "sha1-a7rwh3UA02vjTsqlhODbn+8DUgk=" + } + } + }, + "httpreq": { + "version": "0.4.24", + "resolved": "https://registry.npmjs.org/httpreq/-/httpreq-0.4.24.tgz", + "integrity": "sha1-QzX/2CzZaWaKOUZckprGHWOTYn8=" + }, + "iconv-lite": { + "version": "0.4.23", + "resolved": "https://registry.npmjs.org/iconv-lite/-/iconv-lite-0.4.23.tgz", + "integrity": "sha512-neyTUVFtahjf0mB3dZT77u+8O0QB89jFdnBkd5P1JgYPbPaia3gXXOVL2fq8VyU2gMMD7SaN7QukTB/pmXYvDA==", + "requires": { + "safer-buffer": ">= 2.1.2 < 3" + } + }, + "ienoopen": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/ienoopen/-/ienoopen-1.0.0.tgz", + "integrity": "sha1-NGpCj0dKrI9QzzeE6i0PFvYr2ms=" + }, + "ignore": { + "version": "4.0.6", + "resolved": "https://registry.npmjs.org/ignore/-/ignore-4.0.6.tgz", + "integrity": "sha512-cyFDKrqc/YdcWFniJhzI42+AzS+gNwmUzOSFcRCQYwySuBBBy/KjuxWLZ/FHEH6Moq1NizMOBWyTcv8O4OZIMg==", + "dev": true + }, + "ignore-walk": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/ignore-walk/-/ignore-walk-3.0.1.tgz", + "integrity": "sha512-DTVlMx3IYPe0/JJcYP7Gxg7ttZZu3IInhuEhbchuqneY9wWe5Ojy2mXLBaQFUQmo0AW2r3qG7m1mg86js+gnlQ==", + "requires": { + "minimatch": "^3.0.4" + } + }, + "imurmurhash": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/imurmurhash/-/imurmurhash-0.1.4.tgz", + "integrity": "sha1-khi5srkoojixPcT7a21XbyMUU+o=", + "dev": true + }, + "inflection": { + "version": "1.12.0", + "resolved": "https://registry.npmjs.org/inflection/-/inflection-1.12.0.tgz", + "integrity": "sha1-ogCTVlbW9fa8TcdQLhrstwMihBY=" + }, + "inflight": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/inflight/-/inflight-1.0.6.tgz", + "integrity": "sha1-Sb1jMdfQLQwJvJEKEHW6gWW1bfk=", + "requires": { + "once": "^1.3.0", + "wrappy": "1" + } + }, + "inherits": { + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/inherits/-/inherits-2.0.3.tgz", + "integrity": "sha1-Yzwsg+PaQqUC9SRmAiSA9CCCYd4=" + }, + "ini": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/ini/-/ini-1.3.5.tgz", + "integrity": "sha512-RZY5huIKCMRWDUqZlEi72f/lmXKMvuszcMBduliQ3nnWbx9X/ZBQO7DijMEYS9EhHBb2qacRUMtC7svLwe0lcw==" + }, + "inquirer": { + "version": "6.2.0", + "resolved": "https://registry.npmjs.org/inquirer/-/inquirer-6.2.0.tgz", + "integrity": "sha512-QIEQG4YyQ2UYZGDC4srMZ7BjHOmNk1lR2JQj5UknBapklm6WHA+VVH7N+sUdX3A7NeCfGF8o4X1S3Ao7nAcIeg==", + "dev": true, + "requires": { + "ansi-escapes": "^3.0.0", + "chalk": "^2.0.0", + "cli-cursor": "^2.1.0", + "cli-width": "^2.0.0", + "external-editor": "^3.0.0", + "figures": "^2.0.0", + "lodash": "^4.17.10", + "mute-stream": "0.0.7", + "run-async": "^2.2.0", + "rxjs": "^6.1.0", + "string-width": "^2.1.0", + "strip-ansi": "^4.0.0", + "through": "^2.3.6" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "invert-kv": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/invert-kv/-/invert-kv-1.0.0.tgz", + "integrity": "sha1-EEqOSqym09jNFXqO+L+rLXo//bY=" + }, + "ipaddr.js": { + "version": "1.8.0", + "resolved": "https://registry.npmjs.org/ipaddr.js/-/ipaddr.js-1.8.0.tgz", + "integrity": "sha1-6qM9bd16zo9/b+DJygRA5wZzix4=" + }, + "is-arrayish": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.2.1.tgz", + "integrity": "sha1-d8mYQFJ6qOyxqLppe4BkWnqSap0=" + }, + "is-bluebird": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/is-bluebird/-/is-bluebird-1.0.2.tgz", + "integrity": "sha1-CWQ5Bg9KpBGr7hkUOoTWpVNG1uI=" + }, + "is-builtin-module": { + "version": "1.0.0", + "resolved": "http://registry.npmjs.org/is-builtin-module/-/is-builtin-module-1.0.0.tgz", + "integrity": "sha1-VAVy0096wxGfj3bDDLwbHgN6/74=", + "requires": { + "builtin-modules": "^1.0.0" + } + }, + "is-fullwidth-code-point": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-1.0.0.tgz", + "integrity": "sha1-754xOG8DGn8NZDr4L95QxFfvAMs=", + "requires": { + "number-is-nan": "^1.0.0" + } + }, + "is-number-like": { + "version": "1.0.8", + "resolved": "https://registry.npmjs.org/is-number-like/-/is-number-like-1.0.8.tgz", + "integrity": "sha512-6rZi3ezCyFcn5L71ywzz2bS5b2Igl1En3eTlZlvKjpz1n3IZLAYMbKYAIQgFmEu0GENg92ziU/faEOA/aixjbA==", + "requires": { + "lodash.isfinite": "^3.3.2" + } + }, + "is-path-cwd": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-path-cwd/-/is-path-cwd-1.0.0.tgz", + "integrity": "sha1-0iXsIxMuie3Tj9p2dHLmLmXxEG0=", + "dev": true + }, + "is-path-in-cwd": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-in-cwd/-/is-path-in-cwd-1.0.1.tgz", + "integrity": "sha512-FjV1RTW48E7CWM7eE/J2NJvAEEVektecDBVBE5Hh3nM1Jd0kvhHtX68Pr3xsDf857xt3Y4AkwVULK1Vku62aaQ==", + "dev": true, + "requires": { + "is-path-inside": "^1.0.0" + } + }, + "is-path-inside": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/is-path-inside/-/is-path-inside-1.0.1.tgz", + "integrity": "sha1-jvW33lBDej/cprToZe96pVy0gDY=", + "dev": true, + "requires": { + "path-is-inside": "^1.0.1" + } + }, + "is-promise": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-promise/-/is-promise-2.1.0.tgz", + "integrity": "sha1-eaKp7OfwlugPNtKy87wWwf9L8/o=" + }, + "is-resolvable": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-resolvable/-/is-resolvable-1.1.0.tgz", + "integrity": "sha512-qgDYXFSR5WvEfuS5dMj6oTMEbrrSaM0CrFk2Yiq/gXnBvD9pMa2jGXxyhGLfvhZpuMZe18CJpFxAt3CRs42NMg==", + "dev": true + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha1-EtSj3U5o4Lec6428hBc66A2RykQ=" + }, + "is-typedarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/is-typedarray/-/is-typedarray-1.0.0.tgz", + "integrity": "sha1-5HnICFjfDBsR3dppQPlgEfzaSpo=" + }, + "isarray": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/isarray/-/isarray-1.0.0.tgz", + "integrity": "sha1-u5NdSFgsuhaMBoNJV6VKPgcSTxE=" + }, + "isexe": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", + "integrity": "sha1-6PvzdNxVb/iUehDcsFctYz8s+hA=" + }, + "isstream": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/isstream/-/isstream-0.1.2.tgz", + "integrity": "sha1-R+Y/evVa+m+S4VAOaQ64uFKcCZo=" + }, + "js-beautify": { + "version": "1.8.6", + "resolved": "https://registry.npmjs.org/js-beautify/-/js-beautify-1.8.6.tgz", + "integrity": "sha512-TYDZa+lg8vEC5U0OmGQEEwiZ0XFBfvZAUeNOtqflLe+woKuIqF4JzlsBx/C1KVYW5lUewZy2ODL4Obq6sH7a4Q==", + "requires": { + "config-chain": "~1.1.5", + "editorconfig": "^0.15.0", + "mkdirp": "~0.5.0", + "nopt": "~4.0.1" + } + }, + "js-tokens": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/js-tokens/-/js-tokens-4.0.0.tgz", + "integrity": "sha512-RdJUflcE3cUzKiMqQgsCu06FPu9UdIJO0beYbPhHN4k6apgJtifcoCtT9bcxOpYBtpD2kCM6Sbzg4CausW/PKQ==", + "dev": true + }, + "js-yaml": { + "version": "3.12.0", + "resolved": "https://registry.npmjs.org/js-yaml/-/js-yaml-3.12.0.tgz", + "integrity": "sha512-PIt2cnwmPfL4hKNwqeiuz4bKfnzHTBv6HyVgjahA6mPLwPDzjDWrplJBMjHUFxku/N3FlmrbyPclad+I+4mJ3A==", + "dev": true, + "requires": { + "argparse": "^1.0.7", + "esprima": "^4.0.0" + } + }, + "jsbn": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/jsbn/-/jsbn-0.1.1.tgz", + "integrity": "sha1-peZUwuWi3rXyAdls77yoDA7y9RM=" + }, + "json-schema": { + "version": "0.2.3", + "resolved": "https://registry.npmjs.org/json-schema/-/json-schema-0.2.3.tgz", + "integrity": "sha1-tIDIkuWaLwWVTOcnvT8qTogvnhM=" + }, + "json-schema-traverse": { + "version": "0.3.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.3.1.tgz", + "integrity": "sha1-NJptRMU6Ud6JtAgFxdXlm0F9M0A=" + }, + "json-stable-stringify-without-jsonify": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/json-stable-stringify-without-jsonify/-/json-stable-stringify-without-jsonify-1.0.1.tgz", + "integrity": "sha1-nbe1lJatPzz+8wp1FC0tkwrXJlE=", + "dev": true + }, + "json-stringify-safe": { + "version": "5.0.1", + "resolved": "https://registry.npmjs.org/json-stringify-safe/-/json-stringify-safe-5.0.1.tgz", + "integrity": "sha1-Epai1Y/UXxmg9s4B1lcB4sc1tus=" + }, + "jsonfile": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/jsonfile/-/jsonfile-4.0.0.tgz", + "integrity": "sha1-h3Gq4HmbZAdrdmQPygWPnBDjPss=", + "requires": { + "graceful-fs": "^4.1.6" + } + }, + "jsonschema": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/jsonschema/-/jsonschema-1.2.4.tgz", + "integrity": "sha512-lz1nOH69GbsVHeVgEdvyavc/33oymY1AZwtePMiMj4HZPMbP5OIKK3zT9INMWjwua/V4Z4yq7wSlBbSG+g4AEw==" + }, + "jsprim": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/jsprim/-/jsprim-1.4.1.tgz", + "integrity": "sha1-MT5mvB5cwG5Di8G3SZwuXFastqI=", + "requires": { + "assert-plus": "1.0.0", + "extsprintf": "1.3.0", + "json-schema": "0.2.3", + "verror": "1.10.0" + } + }, + "kuler": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/kuler/-/kuler-1.0.1.tgz", + "integrity": "sha512-J9nVUucG1p/skKul6DU3PUZrhs0LPulNaeUOox0IyXDi8S4CztTHs1gQphhuZmzXG7VOQSf6NJfKuzteQLv9gQ==", + "requires": { + "colornames": "^1.1.1" + } + }, + "lcid": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/lcid/-/lcid-1.0.0.tgz", + "integrity": "sha1-MIrMr6C8SDo4Z7S28rlQYlHRuDU=", + "requires": { + "invert-kv": "^1.0.0" + } + }, + "levn": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/levn/-/levn-0.3.0.tgz", + "integrity": "sha1-OwmSTt+fCDwEkP3UwLxEIeBHZO4=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2" + } + }, + "load-json-file": { + "version": "2.0.0", + "resolved": "http://registry.npmjs.org/load-json-file/-/load-json-file-2.0.0.tgz", + "integrity": "sha1-eUfkIUmvgNaWy/eXvKq8/h/inKg=", + "requires": { + "graceful-fs": "^4.1.2", + "parse-json": "^2.2.0", + "pify": "^2.0.0", + "strip-bom": "^3.0.0" + } + }, + "locate-path": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/locate-path/-/locate-path-2.0.0.tgz", + "integrity": "sha1-K1aLJl7slExtnA3pw9u7ygNUzY4=", + "requires": { + "p-locate": "^2.0.0", + "path-exists": "^3.0.0" + } + }, + "lodash": { + "version": "4.17.11", + "resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.11.tgz", + "integrity": "sha512-cQKh8igo5QUhZ7lg38DYWAxMvjSAKG0A8wGSVimP07SIUEK2UO+arSRKbRZWtelMtN5V0Hkwh5ryOto/SshYIg==" + }, + "lodash.camelcase": { + "version": "4.3.0", + "resolved": "https://registry.npmjs.org/lodash.camelcase/-/lodash.camelcase-4.3.0.tgz", + "integrity": "sha1-soqmKIorn8ZRA1x3EfZathkDMaY=" + }, + "lodash.isfinite": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/lodash.isfinite/-/lodash.isfinite-3.3.2.tgz", + "integrity": "sha1-+4m2WpqAKBgz8LdHizpRBPiY67M=" + }, + "lodash.padend": { + "version": "4.6.1", + "resolved": "https://registry.npmjs.org/lodash.padend/-/lodash.padend-4.6.1.tgz", + "integrity": "sha1-U8y6BH0G4VjTEfRdpiX05J5vFm4=" + }, + "logform": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/logform/-/logform-1.10.0.tgz", + "integrity": "sha512-em5ojIhU18fIMOw/333mD+ZLE2fis0EzXl1ZwHx4iQzmpQi6odNiY/t+ITNr33JZhT9/KEaH+UPIipr6a9EjWg==", + "requires": { + "colors": "^1.2.1", + "fast-safe-stringify": "^2.0.4", + "fecha": "^2.3.3", + "ms": "^2.1.1", + "triple-beam": "^1.2.0" + }, + "dependencies": { + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + } + } + }, + "lru-cache": { + "version": "4.1.3", + "resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-4.1.3.tgz", + "integrity": "sha512-fFEhvcgzuIoJVUF8fYr5KR0YqxD238zgObTps31YdADwPPAp82a4M8TrckkWyx7ekNlf9aBcVn81cFwwXngrJA==", + "requires": { + "pseudomap": "^1.0.2", + "yallist": "^2.1.2" + } + }, + "lru-queue": { + "version": "0.1.0", + "resolved": "https://registry.npmjs.org/lru-queue/-/lru-queue-0.1.0.tgz", + "integrity": "sha1-Jzi9nw089PhEkMVzbEhpmsYyzaM=", + "requires": { + "es5-ext": "~0.10.2" + } + }, + "media-typer": { + "version": "0.3.0", + "resolved": "https://registry.npmjs.org/media-typer/-/media-typer-0.3.0.tgz", + "integrity": "sha1-hxDXrwqmJvj/+hzgAWhUUmMlV0g=" + }, + "mem": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/mem/-/mem-1.1.0.tgz", + "integrity": "sha1-Xt1StIXKHZAP5kiVUFOZoN+kX3Y=", + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "memoizee": { + "version": "0.4.14", + "resolved": "https://registry.npmjs.org/memoizee/-/memoizee-0.4.14.tgz", + "integrity": "sha512-/SWFvWegAIYAO4NQMpcX+gcra0yEZu4OntmUdrBaWrJncxOqAziGFlHxc7yjKVK2uu3lpPW27P27wkR82wA8mg==", + "requires": { + "d": "1", + "es5-ext": "^0.10.45", + "es6-weak-map": "^2.0.2", + "event-emitter": "^0.3.5", + "is-promise": "^2.1", + "lru-queue": "0.1", + "next-tick": "1", + "timers-ext": "^0.1.5" + } + }, + "merge-descriptors": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/merge-descriptors/-/merge-descriptors-1.0.1.tgz", + "integrity": "sha1-sAqqVW3YtEVoFQ7J0blT8/kMu2E=" + }, + "methods": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/methods/-/methods-1.1.2.tgz", + "integrity": "sha1-VSmk1nZUE07cxSZmVoNbD4Ua/O4=" + }, + "mime": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/mime/-/mime-1.4.1.tgz", + "integrity": "sha512-KI1+qOZu5DcW6wayYHSzR/tXKCDC5Om4s1z2QJjDULzLcmf3DvzS7oluY4HCTrc+9FiKmWUgeNLg7W3uIQvxtQ==" + }, + "mime-db": { + "version": "1.36.0", + "resolved": "https://registry.npmjs.org/mime-db/-/mime-db-1.36.0.tgz", + "integrity": "sha512-L+xvyD9MkoYMXb1jAmzI/lWYAxAMCPvIBSWur0PZ5nOf5euahRLVqH//FKW9mWp2lkqUgYiXPgkzfMUFi4zVDw==" + }, + "mime-types": { + "version": "2.1.20", + "resolved": "https://registry.npmjs.org/mime-types/-/mime-types-2.1.20.tgz", + "integrity": "sha512-HrkrPaP9vGuWbLK1B1FfgAkbqNjIuy4eHlIYnFi7kamZyLLrGlo2mpcx0bBmNpKqBtYtAfGbodDddIgddSJC2A==", + "requires": { + "mime-db": "~1.36.0" + } + }, + "mimic-fn": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/mimic-fn/-/mimic-fn-1.2.0.tgz", + "integrity": "sha512-jf84uxzwiuiIVKiOLpfYk7N46TSy8ubTonmneY9vrpHNAnp0QBt2BxWV9dO3/j+BoVAb+a5G6YDPW3M5HOdMWQ==" + }, + "minimatch": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/minimatch/-/minimatch-3.0.4.tgz", + "integrity": "sha512-yJHVQEhyqPLUTgt9B83PXu6W3rx4MvvHvSUvToogpwoGDOUQ+yDrR0HRot+yOCdCO7u4hX3pWft6kWBBcqh0UA==", + "requires": { + "brace-expansion": "^1.1.7" + } + }, + "minimist": { + "version": "0.0.8", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-0.0.8.tgz", + "integrity": "sha1-hX/Kv8M5fSYluCKCYuhqp6ARsF0=" + }, + "minipass": { + "version": "2.3.5", + "resolved": "https://registry.npmjs.org/minipass/-/minipass-2.3.5.tgz", + "integrity": "sha512-Gi1W4k059gyRbyVUZQ4mEqLm0YIUiGYfvxhF6SIlk3ui1WVxMTGfGdQ2SInh3PDrRTVvPKgULkpJtT4RH10+VA==", + "requires": { + "safe-buffer": "^5.1.2", + "yallist": "^3.0.0" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, + "minizlib": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/minizlib/-/minizlib-1.1.1.tgz", + "integrity": "sha512-TrfjCjk4jLhcJyGMYymBH6oTXcWjYbUAXTHDbtnWHjZC25h0cdajHuPE1zxb4DVmu8crfh+HwH/WMuyLG0nHBg==", + "requires": { + "minipass": "^2.2.1" + } + }, + "mkdirp": { + "version": "0.5.1", + "resolved": "http://registry.npmjs.org/mkdirp/-/mkdirp-0.5.1.tgz", + "integrity": "sha1-MAV0OOrGz3+MR2fzhkjWaX11yQM=", + "requires": { + "minimist": "0.0.8" + } + }, + "moment": { + "version": "2.22.2", + "resolved": "https://registry.npmjs.org/moment/-/moment-2.22.2.tgz", + "integrity": "sha1-PCV/mDn8DpP/UxSWMiOeuQeD/2Y=" + }, + "moment-timezone": { + "version": "0.5.21", + "resolved": "https://registry.npmjs.org/moment-timezone/-/moment-timezone-0.5.21.tgz", + "integrity": "sha512-j96bAh4otsgj3lKydm3K7kdtA3iKf2m6MY2iSYCzCm5a1zmHo1g+aK3068dDEeocLZQIS9kU8bsdQHLqEvgW0A==", + "requires": { + "moment": ">= 2.9.0" + } + }, + "morgan": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/morgan/-/morgan-1.9.1.tgz", + "integrity": "sha512-HQStPIV4y3afTiCYVxirakhlCfGkI161c76kKFca7Fk1JusM//Qeo1ej2XaMniiNeaZklMVrh3vTtIzpzwbpmA==", + "requires": { + "basic-auth": "~2.0.0", + "debug": "2.6.9", + "depd": "~1.1.2", + "on-finished": "~2.3.0", + "on-headers": "~1.0.1" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + }, + "mute-stream": { + "version": "0.0.7", + "resolved": "https://registry.npmjs.org/mute-stream/-/mute-stream-0.0.7.tgz", + "integrity": "sha1-MHXOk7whuPq0PhvE2n6BFe0ee6s=", + "dev": true + }, + "nan": { + "version": "2.10.0", + "resolved": "http://registry.npmjs.org/nan/-/nan-2.10.0.tgz", + "integrity": "sha512-bAdJv7fBLhWC+/Bls0Oza+mvTaNQtP+1RyhhhvD95pgUJz6XM5IzgmxOkItJ9tkoCiplvAnXI1tNmmUD/eScyA==" + }, + "natural-compare": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/natural-compare/-/natural-compare-1.4.0.tgz", + "integrity": "sha1-Sr6/7tdUHywnrPspvbvRXI1bpPc=", + "dev": true + }, + "nconf": { + "version": "0.10.0", + "resolved": "https://registry.npmjs.org/nconf/-/nconf-0.10.0.tgz", + "integrity": "sha512-fKiXMQrpP7CYWJQzKkPPx9hPgmq+YLDyxcG9N8RpiE9FoCkCbzD0NyW0YhE3xn3Aupe7nnDeIx4PFzYehpHT9Q==", + "requires": { + "async": "^1.4.0", + "ini": "^1.3.0", + "secure-keys": "^1.0.0", + "yargs": "^3.19.0" + } + }, + "needle": { + "version": "2.2.4", + "resolved": "https://registry.npmjs.org/needle/-/needle-2.2.4.tgz", + "integrity": "sha512-HyoqEb4wr/rsoaIDfTH2aVL9nWtQqba2/HvMv+++m8u0dz808MaagKILxtfeSN7QU7nvbQ79zk3vYOJp9zsNEA==", + "requires": { + "debug": "^2.1.2", + "iconv-lite": "^0.4.4", + "sax": "^1.2.4" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + } + } + }, + "negotiator": { + "version": "0.6.1", + "resolved": "https://registry.npmjs.org/negotiator/-/negotiator-0.6.1.tgz", + "integrity": "sha1-KzJxhOiZIQEXeyhWP7XnECrNDKk=" + }, + "next-tick": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/next-tick/-/next-tick-1.0.0.tgz", + "integrity": "sha1-yobR/ogoFpsBICCOPchCS524NCw=" + }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==", + "dev": true + }, + "nocache": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/nocache/-/nocache-2.0.0.tgz", + "integrity": "sha1-ICtIAhoMTL3i34DeFaF0Q8i0OYA=" + }, + "node-pre-gyp": { + "version": "0.10.3", + "resolved": "https://registry.npmjs.org/node-pre-gyp/-/node-pre-gyp-0.10.3.tgz", + "integrity": "sha512-d1xFs+C/IPS8Id0qPTZ4bUT8wWryfR/OzzAFxweG+uLN85oPzyo2Iw6bVlLQ/JOdgNonXLCoRyqDzDWq4iw72A==", + "requires": { + "detect-libc": "^1.0.2", + "mkdirp": "^0.5.1", + "needle": "^2.2.1", + "nopt": "^4.0.1", + "npm-packlist": "^1.1.6", + "npmlog": "^4.0.2", + "rc": "^1.2.7", + "rimraf": "^2.6.1", + "semver": "^5.3.0", + "tar": "^4" + } + }, + "nodemailer": { + "version": "4.6.8", + "resolved": "https://registry.npmjs.org/nodemailer/-/nodemailer-4.6.8.tgz", + "integrity": "sha512-A3s7EM/426OBIZbLHXq2KkgvmKbn2Xga4m4G+ZUA4IaZvG8PcZXrFh+2E4VaS2o+emhuUVRnzKN2YmpkXQ9qwA==" + }, + "nodemailer-fetch": { + "version": "1.6.0", + "resolved": "https://registry.npmjs.org/nodemailer-fetch/-/nodemailer-fetch-1.6.0.tgz", + "integrity": "sha1-ecSQihwPXzdbc/6IjamCj23JY6Q=" + }, + "nodemailer-shared": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/nodemailer-shared/-/nodemailer-shared-1.1.0.tgz", + "integrity": "sha1-z1mU4v0mjQD1zw+nZ6CBae2wfsA=", + "requires": { + "nodemailer-fetch": "1.6.0" + } + }, + "nodemailer-smtp-transport": { + "version": "2.7.4", + "resolved": "https://registry.npmjs.org/nodemailer-smtp-transport/-/nodemailer-smtp-transport-2.7.4.tgz", + "integrity": "sha1-DYmvAZoUSkgP2OzJmZfZ+DjxNoU=", + "requires": { + "nodemailer-shared": "1.1.0", + "nodemailer-wellknown": "0.1.10", + "smtp-connection": "2.12.0" + } + }, + "nodemailer-wellknown": { + "version": "0.1.10", + "resolved": "https://registry.npmjs.org/nodemailer-wellknown/-/nodemailer-wellknown-0.1.10.tgz", + "integrity": "sha1-WG24EB2zDLRDjrVGc3pBqtDPE9U=" + }, + "nopt": { + "version": "4.0.1", + "resolved": "https://registry.npmjs.org/nopt/-/nopt-4.0.1.tgz", + "integrity": "sha1-0NRoWv1UFRk8jHUFYC0NF81kR00=", + "requires": { + "abbrev": "1", + "osenv": "^0.1.4" + } + }, + "normalize-package-data": { + "version": "2.4.0", + "resolved": "https://registry.npmjs.org/normalize-package-data/-/normalize-package-data-2.4.0.tgz", + "integrity": "sha512-9jjUFbTPfEy3R/ad/2oNbKtW9Hgovl5O1FvFWKkKblNXoN/Oou6+9+KKohPK13Yc3/TyunyWhJp6gvRNR/PPAw==", + "requires": { + "hosted-git-info": "^2.1.4", + "is-builtin-module": "^1.0.0", + "semver": "2 || 3 || 4 || 5", + "validate-npm-package-license": "^3.0.1" + } + }, + "npm-bundled": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/npm-bundled/-/npm-bundled-1.0.5.tgz", + "integrity": "sha512-m/e6jgWu8/v5niCUKQi9qQl8QdeEduFA96xHDDzFGqly0OOjI7c+60KM/2sppfnUU9JJagf+zs+yGhqSOFj71g==" + }, + "npm-packlist": { + "version": "1.1.12", + "resolved": "https://registry.npmjs.org/npm-packlist/-/npm-packlist-1.1.12.tgz", + "integrity": "sha512-WJKFOVMeAlsU/pjXuqVdzU0WfgtIBCupkEVwn+1Y0ERAbUfWw8R4GjgVbaKnUjRoD2FoQbHOCbOyT5Mbs9Lw4g==", + "requires": { + "ignore-walk": "^3.0.1", + "npm-bundled": "^1.0.1" + } + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha1-NakjLfo11wZ7TLLd8jV7GHFTbF8=", + "requires": { + "path-key": "^2.0.0" + } + }, + "npmlog": { + "version": "4.1.2", + "resolved": "https://registry.npmjs.org/npmlog/-/npmlog-4.1.2.tgz", + "integrity": "sha512-2uUqazuKlTaSI/dC8AzicUck7+IrEaOnN/e0jd3Xtt1KcGpwx30v50mL7oPyr/h9bL3E4aZccVwpwP+5W9Vjkg==", + "requires": { + "are-we-there-yet": "~1.1.2", + "console-control-strings": "~1.1.0", + "gauge": "~2.7.3", + "set-blocking": "~2.0.0" + } + }, + "number-is-nan": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/number-is-nan/-/number-is-nan-1.0.1.tgz", + "integrity": "sha1-CXtgK1NCKlIsGvuHkDGDNpQaAR0=" + }, + "oauth-sign": { + "version": "0.9.0", + "resolved": "https://registry.npmjs.org/oauth-sign/-/oauth-sign-0.9.0.tgz", + "integrity": "sha512-fexhUFFPTGV8ybAtSIGbV6gOkSv8UtRbDBnAyLQw4QPKkgNlsH2ByPGtMUqdWkos6YCRmAqViwgZrJc/mRDzZQ==" + }, + "object-assign": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/object-assign/-/object-assign-4.1.1.tgz", + "integrity": "sha1-IQmtx5ZYh8/AXLvUQsrIv7s2CGM=" + }, + "on-finished": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/on-finished/-/on-finished-2.3.0.tgz", + "integrity": "sha1-IPEzZIGwg811M3mSoWlxqi2QaUc=", + "requires": { + "ee-first": "1.1.1" + } + }, + "on-headers": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/on-headers/-/on-headers-1.0.1.tgz", + "integrity": "sha1-ko9dD0cNSTQmUepnlLCFfBAGk/c=" + }, + "once": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/once/-/once-1.4.0.tgz", + "integrity": "sha1-WDsap3WWHUsROsF9nFC6753Xa9E=", + "requires": { + "wrappy": "1" + } + }, + "one-time": { + "version": "0.0.4", + "resolved": "https://registry.npmjs.org/one-time/-/one-time-0.0.4.tgz", + "integrity": "sha1-+M33eISCb+Tf+T46nMN7HkSAdC4=" + }, + "onetime": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/onetime/-/onetime-2.0.1.tgz", + "integrity": "sha1-BnQoIw/WdEOyeUsiu6UotoZ5YtQ=", + "dev": true, + "requires": { + "mimic-fn": "^1.0.0" + } + }, + "optionator": { + "version": "0.8.2", + "resolved": "https://registry.npmjs.org/optionator/-/optionator-0.8.2.tgz", + "integrity": "sha1-NkxeQJ0/TWMB1sC0wFu6UBgK62Q=", + "dev": true, + "requires": { + "deep-is": "~0.1.3", + "fast-levenshtein": "~2.0.4", + "levn": "~0.3.0", + "prelude-ls": "~1.1.2", + "type-check": "~0.3.2", + "wordwrap": "~1.0.0" + } + }, + "os-homedir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-homedir/-/os-homedir-1.0.2.tgz", + "integrity": "sha1-/7xJiDNuDoM94MFox+8VISGqf7M=" + }, + "os-locale": { + "version": "1.4.0", + "resolved": "http://registry.npmjs.org/os-locale/-/os-locale-1.4.0.tgz", + "integrity": "sha1-IPnxeuKe00XoveWDsT0gCYA8FNk=", + "requires": { + "lcid": "^1.0.0" + } + }, + "os-tmpdir": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/os-tmpdir/-/os-tmpdir-1.0.2.tgz", + "integrity": "sha1-u+Z0BseaqFxc/sdm/lc0VV36EnQ=" + }, + "osenv": { + "version": "0.1.5", + "resolved": "https://registry.npmjs.org/osenv/-/osenv-0.1.5.tgz", + "integrity": "sha512-0CWcCECdMVc2Rw3U5w9ZjqX6ga6ubk1xDVKxtBQPK7wis/0F2r9T6k4ydGYhecl7YUBxBVxhL5oisPsNxAPe2g==", + "requires": { + "os-homedir": "^1.0.0", + "os-tmpdir": "^1.0.0" + } + }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha1-P7z7FbiZpEEjs0ttzBi3JDNqLK4=" + }, + "p-limit": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-1.3.0.tgz", + "integrity": "sha512-vvcXsLAJ9Dr5rQOPk7toZQZJApBl2K4J6dANSsEuh6QI41JYcsS/qhTGa9ErIUUgK3WNQoJYvylxvjqmiqEA9Q==", + "requires": { + "p-try": "^1.0.0" + } + }, + "p-locate": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/p-locate/-/p-locate-2.0.0.tgz", + "integrity": "sha1-IKAQOyIqcMj9OcwuWAaA893l7EM=", + "requires": { + "p-limit": "^1.1.0" + } + }, + "p-try": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-try/-/p-try-1.0.0.tgz", + "integrity": "sha1-y8ec26+P1CKOE/Yh8rGiN8GyB7M=" + }, + "parse-json": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/parse-json/-/parse-json-2.2.0.tgz", + "integrity": "sha1-9ID0BDTvgHQfhGkJn43qGPVaTck=", + "requires": { + "error-ex": "^1.2.0" + } + }, + "parseurl": { + "version": "1.3.2", + "resolved": "https://registry.npmjs.org/parseurl/-/parseurl-1.3.2.tgz", + "integrity": "sha1-/CidTtiZMRlGDBViUyYs3I3mW/M=" + }, + "path": { + "version": "0.12.7", + "resolved": "https://registry.npmjs.org/path/-/path-0.12.7.tgz", + "integrity": "sha1-1NwqUGxM4hl+tIHr/NWzbAFAsQ8=", + "requires": { + "process": "^0.11.1", + "util": "^0.10.3" + } + }, + "path-exists": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/path-exists/-/path-exists-3.0.0.tgz", + "integrity": "sha1-zg6+ql94yxiSXqfYENe1mwEP1RU=" + }, + "path-is-absolute": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/path-is-absolute/-/path-is-absolute-1.0.1.tgz", + "integrity": "sha1-F0uSaHNVNP+8es5r9TpanhtcX18=" + }, + "path-is-inside": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/path-is-inside/-/path-is-inside-1.0.2.tgz", + "integrity": "sha1-NlQX3t5EQw0cEa9hAn+s8HS9/FM=", + "dev": true + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha1-QRyttXTFoUDTpLGRDUDYDMn0C0A=" + }, + "path-parse": { + "version": "1.0.6", + "resolved": "https://registry.npmjs.org/path-parse/-/path-parse-1.0.6.tgz", + "integrity": "sha512-GSmOT2EbHrINBf9SR7CDELwlJ8AENk3Qn7OikK4nFYAu3Ote2+JYNVvkpAEQm3/TLNEJFD/xZJjzyxg3KBWOzw==" + }, + "path-to-regexp": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/path-to-regexp/-/path-to-regexp-0.1.7.tgz", + "integrity": "sha1-32BBeABfUi8V60SQ5yR6G/qmf4w=" + }, + "path-type": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/path-type/-/path-type-2.0.0.tgz", + "integrity": "sha1-8BLMuEFbcJb8LaoQVMPXI4lZTHM=", + "requires": { + "pify": "^2.0.0" + } + }, + "performance-now": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/performance-now/-/performance-now-2.1.0.tgz", + "integrity": "sha1-Ywn04OX6kT7BxpMHrjZLSzd8nns=" + }, + "pify": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/pify/-/pify-2.3.0.tgz", + "integrity": "sha1-7RQaasBDqEnqWISY59yosVMw6Qw=" + }, + "pinkie": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/pinkie/-/pinkie-2.0.4.tgz", + "integrity": "sha1-clVrgM+g1IqXToDnckjoDtT3+HA=", + "dev": true + }, + "pinkie-promise": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/pinkie-promise/-/pinkie-promise-2.0.1.tgz", + "integrity": "sha1-ITXW36ejWMBprJsXh3YogihFD/o=", + "dev": true, + "requires": { + "pinkie": "^2.0.0" + } + }, + "platform": { + "version": "1.3.5", + "resolved": "https://registry.npmjs.org/platform/-/platform-1.3.5.tgz", + "integrity": "sha512-TuvHS8AOIZNAlE77WUDiR4rySV/VMptyMfcfeoMgs4P8apaZM3JrnbzBiixKUv+XR6i+BXrQh8WAnjaSPFO65Q==" + }, + "pluralize": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/pluralize/-/pluralize-7.0.0.tgz", + "integrity": "sha512-ARhBOdzS3e41FbkW/XWrTEtukqqLoK5+Z/4UeDaLuSW+39JPeFgs4gCGqsrJHVZX0fUrx//4OF0K1CUGwlIFow==", + "dev": true + }, + "portscanner": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/portscanner/-/portscanner-2.2.0.tgz", + "integrity": "sha512-IFroCz/59Lqa2uBvzK3bKDbDDIEaAY8XJ1jFxcLWTqosrsc32//P4VuSB2vZXoHiHqOmx8B5L5hnKOxL/7FlPw==", + "requires": { + "async": "^2.6.0", + "is-number-like": "^1.0.3" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "prelude-ls": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/prelude-ls/-/prelude-ls-1.1.2.tgz", + "integrity": "sha1-IZMqVJ9eUv/ZqCf1cOBL5iqX2lQ=", + "dev": true + }, + "process": { + "version": "0.11.10", + "resolved": "https://registry.npmjs.org/process/-/process-0.11.10.tgz", + "integrity": "sha1-czIwDoQBYb2j5podHZGn1LwW8YI=" + }, + "process-nextick-args": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/process-nextick-args/-/process-nextick-args-2.0.0.tgz", + "integrity": "sha512-MtEC1TqN0EU5nephaJ4rAtThHtC86dNN9qCuEhtshvpVBkAW5ZO7BASN9REnF9eoXGcRub+pFuKEpOHE+HbEMw==" + }, + "progress": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/progress/-/progress-2.0.0.tgz", + "integrity": "sha1-ihvjZr+Pwj2yvSPxDG/pILQ4nR8=", + "dev": true + }, + "proto-list": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/proto-list/-/proto-list-1.2.4.tgz", + "integrity": "sha1-IS1b/hMYMGpCD2QCuOJv85ZHqEk=" + }, + "proxy-addr": { + "version": "2.0.4", + "resolved": "https://registry.npmjs.org/proxy-addr/-/proxy-addr-2.0.4.tgz", + "integrity": "sha512-5erio2h9jp5CHGwcybmxmVqHmnCBZeewlfJ0pex+UW7Qny7OOZXTtH56TGNyBizkgiOwhJtMKrVzDTeKcySZwA==", + "requires": { + "forwarded": "~0.1.2", + "ipaddr.js": "1.8.0" + } + }, + "pseudomap": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/pseudomap/-/pseudomap-1.0.2.tgz", + "integrity": "sha1-8FKijacOYYkX7wqKw0wa5aaChrM=" + }, + "psl": { + "version": "1.1.29", + "resolved": "https://registry.npmjs.org/psl/-/psl-1.1.29.tgz", + "integrity": "sha512-AeUmQ0oLN02flVHXWh9sSJF7mcdFq0ppid/JkErufc3hGIV/AMa8Fo9VgDo/cT2jFdOWoFvHp90qqBH54W+gjQ==" + }, + "punycode": { + "version": "1.4.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-1.4.1.tgz", + "integrity": "sha1-wNWmOycYgArY4esPpSachN1BhF4=" + }, + "qs": { + "version": "6.5.2", + "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", + "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" + }, + "querystring": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", + "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" + }, + "range-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", + "integrity": "sha1-9JvmtIeJTdxA3MlKMi9hEJLgDV4=" + }, + "raw-body": { + "version": "2.3.3", + "resolved": "https://registry.npmjs.org/raw-body/-/raw-body-2.3.3.tgz", + "integrity": "sha512-9esiElv1BrZoI3rCDuOuKCBRbuApGGaDPQfjSflGxdy4oyzqghxu6klEkkVIvBje+FF0BX9coEv8KqW6X/7njw==", + "requires": { + "bytes": "3.0.0", + "http-errors": "1.6.3", + "iconv-lite": "0.4.23", + "unpipe": "1.0.0" + } + }, + "rc": { + "version": "1.2.8", + "resolved": "https://registry.npmjs.org/rc/-/rc-1.2.8.tgz", + "integrity": "sha512-y3bGgqKj3QBdxLbLkomlohkvsA8gdAiUQlSBJnBhfn+BPxg4bc62d8TcBW15wavDfgexCgccckhcZvywyQYPOw==", + "requires": { + "deep-extend": "^0.6.0", + "ini": "~1.3.0", + "minimist": "^1.2.0", + "strip-json-comments": "~2.0.1" + }, + "dependencies": { + "minimist": { + "version": "1.2.0", + "resolved": "http://registry.npmjs.org/minimist/-/minimist-1.2.0.tgz", + "integrity": "sha1-o1AIsg9BOD7sH7kU9M1d95omQoQ=" + } + } + }, + "read-pkg": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg/-/read-pkg-2.0.0.tgz", + "integrity": "sha1-jvHAYjxqbbDcZxPEv6xGMysjaPg=", + "requires": { + "load-json-file": "^2.0.0", + "normalize-package-data": "^2.3.2", + "path-type": "^2.0.0" + } + }, + "read-pkg-up": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/read-pkg-up/-/read-pkg-up-2.0.0.tgz", + "integrity": "sha1-a3KoBImE4MQeeVEP1en6mbO1Sb4=", + "requires": { + "find-up": "^2.0.0", + "read-pkg": "^2.0.0" + } + }, + "readable-stream": { + "version": "2.3.6", + "resolved": "http://registry.npmjs.org/readable-stream/-/readable-stream-2.3.6.tgz", + "integrity": "sha512-tQtKA9WIAhBF3+VLAseyMqZeBjW0AHJoxOtYqSUZNJxauErmLbVm2FW1y+J/YA9dUrAC39ITejlZWhVIwawkKw==", + "requires": { + "core-util-is": "~1.0.0", + "inherits": "~2.0.3", + "isarray": "~1.0.0", + "process-nextick-args": "~2.0.0", + "safe-buffer": "~5.1.1", + "string_decoder": "~1.1.1", + "util-deprecate": "~1.0.1" + } + }, + "reduce-flatten": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/reduce-flatten/-/reduce-flatten-1.0.1.tgz", + "integrity": "sha1-JYx479FT3fk8tWEjf2EYTzaW4yc=" + }, + "referrer-policy": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/referrer-policy/-/referrer-policy-1.1.0.tgz", + "integrity": "sha1-NXdOtzW/UPtsB46DM0tHI1AgfXk=" + }, + "regenerator-runtime": { + "version": "0.11.1", + "resolved": "https://registry.npmjs.org/regenerator-runtime/-/regenerator-runtime-0.11.1.tgz", + "integrity": "sha512-MguG95oij0fC3QV3URf4V2SDYGJhJnJGqvIIgdECeODCT98wSWDAJ94SSuVpYQUoTcGUIL6L4yNB7j1DFFHSBg==" + }, + "regexpp": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/regexpp/-/regexpp-2.0.1.tgz", + "integrity": "sha512-lv0M6+TkDVniA3aD1Eg0DVpfU/booSu7Eev3TDO/mZKHBfVjgCGTV4t4buppESEYDtkArYFOxTJWv6S5C+iaNw==", + "dev": true + }, + "request": { + "version": "2.88.0", + "resolved": "https://registry.npmjs.org/request/-/request-2.88.0.tgz", + "integrity": "sha512-NAqBSrijGLZdM0WZNsInLJpkJokL72XYjUpnB0iwsRgxh7dB6COrHnTBNwN0E+lHDAJzu7kLAkDeY08z2/A0hg==", + "requires": { + "aws-sign2": "~0.7.0", + "aws4": "^1.8.0", + "caseless": "~0.12.0", + "combined-stream": "~1.0.6", + "extend": "~3.0.2", + "forever-agent": "~0.6.1", + "form-data": "~2.3.2", + "har-validator": "~5.1.0", + "http-signature": "~1.2.0", + "is-typedarray": "~1.0.0", + "isstream": "~0.1.2", + "json-stringify-safe": "~5.0.1", + "mime-types": "~2.1.19", + "oauth-sign": "~0.9.0", + "performance-now": "^2.1.0", + "qs": "~6.5.2", + "safe-buffer": "^5.1.2", + "tough-cookie": "~2.4.3", + "tunnel-agent": "^0.6.0", + "uuid": "^3.3.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + } + } + }, + "require-directory": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/require-directory/-/require-directory-2.1.1.tgz", + "integrity": "sha1-jGStX9MNqxyXbiNE/+f3kqam30I=" + }, + "require-main-filename": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/require-main-filename/-/require-main-filename-1.0.1.tgz", + "integrity": "sha1-l/cXtp1IeE9fUmpsWqj/3aBVpNE=" + }, + "require-uncached": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/require-uncached/-/require-uncached-1.0.3.tgz", + "integrity": "sha1-Tg1W1slmL9MeQwEcS5WqSZVUIdM=", + "dev": true, + "requires": { + "caller-path": "^0.1.0", + "resolve-from": "^1.0.0" + } + }, + "resolve": { + "version": "1.8.1", + "resolved": "https://registry.npmjs.org/resolve/-/resolve-1.8.1.tgz", + "integrity": "sha512-AicPrAC7Qu1JxPCZ9ZgCZlY35QgFnNqc+0LtbRNxnVw4TXvjQ72wnuL9JQcEBgXkI9JM8MsT9kaQoHcpCRJOYA==", + "requires": { + "path-parse": "^1.0.5" + } + }, + "resolve-from": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/resolve-from/-/resolve-from-1.0.1.tgz", + "integrity": "sha1-Jsv+k10a7uq7Kbw/5a6wHpPUQiY=", + "dev": true + }, + "restore-cursor": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/restore-cursor/-/restore-cursor-2.0.0.tgz", + "integrity": "sha1-n37ih/gv0ybU/RYpI9YhKe7g368=", + "dev": true, + "requires": { + "onetime": "^2.0.0", + "signal-exit": "^3.0.2" + } + }, + "retry-as-promised": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-3.1.0.tgz", + "integrity": "sha512-g6T9rr5G4AfRVJZcnCbbmpcTDw8NJSnmVrvrJ9Pm9OWAzigocIcFp4+ItwHGJIr0wx0YzwlCJOvvEKQrZhzPOw==", + "requires": { + "any-promise": "^1.3.0" + } + }, + "rimraf": { + "version": "2.6.2", + "resolved": "https://registry.npmjs.org/rimraf/-/rimraf-2.6.2.tgz", + "integrity": "sha512-lreewLK/BlghmxtfH36YYVg1i8IAce4TI7oao75I1g245+6BctqTVQiBP3YUJ9C6DQOXJmkYR9X9fCLtCOJc5w==", + "requires": { + "glob": "^7.0.5" + } + }, + "run-async": { + "version": "2.3.0", + "resolved": "https://registry.npmjs.org/run-async/-/run-async-2.3.0.tgz", + "integrity": "sha1-A3GrSuC91yDUFm19/aZP96RFpsA=", + "dev": true, + "requires": { + "is-promise": "^2.1.0" + } + }, + "rxjs": { + "version": "6.3.3", + "resolved": "https://registry.npmjs.org/rxjs/-/rxjs-6.3.3.tgz", + "integrity": "sha512-JTWmoY9tWCs7zvIk/CvRjhjGaOd+OVBM987mxFo+OW66cGpdKjZcpmc74ES1sB//7Kl/PAe8+wEakuhG4pcgOw==", + "dev": true, + "requires": { + "tslib": "^1.9.0" + } + }, + "safe-buffer": { + "version": "5.1.1", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.1.tgz", + "integrity": "sha512-kKvNJn6Mm93gAczWVJg7wH+wGYWNrDHdWvpUmHyEsgCtIwwo3bqPtV4tR5tuPaUhTOo/kvhVwd8XwwOllGYkbg==" + }, + "safer-buffer": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/safer-buffer/-/safer-buffer-2.1.2.tgz", + "integrity": "sha512-YZo3K82SD7Riyi0E1EQPojLz7kpepnSQI9IyPbHHg1XXXevb5dJI7tpyN2ADxGcQbHG7vcyRHk0cbwqcQriUtg==" + }, + "sax": { + "version": "1.2.4", + "resolved": "https://registry.npmjs.org/sax/-/sax-1.2.4.tgz", + "integrity": "sha512-NqVDv9TpANUjFm0N8uM5GxL36UgKi9/atZw+x7YFnQ8ckwFGKrl4xX4yWtrey3UJm5nP1kUbnYgLopqWNSRhWw==" + }, + "secure-keys": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/secure-keys/-/secure-keys-1.0.0.tgz", + "integrity": "sha1-8MgtmKOxOah3aogIBQuCRDEIf8o=" + }, + "semver": { + "version": "5.5.1", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.5.1.tgz", + "integrity": "sha512-PqpAxfrEhlSUWge8dwIp4tZnQ25DIOthpiaHNIthsjEFQD6EvqUKUDM7L8O2rShkFccYo1VjJR0coWfNkCubRw==" + }, + "send": { + "version": "0.16.2", + "resolved": "https://registry.npmjs.org/send/-/send-0.16.2.tgz", + "integrity": "sha512-E64YFPUssFHEFBvpbbjr44NCLtI1AohxQ8ZSiJjQLskAdKuriYEP6VyGEsRDH8ScozGpkaX1BGvhanqCwkcEZw==", + "requires": { + "debug": "2.6.9", + "depd": "~1.1.2", + "destroy": "~1.0.4", + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "etag": "~1.8.1", + "fresh": "0.5.2", + "http-errors": "~1.6.2", + "mime": "1.4.1", + "ms": "2.0.0", + "on-finished": "~2.3.0", + "range-parser": "~1.2.0", + "statuses": "~1.4.0" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "statuses": { + "version": "1.4.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.4.0.tgz", + "integrity": "sha512-zhSCtt8v2NDrRlPQpCNtw/heZLtfUDqxBM1udqikb/Hbk52LK4nQSwr10u77iopCW5LsyHpuXS0GnEc48mLeew==" + } + } + }, + "sequelize": { + "version": "4.39.0", + "resolved": "https://registry.npmjs.org/sequelize/-/sequelize-4.39.0.tgz", + "integrity": "sha512-Rra0b81fzNqGLFJEDCsLxWGCDkmscjSsWV25nTrhd4LAk2qWh4I6Qj1iP+2K58ovRmt0QMkt5LNUEpPHZU6njQ==", + "requires": { + "bluebird": "^3.5.0", + "cls-bluebird": "^2.1.0", + "debug": "^3.1.0", + "depd": "^1.1.0", + "dottie": "^2.0.0", + "generic-pool": "^3.4.0", + "inflection": "1.12.0", + "lodash": "^4.17.1", + "moment": "^2.20.0", + "moment-timezone": "^0.5.14", + "retry-as-promised": "^2.3.2", + "semver": "^5.5.0", + "terraformer-wkt-parser": "^1.1.2", + "toposort-class": "^1.0.1", + "uuid": "^3.2.1", + "validator": "^10.4.0", + "wkx": "^0.4.1" + }, + "dependencies": { + "debug": { + "version": "3.2.6", + "resolved": "https://registry.npmjs.org/debug/-/debug-3.2.6.tgz", + "integrity": "sha512-mel+jf7nrtEl5Pn1Qx46zARXKDpBbvzezse7p7LqINmdoIk8PYP5SySaxEmYv6TZ0JyEKA1hsCId6DIhgITtWQ==", + "requires": { + "ms": "^2.1.1" + } + }, + "ms": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.1.tgz", + "integrity": "sha512-tgp+dl5cGk28utYktBsrFqA7HKgrhgPsg6Z/EfhWI4gl1Hwq8B/GmY/0oXZ6nF8hDVesS/FpnYaD/kOWhYQvyg==" + }, + "retry-as-promised": { + "version": "2.3.2", + "resolved": "https://registry.npmjs.org/retry-as-promised/-/retry-as-promised-2.3.2.tgz", + "integrity": "sha1-zZdO5P2bX+A8vzGHHuSCIcB3N7c=", + "requires": { + "bluebird": "^3.4.6", + "debug": "^2.6.9" + }, + "dependencies": { + "debug": { + "version": "2.6.9", + "resolved": "https://registry.npmjs.org/debug/-/debug-2.6.9.tgz", + "integrity": "sha512-bC7ElrdJaJnPbAP+1EotYvqZsb3ecl5wi6Bfi6BJTUcNowp6cvspg0jXznRTKDjm/E7AdgFBVeAPVMNcKGsHMA==", + "requires": { + "ms": "2.0.0" + } + }, + "ms": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/ms/-/ms-2.0.0.tgz", + "integrity": "sha1-VgiurfwAvmwpAd9fmGF4jeDVl8g=" + } + } + } + } + }, + "sequelize-cli": { + "version": "4.1.1", + "resolved": "https://registry.npmjs.org/sequelize-cli/-/sequelize-cli-4.1.1.tgz", + "integrity": "sha512-dcQuE6fwMayB7c+3ICwzMIc3ZBjUY4ieAJvbV/+sL41dMlf4IRh2swD78DAbA6/cT1kRQLbieUvZJnIebddD0g==", + "requires": { + "bluebird": "^3.5.1", + "cli-color": "^1.2.0", + "fs-extra": "^5.0.0", + "js-beautify": "^1.7.4", + "lodash": "^4.17.5", + "resolve": "^1.5.0", + "umzug": "^2.1.0", + "yargs": "^8.0.2" + }, + "dependencies": { + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=" + }, + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=" + }, + "os-locale": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/os-locale/-/os-locale-2.1.0.tgz", + "integrity": "sha512-3sslG3zJbEYcaC4YVAvDorjGxc7tv6KVATnLPZONiljsUncvihe9BQoVCEs0RZ1kmf4Hk9OBqlZfJZWI4GanKA==", + "requires": { + "execa": "^0.7.0", + "lcid": "^1.0.0", + "mem": "^1.1.0" + } + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "requires": { + "ansi-regex": "^3.0.0" + } + }, + "yargs": { + "version": "8.0.2", + "resolved": "https://registry.npmjs.org/yargs/-/yargs-8.0.2.tgz", + "integrity": "sha1-YpmpBVsc78lp/355wdkY3Osiw2A=", + "requires": { + "camelcase": "^4.1.0", + "cliui": "^3.2.0", + "decamelize": "^1.1.1", + "get-caller-file": "^1.0.1", + "os-locale": "^2.0.0", + "read-pkg-up": "^2.0.0", + "require-directory": "^2.1.1", + "require-main-filename": "^1.0.1", + "set-blocking": "^2.0.0", + "string-width": "^2.0.0", + "which-module": "^2.0.0", + "y18n": "^3.2.1", + "yargs-parser": "^7.0.0" + } + } + } + }, + "serve-static": { + "version": "1.13.2", + "resolved": "https://registry.npmjs.org/serve-static/-/serve-static-1.13.2.tgz", + "integrity": "sha512-p/tdJrO4U387R9oMjb1oj7qSMaMfmOyd4j9hOFoxZe2baQszgHcSWjuya/CiT5kgZZKRudHNOA0pYXOl8rQ5nw==", + "requires": { + "encodeurl": "~1.0.2", + "escape-html": "~1.0.3", + "parseurl": "~1.3.2", + "send": "0.16.2" + } + }, + "set-blocking": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/set-blocking/-/set-blocking-2.0.0.tgz", + "integrity": "sha1-BF+XgtARrppoA93TgrJDkrPYkPc=" + }, + "setprototypeof": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/setprototypeof/-/setprototypeof-1.1.0.tgz", + "integrity": "sha512-BvE/TwpZX4FXExxOxZyRGQQv651MSwmWKZGqvmPcRIjDqWub67kTKuIMx43cZZrS/cBBzwBcNDWoFxt2XEFIpQ==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha1-RKrGW2lbAzmJaMOfNj/uXer98eo=", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha1-2kL0l0DAtC2yypcoVxyxkMmO/qM=" + }, + "shimmer": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shimmer/-/shimmer-1.2.0.tgz", + "integrity": "sha512-xTCx2vohXC2EWWDqY/zb4+5Mu28D+HYNSOuFzsyRDRvI/e1ICb69afwaUwfjr+25ZXldbOLyp+iDUZHq8UnTag==" + }, + "sigmund": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/sigmund/-/sigmund-1.0.1.tgz", + "integrity": "sha1-P/IfGYytIXX587eBhT/ZTQ0ZtZA=" + }, + "signal-exit": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.2.tgz", + "integrity": "sha1-tf3AjxKH6hF4Yo5BXiUTK3NkbG0=" + }, + "simple-swizzle": { + "version": "0.2.2", + "resolved": "https://registry.npmjs.org/simple-swizzle/-/simple-swizzle-0.2.2.tgz", + "integrity": "sha1-pNprY1/8zMoz9w0Xy5JZLeleVXo=", + "requires": { + "is-arrayish": "^0.3.1" + }, + "dependencies": { + "is-arrayish": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/is-arrayish/-/is-arrayish-0.3.2.tgz", + "integrity": "sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==" + } + } + }, + "slice-ansi": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/slice-ansi/-/slice-ansi-1.0.0.tgz", + "integrity": "sha512-POqxBK6Lb3q6s047D/XsDVNPnF9Dl8JSaqe9h9lURl0OdNqy/ujDrOiIHtsqXMGbWWTIomRzAMaTyawAU//Reg==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0" + }, + "dependencies": { + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + } + } + }, + "smtp-connection": { + "version": "2.12.0", + "resolved": "https://registry.npmjs.org/smtp-connection/-/smtp-connection-2.12.0.tgz", + "integrity": "sha1-1275EnyyPCJZ7bHoNJwujV4tdME=", + "requires": { + "httpntlm": "1.6.1", + "nodemailer-shared": "1.1.0" + } + }, + "spdx-correct": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/spdx-correct/-/spdx-correct-3.0.2.tgz", + "integrity": "sha512-q9hedtzyXHr5S0A1vEPoK/7l8NpfkFYTq6iCY+Pno2ZbdZR6WexZFtqeVGkGxW3TEJMN914Z55EnAGMmenlIQQ==", + "requires": { + "spdx-expression-parse": "^3.0.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-exceptions": { + "version": "2.2.0", + "resolved": "https://registry.npmjs.org/spdx-exceptions/-/spdx-exceptions-2.2.0.tgz", + "integrity": "sha512-2XQACfElKi9SlVb1CYadKDXvoajPgBVPn/gOQLrTvHdElaVhr7ZEbqJaRnJLVNeaI4cMEAgVCeBMKF6MWRDCRA==" + }, + "spdx-expression-parse": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/spdx-expression-parse/-/spdx-expression-parse-3.0.0.tgz", + "integrity": "sha512-Yg6D3XpRD4kkOmTpdgbUiEJFKghJH03fiC1OPll5h/0sO6neh2jqRDVHOQ4o/LMea0tgCkbMgea5ip/e+MkWyg==", + "requires": { + "spdx-exceptions": "^2.1.0", + "spdx-license-ids": "^3.0.0" + } + }, + "spdx-license-ids": { + "version": "3.0.1", + "resolved": "https://registry.npmjs.org/spdx-license-ids/-/spdx-license-ids-3.0.1.tgz", + "integrity": "sha512-TfOfPcYGBB5sDuPn3deByxPhmfegAhpDYKSOXZQN81Oyrrif8ZCodOLzK3AesELnCx03kikhyDwh0pfvvQvF8w==" + }, + "sprintf-js": { + "version": "1.0.3", + "resolved": "https://registry.npmjs.org/sprintf-js/-/sprintf-js-1.0.3.tgz", + "integrity": "sha1-BOaSb2YolTVPPdAVIDYzuFcpfiw=", + "dev": true + }, + "sqlite3": { + "version": "4.0.3", + "resolved": "https://registry.npmjs.org/sqlite3/-/sqlite3-4.0.3.tgz", + "integrity": "sha512-nuWqc26oiJZXyY5MEz+rQbiki1BTibnXsy8Kqo7QD/ut6eksOWi6uWwFMbdnFNME7CZyplWdDXj2fbdQVaEfuA==", + "requires": { + "nan": "~2.10.0", + "node-pre-gyp": "^0.10.3", + "request": "^2.87.0" + } + }, + "sshpk": { + "version": "1.15.1", + "resolved": "https://registry.npmjs.org/sshpk/-/sshpk-1.15.1.tgz", + "integrity": "sha512-mSdgNUaidk+dRU5MhYtN9zebdzF2iG0cNPWy8HG+W8y+fT1JnSkh0fzzpjOa0L7P8i1Rscz38t0h4gPcKz43xA==", + "requires": { + "asn1": "~0.2.3", + "assert-plus": "^1.0.0", + "bcrypt-pbkdf": "^1.0.0", + "dashdash": "^1.12.0", + "ecc-jsbn": "~0.1.1", + "getpass": "^0.1.1", + "jsbn": "~0.1.0", + "safer-buffer": "^2.0.2", + "tweetnacl": "~0.14.0" + } + }, + "stack-trace": { + "version": "0.0.10", + "resolved": "https://registry.npmjs.org/stack-trace/-/stack-trace-0.0.10.tgz", + "integrity": "sha1-VHxws0fo0ytOEI6hoqFZ5f3eGcA=" + }, + "statuses": { + "version": "1.5.0", + "resolved": "https://registry.npmjs.org/statuses/-/statuses-1.5.0.tgz", + "integrity": "sha1-Fhx9rBd2Wf2YEfQ3cfqZOBR4Yow=" + }, + "string-format": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/string-format/-/string-format-2.0.0.tgz", + "integrity": "sha512-bbEs3scLeYNXLecRRuk6uJxdXUSj6le/8rNPHChIJTn2V79aXVTR1EH2OH5zLKKoz0V02fOUKZZcw01pLUShZA==" + }, + "string-width": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-1.0.2.tgz", + "integrity": "sha1-EYvfW4zcUaKn5w0hHgfisLmxB9M=", + "requires": { + "code-point-at": "^1.0.0", + "is-fullwidth-code-point": "^1.0.0", + "strip-ansi": "^3.0.0" + } + }, + "string_decoder": { + "version": "1.1.1", + "resolved": "https://registry.npmjs.org/string_decoder/-/string_decoder-1.1.1.tgz", + "integrity": "sha512-n/ShnvDi6FHbbVfviro+WojiFzv+s8MPMHBczVePfUpDJLwoLT0ht1l4YwBCbi8pJAveEEdnkHyPyTP/mzRfwg==", + "requires": { + "safe-buffer": "~5.1.0" + } + }, + "strip-ansi": { + "version": "3.0.1", + "resolved": "http://registry.npmjs.org/strip-ansi/-/strip-ansi-3.0.1.tgz", + "integrity": "sha1-ajhfuIU9lS1f8F0Oiq+UJ43GPc8=", + "requires": { + "ansi-regex": "^2.0.0" + } + }, + "strip-bom": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/strip-bom/-/strip-bom-3.0.0.tgz", + "integrity": "sha1-IzTBjpx1n3vdVv3vfprj1YjmjtM=" + }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha1-u0P/VZim6wXYm1n80SnJgzE2Br8=" + }, + "strip-json-comments": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/strip-json-comments/-/strip-json-comments-2.0.1.tgz", + "integrity": "sha1-PFMZQukIwml8DsNEhYwobHygpgo=" + }, + "supports-color": { + "version": "5.5.0", + "resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz", + "integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==", + "requires": { + "has-flag": "^3.0.0" + } + }, + "table": { + "version": "4.0.3", + "resolved": "http://registry.npmjs.org/table/-/table-4.0.3.tgz", + "integrity": "sha512-S7rnFITmBH1EnyKcvxBh1LjYeQMmnZtCXSEbHcH6S0NoKit24ZuFO/T1vDcLdYsLQkM188PVVhQmzKIuThNkKg==", + "dev": true, + "requires": { + "ajv": "^6.0.1", + "ajv-keywords": "^3.0.0", + "chalk": "^2.1.0", + "lodash": "^4.17.4", + "slice-ansi": "1.0.0", + "string-width": "^2.1.1" + }, + "dependencies": { + "ajv": { + "version": "6.5.4", + "resolved": "https://registry.npmjs.org/ajv/-/ajv-6.5.4.tgz", + "integrity": "sha512-4Wyjt8+t6YszqaXnLDfMmG/8AlO5Zbcsy3ATHncCzjW/NoPzAId8AK6749Ybjmdt+kUY1gP60fCu46oDxPv/mg==", + "dev": true, + "requires": { + "fast-deep-equal": "^2.0.1", + "fast-json-stable-stringify": "^2.0.0", + "json-schema-traverse": "^0.4.1", + "uri-js": "^4.2.2" + } + }, + "ansi-regex": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/ansi-regex/-/ansi-regex-3.0.0.tgz", + "integrity": "sha1-7QMXwyIGT3lGbAKWa922Bas32Zg=", + "dev": true + }, + "fast-deep-equal": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/fast-deep-equal/-/fast-deep-equal-2.0.1.tgz", + "integrity": "sha1-ewUhjd+WZ79/Nwv3/bLLFf3Qqkk=", + "dev": true + }, + "is-fullwidth-code-point": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/is-fullwidth-code-point/-/is-fullwidth-code-point-2.0.0.tgz", + "integrity": "sha1-o7MKXE8ZkYMWeqq5O+764937ZU8=", + "dev": true + }, + "json-schema-traverse": { + "version": "0.4.1", + "resolved": "https://registry.npmjs.org/json-schema-traverse/-/json-schema-traverse-0.4.1.tgz", + "integrity": "sha512-xbbCH5dCYU5T8LcEhhuh7HJ88HXuW3qsI3Y0zOZFKfZEHcpWiHU/Jxzk629Brsab/mMiHQti9wMP+845RPe3Vg==", + "dev": true + }, + "string-width": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/string-width/-/string-width-2.1.1.tgz", + "integrity": "sha512-nOqH59deCq9SRHlxq1Aw85Jnt4w6KvLKqWVik6oA9ZklXLNIOlqg4F2yrT1MVaTjAqvVwdfeZ7w7aCvJD7ugkw==", + "dev": true, + "requires": { + "is-fullwidth-code-point": "^2.0.0", + "strip-ansi": "^4.0.0" + } + }, + "strip-ansi": { + "version": "4.0.0", + "resolved": "https://registry.npmjs.org/strip-ansi/-/strip-ansi-4.0.0.tgz", + "integrity": "sha1-qEeQIusaw2iocTibY1JixQXuNo8=", + "dev": true, + "requires": { + "ansi-regex": "^3.0.0" + } + } + } + }, + "table-layout": { + "version": "0.4.4", + "resolved": "https://registry.npmjs.org/table-layout/-/table-layout-0.4.4.tgz", + "integrity": "sha512-uNaR3SRMJwfdp9OUr36eyEi6LLsbcTqTO/hfTsNviKsNeyMBPICJCC7QXRF3+07bAP6FRwA8rczJPBqXDc0CkQ==", + "requires": { + "array-back": "^2.0.0", + "deep-extend": "~0.6.0", + "lodash.padend": "^4.6.1", + "typical": "^2.6.1", + "wordwrapjs": "^3.0.0" + } + }, + "tar": { + "version": "4.4.6", + "resolved": "https://registry.npmjs.org/tar/-/tar-4.4.6.tgz", + "integrity": "sha512-tMkTnh9EdzxyfW+6GK6fCahagXsnYk6kE6S9Gr9pjVdys769+laCTbodXDhPAjzVtEBazRgP0gYqOjnk9dQzLg==", + "requires": { + "chownr": "^1.0.1", + "fs-minipass": "^1.2.5", + "minipass": "^2.3.3", + "minizlib": "^1.1.0", + "mkdirp": "^0.5.0", + "safe-buffer": "^5.1.2", + "yallist": "^3.0.2" + }, + "dependencies": { + "safe-buffer": { + "version": "5.1.2", + "resolved": "https://registry.npmjs.org/safe-buffer/-/safe-buffer-5.1.2.tgz", + "integrity": "sha512-Gd2UZBJDkXlY7GbJxfsE8/nvKkUEU1G38c1siN6QP6a9PT9MmHB8GnpscSmMJSoF8LOIrt8ud/wPtojys4G6+g==" + }, + "yallist": { + "version": "3.0.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-3.0.2.tgz", + "integrity": "sha1-hFK0u36Dx8GI2AQcGoN8dz1ti7k=" + } + } + }, + "terraformer": { + "version": "1.0.9", + "resolved": "https://registry.npmjs.org/terraformer/-/terraformer-1.0.9.tgz", + "integrity": "sha512-YlmQ1fsMWTkKGDGibCRWgmLzrpDRUr63Q025LJ/taYQ6j1Yb8q9McKF7NBi6ACAyUXO6F/bl9w6v4MY307y5Ag==", + "requires": { + "@types/geojson": "^1.0.0" + } + }, + "terraformer-wkt-parser": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/terraformer-wkt-parser/-/terraformer-wkt-parser-1.2.0.tgz", + "integrity": "sha512-QU3iA54St5lF8Za1jg1oj4NYc8sn5tCZ08aNSWDeGzrsaV48eZk1iAVWasxhNspYBoCqdHuoot1pUTUrE1AJ4w==", + "requires": { + "@types/geojson": "^1.0.0", + "terraformer": "~1.0.5" + } + }, + "test-value": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/test-value/-/test-value-3.0.0.tgz", + "integrity": "sha512-sVACdAWcZkSU9x7AOmJo5TqE+GyNJknHaHsMrR6ZnhjVlVN9Yx6FjHrsKZ3BjIpPCT68zYesPWkakrNupwfOTQ==", + "requires": { + "array-back": "^2.0.0", + "typical": "^2.6.1" + } + }, + "text-hex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/text-hex/-/text-hex-1.0.0.tgz", + "integrity": "sha512-uuVGNWzgJ4yhRaNSiubPY7OjISw4sw4E5Uv0wbjp+OzcbmVU/rsT8ujgcXJhn9ypzsgr5vlzpPqP+MBBKcGvbg==" + }, + "text-table": { + "version": "0.2.0", + "resolved": "https://registry.npmjs.org/text-table/-/text-table-0.2.0.tgz", + "integrity": "sha1-f17oI66AUgfACvLfSoTsP8+lcLQ=", + "dev": true + }, + "through": { + "version": "2.3.8", + "resolved": "http://registry.npmjs.org/through/-/through-2.3.8.tgz", + "integrity": "sha1-DdTJ/6q8NXlgsbckEV1+Doai4fU=", + "dev": true + }, + "timers-ext": { + "version": "0.1.7", + "resolved": "https://registry.npmjs.org/timers-ext/-/timers-ext-0.1.7.tgz", + "integrity": "sha512-b85NUNzTSdodShTIbky6ZF02e8STtVVfD+fu4aXXShEELpozH+bCpJLYMPZbsABN2wDH7fJpqIoXxJpzbf0NqQ==", + "requires": { + "es5-ext": "~0.10.46", + "next-tick": "1" + } + }, + "tmp": { + "version": "0.0.33", + "resolved": "https://registry.npmjs.org/tmp/-/tmp-0.0.33.tgz", + "integrity": "sha512-jRCJlojKnZ3addtTOjdIqoRuPEKBvNXcGYqzO6zWZX8KfKEpnGY5jfggJQ3EjKuu8D4bJRr0y+cYJFmYbImXGw==", + "dev": true, + "requires": { + "os-tmpdir": "~1.0.2" + } + }, + "toposort-class": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/toposort-class/-/toposort-class-1.0.1.tgz", + "integrity": "sha1-f/0feMi+KMO6Rc1OGj9e4ZO9mYg=" + }, + "tough-cookie": { + "version": "2.4.3", + "resolved": "https://registry.npmjs.org/tough-cookie/-/tough-cookie-2.4.3.tgz", + "integrity": "sha512-Q5srk/4vDM54WJsJio3XNn6K2sCG+CQ8G5Wz6bZhRZoAe/+TxjWB/GlFAnYEbkYVlON9FMk/fE3h2RLpPXo4lQ==", + "requires": { + "psl": "^1.1.24", + "punycode": "^1.4.1" + } + }, + "triple-beam": { + "version": "1.3.0", + "resolved": "https://registry.npmjs.org/triple-beam/-/triple-beam-1.3.0.tgz", + "integrity": "sha512-XrHUvV5HpdLmIj4uVMxHggLbFSZYIn7HEWsqePZcI50pco+MPqJ50wMGY794X7AOOhxOBAjbkqfAbEe/QMp2Lw==" + }, + "tslib": { + "version": "1.9.3", + "resolved": "https://registry.npmjs.org/tslib/-/tslib-1.9.3.tgz", + "integrity": "sha512-4krF8scpejhaOgqzBEcGM7yDIEfi0/8+8zDRZhNZZ2kjmHJ4hv3zCbQWxoJGz1iw5U0Jl0nma13xzHXcncMavQ==", + "dev": true + }, + "tunnel-agent": { + "version": "0.6.0", + "resolved": "https://registry.npmjs.org/tunnel-agent/-/tunnel-agent-0.6.0.tgz", + "integrity": "sha1-J6XeoGs2sEoKmWZ3SykIaPD8QP0=", + "requires": { + "safe-buffer": "^5.0.1" + } + }, + "tweetnacl": { + "version": "0.14.5", + "resolved": "https://registry.npmjs.org/tweetnacl/-/tweetnacl-0.14.5.tgz", + "integrity": "sha1-WuaBd/GS1EViadEIr6k/+HQ/T2Q=" + }, + "type-check": { + "version": "0.3.2", + "resolved": "https://registry.npmjs.org/type-check/-/type-check-0.3.2.tgz", + "integrity": "sha1-WITKtRLPHTVeP7eE8wgEsrUg23I=", + "dev": true, + "requires": { + "prelude-ls": "~1.1.2" + } + }, + "type-is": { + "version": "1.6.16", + "resolved": "https://registry.npmjs.org/type-is/-/type-is-1.6.16.tgz", + "integrity": "sha512-HRkVv/5qY2G6I8iab9cI7v1bOIdhm94dVjQCPFElW9W+3GeDOSHmy2EBYe4VTApuzolPcmgFTN3ftVJRKR2J9Q==", + "requires": { + "media-typer": "0.3.0", + "mime-types": "~2.1.18" + } + }, + "typical": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/typical/-/typical-2.6.1.tgz", + "integrity": "sha1-XAgOXWYcu+OCWdLnCjxyU+hziB0=" + }, + "umzug": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/umzug/-/umzug-2.1.0.tgz", + "integrity": "sha512-BgT+ekpItEWaG+3JjLLj6yVTxw2wIH8Cr6JyKYIzukWAx9nzGhC6BGHb/IRMjpobMM1qtIrReATwLUjKpU2iOQ==", + "requires": { + "babel-runtime": "^6.23.0", + "bluebird": "^3.4.1", + "lodash": "^4.17.0", + "resolve": "^1.0.0" + } + }, + "underscore": { + "version": "1.9.1", + "resolved": "https://registry.npmjs.org/underscore/-/underscore-1.9.1.tgz", + "integrity": "sha512-5/4etnCkd9c8gwgowi5/om/mYO5ajCaOgdzj/oW+0eQV9WxKBDZw5+ycmKmeaTXjInS/W0BzpGLo2xR2aBwZdg==" + }, + "universalify": { + "version": "0.1.2", + "resolved": "https://registry.npmjs.org/universalify/-/universalify-0.1.2.tgz", + "integrity": "sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==" + }, + "unpipe": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/unpipe/-/unpipe-1.0.0.tgz", + "integrity": "sha1-sr9O6FFKrmFltIF4KdIbLvSZBOw=" + }, + "uri-js": { + "version": "4.2.2", + "resolved": "https://registry.npmjs.org/uri-js/-/uri-js-4.2.2.tgz", + "integrity": "sha512-KY9Frmirql91X2Qgjry0Wd4Y+YTdrdZheS8TFwvkbLWf/G5KNJDCh6pKL5OZctEW4+0Baa5idK2ZQuELRwPznQ==", + "dev": true, + "requires": { + "punycode": "^2.1.0" + }, + "dependencies": { + "punycode": { + "version": "2.1.1", + "resolved": "https://registry.npmjs.org/punycode/-/punycode-2.1.1.tgz", + "integrity": "sha512-XRsRjdf+j5ml+y/6GKHPZbrF/8p2Yga0JPtdqTIY2Xe5ohJPD9saDJJLPvp9+NSBprVvevdXZybnj2cv8OEd0A==", + "dev": true + } + } + }, + "util": { + "version": "0.10.4", + "resolved": "https://registry.npmjs.org/util/-/util-0.10.4.tgz", + "integrity": "sha512-0Pm9hTQ3se5ll1XihRic3FDIku70C+iHUdT/W926rSgHV5QgXsYbKZN8MSC3tJtSkhuROzvsQjAaFENRXr+19A==", + "requires": { + "inherits": "2.0.3" + } + }, + "util-deprecate": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/util-deprecate/-/util-deprecate-1.0.2.tgz", + "integrity": "sha1-RQ1Nyfpw3nMnYvvS1KKJgUGaDM8=" + }, + "utils-merge": { + "version": "1.0.1", + "resolved": "https://registry.npmjs.org/utils-merge/-/utils-merge-1.0.1.tgz", + "integrity": "sha1-n5VxD1CiZ5R7LMwSR0HBAoQn5xM=" + }, + "uuid": { + "version": "3.3.2", + "resolved": "https://registry.npmjs.org/uuid/-/uuid-3.3.2.tgz", + "integrity": "sha512-yXJmeNaw3DnnKAOKJE51sL/ZaYfWJRl1pK9dr19YFCu0ObS231AB1/LbqTKRAQ5kw8A90rA6fr4riOUpTZvQZA==" + }, + "validate-npm-package-license": { + "version": "3.0.4", + "resolved": "https://registry.npmjs.org/validate-npm-package-license/-/validate-npm-package-license-3.0.4.tgz", + "integrity": "sha512-DpKm2Ui/xN7/HQKCtpZxoRWBhZ9Z0kqtygG8XCgNQ8ZlDnxuQmWhj566j8fN4Cu3/JmbhsDo7fcAJq4s9h27Ew==", + "requires": { + "spdx-correct": "^3.0.0", + "spdx-expression-parse": "^3.0.0" + } + }, + "validator": { + "version": "10.8.0", + "resolved": "https://registry.npmjs.org/validator/-/validator-10.8.0.tgz", + "integrity": "sha512-mXqMxfCh5NLsVgYVKl9WvnHNDPCcbNppHSPPowu0VjtSsGWVY+z8hJF44edLR1nbLNzi3jYoYsIl8KZpioIk6g==" + }, + "vary": { + "version": "1.1.2", + "resolved": "https://registry.npmjs.org/vary/-/vary-1.1.2.tgz", + "integrity": "sha1-IpnwLG3tMNSllhsLn3RSShj2NPw=" + }, + "verror": { + "version": "1.10.0", + "resolved": "https://registry.npmjs.org/verror/-/verror-1.10.0.tgz", + "integrity": "sha1-OhBcoXBTr1XW4nDB+CiGguGNpAA=", + "requires": { + "assert-plus": "^1.0.0", + "core-util-is": "1.0.2", + "extsprintf": "^1.2.0" + } + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + }, + "which-module": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/which-module/-/which-module-2.0.0.tgz", + "integrity": "sha1-2e8H3Od7mQK4o6j6SzHD4/fm6Ho=" + }, + "wide-align": { + "version": "1.1.3", + "resolved": "https://registry.npmjs.org/wide-align/-/wide-align-1.1.3.tgz", + "integrity": "sha512-QGkOQc8XL6Bt5PwnsExKBPuMKBxnGxWWW3fU55Xt4feHozMUhdUMaBCk290qpm/wG5u/RSKzwdAC4i51YigihA==", + "requires": { + "string-width": "^1.0.2 || 2" + } + }, + "window-size": { + "version": "0.1.4", + "resolved": "https://registry.npmjs.org/window-size/-/window-size-0.1.4.tgz", + "integrity": "sha1-+OGqHuWlPsW/FR/6CXQqatdpeHY=" + }, + "winston": { + "version": "3.1.0", + "resolved": "https://registry.npmjs.org/winston/-/winston-3.1.0.tgz", + "integrity": "sha512-FsQfEE+8YIEeuZEYhHDk5cILo1HOcWkGwvoidLrDgPog0r4bser1lEIOco2dN9zpDJ1M88hfDgZvxe5z4xNcwg==", + "requires": { + "async": "^2.6.0", + "diagnostics": "^1.1.1", + "is-stream": "^1.1.0", + "logform": "^1.9.1", + "one-time": "0.0.4", + "readable-stream": "^2.3.6", + "stack-trace": "0.0.x", + "triple-beam": "^1.3.0", + "winston-transport": "^4.2.0" + }, + "dependencies": { + "async": { + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/async/-/async-2.6.1.tgz", + "integrity": "sha512-fNEiL2+AZt6AlAw/29Cr0UDe4sRAHCpEHh54WMz+Bb7QfNcFw4h3loofyJpLeQs4Yx7yuqu/2dLgM5hKOs6HlQ==", + "requires": { + "lodash": "^4.17.10" + } + } + } + }, + "winston-transport": { + "version": "4.2.0", + "resolved": "https://registry.npmjs.org/winston-transport/-/winston-transport-4.2.0.tgz", + "integrity": "sha512-0R1bvFqxSlK/ZKTH86nymOuKv/cT1PQBMuDdA7k7f0S9fM44dNH6bXnuxwXPrN8lefJgtZq08BKdyZ0DZIy/rg==", + "requires": { + "readable-stream": "^2.3.6", + "triple-beam": "^1.2.0" + } + }, + "wkx": { + "version": "0.4.5", + "resolved": "https://registry.npmjs.org/wkx/-/wkx-0.4.5.tgz", + "integrity": "sha512-01dloEcJZAJabLO5XdcRgqdKpmnxS0zIT02LhkdWOZX2Zs2tPM6hlZ4XG9tWaWur1Qd1OO4kJxUbe2+5BofvnA==", + "requires": { + "@types/node": "*" + } + }, + "wordwrap": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/wordwrap/-/wordwrap-1.0.0.tgz", + "integrity": "sha1-J1hIEIkUVqQXHI0CJkQa3pDLyus=", + "dev": true + }, + "wordwrapjs": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/wordwrapjs/-/wordwrapjs-3.0.0.tgz", + "integrity": "sha512-mO8XtqyPvykVCsrwj5MlOVWvSnCdT+C+QVbm6blradR7JExAhbkZ7hZ9A+9NUtwzSqrlUo9a67ws0EiILrvRpw==", + "requires": { + "reduce-flatten": "^1.0.1", + "typical": "^2.6.1" + } + }, + "wrap-ansi": { + "version": "2.1.0", + "resolved": "http://registry.npmjs.org/wrap-ansi/-/wrap-ansi-2.1.0.tgz", + "integrity": "sha1-2Pw9KE3QV5T+hJc8rs3Rz4JP3YU=", + "requires": { + "string-width": "^1.0.1", + "strip-ansi": "^3.0.1" + } + }, + "wrappy": { + "version": "1.0.2", + "resolved": "https://registry.npmjs.org/wrappy/-/wrappy-1.0.2.tgz", + "integrity": "sha1-tSQ9jz7BqjXxNkYFvA0QNuMKtp8=" + }, + "write": { + "version": "0.2.1", + "resolved": "https://registry.npmjs.org/write/-/write-0.2.1.tgz", + "integrity": "sha1-X8A4KOJkzqP+kUVUdvejxWbLB1c=", + "dev": true, + "requires": { + "mkdirp": "^0.5.1" + } + }, + "x-xss-protection": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/x-xss-protection/-/x-xss-protection-1.1.0.tgz", + "integrity": "sha512-rx3GzJlgEeZ08MIcDsU2vY2B1QEriUKJTSiNHHUIem6eg9pzVOr2TL3Y4Pd6TMAM5D5azGjcxqI62piITBDHVg==" + }, + "xregexp": { + "version": "2.0.0", + "resolved": "https://registry.npmjs.org/xregexp/-/xregexp-2.0.0.tgz", + "integrity": "sha1-UqY+VsoLhKfzpfPWGHLxJq16WUM=" + }, + "xss-clean": { + "version": "0.1.1", + "resolved": "https://registry.npmjs.org/xss-clean/-/xss-clean-0.1.1.tgz", + "integrity": "sha1-07poTYXM1SBUlj0BrWqzbWYtsaU=", + "requires": { + "xss-filters": "1.2.6" + } + }, + "xss-filters": { + "version": "1.2.6", + "resolved": "https://registry.npmjs.org/xss-filters/-/xss-filters-1.2.6.tgz", + "integrity": "sha1-aLOQicsd/4udvIiUhIObL1B/XFU=" + }, + "y18n": { + "version": "3.2.1", + "resolved": "https://registry.npmjs.org/y18n/-/y18n-3.2.1.tgz", + "integrity": "sha1-bRX7qITAhnnA136I53WegR4H+kE=" + }, + "yallist": { + "version": "2.1.2", + "resolved": "https://registry.npmjs.org/yallist/-/yallist-2.1.2.tgz", + "integrity": "sha1-HBH5IY8HYImkfdUS+TxmmaaoHVI=" + }, + "yargs": { + "version": "3.32.0", + "resolved": "http://registry.npmjs.org/yargs/-/yargs-3.32.0.tgz", + "integrity": "sha1-AwiOnr+edWtpdRYR0qXvWRSCyZU=", + "requires": { + "camelcase": "^2.0.1", + "cliui": "^3.0.3", + "decamelize": "^1.1.1", + "os-locale": "^1.4.0", + "string-width": "^1.0.1", + "window-size": "^0.1.4", + "y18n": "^3.2.0" + } + }, + "yargs-parser": { + "version": "7.0.0", + "resolved": "https://registry.npmjs.org/yargs-parser/-/yargs-parser-7.0.0.tgz", + "integrity": "sha1-jQrELxbqVd69MyyvTEA4s+P139k=", + "requires": { + "camelcase": "^4.1.0" + }, + "dependencies": { + "camelcase": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/camelcase/-/camelcase-4.1.0.tgz", + "integrity": "sha1-1UVjW+HjPFQmScaRc+Xeas+uNN0=" + } + } + } + } +} diff --git a/package.json b/package.json index 8e5b64b0f..79e3ef1d4 100644 --- a/package.json +++ b/package.json @@ -34,11 +34,9 @@ "url": "https://github.com/ioFog/Controller" }, "scripts": { - "test": "echo \"Error: no test specified\" && exit 1", - "start": "NODE_ENV=production node ./src/main.js", + "start": "NODE_ENV=production node ./src/main.js start", + "start-dev": "NODE_ENV=development node ./src/main.js start", "build": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", - "start-dev": "NODE_ENV=development node ./src/main.js", - "build-dev": "export NODE_ENV=development && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", "lint": "./node_modules/.bin/eslint \"**/*.js\"" }, "preferGlobal": true, @@ -71,6 +69,7 @@ "sequelize-cli": "^4.1.1", "sqlite3": "^4.0.2", "string-format": "^2.0.0", + "umzug": "^2.1.0", "underscore": "^1.9.1", "winston": "^3.1.0", "xss-clean": "^0.1.1" diff --git a/src/logger/index.js b/src/logger/index.js index 0f554e5c4..48122a6df 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -31,13 +31,11 @@ const logger = winston.createLogger({ ], }) -// if (process.env.NODE_ENV !== 'production') { logger.add(new winston.transports.Console({ format: winston.format((log) => { log[MESSAGE] = log.message return log })(), })) -// } module.exports = logger diff --git a/src/main.js b/src/main.js index e1324f2ff..0b8617cdb 100644 --- a/src/main.js +++ b/src/main.js @@ -14,6 +14,7 @@ */ const daemonize = require('daemonize2') +const db = require('./sequelize/models') const Cli = require('./cli') const logger = require('./logger') @@ -50,8 +51,12 @@ function main() { cli.run(daemon) } -if (!process.env.NODE_ENV) { - process.env.NODE_ENV = 'production' -} - -main() +db.sequelize + .sync() + .then(db.migrate) + .then(db.seed) + .then(main) + .catch((err) => { + logger.silly('Unable to initialize the database.', err) + process.exit(1) + }) \ No newline at end of file diff --git a/src/sequelize/config/config.json b/src/sequelize/config/config.json index 9ecda2276..52cb1bc9d 100644 --- a/src/sequelize/config/config.json +++ b/src/sequelize/config/config.json @@ -2,7 +2,6 @@ "development": { "dialect": "sqlite", "storage": "dev_database.sqlite", - "logging": true, "operatorsAliases": false }, "test": { diff --git a/src/sequelize/models/index.js b/src/sequelize/models/index.js index 6906a7139..57540ed14 100644 --- a/src/sequelize/models/index.js +++ b/src/sequelize/models/index.js @@ -3,14 +3,15 @@ const fs = require('fs'); const path = require('path'); const Sequelize = require('sequelize'); +const Umzug = require('umzug'); + const basename = path.basename(__filename); -const env = process.env.NODE_ENV || 'development'; +const env = process.env.NODE_ENV || 'production'; const config = require(__dirname + '/../config/config.json')[env]; const db = {}; let sequelize; -//used because sequelize doesn't work with relative path correctly config.storage = path.resolve(__dirname, '../' + config.storage); if (config.use_env_variable) { @@ -19,13 +20,31 @@ if (config.use_env_variable) { sequelize = new Sequelize(config.database, config.username, config.password, config); } +const createUmzug = (path) => { + return new Umzug({ + storage: 'sequelize', + storageOptions: { + sequelize, + }, + logging: false, + migrations: { + params: [ + sequelize.getQueryInterface(), + Sequelize, + ], + path, + pattern: /\.js$/ + }, + }); +} + fs .readdirSync(__dirname) .filter(file => { return (file.indexOf('.') !== 0) && (file !== basename) && (file.slice(-3) === '.js'); }) .forEach(file => { - const model = sequelize['import'](path.join(__dirname, file)); + const model = sequelize.import(path.join(__dirname, file)); db[model.name] = model; }); @@ -38,4 +57,7 @@ Object.keys(db).forEach(modelName => { db.sequelize = sequelize; db.Sequelize = Sequelize; +db.migrate = () => createUmzug(path.resolve(__dirname, '../migrations')).up(); +db.seed = () => createUmzug(path.resolve(__dirname, '../seeders')).up(); + module.exports = db; From 138c2bc654cec9af489ad7684cc4f9c936aad857 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Fri, 2 Nov 2018 16:43:13 +0300 Subject: [PATCH 17/91] v1.0.0 and NODE_ENV processing fix (#295) --- package.json | 3 ++- src/main.js | 20 ++++++++++++-------- 2 files changed, 14 insertions(+), 9 deletions(-) diff --git a/package.json b/package.json index 79e3ef1d4..f74c6a37e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "0.9.5", + "version": "1.0.0", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", @@ -37,6 +37,7 @@ "start": "NODE_ENV=production node ./src/main.js start", "start-dev": "NODE_ENV=development node ./src/main.js start", "build": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", + "postinstall": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", "lint": "./node_modules/.bin/eslint \"**/*.js\"" }, "preferGlobal": true, diff --git a/src/main.js b/src/main.js index 0b8617cdb..b9a9e0cfd 100644 --- a/src/main.js +++ b/src/main.js @@ -13,10 +13,14 @@ * */ -const daemonize = require('daemonize2') -const db = require('./sequelize/models') -const Cli = require('./cli') -const logger = require('./logger') +if (!process.env.NODE_ENV) { + process.env.NODE_ENV = 'production' +} + +const daemonize = require('daemonize2'); +const db = require('./sequelize/models'); +const Cli = require('./cli'); +const logger = require('./logger'); function main() { const daemon = daemonize.setup({ @@ -24,9 +28,9 @@ function main() { name: 'iofog-controller', pidfile: 'iofog-controller.pid', silent: true, - }) + }); - const cli = new Cli() + const cli = new Cli(); daemon .on('starting', () => { @@ -46,7 +50,7 @@ function main() { }) .on('error', (err) => { logger.silly('iofog-controller failed to start: ' + err.message) - }) + }); cli.run(daemon) } @@ -59,4 +63,4 @@ db.sequelize .catch((err) => { logger.silly('Unable to initialize the database.', err) process.exit(1) - }) \ No newline at end of file + }); \ No newline at end of file From 04ad3b1fba095a6f9b25e0220d65dcc339d2bd61 Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 2 Nov 2018 16:43:41 +0300 Subject: [PATCH 18/91] user endpoints fixes (#310) --- specs/swagger.yml | 21 +++++++++++++++++++++ src/schemas/index.js | 3 +++ src/services/user-service.js | 6 ++++++ 3 files changed, 30 insertions(+) diff --git a/specs/swagger.yml b/specs/swagger.yml index 6b21a35cd..6b9e6be29 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -1930,6 +1930,8 @@ paths: responses: 201: description: Success + schema: + $ref: '#/definitions/SignupSuccessResponse' headers: X-Timestamp: type: number @@ -2941,6 +2943,25 @@ definitions: properties: accessToken: type: string + SignupSuccessResponse: + type: object + required: + - userId + - firstName + - lastName + - email + - emailActivated + properties: + userId: + type: number + firstName: + type: string + lastName: + type: string + email: + type: string + emailActivated: + type: boolean UserProfileDetailsResponse: type: object required: diff --git a/src/schemas/index.js b/src/schemas/index.js index 30801e888..ba825c658 100644 --- a/src/schemas/index.js +++ b/src/schemas/index.js @@ -77,6 +77,9 @@ async function handleValidationError(error) { case "type": message = "Field '" + error.property.replace('instance.', '') + "' " + error.message; break; + case "enum": + message = "Field " + error.stack.replace('instance.', ''); + break; default: message = JSON.stringify(error); break; diff --git a/src/services/user-service.js b/src/services/user-service.js index 5ac48b167..6233e3045 100644 --- a/src/services/user-service.js +++ b/src/services/user-service.js @@ -151,6 +151,12 @@ const updateDetails = async function (user, profileData, isCLI, transaction) { AppHelper.deleteUndefinedFields(updateObject); await UserManager.updateDetails(user, updateObject, transaction); + + return { + firstName: updateObject.firstName, + lastName: updateObject.lastName, + email: user.email + } }; const deleteUser = async function (user, isCLI, transaction) { From b663f4fc04ebeb8912c6b210d4458ec50bf4aa54 Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 5 Nov 2018 15:27:56 +0300 Subject: [PATCH 19/91] EWC-311 postman QA collections for user, controller, agent + some code fixes (#313) --- specs/swagger.yml | 6 +- src/controllers/agent-controller.js | 6 +- src/helpers/error-messages.js | 6 +- src/routes/agent.js | 2 +- src/services/agent-service.js | 37 +- ...Controller Testing.postman_collection.json | 1767 +++++++++++++++++ 6 files changed, 1809 insertions(+), 15 deletions(-) create mode 100644 tests/Controller Testing.postman_collection.json diff --git a/specs/swagger.yml b/specs/swagger.yml index 6b9e6be29..81591995f 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -550,7 +550,7 @@ paths: description: Invalid Node Id '500': description: Internal Server Error - '/agent/microservices/{microserviceId}': + '/agent/microservices/{microserviceUuid}': get: tags: - Agent @@ -559,8 +559,8 @@ paths: parameters: - in: path required: true - name: microserviceId - description: Microservice id + name: microserviceUuid + description: Microservice UUID type: string - in: header name: Authorization diff --git a/src/controllers/agent-controller.js b/src/controllers/agent-controller.js index a456617f0..ab078c5d2 100644 --- a/src/controllers/agent-controller.js +++ b/src/controllers/agent-controller.js @@ -53,11 +53,11 @@ const getAgentMicroservicesEndPoint = async function (req, fog) { }; const getAgentMicroserviceEndPoint = async function (req, fog) { - const microserviceId = req.params.microserviceId; + const microserviceUuid = req.params.microserviceUuid; - logger.info("Microservice id:" + JSON.stringify(microserviceId)); + logger.info("Microservice UUID:" + JSON.stringify(microserviceUuid)); - return await AgentService.getAgentMicroservice(microserviceId, fog); + return await AgentService.getAgentMicroservice(microserviceUuid, fog); }; const getAgentRegistriesEndPoint = async function (req, fog) { diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 2a7c9c0ec..6d6e3ab9f 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -22,7 +22,7 @@ module.exports = { UNABLE_TO_GET_ACTIVATION_CODE: 'Unable to create activation code', INVALID_FOG_NODE_UUID: 'Invalid ioFog UUID {}', INVALID_USER_EMAIL: 'Invalid user email', - INVALID_MICROSERVICE_UUID: 'Invalid microservice UUID {}', + INVALID_MICROSERVICE_UUID: "Invalid microservice UUID '{}'", ACTIVATION_CODE_NOT_FOUND: 'Activation code not found', INVALID_OLD_PASSWORD: 'Old password is incorrect', ACCOUNT_NOT_FOUND: 'Account not found', @@ -53,6 +53,10 @@ module.exports = { REQUIRED_FOG_NODE: 'ioFog node is required.', INVALID_CONNECTOR_DOMAIN: 'Invalid connector domain {}', CERT_PROPERTY_REQUIRED: 'Property "certificate" is required if property "requiresCert" is set to true', + TUNNEL_NOT_FOUND: 'Tunnel not found', + STRACE_NOT_FOUND: 'Strace not found', + INVALID_CONTENT_TYPE: 'Invalid content type', + UPLOADED_FILE_NOT_FOUND: 'Uploaded image snapshot file not found', CLI: { INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.', INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.', diff --git a/src/routes/agent.js b/src/routes/agent.js index a4d1874ef..f2610e1e1 100644 --- a/src/routes/agent.js +++ b/src/routes/agent.js @@ -180,7 +180,7 @@ module.exports = [ }, { method: 'get', - path: '/api/v3/agent/microservices/:microserviceId', + path: '/api/v3/agent/microservices/:microserviceUuid', middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; const errorCodes = [ diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 45dee62dd..48ff590b7 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -249,11 +249,15 @@ const getAgentMicroservices = async function (fog, transaction) { } }; -const getAgentMicroservice = async function (microserviceId, fog, transaction) { +const getAgentMicroservice = async function (microserviceUuid, fog, transaction) { const microservice = await MicroserviceManager.findOneWithDependencies({ - uuid: microserviceId, + uuid: microserviceUuid, iofogUuid: fog.uuid }, {}, transaction); + + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); + } return { microservice: microservice } @@ -280,16 +284,26 @@ const getAgentTunnel = async function (fog, transaction) { const tunnel = await TunnelManager.findOne({ iofogUuid: fog.uuid }, transaction); + + if (!tunnel) { + throw new Errors.NotFoundError(ErrorMessages.TUNNEL_NOT_FOUND); + } + return { tunnel: tunnel } }; const getAgentStrace = async function (fog, transaction) { - const fogWithDependencies = FogManager.findFogStraces({ + const fogWithStrace = FogManager.findFogStraces({ uuid: fog.uuid }, transaction); - return fogWithDependencies.strace; + + if (!fogWithStrace) { + throw new Errors.NotFoundError(ErrorMessages.STRACE_NOT_FOUND); + } + + return fogWithStrace.strace; }; const updateAgentStrace = async function (straceData, fog, transaction) { @@ -363,6 +377,10 @@ const getImageSnapshot = async function (fog, transaction) { }; const putImageSnapshot = async function (req, fog, transaction) { + if (req.headers['content-type'] !== 'application/zip') { + throw new Errors.ValidationError(ErrorMessages.INVALID_CONTENT_TYPE); + } + const form = new formidable.IncomingForm(); form.uploadDir = path.join(appRoot, '../') + 'data'; if (!fs.existsSync(form.uploadDir)) { @@ -380,12 +398,17 @@ const putImageSnapshot = async function (req, fog, transaction) { const saveSnapShot = function (req, form) { return new Promise((resolve, reject) => { + form.parse(req, async function (error, fields, files) { - if (error) { - reject(new Errors.ValidationError()); + const file = files['upstream']; + + if (file === undefined) { + reject(new Errors.ValidationError(ErrorMessages.UPLOADED_FILE_NOT_FOUND)); + return; } - const filePath = files['upstream']['path']; + const filePath = file['path']; + let absolutePath = path.resolve(filePath); fs.rename(absolutePath, absolutePath + '.tar.gz'); diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json new file mode 100644 index 000000000..43cba7644 --- /dev/null +++ b/tests/Controller Testing.postman_collection.json @@ -0,0 +1,1767 @@ +{ + "info": { + "_postman_id": "0c412a3a-7328-4c9e-8919-d2836adccfa1", + "name": "Controller Testing", + "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" + }, + "item": [ + { + "name": "User", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "Activate user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 404\"] = responseCode.code === 404;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Activation code not found\";" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"activationCode\": \"string\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/activate", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "activate" + ] + } + }, + "response": [] + }, + { + "name": "Resend activation email", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup/resend-activation?email=user@domain.com", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup", + "resend-activation" + ], + "query": [ + { + "key": "email", + "value": "user@domain.com" + } + ] + } + }, + "response": [] + }, + { + "name": "Get user profile", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.firstName && data.lastName && data.email;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "Update user profile", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.firstName && data.lastName && data.email;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"Saeid\",\n \"lastName\": \"Rezaei\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + }, + { + "name": "Change password", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"oldPassword\": \"#Bugs4Fun\",\n \"newPassword\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/password", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "password" + ] + } + }, + "response": [] + }, + { + "name": "Reset password", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/password", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "password" + ] + } + }, + "response": [] + }, + { + "name": "Logout", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/logout", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "logout" + ] + } + }, + "response": [] + }, + { + "name": "Login 2", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "Delete user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "General", + "item": [ + { + "name": "Status", + "event": [ + { + "listen": "test", + "script": { + "id": "d674c862-a5e5-4034-95eb-c8c8830c54ab", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.status && data.hasOwnProperty('timestamp');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/status", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "status" + ] + } + }, + "response": [] + }, + { + "name": "Get email activation setting", + "event": [ + { + "listen": "test", + "script": { + "id": "5c76f0c8-1e8c-4c59-a219-dfabe7d898cb", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('isEmailActivationEnabled');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/email-activation", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "email-activation" + ] + } + }, + "response": [] + }, + { + "name": "Get Fog types", + "event": [ + { + "listen": "test", + "script": { + "id": "86f7b7e4-7841-4e57-b02a-ec3312a8e4ac", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.fogTypes;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/fog-types", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "fog-types" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Agent", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"node-id\", data.uuid);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"location\": \"string\",\n \"latitude\": 0,\n \"longitude\": 0,\n \"description\": \"string\",\n \"dockerUrl\": \"string\",\n \"diskLimit\": 0,\n \"diskDirectory\": \"string\",\n \"memoryLimit\": 0,\n \"cpuLimit\": 0,\n \"logLimit\": 0,\n \"logDirectory\": \"string\",\n \"logFileCount\": 0,\n \"statusFrequency\": 0,\n \"changeFrequency\": 0,\n \"deviceScanFrequency\": 0,\n \"bluetoothEnabled\": false,\n \"watchdogEnabled\": true,\n \"abstractedHardwareEnabled\": false,\n \"fogType\": 0\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog" + ] + } + }, + "response": [] + }, + { + "name": "Provisioning Key", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.key;", + "", + "postman.setGlobalVariable(\"provisioning-key\", data.key);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/provisioning-key", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "provisioning-key" + ] + } + }, + "response": [] + }, + { + "name": "Agent provision", + "event": [ + { + "listen": "test", + "script": { + "id": "163b99b3-7e44-4550-95aa-ed1298f69b48", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.token;", + "", + "postman.setGlobalVariable(\"agent-token\", data.token);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"{{provisioning-key}}\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/provision", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "provision" + ] + } + }, + "response": [] + }, + { + "name": "Get agent config", + "event": [ + { + "listen": "test", + "script": { + "id": "a54b1534-6e3d-4315-8eee-80aebecfe383", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.networkInterface && data.dockerUrl && data.hasOwnProperty('diskLimit') && data.diskDirectory", + "&& data.hasOwnProperty('memoryLimit') && data.hasOwnProperty('cpuLimit') && data.hasOwnProperty('logLimit') ", + "&& data.logDirectory && data.hasOwnProperty('logFileCount') ", + "&& data.hasOwnProperty('statusFrequency') && data.hasOwnProperty('changeFrequency') && data.hasOwnProperty('deviceScanFrequency') && data.hasOwnProperty('watchdogEnabled')", + "&& data.hasOwnProperty('latitude') && data.hasOwnProperty('longitude')" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/config", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "config" + ] + } + }, + "response": [] + }, + { + "name": "Update agent config", + "event": [ + { + "listen": "test", + "script": { + "id": "c98e0ec6-82ab-4026-a355-11a245ee5824", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"networkInterface\": \"wlan0\",\r\n \"dockerUrl\": \"http://google.com\",\r\n \"diskLimit\": 15,\r\n \"diskDirectory\": \"testDirectoryPath\",\r\n \"memoryLimit\": 150,\r\n \"cpuLimit\": 17,\r\n \"logLimit\": 16,\r\n \"logDirectory\": \"testLogPath\",\r\n \"logFileCount\": 7,\r\n \"statusFrequency\": 35,\r\n \"changeFrequency\": 36,\r\n \"deviceScanFrequency\": 37,\r\n \"watchdogEnabled\": true,\r\n \"latitude\": 22,\r\n \"longitude\": 66,\r\n \"gpsMode\": \"manual\"\r\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/config", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "config" + ] + } + }, + "response": [] + }, + { + "name": "Get agent config changes", + "event": [ + { + "listen": "test", + "script": { + "id": "2dbf7447-aab4-4b4a-acd4-3083bc0f65d3", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('config') && data.hasOwnProperty('version') && data.hasOwnProperty('reboot')", + "&& data.hasOwnProperty('deleteNode') && data.hasOwnProperty('microserviceList') && data.hasOwnProperty('microserviceConfig')", + "&& data.hasOwnProperty('routing') && data.hasOwnProperty('registries') && data.hasOwnProperty('tunnel') && data.hasOwnProperty('diagnostics')", + "&& data.hasOwnProperty('isImageSnapshot');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/config/changes", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "config", + "changes" + ] + } + }, + "response": [] + }, + { + "name": "Update agent status", + "event": [ + { + "listen": "test", + "script": { + "id": "15295395-0fcd-4138-9f51-6fcd85e569b5", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"daemonStatus\": \"RUNNING\",\r\n \"daemonOperatingDuration\": 15,\r\n \"daemonLastStart\": 25,\r\n \"memoryUsage\": 16,\r\n \"diskUsage\": 14,\r\n \"cpuUsage\": 17,\r\n \"memoryViolation\": true,\r\n \"diskViolation\": true,\r\n \"cpuViolation\": true,\r\n \"microserviceStatus\": \"RUNNING\",\r\n \"repositoryCount\": 5,\r\n \"repositoryStatus\": \"RUNNING\",\r\n \"systemTime\": 155,\r\n \"lastStatusTime\": 166,\r\n \"ipAddress\": \"192.168.0.1\",\r\n \"processedMessages\": 255,\r\n \"microserviceMessageCounts\": \"counts\",\r\n \"messageSpeed\": 52,\r\n \"lastCommandTime\": 57,\r\n \"tunnelStatus\": \"on\",\r\n \"version\": \"1\",\r\n \"isReadyToUpgrade\": true,\r\n \"isReadyToRollback\": true\r\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/status", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "status" + ] + } + }, + "response": [] + }, + { + "name": "Get agent microservices", + "event": [ + { + "listen": "test", + "script": { + "id": "40a4e202-0442-4c3d-b7f9-6b35f7e851c4", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.microservices;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "Get agent microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "157595c7-1beb-4516-84d9-3def5142a50f", + "exec": [ + "tests[\"Status code is 404\"] = responseCode.code === 404;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Invalid microservice UUID 'abcedf'\"" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/microservices/abcedf", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "microservices", + "abcedf" + ] + } + }, + "response": [] + }, + { + "name": "Get agent registries", + "event": [ + { + "listen": "test", + "script": { + "id": "039fc07b-463e-49b0-9996-f18edece7cd3", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.registries;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/registries", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "registries" + ] + } + }, + "response": [] + }, + { + "name": "Get agent tunnel", + "event": [ + { + "listen": "test", + "script": { + "id": "69a2995c-ae44-47d2-9831-dae9c3abfe9c", + "exec": [ + "tests[\"Status code is 404\"] = responseCode.code === 404;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Tunnel not found\"" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/tunnel", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "tunnel" + ] + } + }, + "response": [] + }, + { + "name": "Get agent strace", + "event": [ + { + "listen": "test", + "script": { + "id": "6fb0a761-864d-4465-a6a2-276be8849d5b", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/strace", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "strace" + ] + } + }, + "response": [] + }, + { + "name": "Put agent strace", + "event": [ + { + "listen": "test", + "script": { + "id": "20ad0ef9-f534-4013-a88a-f3642748f9ac", + "exec": [ + "tests[\"Status code is 404\"] = responseCode.code === 404;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Invalid ioFog UUID\"" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"straceData\": [\r\n {\r\n \"microserviceId\": \"abcdef\",\r\n \"buffer\": \"test\"\r\n }\r\n ]\r\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/strace", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "strace" + ] + } + }, + "response": [] + }, + { + "name": "Get change version command", + "event": [ + { + "listen": "test", + "script": { + "id": "11230b41-dc3c-4202-8194-6a30ee5cafbe", + "exec": [ + "tests[\"Status code is 404\"] = responseCode.code === 404;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Version command not found\"" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/version", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "version" + ] + } + }, + "response": [] + }, + { + "name": "Update hardware info", + "event": [ + { + "listen": "test", + "script": { + "id": "51994b21-ac38-40a8-ae08-4ac3bd40ac12", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"info\": \"testData\"\r\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/hal/hw", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "hal", + "hw" + ] + } + }, + "response": [] + }, + { + "name": "Update USB info", + "event": [ + { + "listen": "test", + "script": { + "id": "252f9f3b-f84b-46fd-b83b-dda45f5d493c", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"info\": \"testData2\"\r\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/hal/usb", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "hal", + "usb" + ] + } + }, + "response": [] + }, + { + "name": "Get image snapshot", + "event": [ + { + "listen": "test", + "script": { + "id": "c47b8a61-2386-4ecf-9d37-8a01ec1f5c49", + "exec": [ + "tests[\"Status code is 404\"] = responseCode.code === 404;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === \"NotFoundError\" && data.message === \"Image snapshot not found\"" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/image-snapshot", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "image-snapshot" + ] + } + }, + "response": [] + }, + { + "name": "Update image snapshot", + "event": [ + { + "listen": "test", + "script": { + "id": "ce22d82d-556e-41d5-b665-353c3aae4b3d", + "exec": [ + "tests[\"Status code is 400\"] = responseCode.code === 400;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === \"ValidationError\" && data.message === \"Uploaded image snapshot file not found\"" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/zip" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\r\n \"info\": \"testData2\"\r\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/image-snapshot", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "image-snapshot" + ] + } + }, + "response": [] + }, + { + "name": "Delete agent node", + "event": [ + { + "listen": "test", + "script": { + "id": "b803da95-63d7-40a2-b48e-640e0c73e0d5", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "disabled": false, + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{agent-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/agent/delete-node", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "agent", + "delete-node" + ] + } + }, + "response": [] + }, + { + "name": "Delete user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] + } + ], + "event": [ + { + "listen": "prerequest", + "script": { + "id": "b36a00ce-1c45-40ae-989e-e80ea6c0a789", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "68c4eca9-f898-496e-853b-58b4bfa43f5b", + "type": "text/javascript", + "exec": [ + "" + ] + } + } + ], + "variable": [ + { + "id": "0cd8c928-a4e1-41ac-8c8f-a57d4e75ba89", + "key": "host", + "value": "localhost:51121", + "type": "string" + } + ] +} \ No newline at end of file From 6d687d0105910649d7298ae8406b7a6bcb4bff54 Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 5 Nov 2018 16:22:26 +0300 Subject: [PATCH 20/91] EWC-313 postman QA flow section (#314) --- src/services/flow-service.js | 10 +- ...Controller Testing.postman_collection.json | 388 +++++++++++++++++- 2 files changed, 395 insertions(+), 3 deletions(-) diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 41e7166d9..53612fccd 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -116,11 +116,17 @@ const _getUserFlows = async function (user, isCLI, transaction) { userId: user.id }; - return await FlowManager.findAllExcludeFields(flow, transaction) + const flows = await FlowManager.findAllExcludeFields(flow, transaction); + return { + flows: flows + } }; const _getAllFlows = async function (isCLI, transaction) { - return await FlowManager.findAll({}, transaction); + const flows = await FlowManager.findAll({}, transaction); + return { + flows: flows + } }; const _checkForDuplicateName = async function (name, item, userId, transaction) { diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 43cba7644..30494c3e1 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1732,6 +1732,392 @@ "response": [] } ] + }, + { + "name": "Flow", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"flow-id\", data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Flow Name\",\n \"description\": \"Description\",\n \"isActivated\": true\n}" + }, + "url": { + "raw": "{{host}}/api/v3/flow", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow" + ] + } + }, + "response": [] + }, + { + "name": "Get Flows", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('flows');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/flow", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow" + ] + } + }, + "response": [] + }, + { + "name": "Get Flow By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id') && data.name && data.description && data.hasOwnProperty('isActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/flow/{{flow-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow", + "{{flow-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Update Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Flow Name 22\",\n \"description\": \"Description\",\n \"isActivated\": true\n}" + }, + "url": { + "raw": "{{host}}/api/v3/flow/{{flow-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow", + "{{flow-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/flow/{{flow-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow", + "{{flow-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -1758,7 +2144,7 @@ ], "variable": [ { - "id": "0cd8c928-a4e1-41ac-8c8f-a57d4e75ba89", + "id": "1a291aeb-b1ca-4099-9e67-89604a5093b1", "key": "host", "value": "localhost:51121", "type": "string" From beb85f88c4b7bde4bb3ddd76ceec55457aebe8ee Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 5 Nov 2018 16:52:43 +0300 Subject: [PATCH 21/91] EWC-312 postman QA catalog (#315) --- src/services/catalog-service.js | 7 +- ...Controller Testing.postman_collection.json | 397 +++++++++++++++++- 2 files changed, 401 insertions(+), 3 deletions(-) diff --git a/src/services/catalog-service.js b/src/services/catalog-service.js index a9dc3dc26..97b37069f 100644 --- a/src/services/catalog-service.js +++ b/src/services/catalog-service.js @@ -99,7 +99,7 @@ const _updateCatalogItemIOTypes = async function (data, where, transaction) { inputType = AppHelper.deleteUndefinedFields(inputType); await CatalogItemInputTypeManager.update({catalogItemId: data.id}, inputType, transaction); } - if (data.outputType && data.outputType.length !=0) { + if (data.outputType && data.outputType.length !== 0) { let outputType = { infoType: data.outputType.infoType, infoFormat: data.outputType.infoFormat @@ -118,7 +118,10 @@ const listCatalogItems = async function (user, isCLI, transaction) { ? {} : {exclude: ["userId"]}; - return await CatalogItemManager.findAllWithDependencies(where, attributes, transaction); + const catalogItems = await CatalogItemManager.findAllWithDependencies(where, attributes, transaction); + return { + catalogItems: catalogItems + } }; const getCatalogItem = async function (id, user, isCLI, transaction) { diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 30494c3e1..9cf9116a0 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -2118,6 +2118,401 @@ "response": [] } ] + }, + { + "name": "Catalog", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Catalog Item", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"item-id\", data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"description\": \"string\",\n \"category\": \"string\",\n \"images\": [\n {\n \"containerImage\": \"x86 docker image name\",\n \"fogTypeId\": 1\n },\n {\n \"containerImage\": \"ARM docker image name\",\n \"fogTypeId\": 2\n }\n ],\n \"publisher\": \"string\",\n \"diskRequired\": 0,\n \"ramRequired\": 0,\n \"picture\": \"string\",\n \"isPublic\": true,\n \"registryId\": 1,\n \"inputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"outputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"configExample\": \"string\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "Get Catalog Items", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('catalogItems');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "Get Catalog Item By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id') && data.name && data.description && data.category && data.configExample", + "&& data.publisher && data.hasOwnProperty('diskRequired') && data.hasOwnProperty('ramRequired') && data.picture && data.hasOwnProperty('isPublic')", + "&& data.hasOwnProperty('registryId') && data.hasOwnProperty('images') && data.hasOwnProperty('inputType') && data.hasOwnProperty('outputType');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices/{{item-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices", + "{{item-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Update Catalog Item", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"description\": \"string\",\n \"category\": \"string\",\n \"images\": [\n {\n \"containerImage\": \"x86 docker image name\",\n \"fogTypeId\": 1\n },\n {\n \"containerImage\": \"ARM docker image name\",\n \"fogTypeId\": 2\n }\n ],\n \"publisher\": \"string\",\n \"diskRequired\": 0,\n \"ramRequired\": 0,\n \"picture\": \"string\",\n \"isPublic\": true,\n \"registryId\": 1,\n \"inputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"outputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"configExample\": \"string\"\n}\n" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices/{{item-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices", + "{{item-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete Catalog Item By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices/{{item-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices", + "{{item-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -2144,7 +2539,7 @@ ], "variable": [ { - "id": "1a291aeb-b1ca-4099-9e67-89604a5093b1", + "id": "828a5d14-b19c-440a-a801-d8651e8d975b", "key": "host", "value": "localhost:51121", "type": "string" From e961dcaca7c5ef3e622ff5949afb83772251ead3 Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 5 Nov 2018 17:05:32 +0300 Subject: [PATCH 22/91] EWC-316 postman QA tunnel (#316) --- ...Controller Testing.postman_collection.json | 345 +++++++++++++++++- 1 file changed, 344 insertions(+), 1 deletion(-) diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 9cf9116a0..5c79c2da7 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -2513,6 +2513,349 @@ "response": [] } ] + }, + { + "name": "Tunnel", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"node-id\", data.uuid);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"location\": \"string\",\n \"latitude\": 0,\n \"longitude\": 0,\n \"description\": \"string\",\n \"dockerUrl\": \"string\",\n \"diskLimit\": 0,\n \"diskDirectory\": \"string\",\n \"memoryLimit\": 0,\n \"cpuLimit\": 0,\n \"logLimit\": 0,\n \"logDirectory\": \"string\",\n \"logFileCount\": 0,\n \"statusFrequency\": 0,\n \"changeFrequency\": 0,\n \"deviceScanFrequency\": 0,\n \"bluetoothEnabled\": false,\n \"watchdogEnabled\": true,\n \"abstractedHardwareEnabled\": false,\n \"fogType\": 0\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog" + ] + } + }, + "response": [] + }, + { + "name": "Open SSH Tunnel To ioFog Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"action\": \"open\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/tunnel", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "tunnel" + ] + } + }, + "response": [] + }, + { + "name": "Get Node SSH Tunnel Info", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.username && data.host && data.hasOwnProperty('remotePort') && data.hasOwnProperty('localPort') && data.status;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/tunnel", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "tunnel" + ] + } + }, + "response": [] + }, + { + "name": "Close SSH Tunnel To ioFog Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"action\": \"close\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/tunnel", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "tunnel" + ] + } + }, + "response": [] + }, + { + "name": "Delete user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -2539,7 +2882,7 @@ ], "variable": [ { - "id": "828a5d14-b19c-440a-a801-d8651e8d975b", + "id": "74c6e07c-13f3-4f95-a35c-2a138b6a04fc", "key": "host", "value": "localhost:51121", "type": "string" From 5197b708edb3a31478ced4df0c146b71b5c80b69 Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 6 Nov 2018 13:15:18 +0300 Subject: [PATCH 23/91] EWC-308 postman QA microservices (#318) * EWC-308 postman QA microservices * EWC-308 postman QA diagnostics --- src/controllers/microservices-controller.js | 45 +- src/services/microservices-service.js | 5 +- ...Controller Testing.postman_collection.json | 1732 ++++++++++++++++- 3 files changed, 1759 insertions(+), 23 deletions(-) diff --git a/src/controllers/microservices-controller.js b/src/controllers/microservices-controller.js index e11173af0..65ae7e30d 100644 --- a/src/controllers/microservices-controller.js +++ b/src/controllers/microservices-controller.js @@ -26,7 +26,7 @@ const _createMicroservicesOnFogEndPoint = async function (req, user) { const _getMicroserviceEndPoint = async function (req, user) { const microserviceUuid = req.params.uuid; - logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)) + logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); return await MicroservicesService.getMicroserviceWithTransaction(microserviceUuid, user, false) }; @@ -35,8 +35,8 @@ const _updateMicroserviceEndPoint = async function (req, user) { const microservice = req.body; const microserviceUuid = req.params.uuid; - logger.info("Parameters:" + JSON.stringify(microservice)) - logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)) + logger.info("Parameters:" + JSON.stringify(microservice)); + logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); return await MicroservicesService.updateMicroserviceWithTransaction(microserviceUuid, microservice, user, false) }; @@ -45,8 +45,8 @@ const _deleteMicroserviceEndPoint = async function (req, user) { const microserviceUuid = req.params.uuid; const deleteWithCleanUp = (req.query.withCleanUp == 'true'); - logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)) - logger.info("Delete with cleanup:" + JSON.stringify(deleteWithCleanUp)) + logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); + logger.info("Delete with cleanup:" + JSON.stringify(deleteWithCleanUp)); return await MicroservicesService.deleteMicroserviceWithTransaction(microserviceUuid, deleteWithCleanUp, user, false) }; @@ -54,43 +54,46 @@ const _deleteMicroserviceEndPoint = async function (req, user) { const _getMicroservicesByFlowEndPoint = async function (req, user) { const flowId = req.query.flowId; - logger.info("Flow id:" + flowId) + logger.info("Flow id:" + flowId); return await MicroservicesService.listMicroservicesWithTransaction(flowId, user, false) }; async function _createMicroserviceRoute(req, user) { - const sourceUuid = req.params.uuid - const distUuid = req.params.receiverUuid - logger.info(`Creating route from ${sourceUuid} to ${distUuid}`) + const sourceUuid = req.params.uuid; + const distUuid = req.params.receiverUuid; + logger.info(`Creating route from ${sourceUuid} to ${distUuid}`); return await MicroservicesService.createRouteWithTransaction(sourceUuid, distUuid, user, false) } async function _deleteMicroserviceRoute(req, user) { - const sourceUuid = req.params.uuid - const distUuid = req.params.receiverUuid - logger.info(`Creating route from ${sourceUuid} to ${distUuid}`) + const sourceUuid = req.params.uuid; + const distUuid = req.params.receiverUuid; + logger.info(`Creating route from ${sourceUuid} to ${distUuid}`); return await MicroservicesService.deleteRouteWithTransaction(sourceUuid, distUuid, user, false) } async function _createMicroservicePortMapping(req, user) { - const uuid = req.params.uuid - const portMappingData = req.body - logger.info(`Creating port mapping for ${uuid}`) + const uuid = req.params.uuid; + const portMappingData = req.body; + logger.info(`Creating port mapping for ${uuid}`); return await MicroservicesService.createPortMappingWithTransaction(uuid, portMappingData, user, false) } async function _deleteMicroservicePortMapping(req, user) { - const uuid = req.params.uuid - const internalPort = req.params.internalPort - logger.info(`Deleting port mapping for ${uuid}`) + const uuid = req.params.uuid; + const internalPort = req.params.internalPort; + logger.info(`Deleting port mapping for ${uuid}`); return await MicroservicesService.deletePortMappingWithTransaction(uuid, internalPort, user, false) } async function _getMicroservicePortMappingList(req, user) { - const uuid = req.params.uuid - logger.info(`Getting all port mappings for ${uuid}`) - return await MicroservicesService.getMicroservicePortMappingListWithTransaction(uuid, user, false) + const uuid = req.params.uuid; + logger.info(`Getting all port mappings for ${uuid}`); + const ports = await MicroservicesService.getMicroservicePortMappingListWithTransaction(uuid, user, false); + return { + ports: ports + } } module.exports = { diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 31c1bd7ad..ab94b91ee 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -36,7 +36,10 @@ const _listMicroservices = async function (flowId, user, isCLI, transaction) { } const where = isCLI ? {} : {flowId: flowId}; - return await MicroserviceManager.findAllExcludeFields(where, transaction); + const microservices = await MicroserviceManager.findAllExcludeFields(where, transaction); + return { + microservices: microservices + } }; const _getMicroservice = async function (microserviceUuid, user, isCLI, transaction) { diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 5c79c2da7..0081a9961 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -2856,6 +2856,1736 @@ "response": [] } ] + }, + { + "name": "Microservices", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"node-id\", data.uuid);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"location\": \"string\",\n \"latitude\": 0,\n \"longitude\": 0,\n \"description\": \"string\",\n \"dockerUrl\": \"string\",\n \"diskLimit\": 0,\n \"diskDirectory\": \"string\",\n \"memoryLimit\": 0,\n \"cpuLimit\": 0,\n \"logLimit\": 0,\n \"logDirectory\": \"string\",\n \"logFileCount\": 0,\n \"statusFrequency\": 0,\n \"changeFrequency\": 0,\n \"deviceScanFrequency\": 0,\n \"bluetoothEnabled\": false,\n \"watchdogEnabled\": true,\n \"abstractedHardwareEnabled\": false,\n \"fogType\": 0\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog" + ] + } + }, + "response": [] + }, + { + "name": "New Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"flow-id\", data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Flow Name\",\n \"description\": \"Description\",\n \"isActivated\": true\n}" + }, + "url": { + "raw": "{{host}}/api/v3/flow", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow" + ] + } + }, + "response": [] + }, + { + "name": "New Catalog Item", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"item-id\", data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"description\": \"string\",\n \"category\": \"string\",\n \"images\": [\n {\n \"containerImage\": \"x86 docker image name\",\n \"fogTypeId\": 1\n },\n {\n \"containerImage\": \"ARM docker image name\",\n \"fogTypeId\": 2\n }\n ],\n \"publisher\": \"string\",\n \"diskRequired\": 0,\n \"ramRequired\": 0,\n \"picture\": \"string\",\n \"isPublic\": true,\n \"registryId\": 1,\n \"inputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"outputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"configExample\": \"string\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "New Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"ms-id\", data.uuid);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"ioFogNodeId\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" + }, + "url": { + "raw": "{{host}}/api/v3/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "Get Microservices", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('microservices');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices?flowId={{flow-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices" + ], + "query": [ + { + "key": "flowId", + "value": "{{flow-id}}" + } + ] + } + }, + "response": [] + }, + { + "name": "Get Microservice By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid && data.config && data.name && data.hasOwnProperty('rootHostAccess') && data.hasOwnProperty('logSize');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Update Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"name3\",\n \"config\": \"string\",\n \"needUpdate\": true,\n \"rebuild\": true,\n \"ioFogNodeId\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"imageSnapshot\": \"string\",\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ]\n}\n" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Create a Route From Microservice to Receiver", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/routes/{{ms-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "routes", + "{{ms-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete a Route From Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/routes/{{ms-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "routes", + "{{ms-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Add a Port Mapping to Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"internal\": 15,\n \"external\": 155,\n \"publicMode\": false\n}" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/port-mapping", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "port-mapping" + ] + } + }, + "response": [] + }, + { + "name": "Get Port Mappings", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('ports');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/port-mapping-list", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "port-mapping-list" + ] + } + }, + "response": [] + }, + { + "name": "Delete a Port Mapping By Provided Internal Port", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/port-mapping/15", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "port-mapping", + "15" + ] + } + }, + "response": [] + }, + { + "name": "Delete a Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}?withCleanUp=true", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}" + ], + "query": [ + { + "key": "withCleanUp", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/flow/{{flow-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow", + "{{flow-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete Catalog Item By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices/{{item-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices", + "{{item-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 202\"] = responseCode.code === 202;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete User", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] + }, + { + "name": "Diagnostics", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"node-id\", data.uuid);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"location\": \"string\",\n \"latitude\": 0,\n \"longitude\": 0,\n \"description\": \"string\",\n \"dockerUrl\": \"string\",\n \"diskLimit\": 0,\n \"diskDirectory\": \"string\",\n \"memoryLimit\": 0,\n \"cpuLimit\": 0,\n \"logLimit\": 0,\n \"logDirectory\": \"string\",\n \"logFileCount\": 0,\n \"statusFrequency\": 0,\n \"changeFrequency\": 0,\n \"deviceScanFrequency\": 0,\n \"bluetoothEnabled\": false,\n \"watchdogEnabled\": true,\n \"abstractedHardwareEnabled\": false,\n \"fogType\": 0\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog" + ] + } + }, + "response": [] + }, + { + "name": "New Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"flow-id\", data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"Flow Name\",\n \"description\": \"Description\",\n \"isActivated\": true\n}" + }, + "url": { + "raw": "{{host}}/api/v3/flow", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow" + ] + } + }, + "response": [] + }, + { + "name": "New Catalog Item", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"item-id\", data.id);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"description\": \"string\",\n \"category\": \"string\",\n \"images\": [\n {\n \"containerImage\": \"x86 docker image name\",\n \"fogTypeId\": 1\n },\n {\n \"containerImage\": \"ARM docker image name\",\n \"fogTypeId\": 2\n }\n ],\n \"publisher\": \"string\",\n \"diskRequired\": 0,\n \"ramRequired\": 0,\n \"picture\": \"string\",\n \"isPublic\": true,\n \"registryId\": 1,\n \"inputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"outputType\": {\n \"infoType\": \"string\",\n \"infoFormat\": \"string\"\n },\n \"configExample\": \"string\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "New Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"ms-id\", data.uuid);" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"ioFogNodeId\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" + }, + "url": { + "raw": "{{host}}/api/v3/microservices", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices" + ] + } + }, + "response": [] + }, + { + "name": "Request to Create Image Snapshot", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/image-snapshot", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "image-snapshot" + ] + } + }, + "response": [] + }, + { + "name": "Download Image Snapshot", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/image-snapshotFIXIT", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "image-snapshotFIXIT" + ] + } + }, + "response": [] + }, + { + "name": "Enable/Disable Microservice Strace Option", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"enable\": true\n}" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/strace", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "strace" + ] + } + }, + "response": [] + }, + { + "name": "Get Strace Data For Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('data');", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/strace?format=string", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "strace" + ], + "query": [ + { + "key": "format", + "value": "string" + } + ] + }, + "description": "available formats:\n\t- string\n\t- file" + }, + "response": [] + }, + { + "name": "Post Strace Data to FTP Server", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 500\"] = responseCode.code === 500;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response error message is valid\"] = data.name === 'FtpError' && data.message === 'FTP error: Error: Timeout while connecting to server';" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"ftpHost\": \"string\",\n \"ftpPort\": 0,\n \"ftpUser\": \"string\",\n \"ftpPass\": \"string\",\n \"ftpDestDir\": \"string\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/strace", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "strace" + ] + } + }, + "response": [] + }, + { + "name": "Delete a Microservice", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}?withCleanUp=true", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}" + ], + "query": [ + { + "key": "withCleanUp", + "value": "true" + } + ] + } + }, + "response": [] + }, + { + "name": "Delete Flow", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/flow/{{flow-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "flow", + "{{flow-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete Catalog Item By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/catalog/microservices/{{item-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "catalog", + "microservices", + "{{item-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 202\"] = responseCode.code === 202;", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete User", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -2882,7 +4612,7 @@ ], "variable": [ { - "id": "74c6e07c-13f3-4f95-a35c-2a138b6a04fc", + "id": "8c5861f9-a3a9-4d32-8ec6-b3098b60d3ed", "key": "host", "value": "localhost:51121", "type": "string" From 176c5054b61b000b865598e0c57c45716d8dd529 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Tue, 6 Nov 2018 13:20:03 +0300 Subject: [PATCH 24/91] postinstall script deleted (#319) --- package.json | 1 - 1 file changed, 1 deletion(-) diff --git a/package.json b/package.json index f74c6a37e..2d32ad068 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,6 @@ "start": "NODE_ENV=production node ./src/main.js start", "start-dev": "NODE_ENV=development node ./src/main.js start", "build": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", - "postinstall": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", "lint": "./node_modules/.bin/eslint \"**/*.js\"" }, "preferGlobal": true, From 646af5d6e7482a637dfb0345691464b2a3ff9f8f Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 6 Nov 2018 14:36:57 +0300 Subject: [PATCH 25/91] EWC-310 postman QA iofog (#321) --- src/controllers/iofog-controller.js | 34 +- src/routes/iofog.js | 68 +- src/sequelize/models/fog.js | 2 +- src/services/iofog-service.js | 140 ++-- ...Controller Testing.postman_collection.json | 695 +++++++++++++++++- 5 files changed, 817 insertions(+), 122 deletions(-) diff --git a/src/controllers/iofog-controller.js b/src/controllers/iofog-controller.js index bfc8602b9..99832bc59 100644 --- a/src/controllers/iofog-controller.js +++ b/src/controllers/iofog-controller.js @@ -11,62 +11,62 @@ * */ -const logger = require('../logger') +const logger = require('../logger'); const AuthDecorator = require('../decorators/authorization-decorator'); -const FogService = require('../services/iofog-service') +const FogService = require('../services/iofog-service'); async function _createFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const newFog = req.body + const newFog = req.body; return await FogService.createFogWithTransaction(newFog, user, false) } async function _updateFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const updateFog = req.body - updateFog.uuid = req.params.uuid + const updateFog = req.body; + updateFog.uuid = req.params.uuid; return await FogService.updateFogWithTransaction(updateFog, user, false) } async function _deleteFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const deleteFog = {} - deleteFog.uuid = req.params.uuid + const deleteFog = {}; + deleteFog.uuid = req.params.uuid; return await FogService.deleteFogWithTransaction(deleteFog, user, false) } async function _getFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const getFog = {} - getFog.uuid = req.params.uuid + const getFog = {}; + getFog.uuid = req.params.uuid; return await FogService.getFogWithTransaction(getFog, user, false) } async function _getFogList(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const filters = Array.from(req.body) + const filters = Array.from(req.body); return await FogService.getFogListWithTransaction(filters, user, false) } async function _generateProvisioningKey(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const fog = {} - fog.uuid = req.params.uuid + const fog = {}; + fog.uuid = req.params.uuid; return await FogService.generateProvisioningKeyWithTransaction(fog, user, false) } async function _setFogVersionCommand(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const fogVersionCommand = {} - fogVersionCommand.uuid = req.params.uuid - fogVersionCommand.versionCommand = req.params.versionCommand + const fogVersionCommand = {}; + fogVersionCommand.uuid = req.params.uuid; + fogVersionCommand.versionCommand = req.params.versionCommand; return await FogService.setFogVersionCommandWithTransaction(fogVersionCommand, user, false) } async function _setFogRebootCommand(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); - const fog = {} - fog.uuid = req.params.uuid + const fog = {}; + fog.uuid = req.params.uuid; return await FogService.setFogRebootCommandWithTransaction(fog, user, false) } diff --git a/src/routes/iofog.js b/src/routes/iofog.js index 1b9522a28..9f987cd3a 100644 --- a/src/routes/iofog.js +++ b/src/routes/iofog.js @@ -10,17 +10,17 @@ * ******************************************************************************* * */ -const constants = require('../helpers/constants') -const FogController = require('../controllers/iofog-controller') -const ResponseDecorator = require('../decorators/response-decorator') -const Errors = require('../helpers/errors') +const constants = require('../helpers/constants'); +const FogController = require('../controllers/iofog-controller'); +const ResponseDecorator = require('../decorators/response-decorator'); +const Errors = require('../helpers/errors'); module.exports = [ { method: 'post', path: '/api/v3/iofog-list', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_SUCCESS + const successCode = constants.HTTP_CODE_SUCCESS; const errCodes = [ { code: 400, @@ -30,10 +30,10 @@ module.exports = [ code: 401, errors: [Errors.AuthenticationError] } - ] + ]; - const getFogList = ResponseDecorator.handleErrors(FogController.getFogList, successCode, errCodes) - const responseObject = await getFogList(req) + const getFogList = ResponseDecorator.handleErrors(FogController.getFogList, successCode, errCodes); + const responseObject = await getFogList(req); res .status(responseObject.code) @@ -44,7 +44,7 @@ module.exports = [ method: 'post', path: '/api/v3/iofog', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_CREATED + const successCode = constants.HTTP_CODE_CREATED; const errCodes = [ { code: 400, @@ -54,10 +54,10 @@ module.exports = [ code: 401, errors: [Errors.AuthenticationError] } - ] + ]; - const createFog = ResponseDecorator.handleErrors(FogController.createFog, successCode, errCodes) - const responseObject = await createFog(req) + const createFog = ResponseDecorator.handleErrors(FogController.createFog, successCode, errCodes); + const responseObject = await createFog(req); res .status(responseObject.code) @@ -68,7 +68,7 @@ module.exports = [ method: 'patch', path: '/api/v3/iofog/:uuid', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_NO_CONTENT + const successCode = constants.HTTP_CODE_NO_CONTENT; const errCodes = [ { code: 400, @@ -82,10 +82,10 @@ module.exports = [ code: 404, errors: [Errors.NotFoundError] } - ] + ]; - const updateFog = ResponseDecorator.handleErrors(FogController.updateFog, successCode, errCodes) - const responseObject = await updateFog(req) + const updateFog = ResponseDecorator.handleErrors(FogController.updateFog, successCode, errCodes); + const responseObject = await updateFog(req); res .status(responseObject.code) @@ -106,10 +106,10 @@ module.exports = [ code: 404, errors: [Errors.NotFoundError] } - ] + ]; - const deleteFog = ResponseDecorator.handleErrors(FogController.deleteFog, successCode, errCodes) - const responseObject = await deleteFog(req) + const deleteFog = ResponseDecorator.handleErrors(FogController.deleteFog, successCode, errCodes); + const responseObject = await deleteFog(req); res .status(responseObject.code) @@ -120,7 +120,7 @@ module.exports = [ method: 'get', path: '/api/v3/iofog/:uuid', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_SUCCESS + const successCode = constants.HTTP_CODE_SUCCESS; const errCodes = [ { code: 401, @@ -130,10 +130,10 @@ module.exports = [ code: 404, errors: [Errors.NotFoundError] } - ] + ]; - const getFog = ResponseDecorator.handleErrors(FogController.getFog, successCode, errCodes) - const responseObject = await getFog(req) + const getFog = ResponseDecorator.handleErrors(FogController.getFog, successCode, errCodes); + const responseObject = await getFog(req); res .status(responseObject.code) @@ -144,7 +144,7 @@ module.exports = [ method: 'get', path: '/api/v3/iofog/:uuid/provisioning-key', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_CREATED + const successCode = constants.HTTP_CODE_CREATED; const errCodes = [ { code: 401, @@ -156,8 +156,8 @@ module.exports = [ } ] - const generateFogProvisioningKey = ResponseDecorator.handleErrors(FogController.generateProvisioningKey, successCode, errCodes) - const responseObject = await generateFogProvisioningKey(req) + const generateFogProvisioningKey = ResponseDecorator.handleErrors(FogController.generateProvisioningKey, successCode, errCodes); + const responseObject = await generateFogProvisioningKey(req); res .status(responseObject.code) @@ -168,7 +168,7 @@ module.exports = [ method: 'post', path: '/api/v3/iofog/:uuid/version/:versionCommand', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_NO_CONTENT + const successCode = constants.HTTP_CODE_NO_CONTENT; const errCodes = [ { code: 400, @@ -182,10 +182,10 @@ module.exports = [ code: 404, errors: [Errors.NotFoundError] } - ] + ]; - const setFogVersionCommand = ResponseDecorator.handleErrors(FogController.setFogVersionCommand, successCode, errCodes) - const responseObject = await setFogVersionCommand(req) + const setFogVersionCommand = ResponseDecorator.handleErrors(FogController.setFogVersionCommand, successCode, errCodes); + const responseObject = await setFogVersionCommand(req); res .status(responseObject.code) @@ -196,7 +196,7 @@ module.exports = [ method: 'post', path: '/api/v3/iofog/:uuid/reboot', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_NO_CONTENT + const successCode = constants.HTTP_CODE_NO_CONTENT; const errCodes = [ { code: 400, @@ -210,11 +210,11 @@ module.exports = [ code: 404, errors: [Errors.NotFoundError] } - ] + ]; - const setFogRebootCommand = ResponseDecorator.handleErrors(FogController.setFogRebootCommand, successCode, errCodes) - const responseObject = await setFogRebootCommand(req) + const setFogRebootCommand = ResponseDecorator.handleErrors(FogController.setFogRebootCommand, successCode, errCodes); + const responseObject = await setFogRebootCommand(req); res .status(responseObject.code) diff --git a/src/sequelize/models/fog.js b/src/sequelize/models/fog.js index fb9a7bc7b..d25743ab2 100644 --- a/src/sequelize/models/fog.js +++ b/src/sequelize/models/fog.js @@ -32,7 +32,7 @@ module.exports = (sequelize, DataTypes) => { type: DataTypes.TEXT, field: 'description' }, - lastactive: { + lastActive: { type: DataTypes.BIGINT, field: 'last_active' }, diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 9a91950f0..57d7b939b 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -22,11 +22,11 @@ const ErrorMessages = require('../helpers/error-messages'); const Validator = require('../schemas'); const HWInfoManager = require('../sequelize/managers/hw-info-manager'); const USBInfoManager = require('../sequelize/managers/usb-info-manager'); -const CatalogService = require('../services/catalog-service') -const MicroserviceManager = require('../sequelize/managers/microservice-manager') +const CatalogService = require('../services/catalog-service'); +const MicroserviceManager = require('../sequelize/managers/microservice-manager'); async function _createFog(fogData, user, isCli, transaction) { - await Validator.validate(fogData, Validator.schemas.iofogCreate) + await Validator.validate(fogData, Validator.schemas.iofogCreate); let createFogData = { uuid: fogData.uuid ? fogData.uuid : AppHelper.generateRandomString(32), @@ -53,22 +53,22 @@ async function _createFog(fogData, user, isCli, transaction) { fogTypeId: fogData.fogType, userId: user.id } - createFogData = AppHelper.deleteUndefinedFields(createFogData) + createFogData = AppHelper.deleteUndefinedFields(createFogData); - const fog = await FogManager.create(createFogData, transaction) + const fog = await FogManager.create(createFogData, transaction); const res = { uuid: fog.uuid - } + }; - await ChangeTrackingManager.create({iofogUuid: fog.uuid}, transaction) + await ChangeTrackingManager.create({iofogUuid: fog.uuid}, transaction); //TODO: proccess watchdog flag //TODO refactor. call MicroserviceService.createMicroservice //TODO: refactor. to function if (fogData.abstractedHardwareEnabled) { - const halItem = await CatalogService.getHalCatalogItem(transaction) + const halItem = await CatalogService.getHalCatalogItem(transaction); const halMicroserviceData = { uuid: AppHelper.generateRandomString(32), @@ -80,14 +80,14 @@ async function _createFog(fogData, user, isCli, transaction) { logSize: 50, updatedBy: user.id, configLastUpdated: Date.now() - } + }; await MicroserviceManager.create(halMicroserviceData, transaction); } //TODO: refactor. to function if (fogData.bluetoothEnabled) { - const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction) + const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); const bluetoothMicroserviceData = { uuid: AppHelper.generateRandomString(32), @@ -99,7 +99,7 @@ async function _createFog(fogData, user, isCli, transaction) { logSize: 50, updatedBy: user.id, configLastUpdated: Date.now() - } + }; await MicroserviceManager.create(bluetoothMicroserviceData, transaction); } @@ -108,19 +108,19 @@ async function _createFog(fogData, user, isCli, transaction) { iofogUuid: fogData.uuid, config: true, containerList: true - } + }; - await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, changeTrackingUpdates, transaction) + await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, changeTrackingUpdates, transaction); return res } async function _updateFog(fogData, user, isCli, transaction) { - await Validator.validate(fogData, Validator.schemas.iofogUpdate) + await Validator.validate(fogData, Validator.schemas.iofogUpdate); const queryFogData = isCli ? {uuid: fogData.uuid} - : {uuid: fogData.uuid, userId: user.id} + : {uuid: fogData.uuid, userId: user.id}; let updateFogData = { name: fogData.name, @@ -144,29 +144,29 @@ async function _updateFog(fogData, user, isCli, transaction) { watchdogEnabled: fogData.watchdogEnabled, abstractedHardwareEnabled: fogData.abstractedHardwareEnabled, fogTypeId: fogData.fogType, - } - updateFogData = AppHelper.deleteUndefinedFields(updateFogData) + }; + updateFogData = AppHelper.deleteUndefinedFields(updateFogData); - const oldFog = await FogManager.findOne(queryFogData, transaction) + const oldFog = await FogManager.findOne(queryFogData, transaction); if (!oldFog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - await FogManager.update(queryFogData, updateFogData, transaction) + await FogManager.update(queryFogData, updateFogData, transaction); //TODO: refactor. to function if (oldFog.bluetoothEnabled === true && fogData.bluetoothEnabled === false) { - const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction) + const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); const deleteBluetoothMicroserviceData = { iofogUuid: fogData.uuid, catalogItemId: bluetoothItem.id - } + }; await MicroserviceManager.delete(deleteBluetoothMicroserviceData, transaction) } //TODO: refactor. to function if (oldFog.bluetoothEnabled === false && fogData.bluetoothEnabled === true) { - const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction) + const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); const bluetoothMicroserviceData = { uuid: AppHelper.generateRandomString(32), @@ -178,25 +178,25 @@ async function _updateFog(fogData, user, isCli, transaction) { logSize: 50, updatedBy: user.id, configLastUpdated: Date.now() - } + }; await MicroserviceManager.create(bluetoothMicroserviceData, transaction); } //TODO: refactor. to function if (oldFog.abstractedHardwareEnabled === true && fogData.abstractedHardwareEnabled === false) { - const halItem = await CatalogService.getHalCatalogItem(transaction) + const halItem = await CatalogService.getHalCatalogItem(transaction); const deleteHalMicroserviceData = { iofogUuid: fogData.uuid, catalogItemId: halItem.id - } + }; await MicroserviceManager.delete(deleteHalMicroserviceData, transaction) } //TODO: refactor. to function if (oldFog.abstractedHardwareEnabled === false && fogData.abstractedHardwareEnabled === true) { - const halItem = await CatalogService.getHalCatalogItem(transaction) + const halItem = await CatalogService.getHalCatalogItem(transaction); const halMicroserviceData = { uuid: AppHelper.generateRandomString(32), @@ -208,134 +208,136 @@ async function _updateFog(fogData, user, isCli, transaction) { logSize: 50, updatedBy: user.id, configLastUpdated: Date.now() - } + }; await MicroserviceManager.create(halMicroserviceData, transaction); } - //TODO: proccess watchdog + //TODO: process watchdog const changeTrackingUpdates = { iofogUuid: fogData.uuid, config: true, containerList: true - } + }; await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, changeTrackingUpdates, transaction) } async function _deleteFog(fogData, user, isCli, transaction) { - await Validator.validate(fogData, Validator.schemas.iofogDelete) + await Validator.validate(fogData, Validator.schemas.iofogDelete); const queryFogData = isCli ? {uuid: fogData.uuid} - : {uuid: fogData.uuid, userId: user.id} + : {uuid: fogData.uuid, userId: user.id}; - const fog = await FogManager.findOne(queryFogData, transaction) + const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - await _updateFogsConnectionStatus(fog, transaction) + await _updateFogsConnectionStatus(fog, transaction); await _processDeleteCommand(fog, transaction) } async function _getFog(fogData, user, isCli, transaction) { - await Validator.validate(fogData, Validator.schemas.iofogGet) + await Validator.validate(fogData, Validator.schemas.iofogGet); const queryFogData = isCli ? {uuid: fogData.uuid} - : {uuid: fogData.uuid, userId: user.id} + : {uuid: fogData.uuid, userId: user.id}; - const fog = await FogManager.findOne(queryFogData, transaction) + const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - await _updateFogsConnectionStatus(fog, transaction) + await _updateFogsConnectionStatus(fog, transaction); return fog } async function _getFogList(filters, user, isCli, transaction) { - await Validator.validate(filters, Validator.schemas.iofogFilters) + await Validator.validate(filters, Validator.schemas.iofogFilters); const queryFogData = isCli ? {} - : {userId: user.id} + : {userId: user.id}; - let fogs = await FogManager.findAll(queryFogData, transaction) - fogs = _filterFogs(fogs, filters) + let fogs = await FogManager.findAll(queryFogData, transaction); + fogs = _filterFogs(fogs, filters); for (const fog of fogs) { await _updateFogsConnectionStatus(fog, transaction) } - return fogs + return { + fogs: fogs + } } async function _generateProvisioningKey(fogData, user, isCli, transaction) { - await Validator.validate(fogData, Validator.schemas.iofogGenerateProvision) + await Validator.validate(fogData, Validator.schemas.iofogGenerateProvision); const queryFogData = isCli ? {uuid: fogData.uuid} - : {uuid: fogData.uuid, userId: user.id} + : {uuid: fogData.uuid, userId: user.id}; const newProvision = { iofogUuid: fogData.uuid, provisionKey: AppHelper.generateRandomString(8), expirationTime: new Date().getTime() + (20 * 60 * 1000) - } + }; - const fog = await FogManager.findOne(queryFogData, transaction) + const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - const provisioningKeyData = await FogProvisionKeyManager.updateOrCreate({iofogUuid: fogData.uuid}, newProvision, transaction) + const provisioningKeyData = await FogProvisionKeyManager.updateOrCreate({iofogUuid: fogData.uuid}, newProvision, transaction); const res = { key: provisioningKeyData.provisionKey, expirationTime: provisioningKeyData.expirationTime - } + }; return res } async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { - await Validator.validate(fogVersionData, Validator.schemas.iofogSetVersionCommand) + await Validator.validate(fogVersionData, Validator.schemas.iofogSetVersionCommand); const queryFogData = isCli ? {uuid: fogVersionData.uuid} - : {uuid: fogVersionData.uuid, userId: user.id} + : {uuid: fogVersionData.uuid, userId: user.id}; const newVersionCommand = { iofogUuid: fogVersionData.uuid, versionCommand: fogVersionData.versionCommand - } + }; const changeTrackingUpdates = { iofogUuid: fogVersionData.uuid, version: true - } + }; - const fog = await FogManager.findOne(queryFogData, transaction) + const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - await _generateProvisioningKey({uuid: fogVersionData.uuid}, user, isCli, transaction) - await FogVersionCommandManager.updateOrCreate({iofogUuid: fogVersionData.uuid}, newVersionCommand, transaction) + await _generateProvisioningKey({uuid: fogVersionData.uuid}, user, isCli, transaction); + await FogVersionCommandManager.updateOrCreate({iofogUuid: fogVersionData.uuid}, newVersionCommand, transaction); await ChangeTrackingManager.update({iofogUuid: fogVersionData.uuid}, changeTrackingUpdates, transaction) } async function _setFogRebootCommand(fogData, user, isCli, transaction) { - await Validator.validate(fogData, Validator.schemas.iofogReboot) + await Validator.validate(fogData, Validator.schemas.iofogReboot); const queryFogData = isCli ? {uuid: fogData.uuid} - : {uuid: fogData.uuid, userId: user.id} + : {uuid: fogData.uuid, userId: user.id}; const newRebootCommand = { iofogUuid: fogData.uuid, reboot: true - } + }; - const fog = await FogManager.findOne(queryFogData, transaction) + const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } @@ -378,9 +380,9 @@ function _filterFogs(fogs, filters) { return fogs } - const filtered = [] + const filtered = []; fogs.forEach((fog) => { - let isMatchFog = true + let isMatchFog = true; filters.some((filter) => { let fld = filter.key, val = filter.value, @@ -391,22 +393,22 @@ function _filterFogs(fogs, filters) { isMatchFog = false; return false } - }) + }); if (isMatchFog) { filtered.push(fog) } - }) + }); return filtered } async function _updateFogsConnectionStatus(fog, transaction) { - const minInMs = 60000 - const intervalInMs = fog.statusFrequency > minInMs ? fog.statusFrequency * 2 : minInMs + const minInMs = 60000; + const intervalInMs = fog.statusFrequency > minInMs ? fog.statusFrequency * 2 : minInMs; if (fog.daemonStatus !== 'UNKNOWN' && Date.now() - fog.lastStatusTime > intervalInMs) { - fog.daemonStatus = 'UNKNOWN' - fog.ipAddress = '0.0.0.0' - const queryFogData = {uuid: fog.uuid} - const toUpdate = {daemonStatus: fog.daemonStatus, ipAddress: fog.ipAddress} + fog.daemonStatus = 'UNKNOWN'; + fog.ipAddress = '0.0.0.0'; + const queryFogData = {uuid: fog.uuid}; + const toUpdate = {daemonStatus: fog.daemonStatus, ipAddress: fog.ipAddress}; await FogManager.update(queryFogData, toUpdate, transaction) } } diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 0081a9961..841a805e5 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -4586,6 +4586,699 @@ "response": [] } ] + }, + { + "name": "ioFog", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "New Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid;", + "", + "postman.setGlobalVariable(\"node-id\", data.uuid);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"location\": \"string\",\n \"latitude\": 0,\n \"longitude\": 0,\n \"description\": \"string\",\n \"dockerUrl\": \"string\",\n \"diskLimit\": 0,\n \"diskDirectory\": \"string\",\n \"memoryLimit\": 0,\n \"cpuLimit\": 0,\n \"logLimit\": 0,\n \"logDirectory\": \"string\",\n \"logFileCount\": 0,\n \"statusFrequency\": 0,\n \"changeFrequency\": 0,\n \"deviceScanFrequency\": 0,\n \"bluetoothEnabled\": false,\n \"watchdogEnabled\": true,\n \"abstractedHardwareEnabled\": false,\n \"fogType\": 0\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog" + ] + } + }, + "response": [] + }, + { + "name": "Provisioning Key", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.key;", + "", + "postman.setGlobalVariable(\"provisioning-key\", data.key);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/provisioning-key", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "provisioning-key" + ] + } + }, + "response": [] + }, + { + "name": "List ioFog Nodes", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('fogs');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "[\n {\n \"key\": \"uuid\",\n \"value\": \"{{node-id}}\",\n \"condition\": \"equals\"\n }\n]" + }, + "url": { + "raw": "{{host}}/api/v3/iofog-list", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog-list" + ] + } + }, + "response": [] + }, + { + "name": "Update Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"string\",\n \"location\": \"string\",\n \"latitude\": 0,\n \"longitude\": 0,\n \"description\": \"string\",\n \"dockerUrl\": \"string\",\n \"diskLimit\": 0,\n \"diskDirectory\": \"string\",\n \"memoryLimit\": 0,\n \"cpuLimit\": 0,\n \"logLimit\": 0,\n \"logDirectory\": \"string\",\n \"logFileCount\": 0,\n \"statusFrequency\": 0,\n \"changeFrequency\": 0,\n \"deviceScanFrequency\": 0,\n \"bluetoothEnabled\": false,\n \"watchdogEnabled\": true,\n \"abstractedHardwareEnabled\": false,\n \"fogType\": 0\n}" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Get Node By Id", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.uuid && data.name && data.location && data.hasOwnProperty('gpsMode') && data.hasOwnProperty('latitude')", + "&& data.hasOwnProperty('longitude') && data.description && data.hasOwnProperty('lastActive') && data.daemonStatus && data.hasOwnProperty('daemonOperatingDuration') ", + "&& data.hasOwnProperty('daemonLastStart') && data.hasOwnProperty('memoryUsage') && data.hasOwnProperty('diskUsage') && data.hasOwnProperty('cpuUsage') ", + "&& data.hasOwnProperty('memoryViolation') && data.hasOwnProperty('diskViolation') && data.hasOwnProperty('cpuViolation') && data.hasOwnProperty('catalogItemStatus')", + "&& data.hasOwnProperty('repositoryCount') && data.hasOwnProperty('repositoryStatus') && data.hasOwnProperty('systemTime') && data.hasOwnProperty('lastStatusTime')", + "&& data.hasOwnProperty('ipAddress') && data.hasOwnProperty('processedMessages') && data.hasOwnProperty('catalogItemMessageCounts') && data.hasOwnProperty('messageSpeed')", + "&& data.hasOwnProperty('lastCommandTime') && data.hasOwnProperty('networkInterface') && data.hasOwnProperty('dockerUrl') && data.hasOwnProperty('diskLimit')", + "&& data.hasOwnProperty('diskDirectory') && data.hasOwnProperty('memoryLimit') && data.hasOwnProperty('cpuLimit') && data.hasOwnProperty('logLimit')", + "&& data.logDirectory && data.hasOwnProperty('bluetoothEnabled') && data.hasOwnProperty('abstractedHardwareEnabled') && data.hasOwnProperty('logFileCount') ", + "&& data.hasOwnProperty('version') && data.hasOwnProperty('isReadyToUpgrade') && data.hasOwnProperty('isReadyToRollback') && data.hasOwnProperty('statusFrequency')", + "&& data.hasOwnProperty('changeFrequency') && data.hasOwnProperty('deviceScanFrequency') && data.hasOwnProperty('tunnel') && data.hasOwnProperty('watchdogEnabled')", + "&& data.hasOwnProperty('fogTypeId') && data.hasOwnProperty('userId');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Node Version Command rollback", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/version/rollback", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "version", + "rollback" + ] + }, + "description": "change version command\nAvailable values : upgrade, rollback" + }, + "response": [] + }, + { + "name": "Node Version Command upgrade", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/version/upgrade", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "version", + "upgrade" + ] + }, + "description": "change version command\nAvailable values : upgrade, rollback" + }, + "response": [] + }, + { + "name": "Reboot Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/reboot", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "reboot" + ] + } + }, + "response": [] + }, + { + "name": "Retrieves HAL Hardware Info", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/hal/hw", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "hal", + "hw" + ] + } + }, + "response": [] + }, + { + "name": "Retrieves HAL USB Info", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}/hal/usb", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}", + "hal", + "usb" + ] + } + }, + "response": [] + }, + { + "name": "Delete Node", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 202\"] = responseCode.code === 202;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/iofog/{{node-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "iofog", + "{{node-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete User", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -4612,7 +5305,7 @@ ], "variable": [ { - "id": "8c5861f9-a3a9-4d32-8ec6-b3098b60d3ed", + "id": "0007cf5a-6d77-495e-9111-4455d1b92f66", "key": "host", "value": "localhost:51121", "type": "string" From 90a84a343e52ace2001bd33e616905c4447c101c Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 6 Nov 2018 15:05:21 +0300 Subject: [PATCH 26/91] EWC-317 postman QA registry (#322) --- src/cli/registry.js | 21 +- src/controllers/registry-controller.js | 2 +- src/services/registry-service.js | 7 +- ...Controller Testing.postman_collection.json | 293 +++++++++++++++++- 4 files changed, 309 insertions(+), 14 deletions(-) diff --git a/src/cli/registry.js b/src/cli/registry.js index 047e14ef5..f36a82ef5 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -11,15 +11,15 @@ * */ -const BaseCLIHandler = require('./base-cli-handler') -const constants = require('../helpers/constants') -const logger = require('../logger') -const CliDecorator = require('../decorators/cli-decorator') +const BaseCLIHandler = require('./base-cli-handler'); +const constants = require('../helpers/constants'); +const logger = require('../logger'); +const CliDecorator = require('../decorators/cli-decorator'); const RegistryService = require('../services/registry-service'); class Registry extends BaseCLIHandler { constructor() { - super() + super(); this.name = constants.CMD_REGISTRY this.commandDefinitions = [ @@ -32,7 +32,7 @@ class Registry extends BaseCLIHandler { { name: 'email', alias: 'e', type: String, description: 'Email address', group: [constants.CMD_ADD] }, { name: 'user-id', alias: 'i', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] }, { name: 'item-id', alias: 'd', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE] }, - ] + ]; this.commands = { [constants.CMD_ADD]: 'Add a new Registry.', [constants.CMD_REMOVE]: 'Delete a Registry.', @@ -64,8 +64,9 @@ class Registry extends BaseCLIHandler { async function _createRegistry(obj, user) { const registry = _createRegistryObject(obj); logger.info(JSON.stringify(registry)); - await RegistryService.createRegistry(registry, user); + const response = await RegistryService.createRegistry(registry, user); logger.info('Registry has been created successfully.'); + logger.info('Registry id: ' + response.id); } async function _getRegistries(obj, user) { @@ -75,7 +76,7 @@ async function _getRegistries(obj, user) { } async function _deleteRegistry(obj, user) { - await RegistryService.deleteRegistry({id: obj.itemId}, user, true) + await RegistryService.deleteRegistry({id: obj.itemId}, user, true); logger.info('Registry has been removed successfully.'); } @@ -101,8 +102,8 @@ function _createRegistryObject(cliData) { password: cliData.password, isPublic: cliData.public, email: cliData.email - } + }; return registryObj; } -module.exports = new Registry() \ No newline at end of file +module.exports = new Registry(); \ No newline at end of file diff --git a/src/controllers/registry-controller.js b/src/controllers/registry-controller.js index 840b45da2..ba94ed21b 100644 --- a/src/controllers/registry-controller.js +++ b/src/controllers/registry-controller.js @@ -18,7 +18,7 @@ const RegistryService = require('../services/registry-service'); const createRegistryEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); const registry = req.body; - await RegistryService.createRegistry(registry, user); + return await RegistryService.createRegistry(registry, user); }; const getRegistriesEndPoint = async function (req, user) { diff --git a/src/services/registry-service.js b/src/services/registry-service.js index eb0d12a84..074803f07 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -42,8 +42,11 @@ const createRegistry = async function (registry, user, transaction) { registryCreate = AppHelper.deleteUndefinedFields(registryCreate); - await RegistryManager.create(registryCreate, transaction) + const createdRegistry = await RegistryManager.create(registryCreate, transaction); await updateChangeTracking(user, transaction); + return { + id: createdRegistry.id + } }; const updateChangeTracking = async function (user, transaction) { @@ -52,7 +55,7 @@ const updateChangeTracking = async function (user, transaction) { const changeTrackingUpdates = { iofogUuid: fog.uuid, registries: true - } + }; await ChangeTrackingManager.update({iofogUuid: fog.uuid}, changeTrackingUpdates, transaction); } }; diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 841a805e5..f81b2f80b 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -5279,6 +5279,297 @@ "response": [] } ] + }, + { + "name": "Registries", + "item": [ + { + "name": "Create user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('userId') && data.firstName && data.lastName && data.email && data.hasOwnProperty('emailActivated');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"firstName\": \"John\",\n \"lastName\": \"Doe\",\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/signup", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "signup" + ] + } + }, + "response": [] + }, + { + "name": "Login", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.accessToken;", + "", + "", + "postman.setGlobalVariable(\"user-token\", data.accessToken);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"email\": \"user@domain.com\",\n \"password\": \"#Bugs4Fun\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/user/login", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "login" + ] + } + }, + "response": [] + }, + { + "name": "Create Registry", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "postman.setGlobalVariable(\"reg-id\", data.id);", + "" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"url\": \"string\",\n \"isPublic\": true,\n \"username\": \"string\",\n \"password\": \"string\",\n \"email\": \"string\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/registries", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "registries" + ] + } + }, + "response": [] + }, + { + "name": "Get Registries", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('registries');" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/registries", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "registries" + ] + } + }, + "response": [] + }, + { + "name": "Delete a Registry", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/registries/{{reg-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "registries", + "{{reg-id}}" + ] + } + }, + "response": [] + }, + { + "name": "Delete user", + "event": [ + { + "listen": "test", + "script": { + "id": "954febdd-1a16-4db0-bdff-bd13fc50a451", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/user/profile", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "user", + "profile" + ] + } + }, + "response": [] + } + ] } ], "event": [ @@ -5305,7 +5596,7 @@ ], "variable": [ { - "id": "0007cf5a-6d77-495e-9111-4455d1b92f66", + "id": "291501bd-8b27-45a8-9a93-e39a9f4146fa", "key": "host", "value": "localhost:51121", "type": "string" From de083f03b0628a97202e37f37a90efa97fb94ad3 Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Tue, 6 Nov 2018 15:46:13 +0200 Subject: [PATCH 27/91] fix cli image snapshot (#323) * fix cli image snapshot * fix --- src/cli/diagnostics.js | 6 +-- src/controllers/diagnostic-controller.js | 4 +- src/routes/diagnostics.js | 27 ++++++------- src/services/diagnostic-service.js | 50 ++++++++++++++++++------ 4 files changed, 55 insertions(+), 32 deletions(-) diff --git a/src/cli/diagnostics.js b/src/cli/diagnostics.js index 2640d70a2..434b54ddd 100644 --- a/src/cli/diagnostics.js +++ b/src/cli/diagnostics.js @@ -143,15 +143,15 @@ const _postMicroserviceStraceDataToFtp = async function (obj) { const _postMicroserviceImageSnapshotCreate = async function (obj) { logger.info(JSON.stringify(obj)); - await DiagnosticService.postMicroserviceImageSnapshotCreate(obj.microserviceId, obj, {}, true); + await DiagnosticService.postMicroserviceImageSnapshotCreate(obj.microserviceId, {}, true); logger.info('Microservice image snapshot has been created successfully'); }; const _getMicroserviceImageSnapshot = async function (obj) { logger.info(JSON.stringify(obj)); - await DiagnosticService.getMicroserviceImageSnapshot(obj.microserviceId, obj, {}, true); - logger.info('Microservice images snapshot has been downloaded successfully'); + const filePath = await DiagnosticService.getMicroserviceImageSnapshot(obj.microserviceId, {}, true); + logger.info('Microservice images path = ' + filePath); }; module.exports = new Diagnostics(); \ No newline at end of file diff --git a/src/controllers/diagnostic-controller.js b/src/controllers/diagnostic-controller.js index 2e70050fd..699a6c382 100644 --- a/src/controllers/diagnostic-controller.js +++ b/src/controllers/diagnostic-controller.js @@ -36,13 +36,13 @@ const postMicroserviceStraceDataToFtpEndPoint = async function (req, user) { const createMicroserviceImageSnapshotEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); logger.info("Microservice id: " + req.params.id); - return await DiagnosticService.postMicroserviceImageSnapshotCreate(req.params.id, req.body, user, false); + return await DiagnosticService.postMicroserviceImageSnapshotCreate(req.params.id, user, false); }; const getMicroserviceImageSnapshotEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); logger.info("Microservice id: " + req.params.id); - return await DiagnosticService.getMicroserviceImageSnapshot(req.params.id, req.body, user, false); + return await DiagnosticService.getMicroserviceImageSnapshot(req.params.id, user, false); }; module.exports = { diff --git a/src/routes/diagnostics.js b/src/routes/diagnostics.js index ebefa101c..372828670 100644 --- a/src/routes/diagnostics.js +++ b/src/routes/diagnostics.js @@ -69,21 +69,18 @@ module.exports = [ errorCodes ); const responseObject = await getMicroserviceImageSnapshotEndPoint(req); - - fs.exists(responseObject.body.filePath, function(exists){ - if (exists) { - res.writeHead(200, { - "Content-Length": responseObject.body['Content-Length'], - "Content-Type": responseObject.body['Content-Type'], - "Content-Disposition": "attachment; filename=" + responseObject.body.fileName - }); - fs.createReadStream(responseObject.body.filePath).pipe(res); - } else { - res.writeHead(400, {"Content-Type": "text/plain"}); - res.end("ERROR File does not exist"); - res.end(ErrorMessages.FILE_DOES_NOT_EXIST); - } - }); + if (responseObject.code !== successCode) { + res + .status(responseObject.code) + .send(responseObject.body) + } else { + res.writeHead(successCode, { + "Content-Length": responseObject.body['Content-Length'], + "Content-Type": responseObject.body['Content-Type'], + "Content-Disposition": "attachment; filename=" + responseObject.body.fileName + }); + fs.createReadStream(responseObject.body.filePath).pipe(res); + } } }, { diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index b9b20efb6..2b82a1a67 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -76,8 +76,20 @@ const postMicroserviceStraceDatatoFtp = async function (id, data, user, isCLI, t _deleteFile(filePath); }; -const postMicroserviceImageSnapshotCreate = async function (id, data, user, isCLI, transaction) { - const microservice = await MicroserviceService.getMicroserviceWithTransaction(id, user, isCLI, transaction); +const postMicroserviceImageSnapshotCreate = async function (microserviceUuid, user, isCLI, transaction) { + const where = isCLI ? + { + uuid: microserviceUuid + } + : + { + uuid: microserviceUuid, + updatedBy: user.id + }; + + + const microservice = await MicroserviceManager.findOneWithDependencies(where, {}, transaction); + if (microservice.iofogUuid === null) { throw new Errors.ValidationError(ErrorMessages.IMAGE_SNAPSHOT_WITHOUT_FOG); } @@ -92,31 +104,45 @@ const postMicroserviceImageSnapshotCreate = async function (id, data, user, isCL await ChangeTrackingManager.update({iofogUuid: microservice.iofogUuid}, {isImageSnapshot: true}, transaction); }; -const getMicroserviceImageSnapshot = async function (id, data, user, isCLI, transaction) { - const microservice = await MicroserviceService.getMicroserviceWithTransaction(id, user, isCLI, transaction); +const getMicroserviceImageSnapshot = async function (microserviceUuid, user, isCLI, transaction) { + const where = isCLI ? + { + uuid: microserviceUuid + } + : + { + uuid: microserviceUuid, + updatedBy: user.id + }; + const microservice = await MicroserviceManager.findOneWithDependencies(where, {}, transaction); if (microservice.iofogUuid === null) { throw new Errors.ValidationError(ErrorMessages.IMAGE_SNAPSHOT_WITHOUT_FOG); } const microserviceToUpdate = { - imageSnapshot: '' - }; + imageSnapshot: '' + }; - if (microservice.imageSnapshot){ + if (!microservice.imageSnapshot) { + throw new Errors.ValidationError(ErrorMessages.IMAGE_SNAPSHOT_NOT_AVAILABLE) + } + let _path = microservice.imageSnapshot; + logger.info('successfully deleted ' + microservice.imageSnapshot); + await MicroserviceManager.update({uuid: microservice.uuid}, microserviceToUpdate, transaction); + if (isCLI) { + return _path + } else { let mimetype = mime.lookup(microservice.imageSnapshot); - let _path = microservice.imageSnapshot; let stat = fs.statSync(_path); let fileSize = stat.size; - logger.info('successfully deleted ' + microservice.imageSnapshot); - await MicroserviceManager.update({uuid: microservice.uuid}, microserviceToUpdate, transaction); - return { 'Content-Length': fileSize, - 'Content-Type' : mimetype, + 'Content-Type': mimetype, fileName: _path.split(new RegExp('/'))[1], filePath: _path }; } + }; const _sendFileToFtp = async function (data, filePath) { From fae52b98199cc3e907ad176e2a3d2288a9459757 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Tue, 6 Nov 2018 16:54:40 +0300 Subject: [PATCH 28/91] cert in connector cli fix (#320) --- src/cli/connector.js | 2 +- src/schemas/connector.js | 4 ++-- src/services/connector-service.js | 3 ++- 3 files changed, 5 insertions(+), 4 deletions(-) diff --git a/src/cli/connector.js b/src/cli/connector.js index cdc00f0a1..c3feae7bb 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -125,7 +125,7 @@ function _createConnectorObject(cliData) { name: cliData.name, domain: cliData.domain, publicIp: cliData.publicIp, - certDir: cliData.certDir, + cert: cliData.cert, isSelfSignedCert: AppHelper.validateBooleanCliOptions(cliData.selfSignedEnable, cliData.selfSignedDisable), devMode: AppHelper.validateBooleanCliOptions(cliData.devModeOn, cliData.devModeOff) } diff --git a/src/schemas/connector.js b/src/schemas/connector.js index bc766c641..d23b105bb 100644 --- a/src/schemas/connector.js +++ b/src/schemas/connector.js @@ -18,7 +18,7 @@ const connectorCreate = { "name": {"type": "string", "minLength": 1}, "domain": {"type": "string", "minLength": 4}, "publicIp": {"type": "string", "minLength": 7}, - "certDir": {"type": "string"}, + "cert": {"type": "string"}, "isSelfSignedCert": {"type": "boolean"}, "devMode": {"type": "boolean"} }, @@ -33,7 +33,7 @@ const connectorUpdate = { "name": {"type": "string", "minLength": 1}, "domain": {"type": "string", "minLength": 4}, "publicIp": {"type": "string", "minLength": 7}, - "certDir": {"type": "string"}, + "cert": {"type": "string"}, "isSelfSignedCert": {"type": "boolean"}, "devMode": {"type": "boolean"} }, diff --git a/src/services/connector-service.js b/src/services/connector-service.js index 04bb3cb9c..d48eacb7b 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -24,6 +24,7 @@ const logger = require('../logger') const querystring = require('querystring') const Op = require('sequelize').Op; const Sequelize = require('sequelize'); +const fs = require('fs'); async function _createConnector(connectorData, transaction) { await Validator.validate(connectorData, Validator.schemas.connectorCreate) @@ -121,7 +122,7 @@ async function _makeRequest(connector, options, data) { }) if (connector.cert && connector.isSelfSignedCert === true) { - let ca = '-----BEGIN CERTIFICATE-----\n' + connector.cert + '\n' + '-----END CERTIFICATE-----'; + const ca = fs.readFileSync(connector.cert); options.ca = new Buffer(ca); } From a3841d2a3013f3178e72938d90ee2200784ca1fc Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Tue, 6 Nov 2018 16:56:37 +0300 Subject: [PATCH 29/91] get fog list params in query (#324) --- package.json | 3 +- src/controllers/iofog-controller.js | 8 +-- src/routes/iofog.js | 4 +- ...Controller Testing.postman_collection.json | 49 +++++++++++-------- 4 files changed, 38 insertions(+), 26 deletions(-) diff --git a/package.json b/package.json index 2d32ad068..f3ba2e25d 100644 --- a/package.json +++ b/package.json @@ -72,7 +72,8 @@ "umzug": "^2.1.0", "underscore": "^1.9.1", "winston": "^3.1.0", - "xss-clean": "^0.1.1" + "xss-clean": "^0.1.1", + "qs": "^6.5.2" }, "devDependencies": { "eslint": "^5.6.1" diff --git a/src/controllers/iofog-controller.js b/src/controllers/iofog-controller.js index 99832bc59..a037cbd15 100644 --- a/src/controllers/iofog-controller.js +++ b/src/controllers/iofog-controller.js @@ -14,6 +14,8 @@ const logger = require('../logger'); const AuthDecorator = require('../decorators/authorization-decorator'); const FogService = require('../services/iofog-service'); +const querystring = require('querystring'); +const qs = require('qs'); async function _createFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); @@ -43,9 +45,9 @@ async function _getFog(req, user) { } async function _getFogList(req, user) { - logger.info("Parameters:" + JSON.stringify(req.body)); - const filters = Array.from(req.body); - return await FogService.getFogListWithTransaction(filters, user, false) + logger.info("Parameters:" + JSON.stringify(req.query)); + const query = qs.parse(req.query) + return await FogService.getFogListWithTransaction(query.filters, user, false) } async function _generateProvisioningKey(req, user) { diff --git a/src/routes/iofog.js b/src/routes/iofog.js index 9f987cd3a..2853e97ed 100644 --- a/src/routes/iofog.js +++ b/src/routes/iofog.js @@ -17,7 +17,7 @@ const Errors = require('../helpers/errors'); module.exports = [ { - method: 'post', + method: 'get', path: '/api/v3/iofog-list', middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; @@ -154,7 +154,7 @@ module.exports = [ code: 404, errors: [Errors.NotFoundError] } - ] + ]; const generateFogProvisioningKey = ResponseDecorator.handleErrors(FogController.generateProvisioningKey, successCode, errCodes); const responseObject = await generateFogProvisioningKey(req); diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index f81b2f80b..05258cdf6 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1,12 +1,13 @@ { "info": { - "_postman_id": "0c412a3a-7328-4c9e-8919-d2836adccfa1", + "_postman_id": "b585aece-cb86-4f3b-93f3-12552c1c90c5", "name": "Controller Testing", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "User", + "description": null, "item": [ { "name": "Create user", @@ -509,6 +510,7 @@ }, { "name": "General", + "description": null, "item": [ { "name": "Status", @@ -631,6 +633,7 @@ }, { "name": "Agent", + "description": null, "item": [ { "name": "Create user", @@ -856,7 +859,6 @@ "method": "POST", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" } @@ -906,7 +908,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -954,7 +955,6 @@ "method": "PATCH", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1008,7 +1008,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1057,7 +1056,6 @@ "method": "PUT", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1108,7 +1106,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1159,7 +1156,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1211,7 +1207,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1262,7 +1257,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1310,7 +1304,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1361,7 +1354,6 @@ "method": "PUT", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1412,7 +1404,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1559,7 +1550,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1657,7 +1647,6 @@ "method": "DELETE", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1735,6 +1724,7 @@ }, { "name": "Flow", + "description": null, "item": [ { "name": "Create user", @@ -2121,6 +2111,7 @@ }, { "name": "Catalog", + "description": null, "item": [ { "name": "Create user", @@ -2516,6 +2507,7 @@ }, { "name": "Tunnel", + "description": null, "item": [ { "name": "Create user", @@ -2859,6 +2851,7 @@ }, { "name": "Microservices", + "description": null, "item": [ { "name": "Create user", @@ -3795,6 +3788,7 @@ }, { "name": "Diagnostics", + "description": null, "item": [ { "name": "Create user", @@ -4589,6 +4583,7 @@ }, { "name": "ioFog", + "description": null, "item": [ { "name": "Create user", @@ -4809,7 +4804,7 @@ } ], "request": { - "method": "POST", + "method": "GET", "header": [ { "key": "Content-Type", @@ -4817,16 +4812,15 @@ }, { "key": "Authorization", - "value": "{{user-token}}", - "type": "text" + "value": "{{user-token}}" } ], "body": { "mode": "raw", - "raw": "[\n {\n \"key\": \"uuid\",\n \"value\": \"{{node-id}}\",\n \"condition\": \"equals\"\n }\n]" + "raw": "" }, "url": { - "raw": "{{host}}/api/v3/iofog-list", + "raw": "{{host}}/api/v3/iofog-list?filters[0][key]=uuid&filters[0][value]={{node-id}}&filters[0][condition]=equals", "host": [ "{{host}}" ], @@ -4834,6 +4828,20 @@ "api", "v3", "iofog-list" + ], + "query": [ + { + "key": "filters[0][key]", + "value": "uuid" + }, + { + "key": "filters[0][value]", + "value": "{{node-id}}" + }, + { + "key": "filters[0][condition]", + "value": "equals" + } ] } }, @@ -5282,6 +5290,7 @@ }, { "name": "Registries", + "description": null, "item": [ { "name": "Create user", From efcd5703539cf0c1283e764d6004ac7f337b4614 Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Tue, 6 Nov 2018 16:20:13 +0200 Subject: [PATCH 30/91] small fix snapshot in windows os (#325) * fix cli image snapshot * fix * fix --- src/helpers/error-messages.js | 1 + src/services/diagnostic-service.js | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 6d6e3ab9f..1e82c7de2 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -48,6 +48,7 @@ module.exports = { INVALID_MICROSERVICE_USER: 'Invalid microservice user or UUID', ROUTE_NOT_FOUND: 'Route not found', IMAGE_SNAPSHOT_WITHOUT_FOG: 'Can not run image snapshot for microservice without ioFog.', + IMAGE_SNAPSHOT_NOT_AVAILABLE: 'Image snapshot is not available for this microservice.', FILE_DOES_NOT_EXIST: 'File does not exist.', RESTRICTED_PUBLISHER: "You are not allowed to add catalog item as 'Eclipse ioFog' publisher", REQUIRED_FOG_NODE: 'ioFog node is required.', diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 2b82a1a67..f3ac70836 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -123,7 +123,7 @@ const getMicroserviceImageSnapshot = async function (microserviceUuid, user, isC imageSnapshot: '' }; - if (!microservice.imageSnapshot) { + if (!microservice.imageSnapshot || microservice.imageSnapshot === 'get_image') { throw new Errors.ValidationError(ErrorMessages.IMAGE_SNAPSHOT_NOT_AVAILABLE) } let _path = microservice.imageSnapshot; From a05980f09a84115699c70b835eb35f24139a15ec Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 6 Nov 2018 18:09:33 +0300 Subject: [PATCH 31/91] fixed image snapshot endpoint in postman qa collection (#326) --- ...Controller Testing.postman_collection.json | 40 ++++++++----------- 1 file changed, 17 insertions(+), 23 deletions(-) diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 05258cdf6..a86724e23 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1,13 +1,12 @@ { "info": { - "_postman_id": "b585aece-cb86-4f3b-93f3-12552c1c90c5", + "_postman_id": "3f737064-1335-43ef-9b3c-f3f48558d42b", "name": "Controller Testing", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "User", - "description": null, "item": [ { "name": "Create user", @@ -510,7 +509,6 @@ }, { "name": "General", - "description": null, "item": [ { "name": "Status", @@ -633,7 +631,6 @@ }, { "name": "Agent", - "description": null, "item": [ { "name": "Create user", @@ -919,7 +916,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/config", @@ -1019,7 +1016,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/config/changes", @@ -1117,7 +1114,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/microservices", @@ -1167,7 +1164,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/microservices/abcedf", @@ -1218,7 +1215,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/registries", @@ -1268,7 +1265,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/tunnel", @@ -1315,7 +1312,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/strace", @@ -1415,7 +1412,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/version", @@ -1561,7 +1558,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/image-snapshot", @@ -1724,7 +1721,6 @@ }, { "name": "Flow", - "description": null, "item": [ { "name": "Create user", @@ -2111,7 +2107,6 @@ }, { "name": "Catalog", - "description": null, "item": [ { "name": "Create user", @@ -2507,7 +2502,6 @@ }, { "name": "Tunnel", - "description": null, "item": [ { "name": "Create user", @@ -2851,7 +2845,6 @@ }, { "name": "Microservices", - "description": null, "item": [ { "name": "Create user", @@ -3788,7 +3781,6 @@ }, { "name": "Diagnostics", - "description": null, "item": [ { "name": "Create user", @@ -4145,7 +4137,11 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "" + "tests[\"Status code is 500\"] = responseCode.code === 500;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Error message is valid\"] = data.name === 'ValidationError' && data.message === 'Image snapshot is not available for this microservice.';" ], "type": "text/javascript" } @@ -4169,7 +4165,7 @@ "raw": "" }, "url": { - "raw": "{{host}}/api/v3/microservices/{{ms-id}}/image-snapshotFIXIT", + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/image-snapshot", "host": [ "{{host}}" ], @@ -4178,7 +4174,7 @@ "v3", "microservices", "{{ms-id}}", - "image-snapshotFIXIT" + "image-snapshot" ] } }, @@ -4583,7 +4579,6 @@ }, { "name": "ioFog", - "description": null, "item": [ { "name": "Create user", @@ -5290,7 +5285,6 @@ }, { "name": "Registries", - "description": null, "item": [ { "name": "Create user", From 4c590f18608842815e2e82df13ac64e26679a69f Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 6 Nov 2018 20:29:53 +0300 Subject: [PATCH 32/91] EWC-300 registry patch endpoint & some fixes (#327) --- specs/swagger.yml | 33 +++++- src/cli/registry.js | 105 ++++++++++-------- src/controllers/registry-controller.js | 21 +++- src/helpers/error-messages.js | 1 + src/main.js | 21 ++-- src/routes/registries.js | 28 ++++- src/schemas/registry.js | 17 ++- src/services/registry-service.js | 44 +++++++- ...Controller Testing.postman_collection.json | 84 ++++++++++++-- 9 files changed, 278 insertions(+), 76 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 81591995f..6e75fb688 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -1867,7 +1867,38 @@ paths: '401': description: Not Authorized '404': - description: Invalid Node Id + description: Invalid Registry Id + '500': + description: Internal Server Error + patch: + tags: + - Registries + description: Updates a registry + operationId: updateRegistry + parameters: + - in: path + name: id + description: Registry id + required: true + type: string + - in: header + name: Authorization + description: User token + required: true + type: string + responses: + '204': + description: Updated + headers: + X-Timestamp: + type: number + description: FogController server timestamp + '400': + description: Bad Request + '401': + description: Not Authorized + '404': + description: Invalid Registry Id '500': description: Internal Server Error '/user/login': diff --git a/src/cli/registry.js b/src/cli/registry.js index f36a82ef5..31be587d4 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -16,43 +16,50 @@ const constants = require('../helpers/constants'); const logger = require('../logger'); const CliDecorator = require('../decorators/cli-decorator'); const RegistryService = require('../services/registry-service'); +const AppHelper = require('../helpers/app-helper'); class Registry extends BaseCLIHandler { constructor() { super(); - this.name = constants.CMD_REGISTRY + this.name = constants.CMD_REGISTRY; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: [constants.CMD] }, - { name: 'uri', alias: 'u', type: String, description: 'Registry URI', group: [constants.CMD_ADD] }, - { name: 'public', alias: 'b', type: Boolean, description: 'Set registry as public', group: [constants.CMD_ADD] }, - { name: 'private', alias: 'r', type: Boolean, description: 'Set registry as private', group: [constants.CMD_ADD] }, - { name: 'username', alias: 'l', type: String, description: 'Registry\'s user name', group: [constants.CMD_ADD] }, - { name: 'password', alias: 'p', type: String, description: 'Password', group: [constants.CMD_ADD] }, - { name: 'email', alias: 'e', type: String, description: 'Email address', group: [constants.CMD_ADD] }, - { name: 'user-id', alias: 'i', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] }, - { name: 'item-id', alias: 'd', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE] }, + {name: 'command', defaultOption: true, group: [constants.CMD]}, + {name: 'uri', alias: 'u', type: String, description: 'Registry URI', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'public', alias: 'b', type: Boolean, description: 'Set registry as public', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'private', alias: 'r', type: Boolean, description: 'Set registry as private', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'username', alias: 'l', type: String, description: 'Registry\'s user name', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'password', alias: 'p', type: String, description: 'Password', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'requires-certificate', alias: 'c', type: Boolean, description: 'Requires certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'certificate', alias: 'C', type: String, description: 'Certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'email', alias: 'e', type: String, description: 'Email address', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, + {name: 'user-id', alias: 'i', type: Number, description: 'User\'s id', group: [constants.CMD_ADD]}, + {name: 'item-id', alias: 'd', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE, constants.CMD_UPDATE]} ]; this.commands = { [constants.CMD_ADD]: 'Add a new Registry.', [constants.CMD_REMOVE]: 'Delete a Registry.', + [constants.CMD_UPDATE]: 'Update a Registry', [constants.CMD_LIST]: 'List all Registries.', } } async run(args) { - const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }) + const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv}) switch (registryCommand.command.command) { case constants.CMD_ADD: - await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true); - break; + await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true); + break; case constants.CMD_REMOVE: - await _executeCase(registryCommand, constants.CMD_REMOVE, _deleteRegistry, false); - break; + await _executeCase(registryCommand, constants.CMD_REMOVE, _deleteRegistry, false); + break; + case constants.CMD_UPDATE: + await _executeCase(registryCommand, constants.CMD_UPDATE, _updateRegistry, false); + break; case constants.CMD_LIST: - await _executeCase(registryCommand, constants.CMD_LIST, _getRegistries, false); - break; + await _executeCase(registryCommand, constants.CMD_LIST, _getRegistries, false); + break; case constants.CMD_HELP: default: return this.help([constants.CMD_LIST]) @@ -62,48 +69,56 @@ class Registry extends BaseCLIHandler { } async function _createRegistry(obj, user) { - const registry = _createRegistryObject(obj); - logger.info(JSON.stringify(registry)); - const response = await RegistryService.createRegistry(registry, user); - logger.info('Registry has been created successfully.'); - logger.info('Registry id: ' + response.id); + const registry = _createRegistryObject(obj); + logger.info(JSON.stringify(registry)); + const response = await RegistryService.createRegistry(registry, user); + logger.info('Registry has been created successfully.'); + logger.info('Registry id: ' + response.id); } async function _getRegistries(obj, user) { - const result = await RegistryService.findRegistries(user, true); - logger.info(JSON.stringify(result)); - logger.info('List of Registries has been received successfully.'); + const result = await RegistryService.findRegistries(user, true); + logger.info(JSON.stringify(result)); + logger.info('List of Registries has been received successfully.'); } async function _deleteRegistry(obj, user) { - await RegistryService.deleteRegistry({id: obj.itemId}, user, true); - logger.info('Registry has been removed successfully.'); + await RegistryService.deleteRegistry({id: obj.itemId}, user, true); + logger.info('Registry has been removed successfully.'); +} + +async function _updateRegistry (obj) { + const registry = _createRegistryObject(obj); + logger.info(JSON.stringify(registry)); + await RegistryService.updateRegistry(registry, obj.itemId, {}, true); + logger.info('Registry has been updated successfully.'); } async function _executeCase(commands, commandName, f, isUserRequired) { - try { - const obj = commands[commandName]; + try { + const obj = commands[commandName]; - if (isUserRequired) { - const decoratedFunction = CliDecorator.prepareUserById(f); - await decoratedFunction(obj); - } else { - await f(obj); - } - } catch (error) { - logger.error(error.message); + if (isUserRequired) { + const decoratedFunction = CliDecorator.prepareUserById(f); + await decoratedFunction(obj); + } else { + await f(obj); } + } catch (error) { + logger.error(error.message); + } } function _createRegistryObject(cliData) { - const registryObj = { - url: cliData.uri, - username: cliData.username, - password: cliData.password, - isPublic: cliData.public, - email: cliData.email - }; - return registryObj; + return { + url: cliData.uri, + username: cliData.username, + password: cliData.password, + isPublic: AppHelper.validateBooleanCliOptions(cliData.public, cliData.private), + email: cliData.email, + requiresCert: cliData.requiresCertificate, + certificate: cliData.certificate + }; } module.exports = new Registry(); \ No newline at end of file diff --git a/src/controllers/registry-controller.js b/src/controllers/registry-controller.js index ba94ed21b..3ff6c2971 100644 --- a/src/controllers/registry-controller.js +++ b/src/controllers/registry-controller.js @@ -27,13 +27,24 @@ const getRegistriesEndPoint = async function (req, user) { const deleteRegistryEndPoint = async function (req, user) { const deleteRegistry = { - id: parseInt(req.params.id) - } + id: parseInt(req.params.id) + }; return await RegistryService.deleteRegistry(deleteRegistry, user, false); }; +const updateRegistryEndPoint = async function (req, user) { + const registry = req.body; + const registryId = req.params.id; + + logger.info("Parameters:" + JSON.stringify(registry)); + logger.info("Registry id:" + JSON.stringify(registryId)); + + return await RegistryService.updateRegistry(registry, registryId, user, false) +}; + module.exports = { - createRegistryEndPoint: AuthDecorator.checkAuthToken(createRegistryEndPoint), - getRegistriesEndPoint: AuthDecorator.checkAuthToken(getRegistriesEndPoint), - deleteRegistryEndPoint: AuthDecorator.checkAuthToken(deleteRegistryEndPoint) + createRegistryEndPoint: AuthDecorator.checkAuthToken(createRegistryEndPoint), + getRegistriesEndPoint: AuthDecorator.checkAuthToken(getRegistriesEndPoint), + deleteRegistryEndPoint: AuthDecorator.checkAuthToken(deleteRegistryEndPoint), + updateRegistryEndPoint: AuthDecorator.checkAuthToken(updateRegistryEndPoint) }; \ No newline at end of file diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 1e82c7de2..f72a4ca18 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -58,6 +58,7 @@ module.exports = { STRACE_NOT_FOUND: 'Strace not found', INVALID_CONTENT_TYPE: 'Invalid content type', UPLOADED_FILE_NOT_FOUND: 'Uploaded image snapshot file not found', + REGISTRY_NOT_FOUND: 'Registry not found', CLI: { INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.', INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.', diff --git a/src/main.js b/src/main.js index b9a9e0cfd..95cd37789 100644 --- a/src/main.js +++ b/src/main.js @@ -34,7 +34,16 @@ function main() { daemon .on('starting', () => { - logger.silly('Starting iofog-controller...') + logger.silly('Starting iofog-controller...'); + + db.sequelize + .sync() + .then(db.migrate) + .then(db.seed) + .catch((err) => { + logger.silly('Unable to initialize the database.', err); + process.exit(1) + }); }) .on('stopping', () => { logger.silly('Stopping iofog-controller...') @@ -55,12 +64,4 @@ function main() { cli.run(daemon) } -db.sequelize - .sync() - .then(db.migrate) - .then(db.seed) - .then(main) - .catch((err) => { - logger.silly('Unable to initialize the database.', err) - process.exit(1) - }); \ No newline at end of file +main(); \ No newline at end of file diff --git a/src/routes/registries.js b/src/routes/registries.js index 55e749dc9..51973ffe1 100644 --- a/src/routes/registries.js +++ b/src/routes/registries.js @@ -86,4 +86,30 @@ module.exports = [ .send(responseObject.body) } }, -] + { + method: 'patch', + path: '/api/v3/registries/:id', + middleware: async (req, res) => { + const successCode = constants.HTTP_CODE_NO_CONTENT; + const errorCodes = [ + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError] + }, + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError] + }, + { + code: constants.HTTP_CODE_NOT_FOUND, + errors: [Errors.NotFoundError] + } + ]; + const updateRegistryEndPoint = ResponseDecorator.handleErrors(RegistryController.updateRegistryEndPoint, successCode, errorCodes); + const responseObject = await updateRegistryEndPoint(req); + res + .status(responseObject.code) + .send(responseObject.body) + } + } +]; diff --git a/src/schemas/registry.js b/src/schemas/registry.js index a69a2e982..de986a302 100644 --- a/src/schemas/registry.js +++ b/src/schemas/registry.js @@ -37,6 +37,21 @@ const registryDelete = { "additionalProperties": false }; +const registryUpdate = { + "id": "/registryUpdate", + "type": "object", + "properties": { + "url": {"type": "string", "minLength": 1}, + "isPublic": {"type": "boolean"}, + "username": {"type": "string", "minLength": 1}, + "password": {"type": "string"}, + "email": {"type": "string"}, + "requiresCert": {"type": "boolean"}, + "certificate": {"type": "string"} + }, + "additionalProperties": false +}; + module.exports = { - mainSchemas: [registryCreate, registryDelete] + mainSchemas: [registryCreate, registryDelete, registryUpdate] }; \ No newline at end of file diff --git a/src/services/registry-service.js b/src/services/registry-service.js index 074803f07..8d70ebd46 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -97,8 +97,50 @@ const deleteRegistry = async function (registryData, user, isCli, transaction) { await updateChangeTracking(user, transaction); }; +const updateRegistry = async function (registry, registryId, user, isCLI, transaction) { + await Validator.validate(registry, Validator.schemas.registryUpdate); + + if (registry.requiresCert && registry.certificate === undefined) { + throw new Errors.ValidationError(ErrorMessages.CERT_PROPERTY_REQUIRED); + } + + const existingRegistry = await RegistryManager.findOne({ + id: registryId + }, transaction); + if (!existingRegistry) { + throw new Errors.NotFoundError(ErrorMessages.REGISTRY_NOT_FOUND) + } + + let registryUpdate = { + url: registry.url, + username: registry.username, + password: registry.password, + isPublic: registry.isPublic, + userEmail: registry.email, + requiresCert: registry.requiresCert, + certificate: registry.certificate + }; + + registryUpdate = AppHelper.deleteUndefinedFields(registryUpdate); + + const where = isCLI ? + { + id: registryId + } + : + { + id: registryId, + userId: user.id + }; + + await RegistryManager.update(where, registryUpdate, transaction); + + await updateChangeTracking(user, transaction); +}; + module.exports = { findRegistries: TransactionDecorator.generateTransaction(findRegistries), createRegistry: TransactionDecorator.generateTransaction(createRegistry), - deleteRegistry: TransactionDecorator.generateTransaction(deleteRegistry) + deleteRegistry: TransactionDecorator.generateTransaction(deleteRegistry), + updateRegistry: TransactionDecorator.generateTransaction(updateRegistry) }; \ No newline at end of file diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index a86724e23..da25bb98c 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "3f737064-1335-43ef-9b3c-f3f48558d42b", + "_postman_id": "0c412a3a-7328-4c9e-8919-d2836adccfa1", "name": "Controller Testing", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, @@ -856,6 +856,7 @@ "method": "POST", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" } @@ -905,6 +906,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -916,7 +918,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/config", @@ -952,6 +954,7 @@ "method": "PATCH", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1005,6 +1008,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1016,7 +1020,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/config/changes", @@ -1053,6 +1057,7 @@ "method": "PUT", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1103,6 +1108,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1114,7 +1120,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/microservices", @@ -1153,6 +1159,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1164,7 +1171,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/microservices/abcedf", @@ -1204,6 +1211,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1215,7 +1223,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/registries", @@ -1254,6 +1262,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1265,7 +1274,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/tunnel", @@ -1301,6 +1310,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1312,7 +1322,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/strace", @@ -1351,6 +1361,7 @@ "method": "PUT", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1401,6 +1412,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1412,7 +1424,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/version", @@ -1547,6 +1559,7 @@ "method": "GET", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1558,7 +1571,7 @@ ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" }, "url": { "raw": "{{host}}/api/v3/agent/image-snapshot", @@ -1644,6 +1657,7 @@ "method": "DELETE", "header": [ { + "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -5416,7 +5430,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"url\": \"string\",\n \"isPublic\": true,\n \"username\": \"string\",\n \"password\": \"string\",\n \"email\": \"string\"\n}" + "raw": "{\n \"url\": \"string\",\n \"isPublic\": true,\n \"username\": \"string\",\n \"password\": \"string\",\n \"email\": \"string\",\n \"requiresCert\": false,\n \"certificate\": \"string\"\n}" }, "url": { "raw": "{{host}}/api/v3/registries", @@ -5432,6 +5446,52 @@ }, "response": [] }, + { + "name": "Update Registry", + "event": [ + { + "listen": "test", + "script": { + "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PATCH", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "type": "text", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"url\": \"string2\",\n \"isPublic\": true,\n \"username\": \"string3\",\n \"password\": \"string4\",\n \"email\": \"string5\",\n \"requiresCert\": true,\n \"certificate\": \"string6\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/registries/{{reg-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "registries", + "{{reg-id}}" + ] + } + }, + "response": [] + }, { "name": "Get Registries", "event": [ @@ -5599,7 +5659,7 @@ ], "variable": [ { - "id": "291501bd-8b27-45a8-9a93-e39a9f4146fa", + "id": "2fbdbf4f-879c-40bb-858a-82cb33c8a6e9", "key": "host", "value": "localhost:51121", "type": "string" From 23ac681d2ed524e70b3453dbfaa4972dea538551 Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Thu, 8 Nov 2018 12:54:21 +0300 Subject: [PATCH 33/91] Epankou/feature microservice removal ewc 306 (#312) * EWC-306 microservice removal * EWC-306 microservice removal * EWC-306 microservice removal * EWC-306 microservice removal * EWC-306 microservice removal * EWC-306 microservice removal --- README.md | 4 +- specs/swagger.yml | 4 +- src/cli/microservice.js | 8 +- src/enums/microservice-state.js | 9 ++ src/schemas/microservice.js | 4 +- .../managers/microservice-manager.js | 26 +++++ .../managers/microservice-status-manager.js | 25 +++++ .../20181001062956-create-microservice.js | 2 +- ...923-drop-need-update-col-microservices.js} | 0 ...croservice-status-add-missing-time-cols.js | 18 +++ ...81102163657-microservice-add-col-remove.js | 14 +++ src/sequelize/models/microservice.js | 14 ++- src/sequelize/models/microservicestatus.js | 13 ++- src/services/agent-service.js | 34 +++++- src/services/microservices-service.js | 103 +++++++++++------- 15 files changed, 218 insertions(+), 60 deletions(-) create mode 100644 src/enums/microservice-state.js create mode 100644 src/sequelize/managers/microservice-status-manager.js rename src/sequelize/migrations/{20181031094923-drop_need_update_col_microservices.js.js => 20181031094923-drop-need-update-col-microservices.js} (100%) create mode 100644 src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js create mode 100644 src/sequelize/migrations/20181102163657-microservice-add-col-remove.js diff --git a/README.md b/README.md index 1f4b885eb..b9ff96aad 100644 --- a/README.md +++ b/README.md @@ -530,7 +530,7 @@ $ iofog-controller catalog <*command*> <*options*>
"config": "string",
"catalogItemId": 0,
"flowId": 0,
- "ioFogNodeId": "string",
+ "iofogUuid": "string",
"rootHostAccess": true,
"logLimit": 0,
"volumeMappings": [
@@ -558,7 +558,7 @@ $ iofog-controller catalog <*command*> <*options*>
"name": "string",
"config": "string",
"rebuild": true,
- "ioFogNodeId": "string",
+ "iofogUuid": "string",
"rootHostAccess": true,
"logLimit": 0,
"volumeMappings": [
diff --git a/specs/swagger.yml b/specs/swagger.yml index 6e75fb688..47dd9b939 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -2907,7 +2907,7 @@ definitions: type: integer flowId: type: integer - ioFogNodeId: + iofogUuid: type: string rootHostAccess: type: boolean @@ -2934,7 +2934,7 @@ definitions: type: string rebuild: type: boolean - ioFogNodeId: + iofogUuid: type: string rootHostAccess: type: boolean diff --git a/src/cli/microservice.js b/src/cli/microservice.js index edabe1d2a..d33e3cce3 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -26,7 +26,7 @@ const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( config: "string", catalogItemId: 0, flowId: 0, - ioFogNodeId: "string", + iofogUuid: "string", rootHostAccess: true, logLimit: 0, volumeMappings: [ @@ -54,7 +54,7 @@ const JSON_SCHEMA_UPDATE = AppHelper.stringifyCliJsonSchema( name: "string", config: "string", rebuild: true, - ioFogNodeId: "string", + iofogUuid: "string", rootHostAccess: true, logLimit: 0, volumeMappings: [ @@ -370,7 +370,7 @@ const _updateMicroserviceObject = function (obj) { const microserviceObj = { name: obj.name, config: obj.config, - ioFogNodeId: obj.iofogId, + iofogUuid: obj.iofogId, rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), logLimit: obj.logLimit, rebuild: obj.rebuild @@ -389,7 +389,7 @@ const _createMicroserviceObject = function (obj) { config: obj.config, catalogItemId: parseInt(obj.catalogId), flowId: parseInt(obj.flowId), - ioFogNodeId: obj.iofogId, + iofogUuid: obj.iofogId, rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), logLimit: obj.logLimit, routes: obj.routes diff --git a/src/enums/microservice-state.js b/src/enums/microservice-state.js new file mode 100644 index 000000000..4661b0171 --- /dev/null +++ b/src/enums/microservice-state.js @@ -0,0 +1,9 @@ +const microserviceState = { + NOT_RUNNING: 'NOT_RUNNING', + RUNNING: 'RUNNING', + RESTARTING: 'RESTARTING', + STUCK_IN_RESTART: 'STUCK_IN_RESTART', +} + +module.exports = microserviceState; + diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 05de1f720..29a1e6239 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -9,7 +9,7 @@ const microserviceCreate = { "config": {"type": "string"}, "catalogItemId": {"type": "integer"}, "flowId": {"type": "integer"}, - "ioFogNodeId": {"type": "string"}, + "iofogUuid": {"type": "string"}, "rootHostAccess": {"type": "boolean"}, "logSize": {"type": "integer"}, "imageSnapshot": {"type": "string"}, @@ -36,7 +36,7 @@ const microserviceUpdate = { }, "config": {"type": "string"}, "rebuild": {"type": "boolean"}, - "ioFogNodeId": {"type": "string"}, + "iofogUuid": {"type": "string"}, "rootHostAccess": {"type": "boolean"}, "logSize": {"type": "integer", "minimum" : 0}, "volumeMappings": { diff --git a/src/sequelize/managers/microservice-manager.js b/src/sequelize/managers/microservice-manager.js index 4b07377af..186e8640b 100644 --- a/src/sequelize/managers/microservice-manager.js +++ b/src/sequelize/managers/microservice-manager.js @@ -24,6 +24,7 @@ const Flow = models.Flow; const User = models.User; const Routing = models.Routing; const Registry = models.Registry; +const MicroserviceStatus = models.MicroserviceStatus; class MicroserviceManager extends BaseManager { getEntity() { @@ -194,6 +195,31 @@ class MicroserviceManager extends BaseManager { }, {transaction: transaction}) } + findOneWithStatus(where, transaction) { + return Microservice.findOne({ + include: [ + { + model: MicroserviceStatus, + as: 'microserviceStatus', + required: true + } + ], + where: where + }, {transaction: transaction}) + } + + findAllWithStatuses(transaction) { + return Microservice.findAll({ + include: [ + { + model: MicroserviceStatus, + as: 'microserviceStatus', + required: true + } + ] + }, {transaction: transaction}) + } + findMicroserviceOnGet(where, transaction) { return Microservice.findOne({ include: [ diff --git a/src/sequelize/managers/microservice-status-manager.js b/src/sequelize/managers/microservice-status-manager.js new file mode 100644 index 000000000..77ad85df4 --- /dev/null +++ b/src/sequelize/managers/microservice-status-manager.js @@ -0,0 +1,25 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const BaseManager = require('../managers/base-manager') +const models = require('./../models'); +const MicroserviceStatus = models.MicroserviceStatus; + +class MicroserviceStatusManager extends BaseManager { + getEntity() { + return MicroserviceStatus; + } +} + +const instance = new MicroserviceStatusManager(); +module.exports = instance; \ No newline at end of file diff --git a/src/sequelize/migrations/20181001062956-create-microservice.js b/src/sequelize/migrations/20181001062956-create-microservice.js index a81ba6043..0d6117b37 100644 --- a/src/sequelize/migrations/20181001062956-create-microservice.js +++ b/src/sequelize/migrations/20181001062956-create-microservice.js @@ -44,7 +44,7 @@ module.exports = { type: Sequelize.TEXT, field: 'image_snapshot' }, - deleteWithCleanUp: { + deleteWithCleanup: { type: Sequelize.BOOLEAN, field: 'delete_with_cleanup' }, diff --git a/src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js b/src/sequelize/migrations/20181031094923-drop-need-update-col-microservices.js similarity index 100% rename from src/sequelize/migrations/20181031094923-drop_need_update_col_microservices.js.js rename to src/sequelize/migrations/20181031094923-drop-need-update-col-microservices.js diff --git a/src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js b/src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js new file mode 100644 index 000000000..0844e5fe6 --- /dev/null +++ b/src/sequelize/migrations/20181102105758-microservice-status-add-missing-time-cols.js @@ -0,0 +1,18 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.addColumn('MicroserviceStatuses', + 'operating_duration', + Sequelize.BIGINT + ) + .then(() => queryInterface.addColumn('MicroserviceStatuses', + 'start_time', + Sequelize.BIGINT)); + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('MicroserviceStatuses', 'operating_duration') + .then(() => queryInterface.removeColumn('MicroserviceStatuses', 'start_time')); + } +}; diff --git a/src/sequelize/migrations/20181102163657-microservice-add-col-remove.js b/src/sequelize/migrations/20181102163657-microservice-add-col-remove.js new file mode 100644 index 000000000..6138b1178 --- /dev/null +++ b/src/sequelize/migrations/20181102163657-microservice-add-col-remove.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.addColumn('Microservices', + 'delete', + Sequelize.BOOLEAN + ) + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('Microservices', 'delete') + } +}; diff --git a/src/sequelize/models/microservice.js b/src/sequelize/models/microservice.js index df5d29245..5e64cb234 100644 --- a/src/sequelize/models/microservice.js +++ b/src/sequelize/models/microservice.js @@ -46,7 +46,12 @@ module.exports = (sequelize, DataTypes) => { field: 'image_snapshot', defaultValue: "" }, - deleteWithCleanUp: { + delete: { + type: DataTypes.BOOLEAN, + field: 'delete', + defaultValue: false + }, + deleteWithCleanup: { type: DataTypes.BOOLEAN, field: 'delete_with_cleanup', defaultValue: false @@ -112,7 +117,12 @@ module.exports = (sequelize, DataTypes) => { Microservice.hasMany(models.Routing, { foreignKey: 'source_microservice_uuid', as: 'routes' - }) + }); + + Microservice.hasOne(models.MicroserviceStatus, { + foreignKey: 'microservice_uuid', + as: 'microserviceStatus' + }); }; return Microservice; }; \ No newline at end of file diff --git a/src/sequelize/models/microservicestatus.js b/src/sequelize/models/microservicestatus.js index 5db6d080a..c886603a3 100644 --- a/src/sequelize/models/microservicestatus.js +++ b/src/sequelize/models/microservicestatus.js @@ -10,8 +10,19 @@ module.exports = (sequelize, DataTypes) => { }, status: { type: DataTypes.TEXT, + defaultValue: 'NOT_RUNNING', field: 'status' }, + operatingDuration: { + type: DataTypes.BIGINT, + defaultValue: 0, + field: 'operating_duration' + }, + startTime: { + type: DataTypes.BIGINT, + defaultValue: 0, + field: 'start_time' + }, cpuUsage: { type: DataTypes.FLOAT, defaultValue: 0.000, @@ -24,6 +35,7 @@ module.exports = (sequelize, DataTypes) => { }, containerId: { type: DataTypes.TEXT, + defaultValue: '', field: 'container_id' } }, { @@ -32,7 +44,6 @@ module.exports = (sequelize, DataTypes) => { underscored: true }); MicroserviceStatus.associate = function (models) { - MicroserviceStatus.belongsTo(models.Microservice, { foreignKey: { name: 'microserviceUuid', diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 48ff590b7..ccc679ba3 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -21,6 +21,7 @@ const ChangeTrackingManager = require('../sequelize/managers/change-tracking-man const FogVersionCommandManager = require('../sequelize/managers/iofog-version-command-manager'); const StraceManager = require('../sequelize/managers/strace-manager'); const RegistryManager = require('../sequelize/managers/registry-manager'); +const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager') const Validator = require('../schemas'); const Errors = require('../helpers/errors'); const AppHelper = require('../helpers/app-helper'); @@ -174,7 +175,7 @@ const getAgentConfigChanges = async function (fog, transaction) { const updateAgentStatus = async function (agentStatus, fog, transaction) { await Validator.validate(agentStatus, Validator.schemas.updateAgentStatus); - let update = { + let fogStatus = { daemonStatus: agentStatus.daemonStatus, daemonOperatingDuration: agentStatus.daemonOperatingDuration, daemonLastStart: agentStatus.daemonLastStart, @@ -184,7 +185,6 @@ const updateAgentStatus = async function (agentStatus, fog, transaction) { memoryViolation: agentStatus.memoryViolation, diskViolation: agentStatus.diskViolation, cpuViolation: agentStatus.cpuViolation, - microserviceStatus: agentStatus.microserviceStatus, repositoryCount: agentStatus.repositoryCount, repositoryStatus: agentStatus.repositoryStatus, systemTime: agentStatus.systemTime, @@ -199,11 +199,34 @@ const updateAgentStatus = async function (agentStatus, fog, transaction) { isReadyToUpgrade: agentStatus.isReadyToUpgrade, isReadyToRollback: agentStatus.isReadyToRollback }; - update = AppHelper.deleteUndefinedFields(update); + + fogStatus = AppHelper.deleteUndefinedFields(fogStatus); await FogManager.update({ uuid: fog.uuid - }, update, transaction); + }, fogStatus, transaction); + + await _updateMicroserviceStatuses(JSON.parse(agentStatus.microserviceStatus), transaction); + await MicroserviceService.deleteNotRunningMicroservices(transaction); +}; + + +const _updateMicroserviceStatuses = async function (microserviceStatus, transaction) { + for (status of microserviceStatus) { + let microserviceStatus = { + containerId: status.containerId, + status: status.status, + startTime: status.startTime, + operatingDuration: status.operatingDuration, + cpuUsage: status.cpuUsage, + memoryUsage: status.memoryUsage + }; + microserviceStatus = AppHelper.deleteUndefinedFields(microserviceStatus); + + await MicroserviceStatusManager.update({ + microserviceUuid: status.id + }, microserviceStatus, transaction); + } }; const getAgentMicroservices = async function (fog, transaction) { @@ -230,7 +253,8 @@ const getAgentMicroservices = async function (fog, transaction) { portMappings: microservice.ports, volumeMappings: microservice.volumeMappings, imageSnapshot: microservice.imageSnapshot, - deleteWithCleanUp: microservice.deleteWithCleanUp, + delete: microservice.delete, + deleteWithCleanup: microservice.deleteWithCleanup, routes: routes }; diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index ab94b91ee..17cabb45c 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -13,7 +13,9 @@ const TransactionDecorator = require('../decorators/transaction-decorator'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); +const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager'); const MicroservicePortManager = require('../sequelize/managers/microservice-port-manager'); +const MicroserviceStates = require('../enums/microservice-state'); const VolumeMappingManager = require('../sequelize/managers/volume-mapping-manager'); const ConnectorManager = require('../sequelize/managers/connector-manager'); const ConnectorPortManager = require('../sequelize/managers/connector-port-manager'); @@ -34,7 +36,7 @@ const _listMicroservices = async function (flowId, user, isCLI, transaction) { if (!isCLI) { await FlowService.getFlow(flowId, user, isCLI, transaction); } - const where = isCLI ? {} : {flowId: flowId}; + const where = isCLI ? {delete: false} : {flowId: flowId, delete: false}; const microservices = await MicroserviceManager.findAllExcludeFields(where, transaction); return { @@ -48,7 +50,7 @@ const _getMicroservice = async function (microserviceUuid, user, isCLI, transact } const microservice = await MicroserviceManager.findOneExcludeFields({ - uuid: microserviceUuid + uuid: microserviceUuid, delete: false }, transaction); if (!microservice) { @@ -75,10 +77,12 @@ const _createMicroserviceOnFog = async function (microserviceData, user, isCLI, await _createRoutes(microserviceData.routes, microservice.uuid, user, transaction); } - if (microserviceData.ioFogNodeId) { - await _updateChangeTracking(false, microservice.uuid, microserviceData.ioFogNodeId, user, isCLI, transaction); + if (microserviceData.iofogUuid) { + await _updateChangeTracking(microserviceData.iofogUuid, transaction); } + await _createMicroserviceStatus(microservice.uuid, transaction); + return { uuid: microservice.uuid } @@ -92,7 +96,7 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans config: microserviceData.config, catalogItemId: microserviceData.catalogItemId, flowId: microserviceData.flowId, - iofogUuid: microserviceData.ioFogNodeId, + iofogUuid: microserviceData.iofogUuid, rootHostAccess: microserviceData.rootHostAccess, logSize: microserviceData.logLimit, updatedBy: user.id @@ -114,17 +118,10 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans return await MicroserviceManager.create(newMicroservice, transaction); }; -const _createMicroservicePorts = async function (ports, microserviceUuid, transaction) { - const microservicePortToCreate = { - portInternal: ports.internal, - portExternal: ports.external, - publicMode: ports.publicMode, - microserviceUuid: microserviceUuid - }; - - const microservicePortDataCreate = AppHelper.deleteUndefinedFields(microservicePortToCreate); - - await MicroservicePortManager.create(microservicePortDataCreate, transaction); +const _createMicroserviceStatus = function (uuid, transaction) { + return MicroserviceStatusManager.create({ + microserviceUuid: uuid + }, transaction); }; const _createVolumeMappings = async function (volumeMappings, microserviceUuid, transaction) { @@ -149,7 +146,7 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, name: microserviceData.name, config: microserviceData.config, rebuild: microserviceData.rebuild, - iofogUuid: microserviceData.ioFogNodeId, + iofogUuid: microserviceData.iofogUuid, rootHostAccess: microserviceData.rootHostAccess, logSize: microserviceData.logLimit, volumeMappings: microserviceData.volumeMappings, @@ -180,13 +177,13 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, await _updateVolumeMappings(microserviceDataUpdate.volumeMappings, microserviceUuid, transaction); } - if (microserviceDataUpdate.ioFogNodeId) { + if (microserviceDataUpdate.iofogUuid) { await _deleteRoutes(microserviceData.routes, microserviceUuid, transaction); await _createRoutes(microserviceData.routes, microserviceUuid, user, transaction); - await _updateChangeTracking(false, microserviceUuid, microserviceDataUpdate.ioFogNodeId, user, isCLI, transaction) + await _updateChangeTracking(microserviceDataUpdate.iofogUuid, transaction) } - await _updateChangeTracking(microserviceData.config ? true : false, microserviceUuid, microservice.ioFogNodeId, user, isCLI, transaction); + await _updateChangeTracking(microservice.iofogUuid, transaction); }; const _updateVolumeMappings = async function (volumeMappings, microserviceUuid, transaction) { @@ -197,42 +194,65 @@ const _updateVolumeMappings = async function (volumeMappings, microserviceUuid, } }; -const _updateChangeTracking = async function (configUpdated, microserviceUuid, fogNodeUuid, user, isCLI, transaction) { +const _updateChangeTracking = async function (iofogUuid, transaction) { const trackingData = { containerList: true, - containerConfig: configUpdated, - iofogUuid: fogNodeUuid + containerConfig: true, + routing: true }; - await ChangeTrackingManager.update({iofogUuid: fogNodeUuid}, trackingData, transaction); + await ChangeTrackingManager.update({iofogUuid: iofogUuid}, trackingData, transaction); }; const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, user, isCLI, transaction) { - if (deleteWithCleanUp) { - return await MicroserviceManager.update({ + + const where = isCLI + ? + { + uuid: microserviceUuid, + updatedBy: user.id + } + : + { + uuid: microserviceUuid + }; + + + const microservice = await MicroserviceManager.findOneWithStatus(where, transaction); + + if (microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) { + const affectedRows = await MicroserviceManager.delete({ + uuid: microserviceUuid + }, transaction); + if (affectedRows === 0) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); + } + } else { + await MicroserviceManager.update({ uuid: microserviceUuid }, { - deleteWithCleanUp: deleteWithCleanUp + delete: true, + deleteWithCleanUp: !!deleteWithCleanUp }, transaction); } - const microservice = await MicroserviceManager.findOne({ - uuid: microserviceUuid, - updatedBy: user.id - }, transaction); - - const affectedRows = await MicroserviceManager.delete({ - uuid: microserviceUuid - }, transaction); - if (affectedRows === 0) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); - } - - await _updateChangeTracking(false, microserviceUuid, microservice.ioFogNodeId, user, isCLI, transaction) + await _updateChangeTracking(microservice.iofogUuid, transaction) }; +const _deleteNotRunningMicroservices = async function (transaction) { + const microservices = await MicroserviceManager.findAllWithStatuses(transaction); + microservices + .filter(microservice => !!microservice.delete) + .filter(microservice => microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) + .forEach(microservice => { + MicroserviceManager.delete({ + uuid: microservice.uuid + }, transaction); + }); +} + const _checkForDuplicateName = async function (name, item, userId, transaction) { if (name) { const where = item.id @@ -811,5 +831,6 @@ module.exports = { getMicroservicePortMappingListWithTransaction: TransactionDecorator.generateTransaction(_getPortMappingList), deletePortMappingWithTransaction: TransactionDecorator.generateTransaction(_deletePortMapping), getPhysicalConections: getPhysicalConections, - getListMicroservices: _listMicroservices + listMicroservices: _listMicroservices, + deleteNotRunningMicroservices: _deleteNotRunningMicroservices }; From 6b197667eea40561f963a3bcfe0293d472919cff Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Thu, 8 Nov 2018 13:58:56 +0300 Subject: [PATCH 34/91] change tracking refactoring and renaming ewc 262 (#317) * renaming and refactoring ChangeTrackingService was added containerConfig -> microserviceConfig containerLIst -> microserviceList * cleanup * get fog list params in query --- ...king-container-to-microservice-renaming.js | 17 ++++ src/sequelize/models/changetracking.js | 21 ++++- src/services/agent-service.js | 29 +----- src/services/change-tracking-service.js | 91 +++++++++++++++++++ src/services/connector-service.js | 8 +- src/services/diagnostic-service.js | 10 +- src/services/flow-service.js | 32 ++++--- src/services/iofog-service.js | 49 ++++------ src/services/microservices-service.js | 70 ++++---------- src/services/registry-service.js | 8 +- src/services/tunnel-service.js | 14 +-- ...Controller Testing.postman_collection.json | 26 +++--- 12 files changed, 206 insertions(+), 169 deletions(-) create mode 100644 src/sequelize/migrations/20181105120036-change-tracking-container-to-microservice-renaming.js create mode 100644 src/services/change-tracking-service.js diff --git a/src/sequelize/migrations/20181105120036-change-tracking-container-to-microservice-renaming.js b/src/sequelize/migrations/20181105120036-change-tracking-container-to-microservice-renaming.js new file mode 100644 index 000000000..346a7128d --- /dev/null +++ b/src/sequelize/migrations/20181105120036-change-tracking-container-to-microservice-renaming.js @@ -0,0 +1,17 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.renameColumn('ChangeTrackings', 'container_config', 'microservice_config') + .then(() => { + return queryInterface.renameColumn('ChangeTrackings', 'container_list', 'microservice_list') + }) + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.renameColumn('ChangeTrackings', 'microservice_config', 'container_config') + .then(() => { + return queryInterface.renameColumn('ChangeTrackings', 'microservice_list', 'container_list') + }) + } +}; diff --git a/src/sequelize/models/changetracking.js b/src/sequelize/models/changetracking.js index 9f8685a11..23034e264 100644 --- a/src/sequelize/models/changetracking.js +++ b/src/sequelize/models/changetracking.js @@ -1,3 +1,16 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + 'use strict'; module.exports = (sequelize, DataTypes) => { const ChangeTracking = sequelize.define('ChangeTracking', { @@ -8,9 +21,9 @@ module.exports = (sequelize, DataTypes) => { allowNull: false, field: 'id' }, - containerConfig: { + microserviceConfig: { type: DataTypes.BOOLEAN, - field: 'container_config', + field: 'microservice_config', defaultValue: false }, reboot: { @@ -28,9 +41,9 @@ module.exports = (sequelize, DataTypes) => { field: 'version', defaultValue: false }, - containerList: { + microserviceList: { type: DataTypes.BOOLEAN, - field: 'container_list', + field: 'microservice_list', defaultValue: false }, config: { diff --git a/src/services/agent-service.js b/src/services/agent-service.js index ccc679ba3..557787a21 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -17,7 +17,7 @@ const FogProvisionKeyManager = require('../sequelize/managers/iofog-provision-ke const FogTypeManager = require('../sequelize/managers/iofog-type-manager'); const FogManager = require('../sequelize/managers/iofog-manager'); const FogAccessTokenService = require('../services/iofog-access-token-service'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); +const ChangeTrackingService = require('./change-tracking-service'); const FogVersionCommandManager = require('../sequelize/managers/iofog-version-command-manager'); const StraceManager = require('../sequelize/managers/strace-manager'); const RegistryManager = require('../sequelize/managers/registry-manager'); @@ -131,39 +131,20 @@ const updateAgentConfig = async function (updateData, fog, transaction) { const getAgentConfigChanges = async function (fog, transaction) { - const changeTracking = await ChangeTrackingManager.findOne({ - iofogUuid: fog.uuid - }, transaction); + const changeTracking = await ChangeTrackingService.getByFogId(fog.uuid, transaction); if (!changeTracking) { throw new Errors.NotFoundError(ErrorMessages.INVALID_NODE_ID) } - const cleanTracking = { - config: false, - version: false, - reboot: false, - deleteNode: false, - containerList: false, - containerConfig: false, - routing: false, - registries: false, - tunnel: false, - diagnostics: false, - isImageSnapshot: false - }; - - await ChangeTrackingManager.update({ - iofogUuid: fog.uuid - }, cleanTracking, transaction); - + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.clean, transaction); return { config: changeTracking.config, version: changeTracking.version, reboot: changeTracking.reboot, deleteNode: changeTracking.deleteNode, - microserviceList: changeTracking.containerList, - microserviceConfig: changeTracking.containerConfig, + microserviceList: changeTracking.microserviceList, + microserviceConfig: changeTracking.microserviceConfig, routing: changeTracking.routing, registries: changeTracking.registries, tunnel: changeTracking.tunnel, diff --git a/src/services/change-tracking-service.js b/src/services/change-tracking-service.js new file mode 100644 index 000000000..635ab9e49 --- /dev/null +++ b/src/services/change-tracking-service.js @@ -0,0 +1,91 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); + +const events = Object.freeze({ + clean: { + config: false, + version: false, + reboot: false, + deleteNode: false, + microserviceList: false, + microserviceConfig: false, + routing: false, + registries: false, + tunnel: false, + diagnostics: false, + isImageSnapshot: false + }, + diagnostics: { + diagnostics: true + }, + imageSnapshot: { + isImageSnapshot: true + }, + microserviceFull: { + microserviceConfig: true, + microserviceList: true, + routing: true + }, + microserviceCommon: { + microserviceConfig: true, + microserviceList: true + }, + microserviceList: { + microserviceList: true + }, + microserviceConfig: { + microserviceConfig: true + }, + microserviceRouting: { + routing: true + }, + version: { + version: true + }, + reboot: { + reboot: true + }, + deleteNode: { + deleteNode: true + }, + registries: { + registries: true + }, + tunnel: { + tunnel: true + }, + config: { + config: true + } +}); + +async function update(fogId, data, transaction) { + await ChangeTrackingManager.update({iofogUuid: fogId}, data, transaction); +} + +async function create(fogId, transaction) { + await ChangeTrackingManager.create({iofogUuid: fogId}, transaction); +} + +async function getByFogId(fogId, transaction) { + return await ChangeTrackingManager.findOne({iofogUuid: fogId}, transaction); +} + +module.exports = { + events: events, + create: create, + update: update, + getByFogId: getByFogId +}; \ No newline at end of file diff --git a/src/services/connector-service.js b/src/services/connector-service.js index d48eacb7b..82b85aac6 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -114,9 +114,9 @@ async function _makeRequest(connector, options, data) { let responseObj = JSON.parse(output); console.log(responseObj); if (responseObj.errormessage) { - reject(new Error(responseObj.errormessage)); + return reject(new Error(responseObj.errormessage)); } else { - resolve(responseObj); + return resolve(responseObj); } }); }) @@ -129,9 +129,9 @@ async function _makeRequest(connector, options, data) { httpreq.on('error', function(err) { console.log(err); if (err instanceof Error) - reject(new Error(err.message)); + return reject(new Error(err.message)); else - reject(new Error(JSON.stringify(err))); + return reject(new Error(JSON.stringify(err))); }); httpreq.write(data); diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index f3ac70836..9f72706a9 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -18,7 +18,7 @@ const ErrorMessages = require('../helpers/error-messages'); const validator = require('../schemas/index'); const MicroserviceService = require('../services/microservices-service'); const StraceDiagnosticManager = require('../sequelize/managers/strace-diagnostics-manager'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); +const ChangeTrackingService = require('./change-tracking-service'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); const config = require('../config'); const fs = require('fs'); @@ -41,7 +41,7 @@ const changeMicroserviceStraceState = async function (id, data, user, isCLI, tra }; await StraceDiagnosticManager.updateOrCreate({microserviceUuid: id}, straceObj, transaction); - await ChangeTrackingManager.update({iofogUuid: microservice.iofogUuid}, {diagnostics: true}, transaction) + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.diagnostics, transaction) }; const getMicroserviceStraceData = async function (id, data, user, isCLI, transaction) { @@ -96,12 +96,8 @@ const postMicroserviceImageSnapshotCreate = async function (microserviceUuid, us let imageSnapshot = 'get_image'; - const microserviceToUpdate = { - imageSnapshot: imageSnapshot - }; - await MicroserviceManager.update({uuid: microservice.uuid}, microserviceToUpdate, transaction); - await ChangeTrackingManager.update({iofogUuid: microservice.iofogUuid}, {isImageSnapshot: true}, transaction); + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.imageSnapshot, transaction); }; const getMicroserviceImageSnapshot = async function (microserviceUuid, user, isCLI, transaction) { diff --git a/src/services/flow-service.js b/src/services/flow-service.js index 53612fccd..d1f2458eb 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -17,7 +17,7 @@ const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Validation = require('../schemas'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager') +const ChangeTrackingService = require('./change-tracking-service'); const _createFlow = async function (flowData, user, isCLI, transaction) { await Validation.validate(flowData, Validation.schemas.flowCreate); @@ -47,13 +47,28 @@ const _deleteFlow = async function (flowId, user, isCLI, transaction) { }; const where = AppHelper.deleteUndefinedFields(whereObj); + await _updateChangeTrackingsByFlowId(flowId, transaction) + const affectedRows = await FlowManager.delete(where, transaction); if (affectedRows === 0) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FLOW_ID, flowId)); } + }; +async function _updateChangeTrackingsByFlowId(flowId, transaction) { + const flowWithMicroservices = await FlowManager.findFlowMicroservices({id: flowId}, transaction); + const onlyUnique = (value, index, self) => self.indexOf(value) === index; + const iofogUuids = flowWithMicroservices.microservices + .map(obj => obj.iofogUuid) + .filter(onlyUnique) + .filter(val => val !== null); + for (let iofogUuid of iofogUuids) { + await ChangeTrackingService.update(iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); + } +} + const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) { await Validation.validate(flowData, Validation.schemas.flowUpdate); @@ -81,20 +96,7 @@ const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) await FlowManager.update(where, updateFlowData, transaction); if (oldFlow.isActivated !== flowData.isActivated) { - const flowWithMicroservices = await FlowManager.findFlowMicroservices({id: flowId}, transaction); - const onlyUnique = (value, index, self) => self.indexOf(value) === index; - const iofogUuids = flowWithMicroservices.microservices - .map(obj => obj.iofogUuid) - .filter(onlyUnique) - .filter(val => val !== null); - for (let iofogUuid of iofogUuids) { - const updateChangeTrackingData = { - containerConfig: true, - containerList: true, - routing: true - }; - await ChangeTrackingManager.update({iofogUuid: iofogUuid}, updateChangeTrackingData, transaction); - } + await _updateChangeTrackingsByFlowId(flowId, transaction); } }; diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 57d7b939b..eb5548f58 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -16,7 +16,7 @@ const AppHelper = require('../helpers/app-helper'); const FogManager = require('../sequelize/managers/iofog-manager'); const FogProvisionKeyManager = require('../sequelize/managers/iofog-provision-key-manager'); const FogVersionCommandManager = require('../sequelize/managers/iofog-version-command-manager'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); +const ChangeTrackingService = require('./change-tracking-service'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); const Validator = require('../schemas'); @@ -61,7 +61,7 @@ async function _createFog(fogData, user, isCli, transaction) { uuid: fog.uuid }; - await ChangeTrackingManager.create({iofogUuid: fog.uuid}, transaction); + await ChangeTrackingService.create(fog.uuid, transaction); //TODO: proccess watchdog flag @@ -104,13 +104,7 @@ async function _createFog(fogData, user, isCli, transaction) { await MicroserviceManager.create(bluetoothMicroserviceData, transaction); } - const changeTrackingUpdates = { - iofogUuid: fogData.uuid, - config: true, - containerList: true - }; - - await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, changeTrackingUpdates, transaction); + await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.microserviceCommon, transaction) return res } @@ -151,8 +145,11 @@ async function _updateFog(fogData, user, isCli, transaction) { if (!oldFog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } + await FogManager.update(queryFogData, updateFogData, transaction); + await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.config, transaction); + let msChanged = false; //TODO: refactor. to function if (oldFog.bluetoothEnabled === true && fogData.bluetoothEnabled === false) { const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); @@ -162,6 +159,7 @@ async function _updateFog(fogData, user, isCli, transaction) { }; await MicroserviceManager.delete(deleteBluetoothMicroserviceData, transaction) + msChanged = true; } //TODO: refactor. to function @@ -181,6 +179,7 @@ async function _updateFog(fogData, user, isCli, transaction) { }; await MicroserviceManager.create(bluetoothMicroserviceData, transaction); + msChanged = true; } //TODO: refactor. to function @@ -192,6 +191,7 @@ async function _updateFog(fogData, user, isCli, transaction) { }; await MicroserviceManager.delete(deleteHalMicroserviceData, transaction) + msChanged = true; } //TODO: refactor. to function @@ -211,16 +211,12 @@ async function _updateFog(fogData, user, isCli, transaction) { }; await MicroserviceManager.create(halMicroserviceData, transaction); + msChanged = true; } - //TODO: process watchdog - const changeTrackingUpdates = { - iofogUuid: fogData.uuid, - config: true, - containerList: true - }; - - await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, changeTrackingUpdates, transaction) + if (msChanged) { + await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.microserviceCommon, transaction); + } } async function _deleteFog(fogData, user, isCli, transaction) { @@ -310,11 +306,6 @@ async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { versionCommand: fogVersionData.versionCommand }; - const changeTrackingUpdates = { - iofogUuid: fogVersionData.uuid, - version: true - }; - const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) @@ -322,7 +313,7 @@ async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { await _generateProvisioningKey({uuid: fogVersionData.uuid}, user, isCli, transaction); await FogVersionCommandManager.updateOrCreate({iofogUuid: fogVersionData.uuid}, newVersionCommand, transaction); - await ChangeTrackingManager.update({iofogUuid: fogVersionData.uuid}, changeTrackingUpdates, transaction) + await ChangeTrackingService.update(fogVersionData.uuid, ChangeTrackingService.events.version, transaction) } async function _setFogRebootCommand(fogData, user, isCli, transaction) { @@ -332,17 +323,12 @@ async function _setFogRebootCommand(fogData, user, isCli, transaction) { ? {uuid: fogData.uuid} : {uuid: fogData.uuid, userId: user.id}; - const newRebootCommand = { - iofogUuid: fogData.uuid, - reboot: true - }; - const fog = await FogManager.findOne(queryFogData, transaction); if (!fog) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_FOG_NODE_UUID, fogData.uuid)) } - await ChangeTrackingManager.update({iofogUuid: fogData.uuid}, newRebootCommand, transaction) + await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.reboot, transaction) } async function _getHalHardwareInfo(uuidObj, user, isCLI, transaction) { @@ -417,10 +403,7 @@ async function _processDeleteCommand(fog, transaction) { if (!fog.daemonStatus || fog.daemonStatus === 'UNKNOWN') { await FogManager.delete({uuid: fog.uuid}, transaction) } else { - await ChangeTrackingManager.update({iofogUuid: fog.uuid}, { - iofogUuid: fog.uuid, - deleteNode: true - }, transaction) + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.deleteNode, transaction) } } diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 17cabb45c..830544eff 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -20,7 +20,7 @@ const VolumeMappingManager = require('../sequelize/managers/volume-mapping-manag const ConnectorManager = require('../sequelize/managers/connector-manager'); const ConnectorPortManager = require('../sequelize/managers/connector-port-manager'); const MicroservicePublicModeManager = require('../sequelize/managers/microservice-public-mode-manager'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); +const ChangeTrackingService = require('./change-tracking-service'); const IoFogService = require('../services/iofog-service'); const AppHelper = require('../helpers/app-helper'); const Errors = require('../helpers/errors'); @@ -78,7 +78,7 @@ const _createMicroserviceOnFog = async function (microserviceData, user, isCLI, } if (microserviceData.iofogUuid) { - await _updateChangeTracking(microserviceData.iofogUuid, transaction); + await _updateChangeTracking(false, microserviceData.iofogUuid, transaction); } await _createMicroserviceStatus(microservice.uuid, transaction); @@ -180,10 +180,10 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, if (microserviceDataUpdate.iofogUuid) { await _deleteRoutes(microserviceData.routes, microserviceUuid, transaction); await _createRoutes(microserviceData.routes, microserviceUuid, user, transaction); - await _updateChangeTracking(microserviceDataUpdate.iofogUuid, transaction) + await _updateChangeTracking(false, microserviceDataUpdate.iofogUuid, transaction) } - await _updateChangeTracking(microservice.iofogUuid, transaction); + await _updateChangeTracking(microserviceData.config ? true : false, microservice.iofogUuid, transaction); }; const _updateVolumeMappings = async function (volumeMappings, microserviceUuid, transaction) { @@ -194,15 +194,12 @@ const _updateVolumeMappings = async function (volumeMappings, microserviceUuid, } }; -const _updateChangeTracking = async function (iofogUuid, transaction) { - - const trackingData = { - containerList: true, - containerConfig: true, - routing: true - }; - - await ChangeTrackingManager.update({iofogUuid: iofogUuid}, trackingData, transaction); +const _updateChangeTracking = async function (configUpdated, fogNodeUuid, transaction) { + if (configUpdated) { + await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceCommon, transaction); + } else { + await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceList, transaction); + } }; const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, user, isCLI, transaction) { @@ -238,7 +235,7 @@ const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, }, transaction); } - await _updateChangeTracking(microservice.iofogUuid, transaction) + await _updateChangeTracking(false, microservice.iofogUuid, transaction) }; const _deleteNotRunningMicroservices = async function (transaction) { @@ -464,13 +461,8 @@ async function _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, d await MicroserviceManager.update({uuid: sourceMicroservice.uuid}, updateRebuildMs, transaction) await MicroserviceManager.update({uuid: destMicroservice.uuid}, updateRebuildMs, transaction) - const updateChangeTrackingData = { - containerConfig: true, - containerList: true, - routing: true - } - await ChangeTrackingManager.update({iofogUuid: sourceMicroservice.iofogUuid}, updateChangeTrackingData, transaction) - await ChangeTrackingManager.update({iofogUuid: destMicroservice.iofogUuid}, updateChangeTrackingData, transaction) + await ChangeTrackingService.update(sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) + await ChangeTrackingService.update(destMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } async function _deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { @@ -510,12 +502,8 @@ async function _deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, async function _deleteSimpleRoute(route, transaction) { await RoutingManager.delete({id: route.id}, transaction) - const updateChangeTrackingData = { - routing: true - } - - await ChangeTrackingManager.update({iofogUuid: route.sourceIofogUuid}, updateChangeTrackingData, transaction) - await ChangeTrackingManager.update({iofogUuid: route.destIofogUuid}, updateChangeTrackingData, transaction) + await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) + await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) } async function _deleteRouteOverConnector(route, transaction) { @@ -529,14 +517,8 @@ async function _deleteRouteOverConnector(route, transaction) { await MicroserviceManager.delete({uuid: route.sourceNetworkMicroserviceUuid}, transaction) await MicroserviceManager.delete({uuid: route.destNetworkMicroserviceUuid}, transaction) - const updateChangeTrackingData = { - containerConfig: true, - containerList: true, - routing: true - } - - await ChangeTrackingManager.update({iofogUuid: route.sourceIofogUuid}, updateChangeTrackingData, transaction) - await ChangeTrackingManager.update({iofogUuid: route.destIofogUuid}, updateChangeTrackingData, transaction) + await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceFull, transaction) + await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } async function _createPortMapping(microserviceUuid, portMappingData, user, isCLI, transaction) { @@ -672,17 +654,10 @@ async function _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, let updateChangeTrackingData = {} if (isPublic) { - updateChangeTrackingData = { - containerConfig: true, - containerList: true, - routing: true - } + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } else { - updateChangeTrackingData = { - containerConfig: true, - } + await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceConfig, transaction) } - await ChangeTrackingManager.update({iofogUuid: microservice.iofogUuid}, updateChangeTrackingData, transaction) } async function _deletePortMapping(microserviceUuid, internalPort, user, isCLI, transaction) { @@ -737,12 +712,7 @@ async function _deletePortMappingOverConnector(microservice, msPorts, user, tran } await MicroserviceManager.update({uuid: microservice.uuid}, updateRebuildMs, transaction) - const updateChangeTrackingData = { - containerConfig: true, - containerList: true, - routing: true - } - await ChangeTrackingManager.update({iofogUuid: pubModeData.iofogUuid}, updateChangeTrackingData, transaction) + await ChangeTrackingService.update(pubModeData.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } async function _validatePorts(internal, external) { diff --git a/src/services/registry-service.js b/src/services/registry-service.js index 8d70ebd46..5d3c44737 100644 --- a/src/services/registry-service.js +++ b/src/services/registry-service.js @@ -15,7 +15,7 @@ const RegistryManager = require('../sequelize/managers/registry-manager'); const Validator = require('../schemas'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager'); +const ChangeTrackingService = require('./change-tracking-service'); const TransactionDecorator = require('../decorators/transaction-decorator'); const FogManager = require('../sequelize/managers/iofog-manager'); const Sequelize = require('sequelize'); @@ -52,11 +52,7 @@ const createRegistry = async function (registry, user, transaction) { const updateChangeTracking = async function (user, transaction) { let fogs = await FogManager.findAll({userId: user.id}, transaction); for (fog of fogs) { - const changeTrackingUpdates = { - iofogUuid: fog.uuid, - registries: true - }; - await ChangeTrackingManager.update({iofogUuid: fog.uuid}, changeTrackingUpdates, transaction); + await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.registries, transaction); } }; diff --git a/src/services/tunnel-service.js b/src/services/tunnel-service.js index cd591255d..5b2211fc9 100644 --- a/src/services/tunnel-service.js +++ b/src/services/tunnel-service.js @@ -18,7 +18,7 @@ const AppHelper = require('../helpers/app-helper'); const Validator = require('../schemas') const Errors = require('../helpers/errors') const TransactionDecorator = require('../decorators/transaction-decorator'); -const ChangeTrackingManager = require('../sequelize/managers/change-tracking-manager') +const ChangeTrackingService = require('./change-tracking-service'); const openTunnel = async function (tunnelData, user, isCli, transaction) { const iofog = await FogManager.findOne({uuid : tunnelData.iofogUuid}, transaction); @@ -43,15 +43,7 @@ const openTunnel = async function (tunnelData, user, isCli, transaction) { } await Validator.validate(tunnel, Validator.schemas.tunnelCreate); await TunnelManager.updateOrCreate(tunnelData, tunnel, transaction); - await updateChangeTracking(tunnelData, transaction); -}; - -const updateChangeTracking = async function (tunnelData, transaction){ - const changeTrackingUpdates = { - iofogUuid: tunnelData.iofogUuid, - tunnel: true - } - await ChangeTrackingManager.update({iofogUuid: tunnelData.iofogUuid}, changeTrackingUpdates, transaction); + await ChangeTrackingService.update(tunnelData.iofogUuid, ChangeTrackingService.events.tunnel, transaction); }; const findTunnel = async function (tunnelData, user, transaction) { @@ -78,7 +70,7 @@ const findAll = async function (transaction) { const closeTunnel = async function (tunnelData, user, transaction) { await findTunnel(tunnelData, user, transaction); await TunnelManager.update(tunnelData, {closed : true}, transaction); - await updateChangeTracking(tunnelData, transaction); + await ChangeTrackingService.update(tunnelData.iofogUuid, ChangeTrackingService.events.tunnel, transaction); }; module.exports = { diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index da25bb98c..6a6fe0b9e 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1,12 +1,13 @@ { "info": { - "_postman_id": "0c412a3a-7328-4c9e-8919-d2836adccfa1", + "_postman_id": "b585aece-cb86-4f3b-93f3-12552c1c90c5", "name": "Controller Testing", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "User", + "description": null, "item": [ { "name": "Create user", @@ -509,6 +510,7 @@ }, { "name": "General", + "description": null, "item": [ { "name": "Status", @@ -631,6 +633,7 @@ }, { "name": "Agent", + "description": null, "item": [ { "name": "Create user", @@ -856,7 +859,6 @@ "method": "POST", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" } @@ -906,7 +908,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -954,7 +955,6 @@ "method": "PATCH", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1008,7 +1008,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1057,7 +1056,6 @@ "method": "PUT", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1108,7 +1106,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1159,7 +1156,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1211,7 +1207,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1262,7 +1257,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1310,7 +1304,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1361,7 +1354,6 @@ "method": "PUT", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1412,7 +1404,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1559,7 +1550,6 @@ "method": "GET", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1657,7 +1647,6 @@ "method": "DELETE", "header": [ { - "disabled": false, "key": "Content-Type", "value": "application/json" }, @@ -1735,6 +1724,7 @@ }, { "name": "Flow", + "description": null, "item": [ { "name": "Create user", @@ -2121,6 +2111,7 @@ }, { "name": "Catalog", + "description": null, "item": [ { "name": "Create user", @@ -2516,6 +2507,7 @@ }, { "name": "Tunnel", + "description": null, "item": [ { "name": "Create user", @@ -2859,6 +2851,7 @@ }, { "name": "Microservices", + "description": null, "item": [ { "name": "Create user", @@ -3795,6 +3788,7 @@ }, { "name": "Diagnostics", + "description": null, "item": [ { "name": "Create user", @@ -4593,6 +4587,7 @@ }, { "name": "ioFog", + "description": null, "item": [ { "name": "Create user", @@ -5299,6 +5294,7 @@ }, { "name": "Registries", + "description": null, "item": [ { "name": "Create user", From e3c0ac60cbd2c54e64ad2a3a30d7ddaf421014aa Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Thu, 8 Nov 2018 15:27:27 +0300 Subject: [PATCH 35/91] EWC-322 config cli log messages (#330) * EWC-322 config cli log messages * EWC-322 config cli log messages --- src/cli/catalog.js | 2 +- src/cli/config.js | 124 ++++++++++++++++++++-------------- src/cli/controller.js | 8 +-- src/cli/registry.js | 2 +- src/cli/user.js | 2 - src/helpers/app-helper.js | 6 +- src/helpers/error-messages.js | 2 +- src/schemas/config.js | 39 +++++++++++ src/schemas/tunnel.js | 4 +- 9 files changed, 125 insertions(+), 64 deletions(-) create mode 100644 src/schemas/config.js diff --git a/src/cli/catalog.js b/src/cli/catalog.js index 00ab2b3fa..b8b321fb3 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -174,7 +174,7 @@ const _listCatalogItems = async function () { const _listCatalogItem = async function (obj) { logger.info(JSON.stringify(obj)); const result = await CatalogItemService.getCatalogItem(obj.itemId, {}, true); - logger.info(JSON.stringify(result)); + logger.info(JSON.stringify(result, null, 2)); logger.info('Catalog item has been successfully retrieved.'); }; diff --git a/src/cli/config.js b/src/cli/config.js index e2e7c969d..6a1cf50f7 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -16,6 +16,7 @@ const config = require('../config'); const constants = require('../helpers/constants'); const AppHelper = require('../helpers/app-helper'); const ErrorMessages = require('../helpers/error-messages'); +const Validator = require('../schemas'); const logger = require('../logger'); class Config extends BaseCLIHandler { @@ -77,84 +78,107 @@ const _executeCase = async function (catalogCommand, commandName, f) { }; const _addConfigOption = async function (options) { - if (options.port != null) { + await Validator.validate(options, Validator.schemas.configUpdate); + + updateConfig(options.port, 'port', 'Server:Port', async (onSuccess) => { const port = options.port; - if (!AppHelper.isValidPort(port)) { - logger.error(ErrorMessages.INVALID_PORT_FORMAT); - return; + const status = await AppHelper.checkPortAvailability(port); + if (status === 'closed') { + config.set('Server:Port', port); + onSuccess(); + } else { + logger.error(AppHelper.formatMessage(ErrorMessages.PORT_NOT_AVAILABLE, port)); } - AppHelper.checkPortAvailability(port).then(availability => { - if (availability === 'closed') { - config.set('Server:Port', port); - } - else { - logger.error(AppHelper.formatMessage(ErrorMessages.PORT_NOT_AVAILABLE, port)); - } - }); - } + }); - if (options.sslCert != null) { + updateConfig(options.sslCert, 'ssl-cert', 'Server:SslCert', (onSuccess) => { const sslCert = options.sslCert; if (!AppHelper.isFileExists(sslCert)) { logger.error(ErrorMessages.INVALID_FILE_PATH); return; } - config.set('Server:SslCert', sslCert) - } + config.set('Server:SslCert', sslCert); + onSuccess(); + }); - if (options.sslKey != null) { + if (options.sslKey) { const sslKey = options.sslKey; if (!AppHelper.isFileExists(sslKey)) { logger.error(ErrorMessages.INVALID_FILE_PATH); return; } - config.set('Server:SslKey', sslKey) + config.set('Server:SslKey', sslKey); + logger.info('Config option ssl-key has been updated.'); } - if (options.intermediateCert != null) { + updateConfig(options.intermediateCert, 'intermediate-cert', 'Server:IntermediateCert', (onSuccess) => { const intermediateCert = options.intermediateCert; if (!AppHelper.isFileExists(intermediateCert)) { logger.error(ErrorMessages.INVALID_FILE_PATH); return; } - config.set('Server:IntermediateCert', intermediateCert) - } - - if (options.emailActivationOn != null) { - config.set('Email:ActivationEnabled', true) - } - - if (options.emailActivationOff != null) { - config.set('Email:ActivationEnabled', false) - } - - if (options.homeUrl != null && config.get('Email:HomeUrl') !== options.homeUrl) { - config.set('Email:HomeUrl', options.homeUrl) - } - - if (options.emailAddress != null && config.get('Email:Address') !== options.emailAddress) { - if (options.emailPassword == null) { - return console.log('When changing email address, password must be provided.') + config.set('Server:IntermediateCert', intermediateCert); + onSuccess(); + }); + + updateConfig(options.emailActivationOn, 'email-activation-on', 'Email:ActivationEnabled', (onSuccess) => { + config.set('Email:ActivationEnabled', true); + onSuccess(); + }); + + updateConfig(options.emailActivationOff, 'email-activation-off', 'Email:ActivationEnabled', (onSuccess) => { + config.set('Email:ActivationEnabled', false); + onSuccess(); + }); + + updateConfig(options.homeUrl, 'home-url', 'Email:HomeUrl', (onSuccess) => { + config.set('Email:HomeUrl', options.homeUrl); + onSuccess(); + }); + + updateConfig(options.emailAddress, 'email-address', 'Email:Address', (onSuccess) => { + if (options.emailPassword) { + logger.info('When changing email address, password must be provided.'); + return; } - config.set('Email:Address', options.emailAddress) - } + config.set('Email:Address', options.emailAddress); + onSuccess(); + }); - if (options.emailPassword != null) { - config.set('Email:Password', AppHelper.encryptText(options.emailPassword, config.get('Email:Address'))) + if (options.emailPassword) { + config.set('Email:Password', AppHelper.encryptText(options.emailPassword, config.get('Email:Address'))); + logger.info('Config option email-password has been updated.'); } - if (options.emailService != null) { - config.set('Email:Service', options.emailService) - } + updateConfig(options.emailService, 'email-service', 'Email:Service', (onSuccess) => { + config.set('Email:Service', options.emailService); + onSuccess(); + }); - if (options.logDir != null) { - config.set('Service:LogsDirectory', options.logDir) - } + updateConfig(options.logDir, 'log-dir', 'Service:LogsDirectory', (onSuccess) => { + config.set('Service:LogsDirectory', options.logDir); + onSuccess(); + }); - if (options.logSize != null) { - config.set('Service:LogsFileSize', options.logSize * 1024) + updateConfig(options.logSize, 'log-size', 'Service:LogsFileSize', (onSuccess) => { + config.set('Service:LogsFileSize', options.logSize * 1024); + onSuccess(); + }) +}; + +const updateConfig = async function (newConfigValue, cliConfigName, configName, fn) { + if (newConfigValue) { + const oldConfigValue = config.get(configName); + if (newConfigValue !== oldConfigValue) { + await fn(function() { + const currentConfigValue = config.get(configName); + logger.info(`Config option ${cliConfigName} has been set to ${currentConfigValue}`); + }); + } else { + logger.info(`Config option ${cliConfigName} is already set to ${newConfigValue}`); + } } -} +}; const _listConfigOptions = function () { const configuration = { diff --git a/src/cli/controller.js b/src/cli/controller.js index 8a9324312..f76e91b7e 100644 --- a/src/cli/controller.js +++ b/src/cli/controller.js @@ -78,22 +78,22 @@ const _executeCase = async function (userCommand, commandName, f, isUserRequired const _getStatus = async function () { const response = await ControllerService.statusController(true); - logger.info(JSON.stringify(response)); + logger.info(JSON.stringify(response, null, 2)); }; const _emailActivation = async function () { const response = await ControllerService.emailActivation(true); - logger.info(JSON.stringify(response)); + logger.info(JSON.stringify(response, null, 2)); }; const _getFogTypes = async function () { const response = await ControllerService.getFogTypes(true); - logger.info(JSON.stringify(response)); + logger.info(JSON.stringify(response, null, 2)); }; const _getVersion = async function() { const response = await ControllerService.getVersion(true); - logger.info(response); + logger.info(response, null, 2); }; module.exports = new Controller(); \ No newline at end of file diff --git a/src/cli/registry.js b/src/cli/registry.js index 31be587d4..93c722d36 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -78,7 +78,7 @@ async function _createRegistry(obj, user) { async function _getRegistries(obj, user) { const result = await RegistryService.findRegistries(user, true); - logger.info(JSON.stringify(result)); + logger.info(JSON.stringify(result, null, 2)); logger.info('List of Registries has been received successfully.'); } diff --git a/src/cli/user.js b/src/cli/user.js index 6b6dbed29..61416b4e4 100644 --- a/src/cli/user.js +++ b/src/cli/user.js @@ -14,10 +14,8 @@ const BaseCLIHandler = require('./base-cli-handler'); const constants = require('../helpers/constants'); const UserService = require('../services/user-service'); -const UserManager = require('../sequelize/managers/user-manager'); const logger = require('../logger'); const AppHelper = require('../helpers/app-helper'); -const EmailActivationCodeService = require('../services/email-activation-code-service'); const AuthDecorator = require('../decorators/cli-decorator'); const Validator = require('../schemas'); diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index e66660f95..3dd7a2b59 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -50,9 +50,9 @@ function generateRandomString(size) { // Checks the status of a single port // returns 'closed' if port is available // returns 'open' if port is not available -function checkPortAvailability(port) { - return portscanner.checkPortStatus(port).then(function (status) { - return status; +async function checkPortAvailability(port) { + return new Promise((resolve) => { + return resolve(portscanner.checkPortStatus(port)); }); } diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index f72a4ca18..c7cc1317c 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -34,7 +34,7 @@ module.exports = { EMAIL_SENDER_NOT_CONFIGURED: 'Email sender not configured', INVALID_PORT_FORMAT: 'Invalid port format', INVALID_FILE_PATH: 'Invalid file path', - PORT_NOT_AVAILABLE: 'Port {} not available', + PORT_NOT_AVAILABLE: 'Port {} is not available', UNABLE_TO_WRITE_STRACE: 'Error while writing strace data to file. File name: {}, err: {}', UNABLE_TO_DELETE_STRACE: 'Error while deleting strace data file. File name: {}, err: {}', FTP_ERROR: 'FTP error: {}', diff --git a/src/schemas/config.js b/src/schemas/config.js new file mode 100644 index 000000000..17d5f9018 --- /dev/null +++ b/src/schemas/config.js @@ -0,0 +1,39 @@ +/* + * ******************************************************************************* + * * Copyright (c) 2018 Edgeworx, Inc. + * * + * * This program and the accompanying materials are made available under the + * * terms of the Eclipse Public License v. 2.0 which is available at + * * http://www.eclipse.org/legal/epl-2.0 + * * + * * SPDX-License-Identifier: EPL-2.0 + * ******************************************************************************* + * + */ + +const configUpdate = { + "id": "/configUpdate", + "type": "object", + "properties": { + "port": {"type": "integer", "minimum" : 0, "maximum" : 65535}, + "sslCert": {"type": "string"}, + "sslKey": {"type": "string"}, + "intermediateCert": {"type": "string"}, + "emailActivationOn": {"type": "boolean"}, + "emailActivationOff": {"type": "boolean"}, + "homeUrl": {"type": "string"}, + "emailAddress": { + "type": "string", + "pattern": "^(([^<>()\\[\\]\\\\.,;:\\s@\"]+(\\.[^<>()\\[\\]\\\\.,;:\\s@\"]+)*)|(\".+\"))@((\\[[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}])|(([a-zA-Z\\-0-9]+\\.)+[a-zA-Z]{2,}))$" + }, + "emailPassword": {"type": "string", "minLength": 1}, + "emailService": {"type": "string"}, + "logDir": {"type": "string"}, + "logSize": {"type": "integer"} + } +} + + module.exports = { + mainSchemas: [configUpdate], + innerSchemas: [] +}; diff --git a/src/schemas/tunnel.js b/src/schemas/tunnel.js index 2a1e77a78..87f9397aa 100644 --- a/src/schemas/tunnel.js +++ b/src/schemas/tunnel.js @@ -19,8 +19,8 @@ const tunnelCreate = { "username": {"type": "string", "minLength": 1}, "password": {"type": "string"}, "rsakey": {"type": "string"}, - "lport": {"type": "integer", "minimum" : 0}, - "rport": {"type": "integer", "minimum" : 0} + "lport": {"type": "integer", "minimum" : 0, "maximum" : 65535}, + "rport": {"type": "integer", "minimum" : 0, "maximum" : 65535} }, "required": ["iofogUuid", "username", "password", "lport", "rport"] }; From 143c2d47ef0bc517e97de7ba20057fbe8720ed4c Mon Sep 17 00:00:00 2001 From: Railag Date: Thu, 8 Nov 2018 16:14:02 +0300 Subject: [PATCH 36/91] EWC-321 lastActive agent decorator (#329) * EWC-321 lastActive agent decorator * cleanup --- src/controllers/agent-controller.js | 2 +- src/decorators/authorization-decorator.js | 6 +++++ src/sequelize/managers/iofog-manager.js | 28 +++++++++++++++++------ 3 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/controllers/agent-controller.js b/src/controllers/agent-controller.js index ab078c5d2..6fc8c8330 100644 --- a/src/controllers/agent-controller.js +++ b/src/controllers/agent-controller.js @@ -104,7 +104,7 @@ const deleteNodeEndPoint = async function (req, fog) { return await AgentService.deleteNode(fog); }; -const getImageSnapshotEndPoint = async function(req, fog) { +const getImageSnapshotEndPoint = async function (req, fog) { return await AgentService.getImageSnapshot(fog); }; diff --git a/src/decorators/authorization-decorator.js b/src/decorators/authorization-decorator.js index b4840a59d..b4a36ba75 100644 --- a/src/decorators/authorization-decorator.js +++ b/src/decorators/authorization-decorator.js @@ -65,7 +65,13 @@ function checkFogToken(f) { } fArgs.push(fog); + FogAccessTokenManager.updateExpirationTime(fog.accessToken.id, fog.accessToken.expirationTime + config.get('Settings:FogTokenExpirationIntervalSeconds') * 1000); + + const timestamp = Date.now(); + logger.info('updating agent lastActive timestamp: ' + timestamp); + await FogManager.updateLastActive(fog.uuid, timestamp); + return await f.apply(this, fArgs); } } diff --git a/src/sequelize/managers/iofog-manager.js b/src/sequelize/managers/iofog-manager.js index d380991a7..d4b83c98b 100644 --- a/src/sequelize/managers/iofog-manager.js +++ b/src/sequelize/managers/iofog-manager.js @@ -11,12 +11,12 @@ * */ -const BaseManager = require('../managers/base-manager') +const BaseManager = require('../managers/base-manager'); const models = require('./../models'); -const Fog = models.Fog -const Microservice = models.Microservice -const FogAccessToken = models.FogAccessToken -const Strace = models.StraceDiagnostics +const Fog = models.Fog; +const Microservice = models.Microservice; +const FogAccessToken = models.FogAccessToken; +const Strace = models.StraceDiagnostics; class FogManager extends BaseManager { getEntity() { @@ -36,6 +36,18 @@ class FogManager extends BaseManager { }); } + + // no transaction required here, used by agent-last-active decorator + updateLastActive(uuid, timestamp) { + return Fog.update({ + lastActive: timestamp + }, { + where: { + uuid: uuid + } + }); + } + findFogStraces(where, transaction) { return Fog.findOne({ include: [ @@ -52,7 +64,9 @@ class FogManager extends BaseManager { where: where }, {transaction: transaction}) } + + } -const instance = new FogManager() -module.exports = instance \ No newline at end of file +const instance = new FogManager(); +module.exports = instance; \ No newline at end of file From 80649442d268c5f13623922c0a8fe484dfdc4cf1 Mon Sep 17 00:00:00 2001 From: Railag Date: Thu, 8 Nov 2018 16:14:16 +0300 Subject: [PATCH 37/91] EWC-331 restrict uuid field in iofog create endpoint (#331) --- src/schemas/iofog.js | 1 - src/services/iofog-service.js | 4 ++-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/src/schemas/iofog.js b/src/schemas/iofog.js index 1f1d2d828..7b429302d 100644 --- a/src/schemas/iofog.js +++ b/src/schemas/iofog.js @@ -15,7 +15,6 @@ const iofogCreate = { "id": "/iofogCreate", "type": "object", "properties": { - "uuid": {"type": "string"}, "name": {"type": "string", "minLength": 1}, "location": {"type": "string"}, "latitude": {"type": "number", "minimum": -90, "maximum": 90}, diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index eb5548f58..2ee18a7fd 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -29,7 +29,7 @@ async function _createFog(fogData, user, isCli, transaction) { await Validator.validate(fogData, Validator.schemas.iofogCreate); let createFogData = { - uuid: fogData.uuid ? fogData.uuid : AppHelper.generateRandomString(32), + uuid: AppHelper.generateRandomString(32), name: fogData.name, location: fogData.location, latitude: fogData.latitude, @@ -52,7 +52,7 @@ async function _createFog(fogData, user, isCli, transaction) { abstractedHardwareEnabled: fogData.abstractedHardwareEnabled, fogTypeId: fogData.fogType, userId: user.id - } + }; createFogData = AppHelper.deleteUndefinedFields(createFogData); const fog = await FogManager.create(createFogData, transaction); From ac2c2b817bc67b068eed823620935f216d918523 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Thu, 8 Nov 2018 16:37:56 +0300 Subject: [PATCH 38/91] migration from v1.0.0 to umzug ewc 327 (#328) * get fog list params in query * preisntall and postinstal scripts * merge cleanup * vars to /tmp folder correct comparison of versions --- package.json | 2 ++ scripts/postinstall.sh | 55 ++++++++++++++++++++++++++++++++++++++++++ scripts/preinstall.sh | 4 +++ 3 files changed, 61 insertions(+) create mode 100644 scripts/postinstall.sh create mode 100644 scripts/preinstall.sh diff --git a/package.json b/package.json index f3ba2e25d..dbd1392f4 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,8 @@ "start": "NODE_ENV=production node ./src/main.js start", "start-dev": "NODE_ENV=development node ./src/main.js start", "build": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", + "preinstall": "bash scripts/preinstall.sh", + "postinstall": "bash scripts/postinstall.sh", "lint": "./node_modules/.bin/eslint \"**/*.js\"" }, "preferGlobal": true, diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh new file mode 100644 index 000000000..93412a368 --- /dev/null +++ b/scripts/postinstall.sh @@ -0,0 +1,55 @@ +#!/bin/bash + +vercomp () { + if [[ $1 == $2 ]] + then + echo '=' + return + fi + local IFS=. + local i ver1=($1) ver2=($2) + # fill empty fields in ver1 with zeros + for ((i=${#ver1[@]}; i<${#ver2[@]}; i++)) + do + ver1[i]=0 + done + for ((i=0; i<${#ver1[@]}; i++)) + do + if [[ -z ${ver2[i]} ]] + then + # fill empty fields in ver2 with zeros + ver2[i]=0 + fi + if ((10#${ver1[i]} > 10#${ver2[i]})) + then + echo '>' + return + fi + if ((10#${ver1[i]} < 10#${ver2[i]})) + then + echo '<' + return + fi + done + echo '=' + return +} + +PREV_IOFOG_CONTROLLER_VER=$(grep prev_ver /tmp/iofogcontroller_install_variables | awk '{print $2}') +echo "Prev ver: "${PREV_IOFOG_CONTROLLER_VER} + +if [[ -z "${PREV_IOFOG_CONTROLLER_VER// }" ]] +then + echo "No prev ver" +else + if [[ $(vercomp $PREV_IOFOG_CONTROLLER_VER 1.0.0) = '<' ]] || [[ $(vercomp $PREV_IOFOG_CONTROLLER_VER 1.0.0) = '=' ]] + then + echo "Upgrading from ver 1.0.0" + sqlite3 src/sequelize/prod_database.sqlite "insert into SequelizeMeta (name) values ('20180928110125-insert-registry.js');" + sqlite3 src/sequelize/prod_database.sqlite "insert into SequelizeMeta (name) values ('20180928111532-insert-catalog-item.js');" + sqlite3 src/sequelize/prod_database.sqlite "insert into SequelizeMeta (name) values ('20180928112152-insert-iofog-type.js');" + sqlite3 src/sequelize/prod_database.sqlite "insert into SequelizeMeta (name) values ('20180928121334-insert-catalog-item-image.js');" + fi +fi + +rm -rf /tmp/iofogcontroller_install_variables \ No newline at end of file diff --git a/scripts/preinstall.sh b/scripts/preinstall.sh new file mode 100644 index 000000000..412b9e280 --- /dev/null +++ b/scripts/preinstall.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +export PREV_IOFOG_CONTROLLER_VER=$(npm list --depth=0 -g --silent | grep iofogcontroller | awk -F "@" '{print $2}') +printf 'prev_ver: '$PREV_IOFOG_CONTROLLER_VER > /tmp/iofogcontroller_install_variables \ No newline at end of file From f8045bccc170f24f8fe96ea4fb575a0003f9456e Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Thu, 8 Nov 2018 16:38:26 +0300 Subject: [PATCH 39/91] postman collection (#332) --- src/schemas/microservice.js | 15 ++++++++++----- tests/Controller Testing.postman_collection.json | 6 +++--- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 29a1e6239..833e20a2f 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -23,7 +23,8 @@ const microserviceCreate = { "type": "array", "items": {"type": "string"}} }, - "required": ["name", "flowId", "catalogItemId"] + "required": ["name", "flowId", "catalogItemId"], + "additionalProperties": false }; const microserviceUpdate = { @@ -43,7 +44,8 @@ const microserviceUpdate = { "type": "array", "items": {"$ref": "/volumeMappings"} } - } + }, + "additionalProperties": false }; const ports = { @@ -54,7 +56,8 @@ const ports = { "external": {"type": "integer"}, "publicMode": {"enum": [false]} }, - "required": ["internal", "external"] + "required": ["internal", "external"], + "additionalProperties": false }; const portsCreate = { @@ -65,7 +68,8 @@ const portsCreate = { "external": {"type": "integer"}, "publicMode": {"type": "boolean"} }, - "required": ["internal", "external"] + "required": ["internal", "external"], + "additionalProperties": false }; const volumeMappings = { @@ -76,7 +80,8 @@ const volumeMappings = { "containerDestination": {"type": "string"}, "accessMode": {"type": "string"} }, - "required": ["hostDestination", "containerDestination", "accessMode"] + "required": ["hostDestination", "containerDestination", "accessMode"], + "additionalProperties": false }; module.exports = { diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 6a6fe0b9e..15a288151 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -3137,7 +3137,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"ioFogNodeId\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" + "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" }, "url": { "raw": "{{host}}/api/v3/microservices", @@ -3287,7 +3287,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"name3\",\n \"config\": \"string\",\n \"needUpdate\": true,\n \"rebuild\": true,\n \"ioFogNodeId\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"imageSnapshot\": \"string\",\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ]\n}\n" + "raw": "{\n \"name\": \"name3\",\n \"config\": \"string\",\n \"needUpdate\": true,\n \"rebuild\": true,\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"imageSnapshot\": \"string\",\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ]\n}\n" }, "url": { "raw": "{{host}}/api/v3/microservices/{{ms-id}}", @@ -4074,7 +4074,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"ioFogNodeId\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" + "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" }, "url": { "raw": "{{host}}/api/v3/microservices", From 2d7167e105971a982d05b75e90b417c4775713b3 Mon Sep 17 00:00:00 2001 From: Railag Date: Thu, 8 Nov 2018 17:51:09 +0300 Subject: [PATCH 40/91] EWC-330 fixed redundant timestamp fields in response (#334) --- src/services/agent-service.js | 2 +- src/services/iofog-service.js | 57 +++- ...Controller Testing.postman_collection.json | 263 ++++++++++++++++-- 3 files changed, 295 insertions(+), 27 deletions(-) diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 557787a21..cd1635ac1 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -36,7 +36,7 @@ const fs = require('fs'); const formidable = require('formidable'); const logger = require('../logger'); const Sequelize = require('sequelize'); -const Op = Sequelize.Op +const Op = Sequelize.Op; const agentProvision = async function (provisionData, transaction) { diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 2ee18a7fd..99c36a5c2 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -247,7 +247,56 @@ async function _getFog(fogData, user, isCli, transaction) { } await _updateFogsConnectionStatus(fog, transaction); - return fog + return { + uuid: fog.uuid, + name: fog.name, + location: fog.location, + gpsMode: fog.gpsMode, + latitude: fog.latitude, + longitude: fog.longitude, + description: fog.description, + lastActive: fog.lastActive, + daemonStatus: fog.daemonStatus, + daemonOperatingDuration: fog.daemonOperatingDuration, + daemonLastStart: fog.daemonLastStart, + memoryUsage: fog.memoryUsage, + diskUsage: fog.diskUsage, + cpuUsage: fog.cpuUsage, + memoryViolation: fog.memoryViolation, + diskViolation: fog.diskViolation, + cpuViolation: fog.cpuViolation, + catalogItemStatus: fog.catalogItemStatus, + repositoryCount: fog.repositoryCount, + repositoryStatus: fog.repositoryStatus, + systemTime: fog.systemTime, + lastStatusTime: fog.lastStatusTime, + ipAddress: fog.ipAddress, + processedMessages: fog.processedMessages, + catalogItemMessageCounts: fog.catalogItemMessageCounts, + messageSpeed: fog.messageSpeed, + lastCommandTime: fog.lastCommandTime, + networkInterface: fog.networkInterface, + dockerUrl: fog.dockerUrl, + diskLimit: fog.diskLimit, + diskDirectory: fog.diskDirectory, + memoryLimit: fog.memoryLimit, + cpuLimit: fog.cpuLimit, + logLimit: fog.logLimit, + logDirectory: fog.logDirectory, + bluetoothEnabled: fog.bluetoothEnabled, + abstractedHardwareEnabled: fog.abstractedHardwareEnabled, + logFileCount: fog.logFileCount, + version: fog.version, + isReadyToUpgrade: fog.isReadyToUpgrade, + isReadyToRollback: fog.isReadyToRollback, + statusFrequency: fog.statusFrequency, + changeFrequency: fog.changeFrequency, + deviceScanFrequency: fog.deviceScanFrequency, + tunnel: fog.tunnel, + watchdogEnabled: fog.watchdogEnabled, + fogTypeId: fog.fogTypeId, + userId: fog.userId + }; } async function _getFogList(filters, user, isCli, transaction) { @@ -286,12 +335,10 @@ async function _generateProvisioningKey(fogData, user, isCli, transaction) { } const provisioningKeyData = await FogProvisionKeyManager.updateOrCreate({iofogUuid: fogData.uuid}, newProvision, transaction); - const res = { + return { key: provisioningKeyData.provisionKey, expirationTime: provisioningKeyData.expirationTime - }; - - return res + } } async function _setFogVersionCommand(fogVersionData, user, isCli, transaction) { diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 15a288151..6ccc116c0 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1,13 +1,13 @@ { "info": { - "_postman_id": "b585aece-cb86-4f3b-93f3-12552c1c90c5", + "_postman_id": "5a9e5363-c42e-4cfe-ad53-4ba7f9594334", "name": "Controller Testing", + "description": "iofog-controller collection", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" }, "item": [ { "name": "User", - "description": null, "item": [ { "name": "Create user", @@ -506,11 +506,33 @@ }, "response": [] } + ], + "description": "User collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "3e653bd9-8814-4b3c-ac4b-4d880264ac51", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "e7f8e2fe-9d1d-4368-8b85-3e279b3f79c9", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "General", - "description": null, "item": [ { "name": "Status", @@ -629,11 +651,33 @@ }, "response": [] } + ], + "description": "General collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "a9f31b5d-feea-4535-aa6d-dc3b4916f2c0", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "667d4cc7-d7fe-4fd5-b466-6c6cf566181e", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Agent", - "description": null, "item": [ { "name": "Create user", @@ -919,7 +963,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/config", @@ -1019,7 +1063,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/config/changes", @@ -1117,7 +1161,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/microservices", @@ -1167,7 +1211,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/microservices/abcedf", @@ -1218,7 +1262,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/registries", @@ -1268,7 +1312,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/tunnel", @@ -1315,7 +1359,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/strace", @@ -1415,7 +1459,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/version", @@ -1561,7 +1605,7 @@ ], "body": { "mode": "raw", - "raw": "{\n\t\"type\": 1,\n\t\"key\":\"testtesttest\"\n}" + "raw": "" }, "url": { "raw": "{{host}}/api/v3/agent/image-snapshot", @@ -1720,11 +1764,33 @@ }, "response": [] } + ], + "description": "Agent collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "9a24c940-df22-48f6-adb4-a87d0984ede4", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "09618b10-daee-4fc9-b1cc-f8c53e5dd44c", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Flow", - "description": null, "item": [ { "name": "Create user", @@ -2107,11 +2173,33 @@ }, "response": [] } + ], + "description": "Flow collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "9bbd4e2b-52b4-459e-b897-da7c1b23bb67", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "b7c4da7e-1045-4b10-9512-01aa7a49939f", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Catalog", - "description": null, "item": [ { "name": "Create user", @@ -2503,11 +2591,33 @@ }, "response": [] } + ], + "description": "Catalog collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "0d9a3e47-19ce-40ff-b759-1bb82e596471", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "a4a0c5c9-ec92-4f92-af24-3feb0dc1e1a1", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Tunnel", - "description": null, "item": [ { "name": "Create user", @@ -2847,11 +2957,33 @@ }, "response": [] } + ], + "description": "Tunnel collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "40012762-3050-44e8-a4b2-5f73927f7ee4", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "18a2c8f2-143e-40d4-b2c5-73e65928cd0f", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Microservices", - "description": null, "item": [ { "name": "Create user", @@ -3137,7 +3269,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" + "raw": "{\n \"name\": \"name2\",\n \"config\": \"string\",\n \"catalogItemId\": {{item-id}},\n \"flowId\": {{flow-id}},\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logSize\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ],\n \"ports\": [\n {\n \"internal\": 1,\n \"external\": 1,\n \"publicMode\": false\n }\n ],\n \"routes\": [\n ]\n}\n" }, "url": { "raw": "{{host}}/api/v3/microservices", @@ -3784,11 +3916,33 @@ }, "response": [] } + ], + "description": "Microservices collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "5533a95b-87ad-44ce-bb0d-814f168232e4", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "6d066f42-9672-4132-9fc6-1c1f358aa7c4", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Diagnostics", - "description": null, "item": [ { "name": "Create user", @@ -4583,11 +4737,33 @@ }, "response": [] } + ], + "description": "Diagnostics collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "2bd3ea6c-0644-4d20-af85-ad02d45b9680", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "c15f1694-b141-4e0d-a944-ab267b82676c", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "ioFog", - "description": null, "item": [ { "name": "Create user", @@ -5290,11 +5466,33 @@ }, "response": [] } + ], + "description": "ioFog collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "2ca5703b-9167-4292-b4fa-507bae7a371b", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "e7c20898-bdb2-4989-a0bb-d980b075bb00", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] }, { "name": "Registries", - "description": null, "item": [ { "name": "Create user", @@ -5628,6 +5826,29 @@ }, "response": [] } + ], + "description": "Registries collection", + "event": [ + { + "listen": "prerequest", + "script": { + "id": "77262f2d-e9f2-467d-a34f-49ba0ad7673d", + "type": "text/javascript", + "exec": [ + "" + ] + } + }, + { + "listen": "test", + "script": { + "id": "6cf34135-001b-4782-b4c9-78c470b337cf", + "type": "text/javascript", + "exec": [ + "" + ] + } + } ] } ], From 2cf43dec83f5c9b92efddee3a4a1e5690e122655 Mon Sep 17 00:00:00 2001 From: dbusel Date: Fri, 9 Nov 2018 15:59:11 +0300 Subject: [PATCH 41/91] rename endpoints (#333) --- src/cli/connector.js | 8 ++++---- src/cli/flow.js | 8 ++++---- src/cli/iofog.js | 14 +++++++------- src/cli/microservice.js | 20 ++++++++++---------- src/controllers/flow-controller.js | 8 ++++---- src/controllers/iofog-controller.js | 14 +++++++------- src/controllers/microservices-controller.js | 20 ++++++++++---------- src/services/connector-service.js | 8 ++++---- src/services/diagnostic-service.js | 2 +- src/services/flow-service.js | 10 +++++----- src/services/iofog-service.js | 14 +++++++------- src/services/microservices-service.js | 21 ++++++++++----------- 12 files changed, 73 insertions(+), 74 deletions(-) diff --git a/src/cli/connector.js b/src/cli/connector.js index c3feae7bb..0c2903c93 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -84,7 +84,7 @@ async function _createConnector(obj) { const connector = _createConnectorObject(obj) logger.info(JSON.stringify(connector)); try { - const result = await ConnectorService.createConnectorWithTransaction(connector) + const result = await ConnectorService.createConnector(connector) logger.info(JSON.stringify(result)); logger.info('Connector has been created successfully.'); } catch (e) { @@ -96,7 +96,7 @@ async function _updateConnector(obj) { const connector = _createConnectorObject(obj) logger.info(JSON.stringify(connector)); try { - await ConnectorService.updateConnectorWithTransaction(connector) + await ConnectorService.updateConnector(connector) logger.info('Connector has been updated successfully.'); } catch (e) { logger.info(e.message) @@ -107,7 +107,7 @@ async function _deleteConnector(obj) { const connector = _createConnectorObject(obj) logger.info(JSON.stringify(connector)); try { - await ConnectorService.deleteConnectorWithTransaction(connector) + await ConnectorService.deleteConnector(connector) logger.info('Connector has been removed successfully.'); } catch (e) { logger.info(e.message) @@ -115,7 +115,7 @@ async function _deleteConnector(obj) { } async function _getConnectorList(obj) { - const list = await ConnectorService.getConnectorListWithTransaction() + const list = await ConnectorService.getConnectorList() logger.info('Connector list has been gotten successfully'); logger.info(JSON.stringify(list)); } diff --git a/src/cli/flow.js b/src/cli/flow.js index 783e87779..57e7566ac 100644 --- a/src/cli/flow.js +++ b/src/cli/flow.js @@ -109,7 +109,7 @@ const _createFlow = async function (flowData, user) { logger.info(JSON.stringify(flow)); - await FlowService.createFlowWithTransaction(flow, user, true); + await FlowService.createFlow(flow, user, true); logger.info('Flow created successfully.'); }; @@ -121,7 +121,7 @@ const _updateFlow = async function (flowData) { logger.info(JSON.stringify(flow)); const flowId = flowData.flowId; - await FlowService.updateFlowWithTransaction(flow, flowId, {}, true); + await FlowService.updateFlow(flow, flowId, {}, true); logger.info('Flow updated successfully.'); }; @@ -130,12 +130,12 @@ const _deleteFlow = async function (flowData) { const flowId = flowData.flowId; - await FlowService.deleteFlowWithTransaction(flowId, {}, true); + await FlowService.deleteFlow(flowId, {}, true); logger.info('Flow removed successfully.'); }; const _getAllFlows = async function (emptyObj) { - const flows = await FlowService.getAllFlowsWithTransaction(true); + const flows = await FlowService.getAllFlows(true); logger.info(JSON.stringify(flows)); }; diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 7ff05df3c..495e52a70 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -166,7 +166,7 @@ async function _createFog(obj, user) { logger.info(JSON.stringify(fog)); - const result = await FogService.createFogWithTransaction(fog, user, true); + const result = await FogService.createFog(fog, user, true); logger.info(JSON.stringify(result)); logger.info('Fog has been created successfully.'); } @@ -179,20 +179,20 @@ async function _updateFog(obj, user) { fog.uuid = obj.nodeId logger.info(JSON.stringify(fog)); - await FogService.updateFogWithTransaction(fog, user, true); + await FogService.updateFog(fog, user, true); logger.info('Fog has been updated successfully.'); } async function _deleteFog(obj, user) { const fog = _createFogObject(obj); logger.info(JSON.stringify(fog)); - await FogService.deleteFogWithTransaction(fog, user, true); + await FogService.deleteFog(fog, user, true); logger.info('Fog has been removed successfully'); } async function _getFogList(obj, user) { const emptyFilters = [] - const list = await FogService.getFogListWithTransaction(emptyFilters, user, true); + const list = await FogService.getFogList(emptyFilters, user, true); logger.info('Fog list has been gotten successfully'); logger.info(JSON.stringify(list)); } @@ -207,7 +207,7 @@ async function _getFog(obj, user) { async function _generateProvision(obj, user) { const fog = _createFogObject(obj); logger.info(JSON.stringify(fog)); - const res = await FogService.generateProvisioningKeyWithTransaction(fog, user, true); + const res = await FogService.generateProvisioningKey(fog, user, true); logger.info('Fog provisioning key has been generated successfully'); logger.info('Provisioning key: '+ JSON.stringify(res)); } @@ -215,7 +215,7 @@ async function _generateProvision(obj, user) { async function _setFogRebootCommand(obj, user) { const fog = _createFogObject(obj); logger.info(JSON.stringify(fog)); - await FogService.setFogRebootCommandWithTransaction(fog, user, true); + await FogService.setFogRebootCommand(fog, user, true); logger.info('Fog reboot command has been set successfully'); } @@ -225,7 +225,7 @@ async function _setFogVersionCommand(obj, user) { versionCommand: obj.versionCommand }; logger.info(JSON.stringify(fog)); - await FogService.setFogVersionCommandWithTransaction(fog, user, true); + await FogService.setFogVersionCommand(fog, user, true); logger.info('Fog version command has been set successfully'); } diff --git a/src/cli/microservice.js b/src/cli/microservice.js index d33e3cce3..2d228b51a 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -278,7 +278,7 @@ const _createRoute = async function (obj) { const arr = obj.route.split(':'); const sourceMicroserviceId = arr[0]; const destMicroserviceId = arr[1]; - await MicroserviceService.createRouteWithTransaction(sourceMicroserviceId, destMicroserviceId, {}, true); + await MicroserviceService.createRoute(sourceMicroserviceId, destMicroserviceId, {}, true); logger.info(`Microservice route with source microservice ${sourceMicroserviceId} and dest microservice ${destMicroserviceId} has been created successfully.`) } catch (e) { @@ -292,7 +292,7 @@ const _removeRoute = async function (obj) { const arr = obj.route.split(':'); const sourceMicroserviceId = arr[0]; const destMicroserviceId = arr[1]; - await MicroserviceService.deleteRouteWithTransaction(sourceMicroserviceId, destMicroserviceId, {}, true); + await MicroserviceService.deleteRoute(sourceMicroserviceId, destMicroserviceId, {}, true); logger.info(`Microservice route with source microservice ${obj.sourceMicroserviceId} and dest microservice ${obj.destMicroserviceId} has been removed successfully.`); } catch (e) { @@ -303,7 +303,7 @@ const _removeRoute = async function (obj) { const _createPortMapping = async function (obj) { logger.info(JSON.stringify(obj)); const mapping = parsePortMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_PORT_MAPPING); - await MicroserviceService.createPortMappingWithTransaction(obj.microserviceId, mapping, {}, true); + await MicroserviceService.createPortMapping(obj.microserviceId, mapping, {}, true); logger.info('Port mapping has been create successfully'); }; @@ -311,7 +311,7 @@ const _removePortMapping = async function (obj) { logger.info(JSON.stringify(obj)); try { const internalPort = parseInt(obj.internalPort); - await MicroserviceService.deletePortMappingWithTransaction(obj.microserviceId, internalPort, {}, true); + await MicroserviceService.deletePortMapping(obj.microserviceId, internalPort, {}, true); logger.info('Port mapping has been deleted successfully'); } catch(e) { logger.error(ErrorMessages.CLI.INVALID_INTERNAL_PORT); @@ -319,26 +319,26 @@ const _removePortMapping = async function (obj) { }; const _listPortMappings = async function (obj) { - const result = await MicroserviceService.getMicroservicePortMappingListWithTransaction(obj.microserviceId, {}, true); + const result = await MicroserviceService.getMicroservicePortMappingList(obj.microserviceId, {}, true); logger.info(JSON.stringify(result)); logger.info('Port mappings have been retrieved successfully'); }; const _removeMicroservice = async function (obj) { logger.info(JSON.stringify(obj)); - await MicroserviceService.deleteMicroserviceWithTransaction(obj.microserviceId, obj.cleanUp, {}, true); + await MicroserviceService.deleteMicroservice(obj.microserviceId, obj.cleanUp, {}, true); logger.info('Microservice has been removed successfully.') }; const _listMicroservices = async function () { - const result = await MicroserviceService.listMicroservicesWithTransaction({}, {}, true); + const result = await MicroserviceService.listMicroservices({}, {}, true); logger.info(JSON.stringify(result)); logger.info('Microservices have been retrieved successfully.'); }; const _getMicroservice = async function (obj) { logger.info(JSON.stringify(obj)); - const result = await MicroserviceService.getMicroserviceWithTransaction(obj.microserviceId, {}, true); + const result = await MicroserviceService.getMicroservice(obj.microserviceId, {}, true); logger.info(JSON.stringify(result, null, 2)); logger.info('Microservice has been retrieved successfully.'); }; @@ -350,7 +350,7 @@ const _createMicroservice = async function (obj) { logger.info(JSON.stringify(microservice)); - const result = await MicroserviceService.createMicroserviceOnFogWithTransaction(microservice, {}, true); + const result = await MicroserviceService.createMicroserviceOnFog(microservice, {}, true); logger.info(JSON.stringify(result)); logger.info('Microservice has been created successfully.'); }; @@ -362,7 +362,7 @@ const _updateMicroservice = async function (obj) { logger.info(JSON.stringify(microservice)); - await MicroserviceService.updateMicroserviceWithTransaction(obj.microserviceId, microservice, {}, true); + await MicroserviceService.updateMicroservice(obj.microserviceId, microservice, {}, true); logger.info('Microservice has been updated successfully.'); }; diff --git a/src/controllers/flow-controller.js b/src/controllers/flow-controller.js index 24b296fb9..ecd9a432b 100644 --- a/src/controllers/flow-controller.js +++ b/src/controllers/flow-controller.js @@ -20,11 +20,11 @@ const _createFlowEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(flow)); - return await FlowService.createFlowWithTransaction(flow, user, false) + return await FlowService.createFlow(flow, user, false) }; const _getFlowsByUserEndPoint = async function (req, user) { - return await FlowService.getUserFlowsWithTransaction(user, false) + return await FlowService.getUserFlows(user, false) }; const _getFlowEndPoint = async function (req, user) { @@ -42,7 +42,7 @@ const _updateFlowEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(flow)) logger.info("Flow id:" + JSON.stringify(flowId)) - return await FlowService.updateFlowWithTransaction(flow, flowId, user, false) + return await FlowService.updateFlow(flow, flowId, user, false) }; const _deleteFlowEndPoint = async function (req, user) { @@ -50,7 +50,7 @@ const _deleteFlowEndPoint = async function (req, user) { logger.info("Flow id:" + JSON.stringify(flowId)) - return await FlowService.deleteFlowWithTransaction(flowId, user, false) + return await FlowService.deleteFlow(flowId, user, false) }; module.exports = { diff --git a/src/controllers/iofog-controller.js b/src/controllers/iofog-controller.js index a037cbd15..c9ecd39a7 100644 --- a/src/controllers/iofog-controller.js +++ b/src/controllers/iofog-controller.js @@ -20,21 +20,21 @@ const qs = require('qs'); async function _createFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); const newFog = req.body; - return await FogService.createFogWithTransaction(newFog, user, false) + return await FogService.createFog(newFog, user, false) } async function _updateFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); const updateFog = req.body; updateFog.uuid = req.params.uuid; - return await FogService.updateFogWithTransaction(updateFog, user, false) + return await FogService.updateFog(updateFog, user, false) } async function _deleteFog(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); const deleteFog = {}; deleteFog.uuid = req.params.uuid; - return await FogService.deleteFogWithTransaction(deleteFog, user, false) + return await FogService.deleteFog(deleteFog, user, false) } async function _getFog(req, user) { @@ -47,14 +47,14 @@ async function _getFog(req, user) { async function _getFogList(req, user) { logger.info("Parameters:" + JSON.stringify(req.query)); const query = qs.parse(req.query) - return await FogService.getFogListWithTransaction(query.filters, user, false) + return await FogService.getFogList(query.filters, user, false) } async function _generateProvisioningKey(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); const fog = {}; fog.uuid = req.params.uuid; - return await FogService.generateProvisioningKeyWithTransaction(fog, user, false) + return await FogService.generateProvisioningKey(fog, user, false) } async function _setFogVersionCommand(req, user) { @@ -62,14 +62,14 @@ async function _setFogVersionCommand(req, user) { const fogVersionCommand = {}; fogVersionCommand.uuid = req.params.uuid; fogVersionCommand.versionCommand = req.params.versionCommand; - return await FogService.setFogVersionCommandWithTransaction(fogVersionCommand, user, false) + return await FogService.setFogVersionCommand(fogVersionCommand, user, false) } async function _setFogRebootCommand(req, user) { logger.info("Parameters:" + JSON.stringify(req.body)); const fog = {}; fog.uuid = req.params.uuid; - return await FogService.setFogRebootCommandWithTransaction(fog, user, false) + return await FogService.setFogRebootCommand(fog, user, false) } async function _getHalHardwareInfo(req, user) { diff --git a/src/controllers/microservices-controller.js b/src/controllers/microservices-controller.js index 65ae7e30d..4a0746fa2 100644 --- a/src/controllers/microservices-controller.js +++ b/src/controllers/microservices-controller.js @@ -20,7 +20,7 @@ const _createMicroservicesOnFogEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(microservice)); - return await MicroservicesService.createMicroserviceOnFogWithTransaction(microservice, user, false) + return await MicroservicesService.createMicroserviceOnFog(microservice, user, false) }; const _getMicroserviceEndPoint = async function (req, user) { @@ -28,7 +28,7 @@ const _getMicroserviceEndPoint = async function (req, user) { logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); - return await MicroservicesService.getMicroserviceWithTransaction(microserviceUuid, user, false) + return await MicroservicesService.getMicroservice(microserviceUuid, user, false) }; const _updateMicroserviceEndPoint = async function (req, user) { @@ -38,7 +38,7 @@ const _updateMicroserviceEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(microservice)); logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); - return await MicroservicesService.updateMicroserviceWithTransaction(microserviceUuid, microservice, user, false) + return await MicroservicesService.updateMicroservice(microserviceUuid, microservice, user, false) }; const _deleteMicroserviceEndPoint = async function (req, user) { @@ -48,7 +48,7 @@ const _deleteMicroserviceEndPoint = async function (req, user) { logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); logger.info("Delete with cleanup:" + JSON.stringify(deleteWithCleanUp)); - return await MicroservicesService.deleteMicroserviceWithTransaction(microserviceUuid, deleteWithCleanUp, user, false) + return await MicroservicesService.deleteMicroservice(microserviceUuid, deleteWithCleanUp, user, false) }; const _getMicroservicesByFlowEndPoint = async function (req, user) { @@ -56,41 +56,41 @@ const _getMicroservicesByFlowEndPoint = async function (req, user) { logger.info("Flow id:" + flowId); - return await MicroservicesService.listMicroservicesWithTransaction(flowId, user, false) + return await MicroservicesService.listMicroservices(flowId, user, false) }; async function _createMicroserviceRoute(req, user) { const sourceUuid = req.params.uuid; const distUuid = req.params.receiverUuid; logger.info(`Creating route from ${sourceUuid} to ${distUuid}`); - return await MicroservicesService.createRouteWithTransaction(sourceUuid, distUuid, user, false) + return await MicroservicesService.createRoute(sourceUuid, distUuid, user, false) } async function _deleteMicroserviceRoute(req, user) { const sourceUuid = req.params.uuid; const distUuid = req.params.receiverUuid; logger.info(`Creating route from ${sourceUuid} to ${distUuid}`); - return await MicroservicesService.deleteRouteWithTransaction(sourceUuid, distUuid, user, false) + return await MicroservicesService.deleteRoute(sourceUuid, distUuid, user, false) } async function _createMicroservicePortMapping(req, user) { const uuid = req.params.uuid; const portMappingData = req.body; logger.info(`Creating port mapping for ${uuid}`); - return await MicroservicesService.createPortMappingWithTransaction(uuid, portMappingData, user, false) + return await MicroservicesService.createPortMapping(uuid, portMappingData, user, false) } async function _deleteMicroservicePortMapping(req, user) { const uuid = req.params.uuid; const internalPort = req.params.internalPort; logger.info(`Deleting port mapping for ${uuid}`); - return await MicroservicesService.deletePortMappingWithTransaction(uuid, internalPort, user, false) + return await MicroservicesService.deletePortMapping(uuid, internalPort, user, false) } async function _getMicroservicePortMappingList(req, user) { const uuid = req.params.uuid; logger.info(`Getting all port mappings for ${uuid}`); - const ports = await MicroservicesService.getMicroservicePortMappingListWithTransaction(uuid, user, false); + const ports = await MicroservicesService.getMicroservicePortMappingList(uuid, user, false); return { ports: ports } diff --git a/src/services/connector-service.js b/src/services/connector-service.js index 82b85aac6..f1a53555b 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -203,10 +203,10 @@ async function closePortOnConnector(connector, ports, transaction) { } module.exports = { - createConnectorWithTransaction: TransactionDecorator.generateTransaction(_createConnector), - updateConnectorWithTransaction: TransactionDecorator.generateTransaction(_updateConnector), - deleteConnectorWithTransaction: TransactionDecorator.generateTransaction(_deleteConnector), - getConnectorListWithTransaction: TransactionDecorator.generateTransaction(_getConnectorList), + createConnector: TransactionDecorator.generateTransaction(_createConnector), + updateConnector: TransactionDecorator.generateTransaction(_updateConnector), + deleteConnector: TransactionDecorator.generateTransaction(_deleteConnector), + getConnectorList: TransactionDecorator.generateTransaction(_getConnectorList), openPortOnRandomConnector: openPortOnRandomConnector, closePortOnConnector: closePortOnConnector } \ No newline at end of file diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 9f72706a9..7d718840a 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -30,7 +30,7 @@ const mime = require('mime'); const changeMicroserviceStraceState = async function (id, data, user, isCLI, transaction) { validator.validate(data, validator.schemas.straceStateUpdate); - const microservice = await MicroserviceService.getMicroserviceWithTransaction(id, user, isCLI, transaction); + const microservice = await MicroserviceService.getMicroservice(id, user, isCLI, transaction); if (microservice.iofogUuid === null) { throw new Errors.ValidationError(ErrorMessages.STRACE_WITHOUT_FOG); } diff --git a/src/services/flow-service.js b/src/services/flow-service.js index d1f2458eb..a2d5a775e 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -145,11 +145,11 @@ const _checkForDuplicateName = async function (name, item, userId, transaction) }; module.exports = { - createFlowWithTransaction: TransactionDecorator.generateTransaction(_createFlow), - deleteFlowWithTransaction: TransactionDecorator.generateTransaction(_deleteFlow), - updateFlowWithTransaction: TransactionDecorator.generateTransaction(_updateFlow), + createFlow: TransactionDecorator.generateTransaction(_createFlow), + deleteFlow: TransactionDecorator.generateTransaction(_deleteFlow), + updateFlow: TransactionDecorator.generateTransaction(_updateFlow), getFlowWithTransaction: TransactionDecorator.generateTransaction(_getFlow), - getUserFlowsWithTransaction: TransactionDecorator.generateTransaction(_getUserFlows), - getAllFlowsWithTransaction: TransactionDecorator.generateTransaction(_getAllFlows), + getUserFlows: TransactionDecorator.generateTransaction(_getUserFlows), + getAllFlows: TransactionDecorator.generateTransaction(_getAllFlows), getFlow: _getFlow }; diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 99c36a5c2..c2f39289f 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -455,14 +455,14 @@ async function _processDeleteCommand(fog, transaction) { } module.exports = { - createFogWithTransaction: TransactionDecorator.generateTransaction(_createFog), - updateFogWithTransaction: TransactionDecorator.generateTransaction(_updateFog), - deleteFogWithTransaction: TransactionDecorator.generateTransaction(_deleteFog), + createFog: TransactionDecorator.generateTransaction(_createFog), + updateFog: TransactionDecorator.generateTransaction(_updateFog), + deleteFog: TransactionDecorator.generateTransaction(_deleteFog), getFogWithTransaction: TransactionDecorator.generateTransaction(_getFog), - getFogListWithTransaction: TransactionDecorator.generateTransaction(_getFogList), - generateProvisioningKeyWithTransaction: TransactionDecorator.generateTransaction(_generateProvisioningKey), - setFogVersionCommandWithTransaction: TransactionDecorator.generateTransaction(_setFogVersionCommand), - setFogRebootCommandWithTransaction: TransactionDecorator.generateTransaction(_setFogRebootCommand), + getFogList: TransactionDecorator.generateTransaction(_getFogList), + generateProvisioningKey: TransactionDecorator.generateTransaction(_generateProvisioningKey), + setFogVersionCommand: TransactionDecorator.generateTransaction(_setFogVersionCommand), + setFogRebootCommand: TransactionDecorator.generateTransaction(_setFogRebootCommand), getHalHardwareInfo: TransactionDecorator.generateTransaction(_getHalHardwareInfo), getHalUsbInfo: TransactionDecorator.generateTransaction(_getHalUsbInfo), getFog: _getFog diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 830544eff..0e58adf4f 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -790,17 +790,16 @@ async function _buildLink(protocol, ip, port) { } module.exports = { - createMicroserviceOnFogWithTransaction: TransactionDecorator.generateTransaction(_createMicroserviceOnFog), - listMicroservicesWithTransaction: TransactionDecorator.generateTransaction(_listMicroservices), - getMicroserviceWithTransaction: TransactionDecorator.generateTransaction(_getMicroservice), - updateMicroserviceWithTransaction: TransactionDecorator.generateTransaction(_updateMicroservice), - deleteMicroserviceWithTransaction: TransactionDecorator.generateTransaction(_deleteMicroservice), - createRouteWithTransaction: TransactionDecorator.generateTransaction(_createRoute), - deleteRouteWithTransaction: TransactionDecorator.generateTransaction(_deleteRoute), - createPortMappingWithTransaction: TransactionDecorator.generateTransaction(_createPortMapping), - getMicroservicePortMappingListWithTransaction: TransactionDecorator.generateTransaction(_getPortMappingList), - deletePortMappingWithTransaction: TransactionDecorator.generateTransaction(_deletePortMapping), + createMicroserviceOnFog: TransactionDecorator.generateTransaction(_createMicroserviceOnFog), + listMicroservices: TransactionDecorator.generateTransaction(_listMicroservices), + getMicroservice: TransactionDecorator.generateTransaction(_getMicroservice), + updateMicroservice: TransactionDecorator.generateTransaction(_updateMicroservice), + deleteMicroservice: TransactionDecorator.generateTransaction(_deleteMicroservice), + createRoute: TransactionDecorator.generateTransaction(_createRoute), + deleteRoute: TransactionDecorator.generateTransaction(_deleteRoute), + createPortMapping: TransactionDecorator.generateTransaction(_createPortMapping), + getMicroservicePortMappingList: TransactionDecorator.generateTransaction(_getPortMappingList), + deletePortMapping: TransactionDecorator.generateTransaction(_deletePortMapping), getPhysicalConections: getPhysicalConections, - listMicroservices: _listMicroservices, deleteNotRunningMicroservices: _deleteNotRunningMicroservices }; From 21307ac19669630ca2875e4f916c760527af5a2c Mon Sep 17 00:00:00 2001 From: dbusel Date: Fri, 9 Nov 2018 16:46:58 +0300 Subject: [PATCH 42/91] Rename updatedBy/createdBy field to userId (#335) * rename updatedBy to userId * rename updatedBy to userId * resolve pr comments * remove duplicates --- ...microservice-rename-updatedBy-to-userId.js | 11 +++++++ ...service-port-rename-updatedBy-to-userId.js | 11 +++++++ .../20181109132723-flow-remove-updatedBy.js | 14 ++++++++ src/sequelize/models/flow.js | 9 ------ src/sequelize/models/microservice.js | 4 +-- src/sequelize/models/microserviceport.js | 4 +-- src/sequelize/models/user.js | 8 +++++ src/services/diagnostic-service.js | 4 +-- src/services/flow-service.js | 1 - src/services/iofog-service.js | 8 ++--- src/services/microservices-service.js | 32 +++++++++---------- 11 files changed, 70 insertions(+), 36 deletions(-) create mode 100644 src/sequelize/migrations/20181109132609-microservice-rename-updatedBy-to-userId.js create mode 100644 src/sequelize/migrations/20181109132704-microservice-port-rename-updatedBy-to-userId.js create mode 100644 src/sequelize/migrations/20181109132723-flow-remove-updatedBy.js diff --git a/src/sequelize/migrations/20181109132609-microservice-rename-updatedBy-to-userId.js b/src/sequelize/migrations/20181109132609-microservice-rename-updatedBy-to-userId.js new file mode 100644 index 000000000..5a1789d81 --- /dev/null +++ b/src/sequelize/migrations/20181109132609-microservice-rename-updatedBy-to-userId.js @@ -0,0 +1,11 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.renameColumn('Microservices', 'updated_by', 'user_id') + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.renameColumn('Microservices', 'user_id', 'updated_by') + } +}; diff --git a/src/sequelize/migrations/20181109132704-microservice-port-rename-updatedBy-to-userId.js b/src/sequelize/migrations/20181109132704-microservice-port-rename-updatedBy-to-userId.js new file mode 100644 index 000000000..bb29277f6 --- /dev/null +++ b/src/sequelize/migrations/20181109132704-microservice-port-rename-updatedBy-to-userId.js @@ -0,0 +1,11 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.renameColumn('MicroservicePorts', 'updated_by', 'user_id') + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.renameColumn('MicroservicePorts', 'user_id', 'updated_by') + } +}; diff --git a/src/sequelize/migrations/20181109132723-flow-remove-updatedBy.js b/src/sequelize/migrations/20181109132723-flow-remove-updatedBy.js new file mode 100644 index 000000000..85d4fd00f --- /dev/null +++ b/src/sequelize/migrations/20181109132723-flow-remove-updatedBy.js @@ -0,0 +1,14 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.removeColumn('Flows', 'updated_by') + }, + + down: (queryInterface, Sequelize) => { + return queryInterface.addColumn('Flows', + 'updated_by', + Sequelize.INTEGER + ) + } +}; diff --git a/src/sequelize/models/flow.js b/src/sequelize/models/flow.js index b12f7942f..a4e8439f5 100644 --- a/src/sequelize/models/flow.js +++ b/src/sequelize/models/flow.js @@ -39,15 +39,6 @@ module.exports = (sequelize, DataTypes) => { onDelete: 'cascade' }); - Flow.belongsTo(models.User, { - foreignKey: { - name: 'updatedById', - field: 'updated_by' - }, - as: 'updatedBy', - onDelete: 'set null' - }); - Flow.hasMany(models.Microservice, { foreignKey: { name: 'flowId', diff --git a/src/sequelize/models/microservice.js b/src/sequelize/models/microservice.js index 5e64cb234..a96c22d32 100644 --- a/src/sequelize/models/microservice.js +++ b/src/sequelize/models/microservice.js @@ -92,8 +92,8 @@ module.exports = (sequelize, DataTypes) => { Microservice.belongsTo(models.User, { foreignKey: { - name: 'updatedBy', - field: 'updated_by' + name: 'userId', + field: 'user_id' }, as: 'user', onDelete: 'cascade' diff --git a/src/sequelize/models/microserviceport.js b/src/sequelize/models/microserviceport.js index f397d6ebe..cca3aeedc 100644 --- a/src/sequelize/models/microserviceport.js +++ b/src/sequelize/models/microserviceport.js @@ -37,8 +37,8 @@ module.exports = (sequelize, DataTypes) => { MicroservicePort.belongsTo(models.User, { foreignKey: { - name: 'updatedBy', - field: 'updated_by' + name: 'userId', + field: 'user_id' }, as: 'user', onDelete: 'cascade' diff --git a/src/sequelize/models/user.js b/src/sequelize/models/user.js index 519535f4b..f18b1fa83 100644 --- a/src/sequelize/models/user.js +++ b/src/sequelize/models/user.js @@ -63,6 +63,14 @@ module.exports = (sequelize, DataTypes) => { as: 'fog' }); + User.hasMany(models.Microservice, { + foreignKey: { + name: 'userId', + field: 'user_id' + }, + as: 'microservice' + }); + }; return User; }; \ No newline at end of file diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 7d718840a..8c35344be 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -84,7 +84,7 @@ const postMicroserviceImageSnapshotCreate = async function (microserviceUuid, us : { uuid: microserviceUuid, - updatedBy: user.id + userId: user.id }; @@ -108,7 +108,7 @@ const getMicroserviceImageSnapshot = async function (microserviceUuid, user, isC : { uuid: microserviceUuid, - updatedBy: user.id + userId: user.id }; const microservice = await MicroserviceManager.findOneWithDependencies(where, {}, transaction); if (microservice.iofogUuid === null) { diff --git a/src/services/flow-service.js b/src/services/flow-service.js index a2d5a775e..f22defb59 100644 --- a/src/services/flow-service.js +++ b/src/services/flow-service.js @@ -84,7 +84,6 @@ const _updateFlow = async function (flowData, flowId, user, isCLI, transaction) name: flowData.name, description: flowData.description, isActivated: flowData.isActivated, - updatedBy: user.id }; const updateFlowData = AppHelper.deleteUndefinedFields(flow); diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index c2f39289f..94e078e40 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -78,7 +78,7 @@ async function _createFog(fogData, user, isCli, transaction) { iofogUuid: fog.uuid, rootHostAccess: true, logSize: 50, - updatedBy: user.id, + userId: user.id, configLastUpdated: Date.now() }; @@ -97,7 +97,7 @@ async function _createFog(fogData, user, isCli, transaction) { iofogUuid: fog.uuid, rootHostAccess: true, logSize: 50, - updatedBy: user.id, + userId: user.id, configLastUpdated: Date.now() }; @@ -174,7 +174,7 @@ async function _updateFog(fogData, user, isCli, transaction) { iofogUuid: fogData.uuid, rootHostAccess: true, logSize: 50, - updatedBy: user.id, + userId: user.id, configLastUpdated: Date.now() }; @@ -206,7 +206,7 @@ async function _updateFog(fogData, user, isCli, transaction) { iofogUuid: fogData.uuid, rootHostAccess: true, logSize: 50, - updatedBy: user.id, + userId: user.id, configLastUpdated: Date.now() }; diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 0e58adf4f..7cee26c0f 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -99,7 +99,7 @@ const _createMicroservice = async function (microserviceData, user, isCLI, trans iofogUuid: microserviceData.iofogUuid, rootHostAccess: microserviceData.rootHostAccess, logSize: microserviceData.logLimit, - updatedBy: user.id + userId: user.id }; newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); @@ -150,14 +150,14 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, rootHostAccess: microserviceData.rootHostAccess, logSize: microserviceData.logLimit, volumeMappings: microserviceData.volumeMappings, - updatedBy: user.id + userId: user.id }; const microserviceDataUpdate = AppHelper.deleteUndefinedFields(microserviceToUpdate); const microservice = await MicroserviceManager.findOne({ uuid: microserviceUuid, - updatedBy: user.id + userId: user.id }, transaction); if (microserviceDataUpdate.name) { @@ -208,7 +208,7 @@ const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, ? { uuid: microserviceUuid, - updatedBy: user.id + userId: user.id } : { @@ -257,12 +257,12 @@ const _checkForDuplicateName = async function (name, item, userId, transaction) { name: name, uuid: {[Op.ne]: item.id}, - updatedBy: userId + userId: userId } : { name: name, - updatedBy: userId + userId: userId }; const result = await MicroserviceManager.findOne(where, transaction); @@ -292,7 +292,7 @@ const _validateMicroserviceOnGet = async function (userId, microserviceUuid, tra async function _createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { const sourceWhere = isCLI ? {uuid: sourceMicroserviceUuid} - : {uuid: sourceMicroserviceUuid, updatedBy: user.id}; + : {uuid: sourceMicroserviceUuid, userId: user.id}; const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction); if (!sourceMicroservice) { @@ -301,7 +301,7 @@ async function _createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, const destWhere = isCLI ? {uuid: destMicroserviceUuid} - : {uuid: destMicroserviceUuid, updatedBy: user.id}; + : {uuid: destMicroserviceUuid, userId: user.id}; const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction); if (!destMicroservice) { @@ -447,7 +447,7 @@ async function _createNetworkMicroserviceForMaster(masterMicroservice, sourceNet iofogUuid: masterMicroservice.iofogUuid, rootHostAccess: false, logSize: 50, - updatedBy: user.id, + userId: user.id, configLastUpdated: Date.now() }; @@ -468,7 +468,7 @@ async function _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, d async function _deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { const sourceWhere = isCLI ? {uuid: sourceMicroserviceUuid} - : {uuid: sourceMicroserviceUuid, updatedBy: user.id}; + : {uuid: sourceMicroserviceUuid, userId: user.id}; const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction); if (!sourceMicroservice) { @@ -477,7 +477,7 @@ async function _deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, const destWhere = isCLI ? {uuid: destMicroserviceUuid} - : {uuid: destMicroserviceUuid, updatedBy: user.id}; + : {uuid: destMicroserviceUuid, userId: user.id}; const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction); if (!destMicroservice) { @@ -527,7 +527,7 @@ async function _createPortMapping(microserviceUuid, portMappingData, user, isCLI const where = isCLI ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, updatedBy: user.id}; + : {uuid: microserviceUuid, userId: user.id}; const microservice = await MicroserviceManager.findOne(where, transaction) if (!microservice) { @@ -567,7 +567,7 @@ async function _createSimplePortMapping(microservice, portMappingData, user, tra isPublic: false, portInternal: portMappingData.internal, portExternal: portMappingData.external, - updatedBy: user.id, + userId: user.id, microserviceUuid: microservice.uuid } @@ -625,7 +625,7 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us isPublic: true, portInternal: portMappingData.internal, portExternal: portMappingData.external, - updatedBy: user.id, + userId: user.id, microserviceUuid: microservice.uuid } @@ -663,7 +663,7 @@ async function _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, async function _deletePortMapping(microserviceUuid, internalPort, user, isCLI, transaction) { const where = isCLI ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, updatedBy: user.id} + : {uuid: microserviceUuid, userId: user.id} const microservice = await MicroserviceManager.findOne(where, transaction); if (!microservice) { @@ -748,7 +748,7 @@ async function _buildPortsList(portsPairs, transaction) { async function _getPortMappingList(microserviceUuid, user, isCLI, transaction) { const where = isCLI ? {uuid: microserviceUuid} - : {uuid: microserviceUuid, updatedBy: user.id}; + : {uuid: microserviceUuid, userId: user.id}; const microservice = await MicroserviceManager.findOne(where, transaction) if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) From cd540e58ffb29a363cc24628a8b44bedc94c1fcd Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 9 Nov 2018 16:50:23 +0300 Subject: [PATCH 43/91] EWC-338 fixed email activation field in config CLI (#337) --- src/cli/config.js | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) diff --git a/src/cli/config.js b/src/cli/config.js index 6a1cf50f7..4b7258422 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -21,7 +21,7 @@ const logger = require('../logger'); class Config extends BaseCLIHandler { constructor() { - super() + super(); this.name = constants.CMD_CONFIG; this.commandDefinitions = [ @@ -31,20 +31,19 @@ class Config extends BaseCLIHandler { { name: 'ssl-key', alias: 'k', type: String, description: 'Path to SSL key file', group: constants.CMD_ADD }, { name: 'intermediate-cert', alias: 'i', type: String, description: 'Path to SSL intermediate certificate file', group: constants.CMD_ADD }, { name: 'home-url', alias: 'h', type: String, description: 'Home page url for email activation links', group: constants.CMD_ADD }, - { name: 'email-activation-on', alias: 'm', type: Boolean, description: 'Email activation required', group: constants.CMD_ADD }, - { name: 'email-activation-off', alias: 'n', type: Boolean, description: 'Email activation not required', group: constants.CMD_ADD }, { name: 'email-address', alias: 'a', type: String, description: 'Email address to send activations from', group: constants.CMD_ADD }, { name: 'email-password', alias: 'w', type: String, description: 'Email password to send activations from', group: constants.CMD_ADD }, { name: 'email-service', alias: 's', type: String, description: 'Email service to send activations', group: constants.CMD_ADD }, { name: 'log-dir', alias: 'd', type: String, description: 'Log files directory', group: constants.CMD_ADD }, { name: 'log-size', alias: 'z', type: Number, description: 'Log files size (MB)', group: constants.CMD_ADD }, - { name: 'on', alias: 'o', type: Boolean, description: 'Enable dev mode', group: constants.CMD_DEV_MODE }, - { name: 'off', alias: 'f', type: Boolean, description: 'Disable dev mode', group: constants.CMD_DEV_MODE } - ] + { name: 'on', alias: 'o', type: Boolean, description: 'Enable', group: [constants.CMD_DEV_MODE, constants.CMD_EMAIL_ACTIVATION] }, + { name: 'off', alias: 'f', type: Boolean, description: 'Disable', group: [constants.CMD_DEV_MODE, constants.CMD_EMAIL_ACTIVATION] }, + ]; this.commands = { [constants.CMD_ADD]: 'Add a new config value.', [constants.CMD_LIST]: 'Display current config.', - [constants.CMD_DEV_MODE]: 'dev mode config.' + [constants.CMD_DEV_MODE]: 'Dev mode config.', + [constants.CMD_EMAIL_ACTIVATION]: 'Email activation config.', } } @@ -61,6 +60,9 @@ class Config extends BaseCLIHandler { case constants.CMD_DEV_MODE: await _executeCase(configCommand, constants.CMD_DEV_MODE, _changeDevModeState); break; + case constants.CMD_EMAIL_ACTIVATION: + await _executeCase(configCommand, constants.CMD_EMAIL_ACTIVATION, _changeEmailActivationState); + break; case constants.CMD_HELP: default: return this.help([], true, false) @@ -121,16 +123,6 @@ const _addConfigOption = async function (options) { onSuccess(); }); - updateConfig(options.emailActivationOn, 'email-activation-on', 'Email:ActivationEnabled', (onSuccess) => { - config.set('Email:ActivationEnabled', true); - onSuccess(); - }); - - updateConfig(options.emailActivationOff, 'email-activation-off', 'Email:ActivationEnabled', (onSuccess) => { - config.set('Email:ActivationEnabled', false); - onSuccess(); - }); - updateConfig(options.homeUrl, 'home-url', 'Email:HomeUrl', (onSuccess) => { config.set('Email:HomeUrl', options.homeUrl); onSuccess(); @@ -199,13 +191,20 @@ const _listConfigOptions = function () { const result = Object.keys(configuration) .filter(key => configuration[key] != null) .map(key => `${key}: ${configuration[key]}`) - .join('\n') + .join('\n'); console.log(result) }; const _changeDevModeState = function (options) { const enableDevMode = AppHelper.validateBooleanCliOptions(options.on, options.off); config.set('Server:DevMode', enableDevMode) + logger.info('Dev mode state updated successfully.') +}; + +const _changeEmailActivationState = function (options) { + const enableEmailActivation = AppHelper.validateBooleanCliOptions(options.on, options.off); + config.set('Email:ActivationEnabled', enableEmailActivation); + logger.info('Email activation state updated successfully.') }; module.exports = new Config(); \ No newline at end of file From 33a204704185d46693f1467663d3a2aa77fd6224 Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Fri, 9 Nov 2018 16:13:59 +0200 Subject: [PATCH 44/91] small fix (#338) --- src/services/diagnostic-service.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 8c35344be..171c71786 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -94,7 +94,9 @@ const postMicroserviceImageSnapshotCreate = async function (microserviceUuid, us throw new Errors.ValidationError(ErrorMessages.IMAGE_SNAPSHOT_WITHOUT_FOG); } - let imageSnapshot = 'get_image'; + const microserviceToUpdate = { + imageSnapshot: 'get_image' + }; await MicroserviceManager.update({uuid: microservice.uuid}, microserviceToUpdate, transaction); await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.imageSnapshot, transaction); From f39a6d21278103137c20a757431a9955d7f101c9 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Fri, 9 Nov 2018 17:46:23 +0300 Subject: [PATCH 45/91] transaction validation in decorator (#336) * get fog list params in query * transaction validation --- src/decorators/transaction-decorator.js | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/src/decorators/transaction-decorator.js b/src/decorators/transaction-decorator.js index e51902491..4408ad532 100644 --- a/src/decorators/transaction-decorator.js +++ b/src/decorators/transaction-decorator.js @@ -14,16 +14,21 @@ const db = require('./../sequelize/models'); const retry = require('retry-as-promised'); const sequelize = db.sequelize; +// const Transaction = require('sequelize/lib/transaction'); function transaction(f) { - return function () { + return async function() { const fArgs = Array.prototype.slice.call(arguments); // To be removed when transactions concurrency issue fixed + // if (fArgs[fArgs.length - 1] instanceof Transaction) { + // return await f.apply(this, fArgs); + // } else { return f.apply(this, fArgs) - // return sequelize.transaction(async (t) => { - // fArgs.push(t); - // return await f.apply(this, fArgs); - // }) + // return sequelize.transaction(async (t) => { + // fArgs.push(t); + // return await f.apply(this, fArgs); + // }) + // } } } From d7ad23d13f14398acbfd1ad3ad6d7a70c236e312 Mon Sep 17 00:00:00 2001 From: Railag Date: Fri, 9 Nov 2018 17:59:50 +0300 Subject: [PATCH 46/91] updated postman collection for microservice update endpoint (#339) --- tests/Controller Testing.postman_collection.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 6ccc116c0..a6ac512d2 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -3419,7 +3419,7 @@ ], "body": { "mode": "raw", - "raw": "{\n \"name\": \"name3\",\n \"config\": \"string\",\n \"needUpdate\": true,\n \"rebuild\": true,\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logLimit\": 0,\n \"imageSnapshot\": \"string\",\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ]\n}\n" + "raw": "{\n \"name\": \"name3\",\n \"config\": \"string\",\n \"rebuild\": true,\n \"iofogUuid\": \"{{node-id}}\",\n \"rootHostAccess\": true,\n \"logSize\": 0,\n \"volumeMappings\": [\n {\n \"hostDestination\": \"/var/dest\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }\n ]\n}" }, "url": { "raw": "{{host}}/api/v3/microservices/{{ms-id}}", From 8f78ad29b4166b237fb1c738a40e17464a32ab68 Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Fri, 9 Nov 2018 18:54:05 +0200 Subject: [PATCH 47/91] Ashpak/bug change content type for save image (#341) * small fix * fix --- src/services/agent-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/agent-service.js b/src/services/agent-service.js index cd1635ac1..9c6d9f0bf 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -382,7 +382,7 @@ const getImageSnapshot = async function (fog, transaction) { }; const putImageSnapshot = async function (req, fog, transaction) { - if (req.headers['content-type'] !== 'application/zip') { + if (req.headers['content-type'].includes('multipart/form-data')) { throw new Errors.ValidationError(ErrorMessages.INVALID_CONTENT_TYPE); } From 7079e1b1be4994798e285fbb84a8660ce9d03afb Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Mon, 12 Nov 2018 13:18:06 +0300 Subject: [PATCH 48/91] Epankou/feature volume mapping ewc 332 (#340) * volume mapping & delete with clean up * volume mapping & delete with clean up * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js --- specs/swagger.yml | 153 ++++++++++++++-- src/cli/catalog.js | 2 +- src/cli/connector.js | 2 +- src/cli/diagnostics.js | 7 +- src/cli/flow.js | 8 +- src/cli/iofog.js | 18 +- src/cli/microservice.js | 111 ++++++++---- src/cli/tunnel.js | 24 ++- src/cli/user.js | 5 +- src/controllers/microservices-controller.js | 62 +++++-- src/helpers/constants.js | 3 + src/helpers/error-messages.js | 3 + src/routes/microservices.js | 110 +++++++++++- src/schemas/microservice.js | 13 +- .../managers/volume-mapping-manager.js | 14 +- src/services/microservices-service.js | 87 ++++++++- ...Controller Testing.postman_collection.json | 166 ++++++++++++++++-- 17 files changed, 666 insertions(+), 122 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 47dd9b939..57d7fb063 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -1334,11 +1334,15 @@ paths: description: Microservice Uuid required: true type: string - - in: query - name: withCleanUp - description: Delete with cleanup - required: true - type: boolean + - in: body + name: WithCleanupOption + description: Delete option + required: false + schema: + type: object + properties: + withCleanup: + type: boolean responses: '204': description: Success @@ -1346,6 +1350,8 @@ paths: X-Timestamp: type: number description: FogController server timestamp + '400': + description: Bad Request '401': description: Not Authorized '404': @@ -1532,6 +1538,119 @@ paths: description: Not Found '500': description: Internal Server Error + '/microservices/{uuid}/volume-mapping': + post: + tags: + - Microservices + description: Creates a volume mapping for microservice + operationId: createMicroserviceVolumeMapping + parameters: + - in: header + name: Authorization + description: User Token + required: true + type: string + - in: path + name: uuid + description: Microservice Uuid + required: true + type: string + - in: body + name: volumeMappingData + description: information about volume mapping + required: true + schema: + $ref: '#/definitions/VolumeMapping' + responses: + '201': + description: Created + schema: + type: object + properties: + id: + type: number + headers: + X-Timestamp: + type: number + description: FogController server timestamp + '400': + description: Not Valid + '401': + description: Not Authorized + '404': + description: Not Found + '500': + description: Internal Server Error + get: + tags: + - Microservices + description: Get a volume mapping list for microservice + operationId: getMicroserviceVolumeMapping + parameters: + - in: header + name: Authorization + description: User Token + required: true + type: string + - in: path + name: uuid + description: Microservice Uuid + required: true + type: string + responses: + '200': + description: Success + schema: + type: array + items: + $ref: '#/definitions/VolumeMappingRequest' + headers: + X-Timestamp: + type: number + description: FogController server timestamp + '401': + description: Not Authorized + '404': + description: Not Found + '500': + description: Internal Server Error + '/microservices/{uuid}/volume-mapping/{id}': + delete: + tags: + - Microservices + description: Deletes a volume mapping for microservice + operationId: deleteMicroserviceVolumeMapping + parameters: + - in: header + name: Authorization + description: User Token + required: true + type: string + - in: path + name: uuid + description: Microservice Uuid + required: true + type: string + - in: path + name: id + description: Volume id + required: true + type: string + responses: + '204': + description: Success + headers: + X-Timestamp: + type: number + description: FogController server timestamp + '400': + description: Not Valid + '401': + description: Not Authorized + '404': + description: Not Found + '500': + description: Internal Server Error '/microservices/{id}/image-snapshot': post: tags: @@ -2634,7 +2753,7 @@ definitions: VolumeMappings: type: array items: - $ref: '#/definitions/VolumeMappingAgentRequest' + $ref: '#/definitions/VolumeMapping' imageSnapshot: type: string removeWithCleanUp: @@ -2645,7 +2764,7 @@ definitions: type: array items: type: string - VolumeMappingAgentRequest: + VolumeMapping: type: object properties: hostDestination: @@ -2657,6 +2776,20 @@ definitions: accessMode: type: string example: rw + VolumeMappingRequest: + type: object + properties: + id: + type: number + hostDestination: + type: string + example: /var/dest + containerDestination: + type: string + example: /var/dest + accessMode: + type: string + example: rw PortMappingsResponse: type: object properties: @@ -2889,7 +3022,7 @@ definitions: volumeMappings: type: array items: - $ref: '#/definitions/VolumeMappingAgentRequest' + $ref: '#/definitions/VolumeMappingRequest' ports: type: array items: @@ -2916,7 +3049,7 @@ definitions: volumeMappings: type: array items: - $ref: '#/definitions/VolumeMappingAgentRequest' + $ref: '#/definitions/VolumeMapping' ports: type: array items: @@ -2943,7 +3076,7 @@ definitions: volumeMappings: type: array items: - $ref: '#/definitions/VolumeMappingAgentRequest' + $ref: '#/definitions/VolumeMapping' IOFogNodeTunnelStatusInfoResponse: type: object properties: diff --git a/src/cli/catalog.js b/src/cli/catalog.js index b8b321fb3..9a6b50152 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -167,7 +167,7 @@ const _deleteCatalogItem = async function (obj) { const _listCatalogItems = async function () { const result = await CatalogItemService.listCatalogItems({}, true); - logger.info(JSON.stringify(result)); + logger.info(JSON.stringify(result, null, 2)); logger.info('Catalog items have been successfully retrieved.'); }; diff --git a/src/cli/connector.js b/src/cli/connector.js index 0c2903c93..a2f76102f 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -116,8 +116,8 @@ async function _deleteConnector(obj) { async function _getConnectorList(obj) { const list = await ConnectorService.getConnectorList() + logger.info(JSON.stringify(list, null, 2)); logger.info('Connector list has been gotten successfully'); - logger.info(JSON.stringify(list)); } function _createConnectorObject(cliData) { diff --git a/src/cli/diagnostics.js b/src/cli/diagnostics.js index 434b54ddd..a069abb2f 100644 --- a/src/cli/diagnostics.js +++ b/src/cli/diagnostics.js @@ -130,21 +130,22 @@ const _getMicroserviceStraceData = async function (obj) { logger.info(JSON.stringify(obj)); const result = await DiagnosticService.getMicroserviceStraceData(obj.microserviceId, {format: obj.format}, {}, true); - logger.info(JSON.stringify(result)); + logger.info(JSON.stringify(result, null, 2)); + logger.info('Microservice strace data has been retrieved successfully.'); }; const _postMicroserviceStraceDataToFtp = async function (obj) { logger.info(JSON.stringify(obj)); await DiagnosticService.postMicroserviceStraceDatatoFtp(obj.microserviceId, obj, {}, true); - logger.info('Strace data has been posted to ftp successfully'); + logger.info('Strace data has been posted to ftp successfully.'); }; const _postMicroserviceImageSnapshotCreate = async function (obj) { logger.info(JSON.stringify(obj)); await DiagnosticService.postMicroserviceImageSnapshotCreate(obj.microserviceId, {}, true); - logger.info('Microservice image snapshot has been created successfully'); + logger.info('Microservice image snapshot has been created successfully.'); }; const _getMicroserviceImageSnapshot = async function (obj) { diff --git a/src/cli/flow.js b/src/cli/flow.js index 57e7566ac..77a3f15a1 100644 --- a/src/cli/flow.js +++ b/src/cli/flow.js @@ -134,9 +134,10 @@ const _deleteFlow = async function (flowData) { logger.info('Flow removed successfully.'); }; -const _getAllFlows = async function (emptyObj) { +const _getAllFlows = async function () { const flows = await FlowService.getAllFlows(true); - logger.info(JSON.stringify(flows)); + logger.info(JSON.stringify(flows, null, 2)); + logger.info('All flows have been retrieved successfully.'); }; const _getFlow = async function (flowData) { @@ -145,7 +146,8 @@ const _getFlow = async function (flowData) { const flowId = flowData.flowId; const flow = await FlowService.getFlowWithTransaction(flowId, {}, true); - logger.info(JSON.stringify(flow)); + logger.info(JSON.stringify(flow, null, 2)); + logger.info(`Flow with id ${flowId} has been retrieved successfully.`) }; function _createFlowObject(data) { diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 495e52a70..2318808fe 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -193,23 +193,23 @@ async function _deleteFog(obj, user) { async function _getFogList(obj, user) { const emptyFilters = [] const list = await FogService.getFogList(emptyFilters, user, true); - logger.info('Fog list has been gotten successfully'); - logger.info(JSON.stringify(list)); + logger.info(JSON.stringify(list, null, 2)); + logger.info('Fog list has been gotten successfully.'); } async function _getFog(obj, user) { const fog = _createFogObject(obj); const res = await FogService.getFogWithTransaction(fog, user, true); - logger.info('Fog has been gotten successfully'); - logger.info(JSON.stringify(res)); + logger.info(JSON.stringify(res, null, 2)); + logger.info('Fog has been gotten successfully.'); } async function _generateProvision(obj, user) { const fog = _createFogObject(obj); logger.info(JSON.stringify(fog)); const res = await FogService.generateProvisioningKey(fog, user, true); - logger.info('Fog provisioning key has been generated successfully'); - logger.info('Provisioning key: '+ JSON.stringify(res)); + logger.info('Provisioning key: '+ JSON.stringify(res, null, 2)); + logger.info('Fog provisioning key has been generated successfully.'); } async function _setFogRebootCommand(obj, user) { @@ -237,7 +237,8 @@ async function _getHalHardwareInfo(obj) { logger.info("Parameters" + JSON.stringify(uuidObj)); const info = await FogService.getHalHardwareInfo(uuidObj, {}, true); - logger.info(JSON.stringify(info)); + logger.info(JSON.stringify(info, null, 2)); + logger.info('Hardware info has been retrieved successfully.') } async function _getHalUsbInfo(obj) { @@ -248,7 +249,8 @@ async function _getHalUsbInfo(obj) { logger.info("Parameters" + JSON.stringify(uuidObj)); const info = await FogService.getHalHardwareInfo(uuidObj, {}, true); - logger.info(JSON.stringify(info)); + logger.info(JSON.stringify(info, null, 2)); + logger.info('Usb info has been retrieved successfully.') } function _createFogObject(cliData) { diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 2d228b51a..f96622a58 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -18,7 +18,6 @@ const logger = require('../logger'); const MicroserviceService = require('../services/microservices-service'); const fs = require('fs'); const AppHelper = require('../helpers/app-helper'); -const AuthDecorator = require('../decorators/cli-decorator'); const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( { @@ -81,7 +80,8 @@ class Microservice extends BaseCLIHandler { { name: 'microservice-id', alias: 'i', type: String, description: 'Microservice ID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PORT_MAPPING_CREATE, - constants.CMD_PORT_MAPPING_REMOVE, constants.CMD_PORT_MAPPING_LIST] + constants.CMD_PORT_MAPPING_REMOVE, constants.CMD_PORT_MAPPING_LIST, constants.CMD_VOLUME_MAPPING_CREATE, + constants.CMD_VOLUME_MAPPING_REMOVE, constants.CMD_VOLUME_MAPPING_LIST] }, { name: 'name', alias: 'n', type: String, description: 'Microservice name', @@ -125,7 +125,7 @@ class Microservice extends BaseCLIHandler { }, { name: 'mapping', alias: 'P', type: String, description: 'Container port mapping', - group: [constants.CMD_PORT_MAPPING_CREATE] + group: [constants.CMD_PORT_MAPPING_CREATE, constants.CMD_VOLUME_MAPPING_CREATE] }, { name: 'routes', alias: 't', type: String, description: 'Microservice route(s) (receiving microservices)', multiple: true, @@ -144,12 +144,16 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_UPDATE] }, { - name: 'cleanUp', alias: 'z', type: Boolean, description: 'Delete microservice with cleanup', + name: 'cleanup', alias: 'z', type: Boolean, description: 'Delete microservice with cleanup', group: [constants.CMD_REMOVE] }, { name: 'user-id', alias: 'u', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] + }, + { + name: 'mapping-id', alias: 'a', type: Number, description: 'Volume mapping id', + group: [constants.CMD_VOLUME_MAPPING_REMOVE] } ] this.commands = { @@ -162,7 +166,10 @@ class Microservice extends BaseCLIHandler { [constants.CMD_ROUTE_REMOVE]: 'Remove microservice route.', [constants.CMD_PORT_MAPPING_CREATE]: 'Create microservice port mapping.', [constants.CMD_PORT_MAPPING_REMOVE]: 'Remove microservice port mapping.', - [constants.CMD_PORT_MAPPING_LIST]: 'List microservice port mapping.' + [constants.CMD_PORT_MAPPING_LIST]: 'List microservice port mapping.', + [constants.CMD_VOLUME_MAPPING_CREATE]: 'Create microservice volume mapping.', + [constants.CMD_VOLUME_MAPPING_REMOVE]: 'Remove microservice volume mapping.', + [constants.CMD_VOLUME_MAPPING_LIST]: 'List microservice volume mapping.', } } @@ -200,6 +207,15 @@ class Microservice extends BaseCLIHandler { case constants.CMD_PORT_MAPPING_LIST: await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_LIST, _listPortMappings); break; + case constants.CMD_VOLUME_MAPPING_CREATE: + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_CREATE, _createVolumeMapping); + break; + case constants.CMD_VOLUME_MAPPING_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_REMOVE, _removeVolumeMapping); + break; + case constants.CMD_VOLUME_MAPPING_LIST: + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_LIST, _listVolumeMappings); + break; case constants.CMD_HELP: default: return this.help() @@ -227,11 +243,11 @@ class Microservice extends BaseCLIHandler { content: [ { desc: '1. Single mapping', - example: '$ iofog-controller microservice add [other required options] --volumes /host_src:/container_src', + example: '$ iofog-controller microservice add [other required options] --volumes /host_src:/container_src:rw', }, { desc: '2. Multiple mappings', - example: '$ iofog-controller microservice add [other required options] --volumes /host_src:/container_src /host_bin:/container_bin', + example: '$ iofog-controller microservice add [other required options] --volumes /host_src:/container_src:rw /host_bin:/container_bin:r', }, { desc: '3. Port mapping (80:8080:false - internal port : external port : public mode)', @@ -256,6 +272,14 @@ class Microservice extends BaseCLIHandler { { desc: '8. Delete port mapping (80 - internal port, ABC - microservice id)', example: '$ iofog-controller microservice port-mapping-remove --internal-port 80 -i ABC' + }, + { + desc: '9. Create volume mapping', + example: '$ iofog-controller microservice volume-mapping-create --mapping /host_src:/container_src:rw -i ABC' + }, + { + desc: '10. Delete volume mapping', + example: '$ iofog-controller microservice volume-mapping-remove -i ABC -a 1' } ], }, @@ -304,7 +328,15 @@ const _createPortMapping = async function (obj) { logger.info(JSON.stringify(obj)); const mapping = parsePortMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_PORT_MAPPING); await MicroserviceService.createPortMapping(obj.microserviceId, mapping, {}, true); - logger.info('Port mapping has been create successfully'); + logger.info('Port mapping has been created successfully.'); +}; + +const _createVolumeMapping = async function (obj) { + logger.info(JSON.stringify(obj)); + const mapping = parseVolumeMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_VOLUME_MAPPING); + const result = await MicroserviceService.createVolumeMapping(obj.microserviceId, mapping, {}, true); + logger.info(JSON.stringify(result, null, 2)); + logger.info('Volume mapping has been created successfully.') }; const _removePortMapping = async function (obj) { @@ -312,27 +344,43 @@ const _removePortMapping = async function (obj) { try { const internalPort = parseInt(obj.internalPort); await MicroserviceService.deletePortMapping(obj.microserviceId, internalPort, {}, true); - logger.info('Port mapping has been deleted successfully'); + logger.info('Port mapping has been deleted successfully.'); } catch(e) { logger.error(ErrorMessages.CLI.INVALID_INTERNAL_PORT); } }; +const _removeVolumeMapping = async function (obj) { + logger.info(JSON.stringify(obj)); + try { + await MicroserviceService.deleteVolumeMapping(obj.microserviceId, obj.mappingId, {}, true); + logger.info('Volume mapping has been deleted successfully.'); + } catch(e) { + logger.error(ErrorMessages.CLI.INVALID_VOLUME_MAPPING); + } +}; + const _listPortMappings = async function (obj) { - const result = await MicroserviceService.getMicroservicePortMappingList(obj.microserviceId, {}, true); - logger.info(JSON.stringify(result)); - logger.info('Port mappings have been retrieved successfully'); + const result = await MicroserviceService.listMicroservicePortMappings(obj.microserviceId, {}, true); + logger.info(JSON.stringify(result, null, 2)); + logger.info('Port mappings have been retrieved successfully.'); +}; + +const _listVolumeMappings = async function (obj) { + const result = await MicroserviceService.listVolumeMappings(obj.microserviceId, {}, true); + logger.info(JSON.stringify(result, null, 2)); + logger.info('Volume mappings have been retrieved successfully.'); }; const _removeMicroservice = async function (obj) { logger.info(JSON.stringify(obj)); - await MicroserviceService.deleteMicroservice(obj.microserviceId, obj.cleanUp, {}, true); + await MicroserviceService.deleteMicroservice(obj.microserviceId, obj.cleanup, {}, true); logger.info('Microservice has been removed successfully.') }; const _listMicroservices = async function () { const result = await MicroserviceService.listMicroservices({}, {}, true); - logger.info(JSON.stringify(result)); + logger.info(JSON.stringify(result, null, 2)); logger.info('Microservices have been retrieved successfully.'); }; @@ -377,7 +425,7 @@ const _updateMicroserviceObject = function (obj) { }; if (obj.volumes) { - microserviceObj.volumeMappings = parseVolumes(obj.volumes, 'Error during parsing of volume mapping option.'); + microserviceObj.volumeMappings = parseVolumeMappingArray(obj.volumes, 'Error during parsing of volume mapping option.'); } return AppHelper.deleteUndefinedFields(microserviceObj); @@ -396,7 +444,7 @@ const _createMicroserviceObject = function (obj) { }; if (obj.volumes) { - microserviceObj.volumeMappings = parseVolumes(obj.volumes, ErrorMessages.CLI.INVALID_VOLUME_MAPPING); + microserviceObj.volumeMappings = parseVolumeMappingArray(obj.volumes, ErrorMessages.CLI.INVALID_VOLUME_MAPPING); } if (obj.ports) { microserviceObj.ports = parsePortMappingArray(obj.ports, ErrorMessages.CLI.INVALID_PORT_MAPPING); @@ -405,22 +453,23 @@ const _createMicroserviceObject = function (obj) { return AppHelper.deleteUndefinedFields(microserviceObj); }; - -const parseVolumes = function (arr, errMsg) { - return arr.map(item => { - let result = {}; - try { - const props = item.split(':'); - result = { - hostDestination: props[0], - containerDestination: props[1], - accessMode: props[2] - } - } catch(e) { - logger.warn(errMsg); +const parseVolumeMappingObject = function (obj, errMsg) { + let result = {}; + try { + const props = obj.split(':'); + result = { + hostDestination: props[0], + containerDestination: props[1], + accessMode: props[2] } - return result; - }) + } catch(e) { + logger.warn(errMsg); + } + return result; +}; + +const parseVolumeMappingArray = function (arr, errMsg) { + return arr.map(obj => parseVolumeMappingObject(obj, errMsg)); }; const parsePortMappingObject = function (obj, errMsg) { diff --git a/src/cli/tunnel.js b/src/cli/tunnel.js index d5b326462..34fcb6980 100644 --- a/src/cli/tunnel.js +++ b/src/cli/tunnel.js @@ -74,11 +74,10 @@ async function _updateTunnel(obj, user) { logger.info('Tunnel has been updated successfully.'); } -async function _tunnelList(obj) { +async function _tunnelList() { const tunnels = await TunnelService.findAll(); - logger.info(JSON.stringify(tunnels)); + logger.info(JSON.stringify(tunnels, null, 2)); logger.info('Tunnels has been received successfully.'); - return tunnels; } async function _executeCase(commands, commandName, f, isUserRequired) { @@ -98,15 +97,14 @@ async function _executeCase(commands, commandName, f, isUserRequired) { function _createTunnelObject(cliData) { const rsa = cliData.rsaKey ? fs.readFileSync(cliData.rsaKey, 'utf8') : ""; - const tunnel = { - host: cliData.host, - username: cliData.username, - password: cliData.password, - rsakey: rsa, - lport: cliData.port, - iofogUuid: cliData.iofogUuid - } - return tunnel; + return { + host: cliData.host, + username: cliData.username, + password: cliData.password, + rsakey: rsa, + lport: cliData.port, + iofogUuid: cliData.iofogUuid + }; } -module.exports = new Tunnel() \ No newline at end of file +module.exports = new Tunnel(); \ No newline at end of file diff --git a/src/cli/user.js b/src/cli/user.js index 61416b4e4..5be79c11a 100644 --- a/src/cli/user.js +++ b/src/cli/user.js @@ -129,9 +129,10 @@ const _deleteUser = async function (emailObj, user) { logger.info('User removed successfully.'); }; -const _getAllUsers = async function (emptyObj) { +const _getAllUsers = async function () { const users = await UserService.list(true); - logger.info(JSON.stringify(users)); + logger.info(JSON.stringify(users, null, 2)); + logger.info('All users have been retrieved successfully.') }; const _generateToken = async function (emailObj, user) { diff --git a/src/controllers/microservices-controller.js b/src/controllers/microservices-controller.js index 4a0746fa2..7cbfb0ae5 100644 --- a/src/controllers/microservices-controller.js +++ b/src/controllers/microservices-controller.js @@ -35,7 +35,7 @@ const _updateMicroserviceEndPoint = async function (req, user) { const microservice = req.body; const microserviceUuid = req.params.uuid; - logger.info("Parameters:" + JSON.stringify(microservice)); + logger.info("Parameters: " + JSON.stringify(microservice)); logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); return await MicroservicesService.updateMicroservice(microserviceUuid, microservice, user, false) @@ -43,12 +43,11 @@ const _updateMicroserviceEndPoint = async function (req, user) { const _deleteMicroserviceEndPoint = async function (req, user) { const microserviceUuid = req.params.uuid; - const deleteWithCleanUp = (req.query.withCleanUp == 'true'); - + const microserviceData = req.body || {}; logger.info("Microservice uuid:" + JSON.stringify(microserviceUuid)); - logger.info("Delete with cleanup:" + JSON.stringify(deleteWithCleanUp)); + logger.info("Parameters: " + JSON.stringify(microserviceData)); - return await MicroservicesService.deleteMicroservice(microserviceUuid, deleteWithCleanUp, user, false) + return await MicroservicesService.deleteMicroservice(microserviceUuid, microserviceData, user, false) }; const _getMicroservicesByFlowEndPoint = async function (req, user) { @@ -59,42 +58,68 @@ const _getMicroservicesByFlowEndPoint = async function (req, user) { return await MicroservicesService.listMicroservices(flowId, user, false) }; -async function _createMicroserviceRoute(req, user) { +const _createMicroserviceRouteEndPoint = async function (req, user) { const sourceUuid = req.params.uuid; const distUuid = req.params.receiverUuid; logger.info(`Creating route from ${sourceUuid} to ${distUuid}`); return await MicroservicesService.createRoute(sourceUuid, distUuid, user, false) } -async function _deleteMicroserviceRoute(req, user) { +const _deleteMicroserviceRouteEndPoint = async function (req, user) { const sourceUuid = req.params.uuid; const distUuid = req.params.receiverUuid; logger.info(`Creating route from ${sourceUuid} to ${distUuid}`); return await MicroservicesService.deleteRoute(sourceUuid, distUuid, user, false) } -async function _createMicroservicePortMapping(req, user) { +const _createMicroservicePortMappingEndPoint = async function (req, user) { const uuid = req.params.uuid; const portMappingData = req.body; logger.info(`Creating port mapping for ${uuid}`); return await MicroservicesService.createPortMapping(uuid, portMappingData, user, false) } -async function _deleteMicroservicePortMapping(req, user) { +const _deleteMicroservicePortMappingEndPoint = async function (req, user) { const uuid = req.params.uuid; const internalPort = req.params.internalPort; logger.info(`Deleting port mapping for ${uuid}`); return await MicroservicesService.deletePortMapping(uuid, internalPort, user, false) } -async function _getMicroservicePortMappingList(req, user) { +const _listMicroservicePortMappingsEndPoint = async function (req, user) { const uuid = req.params.uuid; logger.info(`Getting all port mappings for ${uuid}`); - const ports = await MicroservicesService.getMicroservicePortMappingList(uuid, user, false); + const ports = await MicroservicesService.listMicroservicePortMappings(uuid, user, false); return { ports: ports } -} +}; + +const _createMicroserviceVolumeMappingEndPoint = async function (req, user) { + const microserviceUuid = req.params.uuid; + const volumeMappingData = req.body; + logger.info(`Creating volume mapping for ${microserviceUuid}`); + const volumeMapping = await MicroservicesService.createVolumeMapping(microserviceUuid, volumeMappingData, user, false); + return { + id: volumeMapping.id + } +}; + +const _listMicroserviceVolumeMappingsEndPoint = async function (req, user) { + const uuid = req.params.uuid; + logger.info(`Getting all volume mappings for ${uuid}`); + const volumeMappings = await MicroservicesService.listVolumeMappings(uuid, user, false); + return { + volumeMappings: volumeMappings + } +}; + +const _deleteMicroserviceVolumeMappingEndPoint = async function (req, user) { + const uuid = req.params.uuid; + const id = req.params.id; + logger.info(`Deleting volume mapping ${id} for ${uuid}`); + return await MicroservicesService.deleteVolumeMapping(uuid, id, user, false); +}; module.exports = { createMicroservicesOnFogEndPoint: AuthDecorator.checkAuthToken(_createMicroservicesOnFogEndPoint), @@ -102,9 +127,12 @@ module.exports = { updateMicroserviceEndPoint: AuthDecorator.checkAuthToken(_updateMicroserviceEndPoint), deleteMicroserviceEndPoint: AuthDecorator.checkAuthToken(_deleteMicroserviceEndPoint), getMicroservicesByFlowEndPoint: AuthDecorator.checkAuthToken(_getMicroservicesByFlowEndPoint), - createMicroserviceRoute: AuthDecorator.checkAuthToken(_createMicroserviceRoute), - deleteMicroserviceRoute: AuthDecorator.checkAuthToken(_deleteMicroserviceRoute), - createMicroservicePortMapping: AuthDecorator.checkAuthToken(_createMicroservicePortMapping), - deleteMicroservicePortMapping: AuthDecorator.checkAuthToken(_deleteMicroservicePortMapping), - getMicroservicePortMappingList: AuthDecorator.checkAuthToken(_getMicroservicePortMappingList) + createMicroserviceRouteEndPoint: AuthDecorator.checkAuthToken(_createMicroserviceRouteEndPoint), + deleteMicroserviceRouteEndPoint: AuthDecorator.checkAuthToken(_deleteMicroserviceRouteEndPoint), + createMicroservicePortMappingEndPoint: AuthDecorator.checkAuthToken(_createMicroservicePortMappingEndPoint), + deleteMicroservicePortMappingEndPoint: AuthDecorator.checkAuthToken(_deleteMicroservicePortMappingEndPoint), + getMicroservicePortMappingListEndPoint: AuthDecorator.checkAuthToken(_listMicroservicePortMappingsEndPoint), + createMicroserviceVolumeMappingEndPoint: AuthDecorator.checkAuthToken(_createMicroserviceVolumeMappingEndPoint), + listMicroserviceVolumeMappingsEndPoint: AuthDecorator.checkAuthToken(_listMicroserviceVolumeMappingsEndPoint), + deleteMicroserviceVolumeMappingEndPoint: AuthDecorator.checkAuthToken(_deleteMicroserviceVolumeMappingEndPoint) }; \ No newline at end of file diff --git a/src/helpers/constants.js b/src/helpers/constants.js index 3e7eee6d1..17a98d9a4 100644 --- a/src/helpers/constants.js +++ b/src/helpers/constants.js @@ -41,6 +41,9 @@ module.exports = { CMD_PORT_MAPPING_CREATE: 'port-mapping-create', CMD_PORT_MAPPING_REMOVE: 'port-mapping-remove', CMD_PORT_MAPPING_LIST: 'port-mapping-list', + CMD_VOLUME_MAPPING_CREATE: 'volume-mapping-create', + CMD_VOLUME_MAPPING_REMOVE: 'volume-mapping-remove', + CMD_VOLUME_MAPPING_LIST: 'volume-mapping-list', CMD_REGISTRY: 'registry', CMD_ACTIVATE: 'activate', CMD_SUSPEND: 'suspend', diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index c7cc1317c..989907761 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -23,6 +23,7 @@ module.exports = { INVALID_FOG_NODE_UUID: 'Invalid ioFog UUID {}', INVALID_USER_EMAIL: 'Invalid user email', INVALID_MICROSERVICE_UUID: "Invalid microservice UUID '{}'", + INVALID_VOLUME_MAPPING_UUID: "Invalid volume mapping id '{}'", ACTIVATION_CODE_NOT_FOUND: 'Activation code not found', INVALID_OLD_PASSWORD: 'Old password is incorrect', ACCOUNT_NOT_FOUND: 'Account not found', @@ -52,6 +53,8 @@ module.exports = { FILE_DOES_NOT_EXIST: 'File does not exist.', RESTRICTED_PUBLISHER: "You are not allowed to add catalog item as 'Eclipse ioFog' publisher", REQUIRED_FOG_NODE: 'ioFog node is required.', + PORT_MAPPING_ALREADY_EXISTS: 'Port mapping already exists', + VOLUME_MAPPING_ALREADY_EXISTS: 'Volume mapping already exists', INVALID_CONNECTOR_DOMAIN: 'Invalid connector domain {}', CERT_PROPERTY_REQUIRED: 'Property "certificate" is required if property "requiresCert" is set to true', TUNNEL_NOT_FOUND: 'Tunnel not found', diff --git a/src/routes/microservices.js b/src/routes/microservices.js index 122c0ef30..65c8e3093 100644 --- a/src/routes/microservices.js +++ b/src/routes/microservices.js @@ -162,8 +162,8 @@ module.exports = [ } ]; - const createMicroserviceRoute = ResponseDecorator.handleErrors(MicroservicesController.createMicroserviceRoute, successCode, errorCodes); - const responseObject = await createMicroserviceRoute(req); + const createMicroserviceRouteEndPoint = ResponseDecorator.handleErrors(MicroservicesController.createMicroserviceRouteEndPoint, successCode, errorCodes); + const responseObject = await createMicroserviceRouteEndPoint(req); res .status(responseObject.code) @@ -190,8 +190,8 @@ module.exports = [ } ]; - const deleteMicroserviceRoute = ResponseDecorator.handleErrors(MicroservicesController.deleteMicroserviceRoute, successCode, errorCodes); - const responseObject = await deleteMicroserviceRoute(req); + const deleteMicroserviceRouteEndPoint = ResponseDecorator.handleErrors(MicroservicesController.deleteMicroserviceRouteEndPoint, successCode, errorCodes); + const responseObject = await deleteMicroserviceRouteEndPoint(req); res .status(responseObject.code) @@ -218,8 +218,8 @@ module.exports = [ } ]; - const createMicroservicePortMapping = ResponseDecorator.handleErrors(MicroservicesController.createMicroservicePortMapping, successCode, errorCodes); - const responseObject = await createMicroservicePortMapping(req); + const createMicroservicePortMappingEndPoint = ResponseDecorator.handleErrors(MicroservicesController.createMicroservicePortMappingEndPoint, successCode, errorCodes); + const responseObject = await createMicroservicePortMappingEndPoint(req); res .status(responseObject.code) @@ -242,7 +242,7 @@ module.exports = [ } ]; - const deleteMicroservicePortMapping = ResponseDecorator.handleErrors(MicroservicesController.deleteMicroservicePortMapping, successCode, errorCodes); + const deleteMicroservicePortMapping = ResponseDecorator.handleErrors(MicroservicesController.deleteMicroservicePortMappingEndPoint, successCode, errorCodes); const responseObject = await deleteMicroservicePortMapping(req); res @@ -266,7 +266,7 @@ module.exports = [ } ]; - const getMicroservicePortMapping = ResponseDecorator.handleErrors(MicroservicesController.getMicroservicePortMappingList, successCode, errorCodes); + const getMicroservicePortMapping = ResponseDecorator.handleErrors(MicroservicesController.getMicroservicePortMappingListEndPoint, successCode, errorCodes); const responseObject = await getMicroservicePortMapping(req); res @@ -274,4 +274,96 @@ module.exports = [ .send(responseObject.body) }, }, -] + { + method: 'get', + path: '/api/v3/microservices/:uuid/volume-mapping', + middleware: async (req, res) => { + const successCode = constants.HTTP_CODE_SUCCESS; + const errorCodes = [ + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError] + }, + { + code: constants.HTTP_CODE_NOT_FOUND, + errors: [Errors.NotFoundError] + } + ]; + + const listMicroserviceVolumeMappingEndPoint = ResponseDecorator.handleErrors( + MicroservicesController.listMicroserviceVolumeMappingsEndPoint, + successCode, + errorCodes + ); + const responseObject = await listMicroserviceVolumeMappingEndPoint(req); + + res + .status(responseObject.code) + .send(responseObject.body) + }, + }, + { + method: 'post', + path: '/api/v3/microservices/:uuid/volume-mapping', + middleware: async (req, res) => { + const successCode = constants.HTTP_CODE_CREATED; + const errorCodes = [ + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError] + }, + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError] + }, + { + code: constants.HTTP_CODE_NOT_FOUND, + errors: [Errors.NotFoundError] + } + ]; + + const createMicroserviceVolumeMappingEndPoint = ResponseDecorator.handleErrors( + MicroservicesController.createMicroserviceVolumeMappingEndPoint, + successCode, + errorCodes + ); + const responseObject = await createMicroserviceVolumeMappingEndPoint(req); + + res + .status(responseObject.code) + .send(responseObject.body) + }, + }, + { + method: 'delete', + path: '/api/v3/microservices/:uuid/volume-mapping/:id', + middleware: async (req, res) => { + const successCode = constants.HTTP_CODE_NO_CONTENT; + const errorCodes = [ + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError] + }, + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError] + }, + { + code: constants.HTTP_CODE_NOT_FOUND, + errors: [Errors.NotFoundError] + } + ]; + + const deleteMicroserviceVolumeMappingEndPoint = ResponseDecorator.handleErrors( + MicroservicesController.deleteMicroserviceVolumeMappingEndPoint, + successCode, + errorCodes + ); + const responseObject = await deleteMicroserviceVolumeMappingEndPoint(req); + + res + .status(responseObject.code) + .send(responseObject.body) + }, + }, +]; diff --git a/src/schemas/microservice.js b/src/schemas/microservice.js index 833e20a2f..70d44bfa1 100644 --- a/src/schemas/microservice.js +++ b/src/schemas/microservice.js @@ -48,6 +48,17 @@ const microserviceUpdate = { "additionalProperties": false }; +const microserviceDelete = { + "id": "/microserviceDelete", + "type": "object", + "properties": { + "withCleanup": { + "type": "boolean" + }, + "additionalProperties": false + } +}; + const ports = { "id": "/ports", "type": "object", @@ -85,6 +96,6 @@ const volumeMappings = { }; module.exports = { - mainSchemas: [microserviceCreate, microserviceUpdate, ports, portsCreate], + mainSchemas: [microserviceCreate, microserviceUpdate, ports, portsCreate, microserviceDelete, volumeMappings], innerSchemas: [volumeMappings, ports] }; \ No newline at end of file diff --git a/src/sequelize/managers/volume-mapping-manager.js b/src/sequelize/managers/volume-mapping-manager.js index e1357d570..28f515e97 100644 --- a/src/sequelize/managers/volume-mapping-manager.js +++ b/src/sequelize/managers/volume-mapping-manager.js @@ -14,11 +14,19 @@ const BaseManager = require('./base-manager'); const models = require('./../models'); const VolumeMapping = models.VolumeMapping; +const Microservice = models.Microservice; class VolumeMappingManager extends BaseManager { - getEntity() { - return VolumeMapping - } + getEntity() { + return VolumeMapping + } + + findAll(where, transaction) { + return VolumeMapping.findAll({ + where: where, + attributes: ['hostDestination', 'containerDestination', 'accessMode', 'id'] + }, {transaction: transaction}) + } } const instance = new VolumeMappingManager(); diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 7cee26c0f..0aa79ddf9 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -202,7 +202,7 @@ const _updateChangeTracking = async function (configUpdated, fogNodeUuid, transa } }; -const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, user, isCLI, transaction) { +const _deleteMicroservice = async function (microserviceUuid, microserviceData, user, isCLI, transaction) { const where = isCLI ? @@ -231,7 +231,7 @@ const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, }, { delete: true, - deleteWithCleanUp: !!deleteWithCleanUp + deleteWithCleanUp: !!microserviceData.withCleanup }, transaction); } @@ -241,14 +241,14 @@ const _deleteMicroservice = async function (microserviceUuid, deleteWithCleanUp, const _deleteNotRunningMicroservices = async function (transaction) { const microservices = await MicroserviceManager.findAllWithStatuses(transaction); microservices - .filter(microservice => !!microservice.delete) + .filter(microservice => microservice.delete) .filter(microservice => microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) .forEach(microservice => { MicroserviceManager.delete({ uuid: microservice.uuid }, transaction); }); -} +}; const _checkForDuplicateName = async function (name, item, userId, transaction) { if (name) { @@ -551,7 +551,7 @@ async function _createPortMapping(microserviceUuid, portMappingData, user, isCLI ] }, transaction); if (msPorts) { - throw new Errors.ValidationError('port mapping already exists') + throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_ALREADY_EXISTS); } if (portMappingData.publicMode) { @@ -745,7 +745,7 @@ async function _buildPortsList(portsPairs, transaction) { return res } -async function _getPortMappingList(microserviceUuid, user, isCLI, transaction) { +async function _listPortMappings(microserviceUuid, user, isCLI, transaction) { const where = isCLI ? {uuid: microserviceUuid} : {uuid: microserviceUuid, userId: user.id}; @@ -755,8 +755,7 @@ async function _getPortMappingList(microserviceUuid, user, isCLI, transaction) { } const portsPairs = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction) - const res = await _buildPortsList(portsPairs, transaction); - return res + return await _buildPortsList(portsPairs, transaction) } async function getPhysicalConections(microservice, transaction) { @@ -789,6 +788,73 @@ async function _buildLink(protocol, ip, port) { return `${protocol}://${ip}:${port}` } +async function _createVolumeMapping(microserviceUuid, volumeMappingData, user, isCLI, transaction) { + await Validation.validate(volumeMappingData, Validation.schemas.volumeMappings); + + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const volueMapping = await VolumeMappingManager.findOne({ + microserviceUuid: microserviceUuid, + hostDestination: volumeMappingData.hostDestination, + containerDestination: volumeMappingData.containerDestination + }, transaction); + if (volueMapping) { + throw new Errors.ValidationError(ErrorMessages.VOLUME_MAPPING_ALREADY_EXISTS); + } + + const volumeMappingObj = { + microserviceUuid: microserviceUuid, + hostDestination: volumeMappingData.hostDestination, + containerDestination: volumeMappingData.containerDestination, + accessMode: volumeMappingData.accessMode + }; + + return await VolumeMappingManager.create(volumeMappingObj, transaction); +} + +async function _deleteVolumeMapping(microserviceUuid, volumeMappingUuid, user, isCLI, transaction) { + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const microservice = await MicroserviceManager.findOne(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const volumeMappingWhere = { + uuid: volumeMappingUuid, + microserviceUuid: microserviceUuid + }; + + const affectedRows = await VolumeMappingManager.delete(volumeMappingWhere, transaction); + if (affectedRows === 0) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_VOLUME_MAPPING_UUID, volumeMappingUuid)); + } +} + +async function _listVolumeMappings(microserviceUuid, user, isCLI, transaction) { + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + const microservice = await MicroserviceManager.findOne(where, transaction) + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)) + } + + const volumeMappingWhere = { + microserviceUuid: microserviceUuid + }; + return await VolumeMappingManager.findAll(volumeMappingWhere, transaction); +} + module.exports = { createMicroserviceOnFog: TransactionDecorator.generateTransaction(_createMicroserviceOnFog), listMicroservices: TransactionDecorator.generateTransaction(_listMicroservices), @@ -798,8 +864,11 @@ module.exports = { createRoute: TransactionDecorator.generateTransaction(_createRoute), deleteRoute: TransactionDecorator.generateTransaction(_deleteRoute), createPortMapping: TransactionDecorator.generateTransaction(_createPortMapping), - getMicroservicePortMappingList: TransactionDecorator.generateTransaction(_getPortMappingList), + listMicroservicePortMappings: TransactionDecorator.generateTransaction(_listPortMappings), deletePortMapping: TransactionDecorator.generateTransaction(_deletePortMapping), + createVolumeMapping: TransactionDecorator.generateTransaction(_createVolumeMapping), + deleteVolumeMapping: TransactionDecorator.generateTransaction(_deleteVolumeMapping), + listVolumeMappings: TransactionDecorator.generateTransaction(_listVolumeMappings), getPhysicalConections: getPhysicalConections, deleteNotRunningMicroservices: _deleteNotRunningMicroservices }; diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index a6ac512d2..b040d08c0 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1,6 +1,6 @@ { "info": { - "_postman_id": "5a9e5363-c42e-4cfe-ad53-4ba7f9594334", + "_postman_id": "507ec948-6bd6-48ad-9272-ab609e6ce965", "name": "Controller Testing", "description": "iofog-controller collection", "schema": "https://schema.getpostman.com/json/collection/v2.1.0/collection.json" @@ -8,6 +8,7 @@ "item": [ { "name": "User", + "description": "User collection", "item": [ { "name": "Create user", @@ -507,7 +508,6 @@ "response": [] } ], - "description": "User collection", "event": [ { "listen": "prerequest", @@ -533,6 +533,7 @@ }, { "name": "General", + "description": "General collection", "item": [ { "name": "Status", @@ -652,7 +653,6 @@ "response": [] } ], - "description": "General collection", "event": [ { "listen": "prerequest", @@ -678,6 +678,7 @@ }, { "name": "Agent", + "description": "Agent collection", "item": [ { "name": "Create user", @@ -1765,7 +1766,6 @@ "response": [] } ], - "description": "Agent collection", "event": [ { "listen": "prerequest", @@ -1791,6 +1791,7 @@ }, { "name": "Flow", + "description": "Flow collection", "item": [ { "name": "Create user", @@ -2174,7 +2175,6 @@ "response": [] } ], - "description": "Flow collection", "event": [ { "listen": "prerequest", @@ -2200,6 +2200,7 @@ }, { "name": "Catalog", + "description": "Catalog collection", "item": [ { "name": "Create user", @@ -2592,7 +2593,6 @@ "response": [] } ], - "description": "Catalog collection", "event": [ { "listen": "prerequest", @@ -2618,6 +2618,7 @@ }, { "name": "Tunnel", + "description": "Tunnel collection", "item": [ { "name": "Create user", @@ -2958,7 +2959,6 @@ "response": [] } ], - "description": "Tunnel collection", "event": [ { "listen": "prerequest", @@ -2984,6 +2984,7 @@ }, { "name": "Microservices", + "description": "Microservices collection", "item": [ { "name": "Create user", @@ -3678,6 +3679,150 @@ }, "response": [] }, + { + "name": "Create volume mapping", + "event": [ + { + "listen": "test", + "script": { + "id": "df8a73e8-2b55-48f1-a143-0c243d787dac", + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 201\"] = responseCode.code === 201;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('id');", + "", + "", + "postman.setGlobalVariable(\"volume-id\", data.id);", + "" + ] + } + } + ], + "request": { + "method": "POST", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}" + } + ], + "body": { + "mode": "raw", + "raw": " {\n \"hostDestination\": \"/var/dest7\",\n \"containerDestination\": \"/var/dest\",\n \"accessMode\": \"rw\"\n }" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/volume-mapping", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "volume-mapping" + ] + } + }, + "response": [] + }, + { + "name": "List volume mappings", + "event": [ + { + "listen": "test", + "script": { + "id": "422b4beb-ae6e-4cfc-9656-5eee3c5e792f", + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 200\"] = responseCode.code === 200;", + "", + "var data = JSON.parse(responseBody);", + "", + "tests[\"Response validation passed\"] = data.hasOwnProperty('volumeMappings');" + ] + } + } + ], + "request": { + "method": "GET", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + } + ], + "body": {}, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/volume-mapping", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "volume-mapping" + ] + } + }, + "response": [] + }, + { + "name": "Delete volume mapping", + "event": [ + { + "listen": "test", + "script": { + "id": "98751304-dec8-4149-99ec-e7e76c5ac9ea", + "type": "text/javascript", + "exec": [ + "tests[\"Status code is 204\"] = responseCode.code === 204;" + ] + } + } + ], + "request": { + "method": "DELETE", + "header": [ + { + "key": "Authorization", + "value": "{{user-token}}" + }, + { + "key": "Content-Type", + "value": "application/json" + } + ], + "body": { + "mode": "raw", + "raw": "" + }, + "url": { + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/volume-mapping/{{volume-id}}", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "microservices", + "{{ms-id}}", + "volume-mapping", + "{{volume-id}}" + ] + } + }, + "response": [] + }, { "name": "Delete a Microservice", "event": [ @@ -3917,7 +4062,6 @@ "response": [] } ], - "description": "Microservices collection", "event": [ { "listen": "prerequest", @@ -3943,6 +4087,7 @@ }, { "name": "Diagnostics", + "description": "Diagnostics collection", "item": [ { "name": "Create user", @@ -4738,7 +4883,6 @@ "response": [] } ], - "description": "Diagnostics collection", "event": [ { "listen": "prerequest", @@ -4764,6 +4908,7 @@ }, { "name": "ioFog", + "description": "ioFog collection", "item": [ { "name": "Create user", @@ -5467,7 +5612,6 @@ "response": [] } ], - "description": "ioFog collection", "event": [ { "listen": "prerequest", @@ -5493,6 +5637,7 @@ }, { "name": "Registries", + "description": "Registries collection", "item": [ { "name": "Create user", @@ -5827,7 +5972,6 @@ "response": [] } ], - "description": "Registries collection", "event": [ { "listen": "prerequest", From 97ee67fa5197ef97df29250f266b2e9f84c94d8a Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Mon, 12 Nov 2018 14:01:41 +0300 Subject: [PATCH 49/91] Epankou/bug cli config messages (#342) * volume mapping & delete with clean up * volume mapping & delete with clean up * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js --- src/cli/config.js | 16 ++++++++-------- src/schemas/index.js | 1 - 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/src/cli/config.js b/src/cli/config.js index 4b7258422..66511d22c 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -82,7 +82,7 @@ const _executeCase = async function (catalogCommand, commandName, f) { const _addConfigOption = async function (options) { await Validator.validate(options, Validator.schemas.configUpdate); - updateConfig(options.port, 'port', 'Server:Port', async (onSuccess) => { + await updateConfig(options.port, 'port', 'Server:Port', async (onSuccess) => { const port = options.port; const status = await AppHelper.checkPortAvailability(port); if (status === 'closed') { @@ -93,7 +93,7 @@ const _addConfigOption = async function (options) { } }); - updateConfig(options.sslCert, 'ssl-cert', 'Server:SslCert', (onSuccess) => { + await updateConfig(options.sslCert, 'ssl-cert', 'Server:SslCert', (onSuccess) => { const sslCert = options.sslCert; if (!AppHelper.isFileExists(sslCert)) { logger.error(ErrorMessages.INVALID_FILE_PATH); @@ -113,7 +113,7 @@ const _addConfigOption = async function (options) { logger.info('Config option ssl-key has been updated.'); } - updateConfig(options.intermediateCert, 'intermediate-cert', 'Server:IntermediateCert', (onSuccess) => { + await updateConfig(options.intermediateCert, 'intermediate-cert', 'Server:IntermediateCert', (onSuccess) => { const intermediateCert = options.intermediateCert; if (!AppHelper.isFileExists(intermediateCert)) { logger.error(ErrorMessages.INVALID_FILE_PATH); @@ -123,12 +123,12 @@ const _addConfigOption = async function (options) { onSuccess(); }); - updateConfig(options.homeUrl, 'home-url', 'Email:HomeUrl', (onSuccess) => { + await updateConfig(options.homeUrl, 'home-url', 'Email:HomeUrl', (onSuccess) => { config.set('Email:HomeUrl', options.homeUrl); onSuccess(); }); - updateConfig(options.emailAddress, 'email-address', 'Email:Address', (onSuccess) => { + await updateConfig(options.emailAddress, 'email-address', 'Email:Address', (onSuccess) => { if (options.emailPassword) { logger.info('When changing email address, password must be provided.'); return; @@ -142,17 +142,17 @@ const _addConfigOption = async function (options) { logger.info('Config option email-password has been updated.'); } - updateConfig(options.emailService, 'email-service', 'Email:Service', (onSuccess) => { + await updateConfig(options.emailService, 'email-service', 'Email:Service', (onSuccess) => { config.set('Email:Service', options.emailService); onSuccess(); }); - updateConfig(options.logDir, 'log-dir', 'Service:LogsDirectory', (onSuccess) => { + await updateConfig(options.logDir, 'log-dir', 'Service:LogsDirectory', (onSuccess) => { config.set('Service:LogsDirectory', options.logDir); onSuccess(); }); - updateConfig(options.logSize, 'log-size', 'Service:LogsFileSize', (onSuccess) => { + await updateConfig(options.logSize, 'log-size', 'Service:LogsFileSize', (onSuccess) => { config.set('Service:LogsFileSize', options.logSize * 1024); onSuccess(); }) diff --git a/src/schemas/index.js b/src/schemas/index.js index ba825c658..158302d73 100644 --- a/src/schemas/index.js +++ b/src/schemas/index.js @@ -52,7 +52,6 @@ fs.readdirSync(__dirname) async function validate(object, schema) { const response = v.validate(object, schema); if (!response.valid) { - Logger.info(JSON.stringify(response)); await handleValidationError(response.errors[0]); } return response From d3322961e03458765f6740ecd2443a3dccac938d Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 12 Nov 2018 16:06:04 +0300 Subject: [PATCH 50/91] CLI fixes EWC 340 (#344) * EWC-340 CLI fixes * cleanup --- src/cli/base-cli-handler.js | 18 +-- src/cli/catalog.js | 157 +++++++++++++++------ src/cli/config.js | 117 +++++++++++----- src/cli/connector.js | 129 +++++++++++------ src/cli/controller.js | 50 ++++--- src/cli/diagnostics.js | 56 ++++---- src/cli/flow.js | 105 +++++++++----- src/cli/index.js | 64 ++++----- src/cli/iofog.js | 271 ++++++++++++++++++++++++++---------- src/cli/microservice.js | 121 ++++++++-------- src/cli/registry.js | 105 ++++++++++---- src/cli/start.js | 30 ++-- src/cli/tunnel.js | 154 ++++++++++++-------- src/cli/user.js | 86 +++++++----- src/helpers/app-helper.js | 17 ++- 15 files changed, 960 insertions(+), 520 deletions(-) diff --git a/src/cli/base-cli-handler.js b/src/cli/base-cli-handler.js index 7e8f17697..6b6e2c616 100644 --- a/src/cli/base-cli-handler.js +++ b/src/cli/base-cli-handler.js @@ -11,13 +11,13 @@ * */ -const commandLineArgs = require('command-line-args') -const commandLineUsage = require('command-line-usage') +const commandLineArgs = require('command-line-args'); +const commandLineUsage = require('command-line-usage'); class CLIHandler { constructor() { - this.commandDefinitions = [] - this.commands = {} + this.commandDefinitions = []; + this.commands = {}; this.name = '' } @@ -36,14 +36,14 @@ class CLIHandler { header: key, optionList: this.commandDefinitions, group: [key], - })) + })); const commandsList = { header: 'Command List', content: Object.keys(this.commands).map((key) => ({ name: key, summary: this.commands[key], })), - } + }; const sections = [ { @@ -52,16 +52,16 @@ class CLIHandler { }, ].concat(hasCommands ? commandsList : []) .concat(showOptions ? options : []) - .concat(additionalSection) + .concat(additionalSection); const usage = [ { header: 'ioFogController', content: 'Fog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.', } - ].concat(sections) + ].concat(sections); console.log(commandLineUsage(usage)) } } -module.exports = CLIHandler \ No newline at end of file +module.exports = CLIHandler; \ No newline at end of file diff --git a/src/cli/catalog.js b/src/cli/catalog.js index 9a6b50152..155482e72 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -52,28 +52,93 @@ class Catalog extends BaseCLIHandler { this.name = constants.CMD_CATALOG; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: [constants.CMD] }, - { name: 'file', alias: 'f', type: String, description: 'Catalog item settings JSON file', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'item-id', alias: 'i', type: String, description: 'Catalog item ID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO] }, - { name: 'name', alias: 'n', type: String, description: 'Catalog item name', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'description', alias: 'd', type: String, description: 'Catalog item description', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'category', alias: 'c', type: String, description: 'Catalog item category', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'x86-image', alias: 'x', type: String, description: 'x86 docker image name', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'arm-image', alias: 'a', type: String, description: 'ARM docker image name', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'publisher', alias: 'p', type: String, description: 'Catalog item publisher name', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'disk-required', alias: 's', type: Number, description: 'Amount of disk required to run the microservice (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'ram-required', alias: 'r', type: Number, description: 'Amount of RAM required to run the microservice (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'picture', alias: 't', type: String, description: 'Catalog item picture', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'public', alias: 'P', type: Boolean, description: 'Public catalog item', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'private', alias: 'V', type: Boolean, description: 'Private catalog item', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'registry-id', alias: 'g', type: Number, description: 'Catalog item docker registry ID', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'input-type', alias: 'I', type: String, description: 'Catalog item input type', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'input-format', alias: 'F', type: String, description: 'Catalog item input format', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'output-type', alias: 'O', type: String, description: 'Catalog item output type', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'output-format', alias: 'T', type: String, description: 'Catalog item output format', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'config-example', alias: 'X', type: String, description: 'Catalog item config example', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'user-id', alias: 'u', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] }, - ] + { + name: 'command', defaultOption: true, + group: [constants.CMD] + }, + { + name: 'file', alias: 'f', type: String, description: 'Catalog item settings JSON file', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'item-id', alias: 'i', type: String, description: 'Catalog item ID', + group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO] + }, + { + name: 'name', alias: 'n', type: String, description: 'Catalog item name', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'description', alias: 'd', type: String, description: 'Catalog item description', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'category', alias: 'c', type: String, description: 'Catalog item category', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'x86-image', alias: 'x', type: String, description: 'x86 docker image name', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'arm-image', alias: 'a', type: String, description: 'ARM docker image name', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'publisher', alias: 'p', type: String, description: 'Catalog item publisher name', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'disk-required', alias: 's', type: Number, + description: 'Amount of disk required to run the microservice (MB)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'ram-required', alias: 'r', type: Number, + description: 'Amount of RAM required to run the microservice (MB)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'picture', alias: 't', type: String, description: 'Catalog item picture', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'public', alias: 'P', type: Boolean, description: 'Public catalog item', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'private', alias: 'V', type: Boolean, description: 'Private catalog item', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'registry-id', alias: 'g', type: Number, description: 'Catalog item docker registry ID', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'input-type', alias: 'I', type: String, description: 'Catalog item input type', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'input-format', alias: 'F', type: String, description: 'Catalog item input format', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'output-type', alias: 'O', type: String, description: 'Catalog item output type', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'output-format', alias: 'T', type: String, description: 'Catalog item output format', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'config-example', alias: 'X', type: String, description: 'Catalog item config example', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'user-id', alias: 'u', type: Number, description: 'User\'s id', + group: [constants.CMD_ADD] + }, + ]; this.commands = { [constants.CMD_ADD]: 'Add a new catalog item.', [constants.CMD_UPDATE]: 'Update existing catalog item.', @@ -84,27 +149,31 @@ class Catalog extends BaseCLIHandler { } async run(args) { - const catalogCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv}); - - switch (catalogCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(catalogCommand, constants.CMD_ADD, _createCatalogItem, true); - break; - case constants.CMD_UPDATE: - await _executeCase(catalogCommand, constants.CMD_UPDATE, _updateCatalogItem, false); - break; - case constants.CMD_REMOVE: - await _executeCase(catalogCommand, constants.CMD_REMOVE, _deleteCatalogItem, false); - break; - case constants.CMD_LIST: - await _executeCase(catalogCommand, constants.CMD_LIST, _listCatalogItems, false); - break; - case constants.CMD_INFO: - await _executeCase(catalogCommand, constants.CMD_INFO, _listCatalogItem, false); - break; - case constants.CMD_HELP: - default: - return this.help() + try { + const catalogCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (catalogCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(catalogCommand, constants.CMD_ADD, _createCatalogItem, true); + break; + case constants.CMD_UPDATE: + await _executeCase(catalogCommand, constants.CMD_UPDATE, _updateCatalogItem, false); + break; + case constants.CMD_REMOVE: + await _executeCase(catalogCommand, constants.CMD_REMOVE, _deleteCatalogItem, false); + break; + case constants.CMD_LIST: + await _executeCase(catalogCommand, constants.CMD_LIST, _listCatalogItems, false); + break; + case constants.CMD_INFO: + await _executeCase(catalogCommand, constants.CMD_INFO, _listCatalogItem, false); + break; + case constants.CMD_HELP: + default: + return this.help() + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -121,7 +190,7 @@ class Catalog extends BaseCLIHandler { } } -const _executeCase = async function (catalogCommand, commandName, f, isUserRequired) { +const _executeCase = async function (catalogCommand, commandName, f, isUserRequired) { try { const item = catalogCommand[commandName]; diff --git a/src/cli/config.js b/src/cli/config.js index 66511d22c..c8a654279 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -25,19 +25,64 @@ class Config extends BaseCLIHandler { this.name = constants.CMD_CONFIG; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: constants.CMD }, - { name: 'port', alias: 'p', type: Number, description: 'Port', group: constants.CMD_ADD }, - { name: 'ssl-cert', alias: 'c', type: String, description: 'Path to SSL certificate file', group: constants.CMD_ADD }, - { name: 'ssl-key', alias: 'k', type: String, description: 'Path to SSL key file', group: constants.CMD_ADD }, - { name: 'intermediate-cert', alias: 'i', type: String, description: 'Path to SSL intermediate certificate file', group: constants.CMD_ADD }, - { name: 'home-url', alias: 'h', type: String, description: 'Home page url for email activation links', group: constants.CMD_ADD }, - { name: 'email-address', alias: 'a', type: String, description: 'Email address to send activations from', group: constants.CMD_ADD }, - { name: 'email-password', alias: 'w', type: String, description: 'Email password to send activations from', group: constants.CMD_ADD }, - { name: 'email-service', alias: 's', type: String, description: 'Email service to send activations', group: constants.CMD_ADD }, - { name: 'log-dir', alias: 'd', type: String, description: 'Log files directory', group: constants.CMD_ADD }, - { name: 'log-size', alias: 'z', type: Number, description: 'Log files size (MB)', group: constants.CMD_ADD }, - { name: 'on', alias: 'o', type: Boolean, description: 'Enable', group: [constants.CMD_DEV_MODE, constants.CMD_EMAIL_ACTIVATION] }, - { name: 'off', alias: 'f', type: Boolean, description: 'Disable', group: [constants.CMD_DEV_MODE, constants.CMD_EMAIL_ACTIVATION] }, + { + name: 'command', defaultOption: true, + group: constants.CMD + }, + { + name: 'port', alias: 'p', type: Number, description: 'Port', + group: constants.CMD_ADD + }, + { + name: 'ssl-cert', alias: 'c', type: String, + description: 'Path to SSL certificate file', + group: constants.CMD_ADD + }, + { + name: 'ssl-key', alias: 'k', type: String, description: 'Path to SSL key file', + group: constants.CMD_ADD + }, + { + name: 'intermediate-cert', alias: 'i', type: String, + description: 'Path to SSL intermediate certificate file', + group: constants.CMD_ADD + }, + { + name: 'home-url', alias: 'h', type: String, + description: 'Home page url for email activation links', + group: constants.CMD_ADD + }, + { + name: 'email-address', alias: 'a', type: String, + description: 'Email address to send activations from', + group: constants.CMD_ADD + }, + { + name: 'email-password', alias: 'w', type: String, + description: 'Email password to send activations from', + group: constants.CMD_ADD + }, + { + name: 'email-service', alias: 's', type: String, + description: 'Email service to send activations', + group: constants.CMD_ADD + }, + { + name: 'log-dir', alias: 'd', type: String, description: 'Log files directory', + group: constants.CMD_ADD + }, + { + name: 'log-size', alias: 'z', type: Number, + description: 'Log files size (MB)', group: constants.CMD_ADD + }, + { + name: 'on', alias: 'o', type: Boolean, description: 'Enable', + group: [constants.CMD_DEV_MODE, constants.CMD_EMAIL_ACTIVATION] + }, + { + name: 'off', alias: 'f', type: Boolean, description: 'Disable', + group: [constants.CMD_DEV_MODE, constants.CMD_EMAIL_ACTIVATION] + }, ]; this.commands = { [constants.CMD_ADD]: 'Add a new config value.', @@ -48,29 +93,33 @@ class Config extends BaseCLIHandler { } async run(args) { - const configCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv}); - - switch (configCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(configCommand, constants.CMD_ADD, _addConfigOption); - break; - case constants.CMD_LIST: - await _executeCase(configCommand, constants.CMD_LIST, _listConfigOptions); - break; - case constants.CMD_DEV_MODE: - await _executeCase(configCommand, constants.CMD_DEV_MODE, _changeDevModeState); - break; - case constants.CMD_EMAIL_ACTIVATION: - await _executeCase(configCommand, constants.CMD_EMAIL_ACTIVATION, _changeEmailActivationState); - break; - case constants.CMD_HELP: - default: - return this.help([], true, false) + try { + const configCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (configCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(configCommand, constants.CMD_ADD, _addConfigOption); + break; + case constants.CMD_LIST: + await _executeCase(configCommand, constants.CMD_LIST, _listConfigOptions); + break; + case constants.CMD_DEV_MODE: + await _executeCase(configCommand, constants.CMD_DEV_MODE, _changeDevModeState); + break; + case constants.CMD_EMAIL_ACTIVATION: + await _executeCase(configCommand, constants.CMD_EMAIL_ACTIVATION, _changeEmailActivationState); + break; + case constants.CMD_HELP: + default: + return this.help([], true, false) + } + } catch (error) { + AppHelper.handleCLIError(error); } } } -const _executeCase = async function (catalogCommand, commandName, f) { +const _executeCase = async function (catalogCommand, commandName, f) { try { const item = catalogCommand[commandName]; await f(item); @@ -162,7 +211,7 @@ const updateConfig = async function (newConfigValue, cliConfigName, configName, if (newConfigValue) { const oldConfigValue = config.get(configName); if (newConfigValue !== oldConfigValue) { - await fn(function() { + await fn(function () { const currentConfigValue = config.get(configName); logger.info(`Config option ${cliConfigName} has been set to ${currentConfigValue}`); }); @@ -197,7 +246,7 @@ const _listConfigOptions = function () { const _changeDevModeState = function (options) { const enableDevMode = AppHelper.validateBooleanCliOptions(options.on, options.off); - config.set('Server:DevMode', enableDevMode) + config.set('Server:DevMode', enableDevMode); logger.info('Dev mode state updated successfully.') }; diff --git a/src/cli/connector.js b/src/cli/connector.js index a2f76102f..353b698e5 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -11,28 +11,65 @@ * */ -const BaseCLIHandler = require('./base-cli-handler') -const constants = require('../helpers/constants') -const logger = require('../logger') -const ConnectorService = require('../services/connector-service') -const AppHelper = require('../helpers/app-helper') + +const BaseCLIHandler = require('./base-cli-handler'); +const constants = require('../helpers/constants'); +const logger = require('../logger'); +const ConnectorService = require('../services/connector-service'); +const AppHelper = require('../helpers/app-helper'); +const CliDecorator = require("../decorators/cli-decorator"); class Connector extends BaseCLIHandler { constructor() { - super() + super(); - this.name = constants.CMD_CONNECTOR + this.name = constants.CMD_CONNECTOR; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: [constants.CMD] }, - { name: 'name', alias: 'n', type: String, description: 'Connector name', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'domain', alias: 'd', type: String, description: 'Connector domain name', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'public-ip', alias: 'i', type: String, description: 'Connector public IP address', group: [constants.CMD_ADD, constants.CMD_UPDATE, constants.CMD_REMOVE] }, - { name: 'cert', alias: 'c', type: String, description: 'Certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'self-signed-on', alias: 'S', type: Boolean, description: 'Switch on self-signed enabled', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'self-signed-off', alias: 's', type: Boolean, description: 'Switch off self-signed disabled', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'dev-mode-on', alias: 'H', type: Boolean, description: 'Switch on dev mode', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'dev-mode-off', alias: 'h', type: Boolean, description: 'Switch off dev mode', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - ] + { + name: 'command', defaultOption: true, + group: [constants.CMD] + }, + { + name: 'name', alias: 'n', type: String, + description: 'Connector name', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'domain', alias: 'd', type: String, + description: 'Connector domain name', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'public-ip', alias: 'i', type: String, + description: 'Connector public IP address', + group: [constants.CMD_ADD, constants.CMD_UPDATE, constants.CMD_REMOVE] + }, + { + name: 'cert', alias: 'c', type: String, + description: 'Certificate', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'self-signed-on', alias: 'S', type: Boolean, + description: 'Switch on self-signed enabled', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'self-signed-off', alias: 's', type: Boolean, + description: 'Switch off self-signed disabled', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'dev-mode-on', alias: 'H', type: Boolean, + description: 'Switch on dev mode', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'dev-mode-off', alias: 'h', type: Boolean, + description: 'Switch off dev mode', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + } + ]; this.commands = { [constants.CMD_ADD]: 'Add a new Connector.', [constants.CMD_UPDATE]: 'Update existing Connector.', @@ -42,24 +79,28 @@ class Connector extends BaseCLIHandler { } async run(args) { - const connectorCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }) - - switch (connectorCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(connectorCommand, constants.CMD_ADD, _createConnector, false) - break - case constants.CMD_UPDATE: - await _executeCase(connectorCommand, constants.CMD_UPDATE, _updateConnector, false) - break - case constants.CMD_REMOVE: - await _executeCase(connectorCommand, constants.CMD_REMOVE, _deleteConnector, false) - break - case constants.CMD_LIST: - await _executeCase(connectorCommand, constants.CMD_LIST, _getConnectorList, false) - break - case constants.CMD_HELP: - default: - return this.help([constants.CMD_LIST]) + try { + const connectorCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (connectorCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(connectorCommand, constants.CMD_ADD, _createConnector, false); + break; + case constants.CMD_UPDATE: + await _executeCase(connectorCommand, constants.CMD_UPDATE, _updateConnector, false); + break; + case constants.CMD_REMOVE: + await _executeCase(connectorCommand, constants.CMD_REMOVE, _deleteConnector, false); + break; + case constants.CMD_LIST: + await _executeCase(connectorCommand, constants.CMD_LIST, _getConnectorList, false); + break; + case constants.CMD_HELP: + default: + return this.help([constants.CMD_LIST]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -81,10 +122,10 @@ async function _executeCase(commands, commandName, f, isUserRequired) { } async function _createConnector(obj) { - const connector = _createConnectorObject(obj) + const connector = _createConnectorObject(obj); logger.info(JSON.stringify(connector)); try { - const result = await ConnectorService.createConnector(connector) + const result = await ConnectorService.createConnector(connector); logger.info(JSON.stringify(result)); logger.info('Connector has been created successfully.'); } catch (e) { @@ -93,10 +134,10 @@ async function _createConnector(obj) { } async function _updateConnector(obj) { - const connector = _createConnectorObject(obj) + const connector = _createConnectorObject(obj); logger.info(JSON.stringify(connector)); try { - await ConnectorService.updateConnector(connector) + await ConnectorService.updateConnector(connector); logger.info('Connector has been updated successfully.'); } catch (e) { logger.info(e.message) @@ -104,10 +145,10 @@ async function _updateConnector(obj) { } async function _deleteConnector(obj) { - const connector = _createConnectorObject(obj) + const connector = _createConnectorObject(obj); logger.info(JSON.stringify(connector)); try { - await ConnectorService.deleteConnector(connector) + await ConnectorService.deleteConnector(connector); logger.info('Connector has been removed successfully.'); } catch (e) { logger.info(e.message) @@ -115,7 +156,7 @@ async function _deleteConnector(obj) { } async function _getConnectorList(obj) { - const list = await ConnectorService.getConnectorList() + const list = await ConnectorService.getConnectorList(); logger.info(JSON.stringify(list, null, 2)); logger.info('Connector list has been gotten successfully'); } @@ -128,9 +169,9 @@ function _createConnectorObject(cliData) { cert: cliData.cert, isSelfSignedCert: AppHelper.validateBooleanCliOptions(cliData.selfSignedEnable, cliData.selfSignedDisable), devMode: AppHelper.validateBooleanCliOptions(cliData.devModeOn, cliData.devModeOff) - } + }; return AppHelper.deleteUndefinedFields(connectorObj); } -module.exports = new Connector() \ No newline at end of file +module.exports = new Connector(); \ No newline at end of file diff --git a/src/cli/controller.js b/src/cli/controller.js index f76e91b7e..220fa5ad3 100644 --- a/src/cli/controller.js +++ b/src/cli/controller.js @@ -24,8 +24,10 @@ class Controller extends BaseCLIHandler { this.name = constants.CMD_CONTROLLER; this.commandDefinitions = [ { - name: 'command', defaultOption: true, description: 'status, email-activation, fog-types, version', - group: constants.CMD, + name: 'command', + defaultOption: true, + description: 'status, email-activation, fog-types, version', + group: constants.CMD } ]; this.commands = { @@ -37,24 +39,28 @@ class Controller extends BaseCLIHandler { } async run(args) { - const controllerCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv}); + try { + const controllerCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (controllerCommand.command.command) { - case constants.CMD_STATUS: - await _executeCase(controllerCommand, constants.CMD_STATUS, _getStatus, false); - break; - case constants.CMD_EMAIL_ACTIVATION: - await _executeCase(controllerCommand, constants.CMD_EMAIL_ACTIVATION, _emailActivation, false); - break; - case constants.CMD_FOG_TYPES: - await _executeCase(controllerCommand, constants.CMD_FOG_TYPES, _getFogTypes, false); - break; - case constants.CMD_VERSION: - await _executeCase(controllerCommand, constants.CMD_VERSION, _getVersion, false); - break; - case constants.CMD_HELP: - default: - return this.help([constants.CMD_LIST]) + switch (controllerCommand.command.command) { + case constants.CMD_STATUS: + await _executeCase(controllerCommand, constants.CMD_STATUS, _getStatus, false); + break; + case constants.CMD_EMAIL_ACTIVATION: + await _executeCase(controllerCommand, constants.CMD_EMAIL_ACTIVATION, _emailActivation, false); + break; + case constants.CMD_FOG_TYPES: + await _executeCase(controllerCommand, constants.CMD_FOG_TYPES, _getFogTypes, false); + break; + case constants.CMD_VERSION: + await _executeCase(controllerCommand, constants.CMD_VERSION, _getVersion, false); + break; + case constants.CMD_HELP: + default: + return this.help([constants.CMD_LIST]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -82,16 +88,16 @@ const _getStatus = async function () { }; const _emailActivation = async function () { - const response = await ControllerService.emailActivation(true); + const response = await ControllerService.emailActivation(true); logger.info(JSON.stringify(response, null, 2)); }; const _getFogTypes = async function () { - const response = await ControllerService.getFogTypes(true); + const response = await ControllerService.getFogTypes(true); logger.info(JSON.stringify(response, null, 2)); }; -const _getVersion = async function() { +const _getVersion = async function () { const response = await ControllerService.getVersion(true); logger.info(response, null, 2); }; diff --git a/src/cli/diagnostics.js b/src/cli/diagnostics.js index a069abb2f..d861dc686 100644 --- a/src/cli/diagnostics.js +++ b/src/cli/diagnostics.js @@ -21,7 +21,7 @@ const AuthDecorator = require('../decorators/cli-decorator'); class Diagnostics extends BaseCLIHandler { constructor() { - super() + super(); this.name = constants.CMD_DIAGNOSTICS; this.commandDefinitions = [ @@ -35,12 +35,12 @@ class Diagnostics extends BaseCLIHandler { }, { name: 'disable', alias: 'o', type: Boolean, description: 'Disable microservice strace', - group: [constants.CMD_STRACE_UPDATE ] + group: [constants.CMD_STRACE_UPDATE] }, { name: 'microservice-id', alias: 'i', type: String, description: 'Microservice ID', group: [constants.CMD_STRACE_UPDATE, constants.CMD_STRACE_INFO, constants.CMD_STRACE_FTP_POST, - constants.CMD_IMAGE_SNAPSHOT_CREATE, constants.CMD_IMAGE_SNAPSHOT_GET] + constants.CMD_IMAGE_SNAPSHOT_CREATE, constants.CMD_IMAGE_SNAPSHOT_GET] }, { name: 'format', alias: 'f', type: String, description: 'Format of strace data to receive', @@ -66,7 +66,7 @@ class Diagnostics extends BaseCLIHandler { name: 'ftpDestDir', alias: 'd', type: String, description: 'FTP destination directory', group: [constants.CMD_STRACE_FTP_POST] }, - ] + ]; this.commands = { [constants.CMD_STRACE_UPDATE]: 'Change microservice strace status to enabled or disabled.', [constants.CMD_STRACE_INFO]: 'Get microservice strace data.', @@ -77,32 +77,36 @@ class Diagnostics extends BaseCLIHandler { } async run(args) { - const diagnosticCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }) - - switch (diagnosticCommand.command.command) { - case constants.CMD_STRACE_UPDATE: - await _executeCase(diagnosticCommand, constants.CMD_STRACE_UPDATE, _changeMicroserviceStraceState, false); - break; - case constants.CMD_STRACE_INFO: - await _executeCase(diagnosticCommand, constants.CMD_STRACE_INFO, _getMicroserviceStraceData, false); - break; - case constants.CMD_STRACE_FTP_POST: - await _executeCase(diagnosticCommand, constants.CMD_STRACE_FTP_POST, _postMicroserviceStraceDataToFtp, false); - break; - case constants.CMD_IMAGE_SNAPSHOT_CREATE: - await _executeCase(diagnosticCommand, constants.CMD_IMAGE_SNAPSHOT_CREATE, _postMicroserviceImageSnapshotCreate, false); - break; - case constants.CMD_IMAGE_SNAPSHOT_GET: - await _executeCase(diagnosticCommand, constants.CMD_IMAGE_SNAPSHOT_GET, _getMicroserviceImageSnapshot, false); - break; - case constants.CMD_HELP: - default: - return this.help([constants.CMD_LIST]) + try { + const diagnosticCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (diagnosticCommand.command.command) { + case constants.CMD_STRACE_UPDATE: + await _executeCase(diagnosticCommand, constants.CMD_STRACE_UPDATE, _changeMicroserviceStraceState, false); + break; + case constants.CMD_STRACE_INFO: + await _executeCase(diagnosticCommand, constants.CMD_STRACE_INFO, _getMicroserviceStraceData, false); + break; + case constants.CMD_STRACE_FTP_POST: + await _executeCase(diagnosticCommand, constants.CMD_STRACE_FTP_POST, _postMicroserviceStraceDataToFtp, false); + break; + case constants.CMD_IMAGE_SNAPSHOT_CREATE: + await _executeCase(diagnosticCommand, constants.CMD_IMAGE_SNAPSHOT_CREATE, _postMicroserviceImageSnapshotCreate, false); + break; + case constants.CMD_IMAGE_SNAPSHOT_GET: + await _executeCase(diagnosticCommand, constants.CMD_IMAGE_SNAPSHOT_GET, _getMicroserviceImageSnapshot, false); + break; + case constants.CMD_HELP: + default: + return this.help([constants.CMD_LIST]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } } -const _executeCase = async function (diagnosticCommand, commandName, f, isUserRequired) { +const _executeCase = async function (diagnosticCommand, commandName, f, isUserRequired) { try { const item = diagnosticCommand[commandName]; diff --git a/src/cli/flow.js b/src/cli/flow.js index 77a3f15a1..f577a6e2f 100644 --- a/src/cli/flow.js +++ b/src/cli/flow.js @@ -31,14 +31,45 @@ class Flow extends BaseCLIHandler { this.name = constants.CMD_FLOW; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: [constants.CMD] }, - { name: 'file', alias: 'f', type: String, description: 'Application flow settings JSON file', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'flow-id', alias: 'i', type: String, description: 'Application flow ID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO] }, - { name: 'name', alias: 'n', type: String, description: 'Application flow name', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'description', alias: 'd', type: String, description: 'Application flow description', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'activate', alias: 'a', type: Boolean, description: 'Activate application flow', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'deactivate', alias: 'D', type: Boolean, description: 'Deactivate application flow', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'user-id', alias: 'u', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] }, + { + name: 'command', defaultOption: true, + group: [constants.CMD] + }, + { + name: 'file', alias: 'f', type: String, + description: 'Application flow settings JSON file', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'flow-id', alias: 'i', type: String, + description: 'Application flow ID', + group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO] + }, + { + name: 'name', alias: 'n', type: String, + description: 'Application flow name', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'description', alias: 'd', type: String, + description: 'Application flow description', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'activate', alias: 'a', type: Boolean, + description: 'Activate application flow', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'deactivate', alias: 'D', type: Boolean, + description: 'Deactivate application flow', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'user-id', alias: 'u', type: Number, + description: 'User\'s id', + group: [constants.CMD_ADD] + } ]; this.commands = { [constants.CMD_ADD]: 'Add a new flow.', @@ -50,27 +81,31 @@ class Flow extends BaseCLIHandler { } async run(args) { - const flowCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }); - - switch (flowCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(flowCommand, constants.CMD_ADD, _createFlow, true); - break; - case constants.CMD_UPDATE: - await _executeCase(flowCommand, constants.CMD_UPDATE, _updateFlow, false); - break; - case constants.CMD_REMOVE: - await _executeCase(flowCommand, constants.CMD_REMOVE, _deleteFlow, false); - break; - case constants.CMD_LIST: - await _executeCase(flowCommand, constants.CMD_LIST, _getAllFlows, false); - break; - case constants.CMD_INFO: - await _executeCase(flowCommand, constants.CMD_INFO, _getFlow, false); - break; - case constants.CMD_HELP: - default: - return this.help([constants.CMD_LIST]) + try { + const flowCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (flowCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(flowCommand, constants.CMD_ADD, _createFlow, true); + break; + case constants.CMD_UPDATE: + await _executeCase(flowCommand, constants.CMD_UPDATE, _updateFlow, false); + break; + case constants.CMD_REMOVE: + await _executeCase(flowCommand, constants.CMD_REMOVE, _deleteFlow, false); + break; + case constants.CMD_LIST: + await _executeCase(flowCommand, constants.CMD_LIST, _getAllFlows, false); + break; + case constants.CMD_INFO: + await _executeCase(flowCommand, constants.CMD_INFO, _getFlow, false); + break; + case constants.CMD_HELP: + default: + return this.help([constants.CMD_LIST]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -152,13 +187,13 @@ const _getFlow = async function (flowData) { function _createFlowObject(data) { const flow = { - id: data.id, - name: data.name, - description: data.description, - isActivated: AppHelper.validateBooleanCliOptions(data.activate, data.deactivate) - }; + id: data.id, + name: data.name, + description: data.description, + isActivated: AppHelper.validateBooleanCliOptions(data.activate, data.deactivate) + }; - return AppHelper.deleteUndefinedFields(flow); + return AppHelper.deleteUndefinedFields(flow); } module.exports = new Flow(); \ No newline at end of file diff --git a/src/cli/index.js b/src/cli/index.js index 9babb2044..a8fea548d 100644 --- a/src/cli/index.js +++ b/src/cli/index.js @@ -11,28 +11,28 @@ * */ -const BaseCLIHandler = require('./base-cli-handler') -const Start = require('./start') -const User = require('./user') -const Connector = require('./connector') -const Config = require('./config') -const Tunnel = require('./tunnel') -const IOFog = require('./iofog') -const Catalog = require('./catalog') -const Flow = require('./flow') -const Microservice = require('./microservice') -const Registry = require('./registry') -const Controller = require('./controller') -const Diagnostics = require('./diagnostics') +const BaseCLIHandler = require('./base-cli-handler'); +const Start = require('./start'); +const User = require('./user'); +const Connector = require('./connector'); +const Config = require('./config'); +const Tunnel = require('./tunnel'); +const IOFog = require('./iofog'); +const Catalog = require('./catalog'); +const Flow = require('./flow'); +const Microservice = require('./microservice'); +const Registry = require('./registry'); +const Controller = require('./controller'); +const Diagnostics = require('./diagnostics'); -const constants = require('../helpers/constants') +const constants = require('../helpers/constants'); class Cli extends BaseCLIHandler { constructor() { - super() + super(); this.commandDefinitions = [ { name: 'command', defaultOption: true }, - ] + ]; this.commands = { [constants.CMD_START]: 'Start iofog-controller service.', [constants.CMD_STOP]: 'Stop iofog-controller service.', @@ -52,36 +52,36 @@ class Cli extends BaseCLIHandler { } run(daemon) { - const mainCommand = this.parseCommandLineArgs(this.commandDefinitions) - const argv = mainCommand._unknown || [] + const mainCommand = this.parseCommandLineArgs(this.commandDefinitions); + const argv = mainCommand._unknown || []; switch (mainCommand.command) { case constants.CMD_START: - return Start.run({ daemon }) + return Start.run({ daemon }); case constants.CMD_STOP: - return daemon.stop() + return daemon.stop(); case constants.CMD_CONTROLLER: - return Controller.run({ argv }) + return Controller.run({ argv }); case constants.CMD_USER: - return User.run({ argv }) + return User.run({ argv }); case constants.CMD_CONFIG: - return Config.run({ argv }) + return Config.run({ argv }); case constants.CMD_CONNECTOR: - return Connector.run({ argv }) + return Connector.run({ argv }); case constants.CMD_TUNNEL: - return Tunnel.run({ argv }) + return Tunnel.run({ argv }); case constants.CMD_IOFOG: - return IOFog.run({ argv }) + return IOFog.run({ argv }); case constants.CMD_CATALOG: - return Catalog.run({ argv }) + return Catalog.run({ argv }); case constants.CMD_FLOW: - return Flow.run({ argv }) + return Flow.run({ argv }); case constants.CMD_MICROSERVICE: - return Microservice.run({ argv }) + return Microservice.run({ argv }); case constants.CMD_REGISTRY: - return Registry.run({ argv }) + return Registry.run({ argv }); case constants.CMD_DIAGNOSTICS: - return Diagnostics.run({ argv }) + return Diagnostics.run({ argv }); case constants.CMD_HELP: default: return this.help([], false) @@ -89,4 +89,4 @@ class Cli extends BaseCLIHandler { } } -module.exports = Cli \ No newline at end of file +module.exports = Cli; \ No newline at end of file diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 2318808fe..64edcca56 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -11,13 +11,13 @@ * */ -const BaseCLIHandler = require('./base-cli-handler') -const constants = require('../helpers/constants') -const logger = require('../logger') +const BaseCLIHandler = require('./base-cli-handler'); +const constants = require('../helpers/constants'); +const logger = require('../logger'); const fs = require('fs'); -const CliDecorator = require('../decorators/cli-decorator') -const AppHelper = require('../helpers/app-helper') -const FogService = require('../services/iofog-service') +const CliDecorator = require('../decorators/cli-decorator'); +const AppHelper = require('../helpers/app-helper'); +const FogService = require('../services/iofog-service'); const JSON_SCHEMA = AppHelper.stringifyCliJsonSchema({ name: "string", @@ -44,40 +44,155 @@ const JSON_SCHEMA = AppHelper.stringifyCliJsonSchema({ class IOFog extends BaseCLIHandler { constructor() { - super() + super(); - this.name = constants.CMD_IOFOG + this.name = constants.CMD_IOFOG; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: [constants.CMD] }, - { name: 'file', alias: 'f', type: String, description: 'ioFog settings JSON file', group: [constants.CMD_ADD, constants.CMD_UPDATE] }, - { name: 'node-id', alias: 'i', type: String, description: 'ioFog node ID', group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PROVISIONING_KEY, constants.CMD_IOFOG_REBOOT, constants.CMD_VERSION, constants.CMD_HAL_HW, constants.CMD_HAL_USB] }, - { name: 'name', alias: 'n', type: String, description: 'ioFog node name', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'location', alias: 'l', type: String, description: 'ioFog node location', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'latitude', alias: 't', type: Number, description: 'ioFog node latitude', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'longitude', alias: 'g', type: Number, description: 'ioFog node longitude', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'description', alias: 'd', type: String, description: 'ioFog node description', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'docker-url', alias: 'D', type: String, description: 'ioFog node docker url', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'disk-limit', alias: 'M', type: Number, description: 'ioFog node disk usage limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'disk-directory', alias: 'T', type: String, description: 'ioFog node disk directory', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'memory-limit', alias: 'm', type: Number, description: 'ioFog node memory usage limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'cpu-limit', alias: 'c', type: Number, description: 'ioFog node CPU usage limit (%)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'log-limit', alias: 'G', type: Number, description: 'ioFog node log size limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'log-directory', alias: 'Y', type: String, description: 'ioFog node log files directory', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'log-file-count', alias: 'C', type: Number, description: 'ioFog node log files count', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'status-frequency', alias: 's', type: Number, description: 'ioFog node status check frequency (seconds)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'change-frequency', alias: 'F', type: Number, description: 'ioFog node configuration change check frequency (seconds)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'device-frequency', alias: 'Q', type: Number, description: 'ioFog node device scan frequency (seconds)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'bluetooth-enable', alias: 'B', type: Boolean, description: 'Enable bluetooth on ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'bluetooth-disable', alias: 'b', type: Boolean, description: 'Disable bluetooth on ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'watchdog-enable', alias: 'W', type: Boolean, description: 'Enable watchdog on ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'watchdog-disable', alias: 'w', type: Boolean, description: 'Disable watchdog on ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'abs-hw-enable', alias: 'A', type: Boolean, description: 'Enable hardware abstraction on ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'abs-hw-disable', alias: 'a', type: Boolean, description: 'Disable hardware abstraction on ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'reboot', alias: 'o', type: Boolean, description: 'Reboot ioFog node', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'fog-type', alias: 'y', type: Number, description: 'ioFog node architecture type', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, - { name: 'version-command', alias: 'v', type: String, description: 'ioFog version command', group: [constants.CMD_VERSION] }, - { name: 'user-id', alias: 'u', type: Number, description: 'User\'s id', group: [constants.CMD_ADD] } - ] + { + name: 'command', defaultOption: true, + group: [constants.CMD]}, + { + name: 'file', alias: 'f', type: String, + description: 'ioFog settings JSON file', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'node-id', alias: 'i', type: String, + description: 'ioFog node ID', + group: [constants.CMD_UPDATE, constants.CMD_REMOVE, constants.CMD_INFO, constants.CMD_PROVISIONING_KEY, + constants.CMD_IOFOG_REBOOT, constants.CMD_VERSION, constants.CMD_HAL_HW, constants.CMD_HAL_USB] + }, + { + name: 'name', alias: 'n', type: String, + description: 'ioFog node name', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'location', alias: 'l', type: String, + description: 'ioFog node location', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'latitude', alias: 't', type: Number, + description: 'ioFog node latitude', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'longitude', alias: 'g', type: Number, + description: 'ioFog node longitude', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'description', alias: 'd', type: String, + description: 'ioFog node description', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'docker-url', alias: 'D', type: String, + description: 'ioFog node docker url', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'disk-limit', alias: 'M', type: Number, + description: 'ioFog node disk usage limit (MB)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'disk-directory', alias: 'T', type: String, + description: 'ioFog node disk directory', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'memory-limit', alias: 'm', type: Number, + description: 'ioFog node memory usage limit (MB)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'cpu-limit', alias: 'c', type: Number, + description: 'ioFog node CPU usage limit (%)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'log-limit', alias: 'G', type: Number, + description: 'ioFog node log size limit (MB)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'log-directory', alias: 'Y', type: String, + description: 'ioFog node log files directory', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'log-file-count', alias: 'C', type: Number, + description: 'ioFog node log files count', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'status-frequency', alias: 's', type: Number, + description: 'ioFog node status check frequency (seconds)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'change-frequency', alias: 'F', type: Number, + description: 'ioFog node configuration change check frequency (seconds)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'device-frequency', alias: 'Q', type: Number, + description: 'ioFog node device scan frequency (seconds)', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'bluetooth-enable', alias: 'B', type: Boolean, + description: 'Enable bluetooth on ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'bluetooth-disable', alias: 'b', type: Boolean, + description: 'Disable bluetooth on ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'watchdog-enable', alias: 'W', type: Boolean, + description: 'Enable watchdog on ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'watchdog-disable', alias: 'w', type: Boolean, + description: 'Disable watchdog on ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'abs-hw-enable', alias: 'A', type: Boolean, + description: 'Enable hardware abstraction on ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'abs-hw-disable', alias: 'a', type: Boolean, + description: 'Disable hardware abstraction on ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'reboot', alias: 'o', type: Boolean, + description: 'Reboot ioFog node', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'fog-type', alias: 'y', type: Number, + description: 'ioFog node architecture type', + group: [constants.CMD_UPDATE, constants.CMD_ADD] + }, + { + name: 'version-command', alias: 'v', type: String, + description: 'ioFog version command', + group: [constants.CMD_VERSION] + }, + { + name: 'user-id', alias: 'u', type: Number, + description: 'User\'s id', + group: [constants.CMD_ADD] + } + ]; this.commands = { [constants.CMD_ADD]: 'Add a new ioFog node.', [constants.CMD_UPDATE]: 'Update existing ioFog node.', @@ -93,42 +208,46 @@ class IOFog extends BaseCLIHandler { } async run(args) { - const iofogCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }) + try { + const iofogCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (iofogCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(iofogCommand, constants.CMD_ADD, _createFog, true); - break - case constants.CMD_UPDATE: - await _executeCase(iofogCommand, constants.CMD_UPDATE, _updateFog, false) - break - case constants.CMD_REMOVE: - await _executeCase(iofogCommand, constants.CMD_REMOVE, _deleteFog, false) - break - case constants.CMD_LIST: - await _executeCase(iofogCommand, constants.CMD_LIST, _getFogList, false) - break - case constants.CMD_INFO: - await _executeCase(iofogCommand, constants.CMD_INFO, _getFog, false) - break - case constants.CMD_PROVISIONING_KEY: - await _executeCase(iofogCommand, constants.CMD_PROVISIONING_KEY, _generateProvision, false) - break - case constants.CMD_IOFOG_REBOOT: - await _executeCase(iofogCommand, constants.CMD_IOFOG_REBOOT, _setFogRebootCommand, false) - break - case constants.CMD_VERSION: - await _executeCase(iofogCommand, constants.CMD_VERSION, _setFogVersionCommand, false) - break - case constants.CMD_HAL_HW: - await _executeCase(iofogCommand, constants.CMD_HAL_HW, _getHalHardwareInfo, false); - break; - case constants.CMD_HAL_USB: - await _executeCase(iofogCommand, constants.CMD_HAL_USB, _getHalUsbInfo, false); - break; - case constants.CMD_HELP: - default: - return this.help() + switch (iofogCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(iofogCommand, constants.CMD_ADD, _createFog, true); + break; + case constants.CMD_UPDATE: + await _executeCase(iofogCommand, constants.CMD_UPDATE, _updateFog, false); + break; + case constants.CMD_REMOVE: + await _executeCase(iofogCommand, constants.CMD_REMOVE, _deleteFog, false); + break; + case constants.CMD_LIST: + await _executeCase(iofogCommand, constants.CMD_LIST, _getFogList, false); + break; + case constants.CMD_INFO: + await _executeCase(iofogCommand, constants.CMD_INFO, _getFog, false); + break; + case constants.CMD_PROVISIONING_KEY: + await _executeCase(iofogCommand, constants.CMD_PROVISIONING_KEY, _generateProvision, false); + break; + case constants.CMD_IOFOG_REBOOT: + await _executeCase(iofogCommand, constants.CMD_IOFOG_REBOOT, _setFogRebootCommand, false); + break; + case constants.CMD_VERSION: + await _executeCase(iofogCommand, constants.CMD_VERSION, _setFogVersionCommand, false); + break; + case constants.CMD_HAL_HW: + await _executeCase(iofogCommand, constants.CMD_HAL_HW, _getHalHardwareInfo, false); + break; + case constants.CMD_HAL_USB: + await _executeCase(iofogCommand, constants.CMD_HAL_USB, _getHalUsbInfo, false); + break; + case constants.CMD_HELP: + default: + return this.help() + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -208,7 +327,7 @@ async function _generateProvision(obj, user) { const fog = _createFogObject(obj); logger.info(JSON.stringify(fog)); const res = await FogService.generateProvisioningKey(fog, user, true); - logger.info('Provisioning key: '+ JSON.stringify(res, null, 2)); + logger.info('Provisioning key: ' + JSON.stringify(res, null, 2)); logger.info('Fog provisioning key has been generated successfully.'); } @@ -278,9 +397,9 @@ function _createFogObject(cliData) { fogType: cliData.fogType, userId: cliData.userId - } + }; return AppHelper.deleteUndefinedFields(fogObj); } -module.exports = new IOFog() \ No newline at end of file +module.exports = new IOFog(); \ No newline at end of file diff --git a/src/cli/microservice.js b/src/cli/microservice.js index f96622a58..c9fb5637e 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -68,11 +68,14 @@ const JSON_SCHEMA_UPDATE = AppHelper.stringifyCliJsonSchema( class Microservice extends BaseCLIHandler { constructor() { - super() + super(); - this.name = constants.CMD_MICROSERVICE + this.name = constants.CMD_MICROSERVICE; this.commandDefinitions = [ - { name: 'command', defaultOption: true, group: [constants.CMD] }, + { + name: 'command', defaultOption: true, + group: [constants.CMD] + }, { name: 'file', alias: 'f', type: String, description: 'Microservice settings JSON file', group: [constants.CMD_ADD, constants.CMD_UPDATE] @@ -128,7 +131,9 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_PORT_MAPPING_CREATE, constants.CMD_VOLUME_MAPPING_CREATE] }, { - name: 'routes', alias: 't', type: String, description: 'Microservice route(s) (receiving microservices)', multiple: true, + name: 'routes', alias: 't', type: String, + description: 'Microservice route(s) (receiving microservices)', + multiple: true, group: [constants.CMD_ADD] }, { @@ -155,7 +160,7 @@ class Microservice extends BaseCLIHandler { name: 'mapping-id', alias: 'a', type: Number, description: 'Volume mapping id', group: [constants.CMD_VOLUME_MAPPING_REMOVE] } - ] + ]; this.commands = { [constants.CMD_ADD]: 'Add a new microservice.', [constants.CMD_UPDATE]: 'Update existing microservice.', @@ -174,51 +179,55 @@ class Microservice extends BaseCLIHandler { } async run(args) { - const microserviceCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }) - - switch (microserviceCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice); - break; - case constants.CMD_UPDATE: - await _executeCase(microserviceCommand, constants.CMD_UPDATE, _updateMicroservice); - break; - case constants.CMD_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_REMOVE, _removeMicroservice); - break; - case constants.CMD_LIST: - await _executeCase(microserviceCommand, constants.CMD_LIST, _listMicroservices); - break; - case constants.CMD_INFO: - await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice); - break; - case constants.CMD_ROUTE_CREATE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE_CREATE, _createRoute); - break; - case constants.CMD_ROUTE_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE_REMOVE, _removeRoute); - break; - case constants.CMD_PORT_MAPPING_CREATE: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_CREATE, _createPortMapping); - break; - case constants.CMD_PORT_MAPPING_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_REMOVE, _removePortMapping); - break; - case constants.CMD_PORT_MAPPING_LIST: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_LIST, _listPortMappings); - break; - case constants.CMD_VOLUME_MAPPING_CREATE: - await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_CREATE, _createVolumeMapping); - break; - case constants.CMD_VOLUME_MAPPING_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_REMOVE, _removeVolumeMapping); - break; - case constants.CMD_VOLUME_MAPPING_LIST: - await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_LIST, _listVolumeMappings); - break; - case constants.CMD_HELP: - default: - return this.help() + try { + const microserviceCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (microserviceCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice); + break; + case constants.CMD_UPDATE: + await _executeCase(microserviceCommand, constants.CMD_UPDATE, _updateMicroservice); + break; + case constants.CMD_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_REMOVE, _removeMicroservice); + break; + case constants.CMD_LIST: + await _executeCase(microserviceCommand, constants.CMD_LIST, _listMicroservices); + break; + case constants.CMD_INFO: + await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice); + break; + case constants.CMD_ROUTE_CREATE: + await _executeCase(microserviceCommand, constants.CMD_ROUTE_CREATE, _createRoute); + break; + case constants.CMD_ROUTE_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_ROUTE_REMOVE, _removeRoute); + break; + case constants.CMD_PORT_MAPPING_CREATE: + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_CREATE, _createPortMapping); + break; + case constants.CMD_PORT_MAPPING_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_REMOVE, _removePortMapping); + break; + case constants.CMD_PORT_MAPPING_LIST: + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_LIST, _listPortMappings); + break; + case constants.CMD_VOLUME_MAPPING_CREATE: + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_CREATE, _createVolumeMapping); + break; + case constants.CMD_VOLUME_MAPPING_REMOVE: + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_REMOVE, _removeVolumeMapping); + break; + case constants.CMD_VOLUME_MAPPING_LIST: + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_LIST, _listVolumeMappings); + break; + case constants.CMD_HELP: + default: + return this.help() + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -287,7 +296,7 @@ class Microservice extends BaseCLIHandler { } } -const _executeCase = async function (microserviceCommand, commandName, f) { +const _executeCase = async function (microserviceCommand, commandName, f) { try { const item = microserviceCommand[commandName] || {}; await f(item); @@ -345,7 +354,7 @@ const _removePortMapping = async function (obj) { const internalPort = parseInt(obj.internalPort); await MicroserviceService.deletePortMapping(obj.microserviceId, internalPort, {}, true); logger.info('Port mapping has been deleted successfully.'); - } catch(e) { + } catch (e) { logger.error(ErrorMessages.CLI.INVALID_INTERNAL_PORT); } }; @@ -355,7 +364,7 @@ const _removeVolumeMapping = async function (obj) { try { await MicroserviceService.deleteVolumeMapping(obj.microserviceId, obj.mappingId, {}, true); logger.info('Volume mapping has been deleted successfully.'); - } catch(e) { + } catch (e) { logger.error(ErrorMessages.CLI.INVALID_VOLUME_MAPPING); } }; @@ -462,7 +471,7 @@ const parseVolumeMappingObject = function (obj, errMsg) { containerDestination: props[1], accessMode: props[2] } - } catch(e) { + } catch (e) { logger.warn(errMsg); } return result; @@ -481,11 +490,11 @@ const parsePortMappingObject = function (obj, errMsg) { external: parseInt(props[1]), publicMode: props[2] === 'true' } - } catch(e) { + } catch (e) { logger.warn(errMsg); } return result; -} +}; const parsePortMappingArray = function (arr, errMsg) { return arr.map(obj => parsePortMappingObject(obj, errMsg)); diff --git a/src/cli/registry.js b/src/cli/registry.js index 93c722d36..a748f1a57 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -24,17 +24,60 @@ class Registry extends BaseCLIHandler { this.name = constants.CMD_REGISTRY; this.commandDefinitions = [ - {name: 'command', defaultOption: true, group: [constants.CMD]}, - {name: 'uri', alias: 'u', type: String, description: 'Registry URI', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'public', alias: 'b', type: Boolean, description: 'Set registry as public', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'private', alias: 'r', type: Boolean, description: 'Set registry as private', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'username', alias: 'l', type: String, description: 'Registry\'s user name', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'password', alias: 'p', type: String, description: 'Password', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'requires-certificate', alias: 'c', type: Boolean, description: 'Requires certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'certificate', alias: 'C', type: String, description: 'Certificate', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'email', alias: 'e', type: String, description: 'Email address', group: [constants.CMD_ADD, constants.CMD_UPDATE]}, - {name: 'user-id', alias: 'i', type: Number, description: 'User\'s id', group: [constants.CMD_ADD]}, - {name: 'item-id', alias: 'd', type: Number, description: 'Item\'s id', group: [constants.CMD_REMOVE, constants.CMD_UPDATE]} + { + name: 'command', defaultOption: true, + group: [constants.CMD] + }, + { + name: 'uri', alias: 'u', type: String, + description: 'Registry URI', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'public', alias: 'b', type: Boolean, + description: 'Set registry as public', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'private', alias: 'r', type: Boolean, + description: 'Set registry as private', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'username', alias: 'l', type: String, + description: 'Registry\'s user name', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'password', alias: 'p', type: String, + description: 'Password', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'requires-certificate', alias: 'c', type: Boolean, + description: 'Requires certificate', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'certificate', alias: 'C', type: String, + description: 'Certificate', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'email', alias: 'e', type: String, + description: 'Email address', + group: [constants.CMD_ADD, constants.CMD_UPDATE] + }, + { + name: 'user-id', alias: 'i', type: Number, + description: 'User\'s id', + group: [constants.CMD_ADD] + }, + { + name: 'item-id', alias: 'd', type: Number, + description: 'Item\'s id', + group: [constants.CMD_REMOVE, constants.CMD_UPDATE] + } ]; this.commands = { [constants.CMD_ADD]: 'Add a new Registry.', @@ -45,24 +88,28 @@ class Registry extends BaseCLIHandler { } async run(args) { - const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv}) + try { + const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (registryCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true); - break; - case constants.CMD_REMOVE: - await _executeCase(registryCommand, constants.CMD_REMOVE, _deleteRegistry, false); - break; - case constants.CMD_UPDATE: - await _executeCase(registryCommand, constants.CMD_UPDATE, _updateRegistry, false); - break; - case constants.CMD_LIST: - await _executeCase(registryCommand, constants.CMD_LIST, _getRegistries, false); - break; - case constants.CMD_HELP: - default: - return this.help([constants.CMD_LIST]) + switch (registryCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true); + break; + case constants.CMD_REMOVE: + await _executeCase(registryCommand, constants.CMD_REMOVE, _deleteRegistry, false); + break; + case constants.CMD_UPDATE: + await _executeCase(registryCommand, constants.CMD_UPDATE, _updateRegistry, false); + break; + case constants.CMD_LIST: + await _executeCase(registryCommand, constants.CMD_LIST, _getRegistries, false); + break; + case constants.CMD_HELP: + default: + return this.help([constants.CMD_LIST]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -87,7 +134,7 @@ async function _deleteRegistry(obj, user) { logger.info('Registry has been removed successfully.'); } -async function _updateRegistry (obj) { +async function _updateRegistry(obj) { const registry = _createRegistryObject(obj); logger.info(JSON.stringify(registry)); await RegistryService.updateRegistry(registry, obj.itemId, {}, true); diff --git a/src/cli/start.js b/src/cli/start.js index 275c911f8..27189f364 100644 --- a/src/cli/start.js +++ b/src/cli/start.js @@ -11,24 +11,24 @@ * */ -const BaseCLIHandler = require('./base-cli-handler') -const config = require('../config') -const logger = require('../logger') +const BaseCLIHandler = require('./base-cli-handler'); +const config = require('../config'); +const logger = require('../logger'); class Start extends BaseCLIHandler { run(args) { - const daemon = args.daemon + const daemon = args.daemon; const configuration = { devMode: config.get('Server:DevMode'), port: config.get('Server:Port'), sslKey: config.get('Server:SslKey'), sslCert: config.get('Server:SslCert'), intermedKey: config.get('Server:IntermediateCert'), - } - const pid = daemon.status() + }; + const pid = daemon.status(); - if (pid == 0) { - daemon.start() + if (pid === 0) { + daemon.start(); checkDaemon(daemon, configuration) } else { logger.silly(`iofog-controller already running. PID: ${pid}`) @@ -37,27 +37,27 @@ class Start extends BaseCLIHandler { } function checkDaemon(daemon, configuration) { - let iterationsCount = 0 + let iterationsCount = 0; const check = () => { - iterationsCount++ - let pid = daemon.status() + iterationsCount++; + let pid = daemon.status(); if (pid === 0) { return logger.error('Error: port is probably allocated, or ssl_key or ssl_cert or intermediate_cert is either missing or invalid.') } if (iterationsCount === 5) { - checkServerProtocol(configuration) + checkServerProtocol(configuration); return logger.silly(`ioFog-Controller has started at pid: ${pid}`) } setTimeout(check, 1000) - } + }; setTimeout(check, 1000) } function checkServerProtocol(configuration) { - const { devMode, port, sslKey, sslCert, intermedKey } = configuration + const { devMode, port, sslKey, sslCert, intermedKey } = configuration; if (!devMode && sslKey && sslCert && intermedKey) { logger.silly(`==> 🌎 HTTPS server listening on port ${port}. Open up https://localhost:${port}/ in your browser.`) } else { @@ -65,4 +65,4 @@ function checkServerProtocol(configuration) { } } -module.exports = new Start() \ No newline at end of file +module.exports = new Start(); \ No newline at end of file diff --git a/src/cli/tunnel.js b/src/cli/tunnel.js index 34fcb6980..578321729 100644 --- a/src/cli/tunnel.js +++ b/src/cli/tunnel.js @@ -11,100 +11,136 @@ * */ -const BaseCLIHandler = require('./base-cli-handler') -const constants = require('../helpers/constants') +const BaseCLIHandler = require('./base-cli-handler'); +const constants = require('../helpers/constants'); const fs = require('fs'); -const logger = require('../logger') +const logger = require('../logger'); const TunnelService = require('../services/tunnel-service'); -const CliDecorator = require('../decorators/cli-decorator') -const Errors = require('../helpers/errors') -const ErrorMessages = require('../helpers/error-messages') +const CliDecorator = require('../decorators/cli-decorator'); +const Errors = require('../helpers/errors'); +const ErrorMessages = require('../helpers/error-messages'); class Tunnel extends BaseCLIHandler { constructor() { - super() + super(); - this.name = constants.CMD_TUNNEL + this.name = constants.CMD_TUNNEL; this.commandDefinitions = [ - { name: 'command', defaultOption: true, description: 'update, list', group: constants.CMD, }, - { name: 'username', alias: 'u', type: String, description: 'Tunnel username', group: [constants.CMD_UPDATE] }, - { name: 'password', alias: 'p', type: String, description: 'Tunnel password', group: [constants.CMD_UPDATE] }, - { name: 'host', alias: 's', type: String, description: 'Tunnel host address', group: [constants.CMD_UPDATE] }, - { name: 'rsa-key', alias: 'k', type: String, description: 'Tunnel RSA key', group: [constants.CMD_UPDATE] }, - { name: 'port', alias: 'o', type: Number, description: 'Tunnel port', group: [constants.CMD_UPDATE] }, - { name: 'iofogUuid', alias: 'f', type: String, description: 'Fog UUID', group: [constants.CMD_UPDATE] }, - { name: 'action', alias: 'a', type: String, description: 'Type of action. Can be "open" or "close"', group: [constants.CMD_UPDATE] } - ] + { + name: 'command', defaultOption: true, + description: 'update, list', + group: constants.CMD + }, + { + name: 'username', alias: 'u', type: String, + description: 'Tunnel username', + group: [constants.CMD_UPDATE] + }, + { + name: 'password', alias: 'p', type: String, + description: 'Tunnel password', + group: [constants.CMD_UPDATE] + }, + { + name: 'host', alias: 's', type: String, + description: 'Tunnel host address', + group: [constants.CMD_UPDATE] + }, + { + name: 'rsa-key', alias: 'k', type: String, + description: 'Tunnel RSA key', + group: [constants.CMD_UPDATE] + }, + { + name: 'port', alias: 'o', type: Number, + description: 'Tunnel port', + group: [constants.CMD_UPDATE] + }, + { + name: 'iofogUuid', alias: 'f', type: String, + description: 'Fog UUID', + group: [constants.CMD_UPDATE] + }, + { + name: 'action', alias: 'a', type: String, + description: 'Type of action. Can be "open" or "close"', + group: [constants.CMD_UPDATE] + } + ]; this.commands = { [constants.CMD_UPDATE]: 'Update existing tunnel.', [constants.CMD_LIST]: 'List all tunnels.', } } -async run(args) { - const tunnelCommand = this.parseCommandLineArgs(this.commandDefinitions, { argv: args.argv }) + async run(args) { + try { + const tunnelCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (tunnelCommand.command.command) { - case constants.CMD_UPDATE: + switch (tunnelCommand.command.command) { + case constants.CMD_UPDATE: await _executeCase(tunnelCommand, constants.CMD_UPDATE, _updateTunnel, false); break; - case constants.CMD_LIST: + case constants.CMD_LIST: await _executeCase(tunnelCommand, constants.CMD_LIST, _tunnelList, false); break; - default: - return this.help([constants.CMD_HELP]) + default: + return this.help([constants.CMD_HELP]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } } async function _updateTunnel(obj, user) { - const action = obj.action; - const tunnel = _createTunnelObject(obj); - logger.info(JSON.stringify(tunnel)); - switch (action) { - case 'open': - await TunnelService.openTunnel(tunnel, user, true); - break; - case 'close': - await TunnelService.closeTunnel({iofogUuid: tunnel.iofogUuid}, user); - break; - default: - throw new Errors.ValidationError(ErrorMessages.INVALID_ACTION_PROPERTY); - } - logger.info('Tunnel has been updated successfully.'); + const action = obj.action; + const tunnel = _createTunnelObject(obj); + logger.info(JSON.stringify(tunnel)); + switch (action) { + case 'open': + await TunnelService.openTunnel(tunnel, user, true); + break; + case 'close': + await TunnelService.closeTunnel({iofogUuid: tunnel.iofogUuid}, user); + break; + default: + throw new Errors.ValidationError(ErrorMessages.INVALID_ACTION_PROPERTY); + } + logger.info('Tunnel has been updated successfully.'); } async function _tunnelList() { - const tunnels = await TunnelService.findAll(); - logger.info(JSON.stringify(tunnels, null, 2)); - logger.info('Tunnels has been received successfully.'); + const tunnels = await TunnelService.findAll(); + logger.info(JSON.stringify(tunnels, null, 2)); + logger.info('Tunnels has been received successfully.'); } async function _executeCase(commands, commandName, f, isUserRequired) { - try { - const obj = commands[commandName]; + try { + const obj = commands[commandName]; - if (isUserRequired) { - const decoratedFunction = CliDecorator.prepareUserById(f); - await decoratedFunction(obj); - } else { - await f(obj); - } - } catch (error) { - logger.error(error.message); + if (isUserRequired) { + const decoratedFunction = CliDecorator.prepareUserById(f); + await decoratedFunction(obj); + } else { + await f(obj); } + } catch (error) { + logger.error(error.message); + } } function _createTunnelObject(cliData) { - const rsa = cliData.rsaKey ? fs.readFileSync(cliData.rsaKey, 'utf8') : ""; + const rsa = cliData.rsaKey ? fs.readFileSync(cliData.rsaKey, 'utf8') : ""; return { - host: cliData.host, - username: cliData.username, - password: cliData.password, - rsakey: rsa, - lport: cliData.port, - iofogUuid: cliData.iofogUuid - }; + host: cliData.host, + username: cliData.username, + password: cliData.password, + rsakey: rsa, + lport: cliData.port, + iofogUuid: cliData.iofogUuid + }; } module.exports = new Tunnel(); \ No newline at end of file diff --git a/src/cli/user.js b/src/cli/user.js index 5be79c11a..b43ac6b36 100644 --- a/src/cli/user.js +++ b/src/cli/user.js @@ -22,31 +22,37 @@ const Validator = require('../schemas'); class User extends BaseCLIHandler { constructor() { - super() + super(); - this.name = constants.CMD_USER + this.name = constants.CMD_USER; this.commandDefinitions = [ { - name: 'command', defaultOption: true, description: 'add, remove, update, list, generate-token', + name: 'command', defaultOption: true, + description: 'add, remove, update, list, generate-token', group: constants.CMD, }, { - name: 'first-name', alias: 'f', type: String, description: 'User\'s first name', + name: 'first-name', alias: 'f', type: String, + description: 'User\'s first name', group: [constants.CMD_ADD, constants.CMD_UPDATE], }, { - name: 'last-name', alias: 'l', type: String, description: 'User\'s last name', + name: 'last-name', alias: 'l', type: String, + description: 'User\'s last name', group: [constants.CMD_ADD, constants.CMD_UPDATE], }, { - name: 'email', alias: 'e', type: String, description: 'User\'s email address', - group: [constants.CMD_ADD, constants.CMD_GENERATE_TOKEN, constants.CMD_REMOVE, constants.CMD_UPDATE, constants.CMD_ACTIVATE, constants.CMD_SUSPEND], + name: 'email', alias: 'e', type: String, + description: 'User\'s email address', + group: [constants.CMD_ADD, constants.CMD_GENERATE_TOKEN, constants.CMD_REMOVE, + constants.CMD_UPDATE, constants.CMD_ACTIVATE, constants.CMD_SUSPEND], }, { - name: 'password', alias: 'p', type: String, description: 'User\'s password', + name: 'password', alias: 'p', type: String, + description: 'User\'s password', group: [constants.CMD_ADD, constants.CMD_UPDATE], - }, - ] + } + ]; this.commands = { [constants.CMD_ADD]: 'Add a new user.', [constants.CMD_UPDATE]: 'Update existing user.', @@ -59,33 +65,37 @@ class User extends BaseCLIHandler { } async run(args) { - const userCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv,}) - - switch (userCommand.command.command) { - case constants.CMD_ADD: - await _executeCase(userCommand, constants.CMD_ADD, _createUser, false); - break; - case constants.CMD_UPDATE: - await _executeCase(userCommand, constants.CMD_UPDATE, _updateUserDetails, true); - break; - case constants.CMD_REMOVE: - await _executeCase(userCommand, constants.CMD_REMOVE, _deleteUser, true); - break; - case constants.CMD_LIST: - await _executeCase(userCommand, constants.CMD_LIST, _getAllUsers, false); - break; - case constants.CMD_GENERATE_TOKEN: - await _executeCase(userCommand, constants.CMD_GENERATE_TOKEN, _generateToken, true); - break; - case constants.CMD_ACTIVATE: - await _executeCase(userCommand, constants.CMD_ACTIVATE, _activateUser, true); - break; - case constants.CMD_SUSPEND: - await _executeCase(userCommand, constants.CMD_SUSPEND, _suspendUser, true); - break; - case constants.CMD_HELP: - default: - return this.help([constants.CMD_LIST]) + try { + const userCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); + + switch (userCommand.command.command) { + case constants.CMD_ADD: + await _executeCase(userCommand, constants.CMD_ADD, _createUser, false); + break; + case constants.CMD_UPDATE: + await _executeCase(userCommand, constants.CMD_UPDATE, _updateUserDetails, true); + break; + case constants.CMD_REMOVE: + await _executeCase(userCommand, constants.CMD_REMOVE, _deleteUser, true); + break; + case constants.CMD_LIST: + await _executeCase(userCommand, constants.CMD_LIST, _getAllUsers, false); + break; + case constants.CMD_GENERATE_TOKEN: + await _executeCase(userCommand, constants.CMD_GENERATE_TOKEN, _generateToken, true); + break; + case constants.CMD_ACTIVATE: + await _executeCase(userCommand, constants.CMD_ACTIVATE, _activateUser, true); + break; + case constants.CMD_SUSPEND: + await _executeCase(userCommand, constants.CMD_SUSPEND, _suspendUser, true); + break; + case constants.CMD_HELP: + default: + return this.help([constants.CMD_LIST]) + } + } catch (error) { + AppHelper.handleCLIError(error); } } @@ -161,4 +171,4 @@ const _suspendUser = async function (emailObj, user) { }; -module.exports = new User() +module.exports = new User(); diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index 3dd7a2b59..ea6b1bdcd 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -143,6 +143,20 @@ function stringifyCliJsonSchema(json) { .replace(/}/g, "\\}"); } +function handleCLIError(error) { + switch (error.name) { + case "UNKNOWN_OPTION": + console.log("Unknown parameter " + error.optionName); + break; + case "UNKNOWN_VALUE": + console.log("Unknown value " + error.value); + break; + default: + console.log(JSON.stringify(error)); + break; + } +} + module.exports = { encryptText, decryptText, @@ -158,5 +172,6 @@ module.exports = { formatMessage, findAvailablePort, stringifyCliJsonSchema, - isValidPublicIP + isValidPublicIP, + handleCLIError }; From 542bdfce5838e64b04ff3f11c4faa26987d560fc Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Mon, 12 Nov 2018 15:46:35 +0200 Subject: [PATCH 51/91] fix file size, rename (#345) * fix file size, rename * update --- src/services/agent-service.js | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/src/services/agent-service.js b/src/services/agent-service.js index 9c6d9f0bf..c1d5bbbd8 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -382,31 +382,27 @@ const getImageSnapshot = async function (fog, transaction) { }; const putImageSnapshot = async function (req, fog, transaction) { - if (req.headers['content-type'].includes('multipart/form-data')) { + const opts = { + maxFieldsSize: 500 * 1024 * 1024, + maxFileSize: 500 * 1024 * 1024 + }; + if (!req.headers['content-type'].includes('multipart/form-data')) { throw new Errors.ValidationError(ErrorMessages.INVALID_CONTENT_TYPE); } - const form = new formidable.IncomingForm(); + const form = new formidable.IncomingForm(opts); form.uploadDir = path.join(appRoot, '../') + 'data'; if (!fs.existsSync(form.uploadDir)) { fs.mkdirSync(form.uploadDir); } - const absolutePath = await saveSnapShot(req, form); - await MicroserviceManager.update({ - iofogUuid: fog.uuid, - imageSnapshot: 'get_image' - }, { - imageSnapshot: absolutePath - }, transaction); + await saveSnapShot(req, form,fog, transaction); }; -const saveSnapShot = function (req, form) { +const saveSnapShot = function (req, form, fog, transaction) { return new Promise((resolve, reject) => { - form.parse(req, async function (error, fields, files) { const file = files['upstream']; - if (file === undefined) { reject(new Errors.ValidationError(ErrorMessages.UPLOADED_FILE_NOT_FOUND)); return; @@ -414,10 +410,18 @@ const saveSnapShot = function (req, form) { const filePath = file['path']; - let absolutePath = path.resolve(filePath); - fs.rename(absolutePath, absolutePath + '.tar.gz'); - resolve(absolutePath + '.tar.gz'); + fs.renameSync(absolutePath, absolutePath + '.tar.gz'); + + await MicroserviceManager.update({ + iofogUuid: fog.uuid, + imageSnapshot: 'get_image' + }, { + imageSnapshot: absolutePath + '.tar.gz' + }, transaction); + + resolve(); + }); }); }; From fbb0a9f7c1647cc9c21d75f6b44e9071a424f0ef Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Mon, 12 Nov 2018 19:17:51 +0300 Subject: [PATCH 52/91] Epankou/bug swagger fix & connector cli fix (#343) * volume mapping & delete with clean up * volume mapping & delete with clean up * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js --- specs/swagger.yml | 11 +++++++--- src/cli/connector.js | 4 ++-- src/services/connector-service.js | 2 +- src/services/microservices-service.js | 8 +++---- ...Controller Testing.postman_collection.json | 22 +++++++------------ 5 files changed, 23 insertions(+), 24 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 57d7fb063..871370ee8 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -1601,9 +1601,7 @@ paths: '200': description: Success schema: - type: array - items: - $ref: '#/definitions/VolumeMappingRequest' + $ref: '#/definitions/VolumeMappingResponse' headers: X-Timestamp: type: number @@ -2776,6 +2774,13 @@ definitions: accessMode: type: string example: rw + VolumeMappingResponse: + type: object + properties: + volumeMappings: + type: array + items: + $ref: '#/definitions/VolumeMappingRequest' VolumeMappingRequest: type: object properties: diff --git a/src/cli/connector.js b/src/cli/connector.js index 353b698e5..0c56bfb81 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -155,7 +155,7 @@ async function _deleteConnector(obj) { } } -async function _getConnectorList(obj) { +async function _getConnectorList() { const list = await ConnectorService.getConnectorList(); logger.info(JSON.stringify(list, null, 2)); logger.info('Connector list has been gotten successfully'); @@ -167,7 +167,7 @@ function _createConnectorObject(cliData) { domain: cliData.domain, publicIp: cliData.publicIp, cert: cliData.cert, - isSelfSignedCert: AppHelper.validateBooleanCliOptions(cliData.selfSignedEnable, cliData.selfSignedDisable), + isSelfSignedCert: AppHelper.validateBooleanCliOptions(cliData.selfSignedOn, cliData.selfSignedOff), devMode: AppHelper.validateBooleanCliOptions(cliData.devModeOn, cliData.devModeOff) }; diff --git a/src/services/connector-service.js b/src/services/connector-service.js index f1a53555b..a2a6a5bae 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -39,7 +39,7 @@ async function _createConnector(connectorData, transaction) { if (connector) { throw new Errors.ValidationError(ErrorMessages.ALREADY_EXISTS) } - await ConnectorManager.create(connectorData, transaction) + return await ConnectorManager.create(connectorData, transaction) } async function _updateConnector(connectorData, transaction) { diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 0aa79ddf9..8fd62b5b6 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -217,14 +217,14 @@ const _deleteMicroservice = async function (microserviceUuid, microserviceData, const microservice = await MicroserviceManager.findOneWithStatus(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); + } if (microservice.microserviceStatus.status === MicroserviceStates.NOT_RUNNING) { - const affectedRows = await MicroserviceManager.delete({ + await MicroserviceManager.delete({ uuid: microserviceUuid }, transaction); - if (affectedRows === 0) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); - } } else { await MicroserviceManager.update({ uuid: microserviceUuid diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index b040d08c0..4b593b828 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -3829,11 +3829,12 @@ { "listen": "test", "script": { - "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", + "id": "6d078bca-3762-400b-bf9f-2701f7f5b01b", + "type": "text/javascript", "exec": [ - "tests[\"Status code is 204\"] = responseCode.code === 204;" - ], - "type": "text/javascript" + "tests[\"Status code is 204\"] = responseCode.code === 204;", + "" + ] } } ], @@ -3846,16 +3847,15 @@ }, { "key": "Authorization", - "value": "{{user-token}}", - "type": "text" + "value": "{{user-token}}" } ], "body": { "mode": "raw", - "raw": "" + "raw": "{\n\t\"withCleanup\": false\n}" }, "url": { - "raw": "{{host}}/api/v3/microservices/{{ms-id}}?withCleanUp=true", + "raw": "{{host}}/api/v3/microservices/{{ms-id}}", "host": [ "{{host}}" ], @@ -3864,12 +3864,6 @@ "v3", "microservices", "{{ms-id}}" - ], - "query": [ - { - "key": "withCleanUp", - "value": "true" - } ] } }, From 4b2696ccf109eeb15cec219d5ceae79e698a535f Mon Sep 17 00:00:00 2001 From: Railag Date: Mon, 12 Nov 2018 19:53:04 +0300 Subject: [PATCH 53/91] Connector CLI validation EWC 343 (#347) * EWC-343 fixed connector domain/ip validation * cleanup --- src/helpers/app-helper.js | 2 +- src/services/connector-service.js | 80 ++++++++++++++++--------------- 2 files changed, 43 insertions(+), 39 deletions(-) diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index ea6b1bdcd..5cb30d3a1 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -91,7 +91,7 @@ function isValidDomain(domain) { const isValidPublicIP = function (publicIP) { let re = /^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$|^(([a-zA-Z]|[a-zA-Z][a-zA-Z0-9\-]*[a-zA-Z0-9])\.)*([A-Za-z]|[A-Za-z][A-Za-z0-9\-]*[A-Za-z0-9])$|^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))(%.+)?\s*$/; return re.test(publicIP); -} +}; function generateAccessToken() { let token = '', i; diff --git a/src/services/connector-service.js b/src/services/connector-service.js index a2a6a5bae..4fa555d3d 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -11,31 +11,31 @@ * */ -const TransactionDecorator = require('../decorators/transaction-decorator') -const Validator = require('../schemas') -const ConnectorManager = require('../sequelize/managers/connector-manager') -const Errors = require('../helpers/errors') -const ErrorMessages = require('../helpers/error-messages') -const AppHelper = require('../helpers/app-helper') +const TransactionDecorator = require('../decorators/transaction-decorator'); +const Validator = require('../schemas'); +const ConnectorManager = require('../sequelize/managers/connector-manager'); +const Errors = require('../helpers/errors'); +const ErrorMessages = require('../helpers/error-messages'); +const AppHelper = require('../helpers/app-helper'); const https = require('https'); const http = require('http'); -const constants = require('../helpers/constants') -const logger = require('../logger') -const querystring = require('querystring') +const constants = require('../helpers/constants'); +const logger = require('../logger'); +const querystring = require('querystring'); const Op = require('sequelize').Op; const Sequelize = require('sequelize'); const fs = require('fs'); async function _createConnector(connectorData, transaction) { - await Validator.validate(connectorData, Validator.schemas.connectorCreate) - validateConnectorData(connectorData) + await Validator.validate(connectorData, Validator.schemas.connectorCreate); + validateConnectorData(connectorData); const connector = await ConnectorManager.findOne({ [Op.or]: [ {name: connectorData.name}, {publicIp: connectorData.publicIp}, {domain: connectorData.domain} ] - }, transaction) + }, transaction); if (connector) { throw new Errors.ValidationError(ErrorMessages.ALREADY_EXISTS) } @@ -47,25 +47,29 @@ async function _updateConnector(connectorData, transaction) { validateConnectorData(connectorData); const queryConnectorData = { publicIp: connectorData.publicIp - } + }; await ConnectorManager.update(queryConnectorData, connectorData, transaction) } -function validateConnectorData(connectorData){ - if (connectorData.domain && !AppHelper.isValidDomain(connectorData.domain)){ - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_DOMAIN, connectorData.domain)); - } - if (!AppHelper.isValidPublicIP(connectorData.publicIp)){ - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_IP, connectorData.publicIp)); +function validateConnectorData(connectorData) { + if (connectorData.domain) { + const validDomain = AppHelper.isValidDomain(connectorData.domain) || AppHelper.isValidPublicIP(connectorData.domain); + if (!validDomain) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_DOMAIN, connectorData.domain)); } + } + + if (!AppHelper.isValidPublicIP(connectorData.publicIp)) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_IP, connectorData.publicIp)); + } } async function _deleteConnector(connectorData, transaction) { - await Validator.validate(connectorData, Validator.schemas.connectorDelete) + await Validator.validate(connectorData, Validator.schemas.connectorDelete); const queryConnectorData = { publicIp: connectorData.publicIp - } - const affectedRows = await ConnectorManager.delete(queryConnectorData, transaction) + }; + const affectedRows = await ConnectorManager.delete(queryConnectorData, transaction); if (affectedRows === 0) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_CONNECTOR_IP, connectorData.publicIp)) } @@ -76,41 +80,41 @@ async function _getConnectorList(transaction) { } async function openPortOnRandomConnector(isPublicAccess, transaction) { - let isConnectorPortOpen = false + let isConnectorPortOpen = false; let ports = null; let connector = null; - const maxAttempts = 5 + const maxAttempts = 5; for (let i = 0; i < maxAttempts; i++) { try { - connector = await _getRandomConnector(transaction) - ports = await openPortsOnConnector(connector, isPublicAccess, transaction) + connector = await _getRandomConnector(transaction); + ports = await openPortsOnConnector(connector, isPublicAccess, transaction); if (ports) { - isConnectorPortOpen = true + isConnectorPortOpen = true; break; } - } catch(e) { - logger.warn(`Failed to open ports on comsat. Attempts ${i+1}/${maxAttempts}`) + } catch (e) { + logger.warn(`Failed to open ports on comsat. Attempts ${i + 1}/${maxAttempts}`) } } if (!isConnectorPortOpen) { throw new Error('Not able to open port on remote CONNECTOR. Gave up after 5 attempts.') } - ports.connectorId = connector.id + ports.connectorId = connector.id; return {ports: ports, connector: connector} } async function _makeRequest(connector, options, data) { return new Promise((resolve, reject) => { - let httpreq = (connector.devMode ? http : https).request(options, function(response) { + let httpreq = (connector.devMode ? http : https).request(options, function (response) { console.log(response.statusCode); let output = ''; response.setEncoding('utf8'); - response.on('data', function(chunk) { + response.on('data', function (chunk) { output += chunk; }); - response.on('end', function() { + response.on('end', function () { let responseObj = JSON.parse(output); console.log(responseObj); if (responseObj.errormessage) { @@ -119,14 +123,14 @@ async function _makeRequest(connector, options, data) { return resolve(responseObj); } }); - }) + }); if (connector.cert && connector.isSelfSignedCert === true) { const ca = fs.readFileSync(connector.cert); options.ca = new Buffer(ca); } - httpreq.on('error', function(err) { + httpreq.on('error', function (err) { console.log(err); if (err instanceof Error) return reject(new Error(err.message)); @@ -147,7 +151,7 @@ async function openPortsOnConnector(connector, isPublicAccess, transaction) { }) : await querystring.stringify({ mapping: '{"type":"private","maxconnectionsport1":1, "maxconnectionsport2":1, ' + - '"heartbeatabsencethresholdport1":200000, "heartbeatabsencethresholdport2":200000}' + '"heartbeatabsencethresholdport1":200000, "heartbeatabsencethresholdport2":200000}' }); let port = connector.devMode ? constants.CONNECTOR_HTTP_PORT : constants.CONNECTOR_HTTPS_PORT; @@ -163,12 +167,12 @@ async function openPortsOnConnector(connector, isPublicAccess, transaction) { } }; - const ports = await _makeRequest(connector, options, data) + const ports = await _makeRequest(connector, options, data); return ports } async function _getRandomConnector(transaction) { - const connectors = await _getConnectorList(transaction) + const connectors = await _getConnectorList(transaction); if (connectors && connectors.length > 0) { const randomNumber = Math.round((Math.random() * (connectors.length - 1))); return connectors[randomNumber] From f17d9c5d80287100392d4c569cac6711dfbfa851 Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Mon, 12 Nov 2018 19:56:12 +0300 Subject: [PATCH 54/91] Epankou/bug non dev mode connector ewc 339 (#346) * volume mapping & delete with clean up * volume mapping & delete with clean up * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * connector non dev mode fix EWC-339 --- src/helpers/app-helper.js | 9 ++++++++- src/services/microservices-service.js | 3 ++- 2 files changed, 10 insertions(+), 2 deletions(-) diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index 5cb30d3a1..0fb7dda37 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -157,6 +157,12 @@ function handleCLIError(error) { } } +function trimCertificate(cert) { + let result = cert.replace(/(^[\s\S]*-{3,}BEGIN CERTIFICATE-{3,}[\s]*)/, ""); + result = result.replace(/([\s]*-{3,}END CERTIFICATE-{3,}[\s\S]*$)/, ""); + return result; +} + module.exports = { encryptText, decryptText, @@ -173,5 +179,6 @@ module.exports = { findAvailablePort, stringifyCliJsonSchema, isValidPublicIP, - handleCLIError + handleCLIError, + trimCertificate }; diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 8fd62b5b6..ccb069f97 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -31,6 +31,7 @@ const FlowService = require('../services/flow-service'); const CatalogService = require('../services/catalog-service'); const RoutingManager = require('../sequelize/managers/routing-manager'); const Op = require('sequelize').Op; +const fs = require('fs'); const _listMicroservices = async function (flowId, user, isCLI, transaction) { if (!isCLI) { @@ -602,7 +603,7 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us const netwMsConfig = { 'mode': 'public', 'host': connector.domain, - 'cert': connector.cert, + 'cert': AppHelper.trimCertificate(fs.readFileSync(connector.cert, "utf-8")), 'port': ports.port1, 'passcode': ports.passcode1, 'connectioncount': 60, From 2c441c98459d1cc2cc328441d49dfe22e25e5b1a Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Tue, 13 Nov 2018 12:28:07 +0300 Subject: [PATCH 55/91] Epankou/bug microservice removal ewc 306 (#348) * volume mapping & delete with clean up * volume mapping & delete with clean up * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * connector non dev mode fix EWC-339 * microservice removal cli bug fix --- src/services/microservices-service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index ccb069f97..588648ecc 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -209,11 +209,11 @@ const _deleteMicroservice = async function (microserviceUuid, microserviceData, ? { uuid: microserviceUuid, - userId: user.id } : { - uuid: microserviceUuid + uuid: microserviceUuid, + userId: user.id }; From 1ccad6eaf96f9e9672c0d7e914533eebcd1992e7 Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Tue, 13 Nov 2018 14:18:30 +0200 Subject: [PATCH 56/91] fix return empty json (#349) --- src/services/agent-service.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/services/agent-service.js b/src/services/agent-service.js index c1d5bbbd8..d278c59f0 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -396,7 +396,7 @@ const putImageSnapshot = async function (req, fog, transaction) { fs.mkdirSync(form.uploadDir); } await saveSnapShot(req, form,fog, transaction); - + return {}; }; const saveSnapShot = function (req, form, fog, transaction) { From f29d8974b01d22c11f3dea1c95b05b739679665f Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 13 Nov 2018 18:32:23 +0300 Subject: [PATCH 57/91] fixed migration constaints (#351) --- .../20181113094807-add-missing-constraints.js | 139 ++++++++++++++++++ 1 file changed, 139 insertions(+) create mode 100644 src/sequelize/migrations/20181113094807-add-missing-constraints.js diff --git a/src/sequelize/migrations/20181113094807-add-missing-constraints.js b/src/sequelize/migrations/20181113094807-add-missing-constraints.js new file mode 100644 index 000000000..0f7dd18c6 --- /dev/null +++ b/src/sequelize/migrations/20181113094807-add-missing-constraints.js @@ -0,0 +1,139 @@ +'use strict'; + +module.exports = { + up: (queryInterface, Sequelize) => { + return queryInterface.addConstraint('Flows', ['user_id'], { + type: 'FOREIGN KEY', + name: 'userId', + references: { + name: 'userId', + table: 'Users', + field: 'id' + }, + onDelete: 'cascade' + }).then(() => { + return queryInterface.addConstraint('Microservices', ['user_id'], { + type: 'FOREIGN KEY', + name: 'userId', + references: { + name: 'userId', + table: 'Users', + field: 'id' + }, + onDelete: 'cascade' + }).then(() => { + return queryInterface.addConstraint('Microservices', ['iofog_uuid'], { + type: 'FOREIGN KEY', + name: 'iofogUuid', + references: { + name: 'iofogUuid', + table: 'Fogs', + field: 'uuid' + }, + onDelete: 'cascade' + }) + }).then(() => { + return queryInterface.addConstraint('Microservices', ['catalog_item_id'], { + type: 'FOREIGN KEY', + name: 'catalogItemId', + references: { + name: 'catalogItemId', + table: 'CatalogItems', + field: 'id' + }, + onDelete: 'cascade' + }) + }).then(() => { + return queryInterface.addConstraint('Microservices', ['registry_id'], { + type: 'FOREIGN KEY', + name: 'registryId', + references: { + name: 'registryId', + table: 'Registries', + field: 'id' + }, + onDelete: 'cascade' + }) + }).then(() => { + return queryInterface.addConstraint('Microservices', ['flow_id'], { + type: 'FOREIGN KEY', + name: 'flowId', + references: { + name: 'flowId', + table: 'Flows', + field: 'id' + }, + onDelete: 'cascade' + }) + }).then(() => { + return queryInterface.addConstraint('ChangeTrackings', ['iofog_uuid'], { + type: 'FOREIGN KEY', + name: 'iofogUuid', + references: { + name: 'iofogUuid', + table: 'Fogs', + field: 'uuid' + }, + onDelete: 'cascade' + }) + }) + }).then(() => { + return queryInterface.addConstraint('MicroservicePorts', ['user_id'], { + type: 'FOREIGN KEY', + name: 'userId', + references: { + name: 'userId', + table: 'Users', + field: 'id' + }, + onDelete: 'cascade' + }) + }).then(() => { + return queryInterface.addConstraint('MicroservicePorts', ['microservice_uuid'], { + type: 'FOREIGN KEY', + name: 'microserviceUuid', + references: { + name: 'microserviceUuid', + table: 'Microservices', + field: 'uuid' + }, + onDelete: 'cascade' + }) + }); + }, + + down: + (queryInterface, Sequelize) => { + + // for SQLite + return queryInterface.renameColumn('Flows', 'user_id', 'user_id') + .then(() => { + return queryInterface.renameColumn('Microservices', 'user_id', 'user_id') + }).then(() => { + return queryInterface.renameColumn('ChangeTrackings', 'iofog_uuid', 'iofog_uuid') + }).then(() => { + return queryInterface.renameColumn('MicroservicePorts', 'user_id', 'user_id') + }) + + // for other DB + + // return queryInterface.removeConstraint('Flows', 'userId') + // .then(() => { + // return queryInterface.removeConstraint('Microservices', 'userId') + // }).then(() => { + // return queryInterface.removeConstraint('Microservices', 'iofogUuid') + // }).then(() => { + // return queryInterface.removeConstraint('Microservices', 'catalogItemId') + // }).then(() => { + // return queryInterface.removeConstraint('Microservices', 'registryId') + // }).then(() => { + // return queryInterface.removeConstraint('Microservices', 'flowId') + // }).then(() => { + // return queryInterface.removeConstraint('ChangeTrackings', 'iofogUuid') + // }).then(() => { + // return queryInterface.removeConstraint('MicroservicePorts', 'userId') + // }).then(() => { + // return queryInterface.removeConstraint('MicroservicePorts', 'microserviceUuid') + // }); + } +}; From 368bc00c671931c6a368ca9852ea3d45ad90c844 Mon Sep 17 00:00:00 2001 From: Railag Date: Tue, 13 Nov 2018 19:46:05 +0300 Subject: [PATCH 58/91] fixed migrations constaints (#352) * fixed migration constaints * cleanup --- .../20181113094807-add-missing-constraints.js | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/src/sequelize/migrations/20181113094807-add-missing-constraints.js b/src/sequelize/migrations/20181113094807-add-missing-constraints.js index 0f7dd18c6..7ffae3a94 100644 --- a/src/sequelize/migrations/20181113094807-add-missing-constraints.js +++ b/src/sequelize/migrations/20181113094807-add-missing-constraints.js @@ -106,13 +106,21 @@ module.exports = { (queryInterface, Sequelize) => { // for SQLite - return queryInterface.renameColumn('Flows', 'user_id', 'user_id') + return queryInterface.renameColumn('Flows', 'user_id', 'user_id1') .then(() => { - return queryInterface.renameColumn('Microservices', 'user_id', 'user_id') + return queryInterface.renameColumn('Flows', 'user_id1', 'user_id') }).then(() => { - return queryInterface.renameColumn('ChangeTrackings', 'iofog_uuid', 'iofog_uuid') + return queryInterface.renameColumn('Microservices', 'user_id', 'user_id1') }).then(() => { - return queryInterface.renameColumn('MicroservicePorts', 'user_id', 'user_id') + return queryInterface.renameColumn('Microservices', 'user_id1', 'user_id') + }).then(() => { + return queryInterface.renameColumn('ChangeTrackings', 'iofog_uuid', 'iofog_uuid1') + }).then(() => { + return queryInterface.renameColumn('ChangeTrackings', 'iofog_uuid1', 'iofog_uuid') + }).then(() => { + return queryInterface.renameColumn('MicroservicePorts', 'user_id', 'user_id1') + }).then(() => { + return queryInterface.renameColumn('MicroservicePorts', 'user_id1', 'user_id') }) // for other DB From cbfbc9442a9bd2e5572c37b3bfa315cb0392c360 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Tue, 13 Nov 2018 20:17:48 +0300 Subject: [PATCH 59/91] feature transactions ewc 337 (#353) * get fog list params in query * fake transaction on agent routes cleanup change tracking only if not empty sequelize sync on start was deleted * cleanup * postman fix --- src/decorators/transaction-decorator.js | 54 +++++++-- src/helpers/app-helper.js | 11 +- src/main.js | 17 ++- src/schemas/agent.js | 18 ++- src/sequelize/managers/base-manager.js | 109 +++++++++++++----- src/services/agent-service.js | 34 +++--- src/services/change-tracking-service.js | 5 + ...Controller Testing.postman_collection.json | 2 +- 8 files changed, 179 insertions(+), 71 deletions(-) diff --git a/src/decorators/transaction-decorator.js b/src/decorators/transaction-decorator.js index 4408ad532..39a0e32ed 100644 --- a/src/decorators/transaction-decorator.js +++ b/src/decorators/transaction-decorator.js @@ -14,21 +14,21 @@ const db = require('./../sequelize/models'); const retry = require('retry-as-promised'); const sequelize = db.sequelize; -// const Transaction = require('sequelize/lib/transaction'); +const Transaction = require('sequelize/lib/transaction'); function transaction(f) { return async function() { const fArgs = Array.prototype.slice.call(arguments); - // To be removed when transactions concurrency issue fixed - // if (fArgs[fArgs.length - 1] instanceof Transaction) { - // return await f.apply(this, fArgs); - // } else { - return f.apply(this, fArgs) - // return sequelize.transaction(async (t) => { - // fArgs.push(t); - // return await f.apply(this, fArgs); - // }) - // } + //TODO [when transactions concurrency issue fixed]: Remove 'fArgs[fArgs.length - 1].fakeTransaction' + if (fArgs[fArgs.length - 1] instanceof Transaction || fArgs[fArgs.length - 1].fakeTransaction) { + return await f.apply(this, fArgs); + } else { + //return f.apply(this, fArgs) + return sequelize.transaction(async (t) => { + fArgs.push(t); + return await f.apply(this, fArgs); + }) + } } } @@ -48,6 +48,38 @@ function generateTransaction(f) { } } +function fakeTransaction(f) { + const fakeTransactionObject = {fakeTransaction: true} + return async function() { + const fArgs = Array.prototype.slice.call(arguments); + if (fArgs[fArgs.length - 1] instanceof Transaction) { + fArgs[fArgs.length - 1] = fakeTransactionObject; + return await f.apply(this, fArgs); + } else { + fArgs.push(fakeTransactionObject); + return await f.apply(this, fArgs); + } + } +} + +//TODO [when transactions concurrency issue fixed]: Remove +function generateFakeTransaction(f) { + return function () { + const args = Array.prototype.slice.call(arguments); + return retry(() => { + const t = fakeTransaction(f); + return t.apply(this, args); + }, { + max: 5, + match: [ + sequelize.ConnectionError, + 'SQLITE_BUSY', + ], + }) + } +} + module.exports = { generateTransaction: generateTransaction, + generateFakeTransaction: generateFakeTransaction }; \ No newline at end of file diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index 0fb7dda37..c002042ce 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -22,6 +22,8 @@ const format = require('string-format'); const ALGORITHM = 'aes-256-ctr'; +const Transaction = require('sequelize/lib/transaction'); + function encryptText(text, salt) { const cipher = crypto.createCipher(ALGORITHM, salt); let crypted = cipher.update(text, 'utf8', 'hex'); @@ -102,11 +104,10 @@ function generateAccessToken() { } function checkTransaction(transaction) { - // To be removed when transactions concurrency issue fixed - return - // if (!transaction) { - // throw new Errors.TransactionError() - // } + //TODO [when transactions concurrency issue fixed]: Remove '!transaction.fakeTransaction' + if (!transaction || (!(transaction instanceof Transaction) && !transaction.fakeTransaction)) { + throw new Errors.TransactionError() + } } function deleteUndefinedFields(obj) { diff --git a/src/main.js b/src/main.js index 95cd37789..c97b32c59 100644 --- a/src/main.js +++ b/src/main.js @@ -33,17 +33,16 @@ function main() { const cli = new Cli(); daemon - .on('starting', () => { + .on('starting', async () => { logger.silly('Starting iofog-controller...'); - db.sequelize - .sync() - .then(db.migrate) - .then(db.seed) - .catch((err) => { - logger.silly('Unable to initialize the database.', err); - process.exit(1) - }); + try { + await db.migrate(); + await db.seed(); + } catch (err) { + logger.silly('Unable to initialize the database.', err); + process.exit(1) + } }) .on('stopping', () => { logger.silly('Stopping iofog-controller...') diff --git a/src/schemas/agent.js b/src/schemas/agent.js index 0b1f74dcd..3d3c19cc5 100644 --- a/src/schemas/agent.js +++ b/src/schemas/agent.js @@ -111,6 +111,22 @@ const straceData = { "additionalProperties": false }; +const microserviceStatus = { + "id": "/microserviceStatus", + "type": "object", + "properties": { + "id": {"type": "string"}, + "containerId": {"type": "string"}, + "status": {"type": "string"}, + "startTime": {"type": "integer"}, + "operatingDuration": {"type": "integer"}, + "cpuUsage": {"type": "number"}, + "memoryUsage": {"type": "number"} + }, + "required": ["id"], + "additionalProperties": false +}; + const updateHardwareInfo = { "id": "/updateHardwareInfo", "type": "object", @@ -134,5 +150,5 @@ const updateUsbInfo = { module.exports = { mainSchemas: [agentProvision, updateAgentConfig, agentConfigChanges, updateAgentStatus, updateAgentStrace, updateHardwareInfo, updateUsbInfo], - innerSchemas: [straceData] + innerSchemas: [straceData, microserviceStatus] }; \ No newline at end of file diff --git a/src/sequelize/managers/base-manager.js b/src/sequelize/managers/base-manager.js index 276c4cfe1..6292e7f07 100644 --- a/src/sequelize/managers/base-manager.js +++ b/src/sequelize/managers/base-manager.js @@ -12,8 +12,11 @@ */ const AppHelper = require('../../helpers/app-helper'); -const Errors = require('../../helpers/errors') +const Errors = require('../../helpers/errors'); +const ChangeTracking = require('./../models').ChangeTracking; + +//TODO [when transactions concurrency issue fixed]: Transactions should be used always module.exports = class BaseManager { getEntity() { @@ -25,10 +28,16 @@ module.exports = class BaseManager { object = object || {}; - return this.getEntity().findAll({ - where: object, - transaction: transaction - }); + const options = transaction.fakeTransaction + ? { + where: object, + } + : { + where: object, + transaction: transaction + }; + + return this.getEntity().findAll(options); } async findOne(object, transaction) { @@ -36,54 +45,80 @@ module.exports = class BaseManager { object = object || {}; - return this.getEntity().findOne({ - where: object, - transaction: transaction - }); + const options = transaction.fakeTransaction + ? { + where: object, + } + : { + where: object, + transaction: transaction + }; + + return this.getEntity().findOne(options); } async create(object, transaction) { AppHelper.checkTransaction(transaction); - return this.getEntity().create(object, { - transaction: transaction - }); + + const options = transaction.fakeTransaction + ? {} + : {transaction: transaction}; + + return this.getEntity().create(object, options); } async bulkCreate(arr, transaction) { AppHelper.checkTransaction(transaction); - return this.getEntity().bulkCreate(arr, { - transaction: transaction - }); + const options = transaction.fakeTransaction + ? {} + : {transaction: transaction}; + + return this.getEntity().bulkCreate(arr, options); } async delete(data, transaction) { AppHelper.checkTransaction(transaction); data = data || {}; - return this.getEntity().destroy({ - where: data, - transaction: transaction - }) + + const options = transaction.fakeTransaction + ? { + where: data, + } + : { + where: data, + transaction: transaction + }; + + return this.getEntity().destroy(options); } async update(whereData, newData, transaction) { AppHelper.checkTransaction(transaction); whereData = whereData || {}; - return this.getEntity().update(newData, { - where: whereData, - transaction: transaction - }); + + const options = transaction.fakeTransaction + ? { + where: whereData, + } + : { + where: whereData, + transaction: transaction + }; + + return this.getEntity().update(newData, options); } async upsert(data, transaction) { AppHelper.checkTransaction(transaction); - return this.getEntity().upsert(data, { - transaction: transaction - } - ) + const options = transaction.fakeTransaction + ? {} + : {transaction: transaction}; + + return this.getEntity().upsert(data, options); } async updateOrCreate(whereData, data, transaction) { @@ -96,6 +131,26 @@ module.exports = class BaseManager { } else { return this.create(data, transaction) } + } + + async updateIfChanged(whereData, newData, transaction) { + AppHelper.checkTransaction(transaction); + const obj = await this.findOne(whereData, transaction) + if (!obj) { + throw new Errors.NotFoundError(`${this.getEntity().name} not found`) + } + + let hasUpdates = false; + for (let fldName in newData) { + if (newData.hasOwnProperty(fldName) && obj.dataValues.hasOwnProperty(fldName) && newData[fldName] !== obj.dataValues[fldName]) { + hasUpdates = true; + break; + } + } + + if (hasUpdates) { + return await this.update(whereData, newData, transaction) + } } }; \ No newline at end of file diff --git a/src/services/agent-service.js b/src/services/agent-service.js index d278c59f0..8160eb82e 100644 --- a/src/services/agent-service.js +++ b/src/services/agent-service.js @@ -136,7 +136,7 @@ const getAgentConfigChanges = async function (fog, transaction) { throw new Errors.NotFoundError(ErrorMessages.INVALID_NODE_ID) } - await ChangeTrackingService.update(fog.uuid, ChangeTrackingService.events.clean, transaction); + await ChangeTrackingService.updateIfChanged(fog.uuid, ChangeTrackingService.events.clean, transaction); return { config: changeTracking.config, @@ -460,21 +460,21 @@ async function _checkMicroservicesFogType(fog, fogTypeId, transaction) { } module.exports = { - agentProvision: TransactionDecorator.generateTransaction(agentProvision), + agentProvision: TransactionDecorator.generateFakeTransaction(agentProvision), getAgentConfig: getAgentConfig, - updateAgentConfig: TransactionDecorator.generateTransaction(updateAgentConfig), - getAgentConfigChanges: TransactionDecorator.generateTransaction(getAgentConfigChanges), - updateAgentStatus: TransactionDecorator.generateTransaction(updateAgentStatus), - getAgentMicroservices: TransactionDecorator.generateTransaction(getAgentMicroservices), - getAgentMicroservice: TransactionDecorator.generateTransaction(getAgentMicroservice), - getAgentRegistries: TransactionDecorator.generateTransaction(getAgentRegistries), - getAgentTunnel: TransactionDecorator.generateTransaction(getAgentTunnel), - getAgentStrace: TransactionDecorator.generateTransaction(getAgentStrace), - updateAgentStrace: TransactionDecorator.generateTransaction(updateAgentStrace), - getAgentChangeVersionCommand: TransactionDecorator.generateTransaction(getAgentChangeVersionCommand), - updateHalHardwareInfo: TransactionDecorator.generateTransaction(updateHalHardwareInfo), - updateHalUsbInfo: TransactionDecorator.generateTransaction(updateHalUsbInfo), - deleteNode: TransactionDecorator.generateTransaction(deleteNode), - getImageSnapshot: TransactionDecorator.generateTransaction(getImageSnapshot), - putImageSnapshot: TransactionDecorator.generateTransaction(putImageSnapshot) + updateAgentConfig: TransactionDecorator.generateFakeTransaction(updateAgentConfig), + getAgentConfigChanges: TransactionDecorator.generateFakeTransaction(getAgentConfigChanges), + updateAgentStatus: TransactionDecorator.generateFakeTransaction(updateAgentStatus), + getAgentMicroservices: TransactionDecorator.generateFakeTransaction(getAgentMicroservices), + getAgentMicroservice: TransactionDecorator.generateFakeTransaction(getAgentMicroservice), + getAgentRegistries: TransactionDecorator.generateFakeTransaction(getAgentRegistries), + getAgentTunnel: TransactionDecorator.generateFakeTransaction(getAgentTunnel), + getAgentStrace: TransactionDecorator.generateFakeTransaction(getAgentStrace), + updateAgentStrace: TransactionDecorator.generateFakeTransaction(updateAgentStrace), + getAgentChangeVersionCommand: TransactionDecorator.generateFakeTransaction(getAgentChangeVersionCommand), + updateHalHardwareInfo: TransactionDecorator.generateFakeTransaction(updateHalHardwareInfo), + updateHalUsbInfo: TransactionDecorator.generateFakeTransaction(updateHalUsbInfo), + deleteNode: TransactionDecorator.generateFakeTransaction(deleteNode), + getImageSnapshot: TransactionDecorator.generateFakeTransaction(getImageSnapshot), + putImageSnapshot: TransactionDecorator.generateFakeTransaction(putImageSnapshot) }; \ No newline at end of file diff --git a/src/services/change-tracking-service.js b/src/services/change-tracking-service.js index 635ab9e49..bed1669e9 100644 --- a/src/services/change-tracking-service.js +++ b/src/services/change-tracking-service.js @@ -75,6 +75,10 @@ async function update(fogId, data, transaction) { await ChangeTrackingManager.update({iofogUuid: fogId}, data, transaction); } +async function updateIfChanged(fogId, data, transaction) { + await ChangeTrackingManager.updateIfChanged({iofogUuid: fogId}, data, transaction); +} + async function create(fogId, transaction) { await ChangeTrackingManager.create({iofogUuid: fogId}, transaction); } @@ -87,5 +91,6 @@ module.exports = { events: events, create: create, update: update, + updateIfChanged: updateIfChanged, getByFogId: getByFogId }; \ No newline at end of file diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 4b593b828..0bc7cfa98 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -1112,7 +1112,7 @@ ], "body": { "mode": "raw", - "raw": "{\r\n \"daemonStatus\": \"RUNNING\",\r\n \"daemonOperatingDuration\": 15,\r\n \"daemonLastStart\": 25,\r\n \"memoryUsage\": 16,\r\n \"diskUsage\": 14,\r\n \"cpuUsage\": 17,\r\n \"memoryViolation\": true,\r\n \"diskViolation\": true,\r\n \"cpuViolation\": true,\r\n \"microserviceStatus\": \"RUNNING\",\r\n \"repositoryCount\": 5,\r\n \"repositoryStatus\": \"RUNNING\",\r\n \"systemTime\": 155,\r\n \"lastStatusTime\": 166,\r\n \"ipAddress\": \"192.168.0.1\",\r\n \"processedMessages\": 255,\r\n \"microserviceMessageCounts\": \"counts\",\r\n \"messageSpeed\": 52,\r\n \"lastCommandTime\": 57,\r\n \"tunnelStatus\": \"on\",\r\n \"version\": \"1\",\r\n \"isReadyToUpgrade\": true,\r\n \"isReadyToRollback\": true\r\n}" + "raw": "{\r\n \"daemonStatus\": \"RUNNING\",\r\n \"daemonOperatingDuration\": 15,\r\n \"daemonLastStart\": 25,\r\n \"memoryUsage\": 16,\r\n \"diskUsage\": 14,\r\n \"cpuUsage\": 17,\r\n \"memoryViolation\": true,\r\n \"diskViolation\": true,\r\n \"cpuViolation\": true,\r\n \"microserviceStatus\": \"[]\",\r\n \"repositoryCount\": 5,\r\n \"repositoryStatus\": \"RUNNING\",\r\n \"systemTime\": 155,\r\n \"lastStatusTime\": 166,\r\n \"ipAddress\": \"192.168.0.1\",\r\n \"processedMessages\": 255,\r\n \"microserviceMessageCounts\": \"counts\",\r\n \"messageSpeed\": 52,\r\n \"lastCommandTime\": 57,\r\n \"tunnelStatus\": \"on\",\r\n \"version\": \"1\",\r\n \"isReadyToUpgrade\": true,\r\n \"isReadyToRollback\": true\r\n}" }, "url": { "raw": "{{host}}/api/v3/agent/status", From 2850c198e8795ca5f8568c7a42b353cbd812aef5 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Wed, 14 Nov 2018 12:47:58 +0300 Subject: [PATCH 60/91] bug portmapping and routes api fixes (#354) * get fog list params in query * [post /port-mapping] [post /routes] response code 201 -> 204 [get /port-mapping-list] -> [get /port-mapping] * cleanup: [post /port-mapping] response code 204 -> 201, because has response --- specs/swagger.yml | 5 ++--- src/routes/microservices.js | 4 ++-- tests/Controller Testing.postman_collection.json | 6 +++--- 3 files changed, 7 insertions(+), 8 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index 871370ee8..f326c8c27 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -1381,7 +1381,7 @@ paths: required: true type: string responses: - '201': + '204': description: Created headers: X-Timestamp: @@ -1471,7 +1471,6 @@ paths: description: Not Found '500': description: Internal Server Error - '/microservices/{uuid}/port-mapping-list': get: tags: - Microservices @@ -1489,7 +1488,7 @@ paths: required: true type: string responses: - '201': + '200': description: Created schema: $ref: '#/definitions/PortMappingsListResponse' diff --git a/src/routes/microservices.js b/src/routes/microservices.js index 65c8e3093..6dc6fd813 100644 --- a/src/routes/microservices.js +++ b/src/routes/microservices.js @@ -146,7 +146,7 @@ module.exports = [ method: 'post', path: '/api/v3/microservices/:uuid/routes/:receiverUuid', middleware: async (req, res) => { - const successCode = constants.HTTP_CODE_CREATED; + const successCode = constants.HTTP_CODE_NO_CONTENT; const errorCodes = [ { code: constants.HTTP_CODE_BAD_REQUEST, @@ -252,7 +252,7 @@ module.exports = [ }, { method: 'get', - path: '/api/v3/microservices/:uuid/port-mapping-list', + path: '/api/v3/microservices/:uuid/port-mapping', middleware: async (req, res) => { const successCode = constants.HTTP_CODE_SUCCESS; const errorCodes = [ diff --git a/tests/Controller Testing.postman_collection.json b/tests/Controller Testing.postman_collection.json index 0bc7cfa98..e34879b42 100644 --- a/tests/Controller Testing.postman_collection.json +++ b/tests/Controller Testing.postman_collection.json @@ -3445,7 +3445,7 @@ "script": { "id": "4f7a9f52-12cc-49d0-9e2f-147b6f5cb6fa", "exec": [ - "tests[\"Status code is 201\"] = responseCode.code === 201;" + "tests[\"Status code is 204\"] = responseCode.code === 204;" ], "type": "text/javascript" } @@ -3616,7 +3616,7 @@ "raw": "" }, "url": { - "raw": "{{host}}/api/v3/microservices/{{ms-id}}/port-mapping-list", + "raw": "{{host}}/api/v3/microservices/{{ms-id}}/port-mapping", "host": [ "{{host}}" ], @@ -3625,7 +3625,7 @@ "v3", "microservices", "{{ms-id}}", - "port-mapping-list" + "port-mapping" ] } }, From 8f687601fe2f40f3db266a0e7a36f297de51513a Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Wed, 14 Nov 2018 13:09:14 +0300 Subject: [PATCH 61/91] cli iofog help improvement ewc 342 (#355) * get fog list params in query * iofog version commands list in help --- README.md | 2 +- src/cli/iofog.js | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index b9ff96aad..0d7f53292 100644 --- a/README.md +++ b/README.md @@ -276,7 +276,7 @@ tunnel list *version* -i, --node-id string (ioFog node ID) - -v, --version-command string (ioFog version command) + -v, --version-command string (ioFog version command ) *hal-hw* diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 64edcca56..8f480f187 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -184,7 +184,7 @@ class IOFog extends BaseCLIHandler { }, { name: 'version-command', alias: 'v', type: String, - description: 'ioFog version command', + description: 'ioFog version command ', group: [constants.CMD_VERSION] }, { From 64deaacff3bc025fa3275e64d3b20f13cf8b03cd Mon Sep 17 00:00:00 2001 From: Railag Date: Wed, 14 Nov 2018 13:56:52 +0300 Subject: [PATCH 62/91] EWC-340 additional CLI validation (parameters per 1 command) (#356) * EWC-340 additional CLI validation (parameters per 1 command) * delete with cleanup microservice fix * validation for full-name parameters --- src/cli/catalog.js | 6 ++- src/cli/config.js | 6 ++- src/cli/connector.js | 6 ++- src/cli/controller.js | 8 +++- src/cli/diagnostics.js | 6 ++- src/cli/flow.js | 6 ++- src/cli/iofog.js | 6 ++- src/cli/microservice.js | 13 ++++-- src/cli/registry.js | 6 ++- src/cli/tunnel.js | 8 +++- src/cli/user.js | 6 ++- src/helpers/app-helper.js | 87 ++++++++++++++++++++++++++++++++++++++- src/helpers/errors.js | 11 ++++- 13 files changed, 160 insertions(+), 15 deletions(-) diff --git a/src/cli/catalog.js b/src/cli/catalog.js index 155482e72..af296d266 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -152,7 +152,11 @@ class Catalog extends BaseCLIHandler { try { const catalogCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (catalogCommand.command.command) { + const command = catalogCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(catalogCommand, constants.CMD_ADD, _createCatalogItem, true); break; diff --git a/src/cli/config.js b/src/cli/config.js index c8a654279..53bb561df 100644 --- a/src/cli/config.js +++ b/src/cli/config.js @@ -96,7 +96,11 @@ class Config extends BaseCLIHandler { try { const configCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (configCommand.command.command) { + const command = configCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(configCommand, constants.CMD_ADD, _addConfigOption); break; diff --git a/src/cli/connector.js b/src/cli/connector.js index 0c56bfb81..2165abb5e 100644 --- a/src/cli/connector.js +++ b/src/cli/connector.js @@ -82,7 +82,11 @@ class Connector extends BaseCLIHandler { try { const connectorCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (connectorCommand.command.command) { + const command = connectorCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(connectorCommand, constants.CMD_ADD, _createConnector, false); break; diff --git a/src/cli/controller.js b/src/cli/controller.js index 220fa5ad3..a1dce0e08 100644 --- a/src/cli/controller.js +++ b/src/cli/controller.js @@ -15,6 +15,8 @@ const BaseCLIHandler = require('./base-cli-handler'); const constants = require('../helpers/constants'); const ControllerService = require('../services/controller-service'); const logger = require('../logger'); +const AppHelper = require('../helpers/app-helper'); + class Controller extends BaseCLIHandler { @@ -42,7 +44,11 @@ class Controller extends BaseCLIHandler { try { const controllerCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (controllerCommand.command.command) { + const command = controllerCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_STATUS: await _executeCase(controllerCommand, constants.CMD_STATUS, _getStatus, false); break; diff --git a/src/cli/diagnostics.js b/src/cli/diagnostics.js index d861dc686..05dfabeaf 100644 --- a/src/cli/diagnostics.js +++ b/src/cli/diagnostics.js @@ -80,7 +80,11 @@ class Diagnostics extends BaseCLIHandler { try { const diagnosticCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (diagnosticCommand.command.command) { + const command = diagnosticCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_STRACE_UPDATE: await _executeCase(diagnosticCommand, constants.CMD_STRACE_UPDATE, _changeMicroserviceStraceState, false); break; diff --git a/src/cli/flow.js b/src/cli/flow.js index f577a6e2f..a5d422ca6 100644 --- a/src/cli/flow.js +++ b/src/cli/flow.js @@ -84,7 +84,11 @@ class Flow extends BaseCLIHandler { try { const flowCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (flowCommand.command.command) { + const command = flowCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(flowCommand, constants.CMD_ADD, _createFlow, true); break; diff --git a/src/cli/iofog.js b/src/cli/iofog.js index 8f480f187..267235683 100644 --- a/src/cli/iofog.js +++ b/src/cli/iofog.js @@ -211,7 +211,11 @@ class IOFog extends BaseCLIHandler { try { const iofogCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (iofogCommand.command.command) { + const command = iofogCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(iofogCommand, constants.CMD_ADD, _createFog, true); break; diff --git a/src/cli/microservice.js b/src/cli/microservice.js index c9fb5637e..a02fdefc9 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -182,7 +182,11 @@ class Microservice extends BaseCLIHandler { try { const microserviceCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (microserviceCommand.command.command) { + const command = microserviceCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice); break; @@ -382,8 +386,11 @@ const _listVolumeMappings = async function (obj) { }; const _removeMicroservice = async function (obj) { - logger.info(JSON.stringify(obj)); - await MicroserviceService.deleteMicroservice(obj.microserviceId, obj.cleanup, {}, true); + const microserviceData = { + withCleanup: obj.cleanup + }; + + await MicroserviceService.deleteMicroservice(obj.microserviceId, microserviceData, {}, true); logger.info('Microservice has been removed successfully.') }; diff --git a/src/cli/registry.js b/src/cli/registry.js index a748f1a57..546feb879 100644 --- a/src/cli/registry.js +++ b/src/cli/registry.js @@ -91,7 +91,11 @@ class Registry extends BaseCLIHandler { try { const registryCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (registryCommand.command.command) { + const command = registryCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(registryCommand, constants.CMD_ADD, _createRegistry, true); break; diff --git a/src/cli/tunnel.js b/src/cli/tunnel.js index 578321729..2bc3906b5 100644 --- a/src/cli/tunnel.js +++ b/src/cli/tunnel.js @@ -19,6 +19,8 @@ const TunnelService = require('../services/tunnel-service'); const CliDecorator = require('../decorators/cli-decorator'); const Errors = require('../helpers/errors'); const ErrorMessages = require('../helpers/error-messages'); +const AppHelper = require('../helpers/app-helper'); + class Tunnel extends BaseCLIHandler { constructor() { @@ -77,7 +79,11 @@ class Tunnel extends BaseCLIHandler { try { const tunnelCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (tunnelCommand.command.command) { + const command = tunnelCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_UPDATE: await _executeCase(tunnelCommand, constants.CMD_UPDATE, _updateTunnel, false); break; diff --git a/src/cli/user.js b/src/cli/user.js index b43ac6b36..71f3f6d70 100644 --- a/src/cli/user.js +++ b/src/cli/user.js @@ -68,7 +68,11 @@ class User extends BaseCLIHandler { try { const userCommand = this.parseCommandLineArgs(this.commandDefinitions, {argv: args.argv, partial: false}); - switch (userCommand.command.command) { + const command = userCommand.command.command; + + AppHelper.validateParameters(command, this.commandDefinitions, args.argv); + + switch (command) { case constants.CMD_ADD: await _executeCase(userCommand, constants.CMD_ADD, _createUser, false); break; diff --git a/src/helpers/app-helper.js b/src/helpers/app-helper.js index c002042ce..cb7089b90 100644 --- a/src/helpers/app-helper.js +++ b/src/helpers/app-helper.js @@ -62,6 +62,7 @@ const findAvailablePort = async function (hostname) { let portBounds = Config.get("Tunnel:PortRange").split("-").map(i => parseInt(i)); return await portscanner.findAPortNotInUse(portBounds[0], portBounds[1], hostname); } + /** * @desc generates a random String of the size specified by the input param * @param Integer - size @@ -152,6 +153,9 @@ function handleCLIError(error) { case "UNKNOWN_VALUE": console.log("Unknown value " + error.value); break; + case "InvalidArgumentError": + console.log(error.message); + break; default: console.log(JSON.stringify(error)); break; @@ -164,6 +168,86 @@ function trimCertificate(cert) { return result; } +function validateParameters(command, commandDefinitions, args) { + // 1st argument = command + args.shift(); + + const possibleAliasesList = _getPossibleAliasesList(command, commandDefinitions); + const possibleArgsList = _getPossibleArgsList(command, commandDefinitions); + + for (let arg of args) { + // arg is [argument, alias, value] + + if (arg.startsWith("--")) { // argument + // '--ssl-cert' format -> 'ssl-cert' format + const argument = arg.substr(2); + _validateArg(argument, possibleArgsList); + } else if (arg.startsWith("-")) { // alias + // '-q' format -> 'q' format + const alias = arg.substr(1); + _validateArg(alias, possibleAliasesList); + } else { + // value + continue; + } + } +} + +function _validateArg(arg, aliasesList) { + const valid = aliasesList.includes(arg); + if (!valid) { + throw new Errors.InvalidArgumentError("Invalid argument '" + arg + "'"); + } +} + + +function _getPossibleAliasesList(command, commandDefinitions) { + const possibleAliasesList = []; + + for (const definition of commandDefinitions) { + const group = definition.group; + const isGroupArray = group.constructor === Array; + if (isGroupArray) { + for (const gr of group) { + if (gr === command) { + possibleAliasesList.push(definition.alias); + break; + } + } + } else { + if (group === command) { + possibleAliasesList.push(definition.alias); + } + } + } + + return possibleAliasesList; +} + +function _getPossibleArgsList(command, commandDefinitions) { + const possibleArgsList = []; + + for (const definition of commandDefinitions) { + const group = definition.group; + const isGroupArray = group.constructor === Array; + if (isGroupArray) { + for (const gr of group) { + if (gr === command) { + possibleArgsList.push(definition.name); + break; + } + } + } else { + if (group === command) { + possibleArgsList.push(definition.name); + } + } + } + + return possibleArgsList; +} + + module.exports = { encryptText, decryptText, @@ -181,5 +265,6 @@ module.exports = { stringifyCliJsonSchema, isValidPublicIP, handleCLIError, - trimCertificate + trimCertificate, + validateParameters }; diff --git a/src/helpers/errors.js b/src/helpers/errors.js index b0eab2afe..08b16e1bd 100644 --- a/src/helpers/errors.js +++ b/src/helpers/errors.js @@ -87,6 +87,14 @@ class EmailActivationSetupError extends Error { } } +class InvalidArgumentError extends Error { + constructor(message) { + super(message); + this.message = message; + this.name = "InvalidArgumentError"; + } +} + module.exports = { AuthenticationError: AuthenticationError, TransactionError: TransactionError, @@ -96,5 +104,6 @@ module.exports = { ModelNotFoundError: ModelNotFoundError, DuplicatePropertyError: DuplicatePropertyError, FtpError: FtpError, - EmailActivationSetupError: EmailActivationSetupError + EmailActivationSetupError: EmailActivationSetupError, + InvalidArgumentError: InvalidArgumentError }; \ No newline at end of file From 919a75bcf823e739dc7e7dccfac0263fb6103e47 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Wed, 14 Nov 2018 14:17:38 +0300 Subject: [PATCH 63/91] redundant lib querystring was deleted. qs used instead (#357) --- package-lock.json | 7 +------ package.json | 1 - src/controllers/iofog-controller.js | 1 - src/services/connector-service.js | 8 ++++---- 4 files changed, 5 insertions(+), 12 deletions(-) diff --git a/package-lock.json b/package-lock.json index a72012898..04c6f8be0 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "0.9.5", + "version": "1.0.0", "lockfileVersion": 1, "requires": true, "dependencies": { @@ -2602,11 +2602,6 @@ "resolved": "https://registry.npmjs.org/qs/-/qs-6.5.2.tgz", "integrity": "sha512-N5ZAX4/LxJmF+7wN74pUD6qAh9/wnvdQcjq9TZjevvXzSUo7bfmw91saqMjzGS2xq91/odN2dW/WOl7qQHNDGA==" }, - "querystring": { - "version": "0.2.0", - "resolved": "https://registry.npmjs.org/querystring/-/querystring-0.2.0.tgz", - "integrity": "sha1-sgmEkgO7Jd+CDadW50cAWHhSFiA=" - }, "range-parser": { "version": "1.2.0", "resolved": "https://registry.npmjs.org/range-parser/-/range-parser-1.2.0.tgz", diff --git a/package.json b/package.json index dbd1392f4..a68f42ffb 100644 --- a/package.json +++ b/package.json @@ -65,7 +65,6 @@ "nodemailer-smtp-transport": "^2.7.4", "path": "^0.12.7", "portscanner": "^2.2.0", - "querystring": "^0.2.0", "retry-as-promised": "^3.1.0", "sequelize": "^4.39.0", "sequelize-cli": "^4.1.1", diff --git a/src/controllers/iofog-controller.js b/src/controllers/iofog-controller.js index c9ecd39a7..b68d47730 100644 --- a/src/controllers/iofog-controller.js +++ b/src/controllers/iofog-controller.js @@ -14,7 +14,6 @@ const logger = require('../logger'); const AuthDecorator = require('../decorators/authorization-decorator'); const FogService = require('../services/iofog-service'); -const querystring = require('querystring'); const qs = require('qs'); async function _createFog(req, user) { diff --git a/src/services/connector-service.js b/src/services/connector-service.js index 4fa555d3d..ba8318a04 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -21,7 +21,7 @@ const https = require('https'); const http = require('http'); const constants = require('../helpers/constants'); const logger = require('../logger'); -const querystring = require('querystring'); +const qs = require('qs'); const Op = require('sequelize').Op; const Sequelize = require('sequelize'); const fs = require('fs'); @@ -146,10 +146,10 @@ async function _makeRequest(connector, options, data) { //TODO refactor this async function openPortsOnConnector(connector, isPublicAccess, transaction) { let data = isPublicAccess - ? await querystring.stringify({ + ? await qs.stringify({ mapping: '{"type":"public","maxconnections":60,"heartbeatabsencethreshold":200000}' }) - : await querystring.stringify({ + : await qs.stringify({ mapping: '{"type":"private","maxconnectionsport1":1, "maxconnectionsport2":1, ' + '"heartbeatabsencethresholdport1":200000, "heartbeatabsencethresholdport2":200000}' }); @@ -184,7 +184,7 @@ async function _getRandomConnector(transaction) { async function closePortOnConnector(connector, ports, transaction) { console.log(ports); - let data = querystring.stringify({ + let data = qs.stringify({ mappingid: ports.mappingId }); console.log(data); From ca6583b7ea1c00ce4965f548d1618fa60af8397c Mon Sep 17 00:00:00 2001 From: Railag Date: Wed, 14 Nov 2018 14:50:22 +0300 Subject: [PATCH 64/91] EWC-347 fixed user activate/suspend handling (#358) * EWC-347 fixed user activate/suspend handling * cleanup --- src/controllers/user-controller.js | 2 +- src/helpers/error-messages.js | 2 ++ src/services/user-service.js | 12 ++++++++++++ 3 files changed, 15 insertions(+), 1 deletion(-) diff --git a/src/controllers/user-controller.js b/src/controllers/user-controller.js index 7ffe15abc..2129bb71a 100644 --- a/src/controllers/user-controller.js +++ b/src/controllers/user-controller.js @@ -54,7 +54,7 @@ const resendActivationEndPoint = async function (req) { const activateUserAccountEndPoint = async function (req) { const codeData = req.body; - return await UserService.activateUser(codeData, false); + await UserService.activateUser(codeData, false); }; const userLogoutEndPoint = async function (req, user) { diff --git a/src/helpers/error-messages.js b/src/helpers/error-messages.js index 989907761..e890cf9f0 100644 --- a/src/helpers/error-messages.js +++ b/src/helpers/error-messages.js @@ -62,6 +62,8 @@ module.exports = { INVALID_CONTENT_TYPE: 'Invalid content type', UPLOADED_FILE_NOT_FOUND: 'Uploaded image snapshot file not found', REGISTRY_NOT_FOUND: 'Registry not found', + USER_ALREADY_ACTIVATED: 'User is already activated.', + USER_NOT_ACTIVATED_YET: 'User is not activated yet.', CLI: { INVALID_PORT_MAPPING: 'Port mapping parsing error. Please provide valid port mapping.', INVALID_VOLUME_MAPPING: 'Volume mapping parsing error. Please provide valid volume mapping.', diff --git a/src/services/user-service.js b/src/services/user-service.js index 6233e3045..85e30c08e 100644 --- a/src/services/user-service.js +++ b/src/services/user-service.js @@ -107,6 +107,14 @@ const activateUser = async function (codeData, isCLI, transaction) { }; if (isCLI) { + const user = await UserManager.findOne({ + id: codeData.userId + }, transaction); + + if (user.emailActivated === true) { + throw new Error(ErrorMessages.USER_ALREADY_ACTIVATED) + } + await _updateUser(codeData.userId, updatedObj, transaction); } else { await Validator.validate(codeData, Validator.schemas.activateUser); @@ -201,6 +209,10 @@ const list = async function (isCLI, transaction) { }; const suspendUser = async function (user, isCLI, transaction) { + if (user.emailActivated === false) { + throw new Error(ErrorMessages.USER_NOT_ACTIVATED_YET) + } + const updatedObj = { emailActivated: false }; From 85b95869cc13b331aa51ffafd9256d0165bdcdf5 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Wed, 14 Nov 2018 15:39:16 +0300 Subject: [PATCH 65/91] fArgs.length check in transaction decorator (#359) --- src/decorators/transaction-decorator.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/decorators/transaction-decorator.js b/src/decorators/transaction-decorator.js index 39a0e32ed..580df4d04 100644 --- a/src/decorators/transaction-decorator.js +++ b/src/decorators/transaction-decorator.js @@ -20,7 +20,7 @@ function transaction(f) { return async function() { const fArgs = Array.prototype.slice.call(arguments); //TODO [when transactions concurrency issue fixed]: Remove 'fArgs[fArgs.length - 1].fakeTransaction' - if (fArgs[fArgs.length - 1] instanceof Transaction || fArgs[fArgs.length - 1].fakeTransaction) { + if (fArgs.length > 0 && (fArgs[fArgs.length - 1] instanceof Transaction || fArgs[fArgs.length - 1].fakeTransaction)) { return await f.apply(this, fArgs); } else { //return f.apply(this, fArgs) @@ -52,7 +52,7 @@ function fakeTransaction(f) { const fakeTransactionObject = {fakeTransaction: true} return async function() { const fArgs = Array.prototype.slice.call(arguments); - if (fArgs[fArgs.length - 1] instanceof Transaction) { + if (fArgs.length > 0 && fArgs[fArgs.length - 1] instanceof Transaction) { fArgs[fArgs.length - 1] = fakeTransactionObject; return await f.apply(this, fArgs); } else { From f436023d4b78d31f06aefce2dcf5bdda27338414 Mon Sep 17 00:00:00 2001 From: alexandershpak <35569337+alexandershpak@users.noreply.github.com> Date: Wed, 14 Nov 2018 14:42:09 +0200 Subject: [PATCH 66/91] fix swagger response list (#360) --- specs/swagger.yml | 72 +++++++++++++++++++----------- src/services/diagnostic-service.js | 1 - 2 files changed, 45 insertions(+), 28 deletions(-) diff --git a/specs/swagger.yml b/specs/swagger.yml index f326c8c27..e8bc8b80f 100644 --- a/specs/swagger.yml +++ b/specs/swagger.yml @@ -2317,7 +2317,7 @@ definitions: IOFogNodesListResponse: type: object properties: - instances: + fogs: type: array items: $ref: '#/definitions/IOFogNodeInfoResponse' @@ -2723,9 +2723,12 @@ definitions: ftpDestDir: type: string AgentMicroservicesListResponse: - type: array - items: - $ref: '#/definitions/AgentMicroservicesInfoResponse' + type: object + properties: + microservices: + type: array + items: + $ref: '#/definitions/AgentMicroservicesInfoResponse' AgentMicroservicesInfoResponse: type: object properties: @@ -2820,9 +2823,12 @@ definitions: publicPort: type: number PortMappingsListResponse: - type: array - items: - $ref: '#/definitions/PortMappingsItemResponse' + type: object + properties: + ports: + type: array + items: + $ref: '#/definitions/PortMappingsItemResponse' PortMappingsItemResponse: type: object properties: @@ -2846,9 +2852,12 @@ definitions: type: string example: 80 RegistriesListResponse: - type: array - items: - $ref: '#/definitions/RegistryResponse' + type: object + properties: + registries: + type: array + items: + $ref: '#/definitions/RegistryResponse' RegistryResponse: type: object properties: @@ -2898,9 +2907,12 @@ definitions: - open - close MicroservicesCatalogResponse: - type: array - items: - $ref: '#/definitions/CatalogItemInfoResponse' + type: object + properties: + catalogItems: + type: array + items: + $ref: '#/definitions/CatalogItemInfoResponse' CatalogItemInfoResponse: type: object properties: @@ -2951,8 +2963,8 @@ definitions: fogTypeId: type: number enum: - - 1 - - 2 + - 1 + - 2 CreateUpdateCatalogItemRequestBody: type: object properties: @@ -2983,9 +2995,12 @@ definitions: configExample: type: string GetFlowsResponse: - type: array - items: - $ref: '#/definitions/FlowInfoResponse' + type: object + properties: + flows: + type: array + items: + $ref: '#/definitions/FlowInfoResponse' FlowInfoResponse: type: object properties: @@ -3007,9 +3022,12 @@ definitions: isActivated: type: boolean GetMicroservicesResponse: - type: array - items: - $ref: '#/definitions/MicroserviceInfoResponse' + type: object + properties: + microservices: + type: array + items: + $ref: '#/definitions/MicroserviceInfoResponse' MicroserviceInfoResponse: type: object properties: @@ -3051,9 +3069,9 @@ definitions: logSize: type: number volumeMappings: - type: array - items: - $ref: '#/definitions/VolumeMapping' + type: array + items: + $ref: '#/definitions/VolumeMapping' ports: type: array items: @@ -3078,9 +3096,9 @@ definitions: logLimit: type: number volumeMappings: - type: array - items: - $ref: '#/definitions/VolumeMapping' + type: array + items: + $ref: '#/definitions/VolumeMapping' IOFogNodeTunnelStatusInfoResponse: type: object properties: diff --git a/src/services/diagnostic-service.js b/src/services/diagnostic-service.js index 171c71786..41951b23c 100644 --- a/src/services/diagnostic-service.js +++ b/src/services/diagnostic-service.js @@ -125,7 +125,6 @@ const getMicroserviceImageSnapshot = async function (microserviceUuid, user, isC throw new Errors.ValidationError(ErrorMessages.IMAGE_SNAPSHOT_NOT_AVAILABLE) } let _path = microservice.imageSnapshot; - logger.info('successfully deleted ' + microservice.imageSnapshot); await MicroserviceManager.update({uuid: microservice.uuid}, microserviceToUpdate, transaction); if (isCLI) { return _path From 5f1ba9e1c8593e9c3162f1c1871aaa118d6be438 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:19:29 +0300 Subject: [PATCH 67/91] WIP: EWC-344 automated packaging (#350) * Create pu.sh * Update .travis.yml * add notifications * Update .travis.yml * Update .gitignore --- .gitignore | 1 + .travis.yml | 22 +++++++++++++++++++--- .travis/pu.sh | 46 ++++++++++++++++++++++++++++++++++++++++++++++ 3 files changed, 66 insertions(+), 3 deletions(-) create mode 100644 .travis/pu.sh diff --git a/.gitignore b/.gitignore index f3913bba7..270dbc0fe 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ node_modules .vscode *.sqlite +src/config diff --git a/.travis.yml b/.travis.yml index 98cc7845d..1fc2a879e 100644 --- a/.travis.yml +++ b/.travis.yml @@ -1,18 +1,33 @@ sudo: true language: node_js node_js: "9" +notifications: + email: false + slack: + rooms: + - secure: T6GjQi6ap7dvARwdxo619XBUO8aXyzeP4wB8LRpnLKgDQtd+EVw3hwMcHEB7C5+KBC9D0LE0i5HjnLKj2T9ih1L1zKM0QDYFVO8jTt+zhWbEs9Famdq0kmfGiTCbiVG/vxr+9bvFF4QkFhzK8kV44uyqZkmQrHuFnrCpJivsg7dsqvxZ6iU3FV1lMOLU0SJTBHwjbVnIOEqbYcbXmuBJerLMqU7kSlGdlDgBMX8xnzPo/Ccqft+CHDSEl5XU2RZZo2kGSBApO0jpfl1r+7LzWBiwHbuIkFAR5/bVecyuCRpRB4EGEXD7cxCeNUHYjvdr/vaJwTCiPspvSOkJv5YDWgGl7V3WtCV0oPDcQGOU844nHxUTp9FPCQ1bfsPqJ13tCHgv177/Oku3xH22ex6rgTBI6kkVqP3QWTgVtRW91opaKLeBM0ZigQyxQ/hUvQKsMmXzqDrWELG2CuXt2cnNBQ5Hw9wvzEdyY/T4mkXHlbd1UMJ0PUuaymICusfzcErTTnNeByTDkSjrd4dudQtH3jg+Vn3BSQ1R1U1T6DdUhkV75tt37Ej/cbL9ZN8iey7gqx0N3nzqXA0JsBAsJspjCOZWZ0ODdI2XP9FiD+4TUj+HTBgwHtx5kUqf2uuGlKX0S74zN/RjEmHa2riviW3IVur16Vf33U8oiwY+ilht0Zo= + on_success: always + on_failure: always + template: + - Repo `%{repository_slug}` *%{result}* build (<%{build_url}|#%{build_number}>) + for commit (<%{compare_url}|%{commit}>) on branch `%{branch}`. + - 'Execution time: *%{duration}*' + - 'Message: %{message}' stages: - name: build - if: branch IN (develop, master) AND type = pull_request + if: branch = develop AND type = push - name: package_build if: (branch = develop AND type = cron) OR (branch = master and type = push) jobs: include: - stage: build + before_install: + - sudo apt-get install sshpass + script: + - sshpass -p $DEV_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $DEV_MACHINE_USERNAME@$DEV_MACHINE_IP "cd /FogController; NODE_ENV=production node src/main.js stop; git pull; npm i; NODE_ENV=production node src/main.js start" - stage: package_build - script: - - npm run build + script: .travis/pu.sh deploy: skip_cleanup: true provider: npm @@ -20,3 +35,4 @@ jobs: api_key: ${NPM_AUTH_TOKEN} on: all_branches: true + tags: false diff --git a/.travis/pu.sh b/.travis/pu.sh new file mode 100644 index 000000000..cf45dd475 --- /dev/null +++ b/.travis/pu.sh @@ -0,0 +1,46 @@ +#!/bin/sh + +setup_git() { + # Set the user name and email to match the API token holder + # This will make sure the git commits will have the correct photo + # and the user gets the credit for a checkin + git config --global user.name "dbusel" + git config --global push.default matching + + # Get the credentials from a file + git config credential.helper "store --file=.git/credentials" + + # This associates the API Key with the account + echo "https://${GITHUB_API_KEY}:@github.com" > .git/credentials +} + +make_version() { + # Make sure that the workspace is clean + # It could be "dirty" if + # 1. package-lock.json is not aligned with package.json + # 2. npm install is run + git checkout -- . + + # Echo the status to the log so that we can see it is OK + git status + + # Run the deploy build and increment the package versions + # %s is the placeholder for the created tag + if [ $TRAVIS_BRANCH = 'develop' ]; then + npm version patch -m "chore: dev version %s" + else + npm version minor -m "chore: release version %s" + fi +} + +upload_files() { + # This make sure the current work area is pushed to the tip of the current branch + git push origin HEAD:$TRAVIS_BRANCH + + # This pushes the new tag + git push --tags +} + +setup_git +make_version +upload_files From 1b462a0bda9e0f8fd51403f71b479003747703ac Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:29:06 +0300 Subject: [PATCH 68/91] Update .travis.yml --- .travis.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.travis.yml b/.travis.yml index 1fc2a879e..58d49139c 100644 --- a/.travis.yml +++ b/.travis.yml @@ -27,6 +27,7 @@ jobs: script: - sshpass -p $DEV_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $DEV_MACHINE_USERNAME@$DEV_MACHINE_IP "cd /FogController; NODE_ENV=production node src/main.js stop; git pull; npm i; NODE_ENV=production node src/main.js start" - stage: package_build + before_script: chmod +x .travis/pu.sh script: .travis/pu.sh deploy: skip_cleanup: true From 81122a8375f29fc82819a6caa9aa19b24d02bdb5 Mon Sep 17 00:00:00 2001 From: dbusel Date: Wed, 14 Nov 2018 15:32:44 +0000 Subject: [PATCH 69/91] chore: dev version 1.0.1 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 04c6f8be0..adcddb903 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.0", + "version": "1.0.1", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index a68f42ffb..a396bc159 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.0", + "version": "1.0.1", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", From 35850d1dd17e31b11ad58439a372f8f32a7982bb Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:42:32 +0300 Subject: [PATCH 70/91] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index a396bc159..d8b4e678f 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.1", + "version": "1.0.13", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", From 596ce6ea95a92430bbb24ec7f78a84b1fd10b650 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 14 Nov 2018 18:42:55 +0300 Subject: [PATCH 71/91] Update package-lock.json --- package-lock.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package-lock.json b/package-lock.json index adcddb903..7023d7aaa 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.1", + "version": "1.0.13", "lockfileVersion": 1, "requires": true, "dependencies": { From b558b4ee68c5853e3c763398d6ff5621430f1ef6 Mon Sep 17 00:00:00 2001 From: dbusel Date: Wed, 14 Nov 2018 15:47:14 +0000 Subject: [PATCH 72/91] chore: dev version 1.0.14 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 7023d7aaa..3106acebb 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.13", + "version": "1.0.14", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index d8b4e678f..29f535fe2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.13", + "version": "1.0.14", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", From b375bdba2302667a108faf63eba2fd0424917bf3 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Thu, 15 Nov 2018 15:47:35 +0300 Subject: [PATCH 73/91] Update .travis.yml --- .travis.yml | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/.travis.yml b/.travis.yml index 58d49139c..b638f6270 100644 --- a/.travis.yml +++ b/.travis.yml @@ -15,6 +15,8 @@ notifications: - 'Message: %{message}' stages: - name: build + if: type = pull_request +- name: dev_deploy if: branch = develop AND type = push - name: package_build if: (branch = develop AND type = cron) OR (branch = master and type = push) @@ -22,6 +24,7 @@ stages: jobs: include: - stage: build + - stage: dev_deploy before_install: - sudo apt-get install sshpass script: @@ -37,3 +40,9 @@ jobs: on: all_branches: true tags: false + after_deploy: + - if [ "$TRAVIS_BRANCH" == "develop" ]; then sshpass -p $PRE_PROD_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no + $PRE_PROD_MACHINE_USERNAME@$PRE_PROD_MACHINE_IP "iofog-controller stop; npm update -g --unsafe-perm iofogcontroller; iofog-controller start"; + else sshpass -p $PROD_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no + $PROD_MACHINE_USERNAME@$PROD_MACHINE_IP "iofog-controller stop; npm update -g --unsafe-perm iofogcontroller; iofog-controller start"; fi + From 74db44a64a1018af1396c69405d13762cddeab11 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Thu, 15 Nov 2018 15:50:00 +0300 Subject: [PATCH 74/91] bluetooth and microservice creation on fog update fix: (#362) if trying to update fog from cli then userId for bluetooth or hal microservices got from oldFog data instead of user obj? which doesn't exists in cli call --- src/services/iofog-service.js | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 94e078e40..270fad60a 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -174,7 +174,7 @@ async function _updateFog(fogData, user, isCli, transaction) { iofogUuid: fogData.uuid, rootHostAccess: true, logSize: 50, - userId: user.id, + userId: isCli ? oldFog.userId : user.id, configLastUpdated: Date.now() }; @@ -206,7 +206,7 @@ async function _updateFog(fogData, user, isCli, transaction) { iofogUuid: fogData.uuid, rootHostAccess: true, logSize: 50, - userId: user.id, + userId: isCli ? oldFog.userId : user.id, configLastUpdated: Date.now() }; From 57fdf515a5755c05bab54158d5db44428c9ad5e5 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Thu, 15 Nov 2018 15:50:19 +0300 Subject: [PATCH 75/91] correct delete and create routes on update iofognode field of microservice (#361) --- src/services/microservices-service.js | 45 +++++++++++++++++++++++---- 1 file changed, 39 insertions(+), 6 deletions(-) diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 588648ecc..1e07b56e3 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -178,13 +178,24 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, await _updateVolumeMappings(microserviceDataUpdate.volumeMappings, microserviceUuid, transaction); } - if (microserviceDataUpdate.iofogUuid) { - await _deleteRoutes(microserviceData.routes, microserviceUuid, transaction); - await _createRoutes(microserviceData.routes, microserviceUuid, user, transaction); - await _updateChangeTracking(false, microserviceDataUpdate.iofogUuid, transaction) + if (microserviceDataUpdate.iofogUuid !== microservice.iofogUuid) { + const routes = await _getLogicalNetworkRoutesByFog(microservice.iofogUuid, transaction); + for (let route of routes) { + await _deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, isCLI, transaction); + await _createRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, isCLI, transaction); + //update change tracking for another fog in route + if (microservice.iofogUuid === route.sourceIofogUuid) { + await _updateChangeTracking(false, route.destIofogUuid, transaction); + } else if (microservice.iofogUuid === route.destIofogUuid) { + await _updateChangeTracking(false, route.sourceIofogUuid, transaction); + } + } + //update change tracking for old fog + await _updateChangeTracking(false, microservice.iofogUuid, transaction); } - await _updateChangeTracking(microserviceData.config ? true : false, microservice.iofogUuid, transaction); + //update change tracking for new fog + await _updateChangeTracking(microserviceData.config ? true : false, microserviceDataUpdate.iofogUuid, transaction); }; const _updateVolumeMappings = async function (volumeMappings, microserviceUuid, transaction) { @@ -769,7 +780,7 @@ async function getPhysicalConections(microservice, transaction) { const sourceRoutes = await RoutingManager.findAll({sourceMicroserviceUuid: microservice.uuid}, transaction) for (const sr of sourceRoutes) { if (!sr.sourceIofogUuid || !sr.destIofogUuid) { - break; + continue; } else if (sr.sourceIofogUuid === sr.destIofogUuid) { res.push(sr.destMicroserviceUuid) } else if (sr.sourceIofogUuid !== sr.destIofogUuid) { @@ -785,6 +796,28 @@ async function getPhysicalConections(microservice, transaction) { return res } +async function _getLogicalNetworkRoutesByFog(iofogUuid, transaction) { + let res = []; + const query = { + [Op.or]: + [ + { + sourceIofogUuid: iofogUuid + }, + { + destIofogUuid: iofogUuid + } + ] + }; + const routes = await RoutingManager.findAll(query, transaction) + for (let route of routes) { + if (route.sourceIofogUuid && route.destIofogUuid && route.isNetworkConnection) { + res.push(route); + } + } + return res; +} + async function _buildLink(protocol, ip, port) { return `${protocol}://${ip}:${port}` } From 06f1db0e6718b2236f323709bacd26171029a8eb Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Fri, 16 Nov 2018 11:49:08 +0300 Subject: [PATCH 76/91] EWC-351 type of catalog-id and flow-id in microservice cli was changed (#364) string -> number --- README.md | 4 ++-- src/cli/microservice.js | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/README.md b/README.md index 0d7f53292..637bb504f 100644 --- a/README.md +++ b/README.md @@ -467,8 +467,8 @@ $ iofog-controller catalog <*command*> <*options*>
-f, --file string (Microservice settings JSON file)
-n, --name string (Microservice name)
- -c, --catalog-id string (Catalog item ID)
- -F, --flow-id string (Application flow ID)
+ -c, --catalog-id number (Catalog item ID)
+ -F, --flow-id number (Application flow ID)
-I, --iofog-id string (ioFog node ID)
-g, --config string (Microservice config)
-v, --volumes string[] (Microservice volume mapping(s))
diff --git a/src/cli/microservice.js b/src/cli/microservice.js index a02fdefc9..61bfb331d 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -91,11 +91,11 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'catalog-id', alias: 'c', type: String, description: 'Catalog item ID', + name: 'catalog-id', alias: 'c', type: Number, description: 'Catalog item ID', group: [constants.CMD_ADD] }, { - name: 'flow-id', alias: 'F', type: String, description: 'Application flow ID', + name: 'flow-id', alias: 'F', type: Number, description: 'Application flow ID', group: [constants.CMD_ADD] }, { From 629f37a9f333e98dfedf90b101841aa478fd1f67 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Fri, 16 Nov 2018 11:55:52 +0300 Subject: [PATCH 77/91] todo in iofog-service was done (#363) --- src/services/connector-service.js | 1 - src/services/iofog-service.js | 148 +++++++++++++----------------- 2 files changed, 63 insertions(+), 86 deletions(-) diff --git a/src/services/connector-service.js b/src/services/connector-service.js index ba8318a04..0bfd157bf 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -143,7 +143,6 @@ async function _makeRequest(connector, options, data) { }) } -//TODO refactor this async function openPortsOnConnector(connector, isPublicAccess, transaction) { let data = isPublicAccess ? await qs.stringify({ diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 270fad60a..46e595751 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -63,45 +63,12 @@ async function _createFog(fogData, user, isCli, transaction) { await ChangeTrackingService.create(fog.uuid, transaction); - //TODO: proccess watchdog flag - - //TODO refactor. call MicroserviceService.createMicroservice - //TODO: refactor. to function if (fogData.abstractedHardwareEnabled) { - const halItem = await CatalogService.getHalCatalogItem(transaction); - - const halMicroserviceData = { - uuid: AppHelper.generateRandomString(32), - name: `HAL for Fog ${fog.uuid}`, - config: '{}', - catalogItemId: halItem.id, - iofogUuid: fog.uuid, - rootHostAccess: true, - logSize: 50, - userId: user.id, - configLastUpdated: Date.now() - }; - - await MicroserviceManager.create(halMicroserviceData, transaction); + await _createHalMicroserviceForFog(fog, null, user, transaction); } - //TODO: refactor. to function if (fogData.bluetoothEnabled) { - const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); - - const bluetoothMicroserviceData = { - uuid: AppHelper.generateRandomString(32), - name: `Bluetooth for Fog ${fog.uuid}`, - config: '{}', - catalogItemId: bluetoothItem.id, - iofogUuid: fog.uuid, - rootHostAccess: true, - logSize: 50, - userId: user.id, - configLastUpdated: Date.now() - }; - - await MicroserviceManager.create(bluetoothMicroserviceData, transaction); + await _createBluetoothMicroserviceForFog(fog, null, user, transaction); } await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.microserviceCommon, transaction) @@ -150,67 +117,22 @@ async function _updateFog(fogData, user, isCli, transaction) { await ChangeTrackingService.update(fogData.uuid, ChangeTrackingService.events.config, transaction); let msChanged = false; - //TODO: refactor. to function - if (oldFog.bluetoothEnabled === true && fogData.bluetoothEnabled === false) { - const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); - const deleteBluetoothMicroserviceData = { - iofogUuid: fogData.uuid, - catalogItemId: bluetoothItem.id - }; - await MicroserviceManager.delete(deleteBluetoothMicroserviceData, transaction) + if (oldFog.bluetoothEnabled === true && fogData.bluetoothEnabled === false) { + await _deleteBluetoothMicroserviceByFog(fogData, transaction); msChanged = true; } - - //TODO: refactor. to function if (oldFog.bluetoothEnabled === false && fogData.bluetoothEnabled === true) { - const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); - - const bluetoothMicroserviceData = { - uuid: AppHelper.generateRandomString(32), - name: `Bluetooth for Fog ${fogData.uuid}`, - config: '{}', - catalogItemId: bluetoothItem.id, - iofogUuid: fogData.uuid, - rootHostAccess: true, - logSize: 50, - userId: isCli ? oldFog.userId : user.id, - configLastUpdated: Date.now() - }; - - await MicroserviceManager.create(bluetoothMicroserviceData, transaction); + await _createBluetoothMicroserviceForFog(fogData, oldFog, user, transaction); msChanged = true; } - //TODO: refactor. to function if (oldFog.abstractedHardwareEnabled === true && fogData.abstractedHardwareEnabled === false) { - const halItem = await CatalogService.getHalCatalogItem(transaction); - const deleteHalMicroserviceData = { - iofogUuid: fogData.uuid, - catalogItemId: halItem.id - }; - - await MicroserviceManager.delete(deleteHalMicroserviceData, transaction) + await _deleteHalMicroseviceByFog(fogData, transaction); msChanged = true; } - - //TODO: refactor. to function if (oldFog.abstractedHardwareEnabled === false && fogData.abstractedHardwareEnabled === true) { - const halItem = await CatalogService.getHalCatalogItem(transaction); - - const halMicroserviceData = { - uuid: AppHelper.generateRandomString(32), - name: `Hal for Fog ${fogData.uuid}`, - config: '{}', - catalogItemId: halItem.id, - iofogUuid: fogData.uuid, - rootHostAccess: true, - logSize: 50, - userId: isCli ? oldFog.userId : user.id, - configLastUpdated: Date.now() - }; - - await MicroserviceManager.create(halMicroserviceData, transaction); + await _createHalMicroserviceForFog(fogData, oldFog, user, transaction); msChanged = true; } @@ -454,6 +376,62 @@ async function _processDeleteCommand(fog, transaction) { } } +async function _createHalMicroserviceForFog(fogData, oldFog, user, transaction) { + const halItem = await CatalogService.getHalCatalogItem(transaction); + + const halMicroserviceData = { + uuid: AppHelper.generateRandomString(32), + name: `Hal for Fog ${fogData.uuid}`, + config: '{}', + catalogItemId: halItem.id, + iofogUuid: fogData.uuid, + rootHostAccess: true, + logSize: 50, + userId: oldFog ? oldFog.userId : user.id, + configLastUpdated: Date.now() + }; + + await MicroserviceManager.create(halMicroserviceData, transaction); +} + +async function _deleteHalMicroseviceByFog(fogData, transaction) { + const halItem = await CatalogService.getHalCatalogItem(transaction); + const deleteHalMicroserviceData = { + iofogUuid: fogData.uuid, + catalogItemId: halItem.id + }; + + await MicroserviceManager.delete(deleteHalMicroserviceData, transaction) +} + +async function _createBluetoothMicroserviceForFog(fogData, oldFog, user, transaction) { + const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); + + const bluetoothMicroserviceData = { + uuid: AppHelper.generateRandomString(32), + name: `Bluetooth for Fog ${fogData.uuid}`, + config: '{}', + catalogItemId: bluetoothItem.id, + iofogUuid: fogData.uuid, + rootHostAccess: true, + logSize: 50, + userId: oldFog ? oldFog.userId : user.id, + configLastUpdated: Date.now() + }; + + await MicroserviceManager.create(bluetoothMicroserviceData, transaction); +} + +async function _deleteBluetoothMicroserviceByFog(fogData, transaction) { + const bluetoothItem = await CatalogService.getBluetoothCatalogItem(transaction); + const deleteBluetoothMicroserviceData = { + iofogUuid: fogData.uuid, + catalogItemId: bluetoothItem.id + }; + + await MicroserviceManager.delete(deleteBluetoothMicroserviceData, transaction) +} + module.exports = { createFog: TransactionDecorator.generateTransaction(_createFog), updateFog: TransactionDecorator.generateTransaction(_updateFog), From 94e50946c98a701636173b4d11817eda8e5e71ea Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Fri, 16 Nov 2018 17:18:57 +0300 Subject: [PATCH 78/91] user preparation in microservice cli (#366) --- src/cli/microservice.js | 89 ++++++++++++++++++++++------------------- 1 file changed, 48 insertions(+), 41 deletions(-) diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 61bfb331d..f97028739 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -18,6 +18,7 @@ const logger = require('../logger'); const MicroserviceService = require('../services/microservices-service'); const fs = require('fs'); const AppHelper = require('../helpers/app-helper'); +const CliDecorator = require('../decorators/cli-decorator'); const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( { @@ -188,43 +189,43 @@ class Microservice extends BaseCLIHandler { switch (command) { case constants.CMD_ADD: - await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice); + await _executeCase(microserviceCommand, constants.CMD_ADD, _createMicroservice, true); break; case constants.CMD_UPDATE: - await _executeCase(microserviceCommand, constants.CMD_UPDATE, _updateMicroservice); + await _executeCase(microserviceCommand, constants.CMD_UPDATE, _updateMicroservice, false); break; case constants.CMD_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_REMOVE, _removeMicroservice); + await _executeCase(microserviceCommand, constants.CMD_REMOVE, _removeMicroservice, false); break; case constants.CMD_LIST: - await _executeCase(microserviceCommand, constants.CMD_LIST, _listMicroservices); + await _executeCase(microserviceCommand, constants.CMD_LIST, _listMicroservices, false); break; case constants.CMD_INFO: - await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice); + await _executeCase(microserviceCommand, constants.CMD_INFO, _getMicroservice, false); break; case constants.CMD_ROUTE_CREATE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE_CREATE, _createRoute); + await _executeCase(microserviceCommand, constants.CMD_ROUTE_CREATE, _createRoute, false); break; case constants.CMD_ROUTE_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_ROUTE_REMOVE, _removeRoute); + await _executeCase(microserviceCommand, constants.CMD_ROUTE_REMOVE, _removeRoute, false); break; case constants.CMD_PORT_MAPPING_CREATE: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_CREATE, _createPortMapping); + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_CREATE, _createPortMapping, false); break; case constants.CMD_PORT_MAPPING_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_REMOVE, _removePortMapping); + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_REMOVE, _removePortMapping, false); break; case constants.CMD_PORT_MAPPING_LIST: - await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_LIST, _listPortMappings); + await _executeCase(microserviceCommand, constants.CMD_PORT_MAPPING_LIST, _listPortMappings, false); break; case constants.CMD_VOLUME_MAPPING_CREATE: - await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_CREATE, _createVolumeMapping); + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_CREATE, _createVolumeMapping, false); break; case constants.CMD_VOLUME_MAPPING_REMOVE: - await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_REMOVE, _removeVolumeMapping); + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_REMOVE, _removeVolumeMapping, false); break; case constants.CMD_VOLUME_MAPPING_LIST: - await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_LIST, _listVolumeMappings); + await _executeCase(microserviceCommand, constants.CMD_VOLUME_MAPPING_LIST, _listVolumeMappings, false); break; case constants.CMD_HELP: default: @@ -300,22 +301,28 @@ class Microservice extends BaseCLIHandler { } } -const _executeCase = async function (microserviceCommand, commandName, f) { +async function _executeCase(commands, commandName, f, isUserRequired) { try { - const item = microserviceCommand[commandName] || {}; - await f(item); + const obj = commands[commandName]; + + if (isUserRequired) { + const decoratedFunction = CliDecorator.prepareUserById(f); + await decoratedFunction(obj); + } else { + await f(obj); + } } catch (error) { logger.error(error.message); } -}; +} -const _createRoute = async function (obj) { +const _createRoute = async function (obj, user) { logger.info(JSON.stringify(obj)); try { const arr = obj.route.split(':'); const sourceMicroserviceId = arr[0]; const destMicroserviceId = arr[1]; - await MicroserviceService.createRoute(sourceMicroserviceId, destMicroserviceId, {}, true); + await MicroserviceService.createRoute(sourceMicroserviceId, destMicroserviceId, user, true); logger.info(`Microservice route with source microservice ${sourceMicroserviceId} and dest microservice ${destMicroserviceId} has been created successfully.`) } catch (e) { @@ -323,13 +330,13 @@ const _createRoute = async function (obj) { } }; -const _removeRoute = async function (obj) { +const _removeRoute = async function (obj, user) { logger.info(JSON.stringify(obj)); try { const arr = obj.route.split(':'); const sourceMicroserviceId = arr[0]; const destMicroserviceId = arr[1]; - await MicroserviceService.deleteRoute(sourceMicroserviceId, destMicroserviceId, {}, true); + await MicroserviceService.deleteRoute(sourceMicroserviceId, destMicroserviceId, user, true); logger.info(`Microservice route with source microservice ${obj.sourceMicroserviceId} and dest microservice ${obj.destMicroserviceId} has been removed successfully.`); } catch (e) { @@ -337,60 +344,60 @@ const _removeRoute = async function (obj) { } }; -const _createPortMapping = async function (obj) { +const _createPortMapping = async function (obj, user) { logger.info(JSON.stringify(obj)); const mapping = parsePortMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_PORT_MAPPING); - await MicroserviceService.createPortMapping(obj.microserviceId, mapping, {}, true); + await MicroserviceService.createPortMapping(obj.microserviceId, mapping, user, true); logger.info('Port mapping has been created successfully.'); }; -const _createVolumeMapping = async function (obj) { +const _createVolumeMapping = async function (obj, user) { logger.info(JSON.stringify(obj)); const mapping = parseVolumeMappingObject(obj.mapping, ErrorMessages.CLI.INVALID_VOLUME_MAPPING); - const result = await MicroserviceService.createVolumeMapping(obj.microserviceId, mapping, {}, true); + const result = await MicroserviceService.createVolumeMapping(obj.microserviceId, mapping, user, true); logger.info(JSON.stringify(result, null, 2)); logger.info('Volume mapping has been created successfully.') }; -const _removePortMapping = async function (obj) { +const _removePortMapping = async function (obj, user) { logger.info(JSON.stringify(obj)); try { const internalPort = parseInt(obj.internalPort); - await MicroserviceService.deletePortMapping(obj.microserviceId, internalPort, {}, true); + await MicroserviceService.deletePortMapping(obj.microserviceId, internalPort, user, true); logger.info('Port mapping has been deleted successfully.'); } catch (e) { logger.error(ErrorMessages.CLI.INVALID_INTERNAL_PORT); } }; -const _removeVolumeMapping = async function (obj) { +const _removeVolumeMapping = async function (obj, user) { logger.info(JSON.stringify(obj)); try { - await MicroserviceService.deleteVolumeMapping(obj.microserviceId, obj.mappingId, {}, true); + await MicroserviceService.deleteVolumeMapping(obj.microserviceId, obj.mappingId, user, true); logger.info('Volume mapping has been deleted successfully.'); } catch (e) { logger.error(ErrorMessages.CLI.INVALID_VOLUME_MAPPING); } }; -const _listPortMappings = async function (obj) { - const result = await MicroserviceService.listMicroservicePortMappings(obj.microserviceId, {}, true); +const _listPortMappings = async function (obj, user) { + const result = await MicroserviceService.listMicroservicePortMappings(obj.microserviceId, user, true); logger.info(JSON.stringify(result, null, 2)); logger.info('Port mappings have been retrieved successfully.'); }; -const _listVolumeMappings = async function (obj) { - const result = await MicroserviceService.listVolumeMappings(obj.microserviceId, {}, true); +const _listVolumeMappings = async function (obj, user) { + const result = await MicroserviceService.listVolumeMappings(obj.microserviceId, user, true); logger.info(JSON.stringify(result, null, 2)); logger.info('Volume mappings have been retrieved successfully.'); }; -const _removeMicroservice = async function (obj) { +const _removeMicroservice = async function (obj, user) { const microserviceData = { withCleanup: obj.cleanup }; - await MicroserviceService.deleteMicroservice(obj.microserviceId, microserviceData, {}, true); + await MicroserviceService.deleteMicroservice(obj.microserviceId, microserviceData, user, true); logger.info('Microservice has been removed successfully.') }; @@ -400,33 +407,33 @@ const _listMicroservices = async function () { logger.info('Microservices have been retrieved successfully.'); }; -const _getMicroservice = async function (obj) { +const _getMicroservice = async function (obj, user) { logger.info(JSON.stringify(obj)); - const result = await MicroserviceService.getMicroservice(obj.microserviceId, {}, true); + const result = await MicroserviceService.getMicroservice(obj.microserviceId, user, true); logger.info(JSON.stringify(result, null, 2)); logger.info('Microservice has been retrieved successfully.'); }; -const _createMicroservice = async function (obj) { +const _createMicroservice = async function (obj, user) { const microservice = obj.file ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _createMicroserviceObject(obj); logger.info(JSON.stringify(microservice)); - const result = await MicroserviceService.createMicroserviceOnFog(microservice, {}, true); + const result = await MicroserviceService.createMicroserviceOnFog(microservice, user, true); logger.info(JSON.stringify(result)); logger.info('Microservice has been created successfully.'); }; -const _updateMicroservice = async function (obj) { +const _updateMicroservice = async function (obj, user) { const microservice = obj.file ? JSON.parse(fs.readFileSync(obj.file, 'utf8')) : _updateMicroserviceObject(obj); logger.info(JSON.stringify(microservice)); - await MicroserviceService.updateMicroservice(obj.microserviceId, microservice, {}, true); + await MicroserviceService.updateMicroservice(obj.microserviceId, microservice, user, true); logger.info('Microservice has been updated successfully.'); }; From 1276f7b58df30f65822affa57edc7bf497db68d6 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Fri, 16 Nov 2018 17:21:22 +0300 Subject: [PATCH 79/91] EWC-353 renaming in microservice cli: (#365) logLimit -> logSize --- README.md | 4 ++-- src/cli/microservice.js | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 637bb504f..2790ad965 100644 --- a/README.md +++ b/README.md @@ -472,7 +472,7 @@ $ iofog-controller catalog <*command*> <*options*>
-I, --iofog-id string (ioFog node ID)
-g, --config string (Microservice config)
-v, --volumes string[] (Microservice volume mapping(s))
- -l, --log-limit number (Log file size limit (MB))
+ -l, --log-size number (Log file size limit (MB))
-r, --root-enable (Enable root access)
-R, --root-disable (Disable root access)
-p, --ports string[] (Container ports)
@@ -485,7 +485,7 @@ $ iofog-controller catalog <*command*> <*options*>
-I, --iofog-id string (ioFog node ID)
-g, --config string (Microservice config)
-v, --volumes string[] (Microservice volume mapping(s))
- -l, --log-limit number (Log file size limit (MB))
+ -l, --log-size number (Log file size limit (MB))
-r, --root-enable (Enable root access)
-R, --root-disable (Disable root access)
-w, --rebuild (Rebuild microservice image on fog agent)
diff --git a/src/cli/microservice.js b/src/cli/microservice.js index f97028739..2c9d3c91d 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -28,7 +28,7 @@ const JSON_SCHEMA_ADD = AppHelper.stringifyCliJsonSchema( flowId: 0, iofogUuid: "string", rootHostAccess: true, - logLimit: 0, + logSize: 0, volumeMappings: [ { hostDestination: "/var/dest", @@ -56,7 +56,7 @@ const JSON_SCHEMA_UPDATE = AppHelper.stringifyCliJsonSchema( rebuild: true, iofogUuid: "string", rootHostAccess: true, - logLimit: 0, + logSize: 0, volumeMappings: [ { hostDestination: "/var/dest", @@ -443,7 +443,7 @@ const _updateMicroserviceObject = function (obj) { config: obj.config, iofogUuid: obj.iofogId, rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), - logLimit: obj.logLimit, + logSize: obj.logSize, rebuild: obj.rebuild }; @@ -462,7 +462,7 @@ const _createMicroserviceObject = function (obj) { flowId: parseInt(obj.flowId), iofogUuid: obj.iofogId, rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), - logLimit: obj.logLimit, + logSize: obj.logSize, routes: obj.routes }; From 49413861114c363b27e735a0eec984dca02f093e Mon Sep 17 00:00:00 2001 From: Marina Lipnitskaya Date: Fri, 16 Nov 2018 17:49:06 +0300 Subject: [PATCH 80/91] Update README.md (#367) --- README.md | 199 ++++++++++++++++++++++++++++++++++-------------------- 1 file changed, 126 insertions(+), 73 deletions(-) diff --git a/README.md b/README.md index 2790ad965..f4ef09950 100644 --- a/README.md +++ b/README.md @@ -96,8 +96,7 @@ $ iofog-controller config <*options*> -c, --ssl-cert string (Path to SSL certificate file)
-k, --ssl-key string (Path to SSL key file)
-i, --intermediate-cert string (Path to SSL intermediate certificate file)
- -m, --email-activation-on (Email activation required)
- -n, --email-activation-off (Email activation not required)
+ -h, --home-url string (Home page url for email activation links)
-a, --email-address string (Email address to send activations from)
-w, --email-password string (Email password to send activations from)
-s, --email-service string (Email service to send activations)
@@ -111,6 +110,11 @@ $ iofog-controller config <*options*> -o, --on (Enable dev mode)
-f, --off (Disable dev mode)
+ *email-activation*
+ + -o, --on (Enable)
+ -f, --off (Disable)
+


@@ -286,30 +290,30 @@ tunnel list -i, --node-id string (ioFog node ID)
-*JSON File Schema* - - name: string
- location: string
- latitude: number
- longitude: number
- description: string
- dockerUrl: string
- diskLimit: number
- diskDirectory: string
- memoryLimit: number
- cpuLimit: number
- logLimit: number
- logDirectory: string
- logFileCount: number
- statusFrequency: number
- changeFrequency: number
- deviceScanFrequency: number
- bluetoothEnabled: boolean
- watchdogEnabled: boolean
- abstractedHardwareEnabled: boolean
- reboot: boolean
- fogType: number
- +*JSON File Schema*
+ + {
+ "name": "string",
+ "location": "string",
+ "latitude": 0,
+ "longitude": 0,
+ "description": "string",
+ "dockerUrl": "string",
+ "diskLimit": 0,
+ "diskDirectory": "string",
+ "memoryLimit": 0,
+ "cpuLimit": 0,
+ "logLimit": 0,
+ "logDirectory": "string",
+ "logFileCount": 0,
+ "statusFrequency": 0,
+ "changeFrequency": 0,
+ "deviceScanFrequency": 0,
+ "bluetoothEnabled": false,
+ "watchdogEnabled": true,
+ "abstractedHardwareEnabled": false,
+ "fogType": 0
+ }



@@ -378,28 +382,36 @@ $ iofog-controller catalog <*command*> <*options*>
*JSON File Schema*
- name: string
- description: string
- category: string
- publisher: string
- diskRequired: number
- ramRequired: number
- picture: string
- isPublic: boolean
- registryId: number
- configExample: string
- images: array of objects
- containerImage: string
- fogTypeId: number
- inputType: object
- infoType: string
- infoFormat: string
- outputType: object
- infoType: string
- infoFormat: string
+ {
+ "name": "string",
+ "description": "string",
+ "category": "string",
+ "images": [
+ {
+ "containerImage": "string",
+ "fogTypeId": 1
+ }
+ ],
+ "publisher": "string",
+ "diskRequired": 0,
+ "ramRequired": 0,
+ "picture": "string",
+ "isPublic": true,
+ "registryId": 0,
+ "inputType": {
+ "infoType": "string",
+ "infoFormat": "string"
+ },
+ "outputType": {
+ "infoType": "string",
+ "infoFormat": "string"
+ },
+ "configExample": "string"
+}



+ **Flow**
$ iofog-controller flow <*command*> <*options*>
@@ -438,9 +450,11 @@ $ iofog-controller catalog <*command*> <*options*>
*JSON File Schema*
- name: string
- description: string
- isActivated: boolean
+{
+ "name": "string",
+ "description": "string",
+ "isActivated": true
+}


@@ -452,16 +466,19 @@ $ iofog-controller catalog <*command*> <*options*>
*Command List*
- add -- Add a new microservice.
- update -- Update existing microservice.
- remove -- Delete a microservice.
- list -- List all microservices.
- info -- Get microservice settings.
- route-create -- Create microservice route.
- route-remove -- Remove microservice route.
- port-mapping-create -- Create microservice port mapping.
- port-mapping-remove -- Remove microservice port mapping.
- port-mapping-list -- List microservice port mapping.
+ add -- Add a new microservice.
+ update -- Update existing microservice.
+ remove -- Delete a microservice.
+ list -- List all microservices.
+ info -- Get microservice settings.
+ route-create -- Create microservice route.
+ route-remove -- Remove microservice route.
+ port-mapping-create -- Create microservice port mapping.
+ port-mapping-remove -- Remove microservice port mapping.
+ port-mapping-list -- List microservice port mapping.
+ volume-mapping-create -- Create microservice volume mapping.
+ volume-mapping-remove -- Remove microservice volume mapping.
+ volume-mapping-list -- List microservice volume mapping.
*add -u* <*user-id*> @@ -521,7 +538,23 @@ $ iofog-controller catalog <*command*> <*options*>
-i, --microservice-id string (Microservice ID)
-b, --internal-port string (Internal port)
-*port-mapping-list* +*port-mapping-list*
+ +-i, --microservice-id string (Microservice ID)
+ +*volume-mapping-create*
+ + -i, --microservice-id string (Microservice ID)
+ -P, --mapping string (Container port mapping)
+ +*volume-mapping-remove*
+ + -i, --microservice-id string (Microservice ID)
+ -a, --mapping-id number (Volume mapping id)
+ +*volume-mapping-list*
+ + -i, --microservice-id string (Microservice ID)
**JSON ADD File Schema**
@@ -574,20 +607,20 @@ $ iofog-controller catalog <*command*> <*options*>
1. Single mapping
$ iofog-controller microservice add [other required options] --volumes
- /host_src:/container_src
+ /host_src:/container_src:rw
2. Multiple mappings
$ iofog-controller microservice add [other required options] --volumes
- /host_src:/container_src
- /host_bin:/container_bin
+ /host_src:/container_src:rw
+ /host_bin:/container_bin:r
3. Port mapping (80:8080:false - internal port : external port : public mode)
- $ iofog-controller microservice add [other required options] --ports
- 80:8080:false 443:5443:false
+ $ iofog-controller microservice add [other required options]
+ --ports 80:8080:false 443:5443:false
4. Add routes (ABC:DEF - source microservice id : dest microservice id)
- $ iofog-controller microservice add [other required options] --routes
- ABC:DEF RFG:HJK
+ $ iofog-controller microservice add [other required options]
+ --routes ABC:DEF RFG:HJK
5. Add route (ABC:DEF - source microservice id : dest microservice id)
$ iofog-controller microservice route-create --route ABC:DEF
@@ -600,6 +633,12 @@ $ iofog-controller catalog <*command*> <*options*>
8. Delete port mapping (80 - internal port, ABC - microservice id)
$ iofog-controller microservice port-mapping-remove --internal-port 80 -i ABC
+ + 9. Create volume mapping
+ $ iofog-controller microservice volume-mapping-create --mapping /host_src:/container_src:rw -i ABC
+ + 10. Delete volume mapping
+ $ iofog-controller microservice volume-mapping-remove -i ABC -a 1



@@ -612,20 +651,34 @@ $ iofog-controller catalog <*command*> <*options*>
add -- Add a new Registry.
remove -- Delete a Registry.
+ update -- Update a Registry.
list -- List all Registries.
-*add -i* <*user-id*> +*add -i* <*user-id*>
- -u, --uri string (Registry URI)
- -b, --public (Set registry as public)
- -r, --private (Set registry as private)
- -l, --username string (Registry's user name)
- -p, --password string (Password)
- -e, --email string (Email address)
+ -u, --uri string (Registry URI)
+ -b, --public (Set registry as public)
+ -r, --private (Set registry as private)
+ -l, --username string (Registry's user name)
+ -p, --password string (Password)
+ -c, --requires-certificate (Requires certificate)
+ -C, --certificate string (Certificate)
+ -e, --email string (Email address)
*remove*
-d, --item-id number (Item's id) + +*update -d* <*item-id*>
+ + -u, --uri string (Registry URI)
+ -b, --public (Set registry as public)
+ -r, --private (Set registry as private)
+ -l, --username string (Registry's user name)
+ -p, --password string (Password)
+ -c, --requires-certificate (Requires certificate)
+ -C, --certificate string (Certificate)
+ -e, --email string (Email address)



From 663d38e3bed781d337c5259f5059384ea3b66d9b Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Mon, 19 Nov 2018 13:50:30 +0300 Subject: [PATCH 81/91] Maksimchepelev/bug cli microservice update ewc 354 (#368) * EWC-354 correct cli processing in update microservice * get microservice response was updated: + flowId + iofoguuid + catalogItemId --- .../managers/microservice-manager.js | 5 +--- src/services/microservices-service.js | 26 ++++++++++++------- 2 files changed, 17 insertions(+), 14 deletions(-) diff --git a/src/sequelize/managers/microservice-manager.js b/src/sequelize/managers/microservice-manager.js index 186e8640b..297711b32 100644 --- a/src/sequelize/managers/microservice-manager.js +++ b/src/sequelize/managers/microservice-manager.js @@ -252,16 +252,13 @@ class MicroserviceManager extends BaseManager { 'created_at', 'updated_at', 'updatedBy', - 'flowId', 'registryId', 'isNetwork', 'rebuild', 'deleteWithCleanUp', 'imageSnapshot', 'catalog_item_id', - 'iofog_uuid', - 'iofogUuid', - 'catalogItemId' + 'iofog_uuid' ]}}, {transaction: transaction}) } diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 1e07b56e3..409987259 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -143,6 +143,17 @@ const _createRoutes = async function (routes, microserviceUuid, user, transactio const _updateMicroservice = async function (microserviceUuid, microserviceData, user, isCLI, transaction) { await Validation.validate(microserviceData, Validation.schemas.microserviceUpdate); + const query = isCLI + ? + { + uuid: microserviceUuid + } + : + { + uuid: microserviceUuid, + userId: user.id + }; + const microserviceToUpdate = { name: microserviceData.name, config: microserviceData.config, @@ -150,19 +161,16 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, iofogUuid: microserviceData.iofogUuid, rootHostAccess: microserviceData.rootHostAccess, logSize: microserviceData.logLimit, - volumeMappings: microserviceData.volumeMappings, - userId: user.id + volumeMappings: microserviceData.volumeMappings }; const microserviceDataUpdate = AppHelper.deleteUndefinedFields(microserviceToUpdate); - const microservice = await MicroserviceManager.findOne({ - uuid: microserviceUuid, - userId: user.id - }, transaction); + const microservice = await MicroserviceManager.findOne(query, transaction); if (microserviceDataUpdate.name) { - await _checkForDuplicateName(microserviceDataUpdate.name, {id: microserviceUuid}, user.id, transaction); + const userId = isCLI ? microservice.userId : user.id; + await _checkForDuplicateName(microserviceDataUpdate.name, {id: microserviceUuid}, userId, transaction); } //validate fog node @@ -170,9 +178,7 @@ const _updateMicroservice = async function (microserviceUuid, microserviceData, await IoFogService.getFog({uuid: microserviceDataUpdate.iofogUuid}, user, isCLI, transaction); } - await MicroserviceManager.update({ - uuid: microserviceUuid - }, microserviceDataUpdate, transaction); + await MicroserviceManager.update(query, microserviceDataUpdate, transaction); if (microserviceDataUpdate.volumeMappings) { await _updateVolumeMappings(microserviceDataUpdate.volumeMappings, microserviceUuid, transaction); From 6c228617b6c2c5285377e91c2cb602760d8094f5 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Mon, 19 Nov 2018 17:52:10 +0300 Subject: [PATCH 82/91] Update .gitignore --- .gitignore | 1 - 1 file changed, 1 deletion(-) diff --git a/.gitignore b/.gitignore index 270dbc0fe..f3913bba7 100644 --- a/.gitignore +++ b/.gitignore @@ -1,4 +1,3 @@ node_modules .vscode *.sqlite -src/config From 96b45b050307883db62c2ffcf341913f7a523d4f Mon Sep 17 00:00:00 2001 From: dbusel Date: Mon, 19 Nov 2018 14:55:23 +0000 Subject: [PATCH 83/91] chore: dev version 1.0.15 --- package-lock.json | 2 +- package.json | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/package-lock.json b/package-lock.json index 3106acebb..6a29bf2c6 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.14", + "version": "1.0.15", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 29f535fe2..9ae31a2b2 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.14", + "version": "1.0.15", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", From 47f427b0c12eac66315469a4fa2ee0e4beb56347 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Mon, 19 Nov 2018 19:24:17 +0300 Subject: [PATCH 84/91] EWC-352 self signed cert fixes: (#369) * correct cert reading from file in routes * correct options for connector's calls with selfi signed cert --- src/services/connector-service.js | 9 ++++----- src/services/microservices-service.js | 4 ++-- 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/src/services/connector-service.js b/src/services/connector-service.js index 0bfd157bf..b0e19853b 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -125,11 +125,6 @@ async function _makeRequest(connector, options, data) { }); }); - if (connector.cert && connector.isSelfSignedCert === true) { - const ca = fs.readFileSync(connector.cert); - options.ca = new Buffer(ca); - } - httpreq.on('error', function (err) { console.log(err); if (err instanceof Error) @@ -165,6 +160,10 @@ async function openPortsOnConnector(connector, isPublicAccess, transaction) { 'Content-Length': Buffer.byteLength(data) } }; + if (connector.cert && connector.isSelfSignedCert === true) { + const ca = fs.readFileSync(connector.cert); + options.ca = new Buffer(ca); + } const ports = await _makeRequest(connector, options, data); return ports diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 409987259..a1cfdf127 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -398,7 +398,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u const sourceNetwMsConfig = { 'mode': 'private', 'host': connector.domain, - 'cert': connector.cert, + 'cert': AppHelper.trimCertificate(fs.readFileSync(connector.cert, "utf-8")), 'port': ports.port1, 'passcode': ports.passcode1, 'connectioncount': 1, @@ -420,7 +420,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u const destNetwMsConfig = { 'mode': 'private', 'host': connector.domain, - 'cert': connector.cert, + 'cert': AppHelper.trimCertificate(fs.readFileSync(connector.cert, "utf-8")), 'port': ports.port2, 'passcode': ports.passcode2, 'connectioncount': 1, From 35efcdc3d44a6c1e63608fbec5129808560447d5 Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Tue, 20 Nov 2018 12:06:42 +0300 Subject: [PATCH 85/91] EWC-353 renaming in microservice cli help: (#370) log-limit -> log-size --- src/cli/microservice.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 2c9d3c91d..33b982fab 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -112,7 +112,7 @@ class Microservice extends BaseCLIHandler { group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { - name: 'log-limit', alias: 'l', type: Number, description: 'Log file size limit (MB)', + name: 'log-size', alias: 'l', type: Number, description: 'Log file size limit (MB)', group: [constants.CMD_UPDATE, constants.CMD_ADD] }, { From 0e4762d8ff0e19d7169befb98057f322fc08f90f Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Tue, 20 Nov 2018 19:10:18 +0300 Subject: [PATCH 86/91] restoring old db on update controller (#371) --- scripts/postinstall.sh | 19 +++++++++++++++++++ scripts/preinstall.sh | 17 ++++++++++++++++- 2 files changed, 35 insertions(+), 1 deletion(-) diff --git a/scripts/postinstall.sh b/scripts/postinstall.sh index 93412a368..1b43ac973 100644 --- a/scripts/postinstall.sh +++ b/scripts/postinstall.sh @@ -35,6 +35,25 @@ vercomp () { return } +#START +#restore db +IOFOG_CONTROLLER_BIN_DIR=$(whereis iofog-controller | awk -F " " '{print $2}') +IOFOG_CONTROLLER_BIN_DIR=${IOFOG_CONTROLLER_BIN_DIR%"iofog-controller"} +IOFOG_CONTROLLER_SEQUELIZE_DIR=$IOFOG_CONTROLLER_BIN_DIR'../lib/node_modules/iofogcontroller/src/sequelize' + +DEV_DB_FILE=$IOFOG_CONTROLLER_SEQUELIZE_DIR'/dev_database.sqlite' +DEV_DB_FILE_BACKUP='/tmp/dev_database.sqlite' +if [ -f $DEV_DB_FILE_BACKUP ]; then + mv $DEV_DB_FILE_BACKUP $DEV_DB_FILE +fi + +PROD_DB_FILE=$IOFOG_CONTROLLER_SEQUELIZE_DIR'/prod_database.sqlite' +PROD_DB_FILE_BACKUP='/tmp/prod_database.sqlite' +if [ -f $PROD_DB_FILE_BACKUP ]; then + mv $PROD_DB_FILE_BACKUP $PROD_DB_FILE +fi + +#prev versions migrations PREV_IOFOG_CONTROLLER_VER=$(grep prev_ver /tmp/iofogcontroller_install_variables | awk '{print $2}') echo "Prev ver: "${PREV_IOFOG_CONTROLLER_VER} diff --git a/scripts/preinstall.sh b/scripts/preinstall.sh index 412b9e280..a08aff9c5 100644 --- a/scripts/preinstall.sh +++ b/scripts/preinstall.sh @@ -1,4 +1,19 @@ #!/bin/bash +#store prev ver number export PREV_IOFOG_CONTROLLER_VER=$(npm list --depth=0 -g --silent | grep iofogcontroller | awk -F "@" '{print $2}') -printf 'prev_ver: '$PREV_IOFOG_CONTROLLER_VER > /tmp/iofogcontroller_install_variables \ No newline at end of file +printf 'prev_ver: '$PREV_IOFOG_CONTROLLER_VER > /tmp/iofogcontroller_install_variables + +#backup db +IOFOG_CONTROLLER_BIN_DIR=$(whereis iofog-controller | awk -F " " '{print $2}') +IOFOG_CONTROLLER_BIN_DIR=${IOFOG_CONTROLLER_BIN_DIR%"iofog-controller"} +IOFOG_CONTROLLER_SEQUELIZE_DIR=$IOFOG_CONTROLLER_BIN_DIR'../lib/node_modules/iofogcontroller/src/sequelize' + +DEV_DB_FILE=$IOFOG_CONTROLLER_SEQUELIZE_DIR'/dev_database.sqlite' +if [ -f $DEV_DB_FILE ]; then + mv $DEV_DB_FILE /tmp/ +fi +PROD_DB_FILE=$IOFOG_CONTROLLER_SEQUELIZE_DIR'/prod_database.sqlite' +if [ -f $PROD_DB_FILE ]; then + mv $PROD_DB_FILE /tmp/ +fi \ No newline at end of file From e92cab52825bdb878facfcfe6298cabe31739164 Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 21 Nov 2018 12:58:50 +0300 Subject: [PATCH 87/91] remove auto version increment --- .travis.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index b638f6270..5a06b4b4a 100644 --- a/.travis.yml +++ b/.travis.yml @@ -30,8 +30,8 @@ jobs: script: - sshpass -p $DEV_MACHINE_PASSWORD ssh -o StrictHostKeyChecking=no $DEV_MACHINE_USERNAME@$DEV_MACHINE_IP "cd /FogController; NODE_ENV=production node src/main.js stop; git pull; npm i; NODE_ENV=production node src/main.js start" - stage: package_build - before_script: chmod +x .travis/pu.sh - script: .travis/pu.sh + #before_script: chmod +x .travis/pu.sh + #script: .travis/pu.sh deploy: skip_cleanup: true provider: npm From ed87d6d11238edfe2ac29a5e94ded8e8f93eb1cb Mon Sep 17 00:00:00 2001 From: epankou <35571073+epankou@users.noreply.github.com> Date: Wed, 21 Nov 2018 13:37:26 +0300 Subject: [PATCH 88/91] Epankou/bug catalog item images cli (#372) * volume mapping & delete with clean up * volume mapping & delete with clean up * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * Merge branch 'develop' of https://github.com/ioFog/FogController into epankou/feature-volume-mapping-endpoint-EWC-332 # Conflicts: # src/cli/microservice.js # src/controllers/microservices-controller.js # src/services/microservices-service.js * connector non dev mode fix EWC-339 * microservice removal cli bug fix * catalog item creation fix --- src/cli/catalog.js | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/src/cli/catalog.js b/src/cli/catalog.js index af296d266..9131cf433 100644 --- a/src/cli/catalog.js +++ b/src/cli/catalog.js @@ -262,11 +262,8 @@ const _createCatalogItemObject = function (catalogItem) { ramRequired: catalogItem.ramRequired, picture: catalogItem.picture, isPublic: AppHelper.validateBooleanCliOptions(catalogItem.public, catalogItem.private), - registryId: catalogItem.registryId - }; - - if (catalogItem.images) { - catalogItemObj.images = [ + registryId: catalogItem.registryId, + images: [ { containerImage: catalogItem.x86Image, fogTypeId: 1 @@ -275,8 +272,8 @@ const _createCatalogItemObject = function (catalogItem) { containerImage: catalogItem.armImage, fogTypeId: 2 } - ]; - } + ] + }; if (catalogItem.inputType) { catalogItemObj.inputType = { From 9bd1c25834834f04d0d90efe1f78b37001206b9c Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 21 Nov 2018 13:45:58 +0300 Subject: [PATCH 89/91] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 9ae31a2b2..e7abfd628 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.15", + "version": "1.0.16", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", From 1b08382fb76ce2707fce91a3c95761a46080df7a Mon Sep 17 00:00:00 2001 From: MaksimChepelev Date: Wed, 21 Nov 2018 14:22:18 +0300 Subject: [PATCH 90/91] EWC-360 preinstall to preuninstall (#374) --- package.json | 2 +- scripts/{preinstall.sh => preuninstall.sh} | 0 2 files changed, 1 insertion(+), 1 deletion(-) rename scripts/{preinstall.sh => preuninstall.sh} (100%) diff --git a/package.json b/package.json index e7abfd628..01ed784cf 100644 --- a/package.json +++ b/package.json @@ -37,7 +37,7 @@ "start": "NODE_ENV=production node ./src/main.js start", "start-dev": "NODE_ENV=development node ./src/main.js start", "build": "export NODE_ENV=production && cd src/sequelize && ../../node_modules/.bin/sequelize db:migrate && ../../node_modules/.bin/sequelize db:seed:all", - "preinstall": "bash scripts/preinstall.sh", + "preuninstall": "bash scripts/preuninstall.sh", "postinstall": "bash scripts/postinstall.sh", "lint": "./node_modules/.bin/eslint \"**/*.js\"" }, diff --git a/scripts/preinstall.sh b/scripts/preuninstall.sh similarity index 100% rename from scripts/preinstall.sh rename to scripts/preuninstall.sh From 1d49b5f082d526a8d7660e771619da2b2ac9beda Mon Sep 17 00:00:00 2001 From: dbusel <10116634+dbusel@users.noreply.github.com> Date: Wed, 21 Nov 2018 14:23:10 +0300 Subject: [PATCH 91/91] Update package.json --- package.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/package.json b/package.json index 01ed784cf..13affa3bb 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.16", + "version": "1.0.17", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi",