UNPKG

8.49 kBJavaScriptView Raw
1var os = require('os');
2var PLATFORM = os.platform() === 'darwin' ? 'osx' : os.platform();
3var ARCH = os.arch() === 'x64' ? 'x86_64' : os.arch();
4var versions = require('mongodb-version-list');
5var semver = require('semver');
6var request = require('request');
7var async = require('async');
8var defaults = require('lodash.defaults');
9var format = require('util').format;
10var debug = require('debug')('mongodb-download-url');
11
12var EVERGREEN_ENDPOINT = 'http://mci-motu.10gen.cc:9090';
13var LATEST = /^(4.2|stable)/g;
14
15/* Architectural condition has been put for arm64.
16At https://www.mongodb.com/download-center/community, only arm64-ubuntu1604 MongoDB server is present to download for arm64 platform.
17*/
18if (os.arch() == 'arm64'){
19 ARCH = 'arm64-ubuntu1604';
20}
21
22function resolveEvergreenBuildArtifact(opts, fn) {
23 if (opts.platform === 'win32') {
24 opts.distro = 'windows_64_2k8';
25 if (opts.debug) {
26 opts.distro += '_debug';
27 }
28 }
29
30 var projectName = format('mongodb-mongo-%s', opts.branch);
31 var url = format(
32 '%s/rest/v1/projects/%s/revisions/%s',
33 EVERGREEN_ENDPOINT,
34 projectName,
35 opts.version
36 );
37
38 debug('resolving git commit sha1 via evergreen `%s`', url);
39 request.get(
40 {
41 url: url,
42 json: true
43 },
44 function(err, res, body) {
45 if (err) {
46 return fn(err);
47 }
48
49 if (res.statusCode === 404) {
50 return fn(new Error(body.message));
51 }
52
53 var dl = format(
54 'https://s3.amazonaws.com/mciuploads/%s/%s/%s/binaries',
55 projectName,
56 opts.distro,
57 opts.version
58 );
59 var artifactPrefix = format(
60 'mongodb_mongo_%s_%s',
61 opts.branch,
62 opts.distro
63 );
64 var basename = body.builds.filter(function(b) {
65 return b.indexOf(artifactPrefix) > -1;
66 })[0];
67
68 // @todo: test across all distros as I believe this may be different for some.
69 basename = 'binaries-' + basename;
70 fn(null, {
71 name: 'mongodb',
72 version: opts.version,
73 artifact: basename + opts.ext,
74 url: dl + '/' + basename + opts.ext
75 });
76 }
77 );
78}
79
80function search(query, fn) {
81 debug('searching for version', query);
82 versions(function(err, res) {
83 if (err) {
84 return fn(err);
85 }
86
87 var found = false;
88 for (var i = 0; i < res.length; i++) {
89 if (!found && semver.satisfies(res[i], query.version)) {
90 found = true;
91 fn(null, res[i]);
92 }
93 }
94 if (!found) {
95 fn(
96 new Error(
97 'Could not find a MongoDB version matching `' +
98 JSON.stringify(query) +
99 '`'
100 )
101 );
102 }
103 });
104}
105
106function latest(fn) {
107 versions(function(err, res) {
108 if (err) {
109 return fn(err);
110 }
111 fn(null, res[0]);
112 });
113}
114
115function stable(fn) {
116 versions(function(err, res) {
117 if (err) {
118 return fn(err);
119 }
120
121 fn(
122 null,
123 res
124 .map(function(v) {
125 return semver.parse(v);
126 })
127 .filter(function(v) {
128 return v.prerelease.length === 0 && v.minor % 2 === 0;
129 })
130 .map(function(v) {
131 return v.version;
132 })[0]
133 );
134 });
135}
136
137function parsePlatform(opts) {
138 if (opts.platform === 'darwin') {
139 opts.platform = 'osx';
140 }
141 if (opts.platform === 'windows') {
142 opts.platform = 'win32';
143 }
144 return opts;
145}
146
147function parseBits(opts) {
148 // 64bit -> 64
149 opts.bits = '' + opts.bits;
150 opts.bits = opts.bits.replace(/[^0-9]/g, '');
151 return opts;
152}
153
154function parseFileExtension(opts) {
155 opts.ext = '.tgz';
156 if (opts.platform === 'win32') {
157 opts.ext = '.zip';
158 }
159 return opts;
160}
161
162function parseDistro(opts) {
163 if (!opts.distro) {
164 if (opts.platform === 'linux') {
165 opts.distro = 'linux_' + opts.bits;
166 } else if (opts.platform === 'osx') {
167 opts.distro = '';
168 } else if (opts.enterprise) {
169 opts.distro = 'windows-64';
170 } else if (opts.version.charAt(0) === '2') {
171 // 2.x did not ship ssl for windows.
172 opts.distro = '2008plus';
173 } else if (opts.platform === 'win32' && opts.bits === '32') {
174 opts.distro = '';
175 } else if (opts.platform === 'win32' && opts.bits === '64' && opts.version.match(LATEST)) {
176 // 4.2.x uses 2012plus
177 opts.distro = '2012plus';
178 } else {
179 opts.distro = '2008plus-ssl';
180 }
181 if (opts.debug) {
182 opts.distro += '_debug';
183 }
184 }
185 return opts;
186}
187
188function parseArch(opts) {
189 if (opts.bits === '32' && opts.platform === 'linux') {
190 opts.arch = 'i686';
191 } else if (opts.bits === '32' && opts.platform === 'win32') {
192 opts.arch = 'i386';
193 } else if (opts.bits === '64' && opts.platform === 'linux' && ARCH === 'arm64-ubuntu1604') {
194 opts.arch = 'arm64-ubuntu1604';
195 } else {
196 opts.arch = 'x86_64';
197 }
198 return opts;
199}
200
201function resolve(opts, fn) {
202 /**
203 * If it's a commit hash, resolve the artifact
204 * URL using the evergreen rest api.
205 */
206 if (opts.version && opts.version.length === 40) {
207 return resolveEvergreenBuildArtifact(opts, fn);
208 }
209
210 opts.filenamePlatform = opts.platform;
211
212 var handler = versions;
213 if (opts.version === 'latest' || opts.version === 'unstable') {
214 handler = latest;
215 } else if (opts.version === 'stable') {
216 handler = stable;
217 } else {
218 handler = search.bind(null, opts);
219 }
220
221 handler(function(err, versionId) {
222 if (err) {
223 return fn(err);
224 }
225
226 // For osx, force ssl on versions >=3.2
227 // TODO: Lets find a more elegant way to try ssl first, and
228 // then resort to non-ssl if it does not exist
229 if (
230 opts.platform === 'osx' &&
231 semver.gte(versionId, '3.2.0') &&
232 semver.lte(versionId, '3.6.8')
233 ) {
234 opts.ssl = true;
235 }
236
237 // SEE: https://github.com/mongodb-js/version-manager/issues/146
238 if (opts.platform === 'osx' && semver.gte(versionId, '3.6.9')) {
239 opts.filenamePlatform = 'macos';
240 }
241
242 if (opts.platform === 'osx' && semver.satisfies(versionId, '~4.0.0')) {
243 opts.ssl = true;
244 opts.filenamePlatform = 'osx';
245 }
246
247 var extraDash = '-';
248 if (opts.distro.length === 0) {
249 extraDash = '';
250 }
251
252 var artifact;
253 var hostname = 'fastdl.mongodb.org';
254
255 if (opts.enterprise) {
256 hostname = 'downloads.mongodb.com';
257 artifact = format(
258 'mongodb-%s-%s-enterprise-%s',
259 opts.platform,
260 opts.arch,
261 [
262 opts.distro,
263 extraDash,
264 opts.debug ? '-debugsymbols-' : '',
265 versionId,
266 opts.ext
267 ].join('')
268 );
269 } else if (opts.platform === 'linux') {
270 var distro = require('./linuxDistro').getDistro();
271 if (distro && opts.bits === '64' && semver.gte(versionId, '4.0.0')) {
272 artifact = format(
273 'mongodb-%s-%s-%s-%s',
274 opts.platform,
275 opts.arch,
276 distro,
277 [opts.debug ? '-debugsymbols-' : '', versionId, opts.ext].join('')
278 )
279 } else {
280 artifact = format(
281 'mongodb-%s-%s-%s',
282 opts.platform,
283 opts.arch,
284 [opts.debug ? '-debugsymbols-' : '', versionId, opts.ext].join('')
285 );
286 }
287 } else {
288 artifact =
289 'mongodb-' +
290 opts.filenamePlatform +
291 '-' +
292 (opts.ssl ? 'ssl-' : '') +
293 opts.arch +
294 '-' +
295 opts.distro +
296 extraDash +
297 (opts.debug ? '-debugsymbols-' : '') +
298 versionId +
299 opts.ext;
300 }
301
302 opts.name = 'mongodb';
303 opts.version = versionId;
304 opts.artifact = artifact;
305 opts.url = format('https://%s/%s/%s', hostname, opts.platform, artifact);
306
307 debug('fully resolved', JSON.stringify(opts, null, 2));
308 fn(null, opts);
309 });
310}
311
312function options(opts) {
313 if (typeof opts === 'string') {
314 opts = {
315 version: opts
316 };
317 }
318
319 opts = opts || {};
320
321 defaults(opts, {
322 version: process.env.MONGODB_VERSION || 'stable',
323 arch: ARCH,
324 platform: PLATFORM,
325 branch: 'master',
326 bits: '64',
327 debug: false
328 });
329
330 parsePlatform(opts);
331 parseBits(opts);
332 parseFileExtension(opts);
333 parseDistro(opts);
334 parseArch(opts);
335 return opts;
336}
337
338function getDownloadURL(opts, fn) {
339 if (Array.isArray(opts)) {
340 var tasks = {};
341
342 opts.map(function(opt) {
343 tasks[opt.version] = getDownloadURL.bind(null, opt);
344 });
345
346 return async.parallel(tasks, fn);
347 }
348
349 options(opts);
350
351 debug('Building URL for options `%j`', opts);
352 resolve(opts, fn);
353}
354
355module.exports = getDownloadURL;
356module.exports.options = options;