diff --git a/azure-pipelines.yml b/azure-pipelines.yml index cae6b029a..0fad5517f 100644 --- a/azure-pipelines.yml +++ b/azure-pipelines.yml @@ -5,7 +5,7 @@ trigger: branches: include: - develop - - release* + - release/* paths: exclude: - README.md @@ -70,32 +70,6 @@ jobs: echo "npm test" displayName: 'integration tests' - - script: | - npm pack - ls iofogcontroller-*.tgz - displayName: 'npm pack for release artefact' - - - task: CopyFiles@2 - inputs: - SourceFolder: $(System.DefaultWorkingDirectory) - TargetFolder: $(Build.ArtifactStagingDirectory) - Contents: | - standardjs.out - *.tgz - Dockerfile.dev - OverWrite: true - displayName: 'artefacts to publish' - - - script: | - rm -fr iofogcontroller-*.tgz - git checkout package-lock.json - git config --global user.email "info@edgeworx.io" - git config --global user.name "Azure DevOps" - - PACKAGE_VERSION=$(cat package.json | grep version | head -1 | awk -F: '{ print $2 }' | sed 's/[\",]//g' | tr -d '[[:space:]]') - npm --no-git-tag-version version $PACKAGE_VERSION-b$(Build.BuildId) - displayName: 'npm version' - - script: | npm pack displayName: 'npm pack with version containing build number' diff --git a/package-lock.json b/package-lock.json index 941bcee1c..fb7fdea01 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,6 +1,6 @@ { "name": "iofogcontroller", - "version": "1.0.37", + "version": "1.0.38", "lockfileVersion": 1, "requires": true, "dependencies": { diff --git a/package.json b/package.json index 9e4295795..dc536e7e7 100644 --- a/package.json +++ b/package.json @@ -1,12 +1,13 @@ { "name": "iofogcontroller", - "version": "1.0.37", + "version": "1.0.38", "description": "ioFog Controller project for Eclipse IoFog @ iofog.org \\nCopyright (c) 2018 Edgeworx, Inc.", "main": "./src/main.js", "author": "Saeid Baghbidi", "contributors": [ "Kilton Hopkins ", "Saeid Baghbidi", + "Alexandre de Wergifosse", "Pavel Kazlou", "Egor Krylovich", "Iryna Laryionava", @@ -86,7 +87,7 @@ "path": "0.12.7", "portscanner": "2.2.0", "qs": "6.6.0", - "request-promise": "^4.2.4", + "request-promise": "4.2.4", "retry-as-promised": "3.1.0", "semver": "5.6.0", "sequelize": "4.42.0", @@ -105,8 +106,8 @@ "chai": "4.2.0", "chai-as-promised": "7.1.1", "chai-http": "4.2.1", - "eslint": "^5.14.1", - "eslint-config-google": "^0.12.0", + "eslint": "5.14.1", + "eslint-config-google": "0.12.0", "mocha": "5.2.0", "nyc": "13.3.0", "sinon": "7.2.3", diff --git a/scripts/cli-tests.js b/scripts/cli-tests.js index 53b185ad6..32cf110ff 100644 --- a/scripts/cli-tests.js +++ b/scripts/cli-tests.js @@ -53,7 +53,7 @@ const registryListFields = ['registries'] const tunnelListFields = ['tunnels'] -function testControllerSection() { +function testControllerSection () { console.log('\n=============================\nStarting controller section..') responseHasFields(testCommand('controller status'), controllerStatusFields) @@ -62,7 +62,7 @@ function testControllerSection() { hasSomeResponse(testCommand('controller version')) } -function testUserSection() { +function testUserSection () { console.log('\n=============================\nStarting user section..') responseHasFields(testCommand('user add -f John -l Doe -e user@domain.com -p \'#Bugs4Fun\''), userCreateFields) @@ -75,7 +75,7 @@ function testUserSection() { responseEquals(testCommand('user remove -e user@domain.com'), 'User removed successfully.') } -function testConfigSection() { +function testConfigSection () { console.log('\n=============================\nStarting config section..') // TODO backup config before this command @@ -86,7 +86,7 @@ function testConfigSection() { responseEquals(testCommand('config email-activation -f'), 'Email activation state updated successfully.') } -function testConnectorSection() { +function testConnectorSection () { console.log('\n=============================\nStarting connector section..') responseContains(testCommand('connector add -i 127.0.0.1 -n Connector1 -d iofog.test.org -c testCertPath' + @@ -97,7 +97,7 @@ function testConnectorSection() { responseIsArray(testCommand('connector list')) } -function testTunnelSection() { +function testTunnelSection () { console.log('\n=============================\nStarting tunnel section..') responseContains(testCommand('tunnel update -i testIoFogUuid -u testUsername -p testPassword -s 127.0.0.1 ' + @@ -105,7 +105,7 @@ function testTunnelSection() { responseHasFields(testCommand('tunnel list'), tunnelListFields) } -function testIoFogSection() { +function testIoFogSection () { console.log('\n=============================\nStarting iofog section..') const userCreateResponse = responseHasFields(executeCommand('user add -f John -l Doe -e fogUser@domain.com' + @@ -135,7 +135,7 @@ function testIoFogSection() { } } -function testCatalogSection() { +function testCatalogSection () { console.log('\n=============================\nStarting catalog section..') const userCreateResponse = responseHasFields(executeCommand('user add -f John -l Doe -e catalogUser@domain.com' + @@ -147,13 +147,13 @@ function testCatalogSection() { try { const catalogCreateResponse = responseHasFields(testCommand('catalog add -n testCatalogItem1 -d testDescription' + - ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' - + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat ' + + ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' + + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat ' + '-X \'{}\' -u ' + userId), catalogCreateFields) const catalogId = catalogCreateResponse.id responseEquals(testCommand('catalog update -i ' + catalogId + ' -n testCatalogItem2 -d testDescription' + - ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' - + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat -X \'{}\''), + ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' + + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat -X \'{}\''), 'Catalog item has been updated successfully.') responseHasFields(testCommand('catalog list'), catalogListFields) responseHasFields(testCommand('catalog info -i ' + catalogId), catalogCreateFields) @@ -166,7 +166,7 @@ function testCatalogSection() { } } -function testFlowSection() { +function testFlowSection () { console.log('\n=============================\nStarting flow section..') const userCreateResponse = responseHasFields(executeCommand('user add -f John -l Doe -e flowUser@domain.com' + @@ -188,7 +188,7 @@ function testFlowSection() { } } -function testMicroserviceSection() { +function testMicroserviceSection () { console.log('\n=============================\nStarting microservice section..') const userCreateResponse = responseHasFields(executeCommand('user add -f John -l Doe -e microserviceUser@domain.com' + @@ -200,8 +200,8 @@ function testMicroserviceSection() { const registryId = registryCreateResponse.id const catalogCreateResponse = responseHasFields(executeCommand('catalog add -n testCatalogItem1 -d testDescription' + - ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' - + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat ' + + ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' + + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat ' + '-X \'{}\' -u ' + userId), catalogCreateFields) const catalogId = catalogCreateResponse.id @@ -254,7 +254,7 @@ function testMicroserviceSection() { } } -function testRegistrySection() { +function testRegistrySection () { console.log('\n=============================\nStarting registry section..') const userCreateResponse = responseHasFields(executeCommand('user add -f John -l Doe -e registryUser@domain.com' + @@ -275,7 +275,7 @@ function testRegistrySection() { } } -function testDiagnosticsSection() { +function testDiagnosticsSection () { console.log('\n=============================\nStarting diagnostics section..') const userCreateResponse = responseHasFields(executeCommand('user add -f John -l Doe -e diagnosticsUser@domain.com' + @@ -287,8 +287,8 @@ function testDiagnosticsSection() { const registryId = registryCreateResponse.id const catalogCreateResponse = responseHasFields(executeCommand('catalog add -n testCatalogItem1 -d testDescription' + - ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' - + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat ' + + ' -c testCategory -x testIntelImage -a testArmImage -p testPublisher -s 15 -r 15 -t testPicture -g ' + + registryId + ' -I testInputType -F testInputFormat -O testOutputType -T testOutputFormat ' + '-X \'{}\' -u ' + userId), catalogCreateFields) const catalogId = catalogCreateResponse.id @@ -333,27 +333,27 @@ function testDiagnosticsSection() { } } -function testCommand(command) { +function testCommand (command) { console.log('\n Testing command \'' + command + '\'') testsCounter++ return executeCommand(command) } -function executeCommand(command) { +function executeCommand (command) { let response = execSync('node ./src/main.js ' + command, options) response = response.toString() response = response.replace(/\r?\n?/g, '') // remove line breaks return response } -function hasSomeResponse(response) { +function hasSomeResponse (response) { if (response === undefined || response === null) { testsFailed++ console.log('\'hasSomeResponse\' test failed with response: ' + JSON.stringify(response)) } } -function responseIsArray(jsonResponse) { +function responseIsArray (jsonResponse) { try { const response = JSON.parse(jsonResponse) if (!Array.isArray(response)) { @@ -366,7 +366,7 @@ function responseIsArray(jsonResponse) { } } -function responseHasFields(jsonResponse, fields) { +function responseHasFields (jsonResponse, fields) { try { const response = JSON.parse(jsonResponse) for (const field of fields) { @@ -383,21 +383,21 @@ function responseHasFields(jsonResponse, fields) { } } -function responseEquals(response, expectedResponse) { +function responseEquals (response, expectedResponse) { if (response !== expectedResponse) { testsFailed++ console.log('\'responseEquals\' test failed with response: ' + JSON.stringify(response)) } } -function responseContains(response, expectedResponsePart) { +function responseContains (response, expectedResponsePart) { if (!response.includes(expectedResponsePart)) { testsFailed++ console.log('\'responseContains\' test failed with response: ' + JSON.stringify(response)) } } -function cliTest() { +function cliTest () { try { backupDBs() // create new DBs diff --git a/scripts/preuninstall.js b/scripts/preuninstall.js index 585b4e30e..4d1e0f582 100644 --- a/scripts/preuninstall.js +++ b/scripts/preuninstall.js @@ -11,6 +11,7 @@ * */ +const execSync = require('child_process').execSync const fs = require('fs') const version = require('../package').version const { backupDBs, backupConfigs, backupTrackingUuid, INSTALLATION_VARIABLES_FILE } = require('./util') @@ -25,6 +26,11 @@ function preuninstall() { backupDBs() backupConfigs() backupTrackingUuid() + + const options = { + stdio: [process.stdin, process.stdout, process.stderr], + } + execSync('iofog-controller stop', options) } module.exports = { diff --git a/src/cli/microservice.js b/src/cli/microservice.js index 71125f330..d40ec4218 100644 --- a/src/cli/microservice.js +++ b/src/cli/microservice.js @@ -490,7 +490,7 @@ const _updateMicroserviceObject = function(obj) { rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), logSize: obj.logSize, rebuild: obj.rebuild, - arg: obj.cmd, + cmd: obj.cmd, env, } @@ -524,7 +524,7 @@ const _createMicroserviceObject = function(obj) { rootHostAccess: AppHelper.validateBooleanCliOptions(obj.rootEnable, obj.rootDisable), logSize: obj.logSize, routes: obj.routes, - arg: obj.cmd, + cmd: obj.cmd, env, } diff --git a/src/cli/start.js b/src/cli/start.js index 5d6e3f449..9604b9b53 100644 --- a/src/cli/start.js +++ b/src/cli/start.js @@ -31,7 +31,7 @@ class Start extends BaseCLIHandler { if (pid === 0) { this.initDB() daemon.start() - checkDaemon(daemon, configuration) + await checkDaemon(daemon, configuration) } else { logger.cliRes(`iofog-controller already running. PID: ${pid}`) } @@ -49,24 +49,28 @@ class Start extends BaseCLIHandler { } function checkDaemon(daemon, configuration) { - let iterationsCount = 0 - const check = () => { - iterationsCount++ - const 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.') - } + return new Promise((resolve, reject) => { + let iterationsCount = 0 + const check = () => { + iterationsCount++ + const pid = daemon.status() + if (pid === 0) { + logger.error('Error: port is probably allocated, or ssl_key or ssl_cert or intermediate_cert ' + + 'is either missing or invalid.') + return reject(new Error('Error starting ioFog-Controller')) + } - if (iterationsCount === 5) { - checkServerProtocol(configuration) - return logger.cliRes(`ioFog-Controller has started at pid: ${pid}`) + if (iterationsCount === 5) { + checkServerProtocol(configuration) + logger.cliRes(`ioFog-Controller has started at pid: ${pid}`) + return resolve() + } + + setTimeout(check, 1000) } setTimeout(check, 1000) - } - - setTimeout(check, 1000) + }) } function checkServerProtocol(configuration) { diff --git a/src/controllers/connector-controller.js b/src/controllers/connector-controller.js new file mode 100644 index 000000000..ad1d98672 --- /dev/null +++ b/src/controllers/connector-controller.js @@ -0,0 +1,43 @@ +/* + * ******************************************************************************* + * * 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 ConnectorService = require('../services/connector-service') + +const addConnectorEndPoint = async function (req) { + const connectorData = req.body + return ConnectorService.createConnector(connectorData) +} + +const updateConnectorEndPoint = async function (req) { + const connectorData = req.body + return ConnectorService.updateConnector(connectorData) +} + +const deleteConnectorEndPoint = async function (req) { + const connectorData = req.body + return ConnectorService.deleteConnector(connectorData) +} + +const listConnectorEndPoint = async function (req) { + const res = await ConnectorService.getConnectorList() + return { + connectors: res, + } +} + +module.exports = { + addConnectorEndPoint, + updateConnectorEndPoint, + deleteConnectorEndPoint, + listConnectorEndPoint, +} diff --git a/src/logger/index.js b/src/logger/index.js index 009e2706e..a3185661c 100644 --- a/src/logger/index.js +++ b/src/logger/index.js @@ -79,38 +79,13 @@ const logger = winston.createLogger({ prepareObjectLogs(), formattedJson() ), - filename: 'iofog-controller.0.log', + filename: 'iofog-controller.log', dirname: dirname, maxsize: maxsize, - rotationFormat: function() { - return getFormattedLogName() - }, }), ], }) -// logFileName pattern similar to agent -function getFormattedLogName() { - if (fs.existsSync(dirname)) { - const files = fs.readdirSync(dirname) - const latestFilePath = dirname + '/' + files[0] - - if (files.length === 0 || fs.statSync(latestFilePath).size <= maxsize) { - return '' - } - - files.reverse().forEach((file) => { - const path = dirname + '/' + file - if (fs.existsSync(path)) { - const strNumber = file.replace('iofog-controller.', '').replace('.log', '') - const number = parseInt(strNumber) + 1 - fs.renameSync(path, path.replace(strNumber, number)) - } - }) - } - return '' -} - logger.add(new winston.transports.Console({ level: 'info', format: winston.format((log) => { diff --git a/src/main.js b/src/main.js index 2c32f7c9c..c8eee0f33 100644 --- a/src/main.js +++ b/src/main.js @@ -20,10 +20,12 @@ if (!process.env.NODE_ENV) { const Cli = require('./cli') const daemon = require('./daemon') -function main() { +async function main() { const cli = new Cli() - cli.run(daemon) + await cli.run(daemon) } main() + .then(() => process.exit(0)) + .catch(() => process.exit(1)) diff --git a/src/routes/connector.js b/src/routes/connector.js new file mode 100644 index 000000000..cf8ed3f09 --- /dev/null +++ b/src/routes/connector.js @@ -0,0 +1,132 @@ +/* + * ******************************************************************************* + * * 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 constants = require('../helpers/constants') +const Connector = require('../controllers/connector-controller') +const ResponseDecorator = require('../decorators/response-decorator') +const logger = require('../logger') +const Errors = require('../helpers/errors') + +module.exports = [ + { + method: 'post', + path: '/api/v3/connector', + middleware: async (req, res) => { + logger.apiReq(req) + + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError], + }, + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError], + }, + ] + const addConnectorEndPoint = ResponseDecorator.handleErrors(Connector.addConnectorEndPoint, successCode, errorCodes) + const responseObject = await addConnectorEndPoint(req) + + res + .status(responseObject.code) + .send(responseObject.body) + + logger.apiRes({ req: req, res: responseObject }) + }, + }, + { + method: 'get', + path: '/api/v3/connector', + middleware: async (req, res) => { + logger.apiReq(req) + + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError], + }, + ] + const listConnectorEndPoint = ResponseDecorator.handleErrors(Connector.listConnectorEndPoint, successCode, errorCodes) + const responseObject = await listConnectorEndPoint(req) + + res + .status(responseObject.code) + .send(responseObject.body) + + logger.apiRes({ req: req, res: responseObject }) + }, + }, + { + method: 'put', + path: '/api/v3/connector', + middleware: async (req, res) => { + logger.apiReq(req) + + const successCode = constants.HTTP_CODE_SUCCESS + const errorCodes = [ + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError], + }, + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError], + }, + { + code: constants.HTTP_CODE_NOT_FOUND, + errors: [Errors.NotFoundError], + }, + ] + const updateConnectorEndPoint = ResponseDecorator.handleErrors(Connector.updateConnectorEndPoint, successCode, errorCodes) + const responseObject = await updateConnectorEndPoint(req) + + res + .status(responseObject.code) + .send(responseObject.body) + + logger.apiRes({ req: req, res: responseObject }) + }, + }, + { + method: 'delete', + path: '/api/v3/connector', + middleware: async (req, res) => { + logger.apiReq(req) + + const successCode = constants.HTTP_CODE_NO_CONTENT + const errorCodes = [ + { + code: constants.HTTP_CODE_UNAUTHORIZED, + errors: [Errors.AuthenticationError], + }, + { + code: constants.HTTP_CODE_BAD_REQUEST, + errors: [Errors.ValidationError], + }, + { + code: constants.HTTP_CODE_NOT_FOUND, + errors: [Errors.NotFoundError], + }, + ] + const deleteConnectorEndPoint = ResponseDecorator.handleErrors(Connector.deleteConnectorEndPoint, successCode, errorCodes) + const responseObject = await deleteConnectorEndPoint(req) + + res + .status(responseObject.code) + .send(responseObject.body) + + logger.apiRes({ req: req, res: responseObject }) + }, + }, +] diff --git a/src/services/connector-service.js b/src/services/connector-service.js index 5ee2968b9..b50062c7e 100644 --- a/src/services/connector-service.js +++ b/src/services/connector-service.js @@ -22,7 +22,7 @@ const Op = require('sequelize').Op const ConnectorPortManager = require('../sequelize/managers/connector-port-manager') const MicroserviceService = require('../services/microservices-service') -async function createConnector(connectorData, transaction) { +async function createConnector (connectorData, transaction) { await Validator.validate(connectorData, Validator.schemas.connectorCreate) _validateConnectorData(connectorData) const connector = await ConnectorManager.findOne({ @@ -41,10 +41,10 @@ async function createConnector(connectorData, transaction) { if (connector) { throw new Errors.ValidationError(ErrorMessages.ALREADY_EXISTS) } - return await ConnectorManager.create(connectorData, transaction) + return ConnectorManager.create(connectorData, transaction) } -async function updateConnector(connectorData, transaction) { +async function updateConnector (connectorData, transaction) { await Validator.validate(connectorData, Validator.schemas.connectorUpdate) _validateConnectorData(connectorData) const queryConnectorData = { @@ -62,9 +62,10 @@ async function updateConnector(connectorData, transaction) { const updatedConnector = await ConnectorManager.findOne({ publicIp: connectorData.publicIp }, transaction) await MicroserviceService.updateRouteOverConnector(updatedConnector, transaction) await MicroserviceService.updatePortMappingOverConnector(updatedConnector, transaction) + return updatedConnector } -async function deleteConnector(connectorData, transaction) { +async function deleteConnector (connectorData, transaction) { await Validator.validate(connectorData, Validator.schemas.connectorDelete) const queryConnectorData = { publicIp: connectorData.publicIp, @@ -80,11 +81,11 @@ async function deleteConnector(connectorData, transaction) { await ConnectorManager.delete(queryConnectorData, transaction) } -async function getConnectorList(transaction) { - return await ConnectorManager.findAll({}, transaction) +async function getConnectorList (transaction) { + return ConnectorManager.findAll({}, transaction) } -function _validateConnectorData(connectorData) { +function _validateConnectorData (connectorData) { if (connectorData.domain) { const validDomain = AppHelper.isValidDomain(connectorData.domain) || AppHelper.isValidPublicIP(connectorData.domain) if (!validDomain) { diff --git a/src/services/iofog-service.js b/src/services/iofog-service.js index 08c9acc0a..bcd27339d 100644 --- a/src/services/iofog-service.js +++ b/src/services/iofog-service.js @@ -11,7 +11,6 @@ * */ -const config = require('../config') const request = require('request-promise') const TransactionDecorator = require('../decorators/transaction-decorator') @@ -30,6 +29,7 @@ const MicroserviceManager = require('../sequelize/managers/microservice-manager' const FogStates = require('../enums/fog-state') const TrackingDecorator = require('../decorators/tracking-decorator') const TrackingEventType = require('../enums/tracking-event-type') +const config = require('../config') async function createFogEndPoint(fogData, user, isCLI, transaction) { await Validator.validate(fogData, Validator.schemas.iofogCreate) diff --git a/src/services/microservices-service.js b/src/services/microservices-service.js index f1bb53ac2..6aae66b16 100644 --- a/src/services/microservices-service.js +++ b/src/services/microservices-service.js @@ -162,14 +162,16 @@ async function updateMicroserviceEndPoint(microserviceUuid, microserviceData, us throw new Errors.ValidationError(AppHelper.formatMessage(ErrorMessages.SYSTEM_MICROSERVICE_UPDATE, microserviceUuid)) } + const iofogUuid = microserviceDataUpdate.iofogUuid || microservice.iofogUuid + if (microserviceDataUpdate.name) { const userId = isCLI ? microservice.userId : user.id await _checkForDuplicateName(microserviceDataUpdate.name, { id: microserviceUuid }, userId, transaction) } // validate fog node - if (microserviceDataUpdate.iofogUuid) { - await IoFogService.getFog({ uuid: microserviceDataUpdate.iofogUuid }, user, isCLI, transaction) + if (iofogUuid) { + await IoFogService.getFog({ uuid: iofogUuid }, user, isCLI, transaction) } const updatedMicroservice = await MicroserviceManager.updateAndFind(query, microserviceDataUpdate, transaction) @@ -189,10 +191,11 @@ async function updateMicroserviceEndPoint(microserviceUuid, microserviceData, us if (microserviceDataUpdate.iofogUuid && microserviceDataUpdate.iofogUuid !== microservice.iofogUuid) { await _moveRoutesToNewFog(updatedMicroservice, microservice.iofogUuid, user, transaction) await _movePublicModesToNewFog(updatedMicroservice, microservice.iofogUuid, user, transaction) + await _updateChangeTracking(true, microservice.iofogUuid, transaction) } // update change tracking for new fog - await _updateChangeTracking(!!microserviceData.config, microserviceDataUpdate.iofogUuid, transaction) + await _updateChangeTracking(!!microserviceData.config, iofogUuid, transaction) } async function _moveRoutesToNewFog(microservice, oldFogUuid, user, transaction) { @@ -1018,7 +1021,6 @@ async function _createPortMappingOverConnector(microservice, portMappingData, us } await MicroservicePublicModeManager.create(msPubModeData, transaction) - await _switchOnUpdateFlagsForMicroservicesForPortMapping(microservice, true, transaction) const publicLink = _buildLink(connector.devMode ? 'http' : 'https', connector.publicIp, connectorPort.port2) return { publicLink: publicLink } diff --git a/test/postman_collection.json b/test/postman_collection.json index 5ba9de1a8..d62b867a0 100644 --- a/test/postman_collection.json +++ b/test/postman_collection.json @@ -676,6 +676,367 @@ } ] }, + { + "name": "Connector", + "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": "Add connector", + "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');", + "", + "postman.setGlobalVariable(\"connector-ip\", data.publicIp);" + ], + "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\": \"MyConnector\",\n \"domain\": \"ConnectorDomain\",\n \"publicIp\": \"1.2.3.4\", \"devMode\": true\n}" + }, + "url": { + "raw": "{{host}}/api/v3/connector", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "connector" + ] + } + }, + "response": [] + }, + { + "name": "Get Connectors", + "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('connectors') && data.connectors.length === 1" + ], + "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/connector", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "connector" + ] + } + }, + "response": [] + }, + { + "name": "Update Connector", + "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('name') && data.name === 'updatedName';" + ], + "type": "text/javascript" + } + } + ], + "request": { + "method": "PUT", + "header": [ + { + "key": "Content-Type", + "value": "application/json" + }, + { + "key": "Authorization", + "value": "{{user-token}}", + "type": "text" + } + ], + "body": { + "mode": "raw", + "raw": "{\n \"name\": \"updatedName\",\n \"publicIp\": \"{{connector-ip}}\" \n}" + }, + "url": { + "raw": "{{host}}/api/v3/connector", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "connector" + ] + } + }, + "response": [] + }, + { + "name": "Delete Connector", + "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": "{\n \"publicIp\": \"{{connector-ip}}\"\n}" + }, + "url": { + "raw": "{{host}}/api/v3/connector", + "host": [ + "{{host}}" + ], + "path": [ + "api", + "v3", + "connector" + ] + } + }, + "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": [] + } + ], + "description": "Connector 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": "Agent", "item": [ diff --git a/test/src/services/connector-service.test.js b/test/src/services/connector-service.test.js index c58211864..af123deba 100644 --- a/test/src/services/connector-service.test.js +++ b/test/src/services/connector-service.test.js @@ -174,7 +174,7 @@ describe('Connector Service', () => { def('isValidDomainResponse', () => false) def('isValidPublicIpResponse', () => true) def('isValidPublicIpResponse2', () => true) - def('updateConnectorResponse', () => Promise.resolve()) + def('updateConnectorResponse', () => Promise.resolve(connectorData)) def('findOneConnectorResponse', () => Promise.resolve(connector)) def('updateRouteOverConnectorResponse', () => Promise.resolve()) def('updatePortMappingOverConnectorResponse', () => Promise.resolve()) @@ -218,7 +218,7 @@ describe('Connector Service', () => { def('isValidDomainResponse', () => error) it(`fails with ${error}`, () => { - return expect($subject).to.eventually.equal(undefined) + return expect($subject).to.eventually.equal(connector) }) }) @@ -232,7 +232,7 @@ describe('Connector Service', () => { def('isValidPublicIpResponse', () => error) it(`fails with ${error}`, () => { - return expect($subject).to.eventually.equal(undefined) + return expect($subject).to.eventually.equal(connector) }) }) @@ -246,7 +246,7 @@ describe('Connector Service', () => { def('isValidPublicIpResponse2', () => error) it(`fails with ${error}`, () => { - return expect($subject).to.eventually.equal(undefined) + return expect($subject).to.eventually.equal(connector) }) }) @@ -310,7 +310,7 @@ describe('Connector Service', () => { context('when MicroserviceService#updatePortMappingOverConnector() succeeds', () => { it('fulfills the promise', () => { - return expect($subject).to.eventually.equal(undefined) + return expect($subject).to.eventually.equal(connector) }) }) })