pmcf 1.4.1 → 1.5.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.
@@ -1,17 +1,17 @@
1
1
  #!/usr/bin/env node
2
2
 
3
3
  import { writeFile, mkdir, copyFile, glob } from "node:fs/promises";
4
- import { cwd, argv } from "node:process";
5
4
  import { join } from "node:path";
6
- import { World, writeLines, sectionLines } from "../src/model.mjs";
5
+ import { writeLines, sectionLines } from "../src/model.mjs";
6
+ import { prepare } from "../src/cmd.mjs";
7
7
 
8
- const world = new World(argv[2] || cwd());
8
+ const { world, args } = prepare();
9
9
 
10
- const hostName = argv[3];
10
+ const hostName = args[0];
11
11
 
12
12
  const host = await world.host(hostName);
13
13
 
14
- const targetDir = argv[4] || `pkg/host-${host.hostName}`;
14
+ const targetDir = args[1] || `pkg/host-${host.hostName}`;
15
15
 
16
16
  await generateNetworkDefs(host, targetDir);
17
17
  await generateMachineInfo(host, targetDir);
package/bin/pmcf-info CHANGED
@@ -1,10 +1,8 @@
1
1
  #!/usr/bin/env node
2
- import { cwd, argv } from "node:process";
3
- import { World } from "../src/model.mjs";
2
+ import { prepare } from "../src/cmd.mjs";
3
+ const { world, args } = prepare();
4
4
 
5
- const world = new World(argv[2] || cwd());
6
-
7
- const objectName = argv[3];
5
+ const objectName = args[0];
8
6
 
9
7
  if (objectName) {
10
8
  const object = await world.named(objectName);
@@ -1,17 +1,23 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { cwd, argv } from "node:process";
4
3
  import { mkdir, copyFile } from "node:fs/promises";
5
4
  import { join } from "node:path";
6
- import { World, writeLines, sectionLines } from "../src/model.mjs";
5
+ import { writeLines, sectionLines } from "../src/model.mjs";
6
+ import { prepare } from "../src/cmd.mjs";
7
7
 
8
- const world = new World(argv[2] || cwd());
9
- const location = await world.location(argv[3] || "SW");
10
- const targetDir = argv[4];
8
+ const { world, args } = prepare();
9
+
10
+ const location = await world.location(args[0] || "SW");
11
+ const targetDir = args[1];
11
12
 
12
13
  await generateLocationDefs(location, targetDir);
13
14
 
14
- console.log("provides", "location", "mf-location", `mf-location-${location.name}`);
15
+ console.log(
16
+ "provides",
17
+ "location",
18
+ "mf-location",
19
+ `mf-location-${location.name}`
20
+ );
15
21
  console.log("replaces", `mf-location-${location.name}`);
16
22
  console.log("description", `location definitions for ${location.name}`);
17
23
 
@@ -1,14 +1,14 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { cwd, argv } from "node:process";
4
3
  import { join } from "node:path";
5
4
  import { createHmac } from "node:crypto";
5
+ import { writeLines } from "../src/model.mjs";
6
+ import { prepare } from "../src/cmd.mjs";
6
7
 
7
- import { World, writeLines } from "../src/model.mjs";
8
+ const { world, args } = prepare();
8
9
 
9
- const world = new World(argv[2] || cwd());
10
- const location = await world.location(argv[3] || "SW");
11
- const targetDir = argv[4] || `pkg/mf-named-${location.name}`;
10
+ const location = await world.location(args[0] || "SW");
11
+ const targetDir = args[1] || `pkg/mf-named-${location.name}`;
12
12
  const ttl = location.dnsRecordTTL;
13
13
  const updates = [
14
14
  Math.ceil(Date.now() / 1000),
@@ -38,7 +38,7 @@ async function generateNamedDefs(location, targetDir) {
38
38
  const records = new Set();
39
39
 
40
40
  const nameserver = (await location.service({ type: "dns" }))?.owner;
41
- const rname = location.administratorEmail.replace(/@/,'.');
41
+ const rname = location.administratorEmail.replace(/@/, ".");
42
42
 
43
43
  for await (const mail of location.services({ type: "smtp" })) {
44
44
  records.add(
@@ -48,12 +48,7 @@ async function generateNamedDefs(location, targetDir) {
48
48
  );
49
49
  }
50
50
 
51
- console.log(
52
- location.name,
53
- location.domain,
54
- nameserver?.hostName,
55
- rname
56
- );
51
+ console.log(location.name, location.domain, nameserver?.hostName, rname);
57
52
 
58
53
  const catalogZone = {
59
54
  id: `catalog.${domain}`,
@@ -63,7 +58,7 @@ async function generateNamedDefs(location, targetDir) {
63
58
  nameserver.domainName
64
59
  }. ${rname}. (${updates})`,
65
60
  `${"@".padEnd(NAME_LEN, " ")} ${ttl} IN NS ${nameserver.ipAddress}.`,
66
- `${("version."+domain+'.').padEnd(NAME_LEN, " ")} IN TXT "2"`
61
+ `${("version." + domain + ".").padEnd(NAME_LEN, " ")} IN TXT "2"`
67
62
  ])
68
63
  };
69
64
 
@@ -152,9 +147,11 @@ async function generateNamedDefs(location, targetDir) {
152
147
  zones.push(catalogZone);
153
148
 
154
149
  for (const zone of zones) {
155
- if(zone !== catalogZone) {
150
+ if (zone !== catalogZone) {
156
151
  const hash = createHmac("md5", zone.id).digest("hex");
157
- catalogZone.records.add(`${hash}.zones.${domain}. IN PTR ${zone.id}.`);
152
+ catalogZone.records.add(
153
+ `${hash}.zones.${domain}. IN PTR ${zone.id}.`
154
+ );
158
155
  }
159
156
 
160
157
  zoneConfig.push(`zone \"${zone.id}\" {`);
@@ -162,7 +159,9 @@ async function generateNamedDefs(location, targetDir) {
162
159
  zoneConfig.push(` file \"${zone.file}\";`);
163
160
 
164
161
  const u = location.dnsAllowedUpdates;
165
- zoneConfig.push(` allow-update { ${u.length ? u.join(';') : "none" }; };`);
162
+ zoneConfig.push(
163
+ ` allow-update { ${u.length ? u.join(";") : "none"}; };`
164
+ );
166
165
  zoneConfig.push(` notify yes;`);
167
166
  zoneConfig.push(`};`);
168
167
  zoneConfig.push("");
package/bin/pmcf-network CHANGED
@@ -1,16 +1,16 @@
1
1
  #!/usr/bin/env node
2
2
 
3
- import { cwd, argv } from "node:process";
4
- import { World } from "../src/model.mjs";
3
+ import { prepare } from "../src/cmd.mjs";
5
4
 
6
- const world = new World(argv[2] || cwd());
7
- const location = await world.location(argv[3] || "SW");
5
+ const { world, args } = prepare();
6
+
7
+ const location = await world.location(args[0] || "SW");
8
8
 
9
9
  function q(str) {
10
10
  return str.match(/^\w+$/) ? str : `"${str}"`;
11
11
  }
12
12
  function id(str) {
13
- return str.replaceAll(/-/g,'');
13
+ return str.replaceAll(/-/g, "");
14
14
  }
15
15
 
16
16
  console.log("graph G {");
@@ -26,7 +26,11 @@ for await (const host of location.hosts()) {
26
26
  }
27
27
 
28
28
  for await (const network of location.networks()) {
29
- console.log(` ${id(network.name)} [label="${network.name}\\n${network.ipv4}" shape=circle];`);
29
+ console.log(
30
+ ` ${id(network.name)} [label="${network.name}\\n${
31
+ network.ipv4
32
+ }" shape=circle];`
33
+ );
30
34
 
31
35
  for await (const host of network.hosts()) {
32
36
  for (const [n, i] of Object.entries(host.networkInterfaces)) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "pmcf",
3
- "version": "1.4.1",
3
+ "version": "1.5.1",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
package/src/cmd.mjs ADDED
@@ -0,0 +1,26 @@
1
+ import { parseArgs } from "node:util";
2
+ import { argv, cwd, env } from "node:process";
3
+ import { World } from "./model.mjs";
4
+
5
+ export function prepare() {
6
+ const { values, positionals } = parseArgs({
7
+ args: argv.slice(2),
8
+ options: {
9
+ world: {
10
+ type: "string",
11
+ short: "w",
12
+ default: env.PMCF_WORLD || cwd()
13
+ },
14
+ output: {
15
+ type: "string",
16
+ short: "o",
17
+ default: cwd()
18
+ }
19
+ },
20
+ allowPositionals: true
21
+ });
22
+
23
+ const world = new World(values.world);
24
+
25
+ return { world, options: values, args: positionals };
26
+ }
package/src/model.mjs CHANGED
@@ -51,6 +51,17 @@ export class Base {
51
51
  return this.constructor.typeName;
52
52
  }
53
53
 
54
+ get world() {
55
+ return this.owner.world;
56
+ }
57
+
58
+ get location() {
59
+ if (this instanceof Location) {
60
+ return this;
61
+ }
62
+ return this.owner.location;
63
+ }
64
+
54
65
  get host() {
55
66
  if (this instanceof Host) {
56
67
  return this;
@@ -58,11 +69,8 @@ export class Base {
58
69
  return this.owner.host;
59
70
  }
60
71
 
61
- get network() {
62
- if (this instanceof Network) {
63
- return this;
64
- }
65
- return this.owner.network;
72
+ network(name) {
73
+ return this.owner.network(name);
66
74
  }
67
75
 
68
76
  #directory;
@@ -121,6 +129,10 @@ export class World {
121
129
  return "";
122
130
  }
123
131
 
132
+ get world() {
133
+ return this;
134
+ }
135
+
124
136
  async _loadType(name, type) {
125
137
  const baseName = type.baseName(name);
126
138
 
@@ -134,10 +146,21 @@ export class World {
134
146
  )
135
147
  );
136
148
 
149
+ let owner;
150
+ let path = baseName.split("/");
151
+
152
+ if (path.length > 1 && path[0] !== "model" && path[0] != "services") {
153
+ // TODO
154
+ path.length -= 1;
155
+ owner = await this._loadType(path.join("/"), Location);
156
+ } else {
157
+ owner = this;
158
+ }
159
+
137
160
  data.name = baseName;
138
161
 
139
162
  type = await type.prepareData(this, data);
140
- object = new type(this, data);
163
+ object = new type(owner, data);
141
164
  this.#byName.set(data.name, object);
142
165
  }
143
166
 
@@ -193,6 +216,9 @@ export class World {
193
216
  return this._loadType(name, Host);
194
217
  }
195
218
 
219
+ addHost(host) {}
220
+ network(name) {}
221
+
196
222
  async *subnets() {
197
223
  for await (const location of this.locations()) {
198
224
  yield* location.subnets();
@@ -212,7 +238,6 @@ export class Host extends Base {
212
238
  networkInterfaces = {};
213
239
  services = {};
214
240
  postinstall = [];
215
- location;
216
241
  #extends = [];
217
242
  #provides = new Set();
218
243
  #replaces = new Set();
@@ -221,6 +246,7 @@ export class Host extends Base {
221
246
  #os;
222
247
  #distribution;
223
248
  #deployment;
249
+ #location;
224
250
 
225
251
  static get typeName() {
226
252
  return "host";
@@ -245,11 +271,15 @@ export class Host extends Base {
245
271
  constructor(owner, data) {
246
272
  super(owner, data);
247
273
 
274
+ if (data.location !== undefined) {
275
+ this.#location = data.location;
276
+ delete data.location;
277
+ }
278
+
248
279
  if (data.deployment !== undefined) {
249
280
  this.#deployment = data.deployment;
250
281
  delete data.deployment;
251
282
  }
252
-
253
283
  if (data.extends !== undefined) {
254
284
  this.#extends = data.extends;
255
285
  delete data.extends;
@@ -281,13 +311,13 @@ export class Host extends Base {
281
311
 
282
312
  Object.assign(this, { services: {}, networkInterfaces: {} }, data);
283
313
 
284
- this.location?.addHost(this);
314
+ owner.addHost(this);
285
315
 
286
316
  for (const [name, iface] of Object.entries(this.networkInterfaces)) {
287
317
  iface.host = this;
288
318
  iface.name = name;
289
319
  if (iface.network) {
290
- iface.network = this.location?.network(iface.network);
320
+ iface.network = this.network(iface.network);
291
321
  }
292
322
  }
293
323
 
@@ -307,6 +337,10 @@ export class Host extends Base {
307
337
  return this.#extends.map(e => this.expand(e));
308
338
  }
309
339
 
340
+ get location() {
341
+ return this.#location || super.location;
342
+ }
343
+
310
344
  get provides() {
311
345
  let provides = new Set(this.#provides);
312
346
  this.extends.forEach(h => (provides = provides.union(h.provides)));
@@ -0,0 +1,9 @@
1
+ export function prepare(): {
2
+ world: World;
3
+ options: {
4
+ world: string;
5
+ output: string;
6
+ };
7
+ args: string[];
8
+ };
9
+ import { World } from "./model.mjs";
package/types/model.d.mts CHANGED
@@ -11,8 +11,10 @@ export class Base {
11
11
  name: any;
12
12
  description: any;
13
13
  get typeName(): any;
14
+ get world(): any;
15
+ get location(): any;
14
16
  get host(): any;
15
- get network(): any;
17
+ network(name: any): any;
16
18
  set directory(directory: any);
17
19
  get directory(): any;
18
20
  expand(object: any): any;
@@ -23,11 +25,12 @@ export class Base {
23
25
  }
24
26
  export class World {
25
27
  static get types(): {
26
- [k: string]: typeof Host | typeof Network | typeof Location | typeof Subnet | typeof Service;
28
+ [k: string]: typeof Location | typeof Host | typeof Network | typeof Subnet | typeof Service;
27
29
  };
28
30
  constructor(directory: any);
29
31
  directory: any;
30
32
  get name(): string;
33
+ get world(): this;
31
34
  _loadType(name: any, type: any): Promise<any>;
32
35
  load(): Promise<void>;
33
36
  named(name: any): Promise<any>;
@@ -36,6 +39,8 @@ export class World {
36
39
  domains(): AsyncGenerator<any, void, unknown>;
37
40
  location(name: any): Promise<any>;
38
41
  host(name: any): Promise<any>;
42
+ addHost(host: any): void;
43
+ network(name: any): void;
39
44
  subnets(): AsyncGenerator<any, void, unknown>;
40
45
  networkAddresses(): AsyncGenerator<{
41
46
  address: any;
@@ -48,7 +53,6 @@ export class Host extends Base {
48
53
  networkInterfaces: {};
49
54
  services: {};
50
55
  postinstall: any[];
51
- location: any;
52
56
  get deployment(): any;
53
57
  get extends(): any[];
54
58
  get provides(): Set<any>;
@@ -84,7 +88,6 @@ export class Location extends Base {
84
88
  hosts(): AsyncGenerator<any, void, unknown>;
85
89
  service(filter: any): Promise<any>;
86
90
  services(filter: any): AsyncGenerator<any, void, unknown>;
87
- network(name: any): any;
88
91
  networkAddresses(): AsyncGenerator<any, void, unknown>;
89
92
  networks(): AsyncGenerator<any, void, unknown>;
90
93
  subnets(): AsyncGenerator<any, void, unknown>;