-
Notifications
You must be signed in to change notification settings - Fork 1
/
mongo-tools.js
executable file
·140 lines (107 loc) · 3.12 KB
/
mongo-tools.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
// https://mongodb.github.io/node-mongodb-native/2.0/api/
// https://www.npmjs.com/package/mongo-uri
// https://www.npmjs.com/package/mongodump-stream
var MongoClient = Npm.require('mongodb').MongoClient;
var MongoURI = Npm.require('mongo-uri');
var mds = Npm.require('mongodump-stream');
MongoTools = {
// defaults
options: {
mongoUrl: process.env.MONGO_URL,
s3: {
key: null,
secret: null,
bucket: null,
path: null
}
},
// set options
config: function (opts) {
this.options = _.extend({}, this.options, opts);
}
};
/**
* Run mongodump and stream output to Amazon S3
*
* @param {Object}
*
* opts {
* url: String,
* path: String
* }
*/
MongoTools.backup = function (opts) {
var self = this;
opts = opts || {};
var url = opts.url || self.options.mongoUrl;
try {
var m = MongoURI.parse(url);
} catch (err) {
throw new Meteor.Error(err);
}
// build url for just the primary
var mongoUrl = 'mongodb://' + m.username + ':' + m.password + '@' + m.hosts[0] + ':' + m.ports[0] + '/' + m.database
// connect directly to mongo
MongoClient.connect(mongoUrl, Meteor.bindEnvironment(function (err, db) {
if (err) {
throw new Meteor.Error(err)
}
// grab the database
var database = db.db(m.database);
// get all collection names
database.listCollections().toArray(function (err, collection) {
if (err) {
throw new Meteor.Error(err);
}
var pathPrefix = opts.path || self.options.s3.path || '';
// if path is set
if (!!pathPrefix) {
// if no trailing slash, add it
if (pathPrefix.slice(-1) !== '/') {
pathPrefix += '/';
}
}
var now = Date.now();
var awsConf = self.options.s3;
// Dump each collection and stream it to S3.
// Empty collections will be skipped.
_.each(collection, function (c) {
var filename = pathPrefix + now + '/' + c.name + '.bson';
var stream = mds.slurp.binary(mongoUrl, c.name);
mds.dump.s3(filename, stream, awsConf).then(function (out) {
// if collection wasn't empty
if (out.Location) {
console.log(c.name + " collection backed up to " + filename);
}
});
});
db.close();
});
}));
};
/**
* Schedule recurring database dumps to S3
* @param {String} schedule - Text parser argument for Later.js
* @param {Object} opts - Options arg for MongoTools.backup()
*/
MongoTools.scheduleBackup = function (schedule, opts) {
if (typeof Package["percolate:synced-cron"] === 'undefined') {
console.warn("Error: percolate:synced-cron must be installed to use MongoTools.scheduleBackup()");
console.warn("*** NO BACKUPS HAVE BEEN SCHEDULED! ***");
return;
}
var self = this;
SyncedCron.add({
name: 'MongoTools: backup to S3',
schedule: function (parser) {
schedule = schedule || 'every 6 hours';
return parser.text(schedule);
},
job: function() {
console.log("Backing up database to S3...");
self.backup(opts);
return true;
}
});
SyncedCron.start();
};