pmcf 4.19.1 → 4.20.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/README.md +93 -72
- package/bin/pmcf-diagram +1 -1
- package/package.json +19 -19
- package/src/base.mjs +24 -237
- package/src/cli.mjs +4 -4
- package/src/cluster.mjs +15 -13
- package/src/extra-source-service.mjs +7 -10
- package/src/host.mjs +30 -44
- package/src/initialization-context.mjs +324 -0
- package/src/location.mjs +4 -14
- package/src/module.mjs +1 -0
- package/src/network-interfaces/ethernet.mjs +3 -5
- package/src/network-interfaces/loopback.mjs +2 -4
- package/src/network-interfaces/network-interface.mjs +3 -5
- package/src/network-interfaces/skeleton.mjs +9 -3
- package/src/network-interfaces/tun.mjs +2 -4
- package/src/network-interfaces/wireguard.mjs +3 -5
- package/src/network-interfaces/wlan.mjs +4 -7
- package/src/network.mjs +10 -8
- package/src/owner.mjs +8 -32
- package/src/root.mjs +4 -73
- package/src/service-owner.mjs +19 -18
- package/src/service.mjs +13 -18
- package/src/services/alpm.mjs +4 -9
- package/src/services/bind.mjs +424 -388
- package/src/services/chrony.mjs +3 -5
- package/src/services/headscale.mjs +2 -4
- package/src/services/influxdb.mjs +2 -4
- package/src/services/kea.mjs +6 -10
- package/src/services/mosquitto.mjs +2 -4
- package/src/services/openldap.mjs +2 -4
- package/src/services/postfix.mjs +2 -4
- package/src/services/systemd-journal-remote.mjs +2 -4
- package/src/services/systemd-journal-upload.mjs +9 -10
- package/src/services/systemd-journald.mjs +2 -4
- package/src/services/systemd-resolved.mjs +42 -42
- package/src/services/systemd-timesyncd.mjs +9 -13
- package/src/services/tailscale.mjs +5 -2
- package/src/subnet.mjs +9 -5
- package/types/base.d.mts +0 -179
- package/types/cli.d.mts +0 -10
- package/types/cluster.d.mts +0 -507
- package/types/dns-utils.d.mts +0 -14
- package/types/endpoint.d.mts +0 -79
- package/types/extra-source-service.d.mts +0 -1033
- package/types/hooks.d.mts +0 -2
- package/types/host-utils.d.mts +0 -1
- package/types/host.d.mts +0 -285
- package/types/location.d.mts +0 -379
- package/types/module.d.mts +0 -36
- package/types/network-address.d.mts +0 -41
- package/types/network-interfaces/ethernet.d.mts +0 -1189
- package/types/network-interfaces/loopback.d.mts +0 -1140
- package/types/network-interfaces/network-interface.d.mts +0 -1158
- package/types/network-interfaces/skeleton.d.mts +0 -30
- package/types/network-interfaces/tun.d.mts +0 -1131
- package/types/network-interfaces/wireguard.d.mts +0 -1131
- package/types/network-interfaces/wlan.d.mts +0 -1734
- package/types/network-support.d.mts +0 -193
- package/types/network.d.mts +0 -702
- package/types/owner.d.mts +0 -235
- package/types/root.d.mts +0 -10
- package/types/service-owner.d.mts +0 -14
- package/types/service-types.d.mts +0 -246
- package/types/service.d.mts +0 -689
- package/types/services/alpm.d.mts +0 -805
- package/types/services/bind.d.mts +0 -1574
- package/types/services/chrony.d.mts +0 -1310
- package/types/services/headscale.d.mts +0 -801
- package/types/services/influxdb.d.mts +0 -812
- package/types/services/kea.d.mts +0 -945
- package/types/services/mosquitto.d.mts +0 -876
- package/types/services/openldap.d.mts +0 -793
- package/types/services/postfix.d.mts +0 -784
- package/types/services/systemd-journal-remote.d.mts +0 -1030
- package/types/services/systemd-journal-upload.d.mts +0 -932
- package/types/services/systemd-journald.d.mts +0 -1317
- package/types/services/systemd-resolved.d.mts +0 -1644
- package/types/services/systemd-timesyncd.d.mts +0 -1459
- package/types/services/tailscale.d.mts +0 -781
- package/types/subnet.d.mts +0 -57
- package/types/utils.d.mts +0 -37
package/src/cluster.mjs
CHANGED
|
@@ -14,6 +14,7 @@ import { writeLines } from "./utils.mjs";
|
|
|
14
14
|
|
|
15
15
|
const ClusterTypeDefinition = {
|
|
16
16
|
name: "cluster",
|
|
17
|
+
priority: 1.5,
|
|
17
18
|
owners: [Owner.typeDefinition, "network", "location", "root"],
|
|
18
19
|
extends: Host.typeDefinition,
|
|
19
20
|
key: "name",
|
|
@@ -39,18 +40,16 @@ const ClusterTypeDefinition = {
|
|
|
39
40
|
};
|
|
40
41
|
|
|
41
42
|
export class Cluster extends Host {
|
|
42
|
-
|
|
43
|
-
_backups = [];
|
|
44
|
-
routerId = 100;
|
|
45
|
-
checkInterval = 60;
|
|
43
|
+
static typeDefinition = ClusterTypeDefinition;
|
|
46
44
|
|
|
47
45
|
static {
|
|
48
46
|
addType(this);
|
|
49
47
|
}
|
|
50
48
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
49
|
+
_masters = [];
|
|
50
|
+
_backups = [];
|
|
51
|
+
routerId = 100;
|
|
52
|
+
checkInterval = 60;
|
|
54
53
|
|
|
55
54
|
set masters(value) {
|
|
56
55
|
this._masters.push(value);
|
|
@@ -76,7 +75,7 @@ export class Cluster extends Host {
|
|
|
76
75
|
}
|
|
77
76
|
|
|
78
77
|
async *preparePackages(stagingDir) {
|
|
79
|
-
for (const ni of [...this.owner.clusters
|
|
78
|
+
for (const ni of [...this.owner.clusters].reduce(
|
|
80
79
|
(all, cluster) => all.union(cluster.members),
|
|
81
80
|
new Set()
|
|
82
81
|
)) {
|
|
@@ -117,7 +116,7 @@ export class Cluster extends Host {
|
|
|
117
116
|
""
|
|
118
117
|
];
|
|
119
118
|
|
|
120
|
-
for (const cluster of [...this.owner.clusters
|
|
119
|
+
for (const cluster of [...this.owner.clusters].sort((a, b) =>
|
|
121
120
|
a.name.localeCompare(b.name)
|
|
122
121
|
)) {
|
|
123
122
|
cfg.push(`vrrp_instance ${cluster.name} {`);
|
|
@@ -166,7 +165,7 @@ export class Cluster extends Host {
|
|
|
166
165
|
cfg.push("}", "");
|
|
167
166
|
|
|
168
167
|
for (const endpoint of serviceEndpoints(cluster, {
|
|
169
|
-
services:
|
|
168
|
+
services: "services[types[http]]",
|
|
170
169
|
endpoints: e =>
|
|
171
170
|
e.networkInterface && e.networkInterface.kind !== "loopback"
|
|
172
171
|
})) {
|
|
@@ -177,10 +176,13 @@ export class Cluster extends Host {
|
|
|
177
176
|
cfg.push(` protocol ${endpoint.protocol.toUpperCase()}`);
|
|
178
177
|
|
|
179
178
|
for (const member of this.members) {
|
|
180
|
-
const memberService =
|
|
181
|
-
member.
|
|
182
|
-
|
|
179
|
+
const memberService = Array.from(
|
|
180
|
+
member.expression(
|
|
181
|
+
`aggregatedServices[types[${endpoint.type}]][0]`
|
|
182
|
+
)
|
|
183
|
+
);
|
|
183
184
|
|
|
185
|
+
console.log(member.fullName, endpoint.type, memberService);
|
|
184
186
|
cfg.push(` real_server ${member.address} ${memberService.port} {`);
|
|
185
187
|
cfg.push(` weight ${memberService.weight}`);
|
|
186
188
|
|
|
@@ -17,25 +17,22 @@ export const ExtraSourceServiceTypeDefinition = {
|
|
|
17
17
|
};
|
|
18
18
|
|
|
19
19
|
export class ExtraSourceService extends Service {
|
|
20
|
-
|
|
20
|
+
static typeDefinition = ExtraSourceServiceTypeDefinition;
|
|
21
21
|
|
|
22
22
|
static {
|
|
23
23
|
addType(this);
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
-
|
|
27
|
-
return ExtraSourceServiceTypeDefinition;
|
|
28
|
-
}
|
|
26
|
+
source = [];
|
|
29
27
|
|
|
30
28
|
get type() {
|
|
31
29
|
return ExtraSourceServiceTypeDefinition.name;
|
|
32
30
|
}
|
|
33
31
|
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
}
|
|
32
|
+
get services() {
|
|
33
|
+
return [
|
|
34
|
+
this.owner.owner.services,
|
|
35
|
+
...this.source.map(s => s.services)
|
|
36
|
+
].flat();
|
|
40
37
|
}
|
|
41
38
|
}
|
package/src/host.mjs
CHANGED
|
@@ -26,6 +26,7 @@ import { NetworkInterfaceTypeDefinition } from "./network-interfaces/network-int
|
|
|
26
26
|
|
|
27
27
|
const HostTypeDefinition = {
|
|
28
28
|
name: "host",
|
|
29
|
+
priority: 1.9,
|
|
29
30
|
owners: ["owner", "network", "root"],
|
|
30
31
|
extends: Base.typeDefinition,
|
|
31
32
|
key: "name",
|
|
@@ -76,7 +77,7 @@ const HostTypeDefinition = {
|
|
|
76
77
|
},
|
|
77
78
|
architecture: {
|
|
78
79
|
...string_attribute_writable,
|
|
79
|
-
values: ["x86", "x86_64", "aarch64", "armv7"]
|
|
80
|
+
values: ["x86", "x86_64", "aarch64", "armv7", "riscv"]
|
|
80
81
|
},
|
|
81
82
|
replaces: string_set_attribute_writable,
|
|
82
83
|
depends: string_set_attribute_writable,
|
|
@@ -88,6 +89,12 @@ const HostTypeDefinition = {
|
|
|
88
89
|
};
|
|
89
90
|
|
|
90
91
|
export class Host extends ServiceOwner {
|
|
92
|
+
static typeDefinition = HostTypeDefinition;
|
|
93
|
+
|
|
94
|
+
static {
|
|
95
|
+
addType(this);
|
|
96
|
+
}
|
|
97
|
+
|
|
91
98
|
_aliases = new Set();
|
|
92
99
|
_networkInterfaces = new Map();
|
|
93
100
|
_provides = new Set();
|
|
@@ -102,29 +109,19 @@ export class Host extends ServiceOwner {
|
|
|
102
109
|
_serial;
|
|
103
110
|
_keymap;
|
|
104
111
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
}
|
|
108
|
-
|
|
109
|
-
static get typeDefinition() {
|
|
110
|
-
return HostTypeDefinition;
|
|
111
|
-
}
|
|
112
|
-
|
|
113
|
-
read(data, type) {
|
|
114
|
-
super.read(data, type);
|
|
112
|
+
materializeExtends() {
|
|
113
|
+
super.materializeExtends();
|
|
115
114
|
|
|
116
|
-
this.
|
|
117
|
-
|
|
115
|
+
for (const host of this.walkDirections(["extends"])) {
|
|
116
|
+
for (const [name, ni] of host.networkInterfaces) {
|
|
117
|
+
const present = this._networkInterfaces.get(name);
|
|
118
118
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
present.extends.push(ni);
|
|
126
|
-
} else {
|
|
127
|
-
this._networkInterfaces.set(name, ni.forOwner(this));
|
|
119
|
+
if (present) {
|
|
120
|
+
//console.log("LINK", present.fullName, ni.fullName);
|
|
121
|
+
present.extends.push(ni);
|
|
122
|
+
} else {
|
|
123
|
+
this._networkInterfaces.set(name, ni.forOwner(this));
|
|
124
|
+
}
|
|
128
125
|
}
|
|
129
126
|
}
|
|
130
127
|
}
|
|
@@ -171,6 +168,13 @@ export class Host extends ServiceOwner {
|
|
|
171
168
|
return this.extendedAttribute("_vendor");
|
|
172
169
|
}
|
|
173
170
|
|
|
171
|
+
/**
|
|
172
|
+
* @return {string}
|
|
173
|
+
*/
|
|
174
|
+
get id() {
|
|
175
|
+
return this["machine-id"];
|
|
176
|
+
}
|
|
177
|
+
|
|
174
178
|
set keymap(value) {
|
|
175
179
|
this._keymap = value;
|
|
176
180
|
}
|
|
@@ -445,13 +449,13 @@ export class Host extends ServiceOwner {
|
|
|
445
449
|
await ni.systemdDefinitions(dir, packageData);
|
|
446
450
|
}
|
|
447
451
|
|
|
448
|
-
if (this.keymap) {
|
|
449
|
-
await writeLines(dir, "etc/vconsole.conf", `KEYMAP=${this.keymap}`);
|
|
450
|
-
}
|
|
451
|
-
|
|
452
452
|
await generateKnownHosts(this.owner.hosts, join(dir, "root", ".ssh"));
|
|
453
453
|
|
|
454
|
+
console.log([...this.walkDirections(["extends"])].map(e => e.fullName));
|
|
455
|
+
|
|
454
456
|
for (const service of this.services) {
|
|
457
|
+
//console.log("SERVICE",service.name);
|
|
458
|
+
|
|
455
459
|
if (service.systemdConfigs) {
|
|
456
460
|
for (const { serviceName, configFileName, content } of asArray(
|
|
457
461
|
service.expand(service.systemdConfigs(this.name))
|
|
@@ -468,23 +472,5 @@ export class Host extends ServiceOwner {
|
|
|
468
472
|
}
|
|
469
473
|
|
|
470
474
|
yield packageData;
|
|
471
|
-
|
|
472
|
-
if (this.extra) {
|
|
473
|
-
yield {
|
|
474
|
-
sources: [
|
|
475
|
-
new FileContentProvider({
|
|
476
|
-
dir: join(this.directory, "extra"),
|
|
477
|
-
pattern: "**/*"
|
|
478
|
-
})
|
|
479
|
-
],
|
|
480
|
-
outputs: this.outputs,
|
|
481
|
-
properties: {
|
|
482
|
-
name: `${this.typeName}-extra-${this.owner.name}-${this.name}`,
|
|
483
|
-
description: `additional files for ${this.fullName}`,
|
|
484
|
-
access: "private",
|
|
485
|
-
dependencies: [packageData.properties.name]
|
|
486
|
-
}
|
|
487
|
-
};
|
|
488
|
-
}
|
|
489
475
|
}
|
|
490
476
|
}
|
|
@@ -0,0 +1,324 @@
|
|
|
1
|
+
import { readFile, glob } from "node:fs/promises";
|
|
2
|
+
import { join } from "node:path";
|
|
3
|
+
import { toInternal, attributeIterator, types, resolveTypeLinks } from "pacc";
|
|
4
|
+
import { asArray } from "./utils.mjs";
|
|
5
|
+
import { Base } from "./base.mjs";
|
|
6
|
+
import { Root } from "./root.mjs";
|
|
7
|
+
|
|
8
|
+
/**
|
|
9
|
+
* Keeps track of all in flight object creations and loose ends during config initialization.
|
|
10
|
+
*/
|
|
11
|
+
export class InitializationContext {
|
|
12
|
+
outstandingResolves = [];
|
|
13
|
+
|
|
14
|
+
constructor(directory = "/") {
|
|
15
|
+
resolveTypeLinks();
|
|
16
|
+
this.directory = directory;
|
|
17
|
+
this.root = new Root(directory);
|
|
18
|
+
}
|
|
19
|
+
|
|
20
|
+
resolveOutstanding() {
|
|
21
|
+
for (let { object, attribute, name, value } of this.outstandingResolves) {
|
|
22
|
+
value = object.expand(value);
|
|
23
|
+
|
|
24
|
+
for (const type of attribute.type.members || [attribute.type]) {
|
|
25
|
+
const o =
|
|
26
|
+
object.typeNamed(type.name, value) ||
|
|
27
|
+
object.owner.typeNamed(type.name, value) ||
|
|
28
|
+
object.root.typeNamed(type.name, value); // TODO
|
|
29
|
+
|
|
30
|
+
if (o) {
|
|
31
|
+
this.assign(object, name, attribute, o);
|
|
32
|
+
}
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
/*
|
|
36
|
+
this.error(
|
|
37
|
+
`No such object "${value}" (${attribute.type.name}) for attribute ${name}`,
|
|
38
|
+
object.root.named(value)?.toString()
|
|
39
|
+
);*/
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
resolveLater(object, attribute, name, value) {
|
|
44
|
+
this.outstandingResolves.push({ object, attribute, name, value });
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
error(...args) {
|
|
48
|
+
console.error(...args);
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
assign(object, name, attribute, value) {
|
|
52
|
+
value = toInternal(value, attribute);
|
|
53
|
+
value ??= attribute.default;
|
|
54
|
+
|
|
55
|
+
if (value !== undefined) {
|
|
56
|
+
if (attribute.values) {
|
|
57
|
+
if (attribute.values.indexOf(value) < 0) {
|
|
58
|
+
this.error(name, "unknown value", value, attribute.values);
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
|
|
62
|
+
if (attribute.collection) {
|
|
63
|
+
const current = object[name];
|
|
64
|
+
|
|
65
|
+
switch (typeof current) {
|
|
66
|
+
case "undefined":
|
|
67
|
+
if (attribute.constructor === value.constructor) {
|
|
68
|
+
object[name] = value;
|
|
69
|
+
} else {
|
|
70
|
+
object[name] = asArray(value);
|
|
71
|
+
}
|
|
72
|
+
break;
|
|
73
|
+
case "object":
|
|
74
|
+
if (Array.isArray(current)) {
|
|
75
|
+
if (Array.isArray(value)) {
|
|
76
|
+
current.push(...value);
|
|
77
|
+
} else {
|
|
78
|
+
current.push(value);
|
|
79
|
+
}
|
|
80
|
+
} else {
|
|
81
|
+
if (current instanceof Set) {
|
|
82
|
+
if (value instanceof Set) {
|
|
83
|
+
object[name] = current.union(value);
|
|
84
|
+
} else {
|
|
85
|
+
object[name].add(value);
|
|
86
|
+
}
|
|
87
|
+
} else if (current instanceof Map) {
|
|
88
|
+
const keyName = attribute.type.key;
|
|
89
|
+
if (keyName) {
|
|
90
|
+
current.set(value[keyName], value);
|
|
91
|
+
} else {
|
|
92
|
+
// TODO
|
|
93
|
+
object[name] = value;
|
|
94
|
+
}
|
|
95
|
+
} else {
|
|
96
|
+
const keyName = attribute.type.key;
|
|
97
|
+
object[name][value[keyName]] = value;
|
|
98
|
+
}
|
|
99
|
+
}
|
|
100
|
+
break;
|
|
101
|
+
case "function":
|
|
102
|
+
if (value instanceof Base) {
|
|
103
|
+
object.addObject(value);
|
|
104
|
+
} else {
|
|
105
|
+
this.error("Unknown collection type", name, current);
|
|
106
|
+
}
|
|
107
|
+
break;
|
|
108
|
+
}
|
|
109
|
+
} else {
|
|
110
|
+
object[name] = value;
|
|
111
|
+
}
|
|
112
|
+
}
|
|
113
|
+
}
|
|
114
|
+
|
|
115
|
+
instantiateAndAssign(object, name, attribute, value) {
|
|
116
|
+
if (attribute.type.primitive) {
|
|
117
|
+
this.assign(object, name, attribute, value);
|
|
118
|
+
return;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
switch (typeof value) {
|
|
122
|
+
case "undefined":
|
|
123
|
+
return;
|
|
124
|
+
|
|
125
|
+
case "function":
|
|
126
|
+
this.error("Invalid value", name, value);
|
|
127
|
+
break;
|
|
128
|
+
|
|
129
|
+
case "boolean":
|
|
130
|
+
case "bigint":
|
|
131
|
+
case "number":
|
|
132
|
+
case "string":
|
|
133
|
+
{
|
|
134
|
+
let o;
|
|
135
|
+
|
|
136
|
+
for (const type of attribute.type.members || [attribute.type]) {
|
|
137
|
+
o = object.typeNamed(type.name, value);
|
|
138
|
+
if (o) {
|
|
139
|
+
break;
|
|
140
|
+
}
|
|
141
|
+
}
|
|
142
|
+
|
|
143
|
+
if (o) {
|
|
144
|
+
this.assign(object, name, attribute, o);
|
|
145
|
+
} else {
|
|
146
|
+
if (attribute.type.constructWithIdentifierOnly) {
|
|
147
|
+
o = new attribute.type.clazz(
|
|
148
|
+
object.ownerFor(attribute, value),
|
|
149
|
+
value
|
|
150
|
+
);
|
|
151
|
+
this.read(o, value);
|
|
152
|
+
object.addObject(o);
|
|
153
|
+
} else {
|
|
154
|
+
this.resolveLater(object, attribute, name, value);
|
|
155
|
+
}
|
|
156
|
+
}
|
|
157
|
+
}
|
|
158
|
+
|
|
159
|
+
break;
|
|
160
|
+
|
|
161
|
+
case "object":
|
|
162
|
+
if (attribute.type.clazz && value instanceof attribute.type.clazz) {
|
|
163
|
+
this.assign(object, name, attribute, value);
|
|
164
|
+
} else {
|
|
165
|
+
this.assign(
|
|
166
|
+
object,
|
|
167
|
+
name,
|
|
168
|
+
attribute,
|
|
169
|
+
this.typeFactory(
|
|
170
|
+
attribute.type,
|
|
171
|
+
object.ownerFor(attribute, value),
|
|
172
|
+
value
|
|
173
|
+
)
|
|
174
|
+
);
|
|
175
|
+
}
|
|
176
|
+
break;
|
|
177
|
+
}
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
typeFactory(type, owner, data) {
|
|
181
|
+
const factory = type.factoryFor?.(owner, data) || type.clazz;
|
|
182
|
+
const object = new factory(owner);
|
|
183
|
+
|
|
184
|
+
this.read(object, data);
|
|
185
|
+
owner.addObject(object);
|
|
186
|
+
return object;
|
|
187
|
+
}
|
|
188
|
+
|
|
189
|
+
read(object, data, type = object.constructor.typeDefinition) {
|
|
190
|
+
if (data?.properties) {
|
|
191
|
+
Object.assign(object._properties, data.properties);
|
|
192
|
+
}
|
|
193
|
+
|
|
194
|
+
for (const [path, attribute] of attributeIterator(type.attributes)) {
|
|
195
|
+
if (attribute.writable) {
|
|
196
|
+
const name = path.join(".");
|
|
197
|
+
const value = object.expand(data[name]);
|
|
198
|
+
|
|
199
|
+
if (attribute.collection) {
|
|
200
|
+
if (typeof value === "object") {
|
|
201
|
+
if (Array.isArray(value)) {
|
|
202
|
+
for (const v of value) {
|
|
203
|
+
this.instantiateAndAssign(object, name, attribute, v);
|
|
204
|
+
}
|
|
205
|
+
} else {
|
|
206
|
+
if (value instanceof Base) {
|
|
207
|
+
this.assign(object, name, attribute, value);
|
|
208
|
+
} else {
|
|
209
|
+
for (const [objectName, objectData] of Object.entries(value)) {
|
|
210
|
+
if (typeof objectData === "object") {
|
|
211
|
+
//console.log("KEY", objectName, type.name, type.key);
|
|
212
|
+
objectData[attribute.type.key] = objectName;
|
|
213
|
+
}
|
|
214
|
+
this.instantiateAndAssign(
|
|
215
|
+
object,
|
|
216
|
+
name,
|
|
217
|
+
attribute,
|
|
218
|
+
objectData
|
|
219
|
+
);
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
}
|
|
223
|
+
continue;
|
|
224
|
+
}
|
|
225
|
+
}
|
|
226
|
+
this.instantiateAndAssign(object, name, attribute, value);
|
|
227
|
+
}
|
|
228
|
+
}
|
|
229
|
+
|
|
230
|
+
if (object.name === undefined && data.name) {
|
|
231
|
+
// TODO
|
|
232
|
+
object.name = data.name;
|
|
233
|
+
}
|
|
234
|
+
|
|
235
|
+
if (type.extends) {
|
|
236
|
+
//console.log("READ EXTENDS",data);
|
|
237
|
+
this.read(object, data, type.extends);
|
|
238
|
+
object.materializeExtends();
|
|
239
|
+
}
|
|
240
|
+
}
|
|
241
|
+
|
|
242
|
+
async loadType(name, type) {
|
|
243
|
+
const data = JSON.parse(
|
|
244
|
+
await readFile(
|
|
245
|
+
join(this.directory, name, type.clazz.typeFileName),
|
|
246
|
+
"utf8"
|
|
247
|
+
)
|
|
248
|
+
);
|
|
249
|
+
|
|
250
|
+
//console.log("LOAD", name);
|
|
251
|
+
let owner;
|
|
252
|
+
if (name[0] === "/") {
|
|
253
|
+
const parentName = name.replace(/\/[^\/]+$/, "");
|
|
254
|
+
owner = await this.load(parentName);
|
|
255
|
+
data.name = name.substring(owner.fullName.length + 1);
|
|
256
|
+
} else {
|
|
257
|
+
owner = this.root;
|
|
258
|
+
data.name = name;
|
|
259
|
+
}
|
|
260
|
+
|
|
261
|
+
//console.log("LOAD", [name, owner.fullName, data.name]);
|
|
262
|
+
|
|
263
|
+
const object = this.typeFactory(type, owner, data);
|
|
264
|
+
this.root.addTypeObject(type.clazz.typeName, name, object);
|
|
265
|
+
|
|
266
|
+
/*if(object.name === undefined || object.name.length === 0) {
|
|
267
|
+
throw "NO name";
|
|
268
|
+
}*/
|
|
269
|
+
|
|
270
|
+
return object;
|
|
271
|
+
}
|
|
272
|
+
|
|
273
|
+
async load(name, options) {
|
|
274
|
+
name = name.replace(/\/?([^\/]+\.json)?$/, "");
|
|
275
|
+
|
|
276
|
+
const object = this.root.named(name);
|
|
277
|
+
if (object) {
|
|
278
|
+
return object;
|
|
279
|
+
}
|
|
280
|
+
|
|
281
|
+
if (options?.type) {
|
|
282
|
+
return this.loadType(name, options.type);
|
|
283
|
+
} else {
|
|
284
|
+
for (const type of Object.values(types).filter(
|
|
285
|
+
type => type?.clazz?.typeFileName
|
|
286
|
+
)) {
|
|
287
|
+
try {
|
|
288
|
+
return await this.loadType(name, type);
|
|
289
|
+
} catch {}
|
|
290
|
+
}
|
|
291
|
+
}
|
|
292
|
+
|
|
293
|
+
const parentName = name.replace(/\/[^\/]$/, "");
|
|
294
|
+
return name === parentName ? this.root : this.load(parentName, options);
|
|
295
|
+
}
|
|
296
|
+
|
|
297
|
+
async loadAll() {
|
|
298
|
+
for (const type of Object.values(types).sort(
|
|
299
|
+
(a, b) => b.priority - a.priority
|
|
300
|
+
)) {
|
|
301
|
+
//console.log("LIST","**/" + type.clazz.typeFileName);
|
|
302
|
+
if (type.clazz?.typeFileName) {
|
|
303
|
+
for await (const name of glob("**/" + type.clazz.typeFileName, {
|
|
304
|
+
cwd: this.directory
|
|
305
|
+
})) {
|
|
306
|
+
if (type === this.root.constructor) {
|
|
307
|
+
const data = JSON.parse(
|
|
308
|
+
await readFile(join(this.directory, name), "utf8")
|
|
309
|
+
);
|
|
310
|
+
this.root._properties = data.properties;
|
|
311
|
+
} else {
|
|
312
|
+
await this.load("/" + name, { type });
|
|
313
|
+
}
|
|
314
|
+
}
|
|
315
|
+
}
|
|
316
|
+
}
|
|
317
|
+
|
|
318
|
+
this.resolveOutstanding();
|
|
319
|
+
}
|
|
320
|
+
|
|
321
|
+
named(name) {
|
|
322
|
+
return this.root.named(name);
|
|
323
|
+
}
|
|
324
|
+
}
|
package/src/location.mjs
CHANGED
|
@@ -5,34 +5,24 @@ import { loadHooks } from "./hooks.mjs";
|
|
|
5
5
|
|
|
6
6
|
const LocationTypeDefinition = {
|
|
7
7
|
name: "location",
|
|
8
|
+
priority: 2,
|
|
8
9
|
owners: [Owner.typeDefinition, "location", "root"],
|
|
9
10
|
extends: Owner.typeDefinition,
|
|
10
11
|
key: "name",
|
|
11
|
-
attributes: {
|
|
12
|
-
}
|
|
12
|
+
attributes: {}
|
|
13
13
|
};
|
|
14
14
|
|
|
15
15
|
export class Location extends Owner {
|
|
16
|
+
static typeDefinition = LocationTypeDefinition;
|
|
17
|
+
|
|
16
18
|
static {
|
|
17
19
|
addType(this);
|
|
18
20
|
}
|
|
19
21
|
|
|
20
|
-
static get typeDefinition() {
|
|
21
|
-
return LocationTypeDefinition;
|
|
22
|
-
}
|
|
23
|
-
|
|
24
22
|
get location() {
|
|
25
23
|
return this;
|
|
26
24
|
}
|
|
27
25
|
|
|
28
|
-
locationNamed(name) {
|
|
29
|
-
if (this.isNamed(name)) {
|
|
30
|
-
return this;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
|
-
return super.locationNamed(name);
|
|
34
|
-
}
|
|
35
|
-
|
|
36
26
|
get network() {
|
|
37
27
|
return [...this.typeList("network")][0] || super.network;
|
|
38
28
|
}
|
package/src/module.mjs
CHANGED
|
@@ -20,20 +20,18 @@ export const EthernetNetworkInterfaceTypeDefinition = {
|
|
|
20
20
|
};
|
|
21
21
|
|
|
22
22
|
export class EthernetNetworkInterface extends NetworkInterface {
|
|
23
|
-
|
|
23
|
+
static typeDefinition = EthernetNetworkInterfaceTypeDefinition;
|
|
24
24
|
|
|
25
25
|
static {
|
|
26
26
|
addType(this);
|
|
27
27
|
}
|
|
28
28
|
|
|
29
|
-
static get typeDefinition() {
|
|
30
|
-
return EthernetNetworkInterfaceTypeDefinition;
|
|
31
|
-
}
|
|
32
|
-
|
|
33
29
|
static isCommonName(name) {
|
|
34
30
|
return name.match(/^eth\d+$/);
|
|
35
31
|
}
|
|
36
32
|
|
|
33
|
+
arpbridge;
|
|
34
|
+
|
|
37
35
|
get kind() {
|
|
38
36
|
return EthernetNetworkInterfaceTypeDefinition.name;
|
|
39
37
|
}
|
|
@@ -19,14 +19,12 @@ const _localAddresses = new Map([
|
|
|
19
19
|
const _localDomains = new Set(["localhost"]);
|
|
20
20
|
|
|
21
21
|
export class LoopbackNetworkInterface extends SkeletonNetworkInterface {
|
|
22
|
+
static typeDefinition = LoopbackNetworkInterfaceTypeDefinition;
|
|
23
|
+
|
|
22
24
|
static {
|
|
23
25
|
addType(this);
|
|
24
26
|
}
|
|
25
27
|
|
|
26
|
-
static get typeDefinition() {
|
|
27
|
-
return LoopbackNetworkInterfaceTypeDefinition;
|
|
28
|
-
}
|
|
29
|
-
|
|
30
28
|
static isCommonName(name) {
|
|
31
29
|
return name.match(/^lo\d*$/);
|
|
32
30
|
}
|
|
@@ -63,14 +63,12 @@ export const NetworkInterfaceTypeDefinition = {
|
|
|
63
63
|
};
|
|
64
64
|
|
|
65
65
|
export class NetworkInterface extends SkeletonNetworkInterface {
|
|
66
|
+
static typeDefinition = NetworkInterfaceTypeDefinition;
|
|
67
|
+
|
|
66
68
|
static {
|
|
67
69
|
addType(this);
|
|
68
70
|
}
|
|
69
71
|
|
|
70
|
-
static get typeDefinition() {
|
|
71
|
-
return NetworkInterfaceTypeDefinition;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
72
|
static isCommonName(name) {
|
|
75
73
|
return false;
|
|
76
74
|
}
|
|
@@ -178,7 +176,7 @@ export class NetworkInterface extends SkeletonNetworkInterface {
|
|
|
178
176
|
}
|
|
179
177
|
|
|
180
178
|
get mtu() {
|
|
181
|
-
return this.extendedAttribute("_mtu");
|
|
179
|
+
return this.extendedAttribute("_mtu");
|
|
182
180
|
}
|
|
183
181
|
|
|
184
182
|
set class(value) {
|
|
@@ -4,15 +4,15 @@ import { NetworkAddress, Host, cidrAddresses } from "pmcf";
|
|
|
4
4
|
import { ServiceOwner } from "../service-owner.mjs";
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
|
-
*
|
|
7
|
+
*
|
|
8
8
|
*/
|
|
9
9
|
export class SkeletonNetworkInterface extends ServiceOwner {
|
|
10
|
-
_network;
|
|
11
|
-
|
|
12
10
|
static get typeName() {
|
|
13
11
|
return "network_interface";
|
|
14
12
|
}
|
|
15
13
|
|
|
14
|
+
_network;
|
|
15
|
+
|
|
16
16
|
get typeName() {
|
|
17
17
|
return "network_interface";
|
|
18
18
|
}
|
|
@@ -23,6 +23,12 @@ export class SkeletonNetworkInterface extends ServiceOwner {
|
|
|
23
23
|
}
|
|
24
24
|
}
|
|
25
25
|
|
|
26
|
+
get aggregatedServices() {
|
|
27
|
+
return this.host
|
|
28
|
+
? [...this.services, ...this.host.services]
|
|
29
|
+
: this.services;
|
|
30
|
+
}
|
|
31
|
+
|
|
26
32
|
get hosts() {
|
|
27
33
|
const host = this.host;
|
|
28
34
|
if (host) {
|