pmcf 6.37.2 → 6.38.1

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/src/core.mjs ADDED
@@ -0,0 +1,325 @@
1
+ import { AggregatedMap } from "aggregated-map";
2
+
3
+ import {
4
+ toExternal,
5
+ filterPublic,
6
+ parse,
7
+ extendingAttributeIterator,
8
+ getAttribute,
9
+ expand,
10
+ globals
11
+ } from "pacc";
12
+ import { addType } from "pmcf";
13
+
14
+ export class Core {
15
+ static name = "core";
16
+ static priority = 1;
17
+
18
+ static {
19
+ addType(this);
20
+ }
21
+
22
+ extends = new Set();
23
+
24
+ constructor(owner, data) {
25
+ if (owner) {
26
+ this.owner = owner;
27
+ }
28
+ }
29
+
30
+ set owner(value) {
31
+ if (this === value || this === value?.owner) {
32
+ this.error("Unable to own myself", value.fullName);
33
+ } else {
34
+ this._owner = value;
35
+ }
36
+ }
37
+
38
+ get owner() {
39
+ return this._owner;
40
+ }
41
+
42
+ forOwner(owner) {
43
+ if (this.owner !== owner) {
44
+ const newObject = Object.create(this);
45
+ newObject.owner = owner;
46
+ return newObject;
47
+ }
48
+
49
+ return this;
50
+ }
51
+
52
+ materializeExtends() {
53
+ for (const [path, attribute] of extendingAttributeIterator(
54
+ this.constructor,
55
+ attribute => attribute.collection && !attribute.type.primitive
56
+ )) {
57
+ if (attribute.deferredExpression) {
58
+ const name = attribute.name;
59
+ if (!this.hasOwnProperty(name)) {
60
+ for (const e of this.walkDirections(["extends"])) {
61
+ if (e.hasOwnProperty(name)) {
62
+ Object.defineProperty(this, name, {
63
+ get: () => e[name]
64
+ });
65
+ break;
66
+ }
67
+ }
68
+ }
69
+
70
+ continue;
71
+ }
72
+
73
+ const collection = this[attribute.name];
74
+
75
+ if (typeof collection?.get === "function") {
76
+ for (const [name, extending] of this.mapFromDirections(
77
+ ["extends"],
78
+ attribute.name
79
+ )) {
80
+ const present = collection.get(extending.name);
81
+
82
+ if (present) {
83
+ present.extends.add(extending);
84
+ present.materializeExtends();
85
+ } else {
86
+ collection.set(extending.name, extending.forOwner(this));
87
+ }
88
+ }
89
+ } /*else {
90
+ if (Array.isArray(collection)) {
91
+ // TODO
92
+ } else {
93
+ //console.log("EXTENDS", this.fullName, attribute.name);
94
+
95
+ for (const extending of this.unionFromDirections(
96
+ ["extends"],
97
+ attribute.name
98
+ )) {
99
+ if (!collection.has(extending)) {
100
+ //console.log("ADD", this.fullName, extending.fullName);
101
+ collection.add(extending);
102
+ }
103
+ }
104
+ }
105
+ }*/
106
+ }
107
+ }
108
+
109
+ get typeName() {
110
+ return this.constructor.name;
111
+ }
112
+
113
+ /**
114
+ * Retrive attribute values from an object.
115
+ * @param {Function} [filter]
116
+ * @return {Iterable<[string,any]>} values
117
+ */
118
+ *attributeIterator(filter) {
119
+ for (const [path, attribute] of extendingAttributeIterator(
120
+ this.constructor,
121
+ filter
122
+ )) {
123
+ const name = path.join(".");
124
+ const value = this.attribute(name);
125
+
126
+ if (value !== undefined) {
127
+ yield [
128
+ attribute.externalName ?? name,
129
+ toExternal(value, attribute),
130
+ path,
131
+ attribute
132
+ ];
133
+ }
134
+ }
135
+ }
136
+
137
+ /**
138
+ * Retrive attribute values from an object.
139
+ * @param {Function} [filter]
140
+ * @return {Object} values
141
+ */
142
+ getAttributes(filter = filterPublic) {
143
+ return Object.fromEntries(this.attributeIterator(filter));
144
+ }
145
+
146
+ value(name) {
147
+ return this.attribute(name);
148
+ }
149
+
150
+ /**
151
+ *
152
+ * @param {string} name
153
+ * @returns {any}
154
+ */
155
+ property(name) {
156
+ for (const node of this.walkDirections()) {
157
+ const value = node.properties[name];
158
+
159
+ if (value !== undefined) {
160
+ return this.expand(value);
161
+ }
162
+ }
163
+ }
164
+
165
+ /**
166
+ *
167
+ * @param {string} name
168
+ * @returns {any}
169
+ */
170
+ attribute(name) {
171
+ for (const node of this.walkDirections(["this", "extends"])) {
172
+ const value = getAttribute(node, name);
173
+ if (value !== undefined) {
174
+ return this.expand(value);
175
+ }
176
+ }
177
+ }
178
+
179
+ /**
180
+ * Walk the object graph in some directions and deliver seen nodes.
181
+ * @param {string[]} directions
182
+ * @return {Iterable<Core>}
183
+ */
184
+ *walkDirections(directions = ["this", "extends", "owner"]) {
185
+ if (directions.indexOf("this") >= 0) {
186
+ yield this;
187
+ directions = directions.filter(d => d !== "this");
188
+ }
189
+
190
+ yield* this._walkDirections(directions, new Set());
191
+ }
192
+
193
+ *_walkDirections(directions, seen) {
194
+ if (!seen.has(this)) {
195
+ seen.add(this);
196
+
197
+ for (const direction of directions) {
198
+ const value = this[direction];
199
+
200
+ if (value) {
201
+ if (value[Symbol.iterator]) {
202
+ for (const node of value) {
203
+ yield node;
204
+ yield* node._walkDirections(directions, seen);
205
+ }
206
+ } else {
207
+ yield value;
208
+ yield* value._walkDirections(directions, seen);
209
+ }
210
+ }
211
+ }
212
+ }
213
+ }
214
+
215
+ /**
216
+ * Deliver AggregatedMap of all property Maps.
217
+ * @param {string[]} directions
218
+ * @param {string} property
219
+ * @returns {Map<any,any>}
220
+ */
221
+ mapFromDirections(directions, property) {
222
+ return new AggregatedMap(
223
+ [...this.walkDirections(directions)]
224
+ .map(node => node[property])
225
+ .filter(node => node !== undefined)
226
+ );
227
+ }
228
+
229
+ /**
230
+ * Deliver union set of all property values.
231
+ * @param {string[]} directions
232
+ * @param {string} property
233
+ * @returns {Set<any>}
234
+ */
235
+ unionFromDirections(directions, property) {
236
+ let collected = new Set();
237
+ for (const node of this.walkDirections(directions)) {
238
+ const value = node[property];
239
+ if (value !== undefined) {
240
+ if (!(value instanceof Set)) {
241
+ console.log("NO SET", value, node.fullName, property);
242
+ }
243
+ collected = collected.union(value);
244
+ }
245
+ }
246
+
247
+ return collected;
248
+ }
249
+
250
+ get children() {
251
+ const all = [];
252
+
253
+ for (const [path, attribute] of extendingAttributeIterator(
254
+ this.constructor,
255
+ attribute => attribute.backpointer?.name === "owner"
256
+ )) {
257
+ const value = this[path];
258
+
259
+ if (value !== undefined) {
260
+ if (attribute.collection) {
261
+ if (typeof value.values === "function") {
262
+ all.push(...value.values());
263
+ } else {
264
+ if (value instanceof Iterator) {
265
+ all.push(...value);
266
+ } else {
267
+ if (value instanceof Core) {
268
+ this.error(
269
+ `Unexpected scalar value for "${attribute.name}"`,
270
+ value.fullName
271
+ );
272
+ all.push(value); // TODO should not happen
273
+ } else if (typeof value === "object") {
274
+ all.push(...Object.values(value));
275
+ }
276
+ }
277
+ }
278
+ } else {
279
+ all.push(value);
280
+ }
281
+ }
282
+ }
283
+
284
+ return all;
285
+ }
286
+
287
+ /**
288
+ *
289
+ * @param {any} object
290
+ * @returns {any}
291
+ */
292
+ expand(object) {
293
+ if (this.isTemplate || object instanceof Core) {
294
+ return object;
295
+ }
296
+
297
+ return expand(object, {
298
+ stopClass: Core,
299
+ root: this.root,
300
+ current: this,
301
+ valueFor: (name, at) =>
302
+ typeof at?.value === "function" ? at.value(name) : globals[name]
303
+ });
304
+ }
305
+
306
+ /**
307
+ *
308
+ * @param {string} expression
309
+ * @param {object} options
310
+ * @returns {any}
311
+ */
312
+ expression(expression, options) {
313
+ return parse(expression, {
314
+ root: this.root,
315
+ current: this,
316
+ valueFor: (name, at) =>
317
+ typeof at?.value === "function" ? at.value(name) : globals[name],
318
+ ...options
319
+ });
320
+ }
321
+
322
+ get isTemplate() {
323
+ return false;
324
+ }
325
+ }
package/src/host.mjs CHANGED
@@ -5,7 +5,6 @@ import { AggregatedMap } from "aggregated-map";
5
5
  import {
6
6
  string_attribute,
7
7
  string_attribute_writable,
8
- string_set_attribute_writable,
9
8
  number_attribute_writable,
10
9
  priority_attribute,
11
10
  asArray
@@ -19,12 +18,7 @@ import {
19
18
  } from "./common-attributes.mjs";
20
19
  import { ServiceOwner } from "./service-owner.mjs";
21
20
  import { addHook } from "./hooks.mjs";
22
- import {
23
- domainFromDominName,
24
- domainName,
25
- writeLines,
26
- union
27
- } from "./utils.mjs";
21
+ import { domainFromDominName, domainName, writeLines } from "./utils.mjs";
28
22
  import { loadHooks } from "./hooks.mjs";
29
23
  import { generateKnownHosts } from "./host-utils.mjs";
30
24
 
@@ -75,10 +69,6 @@ export class Host extends ServiceOwner {
75
69
  name: "architecture",
76
70
  values: new Set(["x86", "x86_64", "aarch64", "armv7", "riscv"])
77
71
  },
78
- replaces: { ...string_set_attribute_writable, name: "replaces" },
79
- depends: { ...string_set_attribute_writable, name: "depends" },
80
- provides: { ...string_set_attribute_writable, name: "provides" },
81
- optional: { ...string_set_attribute_writable, name: "optional" },
82
72
  extends: {
83
73
  ...extends_attribute,
84
74
  type: Host
@@ -91,10 +81,6 @@ export class Host extends ServiceOwner {
91
81
  }
92
82
 
93
83
  _networkInterfaces = new Map();
94
- _provides = new Set();
95
- _replaces = new Set();
96
- _depends = new Set();
97
- _optional = new Set();
98
84
  _os;
99
85
  _distribution;
100
86
  _deployment;
@@ -152,12 +138,6 @@ export class Host extends ServiceOwner {
152
138
  return this.attribute("_architecture");
153
139
  }
154
140
 
155
- get derivedPackaging() {
156
- return this.expand(
157
- this.unionFromDirections(["this", "extends"], "_packaging")
158
- );
159
- }
160
-
161
141
  get isTemplate() {
162
142
  return this.isModel || super.isTemplate;
163
143
  }
@@ -174,46 +154,6 @@ export class Host extends ServiceOwner {
174
154
  }
175
155
  }
176
156
 
177
- set provides(value) {
178
- this._provides = union(value, this._provides);
179
- }
180
-
181
- get provides() {
182
- return this.expand(
183
- this.unionFromDirections(["this", "extends"], "_provides")
184
- );
185
- }
186
-
187
- set replaces(value) {
188
- this._replaces = union(value, this._replaces);
189
- }
190
-
191
- get replaces() {
192
- return this.expand(
193
- this.unionFromDirections(["this", "extends"], "_replaces")
194
- );
195
- }
196
-
197
- set depends(value) {
198
- this._depends = union(value, this._depends);
199
- }
200
-
201
- get depends() {
202
- return this.expand(
203
- this.unionFromDirections(["this", "extends"], "_depends")
204
- );
205
- }
206
-
207
- set optional(value) {
208
- this._optional = union(value, this._optional);
209
- }
210
-
211
- get optional() {
212
- return this.expand(
213
- this.unionFromDirections(["this", "extends"], "_optional")
214
- );
215
- }
216
-
217
157
  set os(value) {
218
158
  this._os = value;
219
159
  }
@@ -365,34 +305,20 @@ export class Host extends ServiceOwner {
365
305
  }
366
306
 
367
307
  async publicKey(type = "ed25519") {
368
- return readFile(join(this.directory, `ssh_host_${type}_key.pub`), "utf8");
308
+ return readFile(
309
+ join(this.directory, "content", "etc", "ssh", `ssh_host_${type}_key.pub`),
310
+ "utf8"
311
+ );
369
312
  }
370
313
 
371
314
  async *preparePackages(dir) {
372
315
  const packageData = this.packageData;
316
+
373
317
  packageData.sources.push(
374
318
  await Array.fromAsync(this.templateContent()),
375
- new FileContentProvider(
376
- { dir: this.directory, pattern: "*.pub" },
377
- { destination: "/etc/ssh/", mode: 0o644 }
378
- ),
379
- new FileContentProvider(
380
- { dir: this.directory, pattern: "*_key" },
381
- { destination: "/etc/ssh/", mode: 0o600 }
382
- ),
383
319
  new FileContentProvider({ dir, pattern: ["**/*", "**/.ssh/*"] })
384
320
  );
385
321
 
386
- Object.assign(packageData.properties, {
387
- description: `${this.typeName} definitions for ${this.fullName}`,
388
- dependencies: [...this.depends],
389
- provides: [...this.provides],
390
- replaces: [...this.replaces],
391
- depends: [...this.depends],
392
- optional: [...this.optional],
393
- backup: "root/.ssh/known_hosts"
394
- });
395
-
396
322
  await loadHooks(
397
323
  packageData,
398
324
  new URL("host.install", import.meta.url).pathname
@@ -412,8 +338,6 @@ export class Host extends ServiceOwner {
412
338
  for (const { serviceName, configFileName, content } of asArray(
413
339
  service.expand(service.systemdConfigs(this.name))
414
340
  )) {
415
- //console.log("SERVICE", service.fullName, configFileName);
416
-
417
341
  await writeLines(dir, configFileName, content);
418
342
 
419
343
  addHook(
package/src/module.mjs CHANGED
@@ -1,4 +1,5 @@
1
1
  export * from "./type.mjs";
2
+ export * from "./core.mjs";
2
3
  export * from "./base.mjs";
3
4
  export * from "./cluster.mjs";
4
5
  export * from "./owner.mjs";
@@ -8,6 +9,7 @@ export * from "./service-owner.mjs";
8
9
  export * from "./network.mjs";
9
10
  export * from "./network-address.mjs";
10
11
  export * from "./common-attributes.mjs";
12
+ export * from "./content.mjs";
11
13
  export * from "./host.mjs";
12
14
  export * from "./network-interfaces/network-interface.mjs";
13
15
  export * from "./network-interfaces/loopback.mjs";
package/src/owner.mjs CHANGED
@@ -163,15 +163,6 @@ export class Owner extends ServiceOwner {
163
163
  return this.subnets.values().find(subnet => subnet.matchesAddress(address));
164
164
  }
165
165
 
166
- get derivedPackaging() {
167
- let all = new Set();
168
- for (const host of this.hosts.values()) {
169
- all = all.union(host.packaging);
170
- }
171
-
172
- return all;
173
- }
174
-
175
166
  *networkAddresses(filter) {
176
167
  for (const host of this.hosts.values()) {
177
168
  yield* host.networkAddresses(filter);
@@ -825,17 +825,17 @@ export class bind extends CoreService {
825
825
  }
826
826
 
827
827
  async *preparePackages(dir) {
828
- const permissions = this.packageContentPermissions;
828
+ const permissions = this.content.permissions;
829
829
  const packageData = this.packageData;
830
830
 
831
831
  packageData.sources = await Array.fromAsync(
832
- this.templateContent(...permissions)
832
+ this.templateContent(permissions)
833
833
  );
834
834
 
835
835
  let hasContent = packageData.sources.length > 0;
836
836
 
837
837
  packageData.sources.push(
838
- new FileContentProvider(dir + "/", ...permissions)
838
+ new FileContentProvider(dir + "/", permissions)
839
839
  );
840
840
 
841
841
  const outputControl = { packageData, dir, permissions };
@@ -58,7 +58,7 @@ export class mosquitto extends CoreService {
58
58
  wd.map(n => [n.fullName, n.directory])
59
59
  );*/
60
60
 
61
- const permissions = this.packageContentPermissions;
61
+ const permissions = this.content.permissions;
62
62
  const packageData = this.packageData;
63
63
 
64
64
  packageData.sources = await Array.fromAsync(
@@ -66,7 +66,7 @@ export class mosquitto extends CoreService {
66
66
  );
67
67
 
68
68
  packageData.sources.push(
69
- new FileContentProvider(dir + "/", ...permissions)
69
+ new FileContentProvider(dir + "/", permissions)
70
70
  );
71
71
 
72
72
  await writeLines(
package/src/subnet.mjs CHANGED
@@ -5,16 +5,11 @@ import {
5
5
  matchPrefixIP,
6
6
  FAMILY_IPV6
7
7
  } from "ip-utilties";
8
- import {
9
- string_attribute,
10
- name_attribute,
11
- integer_attribute,
12
- getAttribute
13
- } from "pacc";
8
+ import { string_attribute, name_attribute, integer_attribute } from "pacc";
14
9
  import { networks_attribute } from "./common-attributes.mjs";
15
- import { addType, Network } from "pmcf";
10
+ import { addType, Network, Core } from "pmcf";
16
11
 
17
- export class Subnet {
12
+ export class Subnet extends Core {
18
13
  static name = "subnet";
19
14
  static priority = 1;
20
15
  static owners = ["owner", "network", "network_interface", "root"];
@@ -34,6 +29,7 @@ export class Subnet {
34
29
  networks = new Set();
35
30
 
36
31
  constructor(owner, address) {
32
+ super();
37
33
  const { longPrefix, prefix, prefixLength, cidr, family } =
38
34
  normalizeCIDR(address);
39
35
 
@@ -44,27 +40,13 @@ export class Subnet {
44
40
  this.family = family;
45
41
  }
46
42
 
47
- get owner() {
48
- return this._owner;
49
- }
50
-
51
43
  set owner(value) {
52
- this._owner = value;
44
+ super.owner = value;
53
45
  if (value instanceof Network) {
54
46
  this.networks.add(value);
55
47
  }
56
48
  }
57
49
 
58
- attribute(name) {
59
- return getAttribute(this, name);
60
- }
61
-
62
- value(name) {
63
- return this.attribute(name);
64
- }
65
-
66
- *_walkDirections(directions, seen) {}
67
-
68
50
  get cidr() {
69
51
  return this.address;
70
52
  }