Skip to content

Commit 10d1749

Browse files
committed
fix(MongoBinaryDownload): use coerced versions for semver
fixes #734
1 parent 5676931 commit 10d1749

File tree

3 files changed

+199
-14
lines changed

3 files changed

+199
-14
lines changed

packages/mongodb-memory-server-core/src/util/MongoBinaryDownloadUrl.ts

Lines changed: 31 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,6 +8,7 @@ import {
88
KnownVersionIncompatibilityError,
99
UnknownArchitectureError,
1010
UnknownPlatformError,
11+
UnknownVersionError,
1112
} from './errors';
1213
import { deprecate } from 'util';
1314

@@ -101,11 +102,12 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
101102
*/
102103
getArchiveNameWin(): string {
103104
let name = `mongodb-${this.platform}-${this.arch}`;
105+
const coercedVersion = semver.coerce(this.version);
104106

105-
if (!isNullOrUndefined(semver.coerce(this.version))) {
106-
if (semver.satisfies(this.version, '4.2.x')) {
107+
if (!isNullOrUndefined(coercedVersion)) {
108+
if (semver.satisfies(coercedVersion, '4.2.x')) {
107109
name += '-2012plus';
108-
} else if (semver.lt(this.version, '4.1.0')) {
110+
} else if (semver.lt(coercedVersion, '4.1.0')) {
109111
name += '-2008plus-ssl';
110112
}
111113
}
@@ -121,19 +123,19 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
121123
*/
122124
getArchiveNameOsx(): string {
123125
let name = `mongodb-osx`;
124-
const version = semver.coerce(this.version);
126+
const coercedVersion = semver.coerce(this.version);
125127

126-
if (!isNullOrUndefined(version) && semver.gte(version, '3.2.0')) {
128+
if (!isNullOrUndefined(coercedVersion) && semver.gte(coercedVersion, '3.2.0')) {
127129
name += '-ssl';
128130
}
129-
if (isNullOrUndefined(version) || semver.gte(version, '4.2.0')) {
131+
if (isNullOrUndefined(coercedVersion) || semver.gte(coercedVersion, '4.2.0')) {
130132
name = `mongodb-macos`; // somehow these files are not listed in https://www.mongodb.org/dl/osx
131133
}
132134

133135
// mongodb has native arm64
134136
if (this.arch === 'aarch64') {
135137
// force usage of "x86_64" binary for all versions below than 6.0.0
136-
if (!isNullOrUndefined(version) && semver.lt(version, '6.0.0')) {
138+
if (!isNullOrUndefined(coercedVersion) && semver.lt(coercedVersion, '6.0.0')) {
137139
log('getArchiveNameOsx: Arch is "aarch64" and version is below 6.0.0, using x64 binary');
138140
this.arch = 'x86_64';
139141
} else {
@@ -243,11 +245,16 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
243245
getDebianVersionString(os: LinuxOS): string {
244246
let name = 'debian';
245247
const release: number = parseFloat(os.release);
248+
const coercedVersion = semver.coerce(this.version);
249+
250+
if (isNullOrUndefined(coercedVersion)) {
251+
throw new UnknownVersionError(this.version);
252+
}
246253

247254
if (release >= 11 || ['unstable', 'testing'].includes(os.release)) {
248255
// Debian 11 is compatible with the binaries for debian 10
249256
// but does not have binaries for before 5.0.8
250-
if (semver.lt(this.version, '5.0.8')) {
257+
if (semver.lt(coercedVersion, '5.0.8')) {
251258
log('debian11 detected, but version below 5.0.8 requested, using debian10');
252259
name += '10';
253260
} else {
@@ -264,7 +271,7 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
264271
}
265272

266273
if (release >= 10) {
267-
if (semver.lt(this.version, '4.2.1')) {
274+
if (semver.lt(coercedVersion, '4.2.1')) {
268275
throw new KnownVersionIncompatibilityError(
269276
`Debian ${release}`,
270277
this.version,
@@ -311,6 +318,11 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
311318
let name = 'rhel';
312319
const { release } = os;
313320
const releaseAsSemver = semver.coerce(release); // coerce "8" to "8.0.0" and "8.2" to "8.2.0", makes comparing easier than "parseInt" or "parseFloat"
321+
const coercedVersion = semver.coerce(this.version);
322+
323+
if (isNullOrUndefined(coercedVersion)) {
324+
throw new UnknownVersionError(this.version);
325+
}
314326

315327
if (releaseAsSemver) {
316328
if (this.arch === 'aarch64') {
@@ -325,7 +337,7 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
325337
}
326338
// there are no versions for aarch64 before mongodb 4.4.2
327339
// Note: version 4.4.2 and 4.4.3 are NOT listed at the list, but are existing; list: https://www.mongodb.com/download-center/community/releases/archive
328-
if (semver.lt(this.version, '4.4.2')) {
340+
if (semver.lt(coercedVersion, '4.4.2')) {
329341
throw new KnownVersionIncompatibilityError(`Rhel ${release}`, this.version, '>=4.4.2');
330342
}
331343

@@ -399,6 +411,11 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
399411
*/
400412
getUbuntuVersionString(os: LinuxOS): string {
401413
let ubuntuOS: LinuxOS | undefined = undefined;
414+
const coercedVersion = semver.coerce(this.version);
415+
416+
if (isNullOrUndefined(coercedVersion)) {
417+
throw new UnknownVersionError(this.version);
418+
}
402419

403420
// "id_like" processing (version conversion) [this is an block to be collapsible]
404421
{
@@ -460,13 +477,13 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
460477

461478
if (this.arch === 'aarch64') {
462479
// this is because, before version 4.1.10, everything for "arm64" / "aarch64" were just "arm64" and for "ubuntu1604"
463-
if (semver.satisfies(this.version, '<4.1.10')) {
480+
if (semver.satisfies(coercedVersion, '<4.1.10')) {
464481
this.arch = 'arm64';
465482

466483
return 'ubuntu1604';
467484
}
468485
// this is because versions below "4.4.0" did not provide an binary for anything above 1804
469-
if (semver.satisfies(this.version, '>=4.1.10 <4.4.0')) {
486+
if (semver.satisfies(coercedVersion, '>=4.1.10 <4.4.0')) {
470487
return 'ubuntu1804';
471488
}
472489
}
@@ -477,7 +494,7 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
477494

478495
// there are no MongoDB 3.x binary distributions for ubuntu >= 18
479496
// https://www.mongodb.org/dl/linux/x86_64-ubuntu1604
480-
if (ubuntuYear >= 18 && semver.satisfies(this.version, '3.x.x')) {
497+
if (ubuntuYear >= 18 && semver.satisfies(coercedVersion, '3.x.x')) {
481498
log(
482499
`getUbuntuVersionString: ubuntuYear is "${ubuntuYear}", which dosnt have an 3.x.x version, defaulting to "1604"`
483500
);
@@ -487,7 +504,7 @@ export class MongoBinaryDownloadUrl implements MongoBinaryDownloadUrlOpts {
487504

488505
// there are no MongoDB <=4.3.x binary distributions for ubuntu > 18
489506
// https://www.mongodb.org/dl/linux/x86_64-ubuntu1804
490-
if (ubuntuYear > 18 && semver.satisfies(this.version, '<=4.3.x')) {
507+
if (ubuntuYear > 18 && semver.satisfies(coercedVersion, '<=4.3.x')) {
491508
log(
492509
`getUbuntuVersionString: ubuntuYear is "${ubuntuYear}", which dosnt have an "<=4.3.x" version, defaulting to "1804"`
493510
);

packages/mongodb-memory-server-core/src/util/__tests__/MongoBinaryDownloadUrl.test.ts

Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,16 +3,42 @@ import {
33
UnknownPlatformError,
44
UnknownArchitectureError,
55
KnownVersionIncompatibilityError,
6+
UnknownVersionError,
67
} from '../errors';
78
import { LinuxOS } from '../getos';
89
import MongoBinaryDownloadUrl from '../MongoBinaryDownloadUrl';
910
import { envName, ResolveConfigVariables } from '../resolveConfig';
11+
import * as semver from 'semver';
12+
import { assertion } from '../utils';
1013

1114
afterEach(() => {
1215
jest.restoreAllMocks();
1316
});
1417

1518
describe('MongoBinaryDownloadUrl', () => {
19+
// the following is to make sure that semver works in expected ways and as examples of how we use it
20+
describe('semver correctly coerces mongodb versions', () => {
21+
it('should convert a normal semver version', () => {
22+
const normal5 = semver.coerce('5.0.0');
23+
assertion(normal5);
24+
expect(normal5.version).toStrictEqual('5.0.0');
25+
26+
const normalAll = semver.coerce('4.4.2');
27+
assertion(normalAll);
28+
expect(normalAll.version).toStrictEqual('4.4.2');
29+
});
30+
31+
it('should convert "-latest" version correctly', () => {
32+
const latest5 = semver.coerce('v5.0-latest');
33+
assertion(latest5);
34+
expect(latest5.version).toStrictEqual('5.0.0');
35+
36+
const latest44 = semver.coerce('v4.4-latest');
37+
assertion(latest44);
38+
expect(latest44.version).toStrictEqual('4.4.0');
39+
});
40+
});
41+
1642
describe('getDownloadUrl()', () => {
1743
describe('for mac', () => {
1844
it('latest', async () => {
@@ -92,6 +118,28 @@ describe('MongoBinaryDownloadUrl', () => {
92118
'https://fastdl.mongodb.org/osx/mongodb-macos-arm64-6.0.0.tgz'
93119
);
94120
});
121+
122+
it('should allow v5.0-latest x64', async () => {
123+
const du = new MongoBinaryDownloadUrl({
124+
platform: 'darwin',
125+
arch: 'x64',
126+
version: 'v5.0-latest',
127+
});
128+
expect(await du.getDownloadUrl()).toBe(
129+
'https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-v5.0-latest.tgz'
130+
);
131+
});
132+
133+
it('should allow v5.0-latest arm64', async () => {
134+
const du = new MongoBinaryDownloadUrl({
135+
platform: 'darwin',
136+
arch: 'arm64',
137+
version: 'v5.0-latest',
138+
});
139+
expect(await du.getDownloadUrl()).toBe(
140+
'https://fastdl.mongodb.org/osx/mongodb-macos-x86_64-v5.0-latest.tgz'
141+
);
142+
});
95143
});
96144

97145
describe('for linux', () => {
@@ -224,6 +272,44 @@ describe('MongoBinaryDownloadUrl', () => {
224272
);
225273
});
226274

275+
it('should allow v5.0-latest', async () => {
276+
const du = new MongoBinaryDownloadUrl({
277+
platform: 'linux',
278+
arch: 'x64',
279+
version: 'v5.0-latest',
280+
os: {
281+
os: 'linux',
282+
dist: 'ubuntu',
283+
release: '20.04',
284+
},
285+
});
286+
expect(await du.getDownloadUrl()).toBe(
287+
'https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-ubuntu2004-v5.0-latest.tgz'
288+
);
289+
});
290+
291+
it('should throw a Error when the provided version could not be coerced [UnknownVersionError]', async () => {
292+
const du = new MongoBinaryDownloadUrl({
293+
platform: 'linux',
294+
arch: 'x64',
295+
version: 'vvv',
296+
os: {
297+
os: 'linux',
298+
dist: 'ubuntu',
299+
release: '20.04',
300+
},
301+
});
302+
303+
try {
304+
await du.getDownloadUrl();
305+
fail('Expected to throw a UnknownVersionError');
306+
} catch (err) {
307+
assertIsError(err);
308+
expect(err).toBeInstanceOf(UnknownVersionError);
309+
expect(err.message).toMatchSnapshot();
310+
}
311+
});
312+
227313
describe('arm64', () => {
228314
it('for ubuntu arm64 4.0.25 (below 4.1.10)', async () => {
229315
const du = new MongoBinaryDownloadUrl({
@@ -420,6 +506,44 @@ describe('MongoBinaryDownloadUrl', () => {
420506
);
421507
});
422508

509+
it('should allow v5.0-latest', async () => {
510+
const du = new MongoBinaryDownloadUrl({
511+
platform: 'linux',
512+
arch: 'x64',
513+
version: 'v5.0-latest',
514+
os: {
515+
os: 'linux',
516+
dist: 'debian',
517+
release: '10',
518+
},
519+
});
520+
expect(await du.getDownloadUrl()).toBe(
521+
'https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-debian10-v5.0-latest.tgz'
522+
);
523+
});
524+
525+
it('should throw a Error when the provided version could not be coerced [UnknownVersionError]', async () => {
526+
const du = new MongoBinaryDownloadUrl({
527+
platform: 'linux',
528+
arch: 'x64',
529+
version: 'vvv',
530+
os: {
531+
os: 'linux',
532+
dist: 'debian',
533+
release: '10',
534+
},
535+
});
536+
537+
try {
538+
await du.getDownloadUrl();
539+
fail('Expected to throw a UnknownVersionError');
540+
} catch (err) {
541+
assertIsError(err);
542+
expect(err).toBeInstanceOf(UnknownVersionError);
543+
expect(err.message).toMatchSnapshot();
544+
}
545+
});
546+
423547
it('should throw a Error when requesting a version below 4.2.1 for debian 10+ [#554] [KnownVersionIncompatibilityError]', async () => {
424548
const du = new MongoBinaryDownloadUrl({
425549
platform: 'linux',
@@ -903,6 +1027,22 @@ describe('MongoBinaryDownloadUrl', () => {
9031027
);
9041028
});
9051029

1030+
it('should allow v5.0-latest', async () => {
1031+
const du = new MongoBinaryDownloadUrl({
1032+
platform: 'linux',
1033+
arch: 'x64',
1034+
version: 'v5.0-latest',
1035+
os: {
1036+
os: 'linux',
1037+
dist: 'rhel',
1038+
release: '9',
1039+
},
1040+
});
1041+
expect(await du.getDownloadUrl()).toBe(
1042+
'https://fastdl.mongodb.org/linux/mongodb-linux-x86_64-rhel70-v5.0-latest.tgz'
1043+
);
1044+
});
1045+
9061046
it('should Error when ARM64 and rhel below 8 [KnownVersionIncompatibilityError]', async () => {
9071047
const du = new MongoBinaryDownloadUrl({
9081048
platform: 'linux',
@@ -988,6 +1128,28 @@ describe('MongoBinaryDownloadUrl', () => {
9881128
expect(consoleWarnSpy).toHaveBeenCalledTimes(1);
9891129
expect(consoleWarnSpy).toHaveBeenCalledWith('Couldnt coerce RHEL version "a"');
9901130
});
1131+
1132+
it('should throw a Error when the provided version could not be coerced [UnknownVersionError]', async () => {
1133+
const du = new MongoBinaryDownloadUrl({
1134+
platform: 'linux',
1135+
arch: 'x64',
1136+
version: 'vvv',
1137+
os: {
1138+
os: 'linux',
1139+
dist: 'rhel',
1140+
release: '9',
1141+
},
1142+
});
1143+
1144+
try {
1145+
await du.getDownloadUrl();
1146+
fail('Expected to throw a UnknownVersionError');
1147+
} catch (err) {
1148+
assertIsError(err);
1149+
expect(err).toBeInstanceOf(UnknownVersionError);
1150+
expect(err.message).toMatchSnapshot();
1151+
}
1152+
});
9911153
});
9921154
});
9931155

packages/mongodb-memory-server-core/src/util/__tests__/__snapshots__/MongoBinaryDownloadUrl.test.ts.snap

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,8 @@ exports[`MongoBinaryDownloadUrl getDownloadUrl() for linux for debian should thr
1010
Mongodb does not provide binaries for versions before 4.2.1 for Debian 10+ and also cannot be mapped to a previous Debian release"
1111
`;
1212

13+
exports[`MongoBinaryDownloadUrl getDownloadUrl() for linux for debian should throw a Error when the provided version could not be coerced [UnknownVersionError] 1`] = `"Could not corece VERSION to a semver version (version: \\"vvv\\")"`;
14+
1315
exports[`MongoBinaryDownloadUrl getDownloadUrl() for linux for rhel should Error when ARM64 and rhel below 8 [KnownVersionIncompatibilityError] 1`] = `
1416
"Requested Version \\"4.4.2\\" is not available for \\"Rhel 7\\"! Available Versions: \\">=4.4.2\\"
1517
ARM64(aarch64) support for rhel is only for rhel82 or higher"
@@ -20,6 +22,10 @@ exports[`MongoBinaryDownloadUrl getDownloadUrl() for linux for rhel should Error
2022
ARM64(aarch64) support for rhel is only for rhel82 or higher"
2123
`;
2224

25+
exports[`MongoBinaryDownloadUrl getDownloadUrl() for linux for rhel should throw a Error when the provided version could not be coerced [UnknownVersionError] 1`] = `"Could not corece VERSION to a semver version (version: \\"vvv\\")"`;
26+
27+
exports[`MongoBinaryDownloadUrl getDownloadUrl() for linux for ubuntu should throw a Error when the provided version could not be coerced [UnknownVersionError] 1`] = `"Could not corece VERSION to a semver version (version: \\"vvv\\")"`;
28+
2329
exports[`MongoBinaryDownloadUrl getDownloadUrl() should throw an error if platform is unknown (getArchiveName) 1`] = `"Unknown Platform: \\"unknown\\""`;
2430

2531
exports[`MongoBinaryDownloadUrl getDownloadUrl() should throw an error if platform is unknown (translatePlatform) 1`] = `"Unknown Platform: \\"unknown\\""`;

0 commit comments

Comments
 (0)