pmcf 6.61.4 → 6.61.6

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": "6.61.4",
3
+ "version": "6.61.6",
4
4
  "publishConfig": {
5
5
  "access": "public"
6
6
  },
@@ -55,7 +55,7 @@
55
55
  "filtered-map": "^1.0.0",
56
56
  "ip-utilties": "^3.13.1",
57
57
  "npm-pkgbuild": "^22.2.7",
58
- "pacc": "^11.17.1",
58
+ "pacc": "^11.17.2",
59
59
  "package-directory": "^8.2.0",
60
60
  "yaml": "^2.9.1"
61
61
  },
package/src/cluster.mjs CHANGED
@@ -1,14 +1,9 @@
1
- import { join } from "node:path";
2
- import { FAMILY_IPV4 } from "ip-utilties";
3
- import { duration_attribute_writable } from "pacc";
4
1
  import { host } from "./host.mjs";
5
- import { serviceEndpoints } from "./core-service.mjs";
6
2
  import { addType } from "./type.mjs";
7
3
  import {
8
4
  networkInterfaces_attribute,
9
5
  cluster_attribute
10
6
  } from "./common-attributes.mjs";
11
- import { writeLines } from "./utils.mjs";
12
7
 
13
8
  export class cluster extends host {
14
9
  static priority = 1.5;
@@ -26,11 +21,6 @@ export class cluster extends host {
26
21
  members: {
27
22
  ...networkInterfaces_attribute,
28
23
  name: "members"
29
- },
30
- checkInterval: {
31
- ...duration_attribute_writable,
32
- name: "checkInterval",
33
- default: 60
34
24
  }
35
25
  };
36
26
 
@@ -40,7 +30,6 @@ export class cluster extends host {
40
30
 
41
31
  masters = [];
42
32
  backups = [];
43
- checkInterval = 60;
44
33
 
45
34
  get members() {
46
35
  return new Set(this.masters).union(new Set(this.backups));
@@ -61,197 +50,4 @@ export class cluster extends host {
61
50
  get content() {
62
51
  return [...this.hosts.values()][0]?.content;
63
52
  }
64
-
65
- async *preparePackages(stagingDir) {
66
- for (const ni of [...this.owner.clusters.values()].reduce(
67
- (all, cluster) => all.union(cluster.members),
68
- new Set()
69
- )) {
70
- const host = ni.host;
71
-
72
- const packageStagingDir = join(stagingDir, host.name);
73
- const packageData = await host.preparePackage({ dir: packageStagingDir });
74
-
75
- const extra = [];
76
-
77
- const smtp = this.smtp;
78
-
79
- if (smtp) {
80
- extra.push(` smtp_server ${smtp.address()}`);
81
- }
82
-
83
- const cfg = [
84
- "global_defs {",
85
- " notification_email {",
86
- " " + this.administratorEmail,
87
- " }",
88
- ...extra,
89
- ` notification_email_from keepalived@${host.domainName}`,
90
- " enable_script_security",
91
- " script_user root",
92
- " max_auto_priority 20",
93
- "}",
94
- ""
95
- ];
96
-
97
- const credentials = new Map();
98
- for (const cluster of [...this.owner.clusters.values()].sort((a, b) =>
99
- a.name.localeCompare(b.name)
100
- )) {
101
- const name = cluster.name;
102
- cfg.push(`vrrp_instance ${name} {`);
103
- cfg.push(
104
- ` state ${cluster.masters.indexOf(ni) === 0 ? "MASTER" : "BACKUP"}`
105
- );
106
- cfg.push(` interface ${ni.name}`);
107
-
108
- for (const na of cluster.networkAddresses(
109
- na => na.networkInterface.kind !== "loopback"
110
- )) {
111
- cfg.push(
112
- ` ${
113
- na.family === FAMILY_IPV4
114
- ? "virtual_ipaddress"
115
- : "virtual_ipaddress_excluded"
116
- } {`
117
- );
118
- cfg.push(` ${na.cidrAddress} dev ${ni.name} label ${name}`);
119
- cfg.push(" }");
120
- }
121
-
122
- cfg.push(` virtual_router_id ${cluster.id}`);
123
-
124
- let reducedPrio = cluster.masters.indexOf(ni);
125
- if (reducedPrio < 0) {
126
- reducedPrio = cluster.backups.indexOf(ni) + 5;
127
- }
128
-
129
- const credential = name.toUpperCase() + "_PASSWORD";
130
- credentials.set(credential, name);
131
- cfg.push(` priority ${host.priority - reducedPrio}`);
132
- cfg.push(" smtp_alert");
133
- cfg.push(" advert_int 5");
134
- cfg.push(" authentication {");
135
- cfg.push(" auth_type PASS");
136
- cfg.push(" auth_pass pass1234");
137
- cfg.push(" # auth_pass ${_ENV " + credential + "}");
138
- cfg.push(" # auth_pass ${" + credential + "}");
139
- cfg.push(" }");
140
-
141
- cfg.push(
142
- ` notify_master "/usr/bin/systemctl start ${name}-master.target"`,
143
- ` notify_backup "/usr/bin/systemctl start ${name}-backup.target"`,
144
- ` notify_fault "/usr/bin/systemctl start ${name}-fault.target"`
145
- );
146
-
147
- cfg.push("}", "");
148
-
149
- for (const endpoint of serviceEndpoints(cluster, {
150
- services: "services[types[http]]",
151
- endpoints: e =>
152
- e.networkInterface && e.networkInterface.kind !== "loopback"
153
- })) {
154
- cfg.push(`virtual_server ${cluster.address} ${endpoint.port} {`);
155
- cfg.push(` delay_loop ${cluster.checkInterval}`);
156
- cfg.push(" lb_algo wlc");
157
- cfg.push(" persistence_timeout 600");
158
- cfg.push(` protocol ${endpoint.protocol.toUpperCase()}`);
159
-
160
- for (const member of this.members) {
161
- const memberService = member.expression(
162
- `services[types[${endpoint.type}]][0]`
163
- );
164
-
165
- console.log(
166
- member.fullName,
167
- endpoint.type,
168
- memberService?.fullName
169
- );
170
- cfg.push(` real_server ${member.address} ${memberService.port} {`);
171
- cfg.push(` weight ${memberService.weight}`);
172
-
173
- switch (endpoint.type) {
174
- case "dns":
175
- cfg.push(` DNS_CHECK {`);
176
- cfg.push(" type A");
177
- cfg.push(" name google.com");
178
- cfg.push(" }");
179
- break;
180
- case "smtp":
181
- cfg.push(` SMTP_CHECK {`);
182
- cfg.push(" }");
183
- break;
184
-
185
- default:
186
- switch (endpoint.protocol) {
187
- case PROTOCOL_TCP:
188
- cfg.push(` TCP_CHECK {`);
189
- cfg.push(" connect_timeout 10");
190
- cfg.push(" }");
191
- break;
192
- }
193
- }
194
-
195
- cfg.push(" }");
196
- }
197
-
198
- cfg.push("}", "");
199
- break; // only one for now
200
- }
201
- await writeLines(
202
- join(packageStagingDir, "/usr/lib/systemd/system"),
203
- `${name}-master.target`,
204
- [
205
- "[Unit]",
206
- `Description=master state of cluster ${name}`,
207
- "PartOf=keepalived.service",
208
- `Conflicts=${name}-backup.target ${name}-fault.target`
209
- ]
210
- );
211
-
212
- await writeLines(
213
- join(packageStagingDir, "/usr/lib/systemd/system"),
214
- `${name}-backup.target`,
215
- [
216
- "[Unit]",
217
- `Description=backup state of cluster ${name}`,
218
- "PartOf=keepalived.service",
219
- `Conflicts=${name}-master.target ${name}-fault.target`
220
- ]
221
- );
222
-
223
- await writeLines(
224
- join(packageStagingDir, "/usr/lib/systemd/system"),
225
- `${name}-fault.target`,
226
- [
227
- "[Unit]",
228
- `Description=fault state of cluster ${name}`,
229
- `Conflicts=${name}-master.target ${name}-backup.target`
230
- ]
231
- );
232
-
233
- await writeLines(
234
- join(packageStagingDir, "/usr/lib/systemd/system/keepalived.d"),
235
- "credentials.conf",
236
- [
237
- "[Service]",
238
- ...credentials
239
- .entries()
240
- .map(
241
- ([credName, instance]) =>
242
- `LoadCredentialEncrypted=${credName}:/etc/credstore.encrypted/keepalived.${instance}.password`
243
- )
244
- ]
245
- );
246
- }
247
-
248
- await writeLines(
249
- join(packageStagingDir, "etc/keepalived"),
250
- "keepalived.conf",
251
- cfg
252
- );
253
-
254
- yield packageData;
255
- }
256
- }
257
53
  }
@@ -70,6 +70,13 @@ export const owners_attribute = {
70
70
  backpointer: owner_attribute
71
71
  };
72
72
 
73
+ export const services_attribute = {
74
+ ...default_collection_attribute_writable,
75
+ name: "services",
76
+ type: "service",
77
+ backpointer: owner_attribute
78
+ };
79
+
73
80
  export const cluster_attribute = {
74
81
  ...default_attribute_writable,
75
82
  name: "cluster",
@@ -1,6 +1,11 @@
1
+ import { join } from "node:path";
1
2
  import { duration_attribute_writable } from "pacc";
2
3
  import { addType } from "./type.mjs";
3
4
  import { cluster } from "./cluster.mjs";
5
+ import { FAMILY_IPV4 } from "ip-utilties";
6
+ import { serviceEndpoints } from "./core-service.mjs";
7
+ import { PROTOCOL_TCP } from "./constants.mjs";
8
+ import { writeLines } from "./utils.mjs";
4
9
 
5
10
  export class keepalived extends cluster {
6
11
  static priority = 1.5;
@@ -15,4 +20,199 @@ export class keepalived extends cluster {
15
20
  static {
16
21
  addType(this);
17
22
  }
23
+
24
+ checkInterval = 60;
25
+
26
+ async *preparePackages(stagingDir) {
27
+ for (const ni of [...this.owner.clusters.values()].reduce(
28
+ (all, cluster) => all.union(cluster.members),
29
+ new Set()
30
+ )) {
31
+ const host = ni.host;
32
+
33
+ const packageStagingDir = join(stagingDir, host.name);
34
+ const packageData = await host.preparePackage({ dir: packageStagingDir });
35
+
36
+ const extra = [];
37
+
38
+ const smtp = this.smtp;
39
+
40
+ if (smtp) {
41
+ extra.push(` smtp_server ${smtp.address()}`);
42
+ }
43
+
44
+ const cfg = [
45
+ "global_defs {",
46
+ " notification_email {",
47
+ " " + this.administratorEmail,
48
+ " }",
49
+ ...extra,
50
+ ` notification_email_from keepalived@${host.domainName}`,
51
+ " enable_script_security",
52
+ " script_user root",
53
+ " max_auto_priority 20",
54
+ "}",
55
+ ""
56
+ ];
57
+
58
+ const credentials = new Map();
59
+ for (const cluster of [...this.owner.clusters.values()].sort((a, b) =>
60
+ a.name.localeCompare(b.name)
61
+ )) {
62
+ const name = cluster.name;
63
+ cfg.push(`vrrp_instance ${name} {`);
64
+ cfg.push(
65
+ ` state ${cluster.masters.indexOf(ni) === 0 ? "MASTER" : "BACKUP"}`
66
+ );
67
+ cfg.push(` interface ${ni.name}`);
68
+
69
+ for (const na of cluster.networkAddresses(
70
+ na => na.networkInterface.kind !== "loopback"
71
+ )) {
72
+ cfg.push(
73
+ ` ${
74
+ na.family === FAMILY_IPV4
75
+ ? "virtual_ipaddress"
76
+ : "virtual_ipaddress_excluded"
77
+ } {`
78
+ );
79
+ cfg.push(` ${na.cidrAddress} dev ${ni.name} label ${name}`);
80
+ cfg.push(" }");
81
+ }
82
+
83
+ cfg.push(` virtual_router_id ${cluster.id}`);
84
+
85
+ let reducedPrio = cluster.masters.indexOf(ni);
86
+ if (reducedPrio < 0) {
87
+ reducedPrio = cluster.backups.indexOf(ni) + 5;
88
+ }
89
+
90
+ const credential = name.toUpperCase() + "_PASSWORD";
91
+ credentials.set(credential, name);
92
+ cfg.push(` priority ${host.priority - reducedPrio}`);
93
+ cfg.push(" smtp_alert");
94
+ cfg.push(" advert_int 5");
95
+ cfg.push(" authentication {");
96
+ cfg.push(" auth_type PASS");
97
+ cfg.push(" auth_pass pass1234");
98
+ cfg.push(" # auth_pass ${_ENV " + credential + "}");
99
+ cfg.push(" # auth_pass ${" + credential + "}");
100
+ cfg.push(" }");
101
+
102
+ cfg.push(
103
+ ` notify_master "/usr/bin/systemctl start ${name}-master.target"`,
104
+ ` notify_backup "/usr/bin/systemctl start ${name}-backup.target"`,
105
+ ` notify_fault "/usr/bin/systemctl start ${name}-fault.target"`
106
+ );
107
+
108
+ cfg.push("}", "");
109
+
110
+ for (const endpoint of serviceEndpoints(cluster, {
111
+ services: "services[types[http]]",
112
+ endpoints: e =>
113
+ e.networkInterface && e.networkInterface.kind !== "loopback"
114
+ })) {
115
+ cfg.push(`virtual_server ${cluster.address} ${endpoint.port} {`);
116
+ cfg.push(` delay_loop ${cluster.checkInterval}`);
117
+ cfg.push(" lb_algo wlc");
118
+ cfg.push(" persistence_timeout 600");
119
+ cfg.push(` protocol ${endpoint.protocol.toUpperCase()}`);
120
+
121
+ for (const member of this.members) {
122
+ const memberService = member.expression(
123
+ `services[types[${endpoint.type}]][0]`
124
+ );
125
+
126
+ console.log(
127
+ member.fullName,
128
+ endpoint.type,
129
+ memberService?.fullName
130
+ );
131
+ cfg.push(` real_server ${member.address} ${memberService.port} {`);
132
+ cfg.push(` weight ${memberService.weight}`);
133
+
134
+ switch (endpoint.type) {
135
+ case "dns":
136
+ cfg.push(` DNS_CHECK {`);
137
+ cfg.push(" type A");
138
+ cfg.push(" name google.com");
139
+ cfg.push(" }");
140
+ break;
141
+ case "smtp":
142
+ cfg.push(` SMTP_CHECK {`);
143
+ cfg.push(" }");
144
+ break;
145
+
146
+ default:
147
+ switch (endpoint.protocol) {
148
+ case PROTOCOL_TCP:
149
+ cfg.push(` TCP_CHECK {`);
150
+ cfg.push(" connect_timeout 10");
151
+ cfg.push(" }");
152
+ break;
153
+ }
154
+ }
155
+
156
+ cfg.push(" }");
157
+ }
158
+
159
+ cfg.push("}", "");
160
+ break; // only one for now
161
+ }
162
+ await writeLines(
163
+ join(packageStagingDir, "/usr/lib/systemd/system"),
164
+ `${name}-master.target`,
165
+ [
166
+ "[Unit]",
167
+ `Description=master state of cluster ${name}`,
168
+ "PartOf=keepalived.service",
169
+ `Conflicts=${name}-backup.target ${name}-fault.target`
170
+ ]
171
+ );
172
+
173
+ await writeLines(
174
+ join(packageStagingDir, "/usr/lib/systemd/system"),
175
+ `${name}-backup.target`,
176
+ [
177
+ "[Unit]",
178
+ `Description=backup state of cluster ${name}`,
179
+ "PartOf=keepalived.service",
180
+ `Conflicts=${name}-master.target ${name}-fault.target`
181
+ ]
182
+ );
183
+
184
+ await writeLines(
185
+ join(packageStagingDir, "/usr/lib/systemd/system"),
186
+ `${name}-fault.target`,
187
+ [
188
+ "[Unit]",
189
+ `Description=fault state of cluster ${name}`,
190
+ `Conflicts=${name}-master.target ${name}-backup.target`
191
+ ]
192
+ );
193
+
194
+ await writeLines(
195
+ join(packageStagingDir, "/usr/lib/systemd/system/keepalived.d"),
196
+ "credentials.conf",
197
+ [
198
+ "[Service]",
199
+ ...credentials
200
+ .entries()
201
+ .map(
202
+ ([credName, instance]) =>
203
+ `LoadCredentialEncrypted=${credName}:/etc/credstore.encrypted/keepalived.${instance}.password`
204
+ )
205
+ ]
206
+ );
207
+ }
208
+
209
+ await writeLines(
210
+ join(packageStagingDir, "etc/keepalived"),
211
+ "keepalived.conf",
212
+ cfg
213
+ );
214
+
215
+ yield packageData;
216
+ }
217
+ }
18
218
  }
package/src/owner.mjs CHANGED
@@ -71,10 +71,6 @@ export class owner extends ServiceOwner {
71
71
  );
72
72
  }
73
73
 
74
- set hosts(value) {
75
- this._hosts = value;
76
- }
77
-
78
74
  get clusters() {
79
75
  return new FilteredMap(this.hosts, host => host.isCluster);
80
76
  }
@@ -85,10 +81,6 @@ export class owner extends ServiceOwner {
85
81
  );
86
82
  }
87
83
 
88
- set networks(value) {
89
- this._networks = value;
90
- }
91
-
92
84
  get services() {
93
85
  return new AggregatedMap(
94
86
  [this, ...this.hosts.values()].map(host => host._services)
@@ -1,18 +1,13 @@
1
- import { default_collection_attribute_writable } from "pacc";
2
- import { base, addType } from "pmcf";
3
- import { owner_attribute } from "./common-attributes.mjs";
1
+ import { base } from "./base.mjs";
2
+ import { addType } from "./type.mjs";
3
+ import { services_attribute } from "./common-attributes.mjs";
4
4
 
5
5
  export class ServiceOwner extends base {
6
6
  static name = "service-owner";
7
7
  static priority = 1.9;
8
8
  static owners = ["owner", "site", "network", "root"];
9
9
  static attributes = {
10
- services: {
11
- ...default_collection_attribute_writable,
12
- name: "services",
13
- type: "service",
14
- backpointer: owner_attribute
15
- }
10
+ services: services_attribute
16
11
  };
17
12
 
18
13
  static {
@@ -21,10 +16,6 @@ export class ServiceOwner extends base {
21
16
 
22
17
  _services = new Map();
23
18
 
24
- set services(value) {
25
- this._services = value;
26
- }
27
-
28
19
  get services() {
29
20
  return this._services;
30
21
  }
@@ -360,19 +360,19 @@ export function serviceTypes(type) {
360
360
  */
361
361
  export function serviceTypeEndpoints(type, bundeledToo) {
362
362
  if (type) {
363
- const aggregator = (acc, type) => {
364
- acc.push(...serviceTypeEndpoints(type, bundeledToo));
365
- return acc;
363
+ const aggregator = (result, type) => {
364
+ result.push(...serviceTypeEndpoints(type, bundeledToo));
365
+ return result;
366
366
  };
367
367
 
368
368
  return type.extends.reduce(
369
369
  aggregator,
370
370
  type.endpoints.reduce(
371
- (acc, ep) => {
372
- for (const family of asArray(ep.family)) {
373
- acc.push({ ...ep, family });
371
+ (result, endpoint) => {
372
+ for (const family of asArray(endpoint.family)) {
373
+ result.push({ ...endpoint, family });
374
374
  }
375
- return acc;
375
+ return result;
376
376
  },
377
377
  bundeledToo ? type.services.reduce(aggregator, []) : []
378
378
  )