pmcf 1.57.2 → 1.59.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-package CHANGED
@@ -20,40 +20,43 @@ const publishingDetails = createPublishingDetails(options.publish, process.env);
20
20
  for (const name of args) {
21
21
  const object = await root.load(name);
22
22
  const stagingDir = join(options.output, object.fullName);
23
- const { properties, outputs } = await object.preparePackage(stagingDir);
24
23
 
25
- for (const outputFactory of outputs) {
26
- properties.version = pkg.version;
27
- properties.license = pkg.license;
28
- properties.maintainer = pkg.contributors.map(
29
- c => c.name + (c.email ? ` <${c.email}>` : "")
30
- );
31
-
32
- if (properties.verbose) {
33
- console.log(properties);
24
+ for await (const { properties, outputs } of object.preparePackages(
25
+ stagingDir
26
+ )) {
27
+ for (const outputFactory of outputs) {
28
+ properties.version = pkg.version;
29
+ properties.license = pkg.license;
30
+ properties.maintainer = pkg.contributors.map(
31
+ c => c.name + (c.email ? ` <${c.email}>` : "")
32
+ );
33
+
34
+ if (properties.verbose) {
35
+ console.log(properties);
36
+ }
37
+
38
+ const sources = [
39
+ new FileContentProvider(stagingDir + "/")[Symbol.asyncIterator]()
40
+ ];
41
+
42
+ const output = new outputFactory(properties);
43
+
44
+ const artifact = await output.create(
45
+ sources,
46
+ [],
47
+ publishingDetails,
48
+ options
49
+ );
50
+
51
+ if (properties.verbose) {
52
+ console.log(artifact);
53
+ }
54
+
55
+ await Promise.all(
56
+ publishingDetails.map(publishDetail =>
57
+ output.publish(artifact, publishDetail)
58
+ )
59
+ );
34
60
  }
35
-
36
- const sources = [
37
- new FileContentProvider(stagingDir + "/")[Symbol.asyncIterator]()
38
- ];
39
-
40
- const output = new outputFactory(properties);
41
-
42
- const artifact = await output.create(
43
- sources,
44
- [],
45
- publishingDetails,
46
- options
47
- );
48
-
49
- if (properties.verbose) {
50
- console.log(artifact);
51
- }
52
-
53
- await Promise.all(
54
- publishingDetails.map(publishDetail =>
55
- output.publish(artifact, publishDetail)
56
- )
57
- );
58
61
  }
59
62
  }
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "1.57.2",
3
+ "version": "1.59.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/base.mjs CHANGED
@@ -204,7 +204,7 @@ export class Base {
204
204
  }
205
205
 
206
206
  typeNamed(typeName, name) {
207
- return this.owner.typeNamed(typeName, name);
207
+ return this.owner?.typeNamed(typeName, name);
208
208
  }
209
209
 
210
210
  addObject(object) {
@@ -271,6 +271,23 @@ export class Base {
271
271
  return this.owner?.timezone;
272
272
  }
273
273
 
274
+ findService(filter) {
275
+ let best;
276
+ for (const service of this.findServices(filter)) {
277
+ if (!best || service.priority < best.priority) {
278
+ best = service;
279
+ }
280
+ }
281
+
282
+ return best;
283
+ }
284
+
285
+ *findServices(filter) {
286
+ if (this.owner) {
287
+ yield* this.owner?.findServices(filter);
288
+ }
289
+ }
290
+
274
291
  #directory;
275
292
  set directory(directory) {
276
293
  this.#directory = directory;
@@ -314,8 +331,8 @@ export class Base {
314
331
  return new Set(allOutputs.filter(o => this.packaging.has(o.name)));
315
332
  }
316
333
 
317
- async preparePackage(stagingDir) {
318
- return {
334
+ async *preparePackages(stagingDir) {
335
+ yield {
319
336
  outputs: this.outputs,
320
337
  properties: {
321
338
  name: this.packageName,
package/src/cluster.mjs CHANGED
@@ -1,14 +1,16 @@
1
+ import { join } from "node:path";
1
2
  import { Owner } from "./owner.mjs";
2
3
  import { addType } from "./types.mjs";
4
+ import { writeLines } from "./utils.mjs";
3
5
 
4
6
  const ClusterTypeDefinition = {
5
7
  name: "cluster",
6
- owners: [Owner.typeDefinition, "network", "root"],
8
+ owners: [Owner.typeDefinition, "network", "location", "root"],
7
9
  priority: 0.7,
8
10
  extends: Owner.typeDefinition,
9
11
  properties: {
10
- masters: { type: "host", collection: true, writeable: true },
11
- backups: { type: "host", collection: true, writeable: true }
12
+ masters: { type: "network_interface", collection: true, writeable: true },
13
+ backups: { type: "network_interface", collection: true, writeable: true }
12
14
  }
13
15
  };
14
16
 
@@ -33,30 +35,38 @@ export class Cluster extends Owner {
33
35
  return `${this.constructor.typeDefinition.name}-${this.owner.name}-${this.name}`;
34
36
  }
35
37
 
36
- async preparePackage(stagingDir) {
37
- const result = await super.preparePackage(stagingDir);
38
-
39
- const cfg = [
40
- "vrrp_instance VI_1 {",
41
- " state MASTER",
42
- " interface end0",
43
- " virtual_router_id 101",
44
- " priority 255",
45
- " advert_int 1",
46
- " authentication {",
47
- " auth_type PASS",
48
- " auth_pass pass1234",
49
- " }",
50
- " virtual_ipaddress {",
51
- " 192.168.1.250",
52
- " }",
53
- "}"
54
- ];
55
-
56
- await writeLines(join(targetDir, "etc/keepalived"), "keepalived.conf", cfg);
57
-
58
- result.properties.dependencies = ["keepalived"];
59
-
60
- return result;
38
+ async *preparePackages(stagingDir) {
39
+ for await (const result of super.preparePackages(stagingDir)) {
40
+ for (const ni of this.masters.union(this.backups)) {
41
+
42
+ const cfg = [
43
+ `vrrp_instance ${this.name} {`,
44
+ ` state ${this.masters.has(ni) ? "MASTER" : "BACKUP"}`,
45
+ ` interface ${ni.name}`,
46
+ " virtual_router_id 101",
47
+ " priority 255",
48
+ " advert_int 1",
49
+ " authentication {",
50
+ " auth_type PASS",
51
+ " auth_pass pass1234",
52
+ " }",
53
+ " virtual_ipaddress {",
54
+ " 192.168.1.250",
55
+ " }",
56
+ "}"
57
+ ];
58
+
59
+ await writeLines(
60
+ join(stagingDir, "etc/keepalived"),
61
+ "keepalived.conf",
62
+ cfg
63
+ );
64
+
65
+ result.properties.name = `${this.constructor.typeDefinition.name}-${this.owner.name}-${this.name}-${ni.host.name}`;
66
+ result.properties.dependencies = ["keepalived"];
67
+
68
+ yield result;
69
+ }
70
+ }
61
71
  }
62
72
  }
package/src/dns.mjs CHANGED
@@ -22,6 +22,8 @@ const DNSServiceTypeDefinition = {
22
22
  }
23
23
  };
24
24
 
25
+ const DNS_SERVICE_FILTER = { type: DNSServiceTypeDefinition.name };
26
+
25
27
  export class DNSService extends Base {
26
28
  allowedUpdates = [];
27
29
  recordTTL = "1W";
@@ -65,9 +67,7 @@ export class DNSService extends Base {
65
67
  return this.#forwardsTo;
66
68
  }
67
69
 
68
- async *findServices() {
69
- const filter = { type: DNSServiceTypeDefinition.name };
70
-
70
+ *findServices(filter) {
71
71
  yield* this.owner.findServices(filter);
72
72
 
73
73
  for (const s of this.forwardsTo) {
@@ -80,17 +80,17 @@ export class DNSService extends Base {
80
80
  }
81
81
 
82
82
  async resolvedConfig() {
83
- const dnsServices = (await Array.fromAsync(this.findServices())).sort(
83
+ const dnsServices = Array.from(this.findServices(DNS_SERVICE_FILTER)).sort(
84
84
  (a, b) => a.priority - b.priority
85
85
  );
86
86
 
87
87
  const master = dnsServices
88
88
  .filter(s => s.priority < 10)
89
- .map(s => s.ipAddresses)
89
+ .map(s => s.rawAddresses)
90
90
  .flat();
91
91
  const fallback = dnsServices
92
92
  .filter(s => s.priority >= 10)
93
- .map(s => s.ipAddresses)
93
+ .map(s => s.rawAddresses)
94
94
  .flat();
95
95
 
96
96
  return {
@@ -107,15 +107,15 @@ export class DNSService extends Base {
107
107
  return `named-${this.owner.name}`;
108
108
  }
109
109
 
110
- async preparePackage(stagingDir) {
111
- const result = await super.preparePackage(stagingDir);
112
-
113
- await generateNamedDefs(this, stagingDir);
110
+ async *preparePackages(stagingDir) {
111
+ for await (const result of super.preparePackages(stagingDir)) {
112
+ await generateNamedDefs(this, stagingDir);
114
113
 
115
- result.properties.dependencies = ["mf-named"];
116
- result.properties.replaces = ["mf-named-zones"];
114
+ result.properties.dependencies = ["mf-named"];
115
+ result.properties.replaces = ["mf-named-zones"];
117
116
 
118
- return result;
117
+ yield result;
118
+ }
119
119
  }
120
120
  }
121
121
 
@@ -131,7 +131,7 @@ async function generateNamedDefs(dns, targetDir) {
131
131
  const zones = [];
132
132
  const records = new Set();
133
133
 
134
- const nameserver = (await dns.owner.findService({ type: "dns" }))?.owner;
134
+ const nameService = dns.findService(DNS_SERVICE_FILTER);
135
135
  const rname = dns.administratorEmail.replace(/@/, ".");
136
136
 
137
137
  let maxKeyLength;
@@ -157,18 +157,18 @@ async function generateNamedDefs(dns, targetDir) {
157
157
  );
158
158
  }
159
159
 
160
- console.log(dns.owner.fullName, domain, nameserver?.hostName, rname);
160
+ console.log(dns.owner.fullName, domain, nameService.domainName, rname);
161
161
  const reverseZones = new Map();
162
162
 
163
163
  const SOARecord = createRecord(
164
164
  "@",
165
165
  "SOA",
166
- fullName(nameserver?.domainName),
166
+ fullName(nameService.domainName),
167
167
  fullName(rname),
168
168
  `(${updates})`
169
169
  );
170
170
 
171
- const NSRecord = createRecord("@", "NS", fullName(nameserver?.rawAddress));
171
+ const NSRecord = createRecord("@", "NS", fullName(nameService.rawAddress));
172
172
 
173
173
  const catalogZone = {
174
174
  id: `catalog.${domain}`,
@@ -290,7 +290,11 @@ async function generateNamedDefs(dns, targetDir) {
290
290
  }
291
291
  }
292
292
 
293
- await writeLines(join(targetDir, "var/lib/named"), zone.file, zone.records);
293
+ await writeLines(
294
+ join(targetDir, "var/lib/named"),
295
+ zone.file,
296
+ zone.records
297
+ );
294
298
  }
295
299
 
296
300
  await writeLines(
package/src/host.mjs CHANGED
@@ -109,7 +109,7 @@ export class Host extends Base {
109
109
  for (const ni of this.networkInterfaces.values()) {
110
110
  ni._traverse(...args);
111
111
  }
112
- for (const service of this.findServices()) {
112
+ for (const service of this.#services) {
113
113
  service._traverse(...args);
114
114
  }
115
115
 
@@ -287,6 +287,17 @@ export class Host extends Base {
287
287
  return super.typeNamed(typeName, name);
288
288
  }
289
289
 
290
+ named(name) {
291
+ const ni = this.#networkInterfaces.get(name);
292
+ if (ni) {
293
+ return ni;
294
+ }
295
+ const service = this.services.find(s => s.name === name);
296
+ if (service) {
297
+ return service;
298
+ }
299
+ }
300
+
290
301
  get networkInterfaces() {
291
302
  return this.#networkInterfaces;
292
303
  }
@@ -333,25 +344,26 @@ export class Host extends Base {
333
344
  return `${this.constructor.typeDefinition.name}-${this.owner.name}-${this.name}`;
334
345
  }
335
346
 
336
- async preparePackage(stagingDir) {
337
- const result = await super.preparePackage(stagingDir);
338
- await generateNetworkDefs(this, stagingDir);
339
- await generateMachineInfo(this, stagingDir);
340
- await copySshKeys(this, stagingDir);
341
- await generateKnownHosts(
342
- this.owner.hosts(),
343
- join(stagingDir, "root", ".ssh")
344
- );
347
+ async *preparePackages(stagingDir) {
348
+ for await (const result of super.preparePackages(stagingDir)) {
349
+ await generateNetworkDefs(this, stagingDir);
350
+ await generateMachineInfo(this, stagingDir);
351
+ await copySshKeys(this, stagingDir);
352
+ await generateKnownHosts(
353
+ this.owner.hosts(),
354
+ join(stagingDir, "root", ".ssh")
355
+ );
345
356
 
346
- result.properties.dependencies = [
347
- this.location.packageName,
348
- ...this.depends
349
- ];
350
- result.properties.provides = [...this.provides];
351
- result.properties.replaces = [`mf-${this.hostName}`, ...this.replaces];
352
- result.properties.backup = "root/.ssh/known_hosts";
357
+ result.properties.dependencies = [
358
+ this.location.packageName,
359
+ ...this.depends
360
+ ];
361
+ result.properties.provides = [...this.provides];
362
+ result.properties.replaces = [`mf-${this.hostName}`, ...this.replaces];
363
+ result.properties.backup = "root/.ssh/known_hosts";
353
364
 
354
- return result;
365
+ yield result;
366
+ }
355
367
  }
356
368
  }
357
369
 
package/src/location.mjs CHANGED
@@ -45,52 +45,51 @@ export class Location extends Owner {
45
45
  return [...this.typeList("network")][0] || super.network;
46
46
  }
47
47
 
48
- async preparePackage(stagingDir) {
49
- const result = await super.preparePackage(stagingDir);
50
-
51
- await writeLines(
52
- join(stagingDir, "etc/systemd/resolved.conf.d"),
53
- `${this.name}.conf`,
54
- sectionLines("Resolve", await this.dns.resolvedConfig())
55
- );
56
-
57
- await writeLines(
58
- join(stagingDir, "etc/systemd/journald.conf.d"),
59
- `${this.name}.conf`,
60
- sectionLines("Journal", {
61
- Compress: "yes",
62
- SystemMaxUse: "500M",
63
- SyncIntervalSec: "15m"
64
- })
65
- );
66
-
67
- await writeLines(
68
- join(stagingDir, "etc/systemd/timesyncd.conf.d"),
69
- `${this.name}.conf`,
70
- sectionLines("Time", {
71
- NTP: this.ntp.servers.join(" "),
72
- PollIntervalMinSec: 60,
73
- SaveIntervalSec: 3600
74
- })
75
- );
76
-
77
- const locationDir = join(stagingDir, "etc", "location");
78
-
79
- await mkdir(locationDir, { recursive: true });
80
-
81
- await copyFile(
82
- join(this.directory, "location.json"),
83
- join(locationDir, "location.json")
84
- );
85
-
86
- result.properties.provides = [
87
- "location",
88
- "mf-location",
89
- `mf-location-${this.name}`
90
- ];
91
- result.properties.replaces = [`mf-location-${this.name}`];
92
-
93
- /*
48
+ async *preparePackages(stagingDir) {
49
+ for await (const result of super.preparePackages(stagingDir)) {
50
+ await writeLines(
51
+ join(stagingDir, "etc/systemd/resolved.conf.d"),
52
+ `${this.name}.conf`,
53
+ sectionLines("Resolve", await this.dns.resolvedConfig())
54
+ );
55
+
56
+ await writeLines(
57
+ join(stagingDir, "etc/systemd/journald.conf.d"),
58
+ `${this.name}.conf`,
59
+ sectionLines("Journal", {
60
+ Compress: "yes",
61
+ SystemMaxUse: "500M",
62
+ SyncIntervalSec: "15m"
63
+ })
64
+ );
65
+
66
+ await writeLines(
67
+ join(stagingDir, "etc/systemd/timesyncd.conf.d"),
68
+ `${this.name}.conf`,
69
+ sectionLines("Time", {
70
+ NTP: this.ntp.servers.join(" "),
71
+ PollIntervalMinSec: 60,
72
+ SaveIntervalSec: 3600
73
+ })
74
+ );
75
+
76
+ const locationDir = join(stagingDir, "etc", "location");
77
+
78
+ await mkdir(locationDir, { recursive: true });
79
+
80
+ await copyFile(
81
+ join(this.directory, "location.json"),
82
+ join(locationDir, "location.json")
83
+ );
84
+
85
+ result.properties.provides = [
86
+ "location",
87
+ "mf-location",
88
+ `mf-location-${this.name}`
89
+ ];
90
+ result.properties.replaces = [`mf-location-${this.name}`];
91
+
92
+ /*
94
93
  const install = "location.install";
95
94
 
96
95
  console.log(new URL(install, import.meta.url));
@@ -102,7 +101,8 @@ export class Location extends Owner {
102
101
 
103
102
  result.properties.install = install;
104
103
  */
105
-
106
- return result;
104
+
105
+ yield result;
106
+ }
107
107
  }
108
108
  }
package/src/owner.mjs CHANGED
@@ -90,12 +90,17 @@ export class Owner extends Base {
90
90
  }
91
91
 
92
92
  typeNamed(typeName, name) {
93
- if (name[0] === "/") {
94
- name = name.substring(this.fullName.length + 1);
95
- }
93
+ const localName = name[0] === "/" ? name.substring(this.fullName.length + 1) : name;
96
94
 
97
95
  const typeSlot = this.#membersByType.get(typeName);
98
- return typeSlot?.get(name) || this.owner?.typeNamed(typeName, name);
96
+ if (typeSlot) {
97
+ const object = typeSlot.get(localName);
98
+ if (object) {
99
+ return object;
100
+ }
101
+ }
102
+
103
+ return super.typeNamed(typeName, localName); // TODO use name
99
104
  }
100
105
 
101
106
  typeObject(typeName) {
@@ -121,17 +126,6 @@ export class Owner extends Base {
121
126
  this.addTypeObject(object.typeName, object.name, object);
122
127
  }
123
128
 
124
- findService(filter) {
125
- let best;
126
- for (const service of this.findServices(filter)) {
127
- if (!best || service.priority < best.priority) {
128
- best = service;
129
- }
130
- }
131
-
132
- return best;
133
- }
134
-
135
129
  *findServices(filter) {
136
130
  for (const host of this.hosts()) {
137
131
  for (const service of host.findServices(filter)) {
package/src/service.mjs CHANGED
@@ -79,16 +79,31 @@ export class Service extends Base {
79
79
  return this;
80
80
  }
81
81
 
82
+ get server()
83
+ {
84
+ return this.owner;
85
+ }
86
+
87
+ get domainName()
88
+ {
89
+ return this.server.domainName;
90
+ }
91
+
92
+ get rawAddress()
93
+ {
94
+ return this.#ipAddresses?.[0] || this.server.rawAddress;
95
+ }
96
+
82
97
  set ipAddresses(value) {
83
98
  this.#ipAddresses = value;
84
99
  }
85
100
 
86
- get ipAddresses() {
101
+ get rawAddresses() {
87
102
  return this.#ipAddresses || this.owner.rawAddresses;
88
103
  }
89
104
 
90
105
  get addresses() {
91
- return this.ipAddresses.map(a => `${a}:${this.port}`);
106
+ return this.rawAddresses.map(a => `${a}:${this.port}`);
92
107
  }
93
108
 
94
109
  set port(value) {
package/types/base.d.mts CHANGED
@@ -61,6 +61,8 @@ export class Base {
61
61
  get locales(): any;
62
62
  get country(): any;
63
63
  get timezone(): any;
64
+ findService(filter: any): any;
65
+ findServices(filter: any): Generator<any, void, any>;
64
66
  set directory(directory: any);
65
67
  get directory(): any;
66
68
  get fullName(): any;
@@ -69,14 +71,14 @@ export class Base {
69
71
  get packaging(): Set<any>;
70
72
  get derivedPackaging(): any;
71
73
  get outputs(): Set<typeof import("npm-pkgbuild").ARCH | typeof import("npm-pkgbuild").DOCKER>;
72
- preparePackage(stagingDir: any): Promise<{
74
+ preparePackages(stagingDir: any): AsyncGenerator<{
73
75
  outputs: Set<typeof import("npm-pkgbuild").ARCH | typeof import("npm-pkgbuild").DOCKER>;
74
76
  properties: {
75
77
  name: string;
76
78
  description: string;
77
79
  access: string;
78
80
  };
79
- }>;
81
+ }, void, unknown>;
80
82
  expand(object: any): any;
81
83
  finalize(action: any): void;
82
84
  execFinalize(): void;
package/types/dns.d.mts CHANGED
@@ -70,7 +70,6 @@ export class DNSService extends Base {
70
70
  get soaUpdates(): number[];
71
71
  set forwardsTo(value: any[]);
72
72
  get forwardsTo(): any[];
73
- findServices(): AsyncGenerator<any, void, any>;
74
73
  get domains(): any[];
75
74
  resolvedConfig(): Promise<{
76
75
  DNS: string;
package/types/host.d.mts CHANGED
@@ -176,6 +176,7 @@ export class Host extends Base {
176
176
  get domainName(): string;
177
177
  get host(): this;
178
178
  findServices(filter: any): Generator<any, void, unknown>;
179
+ named(name: any): any;
179
180
  set networkInterfaces(networkInterface: Map<any, any>);
180
181
  get networkInterfaces(): Map<any, any>;
181
182
  networkAddresses(): Generator<{
package/types/owner.d.mts CHANGED
@@ -184,7 +184,6 @@ export class Owner extends Base {
184
184
  typeList(typeName: any): any;
185
185
  addTypeObject(typeName: any, name: any, object: any): void;
186
186
  addObject(object: any): void;
187
- findService(filter: any): any;
188
187
  findServices(filter: any): Generator<any, void, unknown>;
189
188
  locationNamed(name: any): any;
190
189
  locations(): any;
@@ -89,8 +89,11 @@ export class Service extends Base {
89
89
  };
90
90
  };
91
91
  alias: any;
92
+ get server(): any;
93
+ get domainName(): any;
94
+ get rawAddress(): any;
92
95
  set ipAddresses(value: any);
93
- get ipAddresses(): any;
96
+ get rawAddresses(): any;
94
97
  get addresses(): any;
95
98
  set port(value: any);
96
99
  get port(): any;