@cloud-cli/dns 1.2.0 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +1 -4
- package/dist/index.js +14 -8
- package/dist/index.spec.js +20 -12
- package/package.json +1 -1
- package/src/index.spec.ts +20 -12
- package/src/index.ts +16 -9
package/dist/index.d.ts
CHANGED
|
@@ -14,10 +14,7 @@ declare function get(options: {
|
|
|
14
14
|
}): DomainAndTarget | null;
|
|
15
15
|
declare function reload(): Promise<true>;
|
|
16
16
|
declare function addDnsConfig(options: DNSConfig): void;
|
|
17
|
-
export declare function parseDNSLine(line: string):
|
|
18
|
-
domain: string;
|
|
19
|
-
target: string;
|
|
20
|
-
};
|
|
17
|
+
export declare function parseDNSLine(line: string): DomainAndTarget[];
|
|
21
18
|
declare const _default: {
|
|
22
19
|
add: typeof add;
|
|
23
20
|
remove: typeof remove;
|
package/dist/index.js
CHANGED
|
@@ -2,8 +2,7 @@ import fs from 'fs';
|
|
|
2
2
|
import { join } from 'path';
|
|
3
3
|
import { exec } from '@cloud-cli/exec';
|
|
4
4
|
import { init } from '@cloud-cli/cli';
|
|
5
|
-
const
|
|
6
|
-
const filePath = join(process.cwd(), 'configuration', 'apps.conf');
|
|
5
|
+
const filePath = join(process.cwd(), 'configuration', 'hosts.conf');
|
|
7
6
|
const dnsConfig = {
|
|
8
7
|
defaultTarget: '127.0.0.1'
|
|
9
8
|
};
|
|
@@ -32,14 +31,15 @@ function list() {
|
|
|
32
31
|
.trim()
|
|
33
32
|
.split('\n')
|
|
34
33
|
.filter(Boolean)
|
|
35
|
-
.
|
|
34
|
+
.flatMap(parseDNSLine);
|
|
36
35
|
return entries;
|
|
37
36
|
}
|
|
38
37
|
function get(options) {
|
|
39
38
|
return list().filter(d => d.domain === options.domain)[0] || null;
|
|
40
39
|
}
|
|
41
40
|
async function reload() {
|
|
42
|
-
const
|
|
41
|
+
const getPid = await exec('pidof', ['dnsmasq']);
|
|
42
|
+
const cmd = await exec('kill', ['-s', 'HUP', getPid.stdout.trim()]);
|
|
43
43
|
return cmd.ok || Promise.reject(new Error('Failed to reload'));
|
|
44
44
|
}
|
|
45
45
|
function addDnsConfig(options) {
|
|
@@ -48,11 +48,17 @@ function addDnsConfig(options) {
|
|
|
48
48
|
}
|
|
49
49
|
}
|
|
50
50
|
function save(list) {
|
|
51
|
-
const
|
|
52
|
-
|
|
51
|
+
const targets = list.reduce((all, next) => {
|
|
52
|
+
var _a;
|
|
53
|
+
all[_a = next.target] || (all[_a] = []);
|
|
54
|
+
all[next.target].push(next.domain);
|
|
55
|
+
return all;
|
|
56
|
+
}, {});
|
|
57
|
+
const txt = Object.entries(targets).map(([ip, domains]) => `${ip} ${domains.join(' ')}`);
|
|
58
|
+
fs.writeFileSync(filePath, txt.join('\n').trim());
|
|
53
59
|
}
|
|
54
60
|
export function parseDNSLine(line) {
|
|
55
|
-
const
|
|
56
|
-
return { domain:
|
|
61
|
+
const [ip, ...domains] = line.split(/\s+/);
|
|
62
|
+
return domains.map(d => ({ domain: d, target: ip }));
|
|
57
63
|
}
|
|
58
64
|
export default { add, remove, list, reload, get, [init]: addDnsConfig };
|
package/dist/index.spec.js
CHANGED
|
@@ -8,13 +8,16 @@ beforeEach(() => {
|
|
|
8
8
|
});
|
|
9
9
|
describe('dns', () => {
|
|
10
10
|
it('should parse a DNS configuration line', () => {
|
|
11
|
-
const line = '
|
|
11
|
+
const line = '1.2.3.4 foo bar';
|
|
12
12
|
const output = parseDNSLine(line);
|
|
13
|
-
expect(output).toEqual(
|
|
13
|
+
expect(output).toEqual([
|
|
14
|
+
{ target: '1.2.3.4', domain: 'foo' },
|
|
15
|
+
{ target: '1.2.3.4', domain: 'bar' },
|
|
16
|
+
]);
|
|
14
17
|
});
|
|
15
18
|
it('should load entries from file', () => {
|
|
16
19
|
let fileExists = false;
|
|
17
|
-
const buffer = `
|
|
20
|
+
const buffer = `1.2.3.4 test\n5.6.7.8 foo`;
|
|
18
21
|
jest.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
|
|
19
22
|
jest.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
|
|
20
23
|
expect(dns.list()).toEqual([]);
|
|
@@ -27,7 +30,7 @@ describe('dns', () => {
|
|
|
27
30
|
});
|
|
28
31
|
it('should get a DNS entry by domain', () => {
|
|
29
32
|
let fileExists = false;
|
|
30
|
-
const buffer = `
|
|
33
|
+
const buffer = `1.2.3.4 test.com\n5.6.7.8 foo.com`;
|
|
31
34
|
jest.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
|
|
32
35
|
jest.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
|
|
33
36
|
expect(dns.get({ domain: 'foo.com' })).toBe(null);
|
|
@@ -39,21 +42,26 @@ describe('dns', () => {
|
|
|
39
42
|
jest.spyOn(fs, 'writeFileSync').mockImplementation((_file, value) => { text = value; });
|
|
40
43
|
jest.spyOn(fs, 'readFileSync').mockImplementation(() => text);
|
|
41
44
|
dns.add({ domain: 'foo', target: '2.3.4.5' });
|
|
42
|
-
dns.add({ domain: 'bar' });
|
|
43
|
-
|
|
44
|
-
|
|
45
|
+
dns.add({ domain: 'bar', target: '2.3.4.5' });
|
|
46
|
+
dns.add({ domain: 'baz' });
|
|
47
|
+
const lines = ['2.3.4.5 foo bar', '127.0.0.1 baz'];
|
|
48
|
+
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo');
|
|
49
|
+
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo bar');
|
|
45
50
|
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), lines.join('\n'));
|
|
46
|
-
dns.remove({ domain: '
|
|
51
|
+
dns.remove({ domain: 'baz' });
|
|
47
52
|
expect(text).toBe(lines[0]);
|
|
48
53
|
});
|
|
49
54
|
describe('reload', () => {
|
|
50
55
|
it('should reload the DNS service', async () => {
|
|
51
|
-
jest.spyOn(exec, 'exec').
|
|
56
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: true, stdout: '123' });
|
|
57
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: true });
|
|
52
58
|
await expect(dns.reload()).resolves.toBe(true);
|
|
53
|
-
expect(exec.exec).toHaveBeenCalledWith('
|
|
59
|
+
expect(exec.exec).toHaveBeenCalledWith('pidof', ['dnsmasq']);
|
|
60
|
+
expect(exec.exec).toHaveBeenCalledWith('kill', ['-s', 'HUP', '123']);
|
|
54
61
|
});
|
|
55
62
|
it('should show error on reload', async () => {
|
|
56
|
-
jest.spyOn(exec, 'exec').
|
|
63
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: true, stdout: '123' });
|
|
64
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: false, stderr: 'error' });
|
|
57
65
|
await expect(dns.reload()).rejects.toEqual(new Error('Failed to reload'));
|
|
58
66
|
});
|
|
59
67
|
});
|
|
@@ -61,7 +69,7 @@ describe('dns', () => {
|
|
|
61
69
|
it('should configure the default target', () => {
|
|
62
70
|
dns[init]({ defaultTarget: '1.1.2.2' });
|
|
63
71
|
dns.add({ domain: 'bar' });
|
|
64
|
-
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '
|
|
72
|
+
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '1.1.2.2 bar');
|
|
65
73
|
});
|
|
66
74
|
});
|
|
67
75
|
});
|
package/package.json
CHANGED
package/src/index.spec.ts
CHANGED
|
@@ -10,15 +10,18 @@ beforeEach(() => {
|
|
|
10
10
|
|
|
11
11
|
describe('dns', () => {
|
|
12
12
|
it('should parse a DNS configuration line', () => {
|
|
13
|
-
const line = '
|
|
13
|
+
const line = '1.2.3.4 foo bar';
|
|
14
14
|
const output = parseDNSLine(line);
|
|
15
15
|
|
|
16
|
-
expect(output).toEqual(
|
|
16
|
+
expect(output).toEqual([
|
|
17
|
+
{ target: '1.2.3.4', domain: 'foo' },
|
|
18
|
+
{ target: '1.2.3.4', domain: 'bar' },
|
|
19
|
+
]);
|
|
17
20
|
});
|
|
18
21
|
|
|
19
22
|
it('should load entries from file', () => {
|
|
20
23
|
let fileExists = false;
|
|
21
|
-
const buffer = `
|
|
24
|
+
const buffer = `1.2.3.4 test\n5.6.7.8 foo`;
|
|
22
25
|
jest.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
|
|
23
26
|
jest.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
|
|
24
27
|
|
|
@@ -34,7 +37,7 @@ describe('dns', () => {
|
|
|
34
37
|
|
|
35
38
|
it('should get a DNS entry by domain', () => {
|
|
36
39
|
let fileExists = false;
|
|
37
|
-
const buffer = `
|
|
40
|
+
const buffer = `1.2.3.4 test.com\n5.6.7.8 foo.com`;
|
|
38
41
|
jest.spyOn(fs, 'existsSync').mockImplementation(() => fileExists);
|
|
39
42
|
jest.spyOn(fs, 'readFileSync').mockImplementation(() => buffer);
|
|
40
43
|
|
|
@@ -50,27 +53,32 @@ describe('dns', () => {
|
|
|
50
53
|
jest.spyOn(fs, 'readFileSync').mockImplementation(() => text);
|
|
51
54
|
|
|
52
55
|
dns.add({ domain: 'foo', target: '2.3.4.5' });
|
|
53
|
-
dns.add({ domain: 'bar' });
|
|
56
|
+
dns.add({ domain: 'bar', target: '2.3.4.5' });
|
|
57
|
+
dns.add({ domain: 'baz' });
|
|
54
58
|
|
|
55
|
-
const lines = ['
|
|
59
|
+
const lines = ['2.3.4.5 foo bar', '127.0.0.1 baz'];
|
|
56
60
|
|
|
57
|
-
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String),
|
|
61
|
+
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo');
|
|
62
|
+
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '2.3.4.5 foo bar');
|
|
58
63
|
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), lines.join('\n'));
|
|
59
64
|
|
|
60
|
-
dns.remove({ domain: '
|
|
65
|
+
dns.remove({ domain: 'baz' });
|
|
61
66
|
expect(text).toBe(lines[0]);
|
|
62
67
|
});
|
|
63
68
|
|
|
64
69
|
describe('reload', () => {
|
|
65
70
|
it('should reload the DNS service', async () => {
|
|
66
|
-
jest.spyOn(exec, 'exec').
|
|
71
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: true, stdout: '123' } as any);
|
|
72
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: true } as any);
|
|
67
73
|
|
|
68
74
|
await expect(dns.reload()).resolves.toBe(true);
|
|
69
|
-
expect(exec.exec).toHaveBeenCalledWith('
|
|
75
|
+
expect(exec.exec).toHaveBeenCalledWith('pidof', ['dnsmasq']);
|
|
76
|
+
expect(exec.exec).toHaveBeenCalledWith('kill', ['-s', 'HUP', '123']);
|
|
70
77
|
});
|
|
71
78
|
|
|
72
79
|
it('should show error on reload', async () => {
|
|
73
|
-
jest.spyOn(exec, 'exec').
|
|
80
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: true, stdout: '123' } as any);
|
|
81
|
+
jest.spyOn(exec, 'exec').mockResolvedValueOnce({ ok: false, stderr: 'error' } as any);
|
|
74
82
|
|
|
75
83
|
await expect(dns.reload()).rejects.toEqual(new Error('Failed to reload'));
|
|
76
84
|
});
|
|
@@ -81,7 +89,7 @@ describe('dns', () => {
|
|
|
81
89
|
dns[init]({ defaultTarget: '1.1.2.2' });
|
|
82
90
|
dns.add({ domain: 'bar' });
|
|
83
91
|
|
|
84
|
-
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '
|
|
92
|
+
expect(fs.writeFileSync).toHaveBeenCalledWith(expect.any(String), '1.1.2.2 bar');
|
|
85
93
|
});
|
|
86
94
|
})
|
|
87
95
|
});
|
package/src/index.ts
CHANGED
|
@@ -7,8 +7,7 @@ interface DNSConfig {
|
|
|
7
7
|
defaultTarget?: string;
|
|
8
8
|
}
|
|
9
9
|
|
|
10
|
-
const
|
|
11
|
-
const filePath = join(process.cwd(), 'configuration', 'apps.conf');
|
|
10
|
+
const filePath = join(process.cwd(), 'configuration', 'hosts.conf');
|
|
12
11
|
const dnsConfig: DNSConfig = {
|
|
13
12
|
defaultTarget: '127.0.0.1'
|
|
14
13
|
};
|
|
@@ -49,7 +48,7 @@ function list(): DomainAndTarget[] {
|
|
|
49
48
|
.trim()
|
|
50
49
|
.split('\n')
|
|
51
50
|
.filter(Boolean)
|
|
52
|
-
.
|
|
51
|
+
.flatMap(parseDNSLine)
|
|
53
52
|
|
|
54
53
|
return entries;
|
|
55
54
|
}
|
|
@@ -59,7 +58,8 @@ function get(options: { domain: string; }): DomainAndTarget | null {
|
|
|
59
58
|
}
|
|
60
59
|
|
|
61
60
|
async function reload() {
|
|
62
|
-
const
|
|
61
|
+
const getPid = await exec('pidof', ['dnsmasq']);
|
|
62
|
+
const cmd = await exec('kill', ['-s', 'HUP', getPid.stdout.trim()]);
|
|
63
63
|
return cmd.ok || Promise.reject(new Error('Failed to reload'));
|
|
64
64
|
}
|
|
65
65
|
|
|
@@ -70,13 +70,20 @@ function addDnsConfig(options: DNSConfig) {
|
|
|
70
70
|
}
|
|
71
71
|
|
|
72
72
|
function save(list: DomainAndTarget[]) {
|
|
73
|
-
const
|
|
74
|
-
|
|
73
|
+
const targets: Record<string, string[]> = list.reduce((all, next) => {
|
|
74
|
+
all[next.target] ||= [];
|
|
75
|
+
all[next.target].push(next.domain);
|
|
76
|
+
return all;
|
|
77
|
+
}, {});
|
|
78
|
+
|
|
79
|
+
const txt = Object.entries(targets).map(([ip, domains]) => `${ip} ${domains.join(' ')}`);
|
|
80
|
+
|
|
81
|
+
fs.writeFileSync(filePath, txt.join('\n').trim());
|
|
75
82
|
}
|
|
76
83
|
|
|
77
|
-
export function parseDNSLine(line: string) {
|
|
78
|
-
const
|
|
79
|
-
return { domain:
|
|
84
|
+
export function parseDNSLine(line: string): DomainAndTarget[] {
|
|
85
|
+
const [ip, ...domains] = line.split(/\s+/);
|
|
86
|
+
return domains.map(d => ({ domain: d, target: ip }));
|
|
80
87
|
}
|
|
81
88
|
|
|
82
89
|
export default { add, remove, list, reload, get, [init]: addDnsConfig }
|