@highstate/library 0.19.1 → 0.20.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.
Files changed (65) hide show
  1. package/dist/highstate.library.msgpack +0 -0
  2. package/dist/index.js +2314 -1141
  3. package/dist/index.js.map +1 -1
  4. package/package.json +3 -3
  5. package/src/abbreviations.ts +3 -0
  6. package/src/common/access-point.ts +19 -4
  7. package/src/common/files.ts +24 -17
  8. package/src/common/server.ts +19 -6
  9. package/src/databases/etcd.ts +141 -39
  10. package/src/databases/index.ts +8 -7
  11. package/src/databases/influxdb3.ts +103 -0
  12. package/src/databases/minio.ts +157 -0
  13. package/src/databases/mongodb.ts +122 -41
  14. package/src/databases/mysql.ts +172 -0
  15. package/src/databases/postgresql.ts +133 -40
  16. package/src/databases/redis.ts +118 -44
  17. package/src/databases/s3.ts +48 -127
  18. package/src/dns.ts +11 -7
  19. package/src/index.ts +1 -1
  20. package/src/k3s.ts +7 -0
  21. package/src/k8s/apps/etcd.ts +3 -3
  22. package/src/k8s/apps/gitea.ts +1 -1
  23. package/src/k8s/apps/grafana.ts +48 -0
  24. package/src/k8s/apps/index.ts +4 -2
  25. package/src/k8s/apps/mariadb.ts +7 -38
  26. package/src/k8s/apps/matrix-stack.ts +62 -0
  27. package/src/k8s/apps/minio.ts +38 -45
  28. package/src/k8s/apps/mongodb.ts +6 -38
  29. package/src/k8s/apps/portal.ts +27 -0
  30. package/src/k8s/apps/postgresql.ts +7 -41
  31. package/src/k8s/apps/refluxdb.ts +49 -0
  32. package/src/k8s/apps/remnawave.ts +15 -2
  33. package/src/k8s/apps/shared.ts +16 -15
  34. package/src/k8s/apps/traefik.ts +5 -0
  35. package/src/k8s/apps/valkey.ts +5 -5
  36. package/src/k8s/apps/vaultwarden.ts +2 -6
  37. package/src/k8s/apps/workload.ts +14 -11
  38. package/src/k8s/cert-manager.ts +22 -0
  39. package/src/k8s/cilium.ts +17 -2
  40. package/src/k8s/resources.ts +41 -9
  41. package/src/k8s/service.ts +6 -2
  42. package/src/k8s/shared.ts +49 -18
  43. package/src/k8s/workload.ts +59 -43
  44. package/src/network/address-space.ts +16 -7
  45. package/src/network/address.ts +13 -2
  46. package/src/network/endpoint-container.ts +235 -0
  47. package/src/network/endpoint-schema.ts +8 -0
  48. package/src/network/endpoint.ts +20 -39
  49. package/src/network/index.ts +1 -1
  50. package/src/network/subnet.ts +4 -2
  51. package/src/proxmox.ts +24 -7
  52. package/src/restic.ts +8 -2
  53. package/src/ssh.ts +52 -30
  54. package/src/talos.ts +8 -2
  55. package/src/third-party/cloudflare.ts +4 -4
  56. package/src/third-party/timeweb.ts +17 -3
  57. package/src/third-party/yandex.ts +198 -88
  58. package/src/tls.ts +22 -0
  59. package/src/utils.ts +16 -1
  60. package/src/wireguard.ts +346 -120
  61. package/src/databases/mariadb.ts +0 -91
  62. package/src/databases/shared.ts +0 -67
  63. package/src/k8s/apps/kubernetes-dashboard.ts +0 -28
  64. package/src/k8s/apps/maybe.ts +0 -39
  65. package/src/network/dynamic-endpoint.ts +0 -43
@@ -1,11 +1,11 @@
1
- import { defineUnit, z } from "@highstate/contract"
1
+ import { defineUnit, secretSchema, z } from "@highstate/contract"
2
2
  import { providerEntity } from "../dns"
3
3
 
4
4
  export const providerDataSchema = z.object({
5
5
  /**
6
- * The zone ID of the Cloudflare zone.
6
+ * The mapping of zone names to their corresponding Cloudflare zone IDs.
7
7
  */
8
- zoneId: z.string(),
8
+ zoneIds: z.record(z.string(), z.string()),
9
9
 
10
10
  /**
11
11
  * The API token for the Cloudflare account.
@@ -17,7 +17,7 @@ export const providerDataSchema = z.object({
17
17
  * - `Zone:Read`
18
18
  * - `Zone:DNS:Edit`
19
19
  */
20
- apiToken: z.string(),
20
+ apiToken: secretSchema(z.string()),
21
21
  })
22
22
 
23
23
  /**
@@ -1,4 +1,11 @@
1
- import { defineEntity, defineUnit, type EntityInput, z } from "@highstate/contract"
1
+ import {
2
+ defineEntity,
3
+ defineUnit,
4
+ type EntityInput,
5
+ type EntityValue,
6
+ secretSchema,
7
+ z,
8
+ } from "@highstate/contract"
2
9
  import { serverOutputs, vmSecrets, vmSshArgs } from "../common"
3
10
  import * as ssh from "../ssh"
4
11
 
@@ -7,8 +14,15 @@ export const connectionEntity = defineEntity({
7
14
 
8
15
  schema: z.object({
9
16
  name: z.string(),
10
- apiToken: z.string(),
17
+ apiToken: secretSchema(z.string()),
11
18
  }),
19
+
20
+ meta: {
21
+ color: "#0078FF",
22
+ title: "Timeweb Connection",
23
+ icon: "material-symbols:cloud",
24
+ iconColor: "#0078FF",
25
+ },
12
26
  })
13
27
 
14
28
  /**
@@ -105,5 +119,5 @@ export const virtualMachine = defineUnit({
105
119
  },
106
120
  })
107
121
 
108
- export type Connection = z.infer<typeof connectionEntity.schema>
122
+ export type Connection = EntityValue<typeof connectionEntity>
109
123
  export type ConnectionInput = EntityInput<typeof connectionEntity>
@@ -1,5 +1,13 @@
1
- import { defineEntity, defineUnit, type EntityInput, z } from "@highstate/contract"
2
- import { serverOutputs, vmSecrets, vmSshArgs } from "../common"
1
+ import {
2
+ $args,
3
+ defineEntity,
4
+ defineUnit,
5
+ type EntityInput,
6
+ type EntityValue,
7
+ secretSchema,
8
+ z,
9
+ } from "@highstate/contract"
10
+ import { serverEntity, serverOutputs, vmSecrets, vmSshArgs } from "../common"
3
11
  import * as ssh from "../ssh"
4
12
 
5
13
  export const connectionEntity = defineEntity({
@@ -7,9 +15,9 @@ export const connectionEntity = defineEntity({
7
15
 
8
16
  schema: z.object({
9
17
  /**
10
- * The service account key file content (JSON).
18
+ * The JSON of the authorized key for the service account.
11
19
  */
12
- serviceAccountKeyFile: z.string().optional(),
20
+ authorizedKeyJson: secretSchema(z.string()),
13
21
 
14
22
  /**
15
23
  * The ID of the cloud.
@@ -30,10 +38,18 @@ export const connectionEntity = defineEntity({
30
38
  * The region ID.
31
39
  */
32
40
  regionId: z.string().optional(),
41
+
42
+ /**
43
+ * The ID of the service account used for authentication.
44
+ */
45
+ serviceAccountId: z.string(),
33
46
  }),
34
47
 
35
48
  meta: {
36
49
  color: "#0080ff",
50
+ title: "YC Connection",
51
+ icon: "simple-icons:yandexcloud",
52
+ iconColor: "#0080ff",
37
53
  },
38
54
  })
39
55
 
@@ -81,16 +97,16 @@ export const connection = defineUnit({
81
97
 
82
98
  secrets: {
83
99
  /**
84
- * The service account key file content (JSON).
100
+ * The JSON of the authorized key for the service account.
85
101
  *
86
102
  * Important: service account must have `iam.serviceAccounts.user` role to work properly.
87
103
  *
88
104
  * See [Creating an authorized key](https://yandex.cloud/en/docs/iam/operations/authentication/manage-authorized-keys#create-authorized-key) for details.
89
105
  */
90
- serviceAccountKeyFile: {
106
+ authorizedKeyJson: {
91
107
  schema: z.string().meta({ language: "json" }),
92
108
  meta: {
93
- title: "Service Account Key File",
109
+ title: "Authorized Key JSON",
94
110
  },
95
111
  },
96
112
  },
@@ -138,6 +154,13 @@ export const diskSchema = z.object({
138
154
  * For `network-ssd-nonreplicated` and `network-ssd-io-m3` must be multiple of 93.
139
155
  */
140
156
  size: z.number().default(20),
157
+
158
+ /**
159
+ * Whether the disk should be encrypted by separate key in KMS.
160
+ *
161
+ * If `true`, a new key will be created for the disk.
162
+ */
163
+ encrypted: z.boolean().default(true),
141
164
  })
142
165
 
143
166
  export const diskEntity = defineEntity({
@@ -210,7 +233,7 @@ export const imageEntity = defineEntity({
210
233
  }),
211
234
 
212
235
  meta: {
213
- title: "Yandex Cloud Image",
236
+ title: "YC Image",
214
237
  icon: "simple-icons:yandexcloud",
215
238
  iconColor: "#0080ff",
216
239
  secondaryIcon: "mage:compact-disk-fill",
@@ -258,6 +281,103 @@ export const existingImage = defineUnit({
258
281
  },
259
282
  })
260
283
 
284
+ export const platformIdSchema = z.enum([
285
+ // standard platforms
286
+ "standard-v1",
287
+ "standard-v2",
288
+ "standard-v3",
289
+ "amd-v1",
290
+ "standard-v4a",
291
+
292
+ // high-performance platforms
293
+ "highfreq-v3",
294
+ "highfreq-v4a",
295
+
296
+ // with gpu
297
+ "gpu-standard-v1",
298
+ "gpu-standard-v2",
299
+ "gpu-standard-v3",
300
+ "gpu-standard-v3i",
301
+ "standard-v3-t4",
302
+ "standard-v3-t4i",
303
+ "gpu-platform-v4",
304
+ ])
305
+
306
+ const vmArgs = $args({
307
+ /**
308
+ * The platform ID for the instance.
309
+ *
310
+ * See [Platforms](https://yandex.cloud/en/docs/compute/concepts/vm-platforms) for details.
311
+ */
312
+ platformId: platformIdSchema.default("standard-v3"),
313
+
314
+ /**
315
+ * The resources to allocate to the virtual machine.
316
+ */
317
+ resources: z
318
+ .object({
319
+ /**
320
+ * The number of CPU cores.
321
+ */
322
+ cores: z.number().default(2),
323
+
324
+ /**
325
+ * The amount of memory in GB.
326
+ */
327
+ memory: z.number().default(4),
328
+
329
+ /**
330
+ * The guaranteed CPU core performance (10-100).
331
+ */
332
+ coreFraction: z.number().min(10).max(100).default(100),
333
+ })
334
+ .prefault({}),
335
+
336
+ /**
337
+ * The boot disk configuration.
338
+ */
339
+ bootDisk: diskSchema.prefault({}),
340
+
341
+ /**
342
+ * The network configuration.
343
+ */
344
+ network: z
345
+ .object({
346
+ /**
347
+ * The subnet ID to connect to.
348
+ * If not specified, will auto-discover the default subnet for the zone.
349
+ */
350
+ subnetId: z.string().optional(),
351
+
352
+ /**
353
+ * Whether to assign a public IP.
354
+ */
355
+ assignPublicIp: z.boolean().default(true),
356
+
357
+ /**
358
+ * Whether to reserve the public IP permanently.
359
+ *
360
+ * If not set, the public IP can be changed when the VM is stopped and started again.
361
+ *
362
+ * Makes no sense if `assignPublicIp` is false.
363
+ */
364
+ reservePublicIp: z.boolean().default(true),
365
+ })
366
+ .prefault({}),
367
+
368
+ /**
369
+ * The SSH configuration.
370
+ */
371
+ ssh: vmSshArgs,
372
+
373
+ /**
374
+ * Whether the virtual machine is preemptible.
375
+ *
376
+ * See [Preemptible VMs](https://yandex.cloud/en/docs/compute/concepts/preemptible-vms) for details.
377
+ */
378
+ preemptible: z.boolean().default(false),
379
+ })
380
+
261
381
  /**
262
382
  * The virtual machine on Yandex Cloud.
263
383
  */
@@ -272,92 +392,77 @@ export const virtualMachine = defineUnit({
272
392
  vmName: z.string().optional(),
273
393
 
274
394
  /**
275
- * The platform ID for the instance.
276
- *
277
- * See [Platforms](https://yandex.cloud/en/docs/compute/concepts/vm-platforms) for details.
395
+ * The ID of the cloud to create the VM in.
396
+ * If not specified, will use the cloud from the connection.
278
397
  */
279
- platformId: z
280
- .enum([
281
- // standard platforms
282
- "standard-v1",
283
- "standard-v2",
284
- "standard-v3",
285
- "amd-v1",
286
- "standard-v4a",
287
-
288
- // high-performance platforms
289
- "highfreq-v3",
290
- "highfreq-v4a",
291
-
292
- // with gpu
293
- "gpu-standard-v1",
294
- "gpu-standard-v2",
295
- "gpu-standard-v3",
296
- "gpu-standard-v3i",
297
- "standard-v3-t4",
298
- "standard-v3-t4i",
299
- "gpu-platform-v4",
300
- ])
301
- .default("standard-v3"),
398
+ cloudId: z.string().optional(),
302
399
 
303
400
  /**
304
- * The resources to allocate to the virtual machine.
401
+ * The ID of the folder to create the VM in.
402
+ * If not specified, will use the default folder from the connection.
305
403
  */
306
- resources: z
307
- .object({
308
- /**
309
- * The number of CPU cores.
310
- */
311
- cores: z.number().default(2),
312
-
313
- /**
314
- * The amount of memory in GB.
315
- */
316
- memory: z.number().default(4),
317
-
318
- /**
319
- * The guaranteed CPU core performance (10-100).
320
- */
321
- coreFraction: z.number().min(10).max(100).optional(),
322
- })
323
- .prefault({}),
404
+ folderId: z.string().optional(),
405
+
406
+ ...vmArgs,
407
+ },
408
+
409
+ secrets: {
410
+ ...vmSecrets,
411
+ },
324
412
 
413
+ inputs: {
414
+ connection: connectionEntity,
415
+ image: imageEntity,
416
+ ...ssh.inputs,
417
+ },
418
+
419
+ outputs: serverOutputs,
420
+
421
+ meta: {
422
+ title: "YC Virtual Machine",
423
+ category: "Yandex Cloud",
424
+ icon: "simple-icons:yandexcloud",
425
+ iconColor: "#0080ff",
426
+ secondaryIcon: "codicon:vm",
427
+ },
428
+
429
+ source: {
430
+ package: "@highstate/yandex",
431
+ path: "virtual-machine",
432
+ },
433
+ })
434
+
435
+ /**
436
+ * The instance group on Yandex Cloud.
437
+ */
438
+ export const instanceGroup = defineUnit({
439
+ type: "yandex.instance-group.v1",
440
+
441
+ args: {
325
442
  /**
326
- * The boot disk configuration.
443
+ * The name of the instance group.
444
+ * If not specified, the name of the unit will be used.
327
445
  */
328
- bootDisk: diskSchema.prefault({}),
446
+ groupName: z.string().optional(),
329
447
 
330
448
  /**
331
- * The network configuration.
449
+ * The ID of the cloud to create the instance group in.
450
+ * If not specified, will use the cloud from the connection.
332
451
  */
333
- network: z
334
- .object({
335
- /**
336
- * The subnet ID to connect to.
337
- * If not specified, will auto-discover the default subnet for the zone.
338
- */
339
- subnetId: z.string().optional(),
340
-
341
- /**
342
- * Whether to assign a public IP.
343
- */
344
- assignPublicIp: z.boolean().default(true),
345
-
346
- /**
347
- * Whether to reserve the public IP permanently.
348
- *
349
- * If not set, the public IP can be changed when the VM is stopped and started again.
350
- *
351
- * Makes no sense if `assignPublicIp` is false.
352
- */
353
- reservePublicIp: z.boolean().default(true),
354
- })
355
- .prefault({}),
452
+ cloudId: z.string().optional(),
356
453
 
357
454
  /**
358
- * The SSH configuration.
455
+ * The ID of the folder to create the instance group in.
456
+ * If not specified, will use the default folder from the connection.
359
457
  */
360
- ssh: vmSshArgs,
458
+ folderId: z.string().optional(),
459
+
460
+ /**
461
+ * The number of instances to create in the group.
462
+ */
463
+ size: z.number().default(1),
464
+
465
+ ...vmArgs,
361
466
  },
362
467
 
363
468
  secrets: {
@@ -370,27 +475,32 @@ export const virtualMachine = defineUnit({
370
475
  ...ssh.inputs,
371
476
  },
372
477
 
373
- outputs: serverOutputs,
478
+ outputs: {
479
+ servers: {
480
+ entity: serverEntity,
481
+ multiple: true,
482
+ },
483
+ },
374
484
 
375
485
  meta: {
376
- title: "YC Virtual Machine",
486
+ title: "YC Instance Group",
377
487
  category: "Yandex Cloud",
378
488
  icon: "simple-icons:yandexcloud",
379
489
  iconColor: "#0080ff",
380
- secondaryIcon: "codicon:vm",
490
+ secondaryIcon: "mdi:group",
381
491
  },
382
492
 
383
493
  source: {
384
494
  package: "@highstate/yandex",
385
- path: "virtual-machine",
495
+ path: "instance-group",
386
496
  },
387
497
  })
388
498
 
389
- export type Connection = z.infer<typeof connectionEntity.schema>
499
+ export type Connection = EntityValue<typeof connectionEntity>
390
500
  export type ConnectionInput = EntityInput<typeof connectionEntity>
391
501
 
392
- export type Disk = z.infer<typeof diskEntity.schema>
502
+ export type Disk = EntityValue<typeof diskEntity>
393
503
  export type DiskInput = EntityInput<typeof diskEntity>
394
504
 
395
- export type Image = z.infer<typeof imageEntity.schema>
505
+ export type Image = EntityValue<typeof imageEntity>
396
506
  export type ImageInput = EntityInput<typeof imageEntity>
package/src/tls.ts ADDED
@@ -0,0 +1,22 @@
1
+ import { defineEntity, z } from "@highstate/contract"
2
+ import { fileEntity } from "./common"
3
+
4
+ export const certificateEntity = defineEntity({
5
+ type: "tls.certificate.v1",
6
+
7
+ includes: {
8
+ /**
9
+ * The file containing the certificate in PEM format.
10
+ */
11
+ file: fileEntity,
12
+ },
13
+
14
+ schema: z.unknown(),
15
+
16
+ meta: {
17
+ title: "TLS Certificate",
18
+ color: "#4caf50",
19
+ icon: "mdi:certificate",
20
+ iconColor: "#4caf50",
21
+ },
22
+ })
package/src/utils.ts CHANGED
@@ -49,10 +49,25 @@ export const booleanPatchSchema = z.enum(["keep", "true", "false"]).default("kee
49
49
  */
50
50
  export type BooleanPatch = z.infer<typeof booleanPatchSchema>
51
51
 
52
+ export type IsZodType<
53
+ TActual extends z.ZodType,
54
+ TExpected extends z.ZodType,
55
+ > = TActual extends TExpected
56
+ ? true
57
+ : TActual extends z.ZodDefault<infer TInner>
58
+ ? TInner extends TExpected
59
+ ? true
60
+ : false
61
+ : TActual extends z.ZodOptional<infer TInner>
62
+ ? TInner extends TExpected
63
+ ? true
64
+ : false
65
+ : false
66
+
52
67
  export function toPatchArgs<T extends Record<string, FullComponentArgumentOptions>>(
53
68
  args: T,
54
69
  ): {
55
- [K in keyof T]: T[K]["schema"] extends z.ZodBoolean
70
+ [K in keyof T]: IsZodType<T[K]["schema"], z.ZodBoolean> extends true
56
71
  ? Omit<T[K], "schema"> & { schema: typeof booleanPatchSchema }
57
72
  : T[K]
58
73
  } {