pmcf 1.9.2 → 1.11.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-location-defs +2 -2
- package/bin/pmcf-named-defs +6 -6
- package/package.json +1 -1
- package/src/model.mjs +138 -58
- package/types/model.d.mts +21 -8
package/bin/pmcf-location-defs
CHANGED
|
@@ -21,7 +21,7 @@ console.log("replaces", `mf-location-${location.name}`);
|
|
|
21
21
|
console.log("description", `location definitions for ${location.name}`);
|
|
22
22
|
|
|
23
23
|
async function generateLocationDefs(location, dir) {
|
|
24
|
-
const sl = location.
|
|
24
|
+
const sl = (await Array.fromAsync(location.dns.services())).map(s=>s.ipAddress);
|
|
25
25
|
const s1 = sl.shift();
|
|
26
26
|
|
|
27
27
|
await writeLines(
|
|
@@ -51,7 +51,7 @@ async function generateLocationDefs(location, dir) {
|
|
|
51
51
|
join(dir, "etc/systemd/timesyncd.conf.d"),
|
|
52
52
|
`${location.name}.conf`,
|
|
53
53
|
sectionLines("Time", {
|
|
54
|
-
NTP: location.
|
|
54
|
+
NTP: location.ntp.servers.join(" "),
|
|
55
55
|
PollIntervalMinSec: 60,
|
|
56
56
|
SaveIntervalSec: 3600
|
|
57
57
|
})
|
package/bin/pmcf-named-defs
CHANGED
|
@@ -8,7 +8,6 @@ import { prepare } from "../src/cmd.mjs";
|
|
|
8
8
|
const { world, args, options } = prepare();
|
|
9
9
|
|
|
10
10
|
const location = await world.location(args[0] || "SW");
|
|
11
|
-
const ttl = location.dnsRecordTTL;
|
|
12
11
|
const updates = [
|
|
13
12
|
Math.ceil(Date.now() / 1000),
|
|
14
13
|
36000,
|
|
@@ -30,7 +29,9 @@ console.log("description", `named defintions for ${location.name}`);
|
|
|
30
29
|
}*/
|
|
31
30
|
|
|
32
31
|
async function generateNamedDefs(location, targetDir) {
|
|
32
|
+
const dns = location.dns;
|
|
33
33
|
const domain = location.domain;
|
|
34
|
+
const ttl = dns.recordTTL;
|
|
34
35
|
|
|
35
36
|
if (domain) {
|
|
36
37
|
const zones = [];
|
|
@@ -106,7 +107,7 @@ async function generateNamedDefs(location, targetDir) {
|
|
|
106
107
|
} ${normalizeIPAddress(address)}`
|
|
107
108
|
);
|
|
108
109
|
|
|
109
|
-
for (const service of
|
|
110
|
+
for (const service of host.services()) {
|
|
110
111
|
if (service.master && service.alias) {
|
|
111
112
|
zone.records.add(
|
|
112
113
|
`${service.alias.padEnd(NAME_LEN, " ")} ${ttl} IN CNAME ${
|
|
@@ -115,9 +116,9 @@ async function generateNamedDefs(location, targetDir) {
|
|
|
115
116
|
);
|
|
116
117
|
}
|
|
117
118
|
|
|
118
|
-
if (service.
|
|
119
|
+
if (service.srvPrefix) {
|
|
119
120
|
zone.records.add(
|
|
120
|
-
`${`${service.
|
|
121
|
+
`${`${service.srvPrefix}.${host.domainName}.`.padEnd(
|
|
121
122
|
NAME_LEN,
|
|
122
123
|
" "
|
|
123
124
|
)} ${ttl} IN SRV ${String(service.priority).padStart(4)} ${String(
|
|
@@ -157,9 +158,8 @@ async function generateNamedDefs(location, targetDir) {
|
|
|
157
158
|
zoneConfig.push(` type master;`);
|
|
158
159
|
zoneConfig.push(` file \"${zone.file}\";`);
|
|
159
160
|
|
|
160
|
-
const u = location.dnsAllowedUpdates;
|
|
161
161
|
zoneConfig.push(
|
|
162
|
-
` allow-update { ${
|
|
162
|
+
` allow-update { ${dns.allowedUpdates.length ? dns.allowedUpdates.join(";") : "none"}; };`
|
|
163
163
|
);
|
|
164
164
|
zoneConfig.push(` notify yes;`);
|
|
165
165
|
zoneConfig.push(`};`);
|
package/package.json
CHANGED
package/src/model.mjs
CHANGED
|
@@ -41,6 +41,14 @@ export class Base {
|
|
|
41
41
|
}
|
|
42
42
|
}
|
|
43
43
|
|
|
44
|
+
withOwner(owner) {
|
|
45
|
+
if (this.owner !== owner) {
|
|
46
|
+
return new this.constructor(owner, this);
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
return this;
|
|
50
|
+
}
|
|
51
|
+
|
|
44
52
|
get typeName() {
|
|
45
53
|
return this.constructor.typeName;
|
|
46
54
|
}
|
|
@@ -77,7 +85,7 @@ export class Base {
|
|
|
77
85
|
}
|
|
78
86
|
|
|
79
87
|
get fullName() {
|
|
80
|
-
return join(this.owner.fullName, this.name);
|
|
88
|
+
return this.owner ? join(this.owner.fullName, this.name) : this.name;
|
|
81
89
|
}
|
|
82
90
|
|
|
83
91
|
expand(object) {
|
|
@@ -140,6 +148,25 @@ export class Owner extends Base {
|
|
|
140
148
|
this.addObject(host);
|
|
141
149
|
}
|
|
142
150
|
|
|
151
|
+
async service(filter) {
|
|
152
|
+
let best;
|
|
153
|
+
for await (const service of this.services(filter)) {
|
|
154
|
+
if (!best || service.priority < best.priority) {
|
|
155
|
+
best = service;
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
return best;
|
|
160
|
+
}
|
|
161
|
+
|
|
162
|
+
async *services(filter) {
|
|
163
|
+
for await (const host of this.hosts()) {
|
|
164
|
+
for await (const service of host.services(filter)) {
|
|
165
|
+
yield service;
|
|
166
|
+
}
|
|
167
|
+
}
|
|
168
|
+
}
|
|
169
|
+
|
|
143
170
|
network(name) {
|
|
144
171
|
return this.#networks.get(name);
|
|
145
172
|
}
|
|
@@ -192,7 +219,7 @@ export class Owner extends Base {
|
|
|
192
219
|
|
|
193
220
|
_resolveBridges() {
|
|
194
221
|
for (const bridge of this.#bridges) {
|
|
195
|
-
|
|
222
|
+
this.info(bridgeToJSON(bridge));
|
|
196
223
|
for (const network of bridge) {
|
|
197
224
|
if (typeof network === "string") {
|
|
198
225
|
const other = this.network(network);
|
|
@@ -201,7 +228,7 @@ export class Owner extends Base {
|
|
|
201
228
|
bridge.delete(network);
|
|
202
229
|
bridge.add(other);
|
|
203
230
|
other.bridge = bridge;
|
|
204
|
-
|
|
231
|
+
this.info("RESOLVE", network, other, bridgeToJSON(bridge));
|
|
205
232
|
} else {
|
|
206
233
|
this.error(`Unresolvabale bridge network`, network);
|
|
207
234
|
}
|
|
@@ -386,9 +413,34 @@ export class World extends Owner {
|
|
|
386
413
|
}
|
|
387
414
|
}
|
|
388
415
|
|
|
416
|
+
class DNSService {
|
|
417
|
+
owner;
|
|
418
|
+
|
|
419
|
+
allowedUpdates = [];
|
|
420
|
+
recordTTL = "1W";
|
|
421
|
+
forwardsTo = [];
|
|
422
|
+
|
|
423
|
+
constructor(owner, data) {
|
|
424
|
+
this.owner = owner;
|
|
425
|
+
Object.assign(this, data);
|
|
426
|
+
}
|
|
427
|
+
|
|
428
|
+
async *services() {
|
|
429
|
+
const filter = { type: "dns" };
|
|
430
|
+
|
|
431
|
+
yield* this.owner.services(filter);
|
|
432
|
+
|
|
433
|
+
for (const s of this.forwardsTo) {
|
|
434
|
+
const owner = await this.owner.world.load(s);
|
|
435
|
+
yield* owner.services(filter);
|
|
436
|
+
}
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
|
|
389
440
|
export class Location extends Owner {
|
|
390
441
|
domain;
|
|
391
|
-
dns;
|
|
442
|
+
#dns;
|
|
443
|
+
ntp = { servers: [] };
|
|
392
444
|
#administratorEmail;
|
|
393
445
|
|
|
394
446
|
static get typeName() {
|
|
@@ -398,6 +450,13 @@ export class Location extends Owner {
|
|
|
398
450
|
constructor(owner, data) {
|
|
399
451
|
super(owner, data);
|
|
400
452
|
|
|
453
|
+
let dns;
|
|
454
|
+
if (data.dns) {
|
|
455
|
+
dns = data.dns;
|
|
456
|
+
delete data.dns;
|
|
457
|
+
}
|
|
458
|
+
|
|
459
|
+
this.#dns = new DNSService(this, dns);
|
|
401
460
|
const networks = data.networks;
|
|
402
461
|
delete data.networks;
|
|
403
462
|
Object.assign(this, data);
|
|
@@ -418,31 +477,10 @@ export class Location extends Owner {
|
|
|
418
477
|
}
|
|
419
478
|
}
|
|
420
479
|
|
|
421
|
-
|
|
422
|
-
|
|
423
|
-
for await (const service of this.services(filter)) {
|
|
424
|
-
if (!best || service.priority < best.priority) {
|
|
425
|
-
best = service;
|
|
426
|
-
}
|
|
427
|
-
}
|
|
428
|
-
|
|
429
|
-
return best;
|
|
480
|
+
get dns() {
|
|
481
|
+
return this.#dns;
|
|
430
482
|
}
|
|
431
483
|
|
|
432
|
-
async *services(filter) {
|
|
433
|
-
for await (const host of this.hosts()) {
|
|
434
|
-
for (const service of Object.values(host.services)) {
|
|
435
|
-
if (
|
|
436
|
-
!filter ||
|
|
437
|
-
filter.type === "*" ||
|
|
438
|
-
filter.type === service.type ||
|
|
439
|
-
filter.name === service.name
|
|
440
|
-
) {
|
|
441
|
-
yield service;
|
|
442
|
-
}
|
|
443
|
-
}
|
|
444
|
-
}
|
|
445
|
-
}
|
|
446
484
|
|
|
447
485
|
async *networkAddresses() {
|
|
448
486
|
for await (const host of this.hosts()) {
|
|
@@ -452,14 +490,6 @@ export class Location extends Owner {
|
|
|
452
490
|
}
|
|
453
491
|
}
|
|
454
492
|
|
|
455
|
-
get dnsAllowedUpdates() {
|
|
456
|
-
return this.dns?.allowedUpdates || [];
|
|
457
|
-
}
|
|
458
|
-
|
|
459
|
-
get dnsRecordTTL() {
|
|
460
|
-
return this.dns?.recordTTL || "1W";
|
|
461
|
-
}
|
|
462
|
-
|
|
463
493
|
get administratorEmail() {
|
|
464
494
|
return this.#administratorEmail || "admin@" + this.domain;
|
|
465
495
|
}
|
|
@@ -538,9 +568,8 @@ export class Network extends Owner {
|
|
|
538
568
|
|
|
539
569
|
export class Host extends Base {
|
|
540
570
|
networkInterfaces = {};
|
|
541
|
-
services = {};
|
|
542
571
|
postinstall = [];
|
|
543
|
-
#
|
|
572
|
+
#services = [];
|
|
544
573
|
#extends = [];
|
|
545
574
|
#provides = new Set();
|
|
546
575
|
#replaces = new Set();
|
|
@@ -618,7 +647,21 @@ export class Host extends Base {
|
|
|
618
647
|
delete data.provides;
|
|
619
648
|
}
|
|
620
649
|
|
|
621
|
-
|
|
650
|
+
if (data.services) {
|
|
651
|
+
for (const [name, sd] of Object.entries(data.services)) {
|
|
652
|
+
sd.name = name;
|
|
653
|
+
new Service(this, sd);
|
|
654
|
+
}
|
|
655
|
+
delete data.services;
|
|
656
|
+
}
|
|
657
|
+
|
|
658
|
+
for (const host of this.extends) {
|
|
659
|
+
for (const service of host.services()) {
|
|
660
|
+
service.withOwner(this);
|
|
661
|
+
}
|
|
662
|
+
}
|
|
663
|
+
|
|
664
|
+
Object.assign(this, { networkInterfaces: {} }, data);
|
|
622
665
|
|
|
623
666
|
owner.addHost(this);
|
|
624
667
|
|
|
@@ -626,13 +669,6 @@ export class Host extends Base {
|
|
|
626
669
|
iface.name = name;
|
|
627
670
|
this.networkInterfaces[name] = new NetworkInterface(this, iface);
|
|
628
671
|
}
|
|
629
|
-
|
|
630
|
-
for (const [name, data] of Object.entries(
|
|
631
|
-
Object.assign({}, ...this.extends.map(e => e.services), this.services)
|
|
632
|
-
)) {
|
|
633
|
-
data.name = name;
|
|
634
|
-
this.services[name] = new Service(this, data);
|
|
635
|
-
}
|
|
636
672
|
}
|
|
637
673
|
|
|
638
674
|
get deployment() {
|
|
@@ -648,7 +684,7 @@ export class Host extends Base {
|
|
|
648
684
|
}
|
|
649
685
|
|
|
650
686
|
get isModel() {
|
|
651
|
-
return
|
|
687
|
+
return this.#vendor || this.#chassis ? true : false;
|
|
652
688
|
}
|
|
653
689
|
|
|
654
690
|
get model() {
|
|
@@ -714,6 +750,23 @@ export class Host extends Base {
|
|
|
714
750
|
return this.hostName + "." + this.domain;
|
|
715
751
|
}
|
|
716
752
|
|
|
753
|
+
addService(service) {
|
|
754
|
+
this.#services.push(service);
|
|
755
|
+
}
|
|
756
|
+
|
|
757
|
+
*services(filter) {
|
|
758
|
+
for (const service of this.#services) {
|
|
759
|
+
if (
|
|
760
|
+
!filter ||
|
|
761
|
+
filter.type === "*" ||
|
|
762
|
+
filter.type === service.type ||
|
|
763
|
+
filter.name === service.name
|
|
764
|
+
) {
|
|
765
|
+
yield service;
|
|
766
|
+
}
|
|
767
|
+
}
|
|
768
|
+
}
|
|
769
|
+
|
|
717
770
|
*networkAddresses() {
|
|
718
771
|
for (const [name, networkInterface] of Object.entries(
|
|
719
772
|
this.networkInterfaces
|
|
@@ -756,7 +809,7 @@ export class Host extends Base {
|
|
|
756
809
|
...super.toJSON(),
|
|
757
810
|
extends: this.extends.map(host => host.name),
|
|
758
811
|
services: Object.fromEntries(
|
|
759
|
-
|
|
812
|
+
[...this.services()].map(s => [s.name, s.toJSON()])
|
|
760
813
|
)
|
|
761
814
|
};
|
|
762
815
|
}
|
|
@@ -810,15 +863,15 @@ export class Subnet extends Base {
|
|
|
810
863
|
}
|
|
811
864
|
|
|
812
865
|
const ServiceTypes = {
|
|
813
|
-
dns: {
|
|
814
|
-
ldap: {
|
|
815
|
-
http: {
|
|
816
|
-
https: {
|
|
817
|
-
rtsp: {
|
|
818
|
-
smtp: {
|
|
819
|
-
ssh: {
|
|
820
|
-
imap: {
|
|
821
|
-
imaps: {
|
|
866
|
+
dns: { srvPrefix: "_dns._udp", port: 53 },
|
|
867
|
+
ldap: { srvPrefix: "_ldap._tcp", port: 389 },
|
|
868
|
+
http: { srvPrefix: "_http._tcp", port: 80 },
|
|
869
|
+
https: { srvPrefix: "_http._tcp", port: 443 },
|
|
870
|
+
rtsp: { srvPrefix: "_rtsp._tcp", port: 554 },
|
|
871
|
+
smtp: { srvPrefix: "_smtp._tcp", port: 25 },
|
|
872
|
+
ssh: { srvPrefix: "_ssh._tcp", port: 22 },
|
|
873
|
+
imap: { srvPrefix: "_imap._tcp", port: 143 },
|
|
874
|
+
imaps: { srvPrefix: "_imaps._tcp", port: 993 },
|
|
822
875
|
dhcp: {}
|
|
823
876
|
};
|
|
824
877
|
|
|
@@ -858,11 +911,38 @@ export class Service extends Base {
|
|
|
858
911
|
}
|
|
859
912
|
|
|
860
913
|
Object.assign(this, data);
|
|
914
|
+
|
|
861
915
|
this.owner = owner;
|
|
916
|
+
|
|
917
|
+
owner.addService(this);
|
|
918
|
+
}
|
|
919
|
+
|
|
920
|
+
withOwner(owner) {
|
|
921
|
+
if (this.owner !== owner) {
|
|
922
|
+
const data = { name: this.name };
|
|
923
|
+
if (this.alias) {
|
|
924
|
+
data.alias = this.alias;
|
|
925
|
+
}
|
|
926
|
+
if (this.#type) {
|
|
927
|
+
data.type = this.#type;
|
|
928
|
+
}
|
|
929
|
+
if (this.#weight) {
|
|
930
|
+
data.weight = this.#weight;
|
|
931
|
+
}
|
|
932
|
+
if (this.#port) {
|
|
933
|
+
data.port = this.#port;
|
|
934
|
+
}
|
|
935
|
+
if (this.#ipAddress) {
|
|
936
|
+
data.ipAddress = this.#ipAddress;
|
|
937
|
+
}
|
|
938
|
+
return new this.constructor(owner, data);
|
|
939
|
+
}
|
|
940
|
+
|
|
941
|
+
return this;
|
|
862
942
|
}
|
|
863
943
|
|
|
864
|
-
get
|
|
865
|
-
return ServiceTypes[this.type]?.
|
|
944
|
+
get srvPrefix() {
|
|
945
|
+
return ServiceTypes[this.type]?.srvPrefix;
|
|
866
946
|
}
|
|
867
947
|
|
|
868
948
|
get ipAddress() {
|
package/types/model.d.mts
CHANGED
|
@@ -10,6 +10,7 @@ export class Base {
|
|
|
10
10
|
owner: any;
|
|
11
11
|
name: any;
|
|
12
12
|
description: any;
|
|
13
|
+
withOwner(owner: any): any;
|
|
13
14
|
get typeName(): any;
|
|
14
15
|
get world(): any;
|
|
15
16
|
get location(): any;
|
|
@@ -17,7 +18,7 @@ export class Base {
|
|
|
17
18
|
network(name: any): Promise<any>;
|
|
18
19
|
set directory(directory: any);
|
|
19
20
|
get directory(): any;
|
|
20
|
-
get fullName():
|
|
21
|
+
get fullName(): any;
|
|
21
22
|
expand(object: any): any;
|
|
22
23
|
error(...args: any[]): void;
|
|
23
24
|
info(...args: any[]): void;
|
|
@@ -30,6 +31,8 @@ export class Owner extends Base {
|
|
|
30
31
|
hosts(): AsyncGenerator<any, void, unknown>;
|
|
31
32
|
addObject(object: any): void;
|
|
32
33
|
addHost(host: any): void;
|
|
34
|
+
service(filter: any): Promise<any>;
|
|
35
|
+
services(filter: any): AsyncGenerator<any, void, unknown>;
|
|
33
36
|
network(name: any): any;
|
|
34
37
|
networks(): AsyncGenerator<any, void, unknown>;
|
|
35
38
|
addNetwork(network: any): void;
|
|
@@ -53,6 +56,7 @@ export class World extends Owner {
|
|
|
53
56
|
[k: string]: typeof Location | typeof Host | typeof Network | typeof Subnet | typeof Service;
|
|
54
57
|
};
|
|
55
58
|
constructor(directory: any);
|
|
59
|
+
get fullName(): string;
|
|
56
60
|
get world(): this;
|
|
57
61
|
load(name: any, options: any): any;
|
|
58
62
|
loadAll(): Promise<void>;
|
|
@@ -70,12 +74,11 @@ export class World extends Owner {
|
|
|
70
74
|
}
|
|
71
75
|
export class Location extends Owner {
|
|
72
76
|
domain: any;
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
77
|
+
ntp: {
|
|
78
|
+
servers: any[];
|
|
79
|
+
};
|
|
80
|
+
get dns(): DNSService;
|
|
76
81
|
networkAddresses(): AsyncGenerator<any, void, unknown>;
|
|
77
|
-
get dnsAllowedUpdates(): any;
|
|
78
|
-
get dnsRecordTTL(): any;
|
|
79
82
|
get administratorEmail(): any;
|
|
80
83
|
#private;
|
|
81
84
|
}
|
|
@@ -92,7 +95,6 @@ export class Network extends Owner {
|
|
|
92
95
|
export class Host extends Base {
|
|
93
96
|
static prepareData(world: any, data: any): Promise<typeof Host>;
|
|
94
97
|
networkInterfaces: {};
|
|
95
|
-
services: {};
|
|
96
98
|
postinstall: any[];
|
|
97
99
|
get deployment(): any;
|
|
98
100
|
get chassis(): any;
|
|
@@ -111,6 +113,8 @@ export class Host extends Base {
|
|
|
111
113
|
get modelName(): any;
|
|
112
114
|
get hostName(): any;
|
|
113
115
|
get domainName(): string;
|
|
116
|
+
addService(service: any): void;
|
|
117
|
+
services(filter: any): Generator<any, void, unknown>;
|
|
114
118
|
networkAddresses(): Generator<{
|
|
115
119
|
address: any;
|
|
116
120
|
networkInterface: any;
|
|
@@ -131,7 +135,7 @@ export class Subnet extends Base {
|
|
|
131
135
|
}
|
|
132
136
|
export class Service extends Base {
|
|
133
137
|
alias: any;
|
|
134
|
-
get
|
|
138
|
+
get srvPrefix(): any;
|
|
135
139
|
get ipAddress(): any;
|
|
136
140
|
get port(): any;
|
|
137
141
|
get priority(): any;
|
|
@@ -140,3 +144,12 @@ export class Service extends Base {
|
|
|
140
144
|
get type(): any;
|
|
141
145
|
#private;
|
|
142
146
|
}
|
|
147
|
+
declare class DNSService {
|
|
148
|
+
constructor(owner: any, data: any);
|
|
149
|
+
owner: any;
|
|
150
|
+
allowedUpdates: any[];
|
|
151
|
+
recordTTL: string;
|
|
152
|
+
forwardsTo: any[];
|
|
153
|
+
services(): AsyncGenerator<any, void, any>;
|
|
154
|
+
}
|
|
155
|
+
export {};
|