UNPKG

4.65 kBPlain TextView Raw
1import childProcess from 'child_process';
2import { promises as fs } from 'fs';
3import { promisify } from 'util';
4import _debug from 'debug';
5const debug = _debug('mongodb-download-url:linux-distro');
6const execFile = promisify(childProcess.execFile);
7
8type PriorityValue<T> = { value: T; priority: number; }
9
10let osRelease: string;
11export async function getCurrentLinuxDistro(): Promise<PriorityValue<string>[]> {
12 if (process.env.DISTRO_ID) {
13 const distroId = process.env.DISTRO_ID.split('-')[0].split('_')[0];
14 debug('Using environment-provided linux distro ID', distroId);
15 let match;
16 if (match = distroId.match(/^ubuntu(\d\d)(\d\d)$/)) {
17 return listDistroIds({ id: 'ubuntu', version: match[1] });
18 } else if (match = distroId.match(/^debian([8-9])\d$/)) {
19 return listDistroIds({ id: 'debian', version: match[1] });
20 } else if (match = distroId.match(/^debian([1-7]\d)$/)) {
21 return listDistroIds({ id: 'debian', version: match[1] });
22 } else if (match = distroId.match(/^suse(\d+)$/)) {
23 return listDistroIds({ id: 'suse', version: match[1] });
24 } else if (match = distroId.match(/^rhel(\d+)$/)) {
25 return listDistroIds({ id: 'redhatenterprise', version: match[1] });
26 } else if (['amazon', 'amzn64', 'amazon1'].includes(distroId)) {
27 return listDistroIds({ id: 'amazon', version: '2018.03' });
28 }
29 return [{ value: distroId, priority: 100 }];
30 }
31
32 let osReleaseId: string;
33 try {
34 osRelease ??= await fs.readFile('/etc/os-release', 'utf8');
35 debug('loaded /etc/os-release');
36 } catch (err) {
37 if (err.code === 'ENOENT') {
38 osRelease = '';
39 }
40 }
41 if (osRelease) {
42 const id = osReleaseId = osRelease.match(/^ID="?(.+?)"?$/m)?.[1];
43 const version = osRelease.match(/^VERSION_ID="?(.+?)"?$/m)?.[1];
44 if (id && version) {
45 debug('got os-release info', { id, version });
46 const results = listDistroIds({ id, version });
47 if (results.length > 0) {
48 return results;
49 }
50 }
51 }
52 const { id, version } = await lsbReleaseInfo();
53 const results = listDistroIds({ id, version });
54 if (results.length > 0) {
55 return results;
56 }
57 throw new Error(`Could not figure out current Linux distro (${id}, ${osReleaseId})`);
58}
59
60function listDistroIds({ id, version }: { id: string, version: string }): PriorityValue<string>[] {
61 const results: PriorityValue<string>[] = [];
62 switch (id.toLowerCase()) {
63 case 'ubuntu': {
64 const major = +version.split('.')[0];
65 if (major >= 12) results.push({ value: 'ubuntu1204', priority: 100 });
66 if (major >= 14) results.push({ value: 'ubuntu1404', priority: 200 });
67 if (major >= 16) results.push({ value: 'ubuntu1604', priority: 300 });
68 if (major >= 18) results.push({ value: 'ubuntu1804', priority: 400 });
69 if (major >= 20) results.push({ value: 'ubuntu2004', priority: 500 });
70 if (major > 20) results.push({ value: 'ubuntu' + version.replace('.', ''), priority: 600 });
71 return results;
72 }
73 case 'debian': {
74 if (+version >= 8) results.push({ value: 'debian81', priority: 100 });
75 if (+version >= 9) results.push({ value: 'debian92', priority: 200 });
76 if (+version >= 10) results.push({ value: 'debian10', priority: 300 });
77 if (+version > 10) results.push({ value: 'debian' + version, priority: 400 });
78 return results;
79 }
80 case 'suse':
81 case 'sles':
82 return [{ value: 'suse' + version.split('.')[0], priority: 100 }];
83 case 'amzn':
84 case 'amzn64':
85 case 'amazon':
86 if (version.match(/^201[0-9]\./)) {
87 return [{ value: 'amazon', priority: 100 }, { value: 'amzn64', priority: 100 }];
88 } else {
89 return [{ value: 'amazon' + version.replace('.', ''), priority: 100 }];
90 }
91 case 'centos':
92 return [{ value: 'rhel' + version + '0', priority: 100 }];
93 case 'redhatenterprise':
94 case 'redhatenterpriseserver': {
95 const want = +version.replace('.', '');
96 const known = [55, 57, 62, 67, 70, 71, 72, 80, 81, 82];
97 const allowedVersions = known.filter(v => v <= want);
98 return allowedVersions.map((v, i) => ({ value: 'rhel' + v, priority: (i + 1) * 100 }));
99 }
100 }
101 return [];
102}
103
104async function lsbReleaseInfo(): Promise<{ id: string, version: string }> {
105 const [
106 id,
107 version
108 ] = await Promise.all([
109 (async() => {
110 return (await execFile('lsb_release', ['-si'], { encoding: 'utf8' })).stdout.trim();
111 })(),
112 (async() => {
113 return (await execFile('lsb_release', ['-sr'], { encoding: 'utf8' })).stdout.trim();
114 })()
115 ]);
116 debug('got lsb info', { id, version });
117 return { id, version };
118}