• Home
  • Features
  • Pricing
  • Docs
  • Announcements
  • Sign In

telefonicaid / fiware-sth-comet / 9171759696

21 May 2024 08:50AM UTC coverage: 81.86% (-0.05%) from 81.909%
9171759696

push

github

web-flow
Merge pull request #637 from telefonicaid/dependabot/pip/test/acceptance/requests-2.32.0

Bump requests from 2.31.0 to 2.32.0 in /test/acceptance

1235 of 1626 branches covered (75.95%)

Branch coverage included in aggregate %.

2127 of 2481 relevant lines covered (85.73%)

141.79 hits per line

Source File
Press 'n' to go to next uncovered line, 'b' for previous

82.65
/lib/database/model/sthDatabaseNameMapperTool.js
1
/*
2
 * Copyright 2016 Telefónica Investigación y Desarrollo, S.A.U
3
 *
4
 * This file is part of the Short Time Historic (STH) component
5
 *
6
 * STH is free software: you can redistribute it and/or
7
 * modify it under the terms of the GNU Affero General Public License as
8
 * published by the Free Software Foundation, either version 3 of the License,
9
 * or (at your option) any later version.
10
 *
11
 * STH is distributed in the hope that it will be useful,
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
14
 * See the GNU Affero General Public License for more details.
15
 *
16
 * You should have received a copy of the GNU Affero General Public
17
 * License along with STH.
18
 * If not, see http://www.gnu.org/licenses/.
19
 *
20
 * For those usages not covered by the GNU Affero General Public License
21
 * please contact with: [german.torodelvalle@telefonica.com]
22
 */
23

24
/* eslint-disable consistent-return */
25

26
const ROOT_PATH = require('app-root-path');
1✔
27
const async = require('async');
1✔
28
const sthLogger = require('logops');
1✔
29
const sthConfig = require(ROOT_PATH + '/lib/configuration/sthConfiguration');
1✔
30
const sthDatabase = require(ROOT_PATH + '/lib/database/sthDatabase');
1✔
31
const sthDatabaseNameMapper = require(ROOT_PATH + '/lib/database/model/sthDatabaseNameMapper');
1✔
32
const sthDatabaseNaming = require(ROOT_PATH + '/lib/database/model/sthDatabaseNaming');
1✔
33
const sthErrors = require(ROOT_PATH + '/lib/errors/sthErrors');
1✔
34

35
let analysisResult = {};
1✔
36

37
/**
38
 * Resets the analysis report
39
 */
40
function resetAnalysisResult(callback) {
1✔
41
    analysisResult = {};
18✔
42
    return process.nextTick(callback);
18✔
43
}
44

45
/**
46
 * Returns asynchronously the list of databases associated to a STH instance
47
 * @param  {Object}   connection The database associated to the STH instance
48
 * @param  {Function} callback   The callback accepting a possible error as its first param and the list of databases
49
 *                               as the second one
50
 */
51
function listDatabases(connection, callback) {
1✔
52
    const adminDB = connection.admin();
18✔
53
    adminDB.listDatabases(callback);
18✔
54
}
55

56
/**
57
 * Filters the databases associated to a STH instance
58
 * @param {Object}    options      An object including the following properties:
59
 *                                 - {Boolean} map        Flag indicating if the request is about a mapping
60
 *                                 process
61
 *                                 - {Boolean} unmap      Flag indicating if the request is about an unmapping
62
 *                                 process
63
 *                                 - {String}  database   The database name to restrict the analysis to
64
 *                                 - {String}  collection The collection name to restrict the analysis to
65
 * @param  {Object}   databaseData The database data
66
 * @param  {Function} callback     The callback
67
 */
68
function databaseFilter(options, databaseData, callback) {
1✔
69
    callback(
75✔
70
        null,
71
        databaseData.name.indexOf(sthConfig.DB_PREFIX) === 0 &&
130✔
72
            (!options.database || (options.database && options.database === databaseData.name))
73
    );
74
}
75

76
/**
77
 * Filters the databases to only consider the ones associated to a STH instance
78
 * @param {Object}    options       An object including the following properties:
79
 *                                  - {Boolean} map        Flag indicating if the request is about a mapping
80
 *                                  process
81
 *                                  - {Boolean} unmap      Flag indicating if the request is about an unmapping
82
 *                                  process
83
 *                                  - {String}  database   The database name to restrict the analysis to
84
 *                                  - {String}  collection The collection name to restrict the analysis to
85
 * @param  {Object}   databasesData Data about the databases to filter
86
 * @param  {Function} callback      The callback
87
 */
88
function filterDatabases(options, databasesData, callback) {
1✔
89
    async.filter(databasesData.databases, async.apply(databaseFilter, options), callback);
18✔
90
}
91

92
/**
93
 * Includes the associated database name to some collection database
94
 * @param {String}   databaseName   The database name
95
 * @param {Object}   collectionData The collection database
96
 * @param {Function} callback       The callback
97
 */
98
function addDatabaseName(databaseName, collectionData, callback) {
1✔
99
    collectionData.database = databaseName;
28✔
100
    return callback(null, collectionData);
28✔
101
}
102

103
/**
104
 * Lists the collections in certain databaseName
105
 * @param  {String}   databaseName The database name
106
 * @param  {Function} callback     The callback
107
 */
108
function listCollections(databaseName, callback) {
1✔
109
    sthDatabase.client
14✔
110
        .db(databaseName)
111
        .listCollections()
112
        .toArray(function(err, collections) {
113
            if (collections) {
14!
114
                async.map(collections, async.apply(addDatabaseName, databaseName), callback);
14✔
115
            }
116
        });
117
}
118

119
/**
120
 * Filters a collection from its database
121
 * @param {Object}    options        An object including the following properties:
122
 *                                   - {Boolean} map        Flag indicating if the request is about a mapping
123
 *                                   process
124
 *                                   - {Boolean} unmap      Flag indicating if the request is about an unmapping
125
 *                                   process
126
 *                                   - {String}  database   The database name to restrict the analysis to
127
 *                                   - {String}  collection The collection name to restrict the analysis to
128
 * @param  {Object}   collectionData The collection database
129
 * @param  {Function} callback       The callback
130
 */
131
function collectionFilter(options, collectionData, callback) {
1✔
132
    return callback(
28✔
133
        null,
134
        collectionData.name.indexOf(sthConfig.COLLECTION_PREFIX) === 0 &&
88✔
135
            (!options.collection || (options.collection && options.collection === collectionData.name))
136
    );
137
}
138

139
/**
140
 * Filters the collections included in some collections database
141
 * @param {Object}    options         An object including the following properties:
142
 *                                    - {Boolean} map        Flag indicating if the request is about a mapping
143
 *                                    process
144
 *                                    - {Boolean} unmap      Flag indicating if the request is about an unmapping
145
 *                                    process
146
 *                                    - {String}  database   The database name to restrict the analysis to
147
 *                                    - {String}  collection The collection name to restrict the analysis to
148
 * @param  {Object}   collectionsData The collections database
149
 * @param  {Function} callback        The callback
150
 */
151
function filterCollections(options, collectionsData, callback) {
1✔
152
    async.filter(collectionsData, async.apply(collectionFilter, options), callback);
14✔
153
}
154

155
/**
156
 * Analyses a collection from its associated data
157
 * @param {Object}    options        An object including the following properties:
158
 *                                   - {Boolean} map        Flag indicating if the request is about a mapping
159
 *                                   process
160
 *                                   - {Boolean} unmap     Flag indicating if the request is about an unmapping
161
 *                                   process
162
 *                                   - {String}  database   The database name to restrict the analysis to
163
 *                                   - {String}  collection The collection name to restrict the analysis to
164
 * @param  {Object}   collectionData The collection data
165
 * @param  {Function} callback       The callback
166
 */
167
function analyseCollection(options, collectionData, callback) {
1✔
168
    analysisResult[collectionData.database].collections = analysisResult[collectionData.database].collections || {};
16✔
169
    analysisResult[collectionData.database].collections[collectionData.name] = {
16✔
170
        name: options.map
16✔
171
            ? sthDatabaseNameMapper.mapCollectionName(
172
                  collectionData.database.substring(sthConfig.DB_PREFIX.length),
173
                  collectionData.name
174
              )
175
            : sthDatabaseNameMapper.unmapCollectionName(
176
                  collectionData.database.substring(sthConfig.DB_PREFIX.length),
177
                  collectionData.name
178
              )
179
    };
180
    process.nextTick(callback);
16✔
181
}
182

183
/**
184
 * Effectively analyses a group of collection from its associated data
185
 * @param {Object}    options         An object including the following properties:
186
 *                                    - {Boolean} map     Flag indicating if the request is about a mapping
187
 *                                    process
188
 *                                    - {Boolean} unmap     Flag indicating if the request is about an unmapping
189
 *                                    process
190
 *                                    - {String}  database   The database name to restrict the analysis to
191
 *                                    - {String}  collection The collection name to restrict the analysis to
192
 * @param  {Object}   collectionsData The collections database
193
 * @param  {Function} callback        The callback
194
 */
195
function doAnalyseCollections(options, collectionsData, callback) {
1✔
196
    async.each(collectionsData, async.apply(analyseCollection, options), callback);
14✔
197
}
198

199
/**
200
 * Analyses the collections in certain database
201
 * @param {Object}    options      An object including the following properties:
202
 *                                 - {Boolean} map     Flag indicating if the request is about a mapping
203
 *                                 process
204
 *                                 - {Boolean} unmap     Flag indicating if the request is about an unmapping
205
 *                                 process
206
 *                                 - {String}  database   The database name to restrict the analysis to
207
 *                                 - {String}  collection The collection name to restrict the analysis to
208
 * @param  {String}   databaseName The database name
209
 * @param  {Function} callback     The callback
210
 */
211
function analyseCollections(options, databaseName, callback) {
1✔
212
    async.seq(
14✔
213
        async.apply(listCollections, databaseName),
214
        async.apply(filterCollections, options),
215
        async.apply(doAnalyseCollections, options)
216
    )(callback);
217
}
218

219
/**
220
 * Analyses database data to generate the mapping/unmapping report for this database
221
 * @param {Object}    options      An object including the following properties:
222
 *                                 - {Boolean} map        Flag indicating if the request is about a mapping
223
 *                                 process
224
 *                                 - {Boolean} unmap      Flag indicating if the request is about an unmapping
225
 *                                 process
226
 *                                 - {String}  database   The database name to restrict the analysis to
227
 *                                 - {String}  collection The collection name to restrict the analysis to
228
 * @param  {Object}   databaseData The database data
229
 * @param  {Function} callback     The callback
230
 */
231
function analyseDatabase(options, databaseData, callback) {
1✔
232
    analysisResult[databaseData.name] = {
14✔
233
        name: options.map
14✔
234
            ? sthDatabaseNameMapper.mapDatabaseName(databaseData.name)
235
            : sthDatabaseNameMapper.unmapDatabaseName(databaseData.name)
236
    };
237
    analyseCollections(options, databaseData.name, callback);
14✔
238
}
239

240
/**
241
 * Analyses a group of database data to generate a new mapping/unmapping report
242
 * @param {Object}    options       An object including the following properties:
243
 *                                  - {Boolean} map        Flag indicating if the request is about a mapping
244
 *                                  process
245
 *                                  - {Boolean} unmap     Flag indicating if the request is about an unmapping
246
 *                                  process
247
 *                                  - {String}  database   The database name to restrict the analysis to
248
 *                                  - {String}  collection The collection name to restrict the analysis to
249
 * @param  {Object}   databasesData The databases data
250
 * @param  {Function} callback      The callback
251
 */
252
function analyseDatabases(options, databasesData, callback) {
1✔
253
    async.each(databasesData, async.apply(analyseDatabase, options), callback);
18✔
254
}
255

256
/**
257
 * Removes from the mapping analysis information about collections and databases whose names do not change after the
258
 * mapping or unmapping
259
 * @param  {Function} callback The callback
260
 */
261
function cleanAnalysis(callback) {
1✔
262
    const databaseNames = Object.getOwnPropertyNames(analysisResult);
18✔
263
    databaseNames.forEach(function(databaseName) {
18✔
264
        if (analysisResult[databaseName].collections) {
14✔
265
            const collectionNames = Object.getOwnPropertyNames(analysisResult[databaseName].collections);
10✔
266
            collectionNames.forEach(function(collectionName) {
10✔
267
                if (collectionName === analysisResult[databaseName].collections[collectionName].name) {
16✔
268
                    delete analysisResult[databaseName].collections[collectionName];
8✔
269
                }
270
            });
271
            if (Object.keys(analysisResult[databaseName].collections).length === 0) {
10✔
272
                delete analysisResult[databaseName].collections;
6✔
273
                if (databaseName === analysisResult[databaseName].name) {
6!
274
                    delete analysisResult[databaseName];
6✔
275
                }
276
            }
277
        } else if (databaseName === analysisResult[databaseName].name) {
4✔
278
            delete analysisResult[databaseName];
2✔
279
        }
280
    });
281
    process.nextTick(callback.bind(null, null, analysisResult));
18✔
282
}
283

284
/**
285
 * Shows the mapping report
286
 * @param {Object}   options  An object including the following properties:
287
 *                            - {Boolean} map        Flag indicating if the request is about a mapping process
288
 *                            - {Boolean} unmap      Flag indicating if the request is about an unmapping process
289
 *                            - {String}  database   The database name to restrict the analysis to
290
 *                            - {String}  collection The collection name to restrict the analysis to
291
 * @param {Function} callback A callback function accepting a possible error as the first parameter and the result
292
 *                            returned by the last function of the sequence
293
 */
294
function getMappingAnalysis(options, callback) {
1✔
295
    if (!options.map && !options.unmap) {
22✔
296
        return process.nextTick(
4✔
297
            callback.bind(
298
                null,
299
                new sthErrors.MandatoryOptionNotFound('Either the -m (--map) or the -u (--unmap) options are mandatory')
300
            )
301
        );
302
    }
303
    if (options.collection && !options.database) {
18!
304
        return process.nextTick(
×
305
            callback.bind(
306
                null,
307
                new sthErrors.MandatoryOptionNotFound(
308
                    'The -b (--database) option is mandatory if the -c (--collection) option is set'
309
                )
310
            )
311
        );
312
    }
313
    async.seq(
18✔
314
        resetAnalysisResult,
315
        sthDatabase.connect.bind(null, {
316
            authentication: sthConfig.DB_AUTHENTICATION,
317
            dbURI: sthConfig.DB_URI,
318
            replicaSet: sthConfig.REPLICA_SET,
319
            database: sthDatabaseNaming.getDatabaseName(sthConfig.DEFAULT_SERVICE),
320
            poolSize: sthConfig.POOL_SIZE,
321
            authSource: sthConfig.DB_AUTH_SOURCE
322
        }),
323
        listDatabases,
324
        async.apply(filterDatabases, options),
325
        async.apply(analyseDatabases, options),
326
        cleanAnalysis
327
    )(callback);
328
}
329

330
/**
331
 * Maps or unmaps the name of certain collection in certain databaseName
332
 * @param {Object}    options        An object including the following properties:
333
 *                                   - {Boolean} map        Flag indicating if the request is about a mapping
334
 *                                   process
335
 *                                   - {Boolean} unmap      Flag indicating if the request is about an unmapping
336
 *                                   process
337
 *                                   - {String}  database   The database name to restrict the analysis to
338
 *                                   - {String}  collection The collection name to restrict the analysis to
339
 * @param  {String}   databaseName   The database name
340
 * @param  {String}   collectionName The collection name
341
 * @param  {Function} callback       The callback
342
 */
343
function mapOrUnmapCollection(options, databaseName, collectionName, callback) {
1✔
344
    sthLogger.info(
2✔
345
        sthConfig.LOGGING_CONTEXT.DB_LOG,
346
        // prettier-ignore
347
        (options.map ? 'Mapping' : 'Unmapping') + " of collection '" + collectionName + "' of database '" +
2!
348
            databaseName + "' started..."
349
    );
350

351
    sthDatabase.client
2✔
352
        .db(databaseName)
353
        .renameCollection(
354
            collectionName,
355
            options.map
2!
356
                ? sthDatabaseNameMapper.mapCollectionName(
357
                      databaseName.substring(sthConfig.DB_PREFIX.length),
358
                      collectionName
359
                  )
360
                : sthDatabaseNameMapper.unmapCollectionName(
361
                      databaseName.substring(sthConfig.DB_PREFIX.length),
362
                      collectionName
363
                  ),
364
            function(err) {
365
                if (err) {
2!
366
                    return process.nextTick(callback.bind(null, err));
×
367
                }
368
                sthLogger.info(
2✔
369
                    sthConfig.LOGGING_CONTEXT.DB_LOG,
370
                    // prettier-ignore
371
                    (options.map ? 'Mapping' : 'Unmapping') + " of collection '" + collectionName + "' of database '" +
2!
372
                        databaseName + "' successfully completed."
373
                );
374
                return process.nextTick(callback);
2✔
375
            }
376
        );
377
}
378

379
/**
380
 * Copies a database since this is the only way to rename it (the original database is removed afterwards)
381
 * @param {Object}    options      An object including the following properties:
382
 *                                 - {Boolean} map        Flag indicating if the request is about a mapping process
383
 *                                 - {Boolean} unmap      Flag indicating if the request is about an unmapping
384
 *                                 process
385
 *                                 - {String}  database   The database name to restrict the analysis to
386
 *                                 - {String}  collection The collection name to restrict the analysis to
387
 * @param  {String}   databaseName The database name
388
 * @param  {Function} callback     The callback
389
 */
390
// Alternative function without copydb command
391
function copyDatabase(options, databaseName, callback) {
1✔
392
    const adminDB = sthDatabase.connection.admin();
1✔
393
    const listCommand = {
1✔
394
        listCollections: 1,
395
        nameOnly: true
396
    };
397
    var sourceDB = databaseName;
1✔
398
    var targetDB = options.encode
1!
399
        ? sthDatabaseNameMapper.mapDatabaseName(databaseName)
400
        : sthDatabaseNameMapper.unmapDatabaseName(databaseName);
401

402
    const db = sthDatabase.client.db(databaseName);
1✔
403
    db.command(listCommand, function onListCollections(err, results) {
1✔
404
        if (err) {
1!
405
            return process.nextTick(callback.bind(null, err));
×
406
        }
407

408
        var arrayCollectionRenames = [];
1✔
409
        results.cursor.firstBatch.forEach((collection) => {
1✔
410
            var source = sourceDB + '.' + collection.name;
2✔
411
            var destination = targetDB + '.' + collection.name;
2✔
412

413
            let collectionData = { source: source, destination: destination, db: adminDB };
2✔
414
            arrayCollectionRenames.push(collectionData);
2✔
415
        });
416

417
        async.map(
1✔
418
            arrayCollectionRenames,
419
            function(element, callback) {
420
                element.db.command(
2✔
421
                    { renameCollection: element.source, to: element.destination, dropTarget: true },
422
                    function(err) {
423
                        callback(err);
2✔
424
                    }
425
                );
426
            },
427
            function(err) {
428
                if (err) {
1!
429
                    return process.nextTick(callback.bind(null, err));
×
430
                }
431
                sthLogger.info(
1✔
432
                    sthConfig.LOGGING_CONTEXT.DB_LOG,
433
                    (options.map ? 'Mapping' : 'Unmapping') +
1!
434
                        " of database '" +
435
                        databaseName +
436
                        "' successfully completed."
437
                );
438
                process.nextTick(callback);
1✔
439
            }
440
        );
441
    });
442
}
443

444
/**
445
 * Maps or unmaps the name of certain database and its collections
446
 * @param {Object}    options      An object including the following properties:
447
 *                                 - {Boolean} map        Flag indicating if the request is about a mapping process
448
 *                                 - {Boolean} unmap     Flag indicating if the request is about an unmapping
449
 *                                 process
450
 *                                 - {String}  database   The database name to restrict the analysis to
451
 *                                 - {String}  collection The collection name to restrict the analysis to
452
 * @param  {String}   databaseName The database name
453
 * @param  {Function} callback     The callback
454
 */
455
function mapOrUnmapDatabase(options, databaseName, callback) {
1✔
456
    sthLogger.info(
1✔
457
        sthConfig.LOGGING_CONTEXT.DB_LOG,
458
        (options.map ? 'Mapping' : 'Unmapping') + " of database '" + databaseName + "' started..."
1!
459
    );
460

461
    let collectionNames;
1✔
462
    if (
1!
463
        analysisResult[databaseName].collections &&
2✔
464
        Object.getOwnPropertyNames(analysisResult[databaseName].collections).length
465
    ) {
466
        collectionNames = Object.getOwnPropertyNames(analysisResult[databaseName].collections);
1✔
467
        async.eachSeries(
1✔
468
            collectionNames,
469
            async.apply(mapOrUnmapCollection, options, databaseName),
470
            function onMapOrUnmapCollection(err) {
471
                if (err) {
1!
472
                    return process.nextTick(callback.bind(null, err));
×
473
                }
474
                if (databaseName !== analysisResult[databaseName].name) {
1!
475
                    copyDatabase(options, databaseName, callback);
1✔
476
                } else {
477
                    sthLogger.info(
×
478
                        sthConfig.LOGGING_CONTEXT.DB_LOG,
479
                        // prettier-ignore
480
                        (options.map ? 'Mapping' : 'Unmapping') + " of database '" + databaseName +
×
481
                            ' successfully completed.'
482
                    );
483
                    process.nextTick(callback);
×
484
                }
485
            }
486
        );
487
    } else if (databaseName !== analysisResult[databaseName].name) {
×
488
        copyDatabase(options, databaseName, callback);
×
489
    } else {
490
        sthLogger.info(
×
491
            sthConfig.LOGGING_CONTEXT.DB_LOG,
492
            (options.map ? 'Mapping' : 'Unmapping') + " of database '" + databaseName + ' successfully completed.'
×
493
        );
494
        process.nextTick(callback);
×
495
    }
496
}
497

498
/**
499
 * Effectively maps or unmaps the name of the databases and collections included in certain mapping/unmapping
500
 * analysis
501
 * @param {Object}    options   An object including the following properties:
502
 *                              - {Boolean} map        Flag indicating if the request is about a mapping process
503
 *                              - {Boolean} unmap      Flag indicating if the request is about an unmapping process
504
 *                              - {String}  database   The database name to restrict the analysis to
505
 *                              - {String}  collection The collection name to restrict the analysis to
506
 * @param  {Object}   analysis The analysis
507
 * @param  {Function} callback The callback
508
 */
509
function doMapOrUnmap(options, analysis, callback) {
1✔
510
    const databaseNames = Object.getOwnPropertyNames(analysis);
6✔
511
    async.eachSeries(databaseNames, async.apply(mapOrUnmapDatabase, options), callback);
6✔
512
}
513

514
/**
515
 * Maps or unmaps the names of the databases and the collections included in certain mapping/unmapping analysis
516
 * @param {Object}   options  An object including the following properties:
517
 *                            - {Boolean} map        Flag indicating if the request is about a mapping process
518
 *                            - {Boolean} unmap      Flag indicating if the request is about an unmapping process
519
 *                            - {String}  database   The database name to restrict the analysis to
520
 *                            - {String}  collection The collection name to restrict the analysis to
521
 * @param  {Function} callback The callback
522
 */
523
function mapOrUnmap(options, callback) {
1✔
524
    if (!options.map && !options.unmap) {
10✔
525
        return process.nextTick(
4✔
526
            callback.bind(
527
                null,
528
                new sthErrors.MandatoryOptionNotFound('Either the -m (--map) or the -u (--unmap) options are mandatory')
529
            )
530
        );
531
    }
532
    if (options.collection && !options.database) {
6!
533
        return process.nextTick(
×
534
            callback.bind(
535
                null,
536
                new sthErrors.MandatoryOptionNotFound(
537
                    'The -b (--database) option is mandatory if the -c (--collection) option is set'
538
                )
539
            )
540
        );
541
    }
542

543
    sthLogger.info(sthConfig.LOGGING_CONTEXT.DB_LOG, (options.map ? 'Mapping' : 'Unmapping') + ' process started...');
6✔
544

545
    async.seq(async.apply(getMappingAnalysis, options), async.apply(doMapOrUnmap, options))(callback);
6✔
546
}
547

548
module.exports = {
1✔
549
    getMappingAnalysis,
550
    mapOrUnmap
551
};
STATUS · Troubleshooting · Open an Issue · Sales · Support · CAREERS · ENTERPRISE · START FREE · SCHEDULE DEMO
ANNOUNCEMENTS · TWITTER · TOS & SLA · Supported CI Services · What's a CI service? · Automated Testing

© 2025 Coveralls, Inc