pmcf 1.33.0 → 1.35.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/bin/pmcf-named-defs +10 -11
- package/package.json +2 -2
- package/src/model.mjs +38 -29
- package/src/owner.mjs +66 -52
- package/src/utils.mjs +18 -0
- package/types/model.d.mts +8 -3
- package/types/owner.d.mts +7 -6
- package/types/utils.d.mts +9 -0
package/bin/pmcf-named-defs
CHANGED
|
@@ -78,12 +78,11 @@ async function generateNamedDefs(owner, targetDir) {
|
|
|
78
78
|
zones.push(zone);
|
|
79
79
|
|
|
80
80
|
for (const subnet of owner.subnets()) {
|
|
81
|
-
if (subnet.
|
|
82
|
-
const
|
|
83
|
-
const reverseArpa = reverseArpaAddress(subnet.address);
|
|
81
|
+
if (subnet.prefix) {
|
|
82
|
+
const reverseArpa = reverseArpaAddress(subnet.prefix);
|
|
84
83
|
const zone = {
|
|
85
84
|
id: reverseArpa,
|
|
86
|
-
file: `${
|
|
85
|
+
file: `${reverseArpa}.zone`,
|
|
87
86
|
records: new Set([SOARecord, NSRecord])
|
|
88
87
|
};
|
|
89
88
|
zones.push(zone);
|
|
@@ -98,15 +97,15 @@ async function generateNamedDefs(owner, targetDir) {
|
|
|
98
97
|
networkInterface
|
|
99
98
|
} of owner.networkAddresses()) {
|
|
100
99
|
const host = networkInterface.host;
|
|
101
|
-
zone.records.add(
|
|
102
|
-
createRecord(
|
|
103
|
-
host.domainName + ".",
|
|
104
|
-
isIPv4Address(address) ? "A " : "AAAA",
|
|
105
|
-
normalizeIPAddress(address)
|
|
106
|
-
)
|
|
107
|
-
);
|
|
108
100
|
|
|
109
101
|
if (!hosts.has(host)) {
|
|
102
|
+
zone.records.add(
|
|
103
|
+
createRecord(
|
|
104
|
+
host.domainName + ".",
|
|
105
|
+
isIPv4Address(address) ? "A " : "AAAA",
|
|
106
|
+
normalizeIPAddress(address)
|
|
107
|
+
)
|
|
108
|
+
);
|
|
110
109
|
hosts.add(host);
|
|
111
110
|
for (const service of host.services()) {
|
|
112
111
|
//console.log(service.name);
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "pmcf",
|
|
3
|
-
"version": "1.
|
|
3
|
+
"version": "1.35.0",
|
|
4
4
|
"publishConfig": {
|
|
5
5
|
"access": "public"
|
|
6
6
|
},
|
|
@@ -43,7 +43,7 @@
|
|
|
43
43
|
"pacc": "^3.3.0"
|
|
44
44
|
},
|
|
45
45
|
"devDependencies": {
|
|
46
|
-
"@types/node": "^22.13.
|
|
46
|
+
"@types/node": "^22.13.1",
|
|
47
47
|
"ava": "^6.2.0",
|
|
48
48
|
"c8": "^10.1.3",
|
|
49
49
|
"documentation": "^14.0.3",
|
package/src/model.mjs
CHANGED
|
@@ -342,15 +342,21 @@ export class Host extends Base {
|
|
|
342
342
|
*networkAddresses() {
|
|
343
343
|
for (const networkInterface of Object.values(this.networkInterfaces)) {
|
|
344
344
|
for (const address of networkInterface.ipAddresses) {
|
|
345
|
-
yield {
|
|
345
|
+
yield {
|
|
346
|
+
networkInterface,
|
|
347
|
+
address,
|
|
348
|
+
addressWithPrefixLength:
|
|
349
|
+
networkInterface.addressWithPrefixLength(address)
|
|
350
|
+
};
|
|
346
351
|
}
|
|
347
352
|
}
|
|
348
353
|
}
|
|
349
354
|
|
|
350
355
|
get ipAddresses() {
|
|
351
|
-
return [...this.networkAddresses()].map(na =>
|
|
352
|
-
|
|
353
|
-
|
|
356
|
+
return [...this.networkAddresses()].map(na => na.address);
|
|
357
|
+
}
|
|
358
|
+
get ipAddressesWithPrefixLength() {
|
|
359
|
+
return [...this.networkAddresses()].map(na => na.addressWithPrefixLength);
|
|
354
360
|
}
|
|
355
361
|
|
|
356
362
|
get ipAddress() {
|
|
@@ -391,7 +397,7 @@ export class NetworkInterface extends Base {
|
|
|
391
397
|
return "network_interface";
|
|
392
398
|
}
|
|
393
399
|
|
|
394
|
-
#ipAddresses =
|
|
400
|
+
#ipAddresses = new Map();
|
|
395
401
|
#scope;
|
|
396
402
|
#metric;
|
|
397
403
|
#ssid;
|
|
@@ -404,21 +410,6 @@ export class NetworkInterface extends Base {
|
|
|
404
410
|
constructor(owner, data) {
|
|
405
411
|
super(owner, data);
|
|
406
412
|
|
|
407
|
-
if (data.ipv4) {
|
|
408
|
-
this.#ipAddresses.push(...asArray(data.ipv4));
|
|
409
|
-
delete data.ipv4;
|
|
410
|
-
}
|
|
411
|
-
|
|
412
|
-
if (data.ipv6) {
|
|
413
|
-
this.#ipAddresses.push(...asArray(data.ipv6));
|
|
414
|
-
delete data.ipv6;
|
|
415
|
-
}
|
|
416
|
-
|
|
417
|
-
if (data.ipAddresses) {
|
|
418
|
-
this.#ipAddresses.push(...asArray(data.ipAddresses));
|
|
419
|
-
delete data.ipAddresses;
|
|
420
|
-
}
|
|
421
|
-
|
|
422
413
|
if (data.ssid) {
|
|
423
414
|
this.#ssid = data.ssid;
|
|
424
415
|
delete data.ssid;
|
|
@@ -462,26 +453,44 @@ export class NetworkInterface extends Base {
|
|
|
462
453
|
//this.arpbridge = owner.addARPBridge(this, data.arpbridge);
|
|
463
454
|
}
|
|
464
455
|
|
|
456
|
+
set ipAddresses(value) {
|
|
457
|
+
const networkOwner = this.owner.owner;
|
|
458
|
+
for (const address of asArray(value)) {
|
|
459
|
+
const subnet = networkOwner.createSubnet(address);
|
|
460
|
+
this.#ipAddresses.set(normalizeIPAddress(address), subnet);
|
|
461
|
+
}
|
|
462
|
+
}
|
|
463
|
+
|
|
464
|
+
subnetForAddress(address) {
|
|
465
|
+
return (
|
|
466
|
+
this.network?.subnetForAddress(address) ||
|
|
467
|
+
this.owner.owner.subnetForAddress(address)
|
|
468
|
+
);
|
|
469
|
+
}
|
|
470
|
+
|
|
471
|
+
addressWithPrefixLength(address) {
|
|
472
|
+
return `${address}/${this.subnetForAddress(address)?.prefixLength}`;
|
|
473
|
+
}
|
|
474
|
+
|
|
465
475
|
get ipAddresses() {
|
|
466
|
-
return this.#ipAddresses;
|
|
476
|
+
return this.#ipAddresses.keys();
|
|
467
477
|
}
|
|
468
478
|
|
|
469
479
|
get ipAddressesWithPrefixLength() {
|
|
470
|
-
return this
|
|
471
|
-
|
|
480
|
+
return [...this.ipAddresses].map(address =>
|
|
481
|
+
this.addressWithPrefixLength(address)
|
|
472
482
|
);
|
|
473
483
|
}
|
|
474
484
|
|
|
475
485
|
get ipv4Addresses() {
|
|
476
|
-
return this
|
|
486
|
+
return [...this.ipAddresses].filter(a => isIPv4Address(a));
|
|
477
487
|
}
|
|
478
488
|
|
|
479
489
|
get ipv6Addresses() {
|
|
480
|
-
return this
|
|
490
|
+
return [...this.ipAddresses].filter(a => isIPv6Address(a));
|
|
481
491
|
}
|
|
482
492
|
|
|
483
|
-
get prefixLength()
|
|
484
|
-
{
|
|
493
|
+
get prefixLength() {
|
|
485
494
|
return this.network?.prefixLength;
|
|
486
495
|
}
|
|
487
496
|
|
|
@@ -538,8 +547,8 @@ export class NetworkInterface extends Base {
|
|
|
538
547
|
"psk",
|
|
539
548
|
"scope",
|
|
540
549
|
"metric",
|
|
541
|
-
"
|
|
542
|
-
"
|
|
550
|
+
"kind",
|
|
551
|
+
"ipAddresses"
|
|
543
552
|
];
|
|
544
553
|
}
|
|
545
554
|
}
|
package/src/owner.mjs
CHANGED
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
import { asArray } from "./utils.mjs";
|
|
1
|
+
import { asArray, normalizeCIDR } from "./utils.mjs";
|
|
2
2
|
import { Base } from "./base.mjs";
|
|
3
3
|
import { DNSService } from "./dns.mjs";
|
|
4
4
|
|
|
@@ -83,7 +83,7 @@ export class Owner extends Base {
|
|
|
83
83
|
|
|
84
84
|
typeNamed(typeName, name) {
|
|
85
85
|
const typeSlot = this.#membersByType.get(typeName);
|
|
86
|
-
return typeSlot?.get(name);
|
|
86
|
+
return typeSlot?.get(name) || this.owner?.typeNamed(typeName, name);
|
|
87
87
|
}
|
|
88
88
|
|
|
89
89
|
*typeList(typeName) {
|
|
@@ -160,6 +160,32 @@ export class Owner extends Base {
|
|
|
160
160
|
return this.typeList("subnet");
|
|
161
161
|
}
|
|
162
162
|
|
|
163
|
+
subnetForAddress(address) {
|
|
164
|
+
for (const subnet of this.subnets()) {
|
|
165
|
+
if (subnet.matchesAddress(address)) {
|
|
166
|
+
return subnet;
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
}
|
|
170
|
+
|
|
171
|
+
createSubnet(address) {
|
|
172
|
+
if (address instanceof Subnet) {
|
|
173
|
+
return address;
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
const { cidr } = normalizeCIDR(address);
|
|
177
|
+
|
|
178
|
+
if (cidr) {
|
|
179
|
+
let subnet = this.subnetNamed(cidr);
|
|
180
|
+
|
|
181
|
+
if (!subnet) {
|
|
182
|
+
subnet = new Subnet(this, { name: cidr });
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
return subnet;
|
|
186
|
+
}
|
|
187
|
+
}
|
|
188
|
+
|
|
163
189
|
clusterNamed(name) {
|
|
164
190
|
return this.typeNamed("cluster", name);
|
|
165
191
|
}
|
|
@@ -260,9 +286,8 @@ export class Network extends Owner {
|
|
|
260
286
|
kind;
|
|
261
287
|
scope;
|
|
262
288
|
metric;
|
|
263
|
-
subnet;
|
|
264
289
|
bridge;
|
|
265
|
-
|
|
290
|
+
gateway;
|
|
266
291
|
|
|
267
292
|
static get typeName() {
|
|
268
293
|
return "network";
|
|
@@ -271,9 +296,9 @@ export class Network extends Owner {
|
|
|
271
296
|
constructor(owner, data) {
|
|
272
297
|
super(owner, data);
|
|
273
298
|
|
|
274
|
-
if (data.
|
|
275
|
-
this
|
|
276
|
-
delete data.
|
|
299
|
+
if (data.subnets) {
|
|
300
|
+
this.addSubnets(data.subnets);
|
|
301
|
+
delete data.subnets;
|
|
277
302
|
}
|
|
278
303
|
|
|
279
304
|
let bridge;
|
|
@@ -284,20 +309,6 @@ export class Network extends Owner {
|
|
|
284
309
|
|
|
285
310
|
Object.assign(this, data);
|
|
286
311
|
|
|
287
|
-
const subnetAddress = this.subnetAddress;
|
|
288
|
-
|
|
289
|
-
if (subnetAddress) {
|
|
290
|
-
let subnet = owner.subnetNamed(subnetAddress);
|
|
291
|
-
if (!subnet) {
|
|
292
|
-
subnet = new Subnet(owner, { name: subnetAddress });
|
|
293
|
-
}
|
|
294
|
-
|
|
295
|
-
this.subnet = subnet;
|
|
296
|
-
subnet.networks.add(this);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
//owner.addObject(this);
|
|
300
|
-
|
|
301
312
|
this.bridge = owner.addBridge(this, bridge);
|
|
302
313
|
}
|
|
303
314
|
|
|
@@ -308,32 +319,11 @@ export class Network extends Owner {
|
|
|
308
319
|
return super.networkNamed(name);
|
|
309
320
|
}
|
|
310
321
|
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
return this.#ipAddresses;
|
|
317
|
-
}
|
|
318
|
-
|
|
319
|
-
get prefixLength() {
|
|
320
|
-
for (const a of this.#ipAddresses) {
|
|
321
|
-
const m = a.match(/\/(\d+)$/);
|
|
322
|
-
if (m) {
|
|
323
|
-
return parseInt(m[1]);
|
|
324
|
-
}
|
|
325
|
-
}
|
|
326
|
-
|
|
327
|
-
this.error("no prefixLength", this.#ipAddresses);
|
|
328
|
-
}
|
|
329
|
-
|
|
330
|
-
get subnetAddress() {
|
|
331
|
-
for (const a of this.#ipAddresses) {
|
|
332
|
-
const [addr, bits] = a.split(/\//);
|
|
333
|
-
if (bits) {
|
|
334
|
-
const parts = addr.split(/\./);
|
|
335
|
-
return parts.slice(0, bits / 8).join(".");
|
|
336
|
-
}
|
|
322
|
+
addSubnets(value) {
|
|
323
|
+
for (const address of asArray(value)) {
|
|
324
|
+
const subnet = this.owner.createSubnet(address);
|
|
325
|
+
this.addObject(subnet);
|
|
326
|
+
subnet.networks.add(this);
|
|
337
327
|
}
|
|
338
328
|
}
|
|
339
329
|
|
|
@@ -341,12 +331,10 @@ export class Network extends Owner {
|
|
|
341
331
|
return [
|
|
342
332
|
...super.propertyNames,
|
|
343
333
|
"kind",
|
|
344
|
-
"ipAddresses",
|
|
345
|
-
"subnet",
|
|
346
|
-
"prefixLength",
|
|
347
334
|
"scope",
|
|
348
335
|
"metric",
|
|
349
|
-
"bridge"
|
|
336
|
+
"bridge",
|
|
337
|
+
"gateway"
|
|
350
338
|
];
|
|
351
339
|
}
|
|
352
340
|
}
|
|
@@ -359,6 +347,16 @@ export class Subnet extends Base {
|
|
|
359
347
|
}
|
|
360
348
|
|
|
361
349
|
constructor(owner, data) {
|
|
350
|
+
const { cidr } = normalizeCIDR(data.name);
|
|
351
|
+
|
|
352
|
+
if(!cidr) {
|
|
353
|
+
const error = Error(`Invalid address`);
|
|
354
|
+
error.address = data.name;
|
|
355
|
+
throw error;
|
|
356
|
+
}
|
|
357
|
+
|
|
358
|
+
data.name = cidr;
|
|
359
|
+
|
|
362
360
|
super(owner, data);
|
|
363
361
|
|
|
364
362
|
Object.assign(this, data);
|
|
@@ -366,12 +364,28 @@ export class Subnet extends Base {
|
|
|
366
364
|
owner.addObject(this);
|
|
367
365
|
}
|
|
368
366
|
|
|
367
|
+
matchesAddress(address) {
|
|
368
|
+
return address.startsWith(this.prefix);
|
|
369
|
+
}
|
|
370
|
+
|
|
371
|
+
get prefix() {
|
|
372
|
+
const [prefix] = this.name.split("/");
|
|
373
|
+
return prefix;
|
|
374
|
+
}
|
|
375
|
+
|
|
376
|
+
get prefixLength() {
|
|
377
|
+
const m = this.name.match(/\/(\d+)$/);
|
|
378
|
+
if (m) {
|
|
379
|
+
return parseInt(m[1]);
|
|
380
|
+
}
|
|
381
|
+
}
|
|
382
|
+
|
|
369
383
|
get address() {
|
|
370
384
|
return this.name;
|
|
371
385
|
}
|
|
372
386
|
|
|
373
387
|
get propertyNames() {
|
|
374
|
-
return [...super.propertyNames, "networks"];
|
|
388
|
+
return [...super.propertyNames, "networks", "prefixLength"];
|
|
375
389
|
}
|
|
376
390
|
|
|
377
391
|
_traverse(...args) {
|
package/src/utils.mjs
CHANGED
|
@@ -52,3 +52,21 @@ export function normalizeIPAddress(address) {
|
|
|
52
52
|
}
|
|
53
53
|
return parts.map(s => s.padStart(4, "0")).join(":");
|
|
54
54
|
}
|
|
55
|
+
|
|
56
|
+
export function normalizeCIDR(address) {
|
|
57
|
+
let [prefix, prefixLength] = address.split(/\//);
|
|
58
|
+
|
|
59
|
+
if (prefixLength) {
|
|
60
|
+
if (isIPv4Address(prefix)) {
|
|
61
|
+
const parts = prefix.split(/\./);
|
|
62
|
+
prefix = parts.slice(0, prefixLength / 8).join(".");
|
|
63
|
+
} else {
|
|
64
|
+
prefix = normalizeIPAddress(prefix);
|
|
65
|
+
}
|
|
66
|
+
}
|
|
67
|
+
else {
|
|
68
|
+
return {};
|
|
69
|
+
}
|
|
70
|
+
|
|
71
|
+
return { prefix, prefixLength, cidr: `${prefix}/${prefixLength}` };
|
|
72
|
+
}
|
package/types/model.d.mts
CHANGED
|
@@ -38,10 +38,12 @@ export class Host extends Base {
|
|
|
38
38
|
services(filter: any): Generator<any, void, unknown>;
|
|
39
39
|
addNetworkInterface(networkInterface: any): void;
|
|
40
40
|
networkAddresses(): Generator<{
|
|
41
|
-
address: any;
|
|
42
41
|
networkInterface: any;
|
|
42
|
+
address: any;
|
|
43
|
+
addressWithPrefixLength: any;
|
|
43
44
|
}, void, unknown>;
|
|
44
45
|
get ipAddresses(): any[];
|
|
46
|
+
get ipAddressesWithPrefixLength(): any[];
|
|
45
47
|
get ipAddress(): any;
|
|
46
48
|
publicKey(type?: string): Promise<string>;
|
|
47
49
|
toJSON(): {
|
|
@@ -55,8 +57,11 @@ export class NetworkInterface extends Base {
|
|
|
55
57
|
hwaddr: any;
|
|
56
58
|
set network(networkOrName: any);
|
|
57
59
|
get network(): any;
|
|
58
|
-
|
|
59
|
-
get
|
|
60
|
+
set ipAddresses(value: MapIterator<any>);
|
|
61
|
+
get ipAddresses(): MapIterator<any>;
|
|
62
|
+
subnetForAddress(address: any): any;
|
|
63
|
+
addressWithPrefixLength(address: any): string;
|
|
64
|
+
get ipAddressesWithPrefixLength(): string[];
|
|
60
65
|
get ipv4Addresses(): any[];
|
|
61
66
|
get ipv6Addresses(): any[];
|
|
62
67
|
get prefixLength(): any;
|
package/types/owner.d.mts
CHANGED
|
@@ -21,6 +21,8 @@ export class Owner extends Base {
|
|
|
21
21
|
networks(): Generator<any, void, unknown>;
|
|
22
22
|
subnetNamed(name: any): any;
|
|
23
23
|
subnets(): Generator<any, void, unknown>;
|
|
24
|
+
subnetForAddress(address: any): any;
|
|
25
|
+
createSubnet(address: any): any;
|
|
24
26
|
clusterNamed(name: any): any;
|
|
25
27
|
clusters(): Generator<any, void, unknown>;
|
|
26
28
|
addBridge(network: any, destinationNetworks: any): any;
|
|
@@ -34,16 +36,15 @@ export class Network extends Owner {
|
|
|
34
36
|
kind: any;
|
|
35
37
|
scope: any;
|
|
36
38
|
metric: any;
|
|
37
|
-
subnet: any;
|
|
38
39
|
bridge: any;
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
get prefixLength(): number;
|
|
42
|
-
get subnetAddress(): any;
|
|
43
|
-
#private;
|
|
40
|
+
gateway: any;
|
|
41
|
+
addSubnets(value: any): void;
|
|
44
42
|
}
|
|
45
43
|
export class Subnet extends Base {
|
|
46
44
|
networks: Set<any>;
|
|
45
|
+
matchesAddress(address: any): any;
|
|
46
|
+
get prefix(): any;
|
|
47
|
+
get prefixLength(): number;
|
|
47
48
|
get address(): any;
|
|
48
49
|
_traverse(...args: any[]): boolean;
|
|
49
50
|
}
|
package/types/utils.d.mts
CHANGED
|
@@ -5,3 +5,12 @@ export function asArray(value: any): any[];
|
|
|
5
5
|
export function isIPv4Address(address: any): boolean;
|
|
6
6
|
export function isIPv6Address(address: any): boolean;
|
|
7
7
|
export function normalizeIPAddress(address: any): any;
|
|
8
|
+
export function normalizeCIDR(address: any): {
|
|
9
|
+
prefix?: undefined;
|
|
10
|
+
prefixLength?: undefined;
|
|
11
|
+
cidr?: undefined;
|
|
12
|
+
} | {
|
|
13
|
+
prefix: any;
|
|
14
|
+
prefixLength: any;
|
|
15
|
+
cidr: string;
|
|
16
|
+
};
|