@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/commands/upgrade.js
CHANGED
|
@@ -4,13 +4,29 @@ import { Box, Text, useApp, useInput } from "ink";
|
|
|
4
4
|
import SelectInput from "ink-select-input";
|
|
5
5
|
import { BorderBox, Spinner, ThemeProvider, useTheme, Logo, } from "../components/common/index.js";
|
|
6
6
|
import { loadDeploymentConfig, loadDeploymentState, updateDeploymentStatus, getHelmValuesPath, } from "../lib/config.js";
|
|
7
|
-
import { upgradeChart, dryRunUpgrade } from "../lib/helm.js";
|
|
8
|
-
import { formatDate, getAppVersionInfo, } from "../lib/versions.js";
|
|
7
|
+
import { upgradeChart, dryRunUpgrade, getInstalledChartVersion, } from "../lib/helm.js";
|
|
8
|
+
import { formatDate, getAppVersionInfo, hasRegistryDigestMismatch, } from "../lib/versions.js";
|
|
9
9
|
import { formatVersionDisplay, normalizeVersion } from "../lib/dockerHub.js";
|
|
10
10
|
import { CHANGELOG_URL, getNamespace, getReleaseName, } from "../types/index.js";
|
|
11
|
-
import { getDeployedImageVersions, rolloutRestart } from "../lib/kubernetes.js";
|
|
11
|
+
import { getDeployedImageVersions, rolloutRestart, } from "../lib/kubernetes.js";
|
|
12
12
|
import fs from "fs/promises";
|
|
13
13
|
import YAML from "yaml";
|
|
14
|
+
function hasSameVersionHpsPatch(version, deployedVersions) {
|
|
15
|
+
if (!deployedVersions) {
|
|
16
|
+
return false;
|
|
17
|
+
}
|
|
18
|
+
const hpsVersionMatches = deployedVersions.hpsVersion &&
|
|
19
|
+
normalizeVersion(deployedVersions.hpsVersion) ===
|
|
20
|
+
normalizeVersion(version.version);
|
|
21
|
+
const workerVersionMatches = deployedVersions.hpsWorkerVersion &&
|
|
22
|
+
normalizeVersion(deployedVersions.hpsWorkerVersion) ===
|
|
23
|
+
normalizeVersion(version.version);
|
|
24
|
+
if (!hpsVersionMatches && !workerVersionMatches) {
|
|
25
|
+
return false;
|
|
26
|
+
}
|
|
27
|
+
return (hasRegistryDigestMismatch(deployedVersions.hpsDigests, version.hpsDigests) ||
|
|
28
|
+
hasRegistryDigestMismatch(deployedVersions.hpsWorkerDigests, version.hpsWorkerDigests));
|
|
29
|
+
}
|
|
14
30
|
function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
15
31
|
const { exit } = useApp();
|
|
16
32
|
const { colors } = useTheme();
|
|
@@ -22,6 +38,15 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
22
38
|
const [dryRunOutput, setDryRunOutput] = useState(null);
|
|
23
39
|
// Store actual deployed HPS version separately (may differ from expected)
|
|
24
40
|
const [deployedHpsVersion, setDeployedHpsVersion] = useState(null);
|
|
41
|
+
const [deployedVersions, setDeployedVersions] = useState(null);
|
|
42
|
+
async function resolvePinnedChartVersion(namespace, releaseName) {
|
|
43
|
+
const state = await loadDeploymentState(name);
|
|
44
|
+
const stateChartVersion = state?.application?.chartVersion;
|
|
45
|
+
if (stateChartVersion && stateChartVersion !== "latest") {
|
|
46
|
+
return stateChartVersion;
|
|
47
|
+
}
|
|
48
|
+
return (await getInstalledChartVersion(releaseName, namespace)) || undefined;
|
|
49
|
+
}
|
|
25
50
|
useEffect(() => {
|
|
26
51
|
loadVersions();
|
|
27
52
|
}, []);
|
|
@@ -34,11 +59,14 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
34
59
|
const namespace = state?.application?.namespace || getNamespace(name);
|
|
35
60
|
const releaseName = getReleaseName(name);
|
|
36
61
|
const deployedVersions = await getDeployedImageVersions(releaseName, namespace);
|
|
62
|
+
setDeployedVersions(deployedVersions);
|
|
37
63
|
// Use deployed version from K8s, fall back to state file if K8s query fails
|
|
38
|
-
const
|
|
64
|
+
const currentVersion = deployedVersions.appVersion ||
|
|
65
|
+
state?.application?.version ||
|
|
66
|
+
null;
|
|
39
67
|
// Store actual deployed HPS version for display
|
|
40
|
-
setDeployedHpsVersion(deployedVersions.hpsVersion ||
|
|
41
|
-
const info = await getAppVersionInfo(cfg.licenseKey,
|
|
68
|
+
setDeployedHpsVersion(deployedVersions.hpsVersion || null);
|
|
69
|
+
const info = await getAppVersionInfo(cfg.licenseKey, currentVersion);
|
|
42
70
|
setVersionInfo(info);
|
|
43
71
|
if (targetVersion) {
|
|
44
72
|
// Find the version in available list
|
|
@@ -68,13 +96,18 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
68
96
|
}
|
|
69
97
|
async function performDryRun(version) {
|
|
70
98
|
try {
|
|
71
|
-
// Update
|
|
99
|
+
// Update Helm values with the unified product version before dry run
|
|
72
100
|
await updateHelmValuesWithVersion(version);
|
|
73
101
|
const state = await loadDeploymentState(name);
|
|
74
102
|
// Use namespace from state if available (backwards compat), otherwise compute from deployment name
|
|
75
103
|
const namespace = state?.application?.namespace || getNamespace(name);
|
|
76
104
|
const releaseName = getReleaseName(name);
|
|
77
|
-
const
|
|
105
|
+
const chartVersion = await resolvePinnedChartVersion(namespace, releaseName);
|
|
106
|
+
const output = await dryRunUpgrade(name, {
|
|
107
|
+
releaseName,
|
|
108
|
+
namespace,
|
|
109
|
+
version: chartVersion,
|
|
110
|
+
});
|
|
78
111
|
setDryRunOutput(output);
|
|
79
112
|
setStep("complete");
|
|
80
113
|
}
|
|
@@ -88,30 +121,10 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
88
121
|
try {
|
|
89
122
|
const content = await fs.readFile(valuesPath, "utf8");
|
|
90
123
|
const values = YAML.parse(content);
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
values.rulebricks = {};
|
|
124
|
+
if (!values.global) {
|
|
125
|
+
values.global = {};
|
|
94
126
|
}
|
|
95
|
-
|
|
96
|
-
// Update app image tag
|
|
97
|
-
if (!rulebricks.app) {
|
|
98
|
-
rulebricks.app = {};
|
|
99
|
-
}
|
|
100
|
-
const app = rulebricks.app;
|
|
101
|
-
if (!app.image) {
|
|
102
|
-
app.image = {};
|
|
103
|
-
}
|
|
104
|
-
app.image.tag = version.version;
|
|
105
|
-
// Update HPS image tag
|
|
106
|
-
if (!rulebricks.hps) {
|
|
107
|
-
rulebricks.hps = {};
|
|
108
|
-
}
|
|
109
|
-
const hps = rulebricks.hps;
|
|
110
|
-
if (!hps.image) {
|
|
111
|
-
hps.image = {};
|
|
112
|
-
}
|
|
113
|
-
hps.image.tag =
|
|
114
|
-
version.hpsVersion || version.version;
|
|
127
|
+
values.global.version = version.version;
|
|
115
128
|
// Save updated values
|
|
116
129
|
await fs.writeFile(valuesPath, YAML.stringify(values), "utf8");
|
|
117
130
|
}
|
|
@@ -124,14 +137,20 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
124
137
|
return;
|
|
125
138
|
setStep("upgrading");
|
|
126
139
|
try {
|
|
127
|
-
// Update
|
|
140
|
+
// Update Helm values with the unified product version
|
|
128
141
|
await updateHelmValuesWithVersion(selectedVersion);
|
|
129
142
|
const state = await loadDeploymentState(name);
|
|
130
143
|
// Use namespace from state if available (backwards compat), otherwise compute from deployment name
|
|
131
144
|
const namespace = state?.application?.namespace || getNamespace(name);
|
|
132
145
|
const releaseName = getReleaseName(name);
|
|
133
146
|
// Perform the upgrade
|
|
134
|
-
|
|
147
|
+
const chartVersion = await resolvePinnedChartVersion(namespace, releaseName);
|
|
148
|
+
await upgradeChart(name, {
|
|
149
|
+
releaseName,
|
|
150
|
+
namespace,
|
|
151
|
+
version: chartVersion,
|
|
152
|
+
wait: true,
|
|
153
|
+
});
|
|
135
154
|
// Force restart HPS statefulsets to ensure fresh images are pulled
|
|
136
155
|
// (pullPolicy: Always only pulls on pod restart, not on unchanged spec)
|
|
137
156
|
await rolloutRestart("statefulset", `${releaseName}-hps`, namespace);
|
|
@@ -139,8 +158,8 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
139
158
|
// Update deployment state
|
|
140
159
|
await updateDeploymentStatus(name, "running", {
|
|
141
160
|
application: {
|
|
142
|
-
|
|
143
|
-
|
|
161
|
+
version: selectedVersion.version,
|
|
162
|
+
chartVersion: chartVersion || state?.application?.chartVersion,
|
|
144
163
|
namespace,
|
|
145
164
|
url: `https://${config.domain}`,
|
|
146
165
|
},
|
|
@@ -185,7 +204,7 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
185
204
|
if (dryRun && dryRunOutput) {
|
|
186
205
|
return (_jsx(BorderBox, { title: "Dry Run Results", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { color: colors.accent, children: "Preview of changes (no changes made):" }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: colors.muted, children: [dryRunOutput.substring(0, 500), "..."] }) })] }) }));
|
|
187
206
|
}
|
|
188
|
-
return (_jsx(BorderBox, { title: "Upgrade Complete", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsxs(Text, { color: colors.success, bold: true, children: ["\u2713 Upgraded to ", formatVersionDisplay(selectedVersion?.version || "")] }),
|
|
207
|
+
return (_jsx(BorderBox, { title: "Upgrade Complete", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsxs(Text, { color: colors.success, bold: true, children: ["\u2713 Upgraded to ", formatVersionDisplay(selectedVersion?.version || "")] }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { children: ["Run `rulebricks status ", name, "` to verify the deployment"] }) })] }) }));
|
|
189
208
|
}
|
|
190
209
|
if (step === "upgrading") {
|
|
191
210
|
return (_jsx(BorderBox, { title: "Upgrading", children: _jsx(Box, { marginY: 1, children: _jsx(Spinner, { label: `Installing ${formatVersionDisplay(selectedVersion?.version || "")}...` }) }) }));
|
|
@@ -193,36 +212,40 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
193
212
|
if (step === "confirm") {
|
|
194
213
|
return (_jsx(BorderBox, { title: "Confirm Upgrade", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsxs(Text, { children: ["Current:", " ", _jsx(Text, { color: colors.accent, children: versionInfo?.current
|
|
195
214
|
? formatVersionDisplay(versionInfo.current.version)
|
|
196
|
-
: "Not installed" })
|
|
215
|
+
: "Not installed" })] }), _jsxs(Text, { children: ["Target:", " ", _jsx(Text, { color: colors.success, children: formatVersionDisplay(selectedVersion?.version || "") })] }), _jsxs(Box, { marginTop: 1, flexDirection: "column", children: [_jsx(Text, { color: colors.warning, children: "\u26A0 This will upgrade your Rulebricks deployment." }), _jsx(Text, { color: colors.muted, children: "Pods will be restarted and there may be brief downtime." })] }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.success, bold: true, children: "Press Enter to continue, Esc to go back" }) })] }) }));
|
|
197
216
|
}
|
|
198
217
|
// Version selection screen
|
|
199
218
|
const versionItems = versionInfo?.available.map((v) => ({
|
|
200
219
|
label: formatVersionDisplay(v.version),
|
|
201
220
|
value: v.version,
|
|
202
|
-
hpsVersion: v.hpsVersion,
|
|
203
221
|
date: v.releaseDate,
|
|
204
|
-
|
|
222
|
+
hasSameVersionPatch: hasSameVersionHpsPatch(v, deployedVersions),
|
|
223
|
+
// Only mark as "current" if app and HPS versions match what's deployed
|
|
205
224
|
isCurrent: versionInfo.current?.version === v.version &&
|
|
206
225
|
(!deployedHpsVersion ||
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
normalizeVersion(v.hpsVersion)),
|
|
226
|
+
normalizeVersion(deployedHpsVersion) === normalizeVersion(v.version)) &&
|
|
227
|
+
!hasSameVersionHpsPatch(v, deployedVersions),
|
|
210
228
|
isLatest: versionInfo.latest?.version === v.version,
|
|
211
229
|
})) || [];
|
|
212
230
|
return (_jsx(BorderBox, { title: "Rulebricks Version Manager", children: _jsxs(Box, { flexDirection: "column", marginY: 1, children: [(() => {
|
|
213
231
|
// Check if HPS has an update available (even if app version is current)
|
|
214
|
-
const
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
232
|
+
const hasHpsDigestUpdate = versionInfo?.latest
|
|
233
|
+
? hasSameVersionHpsPatch(versionInfo.latest, deployedVersions)
|
|
234
|
+
: false;
|
|
235
|
+
const hasHpsUpdate = hasHpsDigestUpdate ||
|
|
236
|
+
!!(deployedHpsVersion &&
|
|
237
|
+
versionInfo?.latest &&
|
|
238
|
+
normalizeVersion(deployedHpsVersion) !==
|
|
239
|
+
normalizeVersion(versionInfo.latest.version));
|
|
219
240
|
const hasAnyUpdate = versionInfo?.hasUpdate || hasHpsUpdate;
|
|
220
241
|
return (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Text, { children: ["Current:", " ", _jsx(Text, { color: colors.accent, children: versionInfo?.current
|
|
221
242
|
? formatVersionDisplay(versionInfo.current.version)
|
|
222
|
-
: "Not installed" })
|
|
243
|
+
: "Not installed" })] }), _jsxs(Text, { children: ["Latest:", " ", _jsx(Text, { color: hasAnyUpdate ? colors.success : colors.accent, children: versionInfo?.latest
|
|
223
244
|
? formatVersionDisplay(versionInfo.latest.version)
|
|
224
|
-
: "Unknown" })
|
|
225
|
-
|
|
245
|
+
: "Unknown" })] }), hasAnyUpdate && (_jsx(Text, { color: colors.muted, dimColor: true, children: hasHpsDigestUpdate
|
|
246
|
+
? "HPS patch available for the installed version"
|
|
247
|
+
: "Update available" }))] }));
|
|
248
|
+
})(), _jsxs(Box, { marginBottom: 1, paddingX: 1, borderStyle: "single", borderColor: colors.accent, alignSelf: "flex-start", children: [_jsx(Text, { children: "\uD83D\uDCDA What's new: " }), _jsx(Text, { color: colors.accent, underline: true, children: CHANGELOG_URL })] }), _jsx(Text, { bold: true, children: "Select Rulebricks version to install:" }), _jsx(Box, { marginTop: 1, children: _jsx(SelectInput, { items: versionItems, onSelect: handleVersionSelect, limit: 8, itemComponent: ({ isSelected, label }) => {
|
|
226
249
|
const vItem = versionItems.find((v) => v.label === label) || versionItems[0];
|
|
227
250
|
// Highlight latest in green when there's an update available
|
|
228
251
|
const isLatestWithUpdate = vItem.isLatest && !vItem.isCurrent;
|
|
@@ -231,7 +254,7 @@ function UpgradeCommandInner({ name, targetVersion, dryRun, }) {
|
|
|
231
254
|
: isLatestWithUpdate
|
|
232
255
|
? colors.success
|
|
233
256
|
: undefined;
|
|
234
|
-
return (_jsxs(Box, { children: [_jsx(Text, { color: labelColor, children: label }), vItem.
|
|
257
|
+
return (_jsxs(Box, { children: [_jsx(Text, { color: labelColor, children: label }), vItem.isCurrent && (_jsx(Text, { color: colors.warning, children: " current" })), vItem.hasSameVersionPatch && (_jsx(Text, { color: colors.success, children: " patch available" })), _jsxs(Text, { color: colors.muted, children: [" ", formatDate(vItem.date)] })] }));
|
|
235
258
|
} }) })] }) }));
|
|
236
259
|
}
|
|
237
260
|
export function UpgradeCommand(props) {
|
|
@@ -1,9 +1,13 @@
|
|
|
1
1
|
interface DNSWaitScreenProps {
|
|
2
2
|
domain: string;
|
|
3
3
|
selfHostedSupabase: boolean;
|
|
4
|
+
builtInObservability?: boolean;
|
|
5
|
+
observabilityHostname?: string;
|
|
6
|
+
valkeyAdminIngress?: boolean;
|
|
7
|
+
valkeyAdminHostname?: string;
|
|
4
8
|
namespace: string;
|
|
5
9
|
onComplete: () => void;
|
|
6
10
|
onSkip?: () => void;
|
|
7
11
|
}
|
|
8
|
-
export declare function DNSWaitScreen({ domain, selfHostedSupabase, namespace, onComplete, onSkip, }: DNSWaitScreenProps): import("react/jsx-runtime").JSX.Element;
|
|
12
|
+
export declare function DNSWaitScreen({ domain, selfHostedSupabase, builtInObservability, observabilityHostname, valkeyAdminIngress, valkeyAdminHostname, namespace, onComplete, onSkip, }: DNSWaitScreenProps): import("react/jsx-runtime").JSX.Element;
|
|
9
13
|
export {};
|
|
@@ -1,19 +1,32 @@
|
|
|
1
1
|
import { jsx as _jsx, jsxs as _jsxs } from "react/jsx-runtime";
|
|
2
|
-
import { useState, useEffect,
|
|
2
|
+
import { useState, useEffect, useCallback } from "react";
|
|
3
3
|
import { Box, Text, useInput } from "ink";
|
|
4
|
-
import InkSpinner from "ink-spinner";
|
|
5
4
|
import { BorderBox, Spinner, useTheme } from "./common/index.js";
|
|
6
5
|
import { getLoadBalancerAddress, getRequiredDNSRecords, checkDNSRecord, isDNSComplete, } from "../lib/dns.js";
|
|
7
|
-
export function DNSWaitScreen({ domain, selfHostedSupabase, namespace, onComplete, onSkip, }) {
|
|
6
|
+
export function DNSWaitScreen({ domain, selfHostedSupabase, builtInObservability = false, observabilityHostname, valkeyAdminIngress = false, valkeyAdminHostname, namespace, onComplete, onSkip, }) {
|
|
8
7
|
const { colors } = useTheme();
|
|
9
8
|
const [status, setStatus] = useState("loading-lb");
|
|
10
9
|
const [loadBalancer, setLoadBalancer] = useState(null);
|
|
11
10
|
const [records, setRecords] = useState([]);
|
|
12
11
|
const [error, setError] = useState(null);
|
|
13
|
-
const [
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
12
|
+
const [hasChecked, setHasChecked] = useState(false);
|
|
13
|
+
const checkRecords = useCallback(async () => {
|
|
14
|
+
if (status !== "idle" || records.length === 0)
|
|
15
|
+
return;
|
|
16
|
+
setStatus("checking");
|
|
17
|
+
setHasChecked(true);
|
|
18
|
+
const updatedRecords = await Promise.all(records.map(async (record) => {
|
|
19
|
+
if (record.verified)
|
|
20
|
+
return record;
|
|
21
|
+
const result = await checkDNSRecord(record.hostname, record.target);
|
|
22
|
+
return {
|
|
23
|
+
...record,
|
|
24
|
+
verified: result.resolved && result.matchesTarget,
|
|
25
|
+
};
|
|
26
|
+
}));
|
|
27
|
+
setRecords(updatedRecords);
|
|
28
|
+
setStatus(isDNSComplete(updatedRecords) ? "complete" : "idle");
|
|
29
|
+
}, [records, status]);
|
|
17
30
|
useInput((input, key) => {
|
|
18
31
|
if (key.escape || input.toLowerCase() === "s") {
|
|
19
32
|
onSkip?.();
|
|
@@ -21,6 +34,9 @@ export function DNSWaitScreen({ domain, selfHostedSupabase, namespace, onComplet
|
|
|
21
34
|
if (key.return && status === "complete") {
|
|
22
35
|
onComplete();
|
|
23
36
|
}
|
|
37
|
+
else if (key.return && status === "idle") {
|
|
38
|
+
void checkRecords();
|
|
39
|
+
}
|
|
24
40
|
});
|
|
25
41
|
// Fetch load balancer address
|
|
26
42
|
useEffect(() => {
|
|
@@ -32,42 +48,32 @@ export function DNSWaitScreen({ domain, selfHostedSupabase, namespace, onComplet
|
|
|
32
48
|
return;
|
|
33
49
|
}
|
|
34
50
|
setLoadBalancer({ address: result.address, type: result.type });
|
|
35
|
-
const dnsRecords = getRequiredDNSRecords(domain, result.address, result.type, selfHostedSupabase);
|
|
51
|
+
const dnsRecords = getRequiredDNSRecords(domain, result.address, result.type, selfHostedSupabase, builtInObservability, observabilityHostname, valkeyAdminIngress, valkeyAdminHostname);
|
|
36
52
|
setRecords(dnsRecords);
|
|
37
|
-
setStatus("
|
|
53
|
+
setStatus("idle");
|
|
38
54
|
};
|
|
39
55
|
fetchLB();
|
|
40
|
-
}, [
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
if (record.verified)
|
|
50
|
-
return record;
|
|
51
|
-
const result = await checkDNSRecord(record.hostname, record.target);
|
|
52
|
-
return {
|
|
53
|
-
...record,
|
|
54
|
-
verified: result.resolved && result.matchesTarget,
|
|
55
|
-
};
|
|
56
|
-
}));
|
|
57
|
-
setRecords(updatedRecords);
|
|
58
|
-
setPollCount((c) => c + 1);
|
|
59
|
-
if (isDNSComplete(updatedRecords)) {
|
|
60
|
-
setStatus("complete");
|
|
61
|
-
}
|
|
62
|
-
};
|
|
63
|
-
// Initial check
|
|
64
|
-
pollDNS();
|
|
65
|
-
// Poll every 5 seconds
|
|
66
|
-
const interval = setInterval(pollDNS, 5000);
|
|
67
|
-
return () => clearInterval(interval);
|
|
68
|
-
}, [status]);
|
|
56
|
+
}, [
|
|
57
|
+
domain,
|
|
58
|
+
selfHostedSupabase,
|
|
59
|
+
builtInObservability,
|
|
60
|
+
observabilityHostname,
|
|
61
|
+
valkeyAdminIngress,
|
|
62
|
+
valkeyAdminHostname,
|
|
63
|
+
namespace,
|
|
64
|
+
]);
|
|
69
65
|
const verifiedCount = records.filter((r) => r.verified).length;
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
66
|
+
const footerText = status === "complete"
|
|
67
|
+
? "Enter to continue"
|
|
68
|
+
: status === "checking"
|
|
69
|
+
? "Checking DNS records..."
|
|
70
|
+
: hasChecked
|
|
71
|
+
? "We couldn't find one or more DNS records. Please verify they exist and press Enter to try again."
|
|
72
|
+
: "Press Enter once you've created the DNS records • S or Esc to skip DNS validation";
|
|
73
|
+
return (_jsxs(BorderBox, { title: "Configure DNS Records", children: [status === "loading-lb" && (_jsx(Box, { flexDirection: "column", marginY: 1, children: _jsx(Spinner, { label: "Getting load balancer address..." }) })), status === "error" && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { color: colors.error, bold: true, children: "\u2717 Error" }), _jsx(Text, { color: colors.error, children: error }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, children: "Press Esc to skip DNS validation" }) })] })), (status === "idle" || status === "checking" || status === "complete") &&
|
|
74
|
+
loadBalancer && (_jsxs(Box, { flexDirection: "column", marginY: 1, children: [_jsx(Text, { bold: true, children: "Your load balancer address:" }), _jsx(Box, { marginY: 1, children: _jsx(Text, { color: colors.accent, bold: true, children: loadBalancer.address }) }), _jsx(Text, { children: "Please add the following DNS records:" }), _jsx(Box, { marginTop: 1, flexDirection: "column", children: records.map((record, idx) => (_jsxs(Box, { flexDirection: "column", marginBottom: 1, children: [_jsxs(Box, { children: [record.verified ? (_jsx(Text, { color: colors.success, children: "\u2713" })) : hasChecked ? (_jsx(Text, { color: colors.warning, children: "\u25CB" })) : (_jsx(Text, { color: colors.muted, children: "\u25CB" })), _jsx(Text, { children: " " }), _jsx(Text, { color: record.verified
|
|
75
|
+
? colors.success
|
|
76
|
+
: hasChecked
|
|
77
|
+
? colors.warning
|
|
78
|
+
: undefined, children: record.hostname })] }), _jsxs(Box, { marginLeft: 2, children: [_jsx(Text, { color: colors.accent, children: record.type }), _jsx(Text, { color: colors.muted, children: " \u2192 " }), _jsx(Text, { color: colors.accent, children: record.target })] })] }, idx))) }), _jsx(Box, { marginTop: 2, children: status === "complete" ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.success, bold: true, children: "\u2713 All DNS records verified!" }), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, children: "Press Enter to continue with TLS setup" }) })] })) : status === "checking" ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Box, { children: _jsx(Spinner, { label: "Checking DNS records..." }) }), _jsx(Box, { marginTop: 1, children: _jsxs(Text, { color: colors.muted, dimColor: true, children: [verifiedCount, "/", records.length, " records verified"] }) })] })) : hasChecked ? (_jsxs(Box, { flexDirection: "column", children: [_jsx(Text, { color: colors.warning, children: "We couldn't find one or more DNS records." }), _jsx(Text, { color: colors.muted, children: "Please verify they exist and press Enter to try again." })] })) : (_jsx(Box, { flexDirection: "column", children: _jsx(Text, { color: colors.muted, children: "Press Enter once you've created the DNS records." }) })) })] })), _jsx(Box, { marginTop: 1, children: _jsx(Text, { color: colors.muted, dimColor: true, children: footerText }) })] }));
|
|
73
79
|
}
|