• 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.5
/lib/database/model/sthDatabaseNameCodecTool.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 sthDatabaseNameCodec = require(ROOT_PATH + '/lib/database/model/sthDatabaseNameCodec');
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 = {};
16✔
42
    return process.nextTick(callback);
16✔
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();
16✔
53
    adminDB.listDatabases(callback);
16✔
54
}
55

56
/**
57
 * Filters the databases associated to a STH instance
58
 * @param {Object}    options      An object including the following properties:
59
 *                                 - {Boolean} encode     Flag indicating if the request is about a codification
60
 *                                 process
61
 *                                 - {Boolean} decode     Flag indicating if the request is about a decodification
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(
64✔
70
        null,
71
        databaseData.name.indexOf(
216✔
72
            (options.decode ? sthDatabaseNameCodec.decodeDatabaseName(sthConfig.DB_PREFIX) : sthConfig.DB_PREFIX) === 0
64✔
73
        ) &&
74
            (!options.database || (options.database && options.database === databaseData.name))
75
    );
76
}
77

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

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

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

121
/**
122
 * Filters a collection from its database
123
 * @param {Object}    options        An object including the following properties:
124
 *                                   - {Boolean} encode     Flag indicating if the request is about a codification
125
 *                                   process
126
 *                                   - {Boolean} decode     Flag indicating if the request is about a decodification
127
 *                                   process
128
 *                                   - {String}  database   The database name to restrict the analysis to
129
 *                                   - {String}  collection The collection name to restrict the analysis to
130
 * @param  {Object}   collectionData The collection database
131
 * @param  {Function} callback       The callback
132
 */
133
function collectionFilter(options, collectionData, callback) {
1✔
134
    return callback(
37✔
135
        null,
136
        collectionData.name.indexOf(
75✔
137
            options.decode
37✔
138
                ? sthDatabaseNameCodec.decodeCollectionName(sthConfig.COLLECTION_PREFIX)
139
                : sthConfig.COLLECTION_PREFIX
140
        ) === 0 &&
141
            (!options.collection || (options.collection && options.collection === collectionData.name))
142
    );
143
}
144

145
/**
146
 * Filters the collections included in some collections database
147
 * @param {Object}    options         An object including the following properties:
148
 *                                    - {Boolean} encode     Flag indicating if the request is about a codification
149
 *                                    process
150
 *                                    - {Boolean} decode     Flag indicating if the request is about a decodification
151
 *                                    process
152
 *                                    - {String}  database   The database name to restrict the analysis to
153
 *                                    - {String}  collection The collection name to restrict the analysis to
154
 * @param  {Object}   collectionsData The collections database
155
 * @param  {Function} callback        The callback
156
 */
157
function filterCollections(options, collectionsData, callback) {
1✔
158
    async.filter(collectionsData, async.apply(collectionFilter, options), callback);
26✔
159
}
160

161
/**
162
 * Analyses a collection from its associated data
163
 * @param {Object}    options        An object including the following properties:
164
 *                                   - {Boolean} encode     Flag indicating if the request is about a codification
165
 *                                   process
166
 *                                   - {Boolean} decode     Flag indicating if the request is about a decodification
167
 *                                   process
168
 *                                   - {String}  database   The database name to restrict the analysis to
169
 *                                   - {String}  collection The collection name to restrict the analysis to
170
 * @param  {Object}   collectionData The collection data
171
 * @param  {Function} callback       The callback
172
 */
173
function analyseCollection(options, collectionData, callback) {
1✔
174
    analysisResult[collectionData.database].collections = analysisResult[collectionData.database].collections || {};
14✔
175
    analysisResult[collectionData.database].collections[collectionData.name] = {
14✔
176
        name: options.encode
14✔
177
            ? sthDatabaseNameCodec.encodeCollectionName(collectionData.name)
178
            : sthDatabaseNameCodec.decodeCollectionName(collectionData.name)
179
    };
180
    process.nextTick(callback);
14✔
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} encode     Flag indicating if the request is about a codification
187
 *                                    process
188
 *                                    - {Boolean} decode     Flag indicating if the request is about a decodification
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);
26✔
197
}
198

199
/**
200
 * Analyses the collections in certain database
201
 * @param {Object}    options      An object including the following properties:
202
 *                                 - {Boolean} encode     Flag indicating if the request is about a codification
203
 *                                 process
204
 *                                 - {Boolean} decode     Flag indicating if the request is about a decodification
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(
26✔
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 encoding/decoding report for this database
221
 * @param {Object}    options      An object including the following properties:
222
 *                                 - {Boolean} encode     Flag indicating if the request is about a codification
223
 *                                 process
224
 *                                 - {Boolean} decode     Flag indicating if the request is about a decodification
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] = {
26✔
233
        name: options.encode
26✔
234
            ? sthDatabaseNameCodec.encodeDatabaseName(databaseData.name)
235
            : sthDatabaseNameCodec.decodeDatabaseName(databaseData.name)
236
    };
237
    analyseCollections(options, databaseData.name, callback);
26✔
238
}
239

240
/**
241
 * Analyses a group of database data to generate a new encoding/decoding report
242
 * @param {Object}    options       An object including the following properties:
243
 *                                  - {Boolean} encode     Flag indicating if the request is about a codification
244
 *                                  process
245
 *                                  - {Boolean} decode     Flag indicating if the request is about a decodification
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);
16✔
254
}
255

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

284
/**
285
 * Shows the codification report
286
 * @param {Object}   options  An object including the following properties:
287
 *                            - {Boolean} encode     Flag indicating if the request is about a codification process
288
 *                            - {Boolean} decode     Flag indicating if the request is about a decodification 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 getEncodingAnalysis(options, callback) {
1✔
295
    if (!options.encode && !options.decode) {
20✔
296
        return process.nextTick(
4✔
297
            callback.bind(
298
                null,
299
                new sthErrors.MandatoryOptionNotFound(
300
                    'Either the -e (--encode) or the -d (--decode) options are mandatory'
301
                )
302
            )
303
        );
304
    }
305
    if (options.collection && !options.database) {
16!
306
        return process.nextTick(
×
307
            callback.bind(
308
                null,
309
                new sthErrors.MandatoryOptionNotFound(
310
                    'The -b (--database) option is mandatory if the -c (--collection) option is set'
311
                )
312
            )
313
        );
314
    }
315
    async.seq(
16✔
316
        resetAnalysisResult,
317
        sthDatabase.connect.bind(null, {
318
            authentication: sthConfig.DB_AUTHENTICATION,
319
            dbURI: sthConfig.DB_URI,
320
            replicaSet: sthConfig.REPLICA_SET,
321
            database: sthDatabaseNaming.getDatabaseName(sthConfig.DEFAULT_SERVICE),
322
            poolSize: sthConfig.POOL_SIZE,
323
            authSource: sthConfig.DB_AUTH_SOURCE
324
        }),
325
        listDatabases,
326
        async.apply(filterDatabases, options),
327
        async.apply(analyseDatabases, options),
328
        cleanAnalysis
329
    )(callback);
330
}
331

332
/**
333
 * Encodes or decodes the name of certain collection in certain databaseName
334
 * @param {Object}    options        An object including the following properties:
335
 *                                   - {Boolean} encode     Flag indicating if the request is about a codification
336
 *                                   process
337
 *                                   - {Boolean} decode     Flag indicating if the request is about a decodification
338
 *                                   process
339
 *                                   - {String}  database   The database name to restrict the analysis to
340
 *                                   - {String}  collection The collection name to restrict the analysis to
341
 * @param  {String}   databaseName   The database name
342
 * @param  {String}   collectionName The collection name
343
 * @param  {Function} callback       The callback
344
 */
345
function encodeOrDecodeCollection(options, databaseName, collectionName, callback) {
1✔
346
    sthLogger.info(
4✔
347
        sthConfig.LOGGING_CONTEXT.DB_LOG,
348
        // prettier-ignore
349
        (options.encode ? 'Codification' : 'Decodification') + " of collection '" + collectionName +
4✔
350
            "' of database '" + databaseName + "' started..."
351
    );
352

353
    sthDatabase.client
4✔
354
        .db(databaseName)
355
        .renameCollection(
356
            collectionName,
357
            options.encode
4✔
358
                ? sthDatabaseNameCodec.encodeCollectionName(collectionName)
359
                : sthDatabaseNameCodec.decodeCollectionName(collectionName),
360
            function(err) {
361
                if (err) {
4!
362
                    return process.nextTick(callback.bind(null, err));
×
363
                }
364
                sthLogger.info(
4✔
365
                    sthConfig.LOGGING_CONTEXT.DB_LOG,
366
                    // prettier-ignore
367
                    (options.encode ? 'Codification' : 'Decodification') + " of collection '" + collectionName +
4✔
368
                         "' of database '" + databaseName + "' successfully completed."
369
                );
370
                return process.nextTick(callback);
4✔
371
            }
372
        );
373
}
374

375
/**
376
 * Copies a database since this is the only way to rename it (the original database is removed afterwards)
377
 * @param {Object}    options      An object including the following properties:
378
 *                                 - {Boolean} encode     Flag indicating if the request is about a codification process
379
 *                                 - {Boolean} decode     Flag indicating if the request is about a decodification
380
 *                                 process
381
 *                                 - {String}  database   The database name to restrict the analysis to
382
 *                                 - {String}  collection The collection name to restrict the analysis to
383
 * @param  {String}   databaseName The database name
384
 * @param  {Function} callback     The callback
385
 */
386

387
// Alternative function without copydb command
388
function copyDatabase(options, databaseName, callback) {
1✔
389
    const adminDB = sthDatabase.connection.admin();
2✔
390
    const listCommand = {
2✔
391
        listCollections: 1,
392
        nameOnly: true
393
    };
394
    var sourceDB = databaseName;
2✔
395
    var targetDB = options.encode
2✔
396
        ? sthDatabaseNameCodec.encodeDatabaseName(databaseName)
397
        : sthDatabaseNameCodec.decodeDatabaseName(databaseName);
398

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

405
        var arrayCollectionRenames = [];
2✔
406
        results.cursor.firstBatch.forEach((collection) => {
2✔
407
            var source = sourceDB + '.' + collection.name;
4✔
408
            var destination = targetDB + '.' + collection.name;
4✔
409

410
            let collectionData = { source: source, destination: destination, db: adminDB };
4✔
411
            arrayCollectionRenames.push(collectionData);
4✔
412
        });
413

414
        async.map(
2✔
415
            arrayCollectionRenames,
416
            function(element, callback) {
417
                element.db.command(
4✔
418
                    { renameCollection: element.source, to: element.destination, dropTarget: true },
419
                    function(err) {
420
                        callback(err);
4✔
421
                    }
422
                );
423
            },
424
            function(err) {
425
                if (err) {
2!
426
                    return process.nextTick(callback.bind(null, err));
×
427
                }
428
                sthLogger.info(
2✔
429
                    sthConfig.LOGGING_CONTEXT.DB_LOG,
430
                    // prettier-ignore
431
                    (options.encode ? 'Codification' : 'Decodification') + " of database '" + databaseName +
2✔
432
                        ' successfully completed.'
433
                );
434
                process.nextTick(callback);
2✔
435
            }
436
        );
437
    });
438
}
439

440
/**
441
 * Encodes or decodes the name of certain database and its collections
442
 * @param {Object}    options      An object including the following properties:
443
 *                                 - {Boolean} encode     Flag indicating if the request is about a codification process
444
 *                                 - {Boolean} decode     Flag indicating if the request is about a decodification
445
 *                                 process
446
 *                                 - {String}  database   The database name to restrict the analysis to
447
 *                                 - {String}  collection The collection name to restrict the analysis to
448
 * @param  {String}   databaseName The database name
449
 * @param  {Function} callback     The callback
450
 */
451
function encodeOrDecodeDatabase(options, databaseName, callback) {
1✔
452
    sthLogger.info(
2✔
453
        sthConfig.LOGGING_CONTEXT.DB_LOG,
454
        (options.encode ? 'Codification' : 'Decodification') + " of database '" + databaseName + ' started...'
2✔
455
    );
456

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

496
/**
497
 * Effectively encodes or decodes the name of the databases and collections included in certain encoding/decoding
498
 * analysis
499
 * @param {Object}    options   An object including the following properties:
500
 *                              - {Boolean} encode     Flag indicating if the request is about a codification process
501
 *                              - {Boolean} decode     Flag indicating if the request is about a decodification process
502
 *                              - {String}  database   The database name to restrict the analysis to
503
 *                              - {String}  collection The collection name to restrict the analysis to
504
 * @param  {Object}   analysis The analysis
505
 * @param  {Function} callback The callback
506
 */
507
function doEncodeOrDecode(options, analysis, callback) {
1✔
508
    const databaseNames = Object.getOwnPropertyNames(analysis);
6✔
509
    async.eachSeries(databaseNames, async.apply(encodeOrDecodeDatabase, options), callback);
6✔
510
}
511

512
/**
513
 * Encodes or decodes the names of the databases and the collections included in certain encoding/decoding analysis
514
 * @param {Object}   options  An object including the following properties:
515
 *                            - {Boolean} encode     Flag indicating if the request is about a codification process
516
 *                            - {Boolean} decode     Flag indicating if the request is about a decodification process
517
 *                            - {String}  database   The database name to restrict the analysis to
518
 *                            - {String}  collection The collection name to restrict the analysis to
519
 * @param  {Function} callback The callback
520
 */
521
function encodeOrDecode(options, callback) {
1✔
522
    if (!options.encode && !options.decode) {
10✔
523
        return process.nextTick(
4✔
524
            callback.bind(
525
                null,
526
                new sthErrors.MandatoryOptionNotFound(
527
                    'Either the -e (--encode) or the -d (--decode) options are mandatory'
528
                )
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(
6✔
544
        sthConfig.LOGGING_CONTEXT.DB_LOG,
545
        (options.encode ? 'Codification' : 'Decodification') + ' process started...'
6✔
546
    );
547

548
    async.seq(async.apply(getEncodingAnalysis, options), async.apply(doEncodeOrDecode, options))(callback);
6✔
549
}
550

551
module.exports = {
1✔
552
    getEncodingAnalysis,
553
    encodeOrDecode
554
};
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