Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 2 additions & 1 deletion CHANGES_NEXT_RELEASE
Original file line number Diff line number Diff line change
@@ -1 +1,2 @@
- ADD: add locale string number jexl function (#1737)
- FIX: do not pass auth options to mongoose init, because is redundant (#1741)
- ADD: add locale string number jexl function (#1737)
59 changes: 31 additions & 28 deletions lib/model/dbConn.js
Original file line number Diff line number Diff line change
Expand Up @@ -49,34 +49,41 @@ function loadModels() {
*
* @this Reference to the dbConn module itself.
*/

function init(host, db, port, options, callback) {
function init(host, db, port, mongoConfig, options, callback) {
let url;
let retries = 0;
let lastError;
const maxRetries = config.getConfig().mongodb?.retries || constants.DEFAULT_MONGODB_RETRIES;
const maxRetries = mongoConfig.retries || constants.DEFAULT_MONGODB_RETRIES;

function addPort(item) {
return `${item}:${port}`;
}

url = 'mongodb://';
// Build URL for connection
const hosts = host.split(',').map(addPort).join(',');
let authPart = '';

if (options.auth) {
url += `${encodeURIComponent(options.auth.user)}:${encodeURIComponent(options.auth.password)}@`;
if (mongoConfig.user && mongoConfig.password) {
authPart = `${encodeURIComponent(mongoConfig.user)}:${encodeURIComponent(mongoConfig.password)}@`;
}

const hosts = host.split(',').map(addPort).join(',');
url += `${hosts}/${db}`;
url = `mongodb://${authPart}${hosts}/${db}`;

if (options.extraArgs) {
const query = new URLSearchParams(options.extraArgs).toString();
if (query) {
url += `?${query}`;
}
delete options.extraArgs;
// Extra params (authSource, replicaSet, ssl )
const extraArgs = {
authSource: mongoConfig.authSource,
...options.extraArgs
};

const query = new URLSearchParams(Object.entries(extraArgs).filter(([, v]) => v !== undefined)).toString();

if (query) {
url += `?${query}`;
}

// Delete extraArgs for mongoose.connect
delete options.extraArgs;

function connectionAttempt(callback) {
logger.info(context, `Attempting to connect to MongoDB at ${url}. Attempt ${retries + 1}`);

Expand All @@ -91,8 +98,7 @@ function init(host, db, port, options, callback) {
lastError = error;
alarms.raise(constants.MONGO_ALARM, error);
});
/* eslint-disable-next-line no-unused-vars */
defaultDb.on('connecting', function (error) {
defaultDb.on('connecting', function () {
logger.debug(context, 'Mongo Driver connecting');
});
defaultDb.on('connected', function () {
Expand All @@ -117,14 +123,15 @@ function init(host, db, port, options, callback) {
defaultDb.on('close', function () {
logger.debug(context, 'Mongo Driver close');
});

callback();
})
.catch((err) => {
logger.error(context, `MONGODB-001: Error trying to connect to MongoDB: ${err}`);
lastError = err;
retries++;
if (retries < maxRetries) {
const retryTime = config.getConfig().mongodb?.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME;
const retryTime = mongoConfig.retryTime || constants.DEFAULT_MONGODB_RETRY_TIME;
logger.info(context, `Retrying in ${retryTime} seconds...`);
setTimeout(() => connectionAttempt(callback), retryTime * 1000);
} else {
Expand All @@ -144,33 +151,29 @@ function init(host, db, port, options, callback) {

function configureDb(callback) {
const currentConfig = config.getConfig();

if (currentConfig.deviceRegistry?.type === 'mongodb') {
if (!currentConfig.mongodb?.host) {
logger.fatal(context, 'MONGODB-003: No host found for MongoDB driver.');
callback(new errors.BadConfiguration('No host found for MongoDB driver'));
} else {
const dbName = currentConfig.mongodb.db || DEFAULT_DB_NAME;
const port = currentConfig.mongodb.port || 27017;

const options = {};

if (currentConfig.mongodb.replicaSet) options.replicaSet = currentConfig.mongodb.replicaSet;
if (currentConfig.mongodb.ssl) options.ssl = currentConfig.mongodb.ssl;
if (currentConfig.mongodb.extraArgs) options.extraArgs = currentConfig.mongodb.extraArgs;

if (currentConfig.mongodb.user && currentConfig.mongodb.password) {
options.auth = {
user: currentConfig.mongodb.user,
password: currentConfig.mongodb.password
if (currentConfig.mongodb.authSource) {
options.extraArgs = {
...options.extraArgs,
authSource: currentConfig.mongodb.authSource
};
if (currentConfig.mongodb.authSource) {
options.extraArgs = {
...options.extraArgs,
authSource: currentConfig.mongodb.authSource
};
}
}

init(currentConfig.mongodb.host, dbName, port, options, callback);
init(currentConfig.mongodb.host, dbName, port, currentConfig.mongodb, options, callback);
}
} else {
callback();
Expand Down
78 changes: 33 additions & 45 deletions test/unit/mongodb/mongodb-connectionoptions-test.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@ const config = require('../../../lib/commonConfig');
const mongoose = require('mongoose');
const sinon = require('sinon');
const should = require('should');

const iotAgentConfig = {
logLevel: 'FATAL',
contextBroker: {
Expand All @@ -50,6 +51,7 @@ const iotAgentConfig = {
providerUrl: 'http://smartgondor.com',
deviceRegistrationDuration: 'P1M'
};

let oldConfig;

describe('dbConn.configureDb', function () {
Expand All @@ -66,16 +68,15 @@ describe('dbConn.configureDb', function () {
}
});

describe('When set mongodb options, it should call mongoose.createCOnnection by using below params', function () {
describe('When set mongodb options, it should call mongoose.connect using expected params', function () {
const tests = [
{
mongodb: {
host: 'example.com'
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -85,8 +86,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:98765/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -96,8 +96,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/examples',
options: {
}
options: {}
}
},
{
Expand All @@ -119,8 +118,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -130,8 +128,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -142,12 +139,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://user01:[email protected]:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
auth: {
user: 'user01',
password: 'pass01'
}
}
options: {}
}
},
{
Expand All @@ -156,9 +148,8 @@ describe('dbConn.configureDb', function () {
authSource: 'admin'
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME + '?authSource=admin',
options: {}
}
},
{
Expand All @@ -174,11 +165,7 @@ describe('dbConn.configureDb', function () {
expected: {
url: 'mongodb://user01:[email protected]:98765/examples?authSource=admin',
options: {
replicaSet: 'rs0',
auth: {
user: 'user01',
password: 'pass01'
}
replicaSet: 'rs0'
}
}
},
Expand All @@ -203,8 +190,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME + '?retryWrites=true',
options: {
}
options: {}
}
},
{
Expand All @@ -220,8 +206,7 @@ describe('dbConn.configureDb', function () {
'mongodb://example.com:27017/' +
dbConn.DEFAULT_DB_NAME +
'?retryWrites=true&readPreference=nearest',
options: {
}
options: {}
}
},
{
Expand All @@ -231,8 +216,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -242,8 +226,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -253,8 +236,7 @@ describe('dbConn.configureDb', function () {
},
expected: {
url: 'mongodb://example.com:27017/' + dbConn.DEFAULT_DB_NAME,
options: {
}
options: {}
}
},
{
Expand All @@ -275,18 +257,17 @@ describe('dbConn.configureDb', function () {
unknownparam: 'unknown'
},
expected: {
url: 'mongodb://user01:[email protected]:98765/examples?retryWrites=true&readPreference=nearest&w=majority&authSource=admin',
url:
'mongodb://user01:[email protected]:98765/examples?' +
'authSource=admin&retryWrites=true&readPreference=nearest&w=majority',
options: {
replicaSet: 'rs0',
auth: {
user: 'user01',
password: 'pass01'
},
ssl: true
}
}
}
];

tests.forEach(function (params) {
it(
'mongodb options = ' +
Expand All @@ -298,23 +279,26 @@ describe('dbConn.configureDb', function () {
const cfg = Object.assign({}, iotAgentConfig, {
mongodb: params.mongodb
});

stub = sinon.stub(mongoose, 'connect').callsFake(function (url, options, fn) {
url.should.be.equal(params.expected.url);
options.should.be.eql(params.expected.options);
done();
});

config.setConfig(cfg);

dbConn.configureDb(function (error) {
if (error) {
should.fail();
should.fail('configureDb returned an unexpected error');
}
});
}
);
});
});

describe('When no mongodb options or "host" is empty, it should returns an error callback', function () {
describe('When no mongodb options or "host" is empty, it should return an error callback', function () {
const tests = [
{
mongodb: undefined
Expand All @@ -328,18 +312,22 @@ describe('dbConn.configureDb', function () {
}
}
];

tests.forEach(function (params) {
it('mongodb options = ' + JSON.stringify(params.mongodb), function (done) {
const cfg = Object.assign({}, iotAgentConfig, {
mongodb: params.mongodb
});
stub = sinon.stub(mongoose, 'connect').callsFake(function (url, options, fn) {
should.fail();

stub = sinon.stub(mongoose, 'connect').callsFake(() => {
should.fail('mongoose.connect should not be called');
});

config.setConfig(cfg);

dbConn.configureDb(function (error) {
if (!error) {
should.fail();
should.fail('Expected error when MongoDB host is missing');
}
done();
});
Expand Down