From 20ff3610b311347c7d961b4cb287ea8eb5a4f8a0 Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Tue, 6 Nov 2018 10:56:53 +0100 Subject: [PATCH 1/9] use trust and cbHost from deviceGroup in typeInformation --- lib/services/ngsi/ngsiService.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/lib/services/ngsi/ngsiService.js b/lib/services/ngsi/ngsiService.js index b6026488a..c34b747cf 100644 --- a/lib/services/ngsi/ngsiService.js +++ b/lib/services/ngsi/ngsiService.js @@ -203,7 +203,7 @@ function createRequestObject(url, typeInformation, token) { if (config.getConfig().authentication && config.getConfig().authentication.enabled) { headers[config.getConfig().authentication.header] = token; } - + logger.debug(context, 'typeInformation %j', typeInformation); if (typeInformation) { if (typeInformation.service) { headers['fiware-service'] = typeInformation.service; @@ -739,6 +739,10 @@ function executeWithDeviceInformation(operationFunction) { } } else { typeInformation = deviceInformation; + if (deviceGroup && deviceGroup.trust && deviceGroup.cbHost) { + typeInformation.trust = deviceGroup.trust; + typeInformation.cbHost = deviceGroup.cbHost; + } } if (config.getConfig().authentication && config.getConfig().authentication.enabled) { From 50f6d8526b8c5ef05b3dc59da17e8d582eccef2c Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Tue, 6 Nov 2018 16:17:40 +0100 Subject: [PATCH 2/9] send cbHost to iotamanager service --- lib/services/common/iotManagerService.js | 1 + 1 file changed, 1 insertion(+) diff --git a/lib/services/common/iotManagerService.js b/lib/services/common/iotManagerService.js index be1935637..0c96675e0 100644 --- a/lib/services/common/iotManagerService.js +++ b/lib/services/common/iotManagerService.js @@ -46,6 +46,7 @@ function register(callback) { return { apikey: service.apikey, token: service.trust, + cbHost: service.cbHost, entity_type: service.type, resource: service.resource, service: service.service, From c88b2552a7b4b3319a3cc51b5d3bf6cea7443846 Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Wed, 7 Nov 2018 10:29:48 +0100 Subject: [PATCH 3/9] add cbHost to iotam-autoregistration-test json --- test/unit/examples/iotamRequests/registrationWithGroups.json | 1 + .../examples/iotamRequests/registrationWithStaticGroups.json | 1 + 2 files changed, 2 insertions(+) diff --git a/test/unit/examples/iotamRequests/registrationWithGroups.json b/test/unit/examples/iotamRequests/registrationWithGroups.json index 9a60fe182..e113a6e08 100644 --- a/test/unit/examples/iotamRequests/registrationWithGroups.json +++ b/test/unit/examples/iotamRequests/registrationWithGroups.json @@ -7,6 +7,7 @@ { "apikey": "801230BJKL23Y9090DSFL123HJK09H324HV8732", "token": "8970A9078A803H3BL98PINEQRW8342HBAMS", + "cbHost":"http://unexistentHost:1026", "entity_type": "SensorMachine", "resource": "/deviceTest", "service": "theService", diff --git a/test/unit/examples/iotamRequests/registrationWithStaticGroups.json b/test/unit/examples/iotamRequests/registrationWithStaticGroups.json index f09948d57..9adf06caa 100644 --- a/test/unit/examples/iotamRequests/registrationWithStaticGroups.json +++ b/test/unit/examples/iotamRequests/registrationWithStaticGroups.json @@ -7,6 +7,7 @@ { "apikey": "801230BJKL23Y9090DSFL123HJK09H324HV8732", "token": "8970A9078A803H3BL98PINEQRW8342HBAMS", + "cbHost":"http://unexistentHost:1026", "entity_type": "SensorMachine", "resource": "/deviceTest", "service": "theService", From f5e80cb2140a1f583cafc312e7973be395efa2af Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Wed, 7 Nov 2018 11:02:33 +0100 Subject: [PATCH 4/9] update CNR --- CHANGES_NEXT_RELEASE | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/CHANGES_NEXT_RELEASE b/CHANGES_NEXT_RELEASE index 6890d9801..53321475b 100644 --- a/CHANGES_NEXT_RELEASE +++ b/CHANGES_NEXT_RELEASE @@ -1,3 +1,4 @@ +Fix: use trust and cbHost from deviceGroup (#685) Add timestamp in device and group provision (#655) Fix: missing support for device=true in the delete service endpoint (see #596) Add protocol in device provision if not provided (#652) @@ -6,8 +7,8 @@ Fix: object_id fields are not introduced in CB requests by alias plugin (#660) Add: uses provisioned timezone to generate TimeInstant values (#672) Using precise dependencies (~=) in packages.json Fix: updating dependencies due to known vulnerabilities in the previous ones - async: 1.5.2 -> 2.6.1 - body-parser: ~1.11.0 -> ~1.18.3 + async: 1.5.2 -> 2.6.1 + body-parser: ~1.11.0 -> ~1.18.3 express: ~4.11.2 -> ~4.16.4 jison: 0.4.17 -> 0.4.18 moment: ~2.19.4 -> ~2.22.2 From bb67fe440d764f8ea648760b453c012b7e419f9f Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Thu, 8 Nov 2018 12:02:44 +0100 Subject: [PATCH 5/9] use cbHost if present in device/deviceGroup --- lib/services/devices/deviceService.js | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/lib/services/devices/deviceService.js b/lib/services/devices/deviceService.js index a9a181e41..fddb64cb0 100644 --- a/lib/services/devices/deviceService.js +++ b/lib/services/devices/deviceService.js @@ -282,6 +282,10 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) { } }; + if (deviceData.cbHost) { + options.url = deviceData.cbHost + '/v2/entities?options=upsert'; + } + jsonConcat(options.json, formatAttributesNgsi2(deviceData.active, false)); jsonConcat(options.json, formatAttributesNgsi2(deviceData.staticAttributes, true)); jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands)); @@ -425,6 +429,10 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) { } }; + if (deviceData.cbHost) { + options.url = deviceData.cbHost + '/v2/entities/' + String(deviceData.name) + '/attrs'; + } + jsonConcat(options.json, formatAttributesNgsi2(deviceData.active, false)); jsonConcat(options.json, formatAttributesNgsi2(deviceData.staticAttributes, true)); jsonConcat(options.json, formatCommandsNgsi2(deviceData.commands)); From ca8f85036f2f5577b2903f784da5f3f659688340 Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Thu, 8 Nov 2018 12:12:11 +0100 Subject: [PATCH 6/9] use cbHost --- lib/services/devices/registrationUtils.js | 4 +++- lib/services/ngsi/subscriptionService.js | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/services/devices/registrationUtils.js b/lib/services/devices/registrationUtils.js index 6fd3d808b..836250d1f 100644 --- a/lib/services/devices/registrationUtils.js +++ b/lib/services/devices/registrationUtils.js @@ -215,7 +215,9 @@ function sendUnregistrationsNgsi2(deviceData, callback) { 'fiware-servicepath': deviceData.subservice } }; - + if (deviceData.cbHost) { + options.url = deviceData.cbHost + '/v2/registrations/' + deviceData.registrationId; + } if (deviceData.registrationId) { logger.debug(context, 'Sending device unregistrations to Context Broker at [%s]', options.url); logger.debug(context, 'Using the following request:\n\n%s\n\n', JSON.stringify(options, null, 4)); diff --git a/lib/services/ngsi/subscriptionService.js b/lib/services/ngsi/subscriptionService.js index 616958ecb..6c01498d4 100644 --- a/lib/services/ngsi/subscriptionService.js +++ b/lib/services/ngsi/subscriptionService.js @@ -179,7 +179,9 @@ function subscribeNgsi1(device, triggers, content, callback) { store = false; } - if (device.cbHost) { + if (device.cbHost && device.cbHost.indexOf('://') !== -1) { + options.uri = device.cbHost + '/v1/subscribeContext'; + } else if (device.cbHost && device.cbHost.indexOf('://') === -1) { options.uri = 'http://' + device.cbHost + '/v1/subscribeContext'; } else { options.uri = config.getConfig().contextBroker.url + '/v1/subscribeContext'; @@ -239,7 +241,9 @@ function subscribeNgsi2(device, triggers, content, callback) { store = false; } - if (device.cbHost) { + if (device.cbHost && device.cbHost.indexOf('://') !== -1) { + options.uri = device.cbHost + '/v2/subscriptions'; + } else if (device.cbHost && device.cbHost.indexOf('://') === -1) { options.uri = 'http://' + device.cbHost + '/v2/subscriptions'; } else { options.uri = config.getConfig().contextBroker.url + '/v2/subscriptions'; From 7c86e27791774f2d04e61c63477c109541eb9562 Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Thu, 8 Nov 2018 12:19:23 +0100 Subject: [PATCH 7/9] check and complete cbHost uri --- lib/services/devices/deviceService.js | 8 ++++++-- lib/services/devices/registrationUtils.js | 4 +++- 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/lib/services/devices/deviceService.js b/lib/services/devices/deviceService.js index fddb64cb0..0c0b223a5 100644 --- a/lib/services/devices/deviceService.js +++ b/lib/services/devices/deviceService.js @@ -282,8 +282,10 @@ function createInitialEntityNgsi2(deviceData, newDevice, callback) { } }; - if (deviceData.cbHost) { + if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { options.url = deviceData.cbHost + '/v2/entities?options=upsert'; + } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { + options.url = 'http://' + deviceData.cbHost + '/v2/entities?options=upsert'; } jsonConcat(options.json, formatAttributesNgsi2(deviceData.active, false)); @@ -429,8 +431,10 @@ function updateEntityNgsi2(deviceData, updatedDevice, callback) { } }; - if (deviceData.cbHost) { + if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { options.url = deviceData.cbHost + '/v2/entities/' + String(deviceData.name) + '/attrs'; + } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { + options.url = 'http://' + deviceData.cbHost + '/v2/entities/' + String(deviceData.name) + '/attrs'; } jsonConcat(options.json, formatAttributesNgsi2(deviceData.active, false)); diff --git a/lib/services/devices/registrationUtils.js b/lib/services/devices/registrationUtils.js index 836250d1f..af3cd429b 100644 --- a/lib/services/devices/registrationUtils.js +++ b/lib/services/devices/registrationUtils.js @@ -215,8 +215,10 @@ function sendUnregistrationsNgsi2(deviceData, callback) { 'fiware-servicepath': deviceData.subservice } }; - if (deviceData.cbHost) { + if (deviceData.cbHost && deviceData.cbHost.indexOf('://') !== -1) { options.url = deviceData.cbHost + '/v2/registrations/' + deviceData.registrationId; + } else if (deviceData.cbHost && deviceData.cbHost.indexOf('://') === -1) { + options.url = 'http://' + deviceData.cbHost + '/v2/registrations/' + deviceData.registrationId; } if (deviceData.registrationId) { logger.debug(context, 'Sending device unregistrations to Context Broker at [%s]', options.url); From cf202c5b8fa68565615c56e58db51371cdb7312d Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Thu, 8 Nov 2018 15:33:42 +0100 Subject: [PATCH 8/9] check if cbHost is an url --- lib/services/ngsi/ngsiService.js | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/lib/services/ngsi/ngsiService.js b/lib/services/ngsi/ngsiService.js index c34b747cf..a2e2d30dd 100644 --- a/lib/services/ngsi/ngsiService.js +++ b/lib/services/ngsi/ngsiService.js @@ -215,8 +215,10 @@ function createRequestObject(url, typeInformation, token) { serviceContext.subservice = typeInformation.subservice; } - if (typeInformation.cbHost) { + if (typeInformation.cbHost && typeInformation.cbHost.indexOf('://') !== -1) { cbHost = typeInformation.cbHost; + } else if (typeInformation.cbHost && typeInformation.cbHost.indexOf('://') === -1) { + cbHost = 'http://' + typeInformation.cbHost; } } From eb3dd3f9b793d85d472331034f263e5fcadaccf9 Mon Sep 17 00:00:00 2001 From: Alvaro Vega <alvaro.vegagarcia@telefonica.com> Date: Tue, 20 Nov 2018 11:21:02 +0100 Subject: [PATCH 9/9] add a tests to use ngsiv2 --- .../general/iotam-autoregistration-test.js | 377 ++++++++++++++++++ 1 file changed, 377 insertions(+) create mode 100644 test/unit/ngsiv2/general/iotam-autoregistration-test.js diff --git a/test/unit/ngsiv2/general/iotam-autoregistration-test.js b/test/unit/ngsiv2/general/iotam-autoregistration-test.js new file mode 100644 index 000000000..2012bed4f --- /dev/null +++ b/test/unit/ngsiv2/general/iotam-autoregistration-test.js @@ -0,0 +1,377 @@ +/* + * Copyright 2015 Telefonica Investigación y Desarrollo, S.A.U + * + * This file is part of fiware-iotagent-lib + * + * fiware-iotagent-lib is free software: you can redistribute it and/or + * modify it under the terms of the GNU Affero General Public License as + * published by the Free Software Foundation, either version 3 of the License, + * or (at your option) any later version. + * + * fiware-iotagent-lib is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. + * See the GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public + * License along with fiware-iotagent-lib. + * If not, seehttp://www.gnu.org/licenses/. + * + * For those usages not covered by the GNU Affero General Public License + * please contact with::[contacto@tid.es] + */ +'use strict'; + +/* jshint camelcase: false */ + +var iotAgentLib = require('../../../../lib/fiware-iotagent-lib'), + request = require('request'), + nock = require('nock'), + utils = require('../../../tools/utils'), + groupRegistryMemory = require('../../../../lib/services/groups/groupRegistryMemory'), + should = require('should'), + iotAgentConfig = { + logLevel: 'FATAL', + contextBroker: { + host: '192.168.1.1', + port: '1026', + ngsiVersion: 'v2' + }, + server: { + port: 4041 + }, + types: { + 'Light': { + commands: [], + type: 'Light', + lazy: [ + { + name: 'temperature', + type: 'centigrades' + } + ], + attributes: [ + { + name: 'pressure', + type: 'Hgmm' + } + ] + } + }, + providerUrl: 'http://smartGondor.com', + deviceRegistrationDuration: 'P1M', + throttling: 'PT5S', + iotManager: { + host: 'mockediotam.com', + port: 9876, + path: '/protocols', + protocol: 'GENERIC_PROTOCOL', + description: 'A generic protocol', + agentPath: '/iot' + }, + defaultResource: '/iot/d' + }, + groupCreation = { + service: 'theService', + subservice: 'theSubService', + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] + }, + optionsCreation = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + lazy: [ + { + name: 'luminescence', + type: 'Lumens' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] + } + ] + }, + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + } + }, + optionsCreationStatic = { + url: 'http://localhost:4041/iot/services', + method: 'POST', + json: { + services: [ + { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732', + entity_type: 'SensorMachine', + trust: '8970A9078A803H3BL98PINEQRW8342HBAMS', + cbHost: 'http://unexistentHost:1026', + commands: [ + { + name: 'wheel1', + type: 'Wheel' + } + ], + static_attributes: [ + { + name: 'position', + type: 'location', + values: '123,12' + } + ], + attributes: [ + { + name: 'status', + type: 'Boolean' + } + ] + } + ] + }, + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + } + }, + optionsDelete = { + url: 'http://localhost:4041/iot/services', + method: 'DELETE', + json: {}, + headers: { + 'fiware-service': 'theService', + 'fiware-servicepath': 'theSubService' + }, + qs: { + resource: '/deviceTest', + apikey: '801230BJKL23Y9090DSFL123HJK09H324HV8732' + } + }, + iotamMock; + +describe('IoT Manager autoregistration', function() { + describe('When the IoT Agent is started without a "iotManager" config parameter and empty services', function() { + beforeEach(function() { + nock.cleanAll(); + + iotamMock = nock('http://mockediotam.com:9876') + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + }); + + afterEach(function(done) { + iotAgentLib.deactivate(done); + }); + + it('should register itself to the provided IoT Manager URL', function(done) { + iotAgentLib.activate(iotAgentConfig, function(error) { + should.not.exist(error); + iotamMock.done(); + done(); + }); + }); + }); + + describe('When the IoT Agents is started with "iotManager" config with missing attributes', function() { + beforeEach(function() { + nock.cleanAll(); + + delete iotAgentConfig.providerUrl; + + iotamMock = nock('http://mockediotam.com:9876') + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + }); + + afterEach(function() { + iotAgentConfig.providerUrl = 'http://smartGondor.com'; + }); + + it('should fail with a MISSING_CONFIG_PARAMS error', function(done) { + iotAgentLib.activate(iotAgentConfig, function(error) { + should.exist(error); + error.name.should.equal('MISSING_CONFIG_PARAMS'); + done(); + }); + }); + }); + + describe('When the IoT Agents is started with "iotManager" config and multiple services', function() { + beforeEach(function(done) { + nock.cleanAll(); + + iotamMock = nock('http://mockediotam.com:9876') + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + groupRegistryMemory.create(groupCreation, done); + }); + + afterEach(function(done) { + groupRegistryMemory.clear(function() { + iotAgentLib.deactivate(done); + }); + }); + + it('should send all the service information to the IoT Manager in the registration', function(done) { + iotAgentLib.activate(iotAgentConfig, function(error) { + should.not.exist(error); + iotamMock.done(); + done(); + }); + }); + }); + + describe('When a new service is created in the IoT Agent', function() { + beforeEach(function(done) { + nock.cleanAll(); + + iotamMock = nock('http://mockediotam.com:9876') + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + iotamMock + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + iotAgentLib.activate(iotAgentConfig, function(error) { + done(); + }); + }); + + afterEach(function(done) { + groupRegistryMemory.clear(function() { + iotAgentLib.deactivate(done); + }); + }); + + it('should update the registration in the IoT Manager', function(done) { + request(optionsCreation, function(error, result, body) { + should.not.exist(error); + iotamMock.done(); + done(); + }); + }); + }); + + describe('When a service is removed from the IoT Agent', function() { + beforeEach(function(done) { + nock.cleanAll(); + + iotamMock = nock('http://mockediotam.com:9876') + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithGroups.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + iotamMock + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + groupRegistryMemory.create(groupCreation, function() { + iotAgentLib.activate(iotAgentConfig, done); + }); + }); + + afterEach(function(done) { + groupRegistryMemory.clear(function() { + iotAgentLib.deactivate(done); + }); + }); + + it('should update the registration in the IoT Manager', function(done) { + request(optionsDelete, function(error, result, body) { + should.not.exist(error); + iotamMock.done(); + done(); + }); + }); + }); + + describe('When a new service with static attributes is created in the IoT Agent', function() { + beforeEach(function(done) { + nock.cleanAll(); + + iotamMock = nock('http://mockediotam.com:9876') + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationEmpty.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + iotamMock + .post('/protocols', + utils.readExampleFile('./test/unit/examples/iotamRequests/registrationWithStaticGroups.json')) + .reply(200, + utils.readExampleFile('./test/unit/examples/iotamResponses/registrationSuccess.json')); + + iotAgentLib.activate(iotAgentConfig, function(error) { + done(); + }); + }); + + afterEach(function(done) { + groupRegistryMemory.clear(function() { + iotAgentLib.deactivate(done); + }); + }); + + it('should update the registration in the IoT Manager', function(done) { + request(optionsCreationStatic, function(error, result, body) { + should.not.exist(error); + iotamMock.done(); + done(); + }); + }); + }); +});