@ydkn/pulumi-components 0.8.8 → 0.9.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/index.d.ts +5 -1
- package/index.js +5 -1
- package/index.js.map +1 -1
- package/lib/alpine/config.d.ts +19 -0
- package/lib/alpine/config.js +195 -0
- package/lib/alpine/config.js.map +1 -0
- package/lib/alpine/deployment.js +2 -2
- package/lib/alpine/deployment.js.map +1 -1
- package/lib/alpine/host.d.ts +25 -0
- package/lib/alpine/host.js +98 -0
- package/lib/alpine/host.js.map +1 -0
- package/lib/alpine/index.d.ts +3 -1
- package/lib/alpine/index.js +3 -1
- package/lib/alpine/index.js.map +1 -1
- package/lib/avahi/deployment.d.ts +2 -0
- package/lib/avahi/deployment.js +44 -20
- package/lib/avahi/deployment.js.map +1 -1
- package/lib/avahi/service.d.ts +2 -2
- package/lib/avahi/service.js +9 -7
- package/lib/avahi/service.js.map +1 -1
- package/lib/certManager/certificate.js +1 -1
- package/lib/certManager/certificate.js.map +1 -1
- package/lib/certManager/issuer.d.ts +1 -1
- package/lib/certManager/operator.js +8 -8
- package/lib/certManager/operator.js.map +1 -1
- package/lib/cups/avahiService.d.ts +1 -1
- package/lib/cups/avahiService.js +1 -1
- package/lib/cups/avahiService.js.map +1 -1
- package/lib/cups/deployment.d.ts +1 -1
- package/lib/cups/deployment.js +3 -3
- package/lib/cups/deployment.js.map +1 -1
- package/lib/dashy/deployment.d.ts +35 -0
- package/lib/dashy/deployment.js +78 -0
- package/lib/dashy/deployment.js.map +1 -0
- package/lib/dashy/index.d.ts +2 -0
- package/lib/dashy/index.js +3 -0
- package/lib/dashy/index.js.map +1 -0
- package/lib/dhcpd/deployment.d.ts +6 -6
- package/lib/dhcpd/deployment.js +40 -30
- package/lib/dhcpd/deployment.js.map +1 -1
- package/lib/externalDns/operator.d.ts +2 -2
- package/lib/externalDns/operator.js +5 -16
- package/lib/externalDns/operator.js.map +1 -1
- package/lib/fcos/assets/install-ready.service +12 -0
- package/lib/fcos/assets/install-run.service +14 -0
- package/lib/fcos/config.d.ts +2 -5
- package/lib/fcos/config.js +44 -34
- package/lib/fcos/config.js.map +1 -1
- package/lib/fcos/host.d.ts +8 -12
- package/lib/fcos/host.js +45 -39
- package/lib/fcos/host.js.map +1 -1
- package/lib/fcos/index.d.ts +3 -3
- package/lib/fcos/index.js.map +1 -1
- package/lib/flatcar/assets/install-ready.service +12 -0
- package/lib/flatcar/assets/install-run.service +14 -0
- package/lib/flatcar/config.d.ts +3 -5
- package/lib/flatcar/config.js +44 -42
- package/lib/flatcar/config.js.map +1 -1
- package/lib/flatcar/host.d.ts +8 -12
- package/lib/flatcar/host.js +39 -29
- package/lib/flatcar/host.js.map +1 -1
- package/lib/flatcar/index.d.ts +3 -3
- package/lib/flatcar/index.js.map +1 -1
- package/lib/freeradius/deployment.js +1 -1
- package/lib/gitlab/project.js +4 -4
- package/lib/gitlab/project.js.map +1 -1
- package/lib/grafana/alloy.d.ts +1 -1
- package/lib/grafana/alloy.js +11 -12
- package/lib/grafana/alloy.js.map +1 -1
- package/lib/grafana/deployment.js +2 -2
- package/lib/grafana/deployment.js.map +1 -1
- package/lib/hcloud/assets/alpine-install.sh +45 -0
- package/lib/hcloud/assets/fcos-install.sh +13 -6
- package/lib/hcloud/assets/flatcar-install.sh +2 -2
- package/lib/hcloud/cluster.d.ts +9 -2
- package/lib/hcloud/cluster.js +273 -117
- package/lib/hcloud/cluster.js.map +1 -1
- package/lib/homeAssistant/deployment.d.ts +38 -0
- package/lib/homeAssistant/deployment.js +183 -0
- package/lib/homeAssistant/deployment.js.map +1 -0
- package/lib/homeAssistant/index.d.ts +2 -0
- package/lib/homeAssistant/index.js +3 -0
- package/lib/homeAssistant/index.js.map +1 -0
- package/lib/jellyfin/deployment.d.ts +1 -1
- package/lib/jellyfin/deployment.js +2 -5
- package/lib/jellyfin/deployment.js.map +1 -1
- package/lib/k0s/cluster.js +9 -4
- package/lib/k0s/cluster.js.map +1 -1
- package/lib/kubernetes/crashedCleanup.js +19 -2
- package/lib/kubernetes/crashedCleanup.js.map +1 -1
- package/lib/kubernetes/transformations/removeCrdDescriptions.js.map +1 -1
- package/lib/kubernetes/v1/secureIngress.js.map +1 -1
- package/lib/kured/deployment.d.ts +16 -0
- package/lib/kured/deployment.js +42 -0
- package/lib/kured/deployment.js.map +1 -0
- package/lib/kured/index.d.ts +2 -0
- package/lib/kured/index.js +3 -0
- package/lib/kured/index.js.map +1 -0
- package/lib/loki/deployment.js +8 -1
- package/lib/loki/deployment.js.map +1 -1
- package/lib/metallb/controller.d.ts +3 -0
- package/lib/metallb/controller.js +2 -0
- package/lib/metallb/controller.js.map +1 -1
- package/lib/mongodb/cluster.js +1 -1
- package/lib/mongodb/cluster.js.map +1 -1
- package/lib/musicAssistant/deployment.d.ts +26 -0
- package/lib/musicAssistant/deployment.js +77 -0
- package/lib/musicAssistant/deployment.js.map +1 -0
- package/lib/musicAssistant/index.d.ts +2 -0
- package/lib/musicAssistant/index.js +3 -0
- package/lib/musicAssistant/index.js.map +1 -0
- package/lib/nats/cluster.js +14 -10
- package/lib/nats/cluster.js.map +1 -1
- package/lib/netbird/agent.d.ts +0 -4
- package/lib/netbird/agent.js +5 -38
- package/lib/netbird/agent.js.map +1 -1
- package/lib/netbird/management.d.ts +1 -0
- package/lib/netbird/management.js +18 -3
- package/lib/netbird/management.js.map +1 -1
- package/lib/node/config.d.ts +37 -0
- package/lib/node/config.js +2 -0
- package/lib/node/config.js.map +1 -0
- package/lib/node/index.d.ts +2 -2
- package/lib/node/index.js.map +1 -1
- package/lib/node/node.d.ts +1 -1
- package/lib/plex/mediaServer.d.ts +1 -1
- package/lib/plex/mediaServer.js +4 -4
- package/lib/plex/mediaServer.js.map +1 -1
- package/lib/postgresql/cluster.js +1 -1
- package/lib/postgresql/cluster.js.map +1 -1
- package/lib/raspberrypi/cluster.d.ts +5 -2
- package/lib/raspberrypi/cluster.js +128 -76
- package/lib/raspberrypi/cluster.js.map +1 -1
- package/lib/redis/standalone.js +2 -2
- package/lib/rook/blockPool.js +1 -0
- package/lib/rook/blockPool.js.map +1 -1
- package/lib/rook/cluster.d.ts +0 -2
- package/lib/rook/cluster.js +10 -35
- package/lib/rook/cluster.js.map +1 -1
- package/lib/rook/filesystem.js +2 -1
- package/lib/rook/filesystem.js.map +1 -1
- package/lib/rook/operator.d.ts +8 -0
- package/lib/rook/operator.js +128 -122
- package/lib/rook/operator.js.map +1 -1
- package/lib/rook/sharedFilesystem.js +1 -0
- package/lib/rook/sharedFilesystem.js.map +1 -1
- package/lib/samba/avahiService.d.ts +1 -1
- package/lib/samba/avahiService.js +1 -1
- package/lib/samba/avahiService.js.map +1 -1
- package/lib/samba/dc.js +27 -1
- package/lib/samba/dc.js.map +1 -1
- package/lib/samba/deployment.d.ts +2 -1
- package/lib/samba/deployment.js +5 -6
- package/lib/samba/deployment.js.map +1 -1
- package/lib/torproxy/deployment.js +2 -3
- package/lib/torproxy/deployment.js.map +1 -1
- package/lib/traefik/controller.d.ts +12 -0
- package/lib/traefik/controller.js +37 -4
- package/lib/traefik/controller.js.map +1 -1
- package/lib/transmission/deployment.d.ts +5 -3
- package/lib/transmission/deployment.js +27 -11
- package/lib/transmission/deployment.js.map +1 -1
- package/lib/ubuntu/deployment.js +2 -2
- package/lib/ubuntu/deployment.js.map +1 -1
- package/lib/unifi/index.d.ts +2 -2
- package/lib/unifi/index.js +2 -2
- package/lib/unifi/index.js.map +1 -1
- package/lib/unifi/{networkServer.d.ts → osServer.d.ts} +7 -16
- package/lib/unifi/{networkServer.js → osServer.js} +86 -139
- package/lib/unifi/osServer.js.map +1 -0
- package/lib/utils/args.js +1 -1
- package/lib/utils/args.js.map +1 -1
- package/lib/velero/operator.d.ts +2 -2
- package/lib/velero/operator.js +6 -6
- package/lib/velero/operator.js.map +1 -1
- package/lib/wireguard/deployment.js +1 -1
- package/lib/zitadel/deployment.js +1 -1
- package/lib/zitadel/deployment.js.map +1 -1
- package/package.json +28 -24
- package/lib/netbird/assets/nftables.sh +0 -44
- package/lib/unifi/assets/init-mongo.sh +0 -19
- package/lib/unifi/networkServer.js.map +0 -1
|
@@ -3,8 +3,8 @@
|
|
|
3
3
|
DRIVE="${1}"
|
|
4
4
|
CONFIG="${2}"
|
|
5
5
|
|
|
6
|
-
apt-get update -y
|
|
7
|
-
apt-get install -y gawk
|
|
6
|
+
apt-get update -qq -y
|
|
7
|
+
apt-get install -qq -y gawk
|
|
8
8
|
|
|
9
9
|
curl -sf -o /tmp/flatcar-install https://raw.githubusercontent.com/flatcar/init/flatcar-master/bin/flatcar-install
|
|
10
10
|
chmod +x /tmp/flatcar-install
|
package/lib/hcloud/cluster.d.ts
CHANGED
|
@@ -4,12 +4,12 @@ import * as k8s from "@pulumi/kubernetes";
|
|
|
4
4
|
import { ComponentResource } from "../common/index.js";
|
|
5
5
|
import * as node from "../node/index.js";
|
|
6
6
|
import * as k0s from "../k0s/index.js";
|
|
7
|
-
export interface Node extends node.Node, node.
|
|
7
|
+
export interface Node extends node.Node, node.ConfigArgs {
|
|
8
8
|
serverType: pulumi.Input<string>;
|
|
9
9
|
count?: pulumi.Input<number>;
|
|
10
10
|
location?: pulumi.Input<string>;
|
|
11
11
|
}
|
|
12
|
-
export interface ClusterArgs extends k0s.ClusterArgs, node.
|
|
12
|
+
export interface ClusterArgs extends k0s.ClusterArgs, node.ConfigArgs {
|
|
13
13
|
name?: pulumi.Input<string>;
|
|
14
14
|
token: pulumi.Input<string>;
|
|
15
15
|
location: pulumi.Input<string>;
|
|
@@ -30,6 +30,8 @@ export declare class Cluster extends ComponentResource {
|
|
|
30
30
|
private static readonly dnsServers;
|
|
31
31
|
private static readonly gatewayIPv6;
|
|
32
32
|
private static readonly ignitionConfigPathRemote;
|
|
33
|
+
private static readonly cloudInitMetaDataPathRemote;
|
|
34
|
+
private static readonly cloudInitUserDataPathRemote;
|
|
33
35
|
private static readonly installScriptPathRemote;
|
|
34
36
|
private readonly sshKey;
|
|
35
37
|
private readonly network;
|
|
@@ -58,8 +60,13 @@ export declare class Cluster extends ComponentResource {
|
|
|
58
60
|
*/
|
|
59
61
|
constructor(name: string, args: ClusterArgs, opts?: pulumi.ComponentResourceOptions);
|
|
60
62
|
private createServers;
|
|
63
|
+
private mergeNodeArgs;
|
|
64
|
+
private networkManagerConfigFiles;
|
|
65
|
+
private networkdConfigFiles;
|
|
66
|
+
private interfacesConfigFiles;
|
|
61
67
|
private configureFcosNode;
|
|
62
68
|
private configureFlatcarNode;
|
|
69
|
+
private configureAlpineNode;
|
|
63
70
|
private fileAssetFromString;
|
|
64
71
|
private static ethernetInterfaceName;
|
|
65
72
|
}
|
package/lib/hcloud/cluster.js
CHANGED
|
@@ -11,6 +11,7 @@ import * as crypto from "crypto";
|
|
|
11
11
|
import { ComponentResource } from "../common/index.js";
|
|
12
12
|
import * as fcos from "../fcos/index.js";
|
|
13
13
|
import * as flatcar from "../flatcar/index.js";
|
|
14
|
+
import * as alpine from "../alpine/index.js";
|
|
14
15
|
import * as k0s from "../k0s/index.js";
|
|
15
16
|
import { Kubernetes } from "./kubernetes.js";
|
|
16
17
|
export class Cluster extends ComponentResource {
|
|
@@ -27,10 +28,15 @@ export class Cluster extends ComponentResource {
|
|
|
27
28
|
flatcar: {
|
|
28
29
|
DEFAULT: { primary: "eth0", private: [1, 2].map((i) => `eth${i}`) },
|
|
29
30
|
},
|
|
31
|
+
alpine: {
|
|
32
|
+
DEFAULT: { primary: "eth0", private: [1, 2].map((i) => `eth${i}`) },
|
|
33
|
+
},
|
|
30
34
|
};
|
|
31
|
-
static dnsServers = ["2a01:4ff:ff00::add:1", "2a01:4ff:ff00::add:2"];
|
|
35
|
+
static dnsServers = ["185.12.64.1", "185.12.64.2"]; // ["2a01:4ff:ff00::add:1", "2a01:4ff:ff00::add:2"];
|
|
32
36
|
static gatewayIPv6 = "fe80::1";
|
|
33
37
|
static ignitionConfigPathRemote = "/tmp/config.ign";
|
|
38
|
+
static cloudInitMetaDataPathRemote = "/tmp/meta-data";
|
|
39
|
+
static cloudInitUserDataPathRemote = "/tmp/user-data";
|
|
34
40
|
static installScriptPathRemote = "/tmp/install.sh";
|
|
35
41
|
sshKey;
|
|
36
42
|
network;
|
|
@@ -83,7 +89,7 @@ export class Cluster extends ComponentResource {
|
|
|
83
89
|
.apply(([result]) => {
|
|
84
90
|
return result.images.filter((image) => image.osFlavor === "ubuntu").sort((a, b) => (a > b ? -1 : 1))[0].name;
|
|
85
91
|
});
|
|
86
|
-
const servers = this.createServers(args.nodes, serverImage, this.sshKey, this.sshPrivateKey.privateKeyOpenssh, this.nodeSubnet, this.placementGroup, args.
|
|
92
|
+
const servers = this.createServers(args.nodes, serverImage, this.sshKey, this.sshPrivateKey.privateKeyOpenssh, this.nodeSubnet, this.placementGroup, args.packages, args.filesystems, args.users, args.files, args.run, args.sshAuthorizedKeys, args.protect);
|
|
87
93
|
this.nodes = servers.apply((servers) => servers.map((s) => s.node));
|
|
88
94
|
const nodeIPs = pulumi.all([this.nodes]).apply(([nodes]) => pulumi.all(nodes).apply((nodes) => {
|
|
89
95
|
const nodeIPs = [];
|
|
@@ -186,7 +192,7 @@ export class Cluster extends ComponentResource {
|
|
|
186
192
|
}, { ...emptyOpts, providers: [this.provider] });
|
|
187
193
|
this.registerOutputs();
|
|
188
194
|
}
|
|
189
|
-
createServers(nodes, image, sshKey, sshPrivateKey, subnet, placementGroup,
|
|
195
|
+
createServers(nodes, image, sshKey, sshPrivateKey, subnet, placementGroup, packages, filesystems, users, files, run, sshAuthorizedKeys, protect) {
|
|
190
196
|
const emptyOpts = this.opts();
|
|
191
197
|
const hcloudOpts = this.opts(hcloud.Provider);
|
|
192
198
|
return pulumi.all([nodes]).apply(([nodes]) => {
|
|
@@ -232,113 +238,21 @@ export class Cluster extends ComponentResource {
|
|
|
232
238
|
}, { ...hcloudOpts, protect }));
|
|
233
239
|
}
|
|
234
240
|
const serverNetwork = pulumi.all([server.id, server.name]).apply(([serverId, serverName]) => {
|
|
235
|
-
return new hcloud.ServerNetwork(serverName, { serverId: parseInt(serverId), subnetId: subnet.id }, hcloudOpts);
|
|
241
|
+
return new hcloud.ServerNetwork(serverName, { serverId: parseInt(serverId), subnetId: subnet.id }, { ...hcloudOpts, dependsOn: [server] });
|
|
236
242
|
});
|
|
237
243
|
const node = pulumi
|
|
238
|
-
.all([hostname,
|
|
239
|
-
.apply(([hostname,
|
|
240
|
-
const ethernetInterfaces = Cluster.ethernetInterfaceName(nodeGroup.operatingSystem, serverType);
|
|
244
|
+
.all([hostname, filesystems, files, server])
|
|
245
|
+
.apply(([hostname, filesystems, files, server]) => {
|
|
241
246
|
let host;
|
|
242
247
|
switch (nodeGroup.operatingSystem) {
|
|
243
248
|
case "fcos":
|
|
244
|
-
host = new fcos.Host(hostname,
|
|
245
|
-
hostname,
|
|
246
|
-
filesystems: dataVolume !== undefined
|
|
247
|
-
? [
|
|
248
|
-
{
|
|
249
|
-
device: pulumi.interpolate `/dev/disk/by-id/scsi-0HC_Volume_${dataVolume.id}`,
|
|
250
|
-
path: "/var/lib/k0s",
|
|
251
|
-
format: dataVolume.format.apply((format) => format ?? "ext4"),
|
|
252
|
-
},
|
|
253
|
-
]
|
|
254
|
-
: [],
|
|
255
|
-
files: pulumi.all(files ?? []).apply((files) => {
|
|
256
|
-
files.push({
|
|
257
|
-
path: `/etc/NetworkManager/system-connections/${ethernetInterfaces.primary}.nmconnection`,
|
|
258
|
-
contents: [
|
|
259
|
-
"[connection]",
|
|
260
|
-
"type=ethernet",
|
|
261
|
-
`id=${ethernetInterfaces.primary}`,
|
|
262
|
-
`interface-name=${ethernetInterfaces.primary}`,
|
|
263
|
-
"[ipv4]",
|
|
264
|
-
"method=auto",
|
|
265
|
-
"ignore-auto-dns=true",
|
|
266
|
-
"[ipv6]",
|
|
267
|
-
"method=manual",
|
|
268
|
-
`address1=${ipv6Address}`,
|
|
269
|
-
`gateway=${Cluster.gatewayIPv6}`,
|
|
270
|
-
`dns=${Cluster.dnsServers.join(";")}`,
|
|
271
|
-
].join("\n"),
|
|
272
|
-
mode: 0o600,
|
|
273
|
-
});
|
|
274
|
-
for (const iface of ethernetInterfaces.private) {
|
|
275
|
-
files.push({
|
|
276
|
-
path: `/etc/NetworkManager/system-connections/${iface}.nmconnection`,
|
|
277
|
-
contents: [
|
|
278
|
-
"[connection]",
|
|
279
|
-
"type=ethernet",
|
|
280
|
-
`id=${iface}`,
|
|
281
|
-
`interface-name=${iface}`,
|
|
282
|
-
"[ipv4]",
|
|
283
|
-
"method=auto",
|
|
284
|
-
"never-default=true",
|
|
285
|
-
"[ipv6]",
|
|
286
|
-
"method=auto",
|
|
287
|
-
"never-default=true",
|
|
288
|
-
].join("\n"),
|
|
289
|
-
mode: 0o600,
|
|
290
|
-
});
|
|
291
|
-
}
|
|
292
|
-
return files;
|
|
293
|
-
}),
|
|
294
|
-
links,
|
|
295
|
-
systemdUnits,
|
|
296
|
-
users: [{ name: "core", sshAuthorizedKeys }],
|
|
297
|
-
sshUsers: [{ name: Cluster.sshUsername, groups: ["sudo"] }],
|
|
298
|
-
}, emptyOpts);
|
|
249
|
+
host = new fcos.Host(hostname, this.mergeNodeArgs(nodeGroup, hostname, dataVolume, packages, filesystems, users, files, run, sshAuthorizedKeys, this.networkManagerConfigFiles(nodeGroup, server)), emptyOpts);
|
|
299
250
|
break;
|
|
300
251
|
case "flatcar":
|
|
301
|
-
host = new flatcar.Host(hostname,
|
|
302
|
-
|
|
303
|
-
|
|
304
|
-
|
|
305
|
-
{
|
|
306
|
-
device: pulumi.interpolate `/dev/disk/by-id/scsi-0HC_Volume_${dataVolume.id}`,
|
|
307
|
-
path: "/var/lib/k0s",
|
|
308
|
-
format: dataVolume.format.apply((format) => format ?? "ext4"),
|
|
309
|
-
},
|
|
310
|
-
]
|
|
311
|
-
: [],
|
|
312
|
-
files: pulumi.all(files ?? []).apply((files) => {
|
|
313
|
-
files.push({
|
|
314
|
-
path: `/etc/systemd/network/10-${ethernetInterfaces.primary}.network`,
|
|
315
|
-
contents: [
|
|
316
|
-
"[Match]",
|
|
317
|
-
`Name=${ethernetInterfaces.primary}`,
|
|
318
|
-
"[Link]",
|
|
319
|
-
"RequiredForOnline=routable",
|
|
320
|
-
"[Network]",
|
|
321
|
-
"DHCP=yes",
|
|
322
|
-
`Address=${ipv6Address}/64`,
|
|
323
|
-
`Gateway=${Cluster.gatewayIPv6}`,
|
|
324
|
-
...Cluster.dnsServers.map((dns) => `DNS=${dns}`),
|
|
325
|
-
].join("\n"),
|
|
326
|
-
mode: 0o644,
|
|
327
|
-
});
|
|
328
|
-
for (const iface of ethernetInterfaces.private) {
|
|
329
|
-
files.push({
|
|
330
|
-
path: `/etc/systemd/network/10-${iface}.network`,
|
|
331
|
-
contents: ["[Match]", `Name=${iface}`, "[Network]", "DHCP=yes", "IPv6AcceptRA=true"].join("\n"),
|
|
332
|
-
mode: 0o644,
|
|
333
|
-
});
|
|
334
|
-
}
|
|
335
|
-
return files;
|
|
336
|
-
}),
|
|
337
|
-
links,
|
|
338
|
-
systemdUnits,
|
|
339
|
-
users: [{ name: "core", sshAuthorizedKeys }],
|
|
340
|
-
sshUsers: [{ name: Cluster.sshUsername, groups: ["sudo"] }],
|
|
341
|
-
}, emptyOpts);
|
|
252
|
+
host = new flatcar.Host(hostname, this.mergeNodeArgs(nodeGroup, hostname, dataVolume, packages, filesystems, users, files, run, sshAuthorizedKeys, this.networkdConfigFiles(nodeGroup, server)), emptyOpts);
|
|
253
|
+
break;
|
|
254
|
+
case "alpine":
|
|
255
|
+
host = new alpine.Host(hostname, this.mergeNodeArgs(nodeGroup, hostname, dataVolume, packages, filesystems, users, files, run, sshAuthorizedKeys, this.interfacesConfigFiles(nodeGroup, server)), emptyOpts);
|
|
342
256
|
break;
|
|
343
257
|
default:
|
|
344
258
|
throw new Error(`Unsupported operating system ${nodeGroup.operatingSystem}`);
|
|
@@ -353,17 +267,9 @@ export class Cluster extends ComponentResource {
|
|
|
353
267
|
labels: nodeGroup.labels ?? {},
|
|
354
268
|
taints: nodeGroup.taints ?? [],
|
|
355
269
|
username: Cluster.sshUsername,
|
|
356
|
-
privateKey: host.
|
|
357
|
-
for (const username in sshPrivateKeys) {
|
|
358
|
-
if (username === Cluster.sshUsername) {
|
|
359
|
-
// eslint-disable-next-line security/detect-object-injection
|
|
360
|
-
return sshPrivateKeys[username].privateKeyOpenssh;
|
|
361
|
-
}
|
|
362
|
-
}
|
|
363
|
-
throw new Error(`No private key found for user ${Cluster.sshUsername}`);
|
|
364
|
-
}),
|
|
270
|
+
privateKey: host.deployPrivateKey.privateKeyOpenssh,
|
|
365
271
|
operatingSystem: nodeGroup.operatingSystem,
|
|
366
|
-
|
|
272
|
+
initConfig: host.initConfig,
|
|
367
273
|
disabled: nodeGroup.disabled ?? false,
|
|
368
274
|
};
|
|
369
275
|
});
|
|
@@ -375,7 +281,10 @@ export class Cluster extends ComponentResource {
|
|
|
375
281
|
return this.configureFcosNode(sshPrivateKey, server, node);
|
|
376
282
|
case "flatcar":
|
|
377
283
|
return this.configureFlatcarNode(sshPrivateKey, server, node);
|
|
284
|
+
case "alpine":
|
|
285
|
+
return this.configureAlpineNode(sshPrivateKey, server, node);
|
|
378
286
|
default:
|
|
287
|
+
//eslint-disable-next-line @typescript-eslint/restrict-template-expressions
|
|
379
288
|
throw new Error(`Unsupported operating system ${os}`);
|
|
380
289
|
}
|
|
381
290
|
}),
|
|
@@ -385,6 +294,180 @@ export class Cluster extends ComponentResource {
|
|
|
385
294
|
return results;
|
|
386
295
|
});
|
|
387
296
|
}
|
|
297
|
+
mergeNodeArgs(serverNode, hostname, dataVolume, packages, filesystems, users, files, run, sshAuthorizedKeys, additionalFiles) {
|
|
298
|
+
return {
|
|
299
|
+
hostname: pulumi.output(hostname),
|
|
300
|
+
packages: pulumi
|
|
301
|
+
.all([serverNode])
|
|
302
|
+
.apply(([serverNode]) => pulumi
|
|
303
|
+
.all([packages])
|
|
304
|
+
.apply(([packages]) => pulumi
|
|
305
|
+
.all(packages ?? [])
|
|
306
|
+
.apply((packages) => pulumi.all(serverNode.packages ?? []).apply((nodePackages) => packages.concat(nodePackages))))),
|
|
307
|
+
filesystems: pulumi.all([serverNode]).apply(([serverNode]) => pulumi.all([filesystems]).apply(([filesystems]) => pulumi.all(filesystems ?? []).apply((filesystems) => pulumi.all(serverNode.filesystems ?? []).apply((nodeFilesystems) => pulumi.all([dataVolume]).apply(([dataVolume]) => pulumi
|
|
308
|
+
.all([dataVolume ? dataVolume.id : undefined, dataVolume ? dataVolume.format : undefined])
|
|
309
|
+
.apply(([dataVolumeId, dataVolumeFormat]) => (dataVolumeId !== undefined && dataVolumeFormat !== undefined
|
|
310
|
+
? [
|
|
311
|
+
{
|
|
312
|
+
device: `/dev/disk/by-id/scsi-0HC_Volume_${dataVolumeId}`,
|
|
313
|
+
path: "/var/lib/k0s",
|
|
314
|
+
format: dataVolumeFormat ?? "ext4",
|
|
315
|
+
},
|
|
316
|
+
]
|
|
317
|
+
: [])
|
|
318
|
+
.concat(filesystems)
|
|
319
|
+
.concat(nodeFilesystems))))))),
|
|
320
|
+
users: pulumi.all([serverNode]).apply(([serverNode]) => pulumi.all([users]).apply(([users]) => pulumi.all(users ?? []).apply((users) => pulumi.all(serverNode.users ?? []).apply((nodeUsers) => {
|
|
321
|
+
const allUsers = [];
|
|
322
|
+
for (const user of users ?? []) {
|
|
323
|
+
for (const [i, u] of (allUsers ?? []).entries()) {
|
|
324
|
+
if (user.name === u.name) {
|
|
325
|
+
allUsers[i] = { ...u, ...user }; // eslint-disable-line security/detect-object-injection
|
|
326
|
+
break;
|
|
327
|
+
}
|
|
328
|
+
}
|
|
329
|
+
}
|
|
330
|
+
for (const user of nodeUsers ?? []) {
|
|
331
|
+
for (const [i, u] of (allUsers ?? []).entries()) {
|
|
332
|
+
if (user.name === u.name) {
|
|
333
|
+
allUsers[i] = { ...u, ...user }; // eslint-disable-line security/detect-object-injection
|
|
334
|
+
break;
|
|
335
|
+
}
|
|
336
|
+
}
|
|
337
|
+
}
|
|
338
|
+
return allUsers;
|
|
339
|
+
})))),
|
|
340
|
+
files: pulumi.all([serverNode, hostname]).apply(([serverNode, hostname]) => pulumi.all([files]).apply(([files]) => pulumi.all(files ?? []).apply((files) => pulumi.all([additionalFiles]).apply(([additionalFiles]) => pulumi.all(additionalFiles ?? []).apply((additionalFiles) => pulumi.all(serverNode.files ?? []).apply((nodeFiles) => files
|
|
341
|
+
.concat(additionalFiles)
|
|
342
|
+
.concat(nodeFiles)
|
|
343
|
+
.concat([
|
|
344
|
+
{
|
|
345
|
+
path: "/var/lib/calico/nodename",
|
|
346
|
+
user: "root",
|
|
347
|
+
group: "root",
|
|
348
|
+
mode: 0o644,
|
|
349
|
+
contents: hostname,
|
|
350
|
+
},
|
|
351
|
+
]))))))),
|
|
352
|
+
run: pulumi
|
|
353
|
+
.all([serverNode])
|
|
354
|
+
.apply(([serverNode]) => pulumi
|
|
355
|
+
.all([run])
|
|
356
|
+
.apply(([run]) => pulumi
|
|
357
|
+
.all(run ?? [])
|
|
358
|
+
.apply((run) => pulumi.all(serverNode.run ?? []).apply((nodeRun) => run.concat(nodeRun))))),
|
|
359
|
+
sshAuthorizedKeys,
|
|
360
|
+
};
|
|
361
|
+
}
|
|
362
|
+
networkManagerConfigFiles(nodeGroup, server) {
|
|
363
|
+
return pulumi
|
|
364
|
+
.all([nodeGroup.operatingSystem, server.serverType, server.ipv6Address])
|
|
365
|
+
.apply(([os, serverType, ipv6Address]) => {
|
|
366
|
+
const configs = [];
|
|
367
|
+
const ethernetInterfaces = Cluster.ethernetInterfaceName(os, serverType);
|
|
368
|
+
configs.push({
|
|
369
|
+
path: `/etc/NetworkManager/system-connections/${ethernetInterfaces.primary}.nmconnection`,
|
|
370
|
+
contents: [
|
|
371
|
+
"[connection]",
|
|
372
|
+
"type=ethernet",
|
|
373
|
+
`id=${ethernetInterfaces.primary}`,
|
|
374
|
+
`interface-name=${ethernetInterfaces.primary}`,
|
|
375
|
+
"[ipv4]",
|
|
376
|
+
"method=auto",
|
|
377
|
+
"ignore-auto-dns=true",
|
|
378
|
+
"[ipv6]",
|
|
379
|
+
"method=manual",
|
|
380
|
+
`address1=${ipv6Address}`,
|
|
381
|
+
`gateway=${Cluster.gatewayIPv6}`,
|
|
382
|
+
`dns=${Cluster.dnsServers.join(";")}`,
|
|
383
|
+
].join("\n"),
|
|
384
|
+
mode: 0o600,
|
|
385
|
+
});
|
|
386
|
+
for (const iface of ethernetInterfaces.private) {
|
|
387
|
+
configs.push({
|
|
388
|
+
path: `/etc/NetworkManager/system-connections/${iface}.nmconnection`,
|
|
389
|
+
contents: [
|
|
390
|
+
"[connection]",
|
|
391
|
+
"type=ethernet",
|
|
392
|
+
`id=${iface}`,
|
|
393
|
+
`interface-name=${iface}`,
|
|
394
|
+
"[ipv4]",
|
|
395
|
+
"method=auto",
|
|
396
|
+
"never-default=true",
|
|
397
|
+
"[ipv6]",
|
|
398
|
+
"method=auto",
|
|
399
|
+
"never-default=true",
|
|
400
|
+
].join("\n"),
|
|
401
|
+
mode: 0o600,
|
|
402
|
+
});
|
|
403
|
+
}
|
|
404
|
+
return configs;
|
|
405
|
+
});
|
|
406
|
+
}
|
|
407
|
+
networkdConfigFiles(nodeGroup, server) {
|
|
408
|
+
return pulumi
|
|
409
|
+
.all([nodeGroup.operatingSystem, server.serverType, server.ipv6Address])
|
|
410
|
+
.apply(([os, serverType, ipv6Address]) => {
|
|
411
|
+
const configs = [];
|
|
412
|
+
const ethernetInterfaces = Cluster.ethernetInterfaceName(os, serverType);
|
|
413
|
+
configs.push({
|
|
414
|
+
path: `/etc/systemd/network/10-${ethernetInterfaces.primary}.network`,
|
|
415
|
+
contents: [
|
|
416
|
+
"[Match]",
|
|
417
|
+
`Name=${ethernetInterfaces.primary}`,
|
|
418
|
+
"[Link]",
|
|
419
|
+
"RequiredForOnline=routable",
|
|
420
|
+
"[Network]",
|
|
421
|
+
"DHCP=yes",
|
|
422
|
+
`Address=${ipv6Address}/64`,
|
|
423
|
+
`Gateway=${Cluster.gatewayIPv6}`,
|
|
424
|
+
...Cluster.dnsServers.map((dns) => `DNS=${dns}`),
|
|
425
|
+
].join("\n"),
|
|
426
|
+
mode: 0o644,
|
|
427
|
+
});
|
|
428
|
+
for (const iface of ethernetInterfaces.private) {
|
|
429
|
+
configs.push({
|
|
430
|
+
path: `/etc/systemd/network/10-${iface}.network`,
|
|
431
|
+
contents: ["[Match]", `Name=${iface}`, "[Network]", "DHCP=yes", "IPv6AcceptRA=true"].join("\n"),
|
|
432
|
+
mode: 0o644,
|
|
433
|
+
});
|
|
434
|
+
}
|
|
435
|
+
return configs;
|
|
436
|
+
});
|
|
437
|
+
}
|
|
438
|
+
interfacesConfigFiles(nodeGroup, server) {
|
|
439
|
+
return pulumi
|
|
440
|
+
.all([nodeGroup.operatingSystem, server.name, server.serverType, server.ipv6Address])
|
|
441
|
+
.apply(([os, name, serverType, ipv6Address]) => {
|
|
442
|
+
const ethernetInterfaces = Cluster.ethernetInterfaceName(os, serverType);
|
|
443
|
+
return [
|
|
444
|
+
{
|
|
445
|
+
path: "/etc/network/interfaces",
|
|
446
|
+
contents: [
|
|
447
|
+
"auto lo",
|
|
448
|
+
"iface lo inet loopback",
|
|
449
|
+
"",
|
|
450
|
+
`auto ${ethernetInterfaces.primary}`,
|
|
451
|
+
`iface ${ethernetInterfaces.primary} inet dhcp`,
|
|
452
|
+
"",
|
|
453
|
+
`iface ${ethernetInterfaces.primary} inet6 static`,
|
|
454
|
+
`address ${ipv6Address}`,
|
|
455
|
+
"netmask 64",
|
|
456
|
+
`gateway ${Cluster.gatewayIPv6}`,
|
|
457
|
+
`post-up sh -c "echo -n '' > /etc/resolv.conf"`,
|
|
458
|
+
...Cluster.dnsServers.map((dns) => `post-up sh -c "echo 'nameserver ${dns}' >> /etc/resolv.conf"`),
|
|
459
|
+
...(ethernetInterfaces.private ?? []).map((iface) => [
|
|
460
|
+
"",
|
|
461
|
+
`auto ${iface}`,
|
|
462
|
+
`iface ${iface} inet manual`,
|
|
463
|
+
`post-up /sbin/udhcpc -b -R -p /var/run/udhcpc.${iface}.pid -o -O 1 -i ${iface} -x hostname:${name}`,
|
|
464
|
+
].join("\n")),
|
|
465
|
+
].join("\n"),
|
|
466
|
+
mode: 0o644,
|
|
467
|
+
},
|
|
468
|
+
];
|
|
469
|
+
});
|
|
470
|
+
}
|
|
388
471
|
configureFcosNode(sshPrivateKey, server, node) {
|
|
389
472
|
const emptyOpts = this.opts();
|
|
390
473
|
return pulumi.all([server.name, server.ipv4Address, node]).apply(([nodeName, ipv4Address, node]) => {
|
|
@@ -402,7 +485,8 @@ export class Cluster extends ComponentResource {
|
|
|
402
485
|
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
403
486
|
const fcosConfigFile = new command.remote.CopyToRemote(`${nodeName}-fcos-config`, {
|
|
404
487
|
connection,
|
|
405
|
-
|
|
488
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
489
|
+
source: this.fileAssetFromString(node.initConfig),
|
|
406
490
|
remotePath: Cluster.ignitionConfigPathRemote,
|
|
407
491
|
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
408
492
|
const fcosInstall = new command.remote.Command(`${nodeName}-fcos-install`, {
|
|
@@ -411,6 +495,7 @@ export class Cluster extends ComponentResource {
|
|
|
411
495
|
`chmod +x ${Cluster.installScriptPathRemote}`,
|
|
412
496
|
`${Cluster.installScriptPathRemote} /dev/sda ${Cluster.ignitionConfigPathRemote}`,
|
|
413
497
|
].join(" && "),
|
|
498
|
+
addPreviousOutputInEnv: false,
|
|
414
499
|
}, { ...emptyOpts, dependsOn: [fcosInstallScript, fcosConfigFile], ignoreChanges: ["connection", "create"] });
|
|
415
500
|
return new command.remote.Command(`${nodeName}-fcos-up`, {
|
|
416
501
|
connection: {
|
|
@@ -420,7 +505,8 @@ export class Cluster extends ComponentResource {
|
|
|
420
505
|
perDialTimeout: 10,
|
|
421
506
|
dialErrorLimit: 30,
|
|
422
507
|
},
|
|
423
|
-
create: "echo
|
|
508
|
+
create: "until test -f /tmp/install-ready; do echo 'Waiting for install to finish...'; sleep 2; done",
|
|
509
|
+
addPreviousOutputInEnv: false,
|
|
424
510
|
}, { ...emptyOpts, dependsOn: fcosInstall, ignoreChanges: ["connection", "create"] });
|
|
425
511
|
});
|
|
426
512
|
}
|
|
@@ -441,7 +527,8 @@ export class Cluster extends ComponentResource {
|
|
|
441
527
|
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
442
528
|
const flatcarConfigFile = new command.remote.CopyToRemote(`${nodeName}-flatcar-config`, {
|
|
443
529
|
connection,
|
|
444
|
-
|
|
530
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument
|
|
531
|
+
source: this.fileAssetFromString(node.initConfig),
|
|
445
532
|
remotePath: Cluster.ignitionConfigPathRemote,
|
|
446
533
|
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
447
534
|
const flatcarInstall = new command.remote.Command(`${nodeName}-flatcar-install`, {
|
|
@@ -450,6 +537,7 @@ export class Cluster extends ComponentResource {
|
|
|
450
537
|
`chmod +x ${Cluster.installScriptPathRemote}`,
|
|
451
538
|
`${Cluster.installScriptPathRemote} /dev/sda ${Cluster.ignitionConfigPathRemote}`,
|
|
452
539
|
].join(" && "),
|
|
540
|
+
addPreviousOutputInEnv: false,
|
|
453
541
|
}, { ...emptyOpts, dependsOn: [flatcarInstallScript, flatcarConfigFile], ignoreChanges: ["connection", "create"] });
|
|
454
542
|
return new command.remote.Command(`${nodeName}-flatcar-up`, {
|
|
455
543
|
connection: {
|
|
@@ -459,10 +547,68 @@ export class Cluster extends ComponentResource {
|
|
|
459
547
|
perDialTimeout: 10,
|
|
460
548
|
dialErrorLimit: 30,
|
|
461
549
|
},
|
|
462
|
-
create: "echo
|
|
550
|
+
create: "until test -f /tmp/install-ready; do echo 'Waiting for install to finish...'; sleep 2; done",
|
|
551
|
+
addPreviousOutputInEnv: false,
|
|
463
552
|
}, { ...emptyOpts, dependsOn: flatcarInstall, ignoreChanges: ["connection", "create"] });
|
|
464
553
|
});
|
|
465
554
|
}
|
|
555
|
+
configureAlpineNode(sshPrivateKey, server, node) {
|
|
556
|
+
const emptyOpts = this.opts();
|
|
557
|
+
return pulumi.all([server.name, server.ipv4Address, node]).apply(([nodeName, ipv4Address, node]) => {
|
|
558
|
+
const connection = {
|
|
559
|
+
host: ipv4Address,
|
|
560
|
+
privateKey: sshPrivateKey,
|
|
561
|
+
user: Cluster.rescueSshUsername,
|
|
562
|
+
perDialTimeout: 10,
|
|
563
|
+
dialErrorLimit: 30,
|
|
564
|
+
};
|
|
565
|
+
const installScript = new command.remote.CopyToRemote(`${nodeName}-alpine-install-script`, {
|
|
566
|
+
connection,
|
|
567
|
+
source: new pulumi.asset.FileAsset(path.join(path.dirname(url.fileURLToPath(import.meta.url)), "assets", "alpine-install.sh")),
|
|
568
|
+
remotePath: Cluster.installScriptPathRemote,
|
|
569
|
+
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
570
|
+
const metaDataFile = new command.remote.CopyToRemote(`${nodeName}-alpine-meta-data`, {
|
|
571
|
+
connection,
|
|
572
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access
|
|
573
|
+
source: this.fileAssetFromString(node.initConfig.metaData),
|
|
574
|
+
remotePath: Cluster.cloudInitMetaDataPathRemote,
|
|
575
|
+
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
576
|
+
const userDataFile = new command.remote.CopyToRemote(`${nodeName}-alpine-user-data`, {
|
|
577
|
+
connection,
|
|
578
|
+
// eslint-disable-next-line @typescript-eslint/no-unsafe-argument,@typescript-eslint/no-unsafe-member-access
|
|
579
|
+
source: this.fileAssetFromString(node.initConfig.userData),
|
|
580
|
+
remotePath: Cluster.cloudInitUserDataPathRemote,
|
|
581
|
+
}, { ...emptyOpts, dependsOn: server, ignoreChanges: ["connection", "source", "remotePath"] });
|
|
582
|
+
const installCommand = new command.remote.Command(`${nodeName}-alpine-install`, {
|
|
583
|
+
connection,
|
|
584
|
+
create: [
|
|
585
|
+
`chmod +x ${Cluster.installScriptPathRemote}`,
|
|
586
|
+
[
|
|
587
|
+
Cluster.installScriptPathRemote,
|
|
588
|
+
"/dev/sda",
|
|
589
|
+
Cluster.cloudInitMetaDataPathRemote,
|
|
590
|
+
Cluster.cloudInitUserDataPathRemote,
|
|
591
|
+
].join(" "),
|
|
592
|
+
].join(" && "),
|
|
593
|
+
addPreviousOutputInEnv: false,
|
|
594
|
+
}, {
|
|
595
|
+
...emptyOpts,
|
|
596
|
+
dependsOn: [installScript, metaDataFile, userDataFile],
|
|
597
|
+
ignoreChanges: ["connection", "create"],
|
|
598
|
+
});
|
|
599
|
+
return new command.remote.Command(`${nodeName}-alpine-up`, {
|
|
600
|
+
connection: {
|
|
601
|
+
host: ipv4Address,
|
|
602
|
+
privateKey: node.privateKey,
|
|
603
|
+
user: Cluster.sshUsername,
|
|
604
|
+
perDialTimeout: 10,
|
|
605
|
+
dialErrorLimit: 30,
|
|
606
|
+
},
|
|
607
|
+
create: "until test -f /tmp/install-ready; do echo 'Waiting for install to finish...'; sleep 2; done",
|
|
608
|
+
addPreviousOutputInEnv: false,
|
|
609
|
+
}, { ...emptyOpts, dependsOn: installCommand, ignoreChanges: ["connection", "create"] });
|
|
610
|
+
});
|
|
611
|
+
}
|
|
466
612
|
fileAssetFromString(content) {
|
|
467
613
|
return pulumi.all([content]).apply(([content]) => {
|
|
468
614
|
const filename = `/tmp/${crypto.createHash("sha1").update(content).digest("hex")}`;
|
|
@@ -495,6 +641,16 @@ export class Cluster extends ComponentResource {
|
|
|
495
641
|
}
|
|
496
642
|
}
|
|
497
643
|
return { primary: primaryInterface, private: privateInterfaces };
|
|
644
|
+
case "alpine":
|
|
645
|
+
primaryInterface = Cluster.interfacesMap.alpine.DEFAULT.primary;
|
|
646
|
+
privateInterfaces = Cluster.interfacesMap.alpine.DEFAULT.private;
|
|
647
|
+
for (const [pattern, iface] of Object.entries(Cluster.interfacesMap.alpine)) {
|
|
648
|
+
if (RegExp(pattern).exec(serverType)) {
|
|
649
|
+
primaryInterface = iface.primary;
|
|
650
|
+
privateInterfaces = iface.private;
|
|
651
|
+
}
|
|
652
|
+
}
|
|
653
|
+
return { primary: primaryInterface, private: privateInterfaces };
|
|
498
654
|
default:
|
|
499
655
|
throw new Error(`Unsupported operating system ${os}`);
|
|
500
656
|
}
|