1 | var os = require('os');
|
2 | var PLATFORM = os.platform() === 'darwin' ? 'osx' : os.platform();
|
3 | var ARCH = os.arch() === 'x64' ? 'x86_64' : os.arch();
|
4 | var versions = require('mongodb-version-list');
|
5 | var semver = require('semver');
|
6 | var request = require('request');
|
7 | var async = require('async');
|
8 | var defaults = require('lodash.defaults');
|
9 | var format = require('util').format;
|
10 | var debug = require('debug')('mongodb-download-url');
|
11 |
|
12 | var EVERGREEN_ENDPOINT = 'http://mci-motu.10gen.cc:9090';
|
13 | var LATEST = /^(4.2|stable)/g;
|
14 |
|
15 |
|
16 |
|
17 |
|
18 | if (os.arch() == 'arm64'){
|
19 | ARCH = 'arm64-ubuntu1604';
|
20 | }
|
21 |
|
22 | function 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 |
|
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 |
|
80 | function 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 |
|
106 | function latest(fn) {
|
107 | versions(function(err, res) {
|
108 | if (err) {
|
109 | return fn(err);
|
110 | }
|
111 | fn(null, res[0]);
|
112 | });
|
113 | }
|
114 |
|
115 | function 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 |
|
137 | function 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 |
|
147 | function parseBits(opts) {
|
148 |
|
149 | opts.bits = '' + opts.bits;
|
150 | opts.bits = opts.bits.replace(/[^0-9]/g, '');
|
151 | return opts;
|
152 | }
|
153 |
|
154 | function parseFileExtension(opts) {
|
155 | opts.ext = '.tgz';
|
156 | if (opts.platform === 'win32') {
|
157 | opts.ext = '.zip';
|
158 | }
|
159 | return opts;
|
160 | }
|
161 |
|
162 | function 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 |
|
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 |
|
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 |
|
188 | function 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 |
|
201 | function resolve(opts, fn) {
|
202 | |
203 |
|
204 |
|
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 |
|
227 |
|
228 |
|
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 |
|
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 |
|
312 | function 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 |
|
338 | function 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 |
|
355 | module.exports = getDownloadURL;
|
356 | module.exports.options = options;
|