UNPKG

mongodoki

Version:

A tool to on-the-fly run MongoDB as a Docker Container, data restoring included

149 lines 6.04 kB
"use strict"; var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) { if (k2 === undefined) k2 = k; var desc = Object.getOwnPropertyDescriptor(m, k); if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) { desc = { enumerable: true, get: function() { return m[k]; } }; } Object.defineProperty(o, k2, desc); }) : (function(o, m, k, k2) { if (k2 === undefined) k2 = k; o[k2] = m[k]; })); var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) { Object.defineProperty(o, "default", { enumerable: true, value: v }); }) : function(o, v) { o["default"] = v; }); var __importStar = (this && this.__importStar) || function (mod) { if (mod && mod.__esModule) return mod; var result = {}; if (mod != null) for (var k in mod) if (k !== "default" && Object.prototype.hasOwnProperty.call(mod, k)) __createBinding(result, mod, k); __setModuleDefault(result, mod); return result; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.Mongodoki = exports.MongoDoki = exports.Db = void 0; const child_process_1 = require("child_process"); const debuggo_1 = require("debuggo"); const mongodb_1 = require("mongodb"); const path = __importStar(require("path")); const doki_1 = require("./doki"); var mongodb_2 = require("mongodb"); Object.defineProperty(exports, "Db", { enumerable: true, get: function () { return mongodb_2.Db; } }); class MongoDoki extends doki_1.TestDoki { constructor(opts = {}) { super(opts, (0, debuggo_1.getLogger)('mongodoki')); this.opts = opts; if (!this.opts.image) { this.opts.image = 'mongo'; } if (!this.opts.ports) { this.opts.ports = [{ host: 27017 }]; } } /** * Start a mongo container, connect to a db and return a Promise for a mongo driver Db instance. * @param containerName * @param dbName * @param timeout * @param dbDumpPath */ async getDB(dbName = 'local', timeout = 60000, dbDumpPath) { const MAX_RETRIES = 60; if (!this.opts.reuse) { await this.createAndStart(); } else { await this.start(); } let db = undefined; let retries = 0; const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); while (!db && retries <= MAX_RETRIES) { try { const port = this.opts.ports && this.opts.ports.length ? this.opts.ports[0].host : 27017; const client = await mongodb_1.MongoClient.connect(`mongodb://127.0.0.1:${port}`); db = client.db(dbName); } catch (error) { this.logger.error('ERROR connecting... retrying'); this.logger.debug('retries:' + retries); const t = Math.round(timeout / MAX_RETRIES); await wait(t === 0 ? 2 : t); retries += 1; } } try { this.logger.debug('Trying to restore a db...'); if (!this.opts.reuse && dbDumpPath) await this.importDBData(dbDumpPath, timeout); } catch (error) { this.logger.error('Error restoring db'); throw error; } if (!db) { throw new Error(`Unable to connect to ${dbName} DB on the ${this.opts.containerName} container.`); } else { this.logger.debug('All is OK. Done.'); return db; } } /** * Import DB dump data through mongorestore * @param dumpDirPath * @param timeout */ async importDBData(dumpDirPath, timeout = 60000) { const normalizedPath = path.normalize(dumpDirPath); return new Promise((resolve, reject) => { (0, child_process_1.exec)(`docker cp ${normalizedPath} ${this.opts.containerName}:/dbdata`, async (err, stdout, stderr) => { if (err) reject(err); else { console.log(` Running mongorestore on container (${this.opts.containerName}) for data in ${normalizedPath}`); const options = { Cmd: ['mongorestore', '/dbdata'], AttachStdout: true, AttachStderr: true, Tty: true, }; try { const MAX_RETRIES = 30; let maxWaits = MAX_RETRIES; const wait = (ms) => new Promise((resolve) => setTimeout(resolve, ms)); const { container } = await this.getContainer(); if (container) { const cmd = await container.exec(options); const restore = await cmd.start({}); let status = await cmd.inspect(); while (status.Running && maxWaits > 0) { await wait(timeout / MAX_RETRIES); maxWaits -= 1; status = await cmd.inspect(); } if (maxWaits > 0) { resolve(restore); } else { reject(new Error('Restoring DB is taking too much time. Try increasing timeout')); } } else { throw new Error('no container'); } } catch (error) { reject(error); } } }); }); } } exports.MongoDoki = MongoDoki; // Backwards compatibility exports.Mongodoki = MongoDoki; //# sourceMappingURL=mongo.js.map