From 1df4d448356f50050629a0fcc20ac679d691f0a3 Mon Sep 17 00:00:00 2001 From: Railag Date: Thu, 3 Jan 2019 14:56:51 +0300 Subject: [PATCH] test(core) unit tests for microservices service (EWC-383) --- src/cli/microservice.js | 2 +- src/controllers/microservices-controller.js | 2 +- src/services/microservices-service.js | 837 +++++------ .../microservices-controller.test.js | 10 +- .../services/microservices-service.test.js | 1334 +++++++++++++++++ 5 files changed, 1761 insertions(+), 424 deletions(-) create mode 100644 test/src/services/microservices-service.test.js diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 687c0fe52..812e63474 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -421,7 +421,7 @@ const _createMicroservice = async function (obj, user) { logger.info(JSON.stringify(microservice)); - const result = await MicroserviceService.createMicroserviceOnFog(microservice, user, true); + const result = await MicroserviceService.createMicroservice(microservice, user, true); logger.info(JSON.stringify(result)); logger.info('Microservice has been created successfully.'); }; diff --git a/src/controllers/microservices-controller.js b/src/controllers/microservices-controller.js index e5501be60..6426854b3 100644 --- a/src/controllers/microservices-controller.js +++ b/src/controllers/microservices-controller.js @@ -20,7 +20,7 @@ const createMicroserviceOnFogEndPoint = async function (req, user) { logger.info("Parameters:" + JSON.stringify(microservice)); - return await MicroservicesService.createMicroserviceOnFog(microservice, user, false) + return await MicroservicesService.createMicroservice(microservice, user, false) }; const getMicroserviceEndPoint = async function (req, user) { diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index 0ed9a1e97..067aff2af 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -11,7 +11,7 @@ * */ -const logger = require('../logger') +const logger = require('../logger'); const TransactionDecorator = require('../decorators/transaction-decorator'); const MicroserviceManager = require('../sequelize/managers/microservice-manager'); const MicroserviceStatusManager = require('../sequelize/managers/microservice-status-manager'); @@ -27,7 +27,7 @@ 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 Validator = require('../schemas/index'); const FlowService = require('../services/flow-service'); const CatalogService = require('../services/catalog-service'); const RoutingManager = require('../sequelize/managers/routing-manager'); @@ -35,7 +35,7 @@ const Op = require('sequelize').Op; const fs = require('fs'); const _ = require('underscore'); -async function _listMicroservices(flowId, user, isCLI, transaction) { +async function listMicroservices(flowId, user, isCLI, transaction) { if (!isCLI) { await FlowService.getFlow(flowId, user, isCLI, transaction); } @@ -47,7 +47,7 @@ async function _listMicroservices(flowId, user, isCLI, transaction) { } } -async function _getMicroservice(microserviceUuid, user, isCLI, transaction) { +async function getMicroservice(microserviceUuid, user, isCLI, transaction) { if (!isCLI) { await _validateMicroserviceOnGet(user.id, microserviceUuid, transaction); } @@ -62,14 +62,14 @@ async function _getMicroservice(microserviceUuid, user, isCLI, transaction) { return microservice; } -async function _createMicroserviceOnFog(microserviceData, user, isCLI, transaction) { - await Validation.validate(microserviceData, Validation.schemas.microserviceCreate); +async function createMicroservice(microserviceData, user, isCLI, transaction) { + await Validator.validate(microserviceData, Validator.schemas.microserviceCreate); const microservice = await _createMicroservice(microserviceData, user, isCLI, transaction); if (microserviceData.ports) { for (const port of microserviceData.ports) { - await _createPortMapping(microservice.uuid, port, user, isCLI, transaction); + await createPortMapping(microservice.uuid, port, user, isCLI, transaction); } } if (microserviceData.volumeMappings) { @@ -91,59 +91,8 @@ async function _createMicroserviceOnFog(microserviceData, user, isCLI, transacti } } -async function _createMicroservice(microserviceData, user, isCLI, transaction) { - - let newMicroservice = { - uuid: AppHelper.generateRandomString(32), - name: microserviceData.name, - config: microserviceData.config, - catalogItemId: microserviceData.catalogItemId, - flowId: microserviceData.flowId, - iofogUuid: microserviceData.iofogUuid, - rootHostAccess: microserviceData.rootHostAccess, - logSize: microserviceData.logLimit, - userId: user.id - }; - - newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); - - await _checkForDuplicateName(newMicroservice.name, {}, user.id, transaction); - - //validate catalog item - await CatalogService.getCatalogItem(newMicroservice.catalogItemId, user, isCLI, transaction); - //validate flow - await FlowService.getFlow(newMicroservice.flowId, user, isCLI, transaction); - //validate fog node - if (newMicroservice.iofogUuid) { - await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); - } - - return await MicroserviceManager.create(newMicroservice, transaction); -} - -async function _createMicroserviceStatus(uuid, transaction) { - return await MicroserviceStatusManager.create({ - microserviceUuid: uuid - }, transaction); -} - -async function _createVolumeMappings(volumeMappings, microserviceUuid, transaction) { - - for (let volumeMapping of volumeMappings) { - volumeMapping.microserviceUuid = microserviceUuid - } - - await VolumeMappingManager.bulkCreate(volumeMappings, transaction) -} - -async function _createRoutes(routes, microserviceUuid, user, transaction) { - for (let route of routes) { - await _createRoute(microserviceUuid, route, user, false, transaction) - } -} - -async function _updateMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { - await Validation.validate(microserviceData, Validation.schemas.microserviceUpdate); +async function updateMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { + await Validator.validate(microserviceData, Validator.schemas.microserviceUpdate); const query = isCLI ? @@ -192,8 +141,8 @@ async function _updateMicroservice(microserviceUuid, microserviceData, user, isC if (microserviceDataUpdate.iofogUuid && 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); + 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); @@ -206,27 +155,10 @@ async function _updateMicroservice(microserviceUuid, microserviceData, user, isC } //update change tracking for new fog - await _updateChangeTracking(microserviceData.config ? true : false, microserviceDataUpdate.iofogUuid, transaction); -} - -async function _updateVolumeMappings(volumeMappings, microserviceUuid, transaction) { - for (let volumeMapping of volumeMappings) { - await VolumeMappingManager.update({ - microserviceUuid: microserviceUuid - }, volumeMapping, transaction); - } -}; - -async function _updateChangeTracking(configUpdated, fogNodeUuid, transaction) { - if (configUpdated) { - await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceCommon, transaction); - } else { - await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceList, transaction); - } + await _updateChangeTracking(!!microserviceData.config, microserviceDataUpdate.iofogUuid, transaction); } -async function _deleteMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { - +async function deleteMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction) { const where = isCLI ? { @@ -238,7 +170,6 @@ async function _deleteMicroservice(microserviceUuid, microserviceData, user, isC userId: user.id }; - const microservice = await MicroserviceManager.findOneWithStatus(where, transaction); if (!microservice) { throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, microserviceUuid)); @@ -261,21 +192,7 @@ async function _deleteMicroservice(microserviceUuid, microserviceData, user, isC await _updateChangeTracking(false, microservice.iofogUuid, transaction) } -async function _deletePortMappings(microservice, user, transaction) { - const msPortMappings = await MicroservicePortManager.findAll({ - microserviceUuid: microservice.uuid - }, transaction); - - for (const msPorts of msPortMappings) { - if (msPorts.isPublic) { - await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) - } else { - await _deleteSimplePortMapping(microservice, msPorts, user, transaction) - } - } -} - -async function _deleteNotRunningMicroservices(transaction) { +async function deleteNotRunningMicroservices(transaction) { const microservices = await MicroserviceManager.findAllWithStatuses(transaction); microservices .filter(microservice => microservice.delete) @@ -283,40 +200,56 @@ async function _deleteNotRunningMicroservices(transaction) { .forEach(microservice => _deleteMicroserviceWithRoutes(microservice.uuid, transaction)); } -async function _checkForDuplicateName(name, item, userId, transaction) { - if (name) { - const where = item.id - ? - { - name: name, - uuid: {[Op.ne]: item.id}, - userId: userId - } - : - { - name: name, - userId: userId - }; +async function createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { + const sourceWhere = isCLI + ? {uuid: sourceMicroserviceUuid} + : {uuid: sourceMicroserviceUuid, userId: user.id}; - const result = await MicroserviceManager.findOne(where, transaction); - if (result) { - throw new Errors.DuplicatePropertyError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, name)); - } + const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction); + if (!sourceMicroservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, sourceMicroserviceUuid)) } -} -async function _validateMicroserviceOnGet(userId, microserviceUuid, transaction) { - const where = { - '$flow.user.id$': userId, - uuid: microserviceUuid - }; - const microservice = await MicroserviceManager.findMicroserviceOnGet(where, transaction); - if (!microservice) { - throw new Errors.NotFoundError(ErrorMessages.INVALID_MICROSERVICE_USER); + const destWhere = isCLI + ? {uuid: destMicroserviceUuid} + : {uuid: destMicroserviceUuid, userId: user.id}; + + const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction); + if (!destMicroservice) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, destMicroserviceUuid)) } + + if (!sourceMicroservice.iofogUuid || !destMicroservice.iofogUuid) { + throw new Errors.ValidationError('fog not set') + } + if (sourceMicroservice.flowId !== destMicroservice.flowId) { + throw new Errors.ValidationError('microservices on different flows') + } + + const route = await RoutingManager.findOne({ + sourceMicroserviceUuid: sourceMicroserviceUuid, + destMicroserviceUuid: destMicroserviceUuid + }, transaction); + if (route) { + throw new Errors.ValidationError('route already exists') + } + + if (sourceMicroservice.iofogUuid === destMicroservice.iofogUuid) { + await _createSimpleRoute(sourceMicroservice, destMicroservice, transaction) + } else { + await _createRouteOverConnector(sourceMicroservice, destMicroservice, user, transaction) + } +} + +async function updateRouteOverConnector(connector, transaction) { + const routes = await RoutingManager.findAllRoutesByConnectorId(connector.id, transaction); + const networkMicroserviceUuids = _.flatten(_.map( + routes, route => [route.sourceNetworkMicroserviceUuid, route.destNetworkMicroserviceUuid] + )); + await _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction); } -async function _createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { +async function deleteRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, isCLI, transaction) { const sourceWhere = isCLI ? {uuid: sourceMicroserviceUuid} : {uuid: sourceMicroserviceUuid, userId: user.id}; @@ -335,25 +268,312 @@ async function _createRoute(sourceMicroserviceUuid, destMicroserviceUuid, user, throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, destMicroserviceUuid)) } - if (!sourceMicroservice.iofogUuid || !destMicroservice.iofogUuid) { - throw new Errors.ValidationError('fog not set') + const route = await RoutingManager.findOne({ + sourceMicroserviceUuid: sourceMicroserviceUuid, + destMicroserviceUuid: destMicroserviceUuid + }, transaction); + if (!route) { + throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.ROUTE_NOT_FOUND)) } - if (sourceMicroservice.flowId !== destMicroservice.flowId) { - throw new Errors.ValidationError('microservices on different flows') + + if (route.isNetworkConnection) { + await _deleteRouteOverConnector(route, transaction) + } else { + await _deleteSimpleRoute(route, transaction) } +} + +async function createPortMapping(microserviceUuid, portMappingData, user, isCLI, transaction) { + await Validator.validate(portMappingData, Validator.schemas.portsCreate); + await _validatePorts(portMappingData.internal, portMappingData.external); + + 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)) + } + + if (!microservice.iofogUuid) { + throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.REQUIRED_FOG_NODE)); + } + + const msPorts = await MicroservicePortManager.findOne({ + microserviceUuid: microserviceUuid, + [Op.or]: + [ + { + portInternal: portMappingData.internal + }, + { + portExternal: portMappingData.external + } + ] + }, transaction); + if (msPorts) { + throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_ALREADY_EXISTS); + } + + if (portMappingData.publicMode) { + return await _createPortMappingOverConnector(microservice, portMappingData, user, transaction) + } else { + return await _createSimplePortMapping(microservice, portMappingData, user, transaction) + } +} + +async function updatePortMappingOverConnector(connector, transaction) { + const microservicePublicModes = await MicroservicePublicModeManager.findAllMicroservicePublicModesByConnectorId(connector.id, transaction); + const networkMicroserviceUuids = microservicePublicModes.map(obj => obj.networkMicroserviceUuid); + await _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction); +} + +async function deletePortMapping(microserviceUuid, internalPort, 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 msPorts = await MicroservicePortManager.findOne({ + microserviceUuid: microserviceUuid, + portInternal: internalPort + }, transaction) + if (!msPorts) { + throw new Errors.NotFoundError('port mapping not exists') + } + + if (msPorts.isPublic) { + await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) + } else { + await _deleteSimplePortMapping(microservice, msPorts, user, transaction) + } +} + +async function listPortMappings(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 portsPairs = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction) + return await _buildPortsList(portsPairs, transaction) +} + +async function getPhysicalConnections(microservice, transaction) { + let res = []; + const pubModes = await MicroservicePublicModeManager.findAll({microserviceUuid: microservice.uuid}, transaction) + for (const pm of pubModes) { + res.push(pm.networkMicroserviceUuid) + } + + const sourceRoutes = await RoutingManager.findAll({sourceMicroserviceUuid: microservice.uuid}, transaction) + for (const sr of sourceRoutes) { + if (!sr.sourceIofogUuid || !sr.destIofogUuid) { + continue; + } else if (sr.sourceIofogUuid === sr.destIofogUuid) { + res.push(sr.destMicroserviceUuid) + } else if (sr.sourceIofogUuid !== sr.destIofogUuid) { + res.push(sr.sourceNetworkMicroserviceUuid) + } + } + + const netwRoutes = await RoutingManager.findAll({destNetworkMicroserviceUuid: microservice.uuid}, transaction) + for (const nr of netwRoutes) { + res.push(nr.destMicroserviceUuid) + } + + return res +} + +async function createVolumeMapping(microserviceUuid, volumeMappingData, user, isCLI, transaction) { + await Validator.validate(volumeMappingData, Validator.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); +} + +async function _createMicroservice(microserviceData, user, isCLI, transaction) { + + let newMicroservice = { + uuid: AppHelper.generateRandomString(32), + name: microserviceData.name, + config: microserviceData.config, + catalogItemId: microserviceData.catalogItemId, + flowId: microserviceData.flowId, + iofogUuid: microserviceData.iofogUuid, + rootHostAccess: microserviceData.rootHostAccess, + logSize: microserviceData.logLimit, + userId: user.id + }; + + newMicroservice = AppHelper.deleteUndefinedFields(newMicroservice); + + await _checkForDuplicateName(newMicroservice.name, {}, user.id, transaction); + + //validate catalog item + await CatalogService.getCatalogItem(newMicroservice.catalogItemId, user, isCLI, transaction); + //validate flow + await FlowService.getFlow(newMicroservice.flowId, user, isCLI, transaction); + //validate fog node + if (newMicroservice.iofogUuid) { + await IoFogService.getFog({uuid: newMicroservice.iofogUuid}, user, isCLI, transaction); + } + + return await MicroserviceManager.create(newMicroservice, transaction); +} + +async function _createMicroserviceStatus(uuid, transaction) { + return await MicroserviceStatusManager.create({ + microserviceUuid: uuid + }, transaction); +} + +async function _createVolumeMappings(volumeMappings, microserviceUuid, transaction) { + + const mappings = []; + for (const volumeMapping of volumeMappings) { + const mapping = Object.assign({}, volumeMapping); + mapping.microserviceUuid = microserviceUuid; + mappings.push(mapping); + } + + await VolumeMappingManager.bulkCreate(mappings, transaction) +} + +async function _createRoutes(routes, microserviceUuid, user, transaction) { + for (const route of routes) { + await createRoute(microserviceUuid, route, user, false, transaction) + } +} + +async function _updateVolumeMappings(volumeMappings, microserviceUuid, transaction) { + for (let volumeMapping of volumeMappings) { + await VolumeMappingManager.update({ + microserviceUuid: microserviceUuid + }, volumeMapping, transaction); + } +} + +async function _updateChangeTracking(configUpdated, fogNodeUuid, transaction) { + if (configUpdated) { + await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceCommon, transaction); + } else { + await ChangeTrackingService.update(fogNodeUuid, ChangeTrackingService.events.microserviceList, transaction); + } +} + +async function _deletePortMappings(microservice, user, transaction) { + const msPortMappings = await MicroservicePortManager.findAll({ + microserviceUuid: microservice.uuid + }, transaction); + + for (const msPorts of msPortMappings) { + if (msPorts.isPublic) { + await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) + } else { + await _deleteSimplePortMapping(microservice, msPorts, user, transaction) + } + } +} + +async function _checkForDuplicateName(name, item, userId, transaction) { + if (name) { + const where = item.id + ? + { + name: name, + uuid: {[Op.ne]: item.id}, + userId: userId + } + : + { + name: name, + userId: userId + }; - const route = await RoutingManager.findOne({ - sourceMicroserviceUuid: sourceMicroserviceUuid, - destMicroserviceUuid: destMicroserviceUuid - }, transaction) - if (route) { - throw new Errors.ValidationError('route already exists') + const result = await MicroserviceManager.findOne(where, transaction); + if (result) { + throw new Errors.DuplicatePropertyError(AppHelper.formatMessage(ErrorMessages.DUPLICATE_NAME, name)); + } } +} - if (sourceMicroservice.iofogUuid === destMicroservice.iofogUuid) { - await _createSimpleRoute(sourceMicroservice, destMicroservice, transaction) - } else { - await _createRouteOverConnector(sourceMicroservice, destMicroservice, user, transaction) +async function _validateMicroserviceOnGet(userId, microserviceUuid, transaction) { + const where = { + '$flow.user.id$': userId, + uuid: microserviceUuid + }; + const microservice = await MicroserviceManager.findMicroserviceOnGet(where, transaction); + if (!microservice) { + throw new Errors.NotFoundError(ErrorMessages.INVALID_MICROSERVICE_USER); } } @@ -374,19 +594,12 @@ async function _createSimpleRoute(sourceMicroservice, destMicroservice, transact destMicroserviceUuid: destMicroservice.uuid, sourceIofogUuid: sourceMicroservice.iofogUuid, destIofogUuid: destMicroservice.iofogUuid //same as sourceIofogUuid - } + }; - await RoutingManager.create(routeData, transaction) + await RoutingManager.create(routeData, transaction); await _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) } -async function updateRouteOverConnector(connector, transaction) { - const routes = await RoutingManager.findAllRoutesByConnectorId(connector.id, transaction); - const networkMicroserviceUuids = _.flatten(_.map( - routes, route => [route.sourceNetworkMicroserviceUuid, route.destNetworkMicroserviceUuid] - )); - await _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction); -} async function _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction) { const microservices = await MicroserviceManager.findAll({uuid: networkMicroserviceUuids}, transaction); @@ -423,7 +636,7 @@ async function _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, conne async function _createRouteOverConnector(sourceMicroservice, destMicroservice, user, transaction) { //open connector - const justOpenedConnectorsPorts = await ConnectorPortService.openPortOnRandomConnector(false, transaction) + const justOpenedConnectorsPorts = await ConnectorPortService.openPortOnRandomConnector(false, transaction); const ports = justOpenedConnectorsPorts.ports; const connector = justOpenedConnectorsPorts.connector; @@ -462,7 +675,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u 'heartbeatfrequency': 20000, 'heartbeatabsencethreshold': 60000, 'devmode': connector.devMode - } + }; const sourceNetworkMicroservice = await _createNetworkMicroserviceForMaster( sourceMicroservice, sourceNetwMsConfig, @@ -484,7 +697,7 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u 'heartbeatfrequency': 20000, 'heartbeatabsencethreshold': 60000, 'devmode': connector.devMode - } + }; const destNetworkMicroservice = await _createNetworkMicroserviceForMaster( destMicroservice, destNetwMsConfig, @@ -503,8 +716,8 @@ async function _createRouteOverConnector(sourceMicroservice, destMicroservice, u sourceNetworkMicroserviceUuid: sourceNetworkMicroservice.uuid, destNetworkMicroserviceUuid: destNetworkMicroservice.uuid, connectorPortId: connectorPort.id - } - await RoutingManager.create(routeData, transaction) + }; + await RoutingManager.create(routeData, transaction); await _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) } @@ -530,58 +743,24 @@ async function _createNetworkMicroserviceForMaster(masterMicroservice, sourceNet async function _switchOnUpdateFlagsForMicroservicesInRoute(sourceMicroservice, destMicroservice, transaction) { const updateRebuildMs = { rebuild: true - } - await MicroserviceManager.update({uuid: sourceMicroservice.uuid}, updateRebuildMs, transaction) - await MicroserviceManager.update({uuid: destMicroservice.uuid}, updateRebuildMs, 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) { - const sourceWhere = isCLI - ? {uuid: sourceMicroserviceUuid} - : {uuid: sourceMicroserviceUuid, userId: user.id}; - - const sourceMicroservice = await MicroserviceManager.findOne(sourceWhere, transaction); - if (!sourceMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, sourceMicroserviceUuid)) - } - - const destWhere = isCLI - ? {uuid: destMicroserviceUuid} - : {uuid: destMicroserviceUuid, userId: user.id}; - - const destMicroservice = await MicroserviceManager.findOne(destWhere, transaction); - if (!destMicroservice) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.INVALID_MICROSERVICE_UUID, destMicroserviceUuid)) - } - - const route = await RoutingManager.findOne({ - sourceMicroserviceUuid: sourceMicroserviceUuid, - destMicroserviceUuid: destMicroserviceUuid - }, transaction) - if (!route) { - throw new Errors.NotFoundError(AppHelper.formatMessage(ErrorMessages.ROUTE_NOT_FOUND)) - } + }; + await MicroserviceManager.update({uuid: sourceMicroservice.uuid}, updateRebuildMs, transaction); + await MicroserviceManager.update({uuid: destMicroservice.uuid}, updateRebuildMs, transaction); - if (route.isNetworkConnection) { - await _deleteRouteOverConnector(route, transaction) - } else { - await _deleteSimpleRoute(route, transaction) - } + await ChangeTrackingService.update(sourceMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); + await ChangeTrackingService.update(destMicroservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction); } async function _deleteSimpleRoute(route, transaction) { - await RoutingManager.delete({id: route.id}, transaction) + await RoutingManager.delete({id: route.id}, transaction); - await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) - await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction) + await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction); + await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceRouting, transaction); } async function _deleteRouteOverConnector(route, transaction) { - const ports = await ConnectorPortManager.findOne({id: route.connectorPortId}, transaction) - const connector = await ConnectorManager.findOne({id: ports.connectorId}, transaction) + const ports = await ConnectorPortManager.findOne({id: route.connectorPortId}, transaction); + const connector = await ConnectorManager.findOne({id: ports.connectorId}, transaction); try { await ConnectorPortService.closePortOnConnector(connector, ports); @@ -589,53 +768,13 @@ async function _deleteRouteOverConnector(route, transaction) { logger.warn(`Can't close ports pair ${ports.mappingId} on connector ${connector.publicIp}. Delete manually if necessary`); } - await RoutingManager.delete({id: route.id}, transaction) - await ConnectorPortManager.delete({id: ports.id}, transaction) - await MicroserviceManager.delete({uuid: route.sourceNetworkMicroserviceUuid}, transaction) - await MicroserviceManager.delete({uuid: route.destNetworkMicroserviceUuid}, 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) { - await Validation.validate(portMappingData, Validation.schemas.portsCreate); - await _validatePorts(portMappingData.internal, portMappingData.external) - - 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)) - } - - if (!microservice.iofogUuid) { - throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.REQUIRED_FOG_NODE)); - } - - const msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microserviceUuid, - [Op.or]: - [ - { - portInternal: portMappingData.internal - }, - { - portExternal: portMappingData.external - } - ] - }, transaction); - if (msPorts) { - throw new Errors.ValidationError(ErrorMessages.PORT_MAPPING_ALREADY_EXISTS); - } + await RoutingManager.delete({id: route.id}, transaction); + await ConnectorPortManager.delete({id: ports.id}, transaction); + await MicroserviceManager.delete({uuid: route.sourceNetworkMicroserviceUuid}, transaction); + await MicroserviceManager.delete({uuid: route.destNetworkMicroserviceUuid}, transaction); - if (portMappingData.publicMode) { - return await _createPortMappingOverConnector(microservice, portMappingData, user, transaction) - } else { - return await _createSimplePortMapping(microservice, portMappingData, user, transaction) - } + await ChangeTrackingService.update(route.sourceIofogUuid, ChangeTrackingService.events.microserviceFull, transaction); + await ChangeTrackingService.update(route.destIofogUuid, ChangeTrackingService.events.microserviceFull, transaction); } async function _createSimplePortMapping(microservice, portMappingData, user, transaction) { @@ -646,24 +785,19 @@ async function _createSimplePortMapping(microservice, portMappingData, user, tra portExternal: portMappingData.external, userId: microservice.userId, microserviceUuid: microservice.uuid - } + }; - await MicroservicePortManager.create(mappingData, transaction) + await MicroservicePortManager.create(mappingData, transaction); await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, false, transaction) } -async function updatePortMappingOverConnector(connector, transaction) { - const microservicePublicModes = await MicroservicePublicModeManager.findAllMicroservicePublicModesByConnectorId(connector.id, transaction); - const networkMicroserviceUuids = microservicePublicModes.map(obj => obj.networkMicroserviceUuid); - await _updateNetworkMicroserviceConfigs(networkMicroserviceUuids, connector, transaction); -} async function _createPortMappingOverConnector(microservice, portMappingData, user, transaction) { //open connector - const justOpenedConnectorsPorts = await ConnectorPortService.openPortOnRandomConnector(true, transaction) + const justOpenedConnectorsPorts = await ConnectorPortService.openPortOnRandomConnector(true, transaction); - const ports = justOpenedConnectorsPorts.ports - const connector = justOpenedConnectorsPorts.connector + const ports = justOpenedConnectorsPorts.ports; + const connector = justOpenedConnectorsPorts.connector; const createConnectorPortData = { port1: ports.port1, @@ -677,9 +811,9 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us connectorId: ports.connectorId, mappingId: ports.id }; - const connectorPort = await ConnectorPortManager.create(createConnectorPortData, transaction) + const connectorPort = await ConnectorPortManager.create(createConnectorPortData, transaction); - const networkCatalogItem = await CatalogService.getNetworkCatalogItem(transaction) + const networkCatalogItem = await CatalogService.getNetworkCatalogItem(transaction); let cert; if (!connector.devMode && connector.cert) { @@ -698,7 +832,7 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us 'heartbeatfrequency': 20000, 'heartbeatabsencethreshold': 60000, 'devmode': connector.devMode - } + }; const networkMicroservice = await _createNetworkMicroserviceForMaster( microservice, netwMsConfig, @@ -714,9 +848,9 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us portExternal: portMappingData.external, userId: microservice.userId, microserviceUuid: microservice.uuid - } + }; - const msPortMapping = await MicroservicePortManager.create(mappingData, transaction) + const msPortMapping = await MicroservicePortManager.create(mappingData, transaction); const msPubModeData = { microserviceUuid: microservice.uuid, @@ -724,11 +858,11 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us iofogUuid: microservice.iofogUuid, microservicePortId: msPortMapping.id, connectorPortId: connectorPort.id - } - await MicroservicePublicModeManager.create(msPubModeData, transaction) + }; + await MicroservicePublicModeManager.create(msPubModeData, transaction); - await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, true, transaction) + await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, true, transaction); const publicLink = await _buildLink(connector.devMode ? 'http' : 'https', connector.publicIp, connectorPort.port2) return {publicLink: publicLink} } @@ -736,10 +870,9 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us async function _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, isPublic, transaction) { const updateRebuildMs = { rebuild: true - } - await MicroserviceManager.update({uuid: microservice.uuid}, updateRebuildMs, transaction) + }; + await MicroserviceManager.update({uuid: microservice.uuid}, updateRebuildMs, transaction); - let updateChangeTrackingData = {} if (isPublic) { await ChangeTrackingService.update(microservice.iofogUuid, ChangeTrackingService.events.microserviceFull, transaction) } else { @@ -747,30 +880,6 @@ async function _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, } } -async function _deletePortMapping(microserviceUuid, internalPort, 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 msPorts = await MicroservicePortManager.findOne({ - microserviceUuid: microserviceUuid, - portInternal: internalPort - }, transaction) - if (!msPorts) { - throw new Errors.NotFoundError('port mapping not exists') - } - - if (msPorts.isPublic) { - await _deletePortMappingOverConnector(microservice, msPorts, user, transaction) - } else { - await _deleteSimplePortMapping(microservice, msPorts, user, transaction) - } -} async function _deleteSimplePortMapping(microservice, msPorts, user, transaction) { await MicroservicePortManager.delete({id: msPorts.id}, transaction); @@ -812,22 +921,22 @@ async function _validatePorts(internal, external) { //TODO find this ports in project. check is possible to delete some of them || external === 60400 || external === 60401 || external === 10500 || external === 54321 || external === 55555) { - throw new Errors.ValidationError('incorrect port') + throw new Errors.ValidationError('Incorrect port') } } async function _buildPortsList(portsPairs, transaction) { - const res = [] + const res = []; for (const ports of portsPairs) { let portMappingResposeData = { internal: ports.portInternal, external: ports.portExternal, publicMode: ports.isPublic - } + }; if (ports.isPublic) { - const pubMode = await MicroservicePublicModeManager.findOne({microservicePortId: ports.id}, transaction) - const connectorPorts = await ConnectorPortManager.findOne({id: pubMode.connectorPortId}, transaction) - const connector = await ConnectorManager.findOne({id: connectorPorts.connectorId}, transaction) + const pubMode = await MicroservicePublicModeManager.findOne({microservicePortId: ports.id}, transaction); + const connectorPorts = await ConnectorPortManager.findOne({id: pubMode.connectorPortId}, transaction); + const connector = await ConnectorManager.findOne({id: connectorPorts.connectorId}, transaction); portMappingResposeData.publicLink = await _buildLink(connector.devMode ? 'http' : 'https', connector.publicIp, connectorPorts.port2) } @@ -836,45 +945,6 @@ async function _buildPortsList(portsPairs, transaction) { return res } -async function _listPortMappings(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 portsPairs = await MicroservicePortManager.findAll({microserviceUuid: microserviceUuid}, transaction) - return await _buildPortsList(portsPairs, transaction) -} - -async function getPhysicalConections(microservice, transaction) { - let res = [] - const pubModes = await MicroservicePublicModeManager.findAll({microserviceUuid: microservice.uuid}, transaction) - for (const pm of pubModes) { - res.push(pm.networkMicroserviceUuid) - } - - const sourceRoutes = await RoutingManager.findAll({sourceMicroserviceUuid: microservice.uuid}, transaction) - for (const sr of sourceRoutes) { - if (!sr.sourceIofogUuid || !sr.destIofogUuid) { - continue; - } else if (sr.sourceIofogUuid === sr.destIofogUuid) { - res.push(sr.destMicroserviceUuid) - } else if (sr.sourceIofogUuid !== sr.destIofogUuid) { - res.push(sr.sourceNetworkMicroserviceUuid) - } - } - - const netwRoutes = await RoutingManager.findAll({destNetworkMicroserviceUuid: microservice.uuid}, transaction) - for (const nr of netwRoutes) { - res.push(nr.destMicroserviceUuid) - } - - return res -} - async function _getLogicalNetworkRoutesByFog(iofogUuid, transaction) { let res = []; const query = { @@ -910,7 +980,7 @@ async function _getLogicalRoutesByMicroservice(microserviceUuid, transaction) { } ] }; - const routes = await RoutingManager.findAll(query, transaction) + const routes = await RoutingManager.findAll(query, transaction); for (let route of routes) { if (route.sourceMicroserviceUuid && route.destMicroserviceUuid) { res.push(route); @@ -929,7 +999,7 @@ async function _deleteMicroserviceWithRoutes(microserviceUuid, transaction) { const user = { id: userId }; - await _deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, false, transaction); + await deleteRoute(route.sourceMicroserviceUuid, route.destMicroserviceUuid, user, false, transaction); } await MicroserviceManager.delete({ uuid: microserviceUuid @@ -940,89 +1010,22 @@ 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), - getMicroservice: TransactionDecorator.generateTransaction(_getMicroservice), - updateMicroservice: TransactionDecorator.generateTransaction(_updateMicroservice), - deleteMicroservice: TransactionDecorator.generateTransaction(_deleteMicroservice), - createRoute: TransactionDecorator.generateTransaction(_createRoute), - deleteRoute: TransactionDecorator.generateTransaction(_deleteRoute), - createPortMapping: TransactionDecorator.generateTransaction(_createPortMapping), - listMicroservicePortMappings: TransactionDecorator.generateTransaction(_listPortMappings), - deletePortMapping: TransactionDecorator.generateTransaction(_deletePortMapping), - createVolumeMapping: TransactionDecorator.generateTransaction(_createVolumeMapping), - deleteVolumeMapping: TransactionDecorator.generateTransaction(_deleteVolumeMapping), - listVolumeMappings: TransactionDecorator.generateTransaction(_listVolumeMappings), - getPhysicalConnections: getPhysicalConections, - deleteNotRunningMicroservices: _deleteNotRunningMicroservices, + createMicroservice: TransactionDecorator.generateTransaction(createMicroservice), + 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), + listMicroservicePortMappings: TransactionDecorator.generateTransaction(listPortMappings), + deletePortMapping: TransactionDecorator.generateTransaction(deletePortMapping), + createVolumeMapping: TransactionDecorator.generateTransaction(createVolumeMapping), + deleteVolumeMapping: TransactionDecorator.generateTransaction(deleteVolumeMapping), + listVolumeMappings: TransactionDecorator.generateTransaction(listVolumeMappings), + getPhysicalConnections: getPhysicalConnections, + deleteNotRunningMicroservices: deleteNotRunningMicroservices, updateRouteOverConnector: updateRouteOverConnector, updatePortMappingOverConnector: updatePortMappingOverConnector }; diff --git a/test/src/controllers/microservices-controller.test.js b/test/src/controllers/microservices-controller.test.js index 3baa7d889..897400c65 100644 --- a/test/src/controllers/microservices-controller.test.js +++ b/test/src/controllers/microservices-controller.test.js @@ -55,12 +55,12 @@ describe('Microservices Controller', () => { def('subject', () => $subject.createMicroserviceOnFogEndPoint($req, $user)); beforeEach(() => { - $sandbox.stub(MicroservicesService, 'createMicroserviceOnFog').returns($response); + $sandbox.stub(MicroservicesService, 'createMicroservice').returns($response); }); - it('calls MicroservicesService.createMicroserviceOnFog with correct args', async () => { + it('calls MicroservicesService.createMicroservice with correct args', async () => { await $subject; - expect(MicroservicesService.createMicroserviceOnFog).to.have.been.calledWith({ + expect(MicroservicesService.createMicroservice).to.have.been.calledWith({ name: $name, config: $config, catalogItemId: $catalogItemId, @@ -74,7 +74,7 @@ describe('Microservices Controller', () => { }, $user, false); }); - context('when MicroservicesService#createMicroserviceOnFog fails', () => { + context('when MicroservicesService#createMicroservice fails', () => { const error = 'Error!'; def('response', () => Promise.reject(error)); @@ -84,7 +84,7 @@ describe('Microservices Controller', () => { }) }); - context('when MicroservicesService#createMicroserviceOnFog succeeds', () => { + context('when MicroservicesService#createMicroservice succeeds', () => { it(`succeeds`, () => { return expect($subject).to.eventually.equal(undefined) }) diff --git a/test/src/services/microservices-service.test.js b/test/src/services/microservices-service.test.js new file mode 100644 index 000000000..3b7941eae --- /dev/null +++ b/test/src/services/microservices-service.test.js @@ -0,0 +1,1334 @@ +const {expect} = require('chai'); +const sinon = require('sinon'); + +const MicroserviceManager = require('../../../src/sequelize/managers/microservice-manager'); +const MicroservicesService = require('../../../src/services/microservices-service'); +const AppHelper = require('../../../src/helpers/app-helper'); +const Validator = require('../../../src/schemas'); +const ChangeTrackingService = require('../../../src/services/change-tracking-service'); +const CatalogService = require('../../../src/services/catalog-service'); +const FlowService = require('../../../src/services/flow-service'); +const ioFogService = require('../../../src/services/iofog-service'); +const MicroservicePortManager = require('../../../src/sequelize/managers/microservice-port-manager'); +const VolumeMappingManager = require('../../../src/sequelize/managers/volume-mapping-manager'); +const MicroserviceStatusManager = require('../../../src/sequelize/managers/microservice-status-manager'); +const RoutingManager = require('../../../src/sequelize/managers/routing-manager'); +const Op = require('sequelize').Op; + +describe('Microservices Service', () => { + def('subject', () => MicroservicesService); + def('sandbox', () => sinon.createSandbox()); + + const isCLI = true; + + afterEach(() => $sandbox.restore()); + + describe('.listMicroservices()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const flowId = 10; + + const response = [ + { + uuid: 'testUuid' + } + ]; + + def('subject', () => $subject.listMicroservices(flowId, user, isCLI, transaction)); + def('findMicroservicesResponse', () => Promise.resolve(response)); + + beforeEach(() => { + $sandbox.stub(MicroserviceManager, 'findAllExcludeFields').returns($findMicroservicesResponse); + }); + + it('calls MicroserviceManager#findAllExcludeFields() with correct args', async () => { + await $subject; + const where = isCLI ? {delete: false} : {flowId: flowId, delete: false}; + + expect(MicroserviceManager.findAllExcludeFields).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findAllExcludeFields() fails', () => { + def('findMicroservicesResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findAllExcludeFields() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('microservices') + }) + }) + }); + + describe('.getMicroservice()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const microserviceUuid = 'testMicroserviceUuid'; + + const response = { + uuid: 'testUuid' + }; + + def('subject', () => $subject.getMicroservice(microserviceUuid, user, isCLI, transaction)); + def('findMicroserviceResponse', () => Promise.resolve(response)); + + beforeEach(() => { + $sandbox.stub(MicroserviceManager, 'findOneExcludeFields').returns($findMicroserviceResponse); + }); + + it('calls MicroserviceManager#findOneExcludeFields() with correct args', async () => { + await $subject; + expect(MicroserviceManager.findOneExcludeFields).to.have.been.calledWith({ + uuid: microserviceUuid, delete: false + }, transaction); + }); + + context('when MicroserviceManager#findOneExcludeFields() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOneExcludeFields() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('uuid') + }) + }) + }); + + describe('.createMicroservice()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const microserviceData = { + "name": "name2", + "config": "string", + "catalogItemId": 15, + "flowId": 16, + "iofogUuid": 'testIofogUuid', + "rootHostAccess": true, + "logSize": 0, + "volumeMappings": [ + { + "hostDestination": "/var/dest", + "containerDestination": "/var/dest", + "accessMode": "rw" + } + ], + "ports": [ + { + "internal": 1, + "external": 1, + "publicMode": false + } + ], + "routes": [] + }; + + const newMicroserviceUuid = 'newMicroserviceUuid'; + const newMicroservice = { + uuid: newMicroserviceUuid, + name: microserviceData.name, + config: microserviceData.config, + catalogItemId: microserviceData.catalogItemId, + flowId: microserviceData.flowId, + iofogUuid: microserviceData.iofogUuid, + rootHostAccess: microserviceData.rootHostAccess, + logSize: microserviceData.logLimit, + userId: user.id + }; + + const item = {}; + + const portMappingData = + { + "internal": 1, + "external": 1, + "publicMode": false + }; + + const mappings = []; + for (const volumeMapping of microserviceData.volumeMappings) { + const mapping = Object.assign({}, volumeMapping); + mapping.microserviceUuid = microserviceData.uuid; + mappings.push(mapping); + } + + const mappingData = { + isPublic: false, + portInternal: portMappingData.internal, + portExternal: portMappingData.external, + userId: microserviceData.userId, + microserviceUuid: microserviceData.uuid + }; + + def('subject', () => $subject.createMicroservice(microserviceData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('validatorResponse2', () => Promise.resolve(true)); + def('generateRandomStringResponse', () => newMicroserviceUuid); + def('deleteUndefinedFieldsResponse', () => newMicroservice); + def('findMicroserviceResponse', () => Promise.resolve()); + def('findMicroserviceResponse2', () => Promise.resolve(microserviceData)); + def('getCatalogItemResponse', () => Promise.resolve()); + def('getFlowResponse', () => Promise.resolve()); + def('getIoFogResponse', () => Promise.resolve()); + def('createMicroserviceResponse', () => Promise.resolve(microserviceData)); + def('findMicroservicePortResponse', () => Promise.resolve()); + def('createMicroservicePortResponse', () => Promise.resolve()); + def('updateMicroserviceResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + def('createVolumeMappingResponse', () => Promise.resolve()); + def('createMicroserviceStatusResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate') + .onFirstCall().returns($validatorResponse) + .onSecondCall().returns($validatorResponse2); + $sandbox.stub(AppHelper, 'generateRandomString').returns($generateRandomStringResponse); + $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); + $sandbox.stub(MicroserviceManager, 'findOne') + .onFirstCall().returns($findMicroserviceResponse) + .onSecondCall().returns($findMicroserviceResponse2); + $sandbox.stub(CatalogService, 'getCatalogItem').returns($getCatalogItemResponse); + $sandbox.stub(FlowService, 'getFlow').returns($getFlowResponse); + $sandbox.stub(ioFogService, 'getFog').returns($getIoFogResponse); + $sandbox.stub(MicroserviceManager, 'create').returns($createMicroserviceResponse); + $sandbox.stub(MicroservicePortManager, 'findOne').returns($findMicroservicePortResponse); + $sandbox.stub(MicroservicePortManager, 'create').returns($createMicroservicePortResponse); + $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + $sandbox.stub(VolumeMappingManager, 'bulkCreate').returns($createVolumeMappingResponse); + $sandbox.stub(MicroserviceStatusManager, 'create').returns($createMicroserviceStatusResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(microserviceData, + Validator.schemas.microserviceCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls AppHelper#generateRandomString() with correct args', async () => { + await $subject; + expect(AppHelper.generateRandomString).to.have.been.calledWith(32); + }); + + context('when AppHelper#generateRandomString() fails', () => { + def('generateRandomStringResponse', () => error); + + it(`fails with ${error}`, () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }); + + context('when AppHelper#generateRandomString() succeeds', () => { + it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { + await $subject; + expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(newMicroservice); + }); + + context('when AppHelper#deleteUndefinedFields() fails', () => { + const err = 'Invalid microservice UUID \'undefined\''; + def('deleteUndefinedFieldsResponse', () => Promise.reject(err)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(err); + }) + }); + + context('when AppHelper#deleteUndefinedFields() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + const where = item.id + ? + { + name: microserviceData.name, + uuid: {[Op.ne]: item.id}, + userId: user.id + } + : + { + name: microserviceData.name, + userId: user.id + }; + expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findOne() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls CatalogService#getCatalogItem() with correct args', async () => { + await $subject; + expect(CatalogService.getCatalogItem).to.have.been.calledWith(newMicroservice.catalogItemId, + user, isCLI, transaction); + }); + + context('when CatalogService#getCatalogItem() fails', () => { + def('getCatalogItemResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when CatalogService#getCatalogItem() succeeds', () => { + it('calls FlowService#getFlow() with correct args', async () => { + await $subject; + expect(FlowService.getFlow).to.have.been.calledWith(newMicroservice.flowId, + user, isCLI, transaction); + }); + + context('when FlowService#getFlow() fails', () => { + def('getFlowResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when FlowService#getFlow() succeeds', () => { + it('calls IoFogService#getFog() with correct args', async () => { + await $subject; + expect(ioFogService.getFog).to.have.been.calledWith({ + uuid: newMicroservice.iofogUuid + }, user, isCLI, transaction); + }); + + context('when IoFogService#getFog() fails', () => { + def('getIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when IoFogService#getFog() succeeds', () => { + it('calls MicroserviceManager#create() with correct args', async () => { + await $subject; + expect(MicroserviceManager.create).to.have.been.calledWith(newMicroservice, + transaction); + }); + + context('when MicroserviceManager#create() fails', () => { + def('getIoFogResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#create() succeeds', () => { + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse2', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + const where = isCLI + ? {uuid: microserviceData.uuid} + : {uuid: microserviceData.uuid, userId: user.id}; + expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findOne() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#findOne() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.findOne).to.have.been.calledWith({ + microserviceUuid: microserviceData.uuid, + [Op.or]: + [ + { + portInternal: portMappingData.internal + }, + { + portExternal: portMappingData.external + } + ] + }, transaction); + }); + + context('when MicroservicePortManager#findOne() fails', () => { + def('findMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#create() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); + }); + + context('when MicroservicePortManager#create() fails', () => { + def('createMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#create() succeeds', () => { + it('calls MicroserviceManager#update() with correct args', async () => { + await $subject; + const updateRebuildMs = { + rebuild: true + }; + expect(MicroserviceManager.update).to.have.been.calledWith({ + uuid: microserviceData.uuid + }, updateRebuildMs, transaction); + }); + + context('when MicroserviceManager#update() fails', () => { + def('updateMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, + ChangeTrackingService.events.microserviceConfig, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('calls VolumeMappingManager#bulkCreate() with correct args', async () => { + await $subject; + expect(VolumeMappingManager.bulkCreate).to.have.been.calledWith(mappings, + transaction); + }); + + context('when VolumeMappingManager#bulkCreate() fails', () => { + def('createVolumeMappingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when VolumeMappingManager#bulkCreate() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, + ChangeTrackingService.events.microserviceList, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('calls MicroserviceStatusManager#create() with correct args', async () => { + await $subject; + expect(MicroserviceStatusManager.create).to.have.been.calledWith({ + microserviceUuid: microserviceData.uuid + }, transaction); + }); + + context('when MicroserviceStatusManager#create() fails', () => { + def('createMicroserviceStatusResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceStatusManager#create() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).to.eventually.have.property('uuid'); + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }) + }); +// +// describe('.updateMicroservice()', () => { +// const transaction = {}; +// const error = 'Error!'; +// +// const user = { +// id: 15 +// }; +// +// const microserviceUuid = 'testMicroserviceUuid'; +// +// const query = isCLI +// ? +// { +// uuid: microserviceUuid +// } +// : +// { +// uuid: microserviceUuid, +// userId: user.id +// }; +// +// const microserviceData = { +// "name": "name2", +// "config": "string", +// "catalogItemId": 15, +// "flowId": 16, +// "iofogUuid": 'testIofogUuid', +// "rootHostAccess": true, +// "logSize": 0, +// "volumeMappings": [ +// { +// "hostDestination": "/var/dest", +// "containerDestination": "/var/dest", +// "accessMode": "rw" +// } +// ], +// "ports": [ +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// } +// ], +// "routes": [] +// }; +// +// const microserviceToUpdate = { +// name: microserviceData.name, +// config: microserviceData.config, +// rebuild: microserviceData.rebuild, +// iofogUuid: microserviceData.iofogUuid, +// rootHostAccess: microserviceData.rootHostAccess, +// logSize: microserviceData.logLimit, +// volumeMappings: microserviceData.volumeMappings +// }; +// +// const newMicroserviceUuid = 'newMicroserviceUuid'; +// const newMicroservice = { +// uuid: newMicroserviceUuid, +// name: microserviceData.name, +// config: microserviceData.config, +// catalogItemId: microserviceData.catalogItemId, +// flowId: microserviceData.flowId, +// iofogUuid: microserviceData.iofogUuid, +// rootHostAccess: microserviceData.rootHostAccess, +// logSize: microserviceData.logLimit, +// userId: user.id +// }; +// +// const item = {}; +// +// const portMappingData = +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// }; +// +// const mappings = []; +// for (const volumeMapping of microserviceData.volumeMappings) { +// const mapping = Object.assign({}, volumeMapping); +// mapping.microserviceUuid = microserviceData.uuid; +// mappings.push(mapping); +// } +// +// const mappingData = { +// isPublic: false, +// portInternal: portMappingData.internal, +// portExternal: portMappingData.external, +// userId: microserviceData.userId, +// microserviceUuid: microserviceData.uuid +// }; +// +// def('subject', () => $subject.updateMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction)); +// def('validatorResponse', () => Promise.resolve(true)); +// def('deleteUndefinedFieldsResponse', () => newMicroservice); +// def('findMicroserviceResponse', () => Promise.resolve()); +// def('findMicroserviceResponse2', () => Promise.resolve(microserviceData)); +// def('getIoFogResponse', () => Promise.resolve()); +// def('updateMicroserviceResponse', () => Promise.resolve()); +// def('updateVolumeMappingResponse', () => Promise.resolve()); +// // TODO +// +// def('updateChangeTrackingResponse', () => Promise.resolve()); +// def('updateChangeTrackingResponse2', () => Promise.resolve()); +// def('updateChangeTrackingResponse3', () => Promise.resolve()); +// +// beforeEach(() => { +// $sandbox.stub(Validator, 'validate').returns($validatorResponse); +// $sandbox.stub(AppHelper, 'deleteUndefinedFields').returns($deleteUndefinedFieldsResponse); +// $sandbox.stub(MicroserviceManager, 'findOne') +// .onFirstCall().returns($findMicroserviceResponse) +// .onSecondCall().returns($findMicroserviceResponse2); +// $sandbox.stub(ioFogService, 'getFog').returns($getIoFogResponse); +// $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); +// $sandbox.stub(VolumeMappingManager, 'update').returns($updateVolumeMappingResponse); +// $sandbox.stub(RoutingManager, 'findAll').returns($findAllRoutesResponse); +// +// // TODO +// // delete route endpoint +// // create route endpoint +// $sandbox.stub(ChangeTrackingService, 'update') +// .onFirstCall().returns($updateChangeTrackingResponse) +// .onSecondCall().returns($updateChangeTrackingResponse2) +// .onThirdCall().returns($updateChangeTrackingResponse3); +// }); +// +// it('calls Validator#validate() with correct args', async () => { +// await $subject; +// expect(Validator.validate).to.have.been.calledWith(microserviceData, +// Validator.schemas.microserviceCreate); +// }); +// +// context('when Validator#validate() fails', () => { +// def('validatorResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when Validator#validate() succeeds', () => { +// it('calls AppHelper#generateRandomString() with correct args', async () => { +// await $subject; +// expect(AppHelper.generateRandomString).to.have.been.calledWith(32); +// }); +// +// context('when AppHelper#generateRandomString() fails', () => { +// def('generateRandomStringResponse', () => error); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.eventually.have.property('uuid'); +// }) +// }); +// +// context('when AppHelper#generateRandomString() succeeds', () => { +// it('calls AppHelper#deleteUndefinedFields() with correct args', async () => { +// await $subject; +// expect(AppHelper.deleteUndefinedFields).to.have.been.calledWith(newMicroservice); +// }); +// +// context('when AppHelper#deleteUndefinedFields() fails', () => { +// const err = 'Invalid microservice UUID \'undefined\''; +// def('deleteUndefinedFieldsResponse', () => Promise.reject(err)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(err); +// }) +// }); +// +// context('when AppHelper#deleteUndefinedFields() succeeds', () => { +// it('calls MicroserviceManager#findOne() with correct args', async () => { +// await $subject; +// const where = item.id +// ? +// { +// name: microserviceData.name, +// uuid: {[Op.ne]: item.id}, +// userId: user.id +// } +// : +// { +// name: microserviceData.name, +// userId: user.id +// }; +// expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); +// }); +// +// context('when MicroserviceManager#findOne() fails', () => { +// def('findMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#findOne() succeeds', () => { +// it('calls CatalogService#getCatalogItem() with correct args', async () => { +// await $subject; +// expect(CatalogService.getCatalogItem).to.have.been.calledWith(newMicroservice.catalogItemId, +// user, isCLI, transaction); +// }); +// +// context('when CatalogService#getCatalogItem() fails', () => { +// def('getCatalogItemResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when CatalogService#getCatalogItem() succeeds', () => { +// it('calls FlowService#getFlow() with correct args', async () => { +// await $subject; +// expect(FlowService.getFlow).to.have.been.calledWith(newMicroservice.flowId, +// user, isCLI, transaction); +// }); +// +// context('when FlowService#getFlow() fails', () => { +// def('getFlowResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when FlowService#getFlow() succeeds', () => { +// it('calls IoFogService#getFog() with correct args', async () => { +// await $subject; +// expect(ioFogService.getFog).to.have.been.calledWith({ +// uuid: newMicroservice.iofogUuid +// }, user, isCLI, transaction); +// }); +// +// context('when IoFogService#getFog() fails', () => { +// def('getIoFogResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when IoFogService#getFog() succeeds', () => { +// it('calls MicroserviceManager#create() with correct args', async () => { +// await $subject; +// expect(MicroserviceManager.create).to.have.been.calledWith(newMicroservice, +// transaction); +// }); +// +// context('when MicroserviceManager#create() fails', () => { +// def('getIoFogResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#create() succeeds', () => { +// it('calls Validator#validate() with correct args', async () => { +// await $subject; +// expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); +// }); +// +// context('when Validator#validate() fails', () => { +// def('validatorResponse2', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when Validator#validate() succeeds', () => { +// it('calls MicroserviceManager#findOne() with correct args', async () => { +// await $subject; +// const where = isCLI +// ? {uuid: microserviceData.uuid} +// : {uuid: microserviceData.uuid, userId: user.id}; +// expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); +// }); +// +// context('when MicroserviceManager#findOne() fails', () => { +// def('findMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#findOne() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.findOne).to.have.been.calledWith({ +// microserviceUuid: microserviceData.uuid, +// [Op.or]: +// [ +// { +// portInternal: portMappingData.internal +// }, +// { +// portExternal: portMappingData.external +// } +// ] +// }, transaction); +// }); +// +// context('when MicroservicePortManager#findOne() fails', () => { +// def('findMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#create() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); +// }); +// +// context('when MicroservicePortManager#create() fails', () => { +// def('createMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#create() succeeds', () => { +// it('calls MicroserviceManager#update() with correct args', async () => { +// await $subject; +// const updateRebuildMs = { +// rebuild: true +// }; +// expect(MicroserviceManager.update).to.have.been.calledWith({ +// uuid: microserviceData.uuid +// }, updateRebuildMs, transaction); +// }); +// +// context('when MicroserviceManager#update() fails', () => { +// def('updateMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#update() succeeds', () => { +// it('calls ChangeTrackingService#update() with correct args', async () => { +// await $subject; +// expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, +// ChangeTrackingService.events.microserviceConfig, transaction); +// }); +// +// context('when ChangeTrackingService#update() fails', () => { +// def('updateChangeTrackingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when ChangeTrackingService#update() succeeds', () => { +// it('calls VolumeMappingManager#bulkCreate() with correct args', async () => { +// await $subject; +// expect(VolumeMappingManager.bulkCreate).to.have.been.calledWith(mappings, +// transaction); +// }); +// +// context('when VolumeMappingManager#bulkCreate() fails', () => { +// def('createVolumeMappingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when VolumeMappingManager#bulkCreate() succeeds', () => { +// it('calls ChangeTrackingService#update() with correct args', async () => { +// await $subject; +// expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, +// ChangeTrackingService.events.microserviceList, transaction); +// }); +// +// context('when ChangeTrackingService#update() fails', () => { +// def('updateChangeTrackingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when ChangeTrackingService#update() succeeds', () => { +// it('calls MicroserviceStatusManager#create() with correct args', async () => { +// await $subject; +// expect(MicroserviceStatusManager.create).to.have.been.calledWith({ +// microserviceUuid: microserviceData.uuid +// }, transaction); +// }); +// +// context('when MicroserviceStatusManager#create() fails', () => { +// def('createMicroserviceStatusResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceStatusManager#create() succeeds', () => { +// it('fulfills the promise', () => { +// return expect($subject).to.eventually.have.property('uuid'); +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }); +// +// +// describe('.deleteMicroservice()', () => { +// const transaction = {}; +// const error = 'Error!'; +// +// const user = { +// id: 15 +// }; +// +// const microserviceUuid = 'testMicroserviceUuid'; +// +// const microserviceData = { +// "name": "name2", +// "config": "string", +// "catalogItemId": 15, +// "flowId": 16, +// "iofogUuid": 'testIofogUuid', +// "rootHostAccess": true, +// "logSize": 0, +// "volumeMappings": [ +// { +// "hostDestination": "/var/dest", +// "containerDestination": "/var/dest", +// "accessMode": "rw" +// } +// ], +// "ports": [ +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// } +// ], +// "routes": [] +// }; +// +// const portMappingData = [ +// { +// "internal": 1, +// "external": 1, +// "publicMode": false +// } +// ]; +// +// +// const where = isCLI +// ? +// { +// uuid: microserviceUuid, +// } +// : +// { +// uuid: microserviceUuid, +// userId: user.id +// }; +// +// const mappingData = { +// isPublic: false, +// portInternal: portMappingData.internal, +// portExternal: portMappingData.external, +// userId: microserviceData.userId, +// microserviceUuid: microserviceData.uuid +// }; +// +// def('subject', () => $subject.deleteMicroservice(microserviceUuid, microserviceData, user, isCLI, transaction)); +// def('findMicroserviceResponse', () => Promise.resolve(microserviceData)); +// def('findMicroservicePortResponse', () => Promise.resolve()); +// def('deleteMicroservicePortResponse', () => Promise.resolve()); +// def('updateMicroserviceResponse', () => Promise.resolve()); +// def('updateChangeTrackingResponse', () => Promise.resolve()); +// +// beforeEach(() => { +// $sandbox.stub(MicroserviceManager, 'findOneWithStatus').returns($findMicroserviceResponse); +// $sandbox.stub(MicroservicePortManager, 'findAll').returns($findMicroservicePortResponse); +// $sandbox.stub(MicroservicePortManager, 'delete').returns($deleteMicroservicePortResponse); +// $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); +// $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); +// }); +// +// it('calls Validator#validate() with correct args', async () => { +// await $subject; +// expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); +// }); +// +// context('when Validator#validate() fails', () => { +// def('validatorResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when Validator#validate() succeeds', () => { +// it('calls MicroserviceManager#findOne() with correct args', async () => { +// await $subject; +// expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); +// }); +// +// context('when MicroserviceManager#findOne() fails', () => { +// def('findMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#findOne() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.findOne).to.have.been.calledWith({ +// microserviceUuid: microserviceUuid, +// [Op.or]: +// [ +// { +// portInternal: portMappingData.internal +// }, +// { +// portExternal: portMappingData.external +// } +// ] +// }, transaction); +// }); +// +// context('when MicroservicePortManager#findOne() fails', () => { +// def('findMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#findOne() succeeds', () => { +// it('calls MicroservicePortManager#create() with correct args', async () => { +// await $subject; +// expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); +// }); +// +// context('when MicroservicePortManager#create() fails', () => { +// def('createMicroservicePortResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroservicePortManager#create() succeeds', () => { +// it('calls MicroserviceManager#update() with correct args', async () => { +// await $subject; +// const updateRebuildMs = { +// rebuild: true +// }; +// expect(MicroserviceManager.update).to.have.been.calledWith({ +// uuid: microserviceData.uuid +// }, updateRebuildMs, transaction); +// }); +// +// context('when MicroserviceManager#update() fails', () => { +// def('updateMicroserviceResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when MicroserviceManager#update() succeeds', () => { +// it('calls ChangeTrackingService#update() with correct args', async () => { +// await $subject; +// expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, +// ChangeTrackingService.events.microserviceConfig, transaction); +// }); +// +// context('when ChangeTrackingService#update() fails', () => { +// def('updateChangeTrackingResponse', () => Promise.reject(error)); +// +// it(`fails with ${error}`, () => { +// return expect($subject).to.be.rejectedWith(error); +// }) +// }); +// +// context('when ChangeTrackingService#update() succeeds', () => { +// it('fulfills the promise', () => { +// return expect($subject).eventually.equals(undefined); +// }) +// }) +// }) +// }) +// }) +// }) +// }) +// }); +// +// }); +// + + describe('.createPortMapping()', () => { + const transaction = {}; + const error = 'Error!'; + + const user = { + id: 15 + }; + + const microserviceUuid = 'testMicroserviceUuid'; + + const microserviceData = { + "name": "name2", + "config": "string", + "catalogItemId": 15, + "flowId": 16, + "iofogUuid": 'testIofogUuid', + "rootHostAccess": true, + "logSize": 0, + "volumeMappings": [ + { + "hostDestination": "/var/dest", + "containerDestination": "/var/dest", + "accessMode": "rw" + } + ], + "ports": [ + { + "internal": 1, + "external": 1, + "publicMode": false + } + ], + "routes": [] + }; + + const portMappingData = [ + { + "internal": 1, + "external": 1, + "publicMode": false + } + ]; + + const where = isCLI + ? {uuid: microserviceUuid} + : {uuid: microserviceUuid, userId: user.id}; + + const mappingData = { + isPublic: false, + portInternal: portMappingData.internal, + portExternal: portMappingData.external, + userId: microserviceData.userId, + microserviceUuid: microserviceData.uuid + }; + + def('subject', () => $subject.createPortMapping(microserviceUuid, portMappingData, user, isCLI, transaction)); + def('validatorResponse', () => Promise.resolve(true)); + def('findMicroserviceResponse', () => Promise.resolve(microserviceData)); + def('findMicroservicePortResponse', () => Promise.resolve()); + def('createMicroservicePortResponse', () => Promise.resolve()); + def('updateMicroserviceResponse', () => Promise.resolve()); + def('updateChangeTrackingResponse', () => Promise.resolve()); + + beforeEach(() => { + $sandbox.stub(Validator, 'validate').returns($validatorResponse); + $sandbox.stub(MicroserviceManager, 'findOne').returns($findMicroserviceResponse); + $sandbox.stub(MicroservicePortManager, 'findOne').returns($findMicroservicePortResponse); + $sandbox.stub(MicroservicePortManager, 'create').returns($createMicroservicePortResponse); + $sandbox.stub(MicroserviceManager, 'update').returns($updateMicroserviceResponse); + $sandbox.stub(ChangeTrackingService, 'update').returns($updateChangeTrackingResponse); + }); + + it('calls Validator#validate() with correct args', async () => { + await $subject; + expect(Validator.validate).to.have.been.calledWith(portMappingData, Validator.schemas.portsCreate); + }); + + context('when Validator#validate() fails', () => { + def('validatorResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when Validator#validate() succeeds', () => { + it('calls MicroserviceManager#findOne() with correct args', async () => { + await $subject; + expect(MicroserviceManager.findOne).to.have.been.calledWith(where, transaction); + }); + + context('when MicroserviceManager#findOne() fails', () => { + def('findMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#findOne() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.findOne).to.have.been.calledWith({ + microserviceUuid: microserviceUuid, + [Op.or]: + [ + { + portInternal: portMappingData.internal + }, + { + portExternal: portMappingData.external + } + ] + }, transaction); + }); + + context('when MicroservicePortManager#findOne() fails', () => { + def('findMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#findOne() succeeds', () => { + it('calls MicroservicePortManager#create() with correct args', async () => { + await $subject; + expect(MicroservicePortManager.create).to.have.been.calledWith(mappingData, transaction); + }); + + context('when MicroservicePortManager#create() fails', () => { + def('createMicroservicePortResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroservicePortManager#create() succeeds', () => { + it('calls MicroserviceManager#update() with correct args', async () => { + await $subject; + const updateRebuildMs = { + rebuild: true + }; + expect(MicroserviceManager.update).to.have.been.calledWith({ + uuid: microserviceData.uuid + }, updateRebuildMs, transaction); + }); + + context('when MicroserviceManager#update() fails', () => { + def('updateMicroserviceResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when MicroserviceManager#update() succeeds', () => { + it('calls ChangeTrackingService#update() with correct args', async () => { + await $subject; + expect(ChangeTrackingService.update).to.have.been.calledWith(microserviceData.iofogUuid, + ChangeTrackingService.events.microserviceConfig, transaction); + }); + + context('when ChangeTrackingService#update() fails', () => { + def('updateChangeTrackingResponse', () => Promise.reject(error)); + + it(`fails with ${error}`, () => { + return expect($subject).to.be.rejectedWith(error); + }) + }); + + context('when ChangeTrackingService#update() succeeds', () => { + it('fulfills the promise', () => { + return expect($subject).eventually.equals(undefined); + }) + }) + }) + }) + }) + }) + }) + }); + +}); \ No newline at end of file