@highstate/library 0.21.1 → 0.26.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/dist/highstate.library.msgpack +0 -0
- package/dist/index.js +3934 -1838
- package/package.json +3 -3
- package/src/abbreviations.ts +2 -0
- package/src/apps/index.ts +1 -0
- package/src/apps/vault.ts +374 -0
- package/src/common/access-point.ts +152 -9
- package/src/common/filter.ts +40 -0
- package/src/common/index.ts +1 -0
- package/src/common/server.ts +131 -1
- package/src/databases/etcd.ts +12 -4
- package/src/databases/index.ts +1 -0
- package/src/databases/minio.ts +19 -0
- package/src/databases/mongodb.ts +12 -4
- package/src/databases/mysql.ts +12 -4
- package/src/databases/postgresql.ts +12 -4
- package/src/databases/rustfs.ts +169 -0
- package/src/dns.ts +3 -3
- package/src/index.ts +3 -2
- package/src/k3s.ts +129 -3
- package/src/k8s/apps/envoy-gateway.ts +50 -0
- package/src/k8s/apps/etcd.ts +1 -1
- package/src/k8s/apps/grafana.ts +1 -1
- package/src/k8s/apps/index.ts +4 -0
- package/src/k8s/apps/mariadb.ts +1 -1
- package/src/k8s/apps/matrix-stack.ts +2 -1
- package/src/k8s/apps/minio.ts +2 -2
- package/src/k8s/apps/mongodb.ts +1 -1
- package/src/k8s/apps/postgresql.ts +1 -1
- package/src/k8s/apps/rustfs.ts +119 -0
- package/src/k8s/apps/shared.ts +16 -1
- package/src/k8s/apps/signoz.ts +32 -0
- package/src/k8s/apps/traefik.ts +5 -5
- package/src/k8s/apps/valkey.ts +1 -1
- package/src/k8s/apps/vault.ts +113 -0
- package/src/k8s/apps/vaultwarden.ts +31 -2
- package/src/k8s/apps/workload.ts +12 -14
- package/src/k8s/cert-manager.ts +44 -2
- package/src/k8s/cilium.ts +3 -16
- package/src/k8s/coredns.ts +62 -0
- package/src/k8s/gateway.ts +25 -0
- package/src/k8s/index.ts +1 -0
- package/src/k8s/scheduling.ts +87 -0
- package/src/k8s/service-args.ts +109 -0
- package/src/k8s/shared.ts +26 -0
- package/src/k8s/workload.ts +21 -0
- package/src/netaminity.ts +950 -0
- package/src/network/endpoint.ts +12 -1
- package/src/network/index.ts +1 -0
- package/src/network/network.ts +58 -0
- package/src/restic.ts +2 -1
- package/src/ssh.ts +27 -0
- package/src/third-party/gcp.ts +427 -0
- package/src/third-party/index.ts +1 -0
- package/src/third-party/yandex.ts +210 -1
- package/src/tls.ts +135 -6
- package/src/utils.ts +16 -1
- package/src/wireguard.ts +257 -4
package/src/k3s.ts
CHANGED
|
@@ -1,5 +1,7 @@
|
|
|
1
|
-
import { defineUnit, z } from "@highstate/contract"
|
|
1
|
+
import { defineEntity, defineUnit, type EntityValue, secretSchema, z } from "@highstate/contract"
|
|
2
|
+
import { serverEntity } from "./common"
|
|
2
3
|
import { clusterInputs, clusterOutputs } from "./k8s/shared"
|
|
4
|
+
import { l4EndpointEntity } from "./network"
|
|
3
5
|
|
|
4
6
|
export const packagedComponents = [
|
|
5
7
|
"coredns",
|
|
@@ -22,6 +24,48 @@ export const componentSchema = z.enum([...packagedComponents, ...internalCompone
|
|
|
22
24
|
|
|
23
25
|
export const cniSchema = z.enum(["none", "flannel"])
|
|
24
26
|
|
|
27
|
+
export const clusterEntity = defineEntity({
|
|
28
|
+
type: "k3s.cluster.v1",
|
|
29
|
+
|
|
30
|
+
includes: {
|
|
31
|
+
/**
|
|
32
|
+
* The API endpoint workers should use to join the cluster.
|
|
33
|
+
*
|
|
34
|
+
* This is the public endpoint when the cluster has one, otherwise the first master endpoint.
|
|
35
|
+
*/
|
|
36
|
+
bootstrapEndpoint: l4EndpointEntity,
|
|
37
|
+
},
|
|
38
|
+
|
|
39
|
+
schema: z.object({
|
|
40
|
+
/**
|
|
41
|
+
* The cluster name.
|
|
42
|
+
*/
|
|
43
|
+
name: z.string(),
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* The agent token workers should use to join the cluster.
|
|
47
|
+
*/
|
|
48
|
+
agentToken: secretSchema(z.string()),
|
|
49
|
+
|
|
50
|
+
/**
|
|
51
|
+
* The shared K3s agent configuration for workers joining the cluster.
|
|
52
|
+
*/
|
|
53
|
+
agentConfig: z.record(z.string(), z.unknown()),
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* The registry configuration workers should use when joining the cluster.
|
|
57
|
+
*/
|
|
58
|
+
registries: z.record(z.string(), z.unknown()),
|
|
59
|
+
}),
|
|
60
|
+
|
|
61
|
+
meta: {
|
|
62
|
+
color: "#326CE5",
|
|
63
|
+
title: "K3s Cluster",
|
|
64
|
+
icon: "devicon:k3s",
|
|
65
|
+
iconColor: "#326CE5",
|
|
66
|
+
},
|
|
67
|
+
})
|
|
68
|
+
|
|
25
69
|
/**
|
|
26
70
|
* The K3s cluster created on top of the server.
|
|
27
71
|
*/
|
|
@@ -78,8 +122,28 @@ export const cluster = defineUnit({
|
|
|
78
122
|
registries: z.record(z.string(), z.unknown()).optional(),
|
|
79
123
|
},
|
|
80
124
|
|
|
81
|
-
inputs:
|
|
82
|
-
|
|
125
|
+
inputs: {
|
|
126
|
+
...clusterInputs,
|
|
127
|
+
|
|
128
|
+
/**
|
|
129
|
+
* The public API endpoint to expose for cluster access.
|
|
130
|
+
*
|
|
131
|
+
* If specified, it will be used for the kubeconfig, Kubernetes provider, cluster entity, and TLS SANs.
|
|
132
|
+
* Node bootstrap still uses the first master endpoint.
|
|
133
|
+
*/
|
|
134
|
+
publicEndpoint: {
|
|
135
|
+
entity: l4EndpointEntity,
|
|
136
|
+
required: false,
|
|
137
|
+
},
|
|
138
|
+
},
|
|
139
|
+
outputs: {
|
|
140
|
+
...clusterOutputs,
|
|
141
|
+
|
|
142
|
+
/**
|
|
143
|
+
* The K3s cluster join information for provisioning additional workers.
|
|
144
|
+
*/
|
|
145
|
+
cluster: clusterEntity,
|
|
146
|
+
},
|
|
83
147
|
|
|
84
148
|
meta: {
|
|
85
149
|
title: "K3s Cluster",
|
|
@@ -93,3 +157,65 @@ export const cluster = defineUnit({
|
|
|
93
157
|
path: "cluster",
|
|
94
158
|
},
|
|
95
159
|
})
|
|
160
|
+
|
|
161
|
+
/**
|
|
162
|
+
* The group of K3s worker nodes joined to an existing K3s cluster.
|
|
163
|
+
*/
|
|
164
|
+
export const workerGroup = defineUnit({
|
|
165
|
+
type: "k3s.worker-group.v1",
|
|
166
|
+
|
|
167
|
+
args: {
|
|
168
|
+
/**
|
|
169
|
+
* The K3s configuration to pass to each worker in the group.
|
|
170
|
+
*
|
|
171
|
+
* See: https://docs.k3s.io/installation/configuration
|
|
172
|
+
*/
|
|
173
|
+
config: z.record(z.string(), z.unknown()).optional(),
|
|
174
|
+
|
|
175
|
+
/**
|
|
176
|
+
* The map of configuration per each worker in the group, where the key is the hostname of the node.
|
|
177
|
+
*
|
|
178
|
+
* Note: if multiple nodes have the same hostname, the configuration will be applied to all of them.
|
|
179
|
+
*/
|
|
180
|
+
nodeConfig: z.record(z.string(), z.record(z.string(), z.unknown())).optional(),
|
|
181
|
+
},
|
|
182
|
+
|
|
183
|
+
inputs: {
|
|
184
|
+
/**
|
|
185
|
+
* The K3s cluster join information.
|
|
186
|
+
*/
|
|
187
|
+
cluster: clusterEntity,
|
|
188
|
+
|
|
189
|
+
/**
|
|
190
|
+
* The worker servers in the group to join to the cluster.
|
|
191
|
+
*/
|
|
192
|
+
workers: {
|
|
193
|
+
entity: serverEntity,
|
|
194
|
+
multiple: true,
|
|
195
|
+
},
|
|
196
|
+
},
|
|
197
|
+
|
|
198
|
+
outputs: {
|
|
199
|
+
/**
|
|
200
|
+
* The worker servers in the group joined to the cluster.
|
|
201
|
+
*/
|
|
202
|
+
workers: {
|
|
203
|
+
entity: serverEntity,
|
|
204
|
+
multiple: true,
|
|
205
|
+
},
|
|
206
|
+
},
|
|
207
|
+
|
|
208
|
+
meta: {
|
|
209
|
+
title: "K3s Worker Group",
|
|
210
|
+
category: "k3s",
|
|
211
|
+
icon: "devicon:k3s",
|
|
212
|
+
secondaryIcon: "mdi:server",
|
|
213
|
+
},
|
|
214
|
+
|
|
215
|
+
source: {
|
|
216
|
+
package: "@highstate/k3s",
|
|
217
|
+
path: "worker-group",
|
|
218
|
+
},
|
|
219
|
+
})
|
|
220
|
+
|
|
221
|
+
export type Cluster = EntityValue<typeof clusterEntity>
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
import { defineUnit, z } from "@highstate/contract"
|
|
2
|
+
import { pick } from "remeda"
|
|
3
|
+
import { gatewayEntity } from "../../common"
|
|
4
|
+
import { appName, sharedArgs, sharedInputs, source } from "./shared"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* The Envoy Gateway controller and gateway implementation.
|
|
8
|
+
*/
|
|
9
|
+
export const envoyGateway = defineUnit({
|
|
10
|
+
type: "k8s.apps.envoy-gateway.v1",
|
|
11
|
+
|
|
12
|
+
args: {
|
|
13
|
+
...appName("envoy-gateway"),
|
|
14
|
+
...pick(sharedArgs, ["external", "replicas", "values", "patches", "service", "scheduling"]),
|
|
15
|
+
|
|
16
|
+
/**
|
|
17
|
+
* The name of the GatewayClass to configure for Gateway API resources.
|
|
18
|
+
*
|
|
19
|
+
* Defaults to "envoy-gateway".
|
|
20
|
+
*/
|
|
21
|
+
className: z.string().default("envoy-gateway"),
|
|
22
|
+
|
|
23
|
+
/**
|
|
24
|
+
* The Gateway API controller name for Envoy Gateway.
|
|
25
|
+
*/
|
|
26
|
+
controllerName: z.string().default("gateway.envoyproxy.io/gatewayclass-controller"),
|
|
27
|
+
|
|
28
|
+
/**
|
|
29
|
+
* Whether to install CRDs bundled with the Envoy Gateway Helm chart.
|
|
30
|
+
*/
|
|
31
|
+
installCrds: z.boolean().default(true),
|
|
32
|
+
},
|
|
33
|
+
|
|
34
|
+
inputs: {
|
|
35
|
+
...pick(sharedInputs, ["k8sCluster"]),
|
|
36
|
+
},
|
|
37
|
+
|
|
38
|
+
outputs: {
|
|
39
|
+
gateway: gatewayEntity,
|
|
40
|
+
},
|
|
41
|
+
|
|
42
|
+
meta: {
|
|
43
|
+
title: "Envoy Gateway",
|
|
44
|
+
icon: "simple-icons:envoyproxy",
|
|
45
|
+
iconColor: "#AC6199",
|
|
46
|
+
category: "Network",
|
|
47
|
+
},
|
|
48
|
+
|
|
49
|
+
source: source("envoy-gateway"),
|
|
50
|
+
})
|
package/src/k8s/apps/etcd.ts
CHANGED
package/src/k8s/apps/grafana.ts
CHANGED
package/src/k8s/apps/index.ts
CHANGED
|
@@ -1,4 +1,5 @@
|
|
|
1
1
|
export * from "./code-server"
|
|
2
|
+
export * from "./envoy-gateway"
|
|
2
3
|
export * from "./etcd"
|
|
3
4
|
export * from "./grafana"
|
|
4
5
|
export * from "./grocy"
|
|
@@ -11,6 +12,7 @@ export * from "./portal"
|
|
|
11
12
|
export * from "./postgresql"
|
|
12
13
|
export * from "./refluxdb"
|
|
13
14
|
export * from "./remnawave"
|
|
15
|
+
export * from "./rustfs"
|
|
14
16
|
export {
|
|
15
17
|
appName,
|
|
16
18
|
optionalSharedArgs,
|
|
@@ -19,11 +21,13 @@ export {
|
|
|
19
21
|
sharedInputs,
|
|
20
22
|
sharedSecrets,
|
|
21
23
|
} from "./shared"
|
|
24
|
+
export * from "./signoz"
|
|
22
25
|
export * from "./syncthing"
|
|
23
26
|
// export * from "./zitadel"
|
|
24
27
|
// export * from "./gitea"
|
|
25
28
|
export * from "./traefik"
|
|
26
29
|
export * from "./valkey"
|
|
30
|
+
export * from "./vault"
|
|
27
31
|
export * from "./vaultwarden"
|
|
28
32
|
export * from "./wg-feed-server"
|
|
29
33
|
export * from "./workload"
|
package/src/k8s/apps/mariadb.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { defineUnit, z } from "@highstate/contract"
|
|
2
2
|
import { pick } from "remeda"
|
|
3
3
|
import { postgresql } from "../../databases"
|
|
4
|
-
import { appName, sharedInputs, source } from "./shared"
|
|
4
|
+
import { appName, sharedArgs, sharedInputs, source } from "./shared"
|
|
5
5
|
|
|
6
6
|
/**
|
|
7
7
|
* The Matrix stack deployed on Kubernetes.
|
|
@@ -11,6 +11,7 @@ export const matrixStack = defineUnit({
|
|
|
11
11
|
|
|
12
12
|
args: {
|
|
13
13
|
...appName("matrix-stack"),
|
|
14
|
+
...pick(sharedArgs, ["values", "patches", "service"]),
|
|
14
15
|
|
|
15
16
|
/**
|
|
16
17
|
* The base domain for the Matrix stack services.
|
package/src/k8s/apps/minio.ts
CHANGED
|
@@ -20,8 +20,8 @@ export const minio = defineUnit({
|
|
|
20
20
|
|
|
21
21
|
args: {
|
|
22
22
|
...appName("minio"),
|
|
23
|
-
...pick(optionalSharedArgs, ["fqdn"]),
|
|
24
|
-
...pick(sharedArgs, ["external"]),
|
|
23
|
+
...pick(optionalSharedArgs, ["fqdn", "namespace"]),
|
|
24
|
+
...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
|
|
25
25
|
|
|
26
26
|
/**
|
|
27
27
|
* The FQDN of the MinIO console.
|
package/src/k8s/apps/mongodb.ts
CHANGED
|
@@ -0,0 +1,119 @@
|
|
|
1
|
+
import { defineUnit, z } from "@highstate/contract"
|
|
2
|
+
import { pick } from "remeda"
|
|
3
|
+
import { connectionEntity } from "../../databases/rustfs"
|
|
4
|
+
import { workloadEntity } from "../workload"
|
|
5
|
+
import {
|
|
6
|
+
appName,
|
|
7
|
+
optionalSharedArgs,
|
|
8
|
+
optionalSharedInputs,
|
|
9
|
+
sharedArgs,
|
|
10
|
+
sharedInputs,
|
|
11
|
+
sharedSecrets,
|
|
12
|
+
source,
|
|
13
|
+
} from "./shared"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The RustFS S3-compatible object storage deployed on Kubernetes.
|
|
17
|
+
*/
|
|
18
|
+
export const rustfs = defineUnit({
|
|
19
|
+
type: "k8s.apps.rustfs.v1",
|
|
20
|
+
|
|
21
|
+
args: {
|
|
22
|
+
...appName("rustfs"),
|
|
23
|
+
...pick(optionalSharedArgs, ["fqdn", "namespace"]),
|
|
24
|
+
...pick(sharedArgs, ["external", "values", "patches", "service", "scheduling"]),
|
|
25
|
+
|
|
26
|
+
/**
|
|
27
|
+
* The deployment topology to use.
|
|
28
|
+
*
|
|
29
|
+
* Standalone mode deploys one pod with one data volume.
|
|
30
|
+
* Distributed mode deploys an erasure-coded StatefulSet across multiple pods and volumes.
|
|
31
|
+
*/
|
|
32
|
+
mode: z.enum(["standalone", "distributed"]).default("distributed"),
|
|
33
|
+
|
|
34
|
+
/**
|
|
35
|
+
* The FQDN of the RustFS console.
|
|
36
|
+
*
|
|
37
|
+
* If not provided, the console will only be available inside the cluster.
|
|
38
|
+
*/
|
|
39
|
+
consoleFqdn: z.string().optional(),
|
|
40
|
+
|
|
41
|
+
/**
|
|
42
|
+
* The number of nodes in a distributed deployment.
|
|
43
|
+
*
|
|
44
|
+
* Ignored in standalone mode.
|
|
45
|
+
*/
|
|
46
|
+
replicas: z.number().int().min(2).default(4),
|
|
47
|
+
|
|
48
|
+
/**
|
|
49
|
+
* The number of data volumes attached to each distributed node.
|
|
50
|
+
*
|
|
51
|
+
* Ignored in standalone mode.
|
|
52
|
+
*/
|
|
53
|
+
drivesPerNode: z.number().int().min(1).default(4),
|
|
54
|
+
|
|
55
|
+
/**
|
|
56
|
+
* Whether to bypass RustFS validation that each data volume uses a distinct physical disk.
|
|
57
|
+
*
|
|
58
|
+
* This sets `RUSTFS_UNSAFE_BYPASS_DISK_CHECK=true` and must only be used for local testing or CI.
|
|
59
|
+
* Enabling it in production can cause correlated data loss because multiple erasure-coded drives
|
|
60
|
+
* may actually share one physical device.
|
|
61
|
+
*/
|
|
62
|
+
unsafeBypassDiskCheck: z.boolean().default(false),
|
|
63
|
+
|
|
64
|
+
/**
|
|
65
|
+
* Whether distributed RustFS pods may share Kubernetes nodes.
|
|
66
|
+
*
|
|
67
|
+
* By default, RustFS requires each replica to run on a different node for failure isolation.
|
|
68
|
+
* Enable this when the Kubernetes cluster has fewer eligible nodes than RustFS replicas.
|
|
69
|
+
* Pods will still prefer separate nodes, but the scheduler may place multiple replicas on one node.
|
|
70
|
+
* This reduces fault tolerance because one node failure can make multiple RustFS replicas unavailable.
|
|
71
|
+
*
|
|
72
|
+
* Ignored in standalone mode.
|
|
73
|
+
*/
|
|
74
|
+
allowLessNodes: z.boolean().default(false),
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The Kubernetes StorageClass used for RustFS volumes.
|
|
78
|
+
*/
|
|
79
|
+
storageClass: z.string().default("local-path"),
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The requested capacity of each data volume.
|
|
83
|
+
*/
|
|
84
|
+
dataStorageSize: z.string().default("100Gi"),
|
|
85
|
+
|
|
86
|
+
/**
|
|
87
|
+
* The requested capacity of each log volume.
|
|
88
|
+
*/
|
|
89
|
+
logStorageSize: z.string().default("1Gi"),
|
|
90
|
+
|
|
91
|
+
/**
|
|
92
|
+
* The S3 region reported by RustFS.
|
|
93
|
+
*/
|
|
94
|
+
region: z.string().default("us-east-1"),
|
|
95
|
+
},
|
|
96
|
+
|
|
97
|
+
secrets: {
|
|
98
|
+
...pick(sharedSecrets, ["adminPassword", "backupKey"]),
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
inputs: {
|
|
102
|
+
...pick(sharedInputs, ["k8sCluster"]),
|
|
103
|
+
...pick(optionalSharedInputs, ["accessPoint", "resticRepo"]),
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
outputs: {
|
|
107
|
+
connection: connectionEntity,
|
|
108
|
+
workload: workloadEntity,
|
|
109
|
+
},
|
|
110
|
+
|
|
111
|
+
meta: {
|
|
112
|
+
title: "RustFS",
|
|
113
|
+
icon: "simple-icons:rust",
|
|
114
|
+
secondaryIcon: "mdi:bucket",
|
|
115
|
+
category: "Databases",
|
|
116
|
+
},
|
|
117
|
+
|
|
118
|
+
source: source("rustfs"),
|
|
119
|
+
})
|
package/src/k8s/apps/shared.ts
CHANGED
|
@@ -16,7 +16,18 @@ import { etcd, mongodb, mysql, postgresql, redis } from "../../databases"
|
|
|
16
16
|
import { providerEntity } from "../../dns"
|
|
17
17
|
import { repositoryEntity } from "../../restic"
|
|
18
18
|
import { namespaceEntity, persistentVolumeClaimEntity } from "../resources"
|
|
19
|
-
import { clusterEntity } from "../shared"
|
|
19
|
+
import { clusterEntity, helmExtensionArgs, schedulingArg, serviceArg } from "../shared"
|
|
20
|
+
|
|
21
|
+
export {
|
|
22
|
+
helmExtensionArgs,
|
|
23
|
+
type JsonPatchOperation,
|
|
24
|
+
jsonPatchOperationSchema,
|
|
25
|
+
type Scheduling,
|
|
26
|
+
type ServiceArgs,
|
|
27
|
+
schedulingArg,
|
|
28
|
+
schedulingSchema,
|
|
29
|
+
serviceArg,
|
|
30
|
+
} from "../shared"
|
|
20
31
|
|
|
21
32
|
export const sharedArgs = $args({
|
|
22
33
|
/**
|
|
@@ -47,6 +58,10 @@ export const sharedArgs = $args({
|
|
|
47
58
|
* If not provided, defaults to the appName.
|
|
48
59
|
*/
|
|
49
60
|
namespace: z.string().optional(),
|
|
61
|
+
|
|
62
|
+
...helmExtensionArgs,
|
|
63
|
+
...serviceArg,
|
|
64
|
+
...schedulingArg,
|
|
50
65
|
})
|
|
51
66
|
|
|
52
67
|
type ToOptionalArgs<T extends Record<string, FullComponentArgumentOptions>> = Simplify<{
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
import { defineUnit } from "@highstate/contract"
|
|
2
|
+
import { pick } from "remeda"
|
|
3
|
+
import { serviceEntity } from "../service"
|
|
4
|
+
import { appName, sharedArgs, sharedInputs, source } from "./shared"
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* SigNoz deployed on Kubernetes.
|
|
8
|
+
*/
|
|
9
|
+
export const signoz = defineUnit({
|
|
10
|
+
type: "k8s.apps.signoz.v1",
|
|
11
|
+
|
|
12
|
+
args: {
|
|
13
|
+
...appName("signoz"),
|
|
14
|
+
...pick(sharedArgs, ["fqdn", "namespace", "values", "patches", "service", "scheduling"]),
|
|
15
|
+
},
|
|
16
|
+
|
|
17
|
+
inputs: {
|
|
18
|
+
...pick(sharedInputs, ["k8sCluster", "accessPoint", "postgresql"]),
|
|
19
|
+
},
|
|
20
|
+
|
|
21
|
+
outputs: {
|
|
22
|
+
service: serviceEntity,
|
|
23
|
+
},
|
|
24
|
+
|
|
25
|
+
meta: {
|
|
26
|
+
title: "SigNoz",
|
|
27
|
+
icon: "selfhst:signoz",
|
|
28
|
+
category: "Observability",
|
|
29
|
+
},
|
|
30
|
+
|
|
31
|
+
source: source("signoz"),
|
|
32
|
+
})
|
package/src/k8s/apps/traefik.ts
CHANGED
|
@@ -13,7 +13,7 @@ export const traefik = defineUnit({
|
|
|
13
13
|
|
|
14
14
|
args: {
|
|
15
15
|
...appName("traefik"),
|
|
16
|
-
...pick(sharedArgs, ["external", "replicas"]),
|
|
16
|
+
...pick(sharedArgs, ["external", "replicas", "values", "patches", "service", "scheduling"]),
|
|
17
17
|
|
|
18
18
|
/**
|
|
19
19
|
* The name of the class to configure for ingress and gateway resources.
|
|
@@ -23,14 +23,14 @@ export const traefik = defineUnit({
|
|
|
23
23
|
className: z.string().default("traefik"),
|
|
24
24
|
|
|
25
25
|
/**
|
|
26
|
-
*
|
|
26
|
+
* Whether to create and enable reconciliation for Traefik CRDs.
|
|
27
27
|
*/
|
|
28
|
-
|
|
28
|
+
enableTraefikCrds: z.boolean().default(true),
|
|
29
29
|
|
|
30
30
|
/**
|
|
31
|
-
* Whether to
|
|
31
|
+
* Whether to install CRDs bundled with the Traefik Helm chart.
|
|
32
32
|
*/
|
|
33
|
-
|
|
33
|
+
installCrds: z.boolean().default(true),
|
|
34
34
|
|
|
35
35
|
/**
|
|
36
36
|
* Whether to enable reconciliation for Ingress resources and create ingress class.
|
package/src/k8s/apps/valkey.ts
CHANGED
|
@@ -0,0 +1,113 @@
|
|
|
1
|
+
import { defineUnit, z } from "@highstate/contract"
|
|
2
|
+
import { pick } from "remeda"
|
|
3
|
+
import { connectionEntity } from "../../apps/vault"
|
|
4
|
+
import { s3 } from "../../databases"
|
|
5
|
+
import { statefulSetEntity } from "../workload"
|
|
6
|
+
import {
|
|
7
|
+
appName,
|
|
8
|
+
optionalSharedInputs,
|
|
9
|
+
sharedArgs,
|
|
10
|
+
sharedInputs,
|
|
11
|
+
sharedSecrets,
|
|
12
|
+
source,
|
|
13
|
+
} from "./shared"
|
|
14
|
+
|
|
15
|
+
/**
|
|
16
|
+
* The HashiCorp Vault deployed on Kubernetes using the official Helm chart.
|
|
17
|
+
*/
|
|
18
|
+
export const vault = defineUnit({
|
|
19
|
+
type: "k8s.apps.vault.v1",
|
|
20
|
+
|
|
21
|
+
args: {
|
|
22
|
+
...appName("vault"),
|
|
23
|
+
...pick(sharedArgs, [
|
|
24
|
+
"fqdn",
|
|
25
|
+
"external",
|
|
26
|
+
"namespace",
|
|
27
|
+
"values",
|
|
28
|
+
"patches",
|
|
29
|
+
"service",
|
|
30
|
+
"scheduling",
|
|
31
|
+
]),
|
|
32
|
+
|
|
33
|
+
/**
|
|
34
|
+
* The storage backend to use for Vault.
|
|
35
|
+
*
|
|
36
|
+
* The options are:
|
|
37
|
+
* - `file`: uses a persistent volume claim and supports restic backups (default);
|
|
38
|
+
* - `s3`: uses an external S3-compatible bucket; expects `s3Bucket` input.
|
|
39
|
+
*/
|
|
40
|
+
backend: z.enum(["file", "s3"]).default("file"),
|
|
41
|
+
|
|
42
|
+
/**
|
|
43
|
+
* The automatic Vault initialization configuration.
|
|
44
|
+
*/
|
|
45
|
+
autoInit: z
|
|
46
|
+
.object({
|
|
47
|
+
/**
|
|
48
|
+
* Whether to initialize Vault automatically using the Vault CLI.
|
|
49
|
+
*/
|
|
50
|
+
enabled: z.boolean().default(true),
|
|
51
|
+
|
|
52
|
+
/**
|
|
53
|
+
* The number of unseal key shares to create.
|
|
54
|
+
*/
|
|
55
|
+
shares: z.number().int().positive().default(1),
|
|
56
|
+
|
|
57
|
+
/**
|
|
58
|
+
* The number of unseal key shares required to unseal Vault.
|
|
59
|
+
*/
|
|
60
|
+
threshold: z.number().int().positive().default(1),
|
|
61
|
+
})
|
|
62
|
+
.refine(autoInit => autoInit.threshold <= autoInit.shares, {
|
|
63
|
+
message: "threshold must be less than or equal to shares",
|
|
64
|
+
path: ["threshold"],
|
|
65
|
+
})
|
|
66
|
+
.default({
|
|
67
|
+
enabled: true,
|
|
68
|
+
shares: 1,
|
|
69
|
+
threshold: 1,
|
|
70
|
+
}),
|
|
71
|
+
},
|
|
72
|
+
|
|
73
|
+
secrets: {
|
|
74
|
+
...pick(sharedSecrets, ["backupKey"]),
|
|
75
|
+
|
|
76
|
+
/**
|
|
77
|
+
* The root token returned by `vault operator init`.
|
|
78
|
+
*/
|
|
79
|
+
rootToken: z.string().optional(),
|
|
80
|
+
|
|
81
|
+
/**
|
|
82
|
+
* The unseal key shares returned by `vault operator init`.
|
|
83
|
+
*/
|
|
84
|
+
unsealKeys: z.string().array().meta({ complex: true }).optional(),
|
|
85
|
+
},
|
|
86
|
+
|
|
87
|
+
inputs: {
|
|
88
|
+
...pick(sharedInputs, ["k8sCluster", "accessPoint"]),
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* When `backend` is `s3`, supply an existing S3 bucket connection (see `s3.bucketEntity`).
|
|
92
|
+
*/
|
|
93
|
+
s3Bucket: {
|
|
94
|
+
entity: s3.bucketEntity,
|
|
95
|
+
required: false, // only required if backend is s3, will validate presence later
|
|
96
|
+
},
|
|
97
|
+
|
|
98
|
+
...pick(optionalSharedInputs, ["resticRepo", "volume"]),
|
|
99
|
+
},
|
|
100
|
+
|
|
101
|
+
outputs: {
|
|
102
|
+
connection: connectionEntity,
|
|
103
|
+
statefulSet: statefulSetEntity,
|
|
104
|
+
},
|
|
105
|
+
|
|
106
|
+
meta: {
|
|
107
|
+
title: "Vault",
|
|
108
|
+
icon: "simple-icons:vault",
|
|
109
|
+
category: "Security",
|
|
110
|
+
},
|
|
111
|
+
|
|
112
|
+
source: source("vault"),
|
|
113
|
+
})
|
|
@@ -1,6 +1,13 @@
|
|
|
1
|
-
import { defineUnit } from "@highstate/contract"
|
|
1
|
+
import { defineUnit, z } from "@highstate/contract"
|
|
2
2
|
import { pick } from "remeda"
|
|
3
|
-
import {
|
|
3
|
+
import {
|
|
4
|
+
appName,
|
|
5
|
+
optionalSharedInputs,
|
|
6
|
+
sharedArgs,
|
|
7
|
+
sharedInputs,
|
|
8
|
+
sharedSecrets,
|
|
9
|
+
source,
|
|
10
|
+
} from "./shared"
|
|
4
11
|
|
|
5
12
|
/**
|
|
6
13
|
* The Vaultwarden password manager deployed on Kubernetes.
|
|
@@ -11,10 +18,32 @@ export const vaultwarden = defineUnit({
|
|
|
11
18
|
args: {
|
|
12
19
|
...appName("vaultwarden"),
|
|
13
20
|
...pick(sharedArgs, ["fqdn"]),
|
|
21
|
+
|
|
22
|
+
/**
|
|
23
|
+
* Whether signup is allowed for the Vaultwarden instance. Defaults to `false` for security reasons.
|
|
24
|
+
*/
|
|
25
|
+
allowSignup: z.boolean().default(false),
|
|
26
|
+
|
|
27
|
+
/**
|
|
28
|
+
* Whether admin panel is enabled. Defaults to `true`.
|
|
29
|
+
*/
|
|
30
|
+
enableAdminPanel: z.boolean().default(true),
|
|
31
|
+
},
|
|
32
|
+
|
|
33
|
+
secrets: {
|
|
34
|
+
/**
|
|
35
|
+
* The admin token for the Vaulwarden instance.
|
|
36
|
+
*
|
|
37
|
+
* Will be automatically generated if `enableAdminPanel` is `true`.
|
|
38
|
+
*/
|
|
39
|
+
adminToken: z.string().optional(),
|
|
40
|
+
|
|
41
|
+
...pick(sharedSecrets, ["backupKey"]),
|
|
14
42
|
},
|
|
15
43
|
|
|
16
44
|
inputs: {
|
|
17
45
|
...pick(sharedInputs, ["k8sCluster", "accessPoint", "mysql"]),
|
|
46
|
+
...pick(optionalSharedInputs, ["resticRepo"]),
|
|
18
47
|
},
|
|
19
48
|
|
|
20
49
|
meta: {
|