mongodoki
Version:
A tool to on-the-fly run MongoDB as a Docker Container, data restoring included
149 lines • 6.04 kB
JavaScript
;
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