pmcf 1.83.0 → 1.84.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/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "1.83.0",
3
+ "version": "1.84.0",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/base.mjs CHANGED
@@ -1,6 +1,5 @@
1
1
  import { join } from "node:path";
2
- import { createReadStream } from "node:fs";
3
- import { allOutputs, extractFunctions } from "npm-pkgbuild";
2
+ import { allOutputs } from "npm-pkgbuild";
4
3
  import { getAttribute } from "pacc";
5
4
  import { addType, primitives } from "./types.mjs";
6
5
 
@@ -354,27 +353,6 @@ export class Base {
354
353
  return this.#packaging;
355
354
  }
356
355
 
357
- #packageHooks = {};
358
-
359
- get packageHooks() {
360
- return this.#packageHooks;
361
- }
362
-
363
- async loadPackageHooks(file) {
364
- for await (const f of extractFunctions(createReadStream(file, "utf8"))) {
365
- this.addPackageHook(f.name, f.body);
366
- }
367
- }
368
-
369
- addPackageHook(name, content) {
370
- const hook = this.#packageHooks[name];
371
- if (hook) {
372
- content = hook + "\n" + content;
373
- }
374
-
375
- this.#packageHooks[name] = content;
376
- }
377
-
378
356
  get outputs() {
379
357
  return new Set(allOutputs.filter(o => this.packaging.has(o.name)));
380
358
  }
package/src/dns.mjs CHANGED
@@ -29,6 +29,7 @@ const DNSServiceTypeDefinition = {
29
29
  },
30
30
  notify: { type: "boolean", collection: false, writeable: true },
31
31
  recordTTL: { type: "string", collection: false, writeable: true },
32
+ serial: { type: "number", collection: false, writeable: true },
32
33
  refresh: { type: "string", collection: false, writeable: true },
33
34
  retry: { type: "string", collection: false, writeable: true },
34
35
  expire: { type: "string", collection: false, writeable: true },
@@ -49,6 +50,7 @@ export class DNSService extends Base {
49
50
  #source = [];
50
51
  #trusted = [];
51
52
 
53
+ serial = Math.ceil(Date.now() / 1000);
52
54
  refresh = 36000;
53
55
  retry = 72000;
54
56
  expire = 600000;
@@ -73,7 +75,7 @@ export class DNSService extends Base {
73
75
  }
74
76
 
75
77
  get soaUpdates() {
76
- return [this.refresh, this.retry, this.expire, this.minimum];
78
+ return [this.serial, this.refresh, this.retry, this.expire, this.minimum];
77
79
  }
78
80
 
79
81
  set trusted(value) {
@@ -120,11 +122,11 @@ export class DNSService extends Base {
120
122
  ];
121
123
  }
122
124
 
123
- async *preparePackages(stagingDir) {
125
+ async *preparePackages(dir) {
124
126
  const name = this.owner.name;
125
- const p1 = join(stagingDir, "p1");
126
-
127
- const result = {
127
+ const p1 = join(dir, "p1");
128
+ const packageData = {
129
+ dir: p1,
128
130
  sources: [new FileContentProvider(p1 + "/")[Symbol.asyncIterator]()],
129
131
  outputs: this.outputs,
130
132
  properties: {
@@ -154,12 +156,12 @@ export class DNSService extends Base {
154
156
  );
155
157
 
156
158
  if (options.length > 2 || category.length > 2) {
157
- yield result;
159
+ yield packageData;
158
160
  }
159
161
 
160
- const p2 = join(stagingDir, "p2");
162
+ const p2 = (packageData.dir = join(dir, "p2"));
161
163
 
162
- result.properties = {
164
+ packageData.properties = {
163
165
  name: `named-zones-${name}`,
164
166
  description: `zone definitions for ${this.fullName}`,
165
167
  dependencies: ["mf-named"],
@@ -167,31 +169,28 @@ export class DNSService extends Base {
167
169
  access: "private"
168
170
  };
169
171
 
170
- result.sources = [
171
- new FileContentProvider(
172
- p2 + "/",
173
- {
174
- mode: 0o644,
175
- owner: "named",
176
- group: "named"
177
- },
178
- {
179
- mode: 0o755,
180
- owner: "named",
181
- group: "named"
182
- }
183
- )[Symbol.asyncIterator]()
172
+ packageData.sources = [
173
+ new FileContentProvider(p2 + "/", {
174
+ mode: 0o644,
175
+ owner: "named",
176
+ group: "named"
177
+ }, {
178
+ mode: 0o755,
179
+ owner: "named",
180
+ group: "named"
181
+ })[
182
+ Symbol.asyncIterator
183
+ ]()
184
184
  ];
185
185
 
186
- await generateZoneDefs(this, p2);
186
+ await generateZoneDefs(this, packageData);
187
187
 
188
- yield result;
188
+ yield packageData;
189
189
  }
190
190
  }
191
191
 
192
- async function generateZoneDefs(dns, targetDir) {
192
+ async function generateZoneDefs(dns, packageData) {
193
193
  const ttl = dns.recordTTL;
194
- const updates = [Math.ceil(Date.now() / 1000), ...dns.soaUpdates].join(" ");
195
194
  const nameService = dns.findService(DNS_SERVICE_FILTER);
196
195
  const rname = dns.administratorEmail.replace(/@/, ".");
197
196
 
@@ -200,7 +199,7 @@ async function generateZoneDefs(dns, targetDir) {
200
199
  "SOA",
201
200
  dnsFullName(nameService.domainName),
202
201
  dnsFullName(rname),
203
- `(${updates})`
202
+ `(${[...dns.soaUpdates].join(" ")})`
204
203
  );
205
204
 
206
205
  const NSRecord = DNSRecord(
@@ -380,14 +379,14 @@ async function generateZoneDefs(dns, targetDir) {
380
379
  }
381
380
 
382
381
  await writeLines(
383
- join(targetDir, "var/lib/named"),
382
+ join(packageData.dir, "var/lib/named"),
384
383
  zone.file,
385
384
  [...zone.records].map(r => r.toString(maxKeyLength, ttl))
386
385
  );
387
386
  }
388
387
 
389
388
  await writeLines(
390
- join(targetDir, "etc/named.d/zones"),
389
+ join(packageData.dir, "etc/named.d/zones"),
391
390
  config.name,
392
391
  content
393
392
  );
package/src/hooks.mjs ADDED
@@ -0,0 +1,21 @@
1
+ import { createReadStream } from "node:fs";
2
+ import { extractFunctions } from "npm-pkgbuild";
3
+
4
+ export async function loadHooks(hooks, file) {
5
+ for await (const f of extractFunctions(createReadStream(file, "utf8"))) {
6
+ addHook(hooks, f.name, f.body);
7
+ }
8
+
9
+ return hooks;
10
+ }
11
+
12
+ export function addHook(hooks, name, content) {
13
+ const hook = hooks[name];
14
+ if (hook) {
15
+ content = hook + "\n" + content;
16
+ }
17
+
18
+ hooks[name] = content;
19
+
20
+ return hooks;
21
+ }
@@ -1,9 +1,10 @@
1
1
  import { writeFile, mkdir, copyFile, glob, chmod } from "node:fs/promises";
2
2
  import { join } from "node:path";
3
3
  import { writeLines, sectionLines } from "../src/utils.mjs";
4
+ import { addHook } from "./hooks.mjs";
4
5
 
5
- export async function generateMachineInfo(host, dir) {
6
- const etcDir = join(dir, "etc");
6
+ export async function generateMachineInfo(host, packageData) {
7
+ const etcDir = join(packageData.dir, "etc");
7
8
  await writeLines(
8
9
  etcDir,
9
10
  "machine-info",
@@ -20,8 +21,8 @@ export async function generateMachineInfo(host, dir) {
20
21
  await writeLines(etcDir, "hostname", host.hostName);
21
22
  }
22
23
 
23
- export async function generateNetworkDefs(host, dir) {
24
- const networkDir = join(dir, "etc/systemd/network");
24
+ export async function generateNetworkDefs(host, packageData) {
25
+ const networkDir = join(packageData.dir, "etc/systemd/network");
25
26
 
26
27
  for (const ni of host.networkInterfaces.values()) {
27
28
  if (ni.name !== "eth0" && ni.hwaddr) {
@@ -100,7 +101,7 @@ export async function generateNetworkDefs(host, dir) {
100
101
  }
101
102
  break;
102
103
  case "wifi": {
103
- const d = join(dir, "etc/wpa_supplicant");
104
+ const d = join(packageData.dir, "etc/wpa_supplicant");
104
105
  await mkdir(d, { recursive: true });
105
106
  writeFile(
106
107
  join(d, `wpa_supplicant-${ni.name}.conf`),
@@ -116,7 +117,8 @@ network={
116
117
  "utf8"
117
118
  );
118
119
 
119
- host.addPackageHook(
120
+ addHook(
121
+ packageData.properties.hooks,
120
122
  "post_install",
121
123
  `systemctl enable wpa_supplicant@${ni.name}.service`
122
124
  );
@@ -125,8 +127,8 @@ network={
125
127
  }
126
128
  }
127
129
 
128
- export async function copySshKeys(host, dir) {
129
- const sshDir = join(dir, "etc", "ssh");
130
+ export async function copySshKeys(host, packageData) {
131
+ const sshDir = join(packageData.dir, "etc", "ssh");
130
132
 
131
133
  await mkdir(sshDir, { recursive: true });
132
134
 
package/src/host.mjs CHANGED
@@ -18,6 +18,7 @@ import {
18
18
  } from "./utils.mjs";
19
19
  import { objectFilter } from "./filter.mjs";
20
20
  import { addType, types } from "./types.mjs";
21
+ import { loadHooks } from "./hooks.mjs";
21
22
  import {
22
23
  generateNetworkDefs,
23
24
  generateMachineInfo,
@@ -156,7 +157,9 @@ export class Host extends Base {
156
157
  }
157
158
 
158
159
  get architecture() {
159
- return this.#architecture || this.extends.find(e => e.architecture)?.architecture;
160
+ return (
161
+ this.#architecture || this.extends.find(e => e.architecture)?.architecture
162
+ );
160
163
  }
161
164
 
162
165
  get derivedPackaging() {
@@ -390,36 +393,39 @@ export class Host extends Base {
390
393
  return readFile(join(this.directory, `ssh_host_${type}_key.pub`), "utf8");
391
394
  }
392
395
 
393
- async *preparePackages(stagingDir) {
394
- await this.loadPackageHooks(
395
- new URL("host.install", import.meta.url).pathname
396
+ async *preparePackages(dir) {
397
+ const packageData = {
398
+ dir,
399
+ sources: [
400
+ new FileContentProvider(dir + "/")[Symbol.asyncIterator]()
401
+ ],
402
+ outputs: this.outputs,
403
+ properties: {
404
+ name: `${this.typeName}-${this.owner.name}-${this.name}`,
405
+ description: `${this.typeName} definitions for ${this.fullName}`,
406
+ access: "private",
407
+ dependencies: [
408
+ `${this.location.typeName}-${this.location.name}`,
409
+ ...this.depends
410
+ ],
411
+ provides: [...this.provides],
412
+ replaces: [`mf-${this.hostName}`, ...this.replaces],
413
+ backup: "root/.ssh/known_hosts",
414
+ hooks: await loadHooks({},
415
+ new URL("host.install", import.meta.url).pathname
416
+ )
417
+ }
418
+ };
419
+
420
+ await generateNetworkDefs(this, packageData);
421
+ await generateMachineInfo(this, packageData);
422
+ await copySshKeys(this, packageData);
423
+ await generateKnownHosts(
424
+ this.owner.hosts(),
425
+ join(dir, "root", ".ssh")
396
426
  );
397
427
 
398
- for await (const result of super.preparePackages(stagingDir)) {
399
- await generateNetworkDefs(this, stagingDir);
400
- await generateMachineInfo(this, stagingDir);
401
- await copySshKeys(this, stagingDir);
402
- await generateKnownHosts(
403
- this.owner.hosts(),
404
- join(stagingDir, "root", ".ssh")
405
- );
406
-
407
- result.properties.name = `${this.typeName}-${this.owner.name}-${this.name}`;
408
- result.properties.dependencies = [
409
- `${this.location.typeName}-${this.location.name}`,
410
- ...this.depends
411
- ];
412
- result.properties.provides = [...this.provides];
413
- result.properties.replaces = [`mf-${this.hostName}`, ...this.replaces];
414
- result.properties.backup = "root/.ssh/known_hosts";
415
- result.properties.hooks = this.packageHooks;
416
-
417
- result.sources.push(
418
- new FileContentProvider(stagingDir + "/")[Symbol.asyncIterator]()
419
- );
420
-
421
- yield result;
422
- }
428
+ yield packageData;
423
429
  }
424
430
  }
425
431
 
package/src/location.mjs CHANGED
@@ -4,6 +4,7 @@ import { FileContentProvider } from "npm-pkgbuild";
4
4
  import { Owner } from "./owner.mjs";
5
5
  import { addType } from "./types.mjs";
6
6
  import { writeLines, sectionLines } from "./utils.mjs";
7
+ import { loadHooks } from "./hooks.mjs";
7
8
 
8
9
  const LocationTypeDefinition = {
9
10
  name: "location",
@@ -45,56 +46,56 @@ export class Location extends Owner {
45
46
  return [...this.typeList("network")][0] || super.network;
46
47
  }
47
48
 
48
- async *preparePackages(stagingDir) {
49
- await this.loadPackageHooks(
50
- new URL("location.install", import.meta.url).pathname
49
+ async *preparePackages(dir) {
50
+ const packageData = {
51
+ dir,
52
+ sources: [new FileContentProvider(dir + "/")[Symbol.asyncIterator]()],
53
+ outputs: this.outputs,
54
+ properties: {
55
+ name: `${this.typeName}-${this.name}`,
56
+ description: `${this.typeName} definitions for ${this.fullName}`,
57
+ access: "private",
58
+ dependencies: { jq: ">=1.6" },
59
+ provides: ["location", "mf-location"],
60
+ replaces: [`mf-location-${this.name}`],
61
+ hooks: await loadHooks(
62
+ {},
63
+ new URL("location.install", import.meta.url).pathname
64
+ )
65
+ }
66
+ };
67
+
68
+ await writeLines(
69
+ join(dir, "etc/systemd/resolved.conf.d"),
70
+ `${this.name}.conf`,
71
+ sectionLines(...this.dns.systemdConfig)
51
72
  );
52
73
 
53
- for await (const result of super.preparePackages(stagingDir)) {
54
- await writeLines(
55
- join(stagingDir, "etc/systemd/resolved.conf.d"),
56
- `${this.name}.conf`,
57
- sectionLines(...this.dns.systemdConfig)
58
- );
59
-
60
- await writeLines(
61
- join(stagingDir, "etc/systemd/journald.conf.d"),
62
- `${this.name}.conf`,
63
- sectionLines("Journal", {
64
- Compress: "yes",
65
- SystemMaxUse: "500M",
66
- SyncIntervalSec: "15m"
67
- })
68
- );
69
-
70
- await writeLines(
71
- join(stagingDir, "etc/systemd/timesyncd.conf.d"),
72
- `${this.name}.conf`,
73
- sectionLines(...this.ntp.systemdConfig)
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
- );
74
+ await writeLines(
75
+ join(dir, "etc/systemd/journald.conf.d"),
76
+ `${this.name}.conf`,
77
+ sectionLines("Journal", {
78
+ Compress: "yes",
79
+ SystemMaxUse: "500M",
80
+ SyncIntervalSec: "15m"
81
+ })
82
+ );
84
83
 
85
- result.properties.name = `${this.typeName}-${this.name}`;
84
+ await writeLines(
85
+ join(dir, "etc/systemd/timesyncd.conf.d"),
86
+ `${this.name}.conf`,
87
+ sectionLines(...this.ntp.systemdConfig)
88
+ );
86
89
 
87
- result.properties.provides = ["location", "mf-location"];
88
- result.properties.depends = { jq: ">=1.6" };
89
- result.properties.replaces = [`mf-location-${this.name}`];
90
+ const locationDir = join(dir, "etc", "location");
90
91
 
91
- result.sources.push(
92
- new FileContentProvider(stagingDir + "/")[Symbol.asyncIterator]()
93
- );
92
+ await mkdir(locationDir, { recursive: true });
94
93
 
95
- result.properties.hooks = this.packageHooks;
94
+ await copyFile(
95
+ join(this.directory, "location.json"),
96
+ join(locationDir, "location.json")
97
+ );
96
98
 
97
- yield result;
98
- }
99
+ yield packageData;
99
100
  }
100
101
  }
package/types/base.d.mts CHANGED
@@ -73,9 +73,6 @@ export class Base {
73
73
  set packaging(value: Set<any>);
74
74
  get packaging(): Set<any>;
75
75
  get derivedPackaging(): any;
76
- get packageHooks(): {};
77
- loadPackageHooks(file: any): Promise<void>;
78
- addPackageHook(name: any, content: any): void;
79
76
  get outputs(): Set<typeof import("npm-pkgbuild").ARCH | typeof import("npm-pkgbuild").DOCKER>;
80
77
  preparePackages(stagingDir: any): AsyncGenerator<{
81
78
  sources: any[];
@@ -127,6 +127,11 @@ export class Cluster extends Host {
127
127
  collection: boolean;
128
128
  writeable: boolean;
129
129
  };
130
+ serial: {
131
+ type: string;
132
+ collection: boolean;
133
+ writeable: boolean;
134
+ };
130
135
  refresh: {
131
136
  type: string;
132
137
  collection: boolean;
package/types/dns.d.mts CHANGED
@@ -41,6 +41,11 @@ export class DNSService extends Base {
41
41
  collection: boolean;
42
42
  writeable: boolean;
43
43
  };
44
+ serial: {
45
+ type: string;
46
+ collection: boolean;
47
+ writeable: boolean;
48
+ };
44
49
  refresh: {
45
50
  type: string;
46
51
  collection: boolean;
@@ -74,6 +79,7 @@ export class DNSService extends Base {
74
79
  hasCatalog: boolean;
75
80
  hasLinkLocalAdresses: boolean;
76
81
  notify: boolean;
82
+ serial: number;
77
83
  refresh: number;
78
84
  retry: number;
79
85
  expire: number;
@@ -91,7 +97,8 @@ export class DNSService extends Base {
91
97
  MulticastDNS: string;
92
98
  LLMNR: string;
93
99
  })[];
94
- preparePackages(stagingDir: any): AsyncGenerator<{
100
+ preparePackages(dir: any): AsyncGenerator<{
101
+ dir: string;
95
102
  sources: AsyncIterable<import("content-entry").ContentEntry>[];
96
103
  outputs: Set<typeof import("npm-pkgbuild").ARCH | typeof import("npm-pkgbuild").DOCKER>;
97
104
  properties: {
@@ -0,0 +1,2 @@
1
+ export function loadHooks(hooks: any, file: any): Promise<any>;
2
+ export function addHook(hooks: any, name: any, content: any): any;
@@ -1,4 +1,4 @@
1
- export function generateMachineInfo(host: any, dir: any): Promise<void>;
2
- export function generateNetworkDefs(host: any, dir: any): Promise<void>;
3
- export function copySshKeys(host: any, dir: any): Promise<void>;
1
+ export function generateMachineInfo(host: any, packageData: any): Promise<void>;
2
+ export function generateNetworkDefs(host: any, packageData: any): Promise<void>;
3
+ export function copySshKeys(host: any, packageData: any): Promise<void>;
4
4
  export function generateKnownHosts(hosts: any, dir: any): Promise<void>;
package/types/host.d.mts CHANGED
@@ -212,6 +212,21 @@ export class Host extends Base {
212
212
  get cidrAddress(): any;
213
213
  get cidrAddresses(): any[];
214
214
  publicKey(type?: string): Promise<string>;
215
+ preparePackages(dir: any): AsyncGenerator<{
216
+ dir: any;
217
+ sources: AsyncIterable<import("content-entry").ContentEntry>[];
218
+ outputs: Set<typeof import("npm-pkgbuild").ARCH | typeof import("npm-pkgbuild").DOCKER>;
219
+ properties: {
220
+ name: string;
221
+ description: string;
222
+ access: string;
223
+ dependencies: any[];
224
+ provides: any[];
225
+ replaces: any[];
226
+ backup: string;
227
+ hooks: any;
228
+ };
229
+ }, void, unknown>;
215
230
  #private;
216
231
  }
217
232
  export class NetworkInterface extends Base {
@@ -127,6 +127,11 @@ export class Location extends Owner {
127
127
  collection: boolean;
128
128
  writeable: boolean;
129
129
  };
130
+ serial: {
131
+ type: string;
132
+ collection: boolean;
133
+ writeable: boolean;
134
+ };
130
135
  refresh: {
131
136
  type: string;
132
137
  collection: boolean;
@@ -337,6 +342,11 @@ export class Location extends Owner {
337
342
  collection: boolean;
338
343
  writeable: boolean;
339
344
  };
345
+ serial: {
346
+ type: string;
347
+ collection: boolean;
348
+ writeable: boolean;
349
+ };
340
350
  refresh: {
341
351
  type: string;
342
352
  collection: boolean;
@@ -429,5 +439,21 @@ export class Location extends Owner {
429
439
  };
430
440
  };
431
441
  get location(): this;
442
+ preparePackages(dir: any): AsyncGenerator<{
443
+ dir: any;
444
+ sources: AsyncIterable<import("content-entry").ContentEntry>[];
445
+ outputs: Set<typeof import("npm-pkgbuild").ARCH | typeof import("npm-pkgbuild").DOCKER>;
446
+ properties: {
447
+ name: string;
448
+ description: string;
449
+ access: string;
450
+ dependencies: {
451
+ jq: string;
452
+ };
453
+ provides: string[];
454
+ replaces: string[];
455
+ hooks: any;
456
+ };
457
+ }, void, unknown>;
432
458
  }
433
459
  import { Owner } from "./owner.mjs";
@@ -129,6 +129,11 @@ export class Network extends Owner {
129
129
  collection: boolean;
130
130
  writeable: boolean;
131
131
  };
132
+ serial: {
133
+ type: string;
134
+ collection: boolean;
135
+ writeable: boolean;
136
+ };
132
137
  refresh: {
133
138
  type: string;
134
139
  collection: boolean;
package/types/owner.d.mts CHANGED
@@ -125,6 +125,11 @@ export class Owner extends Base {
125
125
  collection: boolean;
126
126
  writeable: boolean;
127
127
  };
128
+ serial: {
129
+ type: string;
130
+ collection: boolean;
131
+ writeable: boolean;
132
+ };
128
133
  refresh: {
129
134
  type: string;
130
135
  collection: boolean;
package/types/root.d.mts CHANGED
@@ -131,6 +131,11 @@ export class Root extends Location {
131
131
  collection: boolean;
132
132
  writeable: boolean;
133
133
  };
134
+ serial: {
135
+ type: string;
136
+ collection: boolean;
137
+ writeable: boolean;
138
+ };
134
139
  refresh: {
135
140
  type: string;
136
141
  collection: boolean;
@@ -341,6 +346,11 @@ export class Root extends Location {
341
346
  collection: boolean;
342
347
  writeable: boolean;
343
348
  };
349
+ serial: {
350
+ type: string;
351
+ collection: boolean;
352
+ writeable: boolean;
353
+ };
344
354
  refresh: {
345
355
  type: string;
346
356
  collection: boolean;