@rulebricks/cli 2.1.7 → 2.3.2
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/README.md +51 -16
- package/cluster-setup/aws/README.md +96 -47
- package/cluster-setup/aws/check-aws-access.sh +216 -52
- package/cluster-setup/aws/parameters.json +13 -0
- package/cluster-setup/aws/rulebricks-cluster.cfn.yaml +355 -0
- package/cluster-setup/azure/README.md +103 -55
- package/cluster-setup/azure/check-aks-prereqs.sh +236 -56
- package/cluster-setup/azure/parameters.json +30 -0
- package/cluster-setup/azure/rulebricks-cluster.bicep +546 -0
- package/cluster-setup/gcp/README.md +51 -34
- package/cluster-setup/gcp/check-gke-prereqs.sh +222 -60
- package/dist/commands/backup.d.ts +5 -0
- package/dist/commands/backup.js +104 -0
- package/dist/commands/deploy.d.ts +3 -1
- package/dist/commands/deploy.js +226 -326
- package/dist/commands/destroy.d.ts +1 -1
- package/dist/commands/destroy.js +73 -123
- package/dist/commands/init.d.ts +5 -1
- package/dist/commands/init.js +78 -54
- package/dist/commands/list.d.ts +1 -0
- package/dist/commands/list.js +74 -0
- package/dist/commands/open.d.ts +1 -1
- package/dist/commands/open.js +4 -12
- package/dist/commands/redeploy.d.ts +6 -0
- package/dist/commands/redeploy.js +310 -0
- package/dist/commands/restore.d.ts +5 -0
- package/dist/commands/restore.js +338 -0
- package/dist/commands/status.js +62 -49
- package/dist/commands/upgrade.js +74 -51
- package/dist/components/DNSWaitScreen.d.ts +5 -1
- package/dist/components/DNSWaitScreen.js +47 -41
- package/dist/components/Wizard/WizardContext.d.ts +157 -36
- package/dist/components/Wizard/WizardContext.js +872 -160
- package/dist/components/Wizard/steps/CloudProviderStep.js +192 -107
- package/dist/components/Wizard/steps/DomainStep.js +5 -24
- package/dist/components/Wizard/steps/ExternalServicesStep.d.ts +6 -0
- package/dist/components/Wizard/steps/ExternalServicesStep.js +645 -0
- package/dist/components/Wizard/steps/FeatureConfigStep.d.ts +2 -1
- package/dist/components/Wizard/steps/FeatureConfigStep.js +739 -425
- package/dist/components/Wizard/steps/FeaturesStep.js +31 -35
- package/dist/components/Wizard/steps/ObservabilityStep.d.ts +6 -0
- package/dist/components/Wizard/steps/ObservabilityStep.js +137 -0
- package/dist/components/Wizard/steps/ReviewStep.d.ts +2 -1
- package/dist/components/Wizard/steps/ReviewStep.js +56 -12
- package/dist/components/Wizard/steps/StorageStep.d.ts +9 -0
- package/dist/components/Wizard/steps/StorageStep.js +592 -0
- package/dist/components/Wizard/steps/SupabaseCredentialsStep.js +20 -21
- package/dist/components/Wizard/steps/VersionStep.js +45 -23
- package/dist/components/Wizard/steps/index.d.ts +3 -3
- package/dist/components/Wizard/steps/index.js +3 -3
- package/dist/components/common/CommandApproval.d.ts +12 -0
- package/dist/components/common/CommandApproval.js +91 -0
- package/dist/components/common/DeploymentPicker.d.ts +14 -0
- package/dist/components/common/DeploymentPicker.js +16 -0
- package/dist/components/common/index.d.ts +2 -0
- package/dist/components/common/index.js +2 -0
- package/dist/index.js +94 -62
- package/dist/lib/cloudCli.d.ts +134 -63
- package/dist/lib/cloudCli.js +512 -220
- package/dist/lib/clusterSetupDefaults.d.ts +30 -0
- package/dist/lib/clusterSetupDefaults.js +64 -0
- package/dist/lib/commandApproval.d.ts +26 -0
- package/dist/lib/commandApproval.js +114 -0
- package/dist/lib/config.d.ts +12 -10
- package/dist/lib/config.js +91 -33
- package/dist/lib/configFixtures.d.ts +5 -0
- package/dist/lib/configFixtures.js +513 -0
- package/dist/lib/deploymentHealth.d.ts +32 -0
- package/dist/lib/deploymentHealth.js +157 -0
- package/dist/lib/dns.d.ts +1 -1
- package/dist/lib/dns.js +19 -1
- package/dist/lib/dns.test.d.ts +1 -0
- package/dist/lib/dns.test.js +27 -0
- package/dist/lib/dockerHub.d.ts +12 -1
- package/dist/lib/dockerHub.js +18 -8
- package/dist/lib/helm.d.ts +4 -0
- package/dist/lib/helm.js +16 -0
- package/dist/lib/helmValues.d.ts +25 -0
- package/dist/lib/helmValues.js +1841 -289
- package/dist/lib/helmValues.test.d.ts +1 -0
- package/dist/lib/helmValues.test.js +1012 -0
- package/dist/lib/htpasswd.d.ts +1 -0
- package/dist/lib/htpasswd.js +15 -0
- package/dist/lib/kubernetes.d.ts +124 -17
- package/dist/lib/kubernetes.js +576 -145
- package/dist/lib/secrets.d.ts +23 -0
- package/dist/lib/secrets.js +158 -0
- package/dist/lib/validateValues.d.ts +31 -0
- package/dist/lib/validateValues.js +253 -0
- package/dist/lib/versions.d.ts +82 -11
- package/dist/lib/versions.js +131 -31
- package/dist/lib/versions.test.d.ts +1 -0
- package/dist/lib/versions.test.js +81 -0
- package/dist/lib/wizardSteps.d.ts +14 -0
- package/dist/lib/wizardSteps.js +23 -0
- package/dist/lib/workloadIdentity.d.ts +26 -0
- package/dist/lib/workloadIdentity.js +323 -0
- package/dist/lib/workloadIdentity.test.d.ts +1 -0
- package/dist/lib/workloadIdentity.test.js +57 -0
- package/dist/types/index.d.ts +1860 -164
- package/dist/types/index.js +518 -295
- package/package.json +9 -4
- package/schema/values.schema.json +1934 -0
- package/cluster-setup/aws/cluster.yaml +0 -33
- package/cluster-setup/azure/main.bicep +0 -282
- package/cluster-setup/azure/main.parameters.json +0 -21
- package/dist/components/Wizard/steps/CredentialsStep.d.ts +0 -6
- package/dist/components/Wizard/steps/CredentialsStep.js +0 -22
- package/dist/components/Wizard/steps/DeploymentModeStep.d.ts +0 -5
- package/dist/components/Wizard/steps/DeploymentModeStep.js +0 -26
- package/dist/components/Wizard/steps/TierStep.d.ts +0 -6
- package/dist/components/Wizard/steps/TierStep.js +0 -29
- package/dist/lib/terraform.d.ts +0 -66
- package/dist/lib/terraform.js +0 -754
- package/terraform/aws/main.tf +0 -355
- package/terraform/azure/main.tf +0 -371
- package/terraform/gcp/main.tf +0 -407
package/dist/types/index.js
CHANGED
|
@@ -6,22 +6,10 @@ export const SUPPORTED_DNS_PROVIDERS = [
|
|
|
6
6
|
"google",
|
|
7
7
|
"azure",
|
|
8
8
|
];
|
|
9
|
-
// Sink category mappings
|
|
10
|
-
export const LOGGING_SINK_CATEGORIES = {
|
|
11
|
-
s3: "cloud-storage",
|
|
12
|
-
"azure-blob": "cloud-storage",
|
|
13
|
-
gcs: "cloud-storage",
|
|
14
|
-
datadog: "logging-platform",
|
|
15
|
-
splunk: "logging-platform",
|
|
16
|
-
elasticsearch: "logging-platform",
|
|
17
|
-
loki: "logging-platform",
|
|
18
|
-
newrelic: "logging-platform",
|
|
19
|
-
axiom: "logging-platform",
|
|
20
|
-
};
|
|
21
9
|
// Region mappings
|
|
22
10
|
export const CLOUD_REGIONS = {
|
|
23
11
|
aws: [
|
|
24
|
-
// US regions
|
|
12
|
+
// US regions
|
|
25
13
|
"us-east-1",
|
|
26
14
|
"us-east-2",
|
|
27
15
|
"us-west-1",
|
|
@@ -29,7 +17,7 @@ export const CLOUD_REGIONS = {
|
|
|
29
17
|
// Canada
|
|
30
18
|
"ca-central-1",
|
|
31
19
|
"ca-west-1",
|
|
32
|
-
// Europe
|
|
20
|
+
// Europe
|
|
33
21
|
"eu-west-1",
|
|
34
22
|
"eu-west-2",
|
|
35
23
|
"eu-west-3",
|
|
@@ -38,7 +26,7 @@ export const CLOUD_REGIONS = {
|
|
|
38
26
|
"eu-north-1",
|
|
39
27
|
"eu-south-1",
|
|
40
28
|
"eu-south-2",
|
|
41
|
-
// Asia Pacific
|
|
29
|
+
// Asia Pacific
|
|
42
30
|
"ap-northeast-1",
|
|
43
31
|
"ap-northeast-2",
|
|
44
32
|
"ap-northeast-3",
|
|
@@ -60,31 +48,30 @@ export const CLOUD_REGIONS = {
|
|
|
60
48
|
"il-central-1",
|
|
61
49
|
],
|
|
62
50
|
gcp: [
|
|
63
|
-
// Tier 1: Full C4A (Google Axion ARM64) availability - 3+ zones confirmed
|
|
64
51
|
// US regions
|
|
65
|
-
"us-central1",
|
|
66
|
-
"us-east1",
|
|
67
|
-
"us-east4",
|
|
68
|
-
"us-west1",
|
|
69
|
-
"us-west4",
|
|
52
|
+
"us-central1",
|
|
53
|
+
"us-east1",
|
|
54
|
+
"us-east4",
|
|
55
|
+
"us-west1",
|
|
56
|
+
"us-west4",
|
|
70
57
|
// North America
|
|
71
|
-
"northamerica-south1",
|
|
58
|
+
"northamerica-south1",
|
|
72
59
|
// Europe
|
|
73
|
-
"europe-west1",
|
|
74
|
-
"europe-west2",
|
|
75
|
-
"europe-west3",
|
|
76
|
-
"europe-west4",
|
|
77
|
-
"europe-north1",
|
|
60
|
+
"europe-west1",
|
|
61
|
+
"europe-west2",
|
|
62
|
+
"europe-west3",
|
|
63
|
+
"europe-west4",
|
|
64
|
+
"europe-north1",
|
|
78
65
|
// Asia Pacific
|
|
79
|
-
"asia-east1",
|
|
80
|
-
"asia-northeast1",
|
|
81
|
-
"asia-south1",
|
|
82
|
-
"asia-southeast1",
|
|
66
|
+
"asia-east1",
|
|
67
|
+
"asia-northeast1",
|
|
68
|
+
"asia-south1",
|
|
69
|
+
"asia-southeast1",
|
|
83
70
|
// Australia
|
|
84
|
-
"australia-southeast2",
|
|
71
|
+
"australia-southeast2",
|
|
85
72
|
],
|
|
86
73
|
azure: [
|
|
87
|
-
// US regions
|
|
74
|
+
// US regions
|
|
88
75
|
"eastus",
|
|
89
76
|
"eastus2",
|
|
90
77
|
"westus",
|
|
@@ -99,7 +86,7 @@ export const CLOUD_REGIONS = {
|
|
|
99
86
|
"canadaeast",
|
|
100
87
|
// South America
|
|
101
88
|
"brazilsouth",
|
|
102
|
-
// Europe
|
|
89
|
+
// Europe
|
|
103
90
|
"northeurope",
|
|
104
91
|
"westeurope",
|
|
105
92
|
"uksouth",
|
|
@@ -137,156 +124,6 @@ export const CLOUD_REGIONS = {
|
|
|
137
124
|
"israelcentral",
|
|
138
125
|
],
|
|
139
126
|
};
|
|
140
|
-
// Performance tier configurations
|
|
141
|
-
export const TIER_CONFIGS = {
|
|
142
|
-
small: {
|
|
143
|
-
description: "Development & Testing",
|
|
144
|
-
throughput: "<1,000 rules/sec",
|
|
145
|
-
nodes: { min: 4, max: 4 },
|
|
146
|
-
resources: "2 vCPU, 4GB RAM each",
|
|
147
|
-
// HPS
|
|
148
|
-
hpsReplicas: 2,
|
|
149
|
-
hpsWorkerReplicas: { min: 4, max: 8 },
|
|
150
|
-
hpsResources: {
|
|
151
|
-
requests: { cpu: "500m", memory: "1Gi" },
|
|
152
|
-
limits: { cpu: "1500m", memory: "1536Mi" },
|
|
153
|
-
},
|
|
154
|
-
hpsWorkerResources: {
|
|
155
|
-
requests: { cpu: "100m", memory: "128Mi" },
|
|
156
|
-
limits: { cpu: "500m", memory: "512Mi" },
|
|
157
|
-
},
|
|
158
|
-
// Kafka
|
|
159
|
-
kafkaStorage: "10Gi",
|
|
160
|
-
kafkaReplication: 1,
|
|
161
|
-
kafkaResources: {
|
|
162
|
-
requests: { cpu: "500m", memory: "2Gi" },
|
|
163
|
-
limits: { cpu: "2000m", memory: "3Gi" },
|
|
164
|
-
},
|
|
165
|
-
kafkaHeapOpts: "-Xmx1g -Xms1g -XX:+UseZGC -XX:+AlwaysPreTouch",
|
|
166
|
-
// Redis
|
|
167
|
-
redisResources: {
|
|
168
|
-
requests: { cpu: "200m", memory: "256Mi" },
|
|
169
|
-
limits: { cpu: "500m", memory: "2Gi" },
|
|
170
|
-
},
|
|
171
|
-
redisPersistenceSize: "4Gi",
|
|
172
|
-
// Vector
|
|
173
|
-
vectorReplicas: 2,
|
|
174
|
-
vectorResources: {
|
|
175
|
-
requests: { cpu: "50m", memory: "128Mi" },
|
|
176
|
-
limits: { cpu: "200m", memory: "256Mi" },
|
|
177
|
-
},
|
|
178
|
-
// Database
|
|
179
|
-
dbResources: {
|
|
180
|
-
requests: { cpu: "500m", memory: "1Gi" },
|
|
181
|
-
limits: { cpu: "1000m", memory: "2Gi" },
|
|
182
|
-
},
|
|
183
|
-
dbPersistenceSize: "10Gi",
|
|
184
|
-
// App
|
|
185
|
-
appReplicas: 2,
|
|
186
|
-
appResources: {
|
|
187
|
-
requests: { cpu: "500m", memory: "512Mi" },
|
|
188
|
-
limits: { cpu: "2000m", memory: "2Gi" },
|
|
189
|
-
},
|
|
190
|
-
},
|
|
191
|
-
medium: {
|
|
192
|
-
description: "Production",
|
|
193
|
-
throughput: "1,000-10,000 rules/sec",
|
|
194
|
-
nodes: { min: 4, max: 8 },
|
|
195
|
-
resources: "2-4 vCPU, 4-8GB RAM each",
|
|
196
|
-
// HPS
|
|
197
|
-
hpsReplicas: 3,
|
|
198
|
-
hpsWorkerReplicas: { min: 10, max: 24 },
|
|
199
|
-
hpsResources: {
|
|
200
|
-
requests: { cpu: "1000m", memory: "1Gi" },
|
|
201
|
-
limits: { cpu: "4000m", memory: "4Gi" },
|
|
202
|
-
},
|
|
203
|
-
hpsWorkerResources: {
|
|
204
|
-
requests: { cpu: "500m", memory: "512Mi" },
|
|
205
|
-
limits: { cpu: "2000m", memory: "2Gi" },
|
|
206
|
-
},
|
|
207
|
-
// Kafka
|
|
208
|
-
kafkaStorage: "50Gi",
|
|
209
|
-
kafkaReplication: 2,
|
|
210
|
-
kafkaResources: {
|
|
211
|
-
requests: { cpu: "1000m", memory: "3Gi" },
|
|
212
|
-
limits: { cpu: "2000m", memory: "4Gi" },
|
|
213
|
-
},
|
|
214
|
-
kafkaHeapOpts: "-Xmx2g -Xms2g -XX:+UseZGC -XX:+AlwaysPreTouch",
|
|
215
|
-
// Redis
|
|
216
|
-
redisResources: {
|
|
217
|
-
requests: { cpu: "200m", memory: "512Mi" },
|
|
218
|
-
limits: { cpu: "1000m", memory: "4Gi" },
|
|
219
|
-
},
|
|
220
|
-
redisPersistenceSize: "8Gi",
|
|
221
|
-
// Vector
|
|
222
|
-
vectorReplicas: 2,
|
|
223
|
-
vectorResources: {
|
|
224
|
-
requests: { cpu: "100m", memory: "256Mi" },
|
|
225
|
-
limits: { cpu: "500m", memory: "512Mi" },
|
|
226
|
-
},
|
|
227
|
-
// Database
|
|
228
|
-
dbResources: {
|
|
229
|
-
requests: { cpu: "1000m", memory: "2Gi" },
|
|
230
|
-
limits: { cpu: "2000m", memory: "4Gi" },
|
|
231
|
-
},
|
|
232
|
-
dbPersistenceSize: "50Gi",
|
|
233
|
-
// App
|
|
234
|
-
appReplicas: 2,
|
|
235
|
-
appResources: {
|
|
236
|
-
requests: { cpu: "500m", memory: "512Mi" },
|
|
237
|
-
limits: { cpu: "2000m", memory: "2Gi" },
|
|
238
|
-
},
|
|
239
|
-
},
|
|
240
|
-
large: {
|
|
241
|
-
description: "High Performance",
|
|
242
|
-
throughput: ">10,000 rules/sec",
|
|
243
|
-
nodes: { min: 5, max: 16 },
|
|
244
|
-
resources: "2-4 vCPU, 4-8GB RAM each",
|
|
245
|
-
// HPS
|
|
246
|
-
hpsReplicas: 4,
|
|
247
|
-
hpsWorkerReplicas: { min: 10, max: 48 },
|
|
248
|
-
hpsResources: {
|
|
249
|
-
requests: { cpu: "2000m", memory: "2Gi" },
|
|
250
|
-
limits: { cpu: "4000m", memory: "4Gi" },
|
|
251
|
-
},
|
|
252
|
-
hpsWorkerResources: {
|
|
253
|
-
requests: { cpu: "1000m", memory: "1Gi" },
|
|
254
|
-
limits: { cpu: "2000m", memory: "2Gi" },
|
|
255
|
-
},
|
|
256
|
-
// Kafka
|
|
257
|
-
kafkaStorage: "100Gi",
|
|
258
|
-
kafkaReplication: 3,
|
|
259
|
-
kafkaResources: {
|
|
260
|
-
requests: { cpu: "2000m", memory: "4Gi" },
|
|
261
|
-
limits: { cpu: "4000m", memory: "6Gi" },
|
|
262
|
-
},
|
|
263
|
-
kafkaHeapOpts: "-Xmx3g -Xms3g -XX:+UseZGC -XX:+AlwaysPreTouch",
|
|
264
|
-
// Redis
|
|
265
|
-
redisResources: {
|
|
266
|
-
requests: { cpu: "500m", memory: "1Gi" },
|
|
267
|
-
limits: { cpu: "2000m", memory: "8Gi" },
|
|
268
|
-
},
|
|
269
|
-
redisPersistenceSize: "16Gi",
|
|
270
|
-
// Vector
|
|
271
|
-
vectorReplicas: 3,
|
|
272
|
-
vectorResources: {
|
|
273
|
-
requests: { cpu: "200m", memory: "512Mi" },
|
|
274
|
-
limits: { cpu: "1000m", memory: "1Gi" },
|
|
275
|
-
},
|
|
276
|
-
// Database
|
|
277
|
-
dbResources: {
|
|
278
|
-
requests: { cpu: "2000m", memory: "4Gi" },
|
|
279
|
-
limits: { cpu: "4000m", memory: "8Gi" },
|
|
280
|
-
},
|
|
281
|
-
dbPersistenceSize: "100Gi",
|
|
282
|
-
// App
|
|
283
|
-
appReplicas: 3,
|
|
284
|
-
appResources: {
|
|
285
|
-
requests: { cpu: "1000m", memory: "1Gi" },
|
|
286
|
-
limits: { cpu: "2000m", memory: "2Gi" },
|
|
287
|
-
},
|
|
288
|
-
},
|
|
289
|
-
};
|
|
290
127
|
// Default SMTP providers
|
|
291
128
|
export const SMTP_PROVIDERS = {
|
|
292
129
|
"aws-ses": {
|
|
@@ -315,6 +152,13 @@ export const DNS_PROVIDER_NAMES = {
|
|
|
315
152
|
azure: "Azure DNS",
|
|
316
153
|
other: "Other / Not sure",
|
|
317
154
|
};
|
|
155
|
+
// Cloud provider display names with proper casing for UI labels. Acronyms stay
|
|
156
|
+
// uppercase; Azure is title-cased (so it doesn't render as "AZURE").
|
|
157
|
+
export const CLOUD_PROVIDER_NAMES = {
|
|
158
|
+
aws: "AWS",
|
|
159
|
+
gcp: "GCP",
|
|
160
|
+
azure: "Azure",
|
|
161
|
+
};
|
|
318
162
|
// Logging sink display info
|
|
319
163
|
export const LOGGING_SINK_INFO = {
|
|
320
164
|
console: {
|
|
@@ -325,19 +169,6 @@ export const LOGGING_SINK_INFO = {
|
|
|
325
169
|
name: "External (not configured)",
|
|
326
170
|
description: "External logging enabled but destination not selected",
|
|
327
171
|
},
|
|
328
|
-
// Cloud Storage
|
|
329
|
-
s3: {
|
|
330
|
-
name: "AWS S3",
|
|
331
|
-
description: "Store logs in an S3 bucket",
|
|
332
|
-
},
|
|
333
|
-
"azure-blob": {
|
|
334
|
-
name: "Azure Blob Storage",
|
|
335
|
-
description: "Store logs in Azure Blob container",
|
|
336
|
-
},
|
|
337
|
-
gcs: {
|
|
338
|
-
name: "Google Cloud Storage",
|
|
339
|
-
description: "Store logs in a GCS bucket",
|
|
340
|
-
},
|
|
341
172
|
// Logging Platforms
|
|
342
173
|
datadog: {
|
|
343
174
|
name: "Datadog",
|
|
@@ -364,30 +195,81 @@ export const LOGGING_SINK_INFO = {
|
|
|
364
195
|
description: "Send logs to Axiom dataset",
|
|
365
196
|
},
|
|
366
197
|
};
|
|
367
|
-
// Logging destination labels for UI display (shown in the Rulebricks app)
|
|
368
|
-
export const LOGGING_DESTINATION_LABELS = {
|
|
369
|
-
console: "Console (stdout)",
|
|
370
|
-
pending: "External (configuring...)",
|
|
371
|
-
s3: "AWS S3",
|
|
372
|
-
"azure-blob": "Azure Blob Storage",
|
|
373
|
-
gcs: "Google Cloud Storage",
|
|
374
|
-
datadog: "Datadog",
|
|
375
|
-
splunk: "Splunk",
|
|
376
|
-
elasticsearch: "Elasticsearch",
|
|
377
|
-
loki: "Grafana Loki",
|
|
378
|
-
newrelic: "New Relic",
|
|
379
|
-
axiom: "Axiom",
|
|
380
|
-
};
|
|
381
|
-
// Helper to get logging destination label for Helm values
|
|
382
|
-
export function getLoggingDestinationLabel(sink) {
|
|
383
|
-
return LOGGING_DESTINATION_LABELS[sink] || "Console (stdout)";
|
|
384
|
-
}
|
|
385
198
|
const SecretKeyRefSchema = z.object({
|
|
386
199
|
name: z.string().min(1),
|
|
387
200
|
key: z.string().min(1),
|
|
388
201
|
});
|
|
389
|
-
|
|
390
|
-
|
|
202
|
+
/**
|
|
203
|
+
* Validates a Prometheus remote_write config the same way buildHelmValues and
|
|
204
|
+
* the Helm chart do, returning human-readable errors. Centralized so the wizard
|
|
205
|
+
* gate, the Zod schema (load time), and Helm value generation all enforce the
|
|
206
|
+
* exact same per-destination/auth requirements. This is what prevents the CLI
|
|
207
|
+
* from ever persisting a monitoring config that throws at deploy time (e.g.
|
|
208
|
+
* "Azure Monitor remote_write managed identity requires client ID").
|
|
209
|
+
*/
|
|
210
|
+
export function validateRemoteWriteConfig(rw) {
|
|
211
|
+
const errors = [];
|
|
212
|
+
switch (rw.destination) {
|
|
213
|
+
case "aws-amp":
|
|
214
|
+
if (!rw.awsRegion) {
|
|
215
|
+
errors.push("AWS Managed Prometheus remote write requires a region.");
|
|
216
|
+
}
|
|
217
|
+
break;
|
|
218
|
+
case "azure-monitor": {
|
|
219
|
+
// The remote_write URL must be the full DCE metrics-ingestion path, not the
|
|
220
|
+
// bare DCE host. Azure Monitor expects:
|
|
221
|
+
// https://<dce>.<region>.metrics.ingest.monitor.azure.com/dataCollectionRules/<dcrImmutableId>/streams/Microsoft-PrometheusMetrics/api/v1/write?api-version=2023-04-24
|
|
222
|
+
// A bare host silently 404s, so catch the common copy-paste mistake here.
|
|
223
|
+
if (rw.url &&
|
|
224
|
+
!(rw.url.includes("/dataCollectionRules/") &&
|
|
225
|
+
rw.url.includes("/streams/") &&
|
|
226
|
+
rw.url.includes("/api/v1/write"))) {
|
|
227
|
+
errors.push("Azure Monitor remote write URL must be the full DCE metrics-ingestion path " +
|
|
228
|
+
"(https://<dce>.<region>.metrics.ingest.monitor.azure.com/dataCollectionRules/<dcrImmutableId>/streams/Microsoft-PrometheusMetrics/api/v1/write?api-version=2023-04-24), " +
|
|
229
|
+
"not just the data collection endpoint host.");
|
|
230
|
+
}
|
|
231
|
+
// An unset authType is treated as managed identity (the chart default).
|
|
232
|
+
const authType = rw.authType ?? "managed-identity";
|
|
233
|
+
if (authType === "oauth") {
|
|
234
|
+
if (!rw.clientId || !rw.tenantId || !rw.clientSecretRef) {
|
|
235
|
+
errors.push("Azure Monitor remote write (OAuth) requires a client ID, tenant ID, and client secret reference.");
|
|
236
|
+
}
|
|
237
|
+
}
|
|
238
|
+
else if (authType === "workload-identity") {
|
|
239
|
+
if (!rw.clientId || !rw.tenantId) {
|
|
240
|
+
errors.push("Azure Monitor remote write (workload identity) requires a client ID and tenant ID.");
|
|
241
|
+
}
|
|
242
|
+
}
|
|
243
|
+
else if (!rw.clientId) {
|
|
244
|
+
errors.push("Azure Monitor remote write (managed identity) requires a client ID.");
|
|
245
|
+
}
|
|
246
|
+
break;
|
|
247
|
+
}
|
|
248
|
+
case "grafana-cloud":
|
|
249
|
+
if (!rw.usernameSecretRef || !rw.passwordSecretRef) {
|
|
250
|
+
errors.push("Grafana Cloud remote write requires username and password secret references.");
|
|
251
|
+
}
|
|
252
|
+
break;
|
|
253
|
+
case "generic":
|
|
254
|
+
if (rw.authType === "basic" &&
|
|
255
|
+
(!rw.usernameSecretRef || !rw.passwordSecretRef)) {
|
|
256
|
+
errors.push("Basic-auth remote write requires username and password secret references.");
|
|
257
|
+
}
|
|
258
|
+
if (rw.authType === "bearer" && !rw.bearerTokenSecretRef) {
|
|
259
|
+
errors.push("Bearer-token remote write requires a token secret reference.");
|
|
260
|
+
}
|
|
261
|
+
break;
|
|
262
|
+
}
|
|
263
|
+
return errors;
|
|
264
|
+
}
|
|
265
|
+
const RemoteWriteConfigSchema = z
|
|
266
|
+
.object({
|
|
267
|
+
destination: z.enum([
|
|
268
|
+
"aws-amp",
|
|
269
|
+
"azure-monitor",
|
|
270
|
+
"grafana-cloud",
|
|
271
|
+
"generic",
|
|
272
|
+
]),
|
|
391
273
|
url: z.string().url(),
|
|
392
274
|
authType: z
|
|
393
275
|
.enum([
|
|
@@ -410,6 +292,11 @@ const RemoteWriteConfigSchema = z.object({
|
|
|
410
292
|
usernameSecretRef: SecretKeyRefSchema.optional(),
|
|
411
293
|
passwordSecretRef: SecretKeyRefSchema.optional(),
|
|
412
294
|
bearerTokenSecretRef: SecretKeyRefSchema.optional(),
|
|
295
|
+
})
|
|
296
|
+
.superRefine((rw, ctx) => {
|
|
297
|
+
for (const message of validateRemoteWriteConfig(rw)) {
|
|
298
|
+
ctx.addIssue({ code: z.ZodIssueCode.custom, message });
|
|
299
|
+
}
|
|
413
300
|
});
|
|
414
301
|
const MonitoringDestinationSchema = z.enum([
|
|
415
302
|
"local-grafana",
|
|
@@ -418,6 +305,210 @@ const MonitoringDestinationSchema = z.enum([
|
|
|
418
305
|
"grafana-cloud",
|
|
419
306
|
"generic",
|
|
420
307
|
]);
|
|
308
|
+
const TracingConfigSchema = z
|
|
309
|
+
.object({
|
|
310
|
+
enabled: z.boolean(),
|
|
311
|
+
// Absent means "elastic" for backward compatibility with existing configs.
|
|
312
|
+
destination: z.enum(["elastic", "otlp", "azure-monitor"]).optional(),
|
|
313
|
+
samplingRatio: z.number().min(0).max(1).optional(),
|
|
314
|
+
elastic: z
|
|
315
|
+
.object({
|
|
316
|
+
endpoint: z.string().url().optional(),
|
|
317
|
+
authMode: z.enum(["secret-token", "api-key", "none"]).optional(),
|
|
318
|
+
secretToken: z.string().optional(),
|
|
319
|
+
apiKey: z.string().optional(),
|
|
320
|
+
})
|
|
321
|
+
.optional(),
|
|
322
|
+
// Generic OTLP/HTTP backend (Grafana Tempo, Honeycomb, Jaeger, vendor
|
|
323
|
+
// gateways, AWS/Azure OTLP ingestion, etc.).
|
|
324
|
+
otlp: z
|
|
325
|
+
.object({
|
|
326
|
+
endpoint: z.string().url().optional(),
|
|
327
|
+
authMode: z.enum(["none", "bearer", "api-key", "header"]).optional(),
|
|
328
|
+
headerName: z.string().optional(),
|
|
329
|
+
token: z.string().optional(),
|
|
330
|
+
apiKey: z.string().optional(),
|
|
331
|
+
headerValue: z.string().optional(),
|
|
332
|
+
headers: z.record(z.string()).optional(),
|
|
333
|
+
tlsInsecureSkipVerify: z.boolean().optional(),
|
|
334
|
+
})
|
|
335
|
+
.optional(),
|
|
336
|
+
// Azure Monitor / Application Insights.
|
|
337
|
+
azureMonitor: z
|
|
338
|
+
.object({
|
|
339
|
+
connectionString: z.string().optional(),
|
|
340
|
+
})
|
|
341
|
+
.optional(),
|
|
342
|
+
})
|
|
343
|
+
.superRefine((t, ctx) => {
|
|
344
|
+
if (!t.enabled)
|
|
345
|
+
return;
|
|
346
|
+
const destination = t.destination ?? "elastic";
|
|
347
|
+
if (destination === "elastic") {
|
|
348
|
+
if (!t.elastic?.endpoint) {
|
|
349
|
+
ctx.addIssue({
|
|
350
|
+
code: z.ZodIssueCode.custom,
|
|
351
|
+
message: "features.tracing.elastic.endpoint is required when tracing destination is 'elastic'",
|
|
352
|
+
path: ["elastic", "endpoint"],
|
|
353
|
+
});
|
|
354
|
+
}
|
|
355
|
+
const mode = t.elastic?.authMode ?? "secret-token";
|
|
356
|
+
if (mode === "secret-token" && !t.elastic?.secretToken) {
|
|
357
|
+
ctx.addIssue({
|
|
358
|
+
code: z.ZodIssueCode.custom,
|
|
359
|
+
message: "features.tracing.elastic.secretToken is required for authMode 'secret-token'",
|
|
360
|
+
path: ["elastic", "secretToken"],
|
|
361
|
+
});
|
|
362
|
+
}
|
|
363
|
+
if (mode === "api-key" && !t.elastic?.apiKey) {
|
|
364
|
+
ctx.addIssue({
|
|
365
|
+
code: z.ZodIssueCode.custom,
|
|
366
|
+
message: "features.tracing.elastic.apiKey is required for authMode 'api-key'",
|
|
367
|
+
path: ["elastic", "apiKey"],
|
|
368
|
+
});
|
|
369
|
+
}
|
|
370
|
+
}
|
|
371
|
+
else if (destination === "otlp") {
|
|
372
|
+
if (!t.otlp?.endpoint) {
|
|
373
|
+
ctx.addIssue({
|
|
374
|
+
code: z.ZodIssueCode.custom,
|
|
375
|
+
message: "features.tracing.otlp.endpoint is required when tracing destination is 'otlp'",
|
|
376
|
+
path: ["otlp", "endpoint"],
|
|
377
|
+
});
|
|
378
|
+
}
|
|
379
|
+
const mode = t.otlp?.authMode ?? "none";
|
|
380
|
+
if (mode === "bearer" && !t.otlp?.token) {
|
|
381
|
+
ctx.addIssue({
|
|
382
|
+
code: z.ZodIssueCode.custom,
|
|
383
|
+
message: "features.tracing.otlp.token is required for authMode 'bearer'",
|
|
384
|
+
path: ["otlp", "token"],
|
|
385
|
+
});
|
|
386
|
+
}
|
|
387
|
+
if (mode === "api-key" && !t.otlp?.apiKey) {
|
|
388
|
+
ctx.addIssue({
|
|
389
|
+
code: z.ZodIssueCode.custom,
|
|
390
|
+
message: "features.tracing.otlp.apiKey is required for authMode 'api-key'",
|
|
391
|
+
path: ["otlp", "apiKey"],
|
|
392
|
+
});
|
|
393
|
+
}
|
|
394
|
+
if (mode === "header" && !t.otlp?.headerValue) {
|
|
395
|
+
ctx.addIssue({
|
|
396
|
+
code: z.ZodIssueCode.custom,
|
|
397
|
+
message: "features.tracing.otlp.headerValue is required for authMode 'header'",
|
|
398
|
+
path: ["otlp", "headerValue"],
|
|
399
|
+
});
|
|
400
|
+
}
|
|
401
|
+
}
|
|
402
|
+
else if (destination === "azure-monitor") {
|
|
403
|
+
if (!t.azureMonitor?.connectionString) {
|
|
404
|
+
ctx.addIssue({
|
|
405
|
+
code: z.ZodIssueCode.custom,
|
|
406
|
+
message: "features.tracing.azureMonitor.connectionString is required when tracing destination is 'azure-monitor'",
|
|
407
|
+
path: ["azureMonitor", "connectionString"],
|
|
408
|
+
});
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
});
|
|
412
|
+
// Application/container log shipping to a customer-managed Elasticsearch (BYO)
|
|
413
|
+
// via the Vector agent DaemonSet. Distinct from decision-log sinks.
|
|
414
|
+
const AppLogsConfigSchema = z
|
|
415
|
+
.object({
|
|
416
|
+
enabled: z.boolean(),
|
|
417
|
+
destination: z.enum(["elasticsearch", "loki", "generic"]).optional(),
|
|
418
|
+
elasticsearch: z
|
|
419
|
+
.object({
|
|
420
|
+
endpoint: z.string().url().optional(),
|
|
421
|
+
index: z.string().optional(),
|
|
422
|
+
authMode: z.enum(["basic", "api-key", "none"]).optional(),
|
|
423
|
+
username: z.string().optional(),
|
|
424
|
+
password: z.string().optional(),
|
|
425
|
+
apiKey: z.string().optional(),
|
|
426
|
+
verifyCertificate: z.boolean().optional(),
|
|
427
|
+
})
|
|
428
|
+
.optional(),
|
|
429
|
+
loki: z
|
|
430
|
+
.object({
|
|
431
|
+
endpoint: z.string().url().optional(),
|
|
432
|
+
labels: z.record(z.string()).optional(),
|
|
433
|
+
})
|
|
434
|
+
.optional(),
|
|
435
|
+
generic: z
|
|
436
|
+
.object({
|
|
437
|
+
endpoint: z.string().url().optional(),
|
|
438
|
+
authHeader: z.string().optional(),
|
|
439
|
+
})
|
|
440
|
+
.optional(),
|
|
441
|
+
})
|
|
442
|
+
.superRefine((a, ctx) => {
|
|
443
|
+
if (!a.enabled)
|
|
444
|
+
return;
|
|
445
|
+
const destination = a.destination ?? "elasticsearch";
|
|
446
|
+
if (destination === "loki") {
|
|
447
|
+
if (!a.loki?.endpoint) {
|
|
448
|
+
ctx.addIssue({
|
|
449
|
+
code: z.ZodIssueCode.custom,
|
|
450
|
+
message: "features.logging.appLogs.loki.endpoint is required when appLogs destination is 'loki'",
|
|
451
|
+
path: ["loki", "endpoint"],
|
|
452
|
+
});
|
|
453
|
+
}
|
|
454
|
+
return;
|
|
455
|
+
}
|
|
456
|
+
if (destination === "generic") {
|
|
457
|
+
if (!a.generic?.endpoint) {
|
|
458
|
+
ctx.addIssue({
|
|
459
|
+
code: z.ZodIssueCode.custom,
|
|
460
|
+
message: "features.logging.appLogs.generic.endpoint is required when appLogs destination is 'generic'",
|
|
461
|
+
path: ["generic", "endpoint"],
|
|
462
|
+
});
|
|
463
|
+
}
|
|
464
|
+
return;
|
|
465
|
+
}
|
|
466
|
+
if (!a.elasticsearch?.endpoint) {
|
|
467
|
+
ctx.addIssue({
|
|
468
|
+
code: z.ZodIssueCode.custom,
|
|
469
|
+
message: "features.logging.appLogs.elasticsearch.endpoint is required when appLogs is enabled",
|
|
470
|
+
path: ["elasticsearch", "endpoint"],
|
|
471
|
+
});
|
|
472
|
+
}
|
|
473
|
+
const mode = a.elasticsearch?.authMode ?? "basic";
|
|
474
|
+
if (mode === "basic" &&
|
|
475
|
+
(!a.elasticsearch?.username || !a.elasticsearch?.password)) {
|
|
476
|
+
ctx.addIssue({
|
|
477
|
+
code: z.ZodIssueCode.custom,
|
|
478
|
+
message: "features.logging.appLogs.elasticsearch username and password are required for authMode 'basic'",
|
|
479
|
+
path: ["elasticsearch", "username"],
|
|
480
|
+
});
|
|
481
|
+
}
|
|
482
|
+
if (mode === "api-key" && !a.elasticsearch?.apiKey) {
|
|
483
|
+
ctx.addIssue({
|
|
484
|
+
code: z.ZodIssueCode.custom,
|
|
485
|
+
message: "features.logging.appLogs.elasticsearch.apiKey is required for authMode 'api-key'",
|
|
486
|
+
path: ["elasticsearch", "apiKey"],
|
|
487
|
+
});
|
|
488
|
+
}
|
|
489
|
+
});
|
|
490
|
+
const CacheObservabilityConfigSchema = z.object({
|
|
491
|
+
valkeyAdmin: z
|
|
492
|
+
.object({
|
|
493
|
+
enabled: z.boolean(),
|
|
494
|
+
exposure: z.enum(["internal", "ingress"]).optional(),
|
|
495
|
+
hostname: z.string().optional(),
|
|
496
|
+
basicAuthUsers: z.array(z.string()).optional(),
|
|
497
|
+
basicAuthExistingSecret: z.string().optional(),
|
|
498
|
+
allowedIPs: z.array(z.string()).optional(),
|
|
499
|
+
})
|
|
500
|
+
.optional(),
|
|
501
|
+
redisExporter: z
|
|
502
|
+
.object({
|
|
503
|
+
enabled: z.boolean(),
|
|
504
|
+
})
|
|
505
|
+
.optional(),
|
|
506
|
+
kafkaExporter: z
|
|
507
|
+
.object({
|
|
508
|
+
enabled: z.boolean(),
|
|
509
|
+
})
|
|
510
|
+
.optional(),
|
|
511
|
+
});
|
|
421
512
|
// Deployment configuration schema
|
|
422
513
|
export const DeploymentConfigSchema = z.object({
|
|
423
514
|
name: z
|
|
@@ -427,12 +518,24 @@ export const DeploymentConfigSchema = z.object({
|
|
|
427
518
|
.regex(/^[a-z0-9]([a-z0-9-]*[a-z0-9])?$/),
|
|
428
519
|
// Infrastructure
|
|
429
520
|
infrastructure: z.object({
|
|
430
|
-
mode: z.
|
|
521
|
+
mode: z.literal("existing"),
|
|
431
522
|
provider: z.enum(["aws", "gcp", "azure"]).optional(),
|
|
432
523
|
region: z.string().optional(),
|
|
433
524
|
clusterName: z.string().optional(),
|
|
434
525
|
gcpProjectId: z.string().optional(),
|
|
435
526
|
azureResourceGroup: z.string().optional(),
|
|
527
|
+
nodeArchitecture: z
|
|
528
|
+
.enum(["amd64", "arm64", "mixed", "unknown"])
|
|
529
|
+
.optional(),
|
|
530
|
+
arm64TolerationRequired: z.boolean().optional(),
|
|
531
|
+
storageClass: z.string().optional(),
|
|
532
|
+
storageProvisioner: z.string().optional(),
|
|
533
|
+
schedulableNodeCount: z.number().optional(),
|
|
534
|
+
totalCpuCores: z.number().optional(),
|
|
535
|
+
totalMemoryGi: z.number().optional(),
|
|
536
|
+
eligibleCpuCores: z.number().optional(),
|
|
537
|
+
eligibleMemoryGi: z.number().optional(),
|
|
538
|
+
totalPersistentStorageGi: z.number().optional(),
|
|
436
539
|
}),
|
|
437
540
|
// Domain & TLS
|
|
438
541
|
domain: z.string().min(1),
|
|
@@ -444,8 +547,6 @@ export const DeploymentConfigSchema = z.object({
|
|
|
444
547
|
provider: z.enum(["route53", "cloudflare", "google", "azure", "other"]),
|
|
445
548
|
// Should we auto-manage DNS records? (only applicable for supported providers)
|
|
446
549
|
autoManage: z.boolean(),
|
|
447
|
-
// For existing clusters: does external-dns already exist cluster-wide?
|
|
448
|
-
existingExternalDns: z.boolean().optional(),
|
|
449
550
|
}),
|
|
450
551
|
// SMTP Configuration
|
|
451
552
|
smtp: z.object({
|
|
@@ -471,8 +572,153 @@ export const DeploymentConfigSchema = z.object({
|
|
|
471
572
|
supabaseDashboardUser: z.string().optional(),
|
|
472
573
|
supabaseDashboardPass: z.string().optional(),
|
|
473
574
|
}),
|
|
474
|
-
//
|
|
475
|
-
|
|
575
|
+
// Shared object storage: one provider, one identity, one bucket/container.
|
|
576
|
+
// Decision logs and DB backups are just key prefixes within it.
|
|
577
|
+
storage: z
|
|
578
|
+
.object({
|
|
579
|
+
provider: z.enum(["s3", "azure-blob", "gcs"]),
|
|
580
|
+
cloudAuthMode: z.enum(["workload-identity", "secret"]).optional(),
|
|
581
|
+
// Single bucket (S3/GCS) or storage account (azure-blob) + its region.
|
|
582
|
+
bucket: z.string().min(1),
|
|
583
|
+
region: z.string().min(1),
|
|
584
|
+
awsIamRoleArn: z.string().optional(),
|
|
585
|
+
azureBlobClientId: z.string().optional(),
|
|
586
|
+
azureBlobTenantId: z.string().optional(),
|
|
587
|
+
azureBlobConnectionStringSecretRef: SecretKeyRefSchema.optional(),
|
|
588
|
+
// Single blob container (azure-blob only) holding all prefixes.
|
|
589
|
+
azureBlobContainer: z.string().optional(),
|
|
590
|
+
gcpServiceAccountEmail: z.string().optional(),
|
|
591
|
+
// Per-purpose key prefixes within the single bucket/container.
|
|
592
|
+
paths: z
|
|
593
|
+
.object({
|
|
594
|
+
decisionLogs: z.string().optional(),
|
|
595
|
+
dbBackups: z.string().optional(),
|
|
596
|
+
})
|
|
597
|
+
.optional(),
|
|
598
|
+
})
|
|
599
|
+
.optional(),
|
|
600
|
+
// External/managed Redis and Kafka (for large deployments that prefer managed
|
|
601
|
+
// services over the in-cluster defaults). Omitted/embedded means the chart
|
|
602
|
+
// deploys these in-cluster as usual.
|
|
603
|
+
externalServices: z
|
|
604
|
+
.object({
|
|
605
|
+
redis: z
|
|
606
|
+
.object({
|
|
607
|
+
mode: z.enum(["embedded", "external"]),
|
|
608
|
+
external: z
|
|
609
|
+
.object({
|
|
610
|
+
host: z.string().optional(),
|
|
611
|
+
port: z.number().int().min(1).max(65535).optional(),
|
|
612
|
+
password: z.string().optional(),
|
|
613
|
+
existingSecret: z.string().optional(),
|
|
614
|
+
existingSecretKey: z.string().optional(),
|
|
615
|
+
tls: z.boolean().optional(),
|
|
616
|
+
httpApi: z
|
|
617
|
+
.object({
|
|
618
|
+
enabled: z.boolean(),
|
|
619
|
+
url: z.string().optional(),
|
|
620
|
+
token: z.string().optional(),
|
|
621
|
+
})
|
|
622
|
+
.optional(),
|
|
623
|
+
})
|
|
624
|
+
.optional(),
|
|
625
|
+
})
|
|
626
|
+
.optional(),
|
|
627
|
+
kafka: z
|
|
628
|
+
.object({
|
|
629
|
+
mode: z.enum(["embedded", "external"]),
|
|
630
|
+
external: z
|
|
631
|
+
.object({
|
|
632
|
+
// Preset drives per-cloud auth defaults and whether the Vector
|
|
633
|
+
// bridge sidecar is required.
|
|
634
|
+
preset: z
|
|
635
|
+
.enum([
|
|
636
|
+
"aws-msk-iam",
|
|
637
|
+
"azure-event-hubs",
|
|
638
|
+
"gcp-managed",
|
|
639
|
+
"custom",
|
|
640
|
+
])
|
|
641
|
+
.optional(),
|
|
642
|
+
brokers: z.string().optional(),
|
|
643
|
+
topic: z.string().optional(),
|
|
644
|
+
// Prefix namespacing all Kafka topics (e.g. "com.rulebricks.").
|
|
645
|
+
topicPrefix: z.string().optional(),
|
|
646
|
+
// Whether the chart creates the required topics on the managed
|
|
647
|
+
// broker (via the kafka-topic-provision Job, MSK IAM only). Set
|
|
648
|
+
// false for a locked-down broker where topics are managed out of
|
|
649
|
+
// band and the workload role has no CreateTopic. Default true.
|
|
650
|
+
provisionTopics: z.boolean().optional(),
|
|
651
|
+
ssl: z.boolean().optional(),
|
|
652
|
+
sasl: z
|
|
653
|
+
.object({
|
|
654
|
+
// "" means no SASL (plaintext/SSL-only).
|
|
655
|
+
mechanism: z.enum([
|
|
656
|
+
"",
|
|
657
|
+
"aws-iam",
|
|
658
|
+
"oauthbearer",
|
|
659
|
+
"scram-sha-256",
|
|
660
|
+
"scram-sha-512",
|
|
661
|
+
"plain",
|
|
662
|
+
]),
|
|
663
|
+
region: z.string().optional(),
|
|
664
|
+
username: z.string().optional(),
|
|
665
|
+
password: z.string().optional(),
|
|
666
|
+
existingSecret: z.string().optional(),
|
|
667
|
+
})
|
|
668
|
+
.optional(),
|
|
669
|
+
// Cloud workload identity for token mechanisms (MSK IAM / GCP
|
|
670
|
+
// OAUTHBEARER). Applied to the HPS and Vector service accounts.
|
|
671
|
+
identity: z
|
|
672
|
+
.object({
|
|
673
|
+
awsRoleArn: z.string().optional(),
|
|
674
|
+
gcpServiceAccountEmail: z.string().optional(),
|
|
675
|
+
azureClientId: z.string().optional(),
|
|
676
|
+
})
|
|
677
|
+
.optional(),
|
|
678
|
+
})
|
|
679
|
+
.optional(),
|
|
680
|
+
})
|
|
681
|
+
.optional(),
|
|
682
|
+
// Managed external PostgreSQL (AWS RDS/Aurora or Azure Flexible Server).
|
|
683
|
+
// Self-hosted Supabase runs against this instead of the bundled in-cluster
|
|
684
|
+
// database. Maps to the chart's supabase.externalDatabase.* values.
|
|
685
|
+
postgres: z
|
|
686
|
+
.object({
|
|
687
|
+
mode: z.enum(["embedded", "external"]),
|
|
688
|
+
external: z
|
|
689
|
+
.object({
|
|
690
|
+
// Managed provider this database lives on (gates CLI prompts; only
|
|
691
|
+
// aws/azure are supported for the structured/managed flow).
|
|
692
|
+
provider: z.enum(["aws", "azure"]).optional(),
|
|
693
|
+
host: z.string().optional(),
|
|
694
|
+
port: z.number().int().min(1).max(65535).optional(),
|
|
695
|
+
database: z.string().optional(),
|
|
696
|
+
// One-time master/owner credentials the chart's pre-install hook
|
|
697
|
+
// uses to initialize the database (roles, schemas, auth helpers,
|
|
698
|
+
// publication). Inline creds are materialized into a hook-scoped
|
|
699
|
+
// secret; secretRef points at a pre-created secret instead.
|
|
700
|
+
bootstrap: z
|
|
701
|
+
.object({
|
|
702
|
+
enabled: z.boolean().optional(),
|
|
703
|
+
masterUsername: z.string().optional(),
|
|
704
|
+
masterPassword: z.string().optional(),
|
|
705
|
+
secretRef: z.string().optional(),
|
|
706
|
+
appRole: z.string().optional(),
|
|
707
|
+
})
|
|
708
|
+
.optional(),
|
|
709
|
+
})
|
|
710
|
+
.optional(),
|
|
711
|
+
})
|
|
712
|
+
.optional(),
|
|
713
|
+
})
|
|
714
|
+
.optional(),
|
|
715
|
+
backup: z
|
|
716
|
+
.object({
|
|
717
|
+
enabled: z.boolean(),
|
|
718
|
+
schedule: z.string().min(1),
|
|
719
|
+
retentionDays: z.number().int().min(1),
|
|
720
|
+
})
|
|
721
|
+
.optional(),
|
|
476
722
|
// Optional features
|
|
477
723
|
features: z.object({
|
|
478
724
|
ai: z.object({
|
|
@@ -495,15 +741,27 @@ export const DeploymentConfigSchema = z.object({
|
|
|
495
741
|
remoteWriteUrl: z.string().url().optional(),
|
|
496
742
|
remoteWrite: RemoteWriteConfigSchema.optional(),
|
|
497
743
|
}),
|
|
744
|
+
observability: z
|
|
745
|
+
.object({
|
|
746
|
+
clickstack: z.object({
|
|
747
|
+
enabled: z.boolean(),
|
|
748
|
+
telemetryRetentionDays: z.number().int().min(1).optional(),
|
|
749
|
+
decisionLogRetentionDays: z.number().int().min(1).optional(),
|
|
750
|
+
clickHouseStorageSize: z.string().optional(),
|
|
751
|
+
}),
|
|
752
|
+
})
|
|
753
|
+
.optional(),
|
|
754
|
+
// Distributed tracing (optional; self-hosted only). Absent on existing
|
|
755
|
+
// config files, which keeps them valid.
|
|
756
|
+
tracing: TracingConfigSchema.optional(),
|
|
757
|
+
cache: CacheObservabilityConfigSchema.optional(),
|
|
498
758
|
logging: z.object({
|
|
499
|
-
//
|
|
500
|
-
//
|
|
759
|
+
// Console logging is always on. This selects an additional external
|
|
760
|
+
// logging platform. Cloud object storage for decision logs is configured
|
|
761
|
+
// separately under `storage`.
|
|
501
762
|
sink: z.enum([
|
|
502
763
|
"console",
|
|
503
764
|
"pending",
|
|
504
|
-
"s3",
|
|
505
|
-
"azure-blob",
|
|
506
|
-
"gcs",
|
|
507
765
|
"datadog",
|
|
508
766
|
"splunk",
|
|
509
767
|
"elasticsearch",
|
|
@@ -511,18 +769,13 @@ export const DeploymentConfigSchema = z.object({
|
|
|
511
769
|
"newrelic",
|
|
512
770
|
"axiom",
|
|
513
771
|
]),
|
|
514
|
-
//
|
|
515
|
-
//
|
|
516
|
-
// For platforms: repurposed for credentials (API key) and extra config
|
|
772
|
+
// For platforms, bucket/region are repurposed to carry the credential
|
|
773
|
+
// (API key/token) and endpoint/site.
|
|
517
774
|
bucket: z.string().optional(),
|
|
518
775
|
region: z.string().optional(),
|
|
519
|
-
|
|
520
|
-
|
|
521
|
-
|
|
522
|
-
azureBlobClientId: z.string().optional(),
|
|
523
|
-
azureBlobTenantId: z.string().optional(),
|
|
524
|
-
azureBlobConnectionStringSecretRef: SecretKeyRefSchema.optional(),
|
|
525
|
-
gcpServiceAccountEmail: z.string().optional(),
|
|
776
|
+
// Application/container log shipping to Elasticsearch via the Vector
|
|
777
|
+
// agent DaemonSet (distinct from the decision-log `sink` above).
|
|
778
|
+
appLogs: AppLogsConfigSchema.optional(),
|
|
526
779
|
}),
|
|
527
780
|
customEmails: z
|
|
528
781
|
.object({
|
|
@@ -548,65 +801,17 @@ export const DeploymentConfigSchema = z.object({
|
|
|
548
801
|
}),
|
|
549
802
|
// Credentials
|
|
550
803
|
licenseKey: z.string().min(1),
|
|
551
|
-
//
|
|
552
|
-
|
|
553
|
-
|
|
804
|
+
// Product version used for app, HPS, and HPS worker images
|
|
805
|
+
version: z.string().min(1),
|
|
806
|
+
// Optional single registry-host override for every image. Empty/unset means
|
|
807
|
+
// the chart default docker.io/rulebricks/*. When set (e.g. "myacr.azurecr.io"
|
|
808
|
+
// for an air-gapped mirror), the CLI rewrites the registry host into
|
|
809
|
+
// global.imageRegistry and into each Tier-2 chart's native image keys, keeping
|
|
810
|
+
// the rulebricks/<name> path. See the helm chart's global.imageRegistry knob.
|
|
811
|
+
imageRegistry: z.string().optional(),
|
|
554
812
|
// Legacy chart version (deprecated, kept for backwards compatibility)
|
|
555
813
|
chartVersion: z.string().optional(),
|
|
556
814
|
});
|
|
557
|
-
export const WIZARD_STEPS = [
|
|
558
|
-
{ id: "mode", title: "Deployment Mode", description: "Choose how to deploy" },
|
|
559
|
-
{
|
|
560
|
-
id: "cloud",
|
|
561
|
-
title: "Cloud Provider",
|
|
562
|
-
description: "Select your cloud provider",
|
|
563
|
-
},
|
|
564
|
-
{
|
|
565
|
-
id: "domain",
|
|
566
|
-
title: "Domain & DNS",
|
|
567
|
-
description: "Configure your domain and DNS",
|
|
568
|
-
},
|
|
569
|
-
{
|
|
570
|
-
id: "smtp",
|
|
571
|
-
title: "Email (SMTP)",
|
|
572
|
-
description: "Configure email delivery",
|
|
573
|
-
},
|
|
574
|
-
{
|
|
575
|
-
id: "database",
|
|
576
|
-
title: "Database",
|
|
577
|
-
description: "Choose your database setup",
|
|
578
|
-
},
|
|
579
|
-
{
|
|
580
|
-
id: "database-creds",
|
|
581
|
-
title: "Database Credentials",
|
|
582
|
-
description: "Configure database access",
|
|
583
|
-
},
|
|
584
|
-
{
|
|
585
|
-
id: "tier",
|
|
586
|
-
title: "Performance Tier",
|
|
587
|
-
description: "Select your deployment size",
|
|
588
|
-
},
|
|
589
|
-
{
|
|
590
|
-
id: "features",
|
|
591
|
-
title: "Optional Features",
|
|
592
|
-
description: "Enable additional features",
|
|
593
|
-
},
|
|
594
|
-
{
|
|
595
|
-
id: "feature-config",
|
|
596
|
-
title: "Feature Settings",
|
|
597
|
-
description: "Configure enabled features",
|
|
598
|
-
},
|
|
599
|
-
{
|
|
600
|
-
id: "credentials",
|
|
601
|
-
title: "License & Version",
|
|
602
|
-
description: "Enter license and select version",
|
|
603
|
-
},
|
|
604
|
-
{
|
|
605
|
-
id: "review",
|
|
606
|
-
title: "Review & Save",
|
|
607
|
-
description: "Review your configuration",
|
|
608
|
-
},
|
|
609
|
-
];
|
|
610
815
|
// Helper to check if DNS provider supports external-dns
|
|
611
816
|
export function isSupportedDnsProvider(provider) {
|
|
612
817
|
return SUPPORTED_DNS_PROVIDERS.includes(provider);
|
|
@@ -635,9 +840,27 @@ export const ProfileConfigSchema = z.object({
|
|
|
635
840
|
openaiApiKey: z.string().optional(),
|
|
636
841
|
licenseKey: z.string().optional(),
|
|
637
842
|
// Preferences
|
|
638
|
-
tier: z.enum(["small", "medium", "large"]).optional(),
|
|
639
843
|
databaseType: z.enum(["self-hosted", "supabase-cloud"]).optional(),
|
|
640
|
-
|
|
844
|
+
storage: z
|
|
845
|
+
.object({
|
|
846
|
+
provider: z.enum(["s3", "azure-blob", "gcs"]),
|
|
847
|
+
cloudAuthMode: z.enum(["workload-identity", "secret"]).optional(),
|
|
848
|
+
bucket: z.string().optional(),
|
|
849
|
+
region: z.string().optional(),
|
|
850
|
+
awsIamRoleArn: z.string().optional(),
|
|
851
|
+
azureBlobClientId: z.string().optional(),
|
|
852
|
+
azureBlobTenantId: z.string().optional(),
|
|
853
|
+
azureBlobConnectionStringSecretRef: SecretKeyRefSchema.optional(),
|
|
854
|
+
azureBlobContainer: z.string().optional(),
|
|
855
|
+
gcpServiceAccountEmail: z.string().optional(),
|
|
856
|
+
paths: z
|
|
857
|
+
.object({
|
|
858
|
+
decisionLogs: z.string().optional(),
|
|
859
|
+
dbBackups: z.string().optional(),
|
|
860
|
+
})
|
|
861
|
+
.optional(),
|
|
862
|
+
})
|
|
863
|
+
.optional(),
|
|
641
864
|
// SSO (optional)
|
|
642
865
|
ssoProvider: z
|
|
643
866
|
.enum(["azure", "google", "okta", "keycloak", "ory", "other"])
|