@replicated/portal-components 0.0.2 → 0.0.3
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/components/metadata/registry.json +83 -2
- package/components/metadata/registry.md +27 -2
- package/dist/actions/index.d.mts +566 -3
- package/dist/actions/index.d.ts +566 -3
- package/dist/actions/index.js +1853 -12
- package/dist/actions/index.js.map +1 -1
- package/dist/airgap-instances.d.mts +26 -0
- package/dist/airgap-instances.d.ts +26 -0
- package/dist/airgap-instances.js +354 -0
- package/dist/airgap-instances.js.map +1 -0
- package/dist/error-page.d.mts +14 -0
- package/dist/error-page.d.ts +14 -0
- package/dist/error-page.js +153 -0
- package/dist/error-page.js.map +1 -0
- package/dist/error.d.mts +15 -0
- package/dist/error.d.ts +15 -0
- package/dist/error.js +144 -0
- package/dist/error.js.map +1 -0
- package/dist/esm/actions/index.js +1816 -13
- package/dist/esm/actions/index.js.map +1 -1
- package/dist/esm/airgap-instances.js +352 -0
- package/dist/esm/airgap-instances.js.map +1 -0
- package/dist/esm/error-page.js +151 -0
- package/dist/esm/error-page.js.map +1 -0
- package/dist/esm/error.js +142 -0
- package/dist/esm/error.js.map +1 -0
- package/dist/esm/helm-install-wizard.js +1007 -0
- package/dist/esm/helm-install-wizard.js.map +1 -0
- package/dist/esm/index.js +2232 -155
- package/dist/esm/index.js.map +1 -1
- package/dist/esm/install-actions.js +746 -0
- package/dist/esm/install-actions.js.map +1 -0
- package/dist/esm/install-card.js +115 -0
- package/dist/esm/install-card.js.map +1 -0
- package/dist/esm/install-targets.js +48 -0
- package/dist/esm/install-targets.js.map +1 -0
- package/dist/esm/instance-card.js +197 -0
- package/dist/esm/instance-card.js.map +1 -0
- package/dist/esm/join-team.js +218 -0
- package/dist/esm/join-team.js.map +1 -0
- package/dist/esm/license-card.js +131 -0
- package/dist/esm/license-card.js.map +1 -0
- package/dist/esm/license-details.js +667 -0
- package/dist/esm/license-details.js.map +1 -0
- package/dist/esm/linux-install-wizard.js +1083 -0
- package/dist/esm/linux-install-wizard.js.map +1 -0
- package/dist/esm/login.js +261 -0
- package/dist/esm/login.js.map +1 -0
- package/dist/esm/online-instance-list.js +287 -0
- package/dist/esm/online-instance-list.js.map +1 -0
- package/dist/esm/pending-installations.js +235 -0
- package/dist/esm/pending-installations.js.map +1 -0
- package/dist/esm/release-history-panel.js +100 -0
- package/dist/esm/release-history-panel.js.map +1 -0
- package/dist/esm/release-notes-card.js +23 -0
- package/dist/esm/release-notes-card.js.map +1 -0
- package/dist/esm/security-card.js +700 -0
- package/dist/esm/security-card.js.map +1 -0
- package/dist/esm/support-bundle-collection-card.js +170 -0
- package/dist/esm/support-bundle-collection-card.js.map +1 -0
- package/dist/esm/support-bundles-card.js +306 -0
- package/dist/esm/support-bundles-card.js.map +1 -0
- package/dist/esm/support-card.js +305 -0
- package/dist/esm/support-card.js.map +1 -0
- package/dist/esm/team-selection.js +117 -0
- package/dist/esm/team-selection.js.map +1 -0
- package/dist/esm/team-settings-card.js +78 -0
- package/dist/esm/team-settings-card.js.map +1 -0
- package/dist/esm/team-settings.js +136 -0
- package/dist/esm/team-settings.js.map +1 -0
- package/dist/esm/top-nav-user-menu.js +173 -0
- package/dist/esm/top-nav-user-menu.js.map +1 -0
- package/dist/esm/top-nav.js +398 -0
- package/dist/esm/top-nav.js.map +1 -0
- package/dist/esm/update-layout.js +405 -0
- package/dist/esm/update-layout.js.map +1 -0
- package/dist/esm/updates-card.js +85 -0
- package/dist/esm/updates-card.js.map +1 -0
- package/dist/esm/upload-support-bundle-modal.js +143 -0
- package/dist/esm/upload-support-bundle-modal.js.map +1 -0
- package/dist/esm/user-settings-card.js +21 -0
- package/dist/esm/user-settings-card.js.map +1 -0
- package/dist/esm/user-settings.js +368 -0
- package/dist/esm/user-settings.js.map +1 -0
- package/dist/esm/utils/index.js +170 -0
- package/dist/esm/utils/index.js.map +1 -0
- package/dist/helm-install-wizard.d.mts +38 -0
- package/dist/helm-install-wizard.d.ts +38 -0
- package/dist/helm-install-wizard.js +1011 -0
- package/dist/helm-install-wizard.js.map +1 -0
- package/dist/index.d.mts +11 -27
- package/dist/index.d.ts +11 -27
- package/dist/index.js +2258 -154
- package/dist/index.js.map +1 -1
- package/dist/install-B19AaKF_.d.mts +233 -0
- package/dist/install-Bi1qJ8Bu.d.ts +233 -0
- package/dist/install-actions.d.mts +141 -0
- package/dist/install-actions.d.ts +141 -0
- package/dist/install-actions.js +765 -0
- package/dist/install-actions.js.map +1 -0
- package/dist/install-card.d.mts +15 -0
- package/dist/install-card.d.ts +15 -0
- package/dist/install-card.js +117 -0
- package/dist/install-card.js.map +1 -0
- package/dist/install-targets.d.mts +19 -0
- package/dist/install-targets.d.ts +19 -0
- package/dist/install-targets.js +50 -0
- package/dist/install-targets.js.map +1 -0
- package/dist/instance-card.d.mts +22 -0
- package/dist/instance-card.d.ts +22 -0
- package/dist/instance-card.js +199 -0
- package/dist/instance-card.js.map +1 -0
- package/dist/join-team.d.mts +30 -0
- package/dist/join-team.d.ts +30 -0
- package/dist/join-team.js +220 -0
- package/dist/join-team.js.map +1 -0
- package/dist/license-card.d.mts +15 -0
- package/dist/license-card.d.ts +15 -0
- package/dist/license-card.js +133 -0
- package/dist/license-card.js.map +1 -0
- package/dist/license-details.d.mts +10 -0
- package/dist/license-details.d.ts +10 -0
- package/dist/license-details.js +669 -0
- package/dist/license-details.js.map +1 -0
- package/dist/linux-install-wizard.d.mts +66 -0
- package/dist/linux-install-wizard.d.ts +66 -0
- package/dist/linux-install-wizard.js +1093 -0
- package/dist/linux-install-wizard.js.map +1 -0
- package/dist/login.d.mts +37 -0
- package/dist/login.d.ts +37 -0
- package/dist/login.js +263 -0
- package/dist/login.js.map +1 -0
- package/dist/online-instance-list.d.mts +22 -0
- package/dist/online-instance-list.d.ts +22 -0
- package/dist/online-instance-list.js +289 -0
- package/dist/online-instance-list.js.map +1 -0
- package/dist/pending-installations.d.mts +15 -0
- package/dist/pending-installations.d.ts +15 -0
- package/dist/pending-installations.js +237 -0
- package/dist/pending-installations.js.map +1 -0
- package/dist/release-history-panel.d.mts +22 -0
- package/dist/release-history-panel.d.ts +22 -0
- package/dist/release-history-panel.js +102 -0
- package/dist/release-history-panel.js.map +1 -0
- package/dist/release-notes-card.d.mts +13 -0
- package/dist/release-notes-card.d.ts +13 -0
- package/dist/release-notes-card.js +25 -0
- package/dist/release-notes-card.js.map +1 -0
- package/dist/security-card.d.mts +73 -0
- package/dist/security-card.d.ts +73 -0
- package/dist/security-card.js +702 -0
- package/dist/security-card.js.map +1 -0
- package/dist/styles.css +1877 -194
- package/dist/support-bundle-collection-card.d.mts +20 -0
- package/dist/support-bundle-collection-card.d.ts +20 -0
- package/dist/support-bundle-collection-card.js +172 -0
- package/dist/support-bundle-collection-card.js.map +1 -0
- package/dist/support-bundles-card.d.mts +19 -0
- package/dist/support-bundles-card.d.ts +19 -0
- package/dist/support-bundles-card.js +308 -0
- package/dist/support-bundles-card.js.map +1 -0
- package/dist/support-card.d.mts +8 -0
- package/dist/support-card.d.ts +8 -0
- package/dist/support-card.js +307 -0
- package/dist/support-card.js.map +1 -0
- package/dist/team-selection.d.mts +23 -0
- package/dist/team-selection.d.ts +23 -0
- package/dist/team-selection.js +119 -0
- package/dist/team-selection.js.map +1 -0
- package/dist/team-settings-card-Dq1d9b5c.d.mts +14 -0
- package/dist/team-settings-card-Dq1d9b5c.d.ts +14 -0
- package/dist/team-settings-card.d.mts +2 -0
- package/dist/team-settings-card.d.ts +2 -0
- package/dist/team-settings-card.js +80 -0
- package/dist/team-settings-card.js.map +1 -0
- package/dist/team-settings.d.mts +25 -0
- package/dist/team-settings.d.ts +25 -0
- package/dist/team-settings.js +138 -0
- package/dist/team-settings.js.map +1 -0
- package/dist/top-nav-0mb1K_H0.d.mts +32 -0
- package/dist/top-nav-0mb1K_H0.d.ts +32 -0
- package/dist/top-nav-user-menu.d.mts +18 -0
- package/dist/top-nav-user-menu.d.ts +18 -0
- package/dist/top-nav-user-menu.js +175 -0
- package/dist/top-nav-user-menu.js.map +1 -0
- package/dist/top-nav.d.mts +3 -0
- package/dist/top-nav.d.ts +3 -0
- package/dist/top-nav.js +400 -0
- package/dist/top-nav.js.map +1 -0
- package/dist/update-layout.d.mts +12 -0
- package/dist/update-layout.d.ts +12 -0
- package/dist/update-layout.js +407 -0
- package/dist/update-layout.js.map +1 -0
- package/dist/updates-card-BbubBrVR.d.mts +18 -0
- package/dist/updates-card-BbubBrVR.d.ts +18 -0
- package/dist/updates-card.d.mts +2 -0
- package/dist/updates-card.d.ts +2 -0
- package/dist/updates-card.js +87 -0
- package/dist/updates-card.js.map +1 -0
- package/dist/upload-support-bundle-modal.d.mts +19 -0
- package/dist/upload-support-bundle-modal.d.ts +19 -0
- package/dist/upload-support-bundle-modal.js +145 -0
- package/dist/upload-support-bundle-modal.js.map +1 -0
- package/dist/user-settings-card.d.mts +8 -0
- package/dist/user-settings-card.d.ts +8 -0
- package/dist/user-settings-card.js +23 -0
- package/dist/user-settings-card.js.map +1 -0
- package/dist/user-settings.d.mts +47 -0
- package/dist/user-settings.d.ts +47 -0
- package/dist/user-settings.js +370 -0
- package/dist/user-settings.js.map +1 -0
- package/dist/utils/index.d.mts +70 -0
- package/dist/utils/index.d.ts +70 -0
- package/dist/utils/index.js +177 -0
- package/dist/utils/index.js.map +1 -0
- package/package.json +163 -3
|
@@ -0,0 +1,1083 @@
|
|
|
1
|
+
import { cache, useState, useRef, useMemo, useEffect, useCallback } from 'react';
|
|
2
|
+
import { jsxs, jsx } from 'react/jsx-runtime';
|
|
3
|
+
|
|
4
|
+
/**
|
|
5
|
+
* Enterprise Portal Components
|
|
6
|
+
* This file is generated by tsup. Do not edit manually.
|
|
7
|
+
*/
|
|
8
|
+
|
|
9
|
+
var LINUX_INSTALL_SERVICE_ACCOUNT_KEY = "linux_install_service_account";
|
|
10
|
+
var LINUX_INSTALL_OPTIONS_KEY = "linux_install_options";
|
|
11
|
+
var navigateTo = (href) => {
|
|
12
|
+
try {
|
|
13
|
+
if (typeof window === "undefined") {
|
|
14
|
+
return;
|
|
15
|
+
}
|
|
16
|
+
window.location.assign(href);
|
|
17
|
+
} catch (error) {
|
|
18
|
+
console.error("[linux-install-wizard] navigation failed", error);
|
|
19
|
+
}
|
|
20
|
+
};
|
|
21
|
+
var copyToClipboard = async (text) => {
|
|
22
|
+
try {
|
|
23
|
+
await navigator.clipboard.writeText(text);
|
|
24
|
+
return true;
|
|
25
|
+
} catch {
|
|
26
|
+
return false;
|
|
27
|
+
}
|
|
28
|
+
};
|
|
29
|
+
var StepIndicator = ({ step }) => /* @__PURE__ */ jsxs("div", { className: "flex items-center justify-center gap-3", children: [
|
|
30
|
+
/* @__PURE__ */ jsx(
|
|
31
|
+
"div",
|
|
32
|
+
{
|
|
33
|
+
className: `flex h-10 w-10 items-center justify-center rounded-full border-2 ${step > 1 ? "border-gray-900 bg-gray-900 text-white" : "border-indigo-500"}`,
|
|
34
|
+
children: step > 1 ? /* @__PURE__ */ jsx(
|
|
35
|
+
"svg",
|
|
36
|
+
{
|
|
37
|
+
xmlns: "http://www.w3.org/2000/svg",
|
|
38
|
+
viewBox: "0 0 16 16",
|
|
39
|
+
className: "h-3.5 w-3.5",
|
|
40
|
+
fill: "none",
|
|
41
|
+
stroke: "currentColor",
|
|
42
|
+
strokeWidth: "2",
|
|
43
|
+
children: /* @__PURE__ */ jsx("path", { d: "m3.5 8 3 3 6-6" })
|
|
44
|
+
}
|
|
45
|
+
) : /* @__PURE__ */ jsx("span", { className: "h-2.5 w-2.5 rounded-full bg-indigo-500" })
|
|
46
|
+
}
|
|
47
|
+
),
|
|
48
|
+
/* @__PURE__ */ jsx("div", { className: `h-0.5 w-12 ${step > 1 ? "bg-gray-900" : "bg-gray-200"}` }),
|
|
49
|
+
/* @__PURE__ */ jsx(
|
|
50
|
+
"div",
|
|
51
|
+
{
|
|
52
|
+
className: `flex h-10 w-10 items-center justify-center rounded-full border-2 ${step === 2 ? "border-gray-900" : "border-gray-200"}`,
|
|
53
|
+
children: step === 2 ? /* @__PURE__ */ jsx("span", { className: "h-2.5 w-2.5 rounded-full bg-gray-900" }) : null
|
|
54
|
+
}
|
|
55
|
+
)
|
|
56
|
+
] });
|
|
57
|
+
var CodeBlock = ({
|
|
58
|
+
command,
|
|
59
|
+
onCopy
|
|
60
|
+
}) => {
|
|
61
|
+
const [copied, setCopied] = useState(false);
|
|
62
|
+
const handleCopy = async () => {
|
|
63
|
+
const success = await copyToClipboard(command);
|
|
64
|
+
if (success) {
|
|
65
|
+
setCopied(true);
|
|
66
|
+
onCopy?.();
|
|
67
|
+
setTimeout(() => setCopied(false), 2e3);
|
|
68
|
+
}
|
|
69
|
+
};
|
|
70
|
+
return /* @__PURE__ */ jsxs("div", { className: "group relative ml-8 mt-2 min-w-0", children: [
|
|
71
|
+
/* @__PURE__ */ jsx("pre", { className: "overflow-x-auto whitespace-pre rounded-lg bg-gray-900 p-4 text-sm text-gray-100", children: /* @__PURE__ */ jsx("code", { className: "block", children: command }) }),
|
|
72
|
+
/* @__PURE__ */ jsx(
|
|
73
|
+
"button",
|
|
74
|
+
{
|
|
75
|
+
type: "button",
|
|
76
|
+
onClick: handleCopy,
|
|
77
|
+
className: "absolute right-2 top-2 rounded bg-gray-700 p-1.5 text-gray-300 opacity-0 transition hover:bg-gray-600 hover:text-white group-hover:opacity-100",
|
|
78
|
+
"aria-label": "Copy to clipboard",
|
|
79
|
+
children: copied ? /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M5 13l4 4L19 7" }) }) : /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", strokeWidth: 2, d: "M8 16H6a2 2 0 01-2-2V6a2 2 0 012-2h8a2 2 0 012 2v2m-6 12h8a2 2 0 002-2v-8a2 2 0 00-2-2h-8a2 2 0 00-2 2v8a2 2 0 002 2z" }) })
|
|
80
|
+
}
|
|
81
|
+
)
|
|
82
|
+
] });
|
|
83
|
+
};
|
|
84
|
+
var VersionDropdown = ({
|
|
85
|
+
releases,
|
|
86
|
+
selectedRelease,
|
|
87
|
+
onSelect,
|
|
88
|
+
isLoading,
|
|
89
|
+
error
|
|
90
|
+
}) => {
|
|
91
|
+
if (isLoading) {
|
|
92
|
+
return /* @__PURE__ */ jsxs("div", { className: "ml-8 flex items-center gap-2 text-sm text-gray-500", children: [
|
|
93
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-indigo-500" }),
|
|
94
|
+
"Loading versions..."
|
|
95
|
+
] });
|
|
96
|
+
}
|
|
97
|
+
if (error) {
|
|
98
|
+
return /* @__PURE__ */ jsxs("div", { className: "ml-8 text-sm text-rose-600", children: [
|
|
99
|
+
"Failed to load versions: ",
|
|
100
|
+
error
|
|
101
|
+
] });
|
|
102
|
+
}
|
|
103
|
+
if (releases.length === 0) {
|
|
104
|
+
return /* @__PURE__ */ jsx("p", { className: "ml-8 text-sm text-gray-500", children: "There is no Embedded Cluster installer in this release." });
|
|
105
|
+
}
|
|
106
|
+
return /* @__PURE__ */ jsxs("div", { className: "ml-8 space-y-2", children: [
|
|
107
|
+
/* @__PURE__ */ jsx("label", { className: "block text-sm text-gray-600", children: "App Version" }),
|
|
108
|
+
/* @__PURE__ */ jsx(
|
|
109
|
+
"select",
|
|
110
|
+
{
|
|
111
|
+
value: selectedRelease?.channelSequence ?? "",
|
|
112
|
+
onChange: (e) => {
|
|
113
|
+
const sequence = parseInt(e.target.value, 10);
|
|
114
|
+
const release = releases.find((r) => r.channelSequence === sequence);
|
|
115
|
+
if (release) {
|
|
116
|
+
onSelect(release);
|
|
117
|
+
}
|
|
118
|
+
},
|
|
119
|
+
className: "portal-select w-full",
|
|
120
|
+
children: releases.map((release) => /* @__PURE__ */ jsxs("option", { value: release.channelSequence, children: [
|
|
121
|
+
release.versionLabel || `Sequence ${release.channelSequence}`,
|
|
122
|
+
release.channelName ? ` (${release.channelName})` : ""
|
|
123
|
+
] }, release.channelSequence))
|
|
124
|
+
}
|
|
125
|
+
)
|
|
126
|
+
] });
|
|
127
|
+
};
|
|
128
|
+
var CheckIcon = () => /* @__PURE__ */ jsx("svg", { className: "h-4 w-4", fill: "none", viewBox: "0 0 24 24", stroke: "currentColor", strokeWidth: 2.5, children: /* @__PURE__ */ jsx("path", { strokeLinecap: "round", strokeLinejoin: "round", d: "M5 13l4 4L19 7" }) });
|
|
129
|
+
var InstallationInstructions = ({
|
|
130
|
+
instructions,
|
|
131
|
+
isLoading,
|
|
132
|
+
completedSteps = {}
|
|
133
|
+
}) => {
|
|
134
|
+
if (isLoading && !instructions?.steps?.length) {
|
|
135
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
136
|
+
/* @__PURE__ */ jsx("h3", { className: "text-lg font-semibold text-gray-900", children: "Installation Instructions" }),
|
|
137
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-sm text-gray-500", children: [
|
|
138
|
+
/* @__PURE__ */ jsx("div", { className: "h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-indigo-500" }),
|
|
139
|
+
"Loading instructions..."
|
|
140
|
+
] })
|
|
141
|
+
] });
|
|
142
|
+
}
|
|
143
|
+
if (!instructions?.steps?.length) {
|
|
144
|
+
return null;
|
|
145
|
+
}
|
|
146
|
+
return /* @__PURE__ */ jsxs("div", { className: `min-w-0 space-y-4 transition-opacity duration-150 ${isLoading ? "opacity-60" : ""}`, children: [
|
|
147
|
+
/* @__PURE__ */ jsxs("h3", { className: "text-lg font-semibold text-gray-900", children: [
|
|
148
|
+
"Installation Instructions",
|
|
149
|
+
isLoading && /* @__PURE__ */ jsx("span", { className: "ml-2 inline-block h-4 w-4 animate-spin rounded-full border-2 border-gray-300 border-t-indigo-500" })
|
|
150
|
+
] }),
|
|
151
|
+
/* @__PURE__ */ jsx("ol", { className: "min-w-0 space-y-6 text-sm text-gray-700", children: instructions.steps.map((step, index) => {
|
|
152
|
+
const completableStepNames = ["download_assets", "install"];
|
|
153
|
+
const canComplete = completableStepNames.includes(step.step_name);
|
|
154
|
+
const isCompleted = canComplete && completedSteps[step.step_name];
|
|
155
|
+
return /* @__PURE__ */ jsxs("li", { className: "space-y-2", children: [
|
|
156
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2", children: [
|
|
157
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-indigo-100 font-semibold text-indigo-500", children: index + 2 }),
|
|
158
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900", children: step.title }),
|
|
159
|
+
canComplete && /* @__PURE__ */ jsx(
|
|
160
|
+
"span",
|
|
161
|
+
{
|
|
162
|
+
className: `flex h-5 w-5 items-center justify-center rounded-full ${isCompleted ? "bg-green-500 text-white" : "bg-gray-200 text-gray-400"}`,
|
|
163
|
+
children: /* @__PURE__ */ jsx(CheckIcon, {})
|
|
164
|
+
}
|
|
165
|
+
),
|
|
166
|
+
isCompleted && /* @__PURE__ */ jsx("span", { className: "text-xs text-green-600", children: "Completed" })
|
|
167
|
+
] }),
|
|
168
|
+
step.description && /* @__PURE__ */ jsx("p", { className: "ml-8 text-gray-500", children: step.description }),
|
|
169
|
+
step.commands.map((command, cmdIndex) => /* @__PURE__ */ jsx(CodeBlock, { command }, cmdIndex))
|
|
170
|
+
] }, step.step_number);
|
|
171
|
+
}) })
|
|
172
|
+
] });
|
|
173
|
+
};
|
|
174
|
+
var LinuxInstallWizard = ({
|
|
175
|
+
token,
|
|
176
|
+
createServiceAccountAction,
|
|
177
|
+
fetchChannelReleasesAction,
|
|
178
|
+
createInstallOptionsAction,
|
|
179
|
+
getInstallOptionsAction,
|
|
180
|
+
updateInstallOptionsAction,
|
|
181
|
+
onStepChange,
|
|
182
|
+
onNetworkChange,
|
|
183
|
+
onInstallOptionsIdChange,
|
|
184
|
+
initialStep,
|
|
185
|
+
initialNetwork,
|
|
186
|
+
initialInstallOptionsId,
|
|
187
|
+
initialInstallOptionsData,
|
|
188
|
+
initialChannelReleases
|
|
189
|
+
}) => {
|
|
190
|
+
const [step, setStep] = useState(initialStep ?? 1);
|
|
191
|
+
const [instanceName, setInstanceName] = useState(initialInstallOptionsData?.instance_name ?? "");
|
|
192
|
+
const [networkAvailability, setNetworkAvailability] = useState(initialNetwork ?? "online");
|
|
193
|
+
const [adminConsoleUrl, setAdminConsoleUrl] = useState(initialInstallOptionsData?.admin_console_url ?? "https://localhost:30000");
|
|
194
|
+
const [proxyUrl, setProxyUrl] = useState("");
|
|
195
|
+
const [showErrors, setShowErrors] = useState(false);
|
|
196
|
+
const [isCreatingServiceAccount, setIsCreatingServiceAccount] = useState(false);
|
|
197
|
+
const [apiError, setApiError] = useState(null);
|
|
198
|
+
const [installOptionsId, setInstallOptionsId] = useState(initialInstallOptionsId ?? null);
|
|
199
|
+
const [serviceAccountId, setServiceAccountId] = useState(initialInstallOptionsData?.service_account_id ?? null);
|
|
200
|
+
const [originalInstanceName, setOriginalInstanceName] = useState(initialInstallOptionsData?.instance_name ?? null);
|
|
201
|
+
const [releases, setReleases] = useState(initialChannelReleases ?? []);
|
|
202
|
+
const [selectedRelease, setSelectedRelease] = useState(() => {
|
|
203
|
+
if (initialInstallOptionsData?.channel_id && initialInstallOptionsData?.channel_release_sequence && initialChannelReleases) {
|
|
204
|
+
return initialChannelReleases.find(
|
|
205
|
+
(r) => r.channelId === initialInstallOptionsData.channel_id && r.channelSequence === initialInstallOptionsData.channel_release_sequence
|
|
206
|
+
) ?? null;
|
|
207
|
+
}
|
|
208
|
+
return null;
|
|
209
|
+
});
|
|
210
|
+
const [isLoadingReleases, setIsLoadingReleases] = useState(false);
|
|
211
|
+
const [releasesError, setReleasesError] = useState(null);
|
|
212
|
+
const [instructions, setInstructions] = useState(initialInstallOptionsData?.instructions ?? null);
|
|
213
|
+
const [isLoadingInstructions, setIsLoadingInstructions] = useState(false);
|
|
214
|
+
const [completedSteps, setCompletedSteps] = useState({});
|
|
215
|
+
const hasLoadedReleases = useRef(!!initialChannelReleases?.length);
|
|
216
|
+
const hasResumedInstallation = useRef(!!initialInstallOptionsData);
|
|
217
|
+
const lastUpdateRef = useRef(
|
|
218
|
+
initialInstallOptionsData?.channel_id && initialInstallOptionsData?.channel_release_sequence ? { channelId: initialInstallOptionsData.channel_id, sequence: initialInstallOptionsData.channel_release_sequence } : {}
|
|
219
|
+
);
|
|
220
|
+
const embeddedClusterReleases = useMemo(() => {
|
|
221
|
+
return releases.filter((r) => r.installationTypes?.embeddedCluster?.version);
|
|
222
|
+
}, [releases]);
|
|
223
|
+
const prevInitialStepRef = useRef(initialStep);
|
|
224
|
+
useEffect(() => {
|
|
225
|
+
if (initialStep !== void 0 && initialStep !== prevInitialStepRef.current) {
|
|
226
|
+
setStep(initialStep);
|
|
227
|
+
}
|
|
228
|
+
prevInitialStepRef.current = initialStep;
|
|
229
|
+
}, [initialStep]);
|
|
230
|
+
useEffect(() => {
|
|
231
|
+
if (initialNetwork !== void 0 && initialNetwork !== networkAvailability) {
|
|
232
|
+
setNetworkAvailability(initialNetwork);
|
|
233
|
+
}
|
|
234
|
+
}, [initialNetwork, networkAvailability]);
|
|
235
|
+
useEffect(() => {
|
|
236
|
+
onStepChange?.(step);
|
|
237
|
+
}, [step, onStepChange]);
|
|
238
|
+
useEffect(() => {
|
|
239
|
+
onNetworkChange?.(networkAvailability);
|
|
240
|
+
}, [networkAvailability, onNetworkChange]);
|
|
241
|
+
useEffect(() => {
|
|
242
|
+
onInstallOptionsIdChange?.(installOptionsId);
|
|
243
|
+
}, [installOptionsId, onInstallOptionsIdChange]);
|
|
244
|
+
useEffect(() => {
|
|
245
|
+
if (step !== 2 || !fetchChannelReleasesAction || hasLoadedReleases.current) {
|
|
246
|
+
return;
|
|
247
|
+
}
|
|
248
|
+
const loadReleases = async () => {
|
|
249
|
+
setIsLoadingReleases(true);
|
|
250
|
+
setReleasesError(null);
|
|
251
|
+
try {
|
|
252
|
+
const result = await fetchChannelReleasesAction(token);
|
|
253
|
+
setReleases(result.channelReleases || []);
|
|
254
|
+
hasLoadedReleases.current = true;
|
|
255
|
+
const ecReleases = (result.channelReleases || []).filter(
|
|
256
|
+
(r) => r.installationTypes?.embeddedCluster?.version
|
|
257
|
+
);
|
|
258
|
+
const firstRelease = ecReleases[0];
|
|
259
|
+
if (firstRelease && !selectedRelease) {
|
|
260
|
+
setSelectedRelease(firstRelease);
|
|
261
|
+
}
|
|
262
|
+
} catch (error) {
|
|
263
|
+
console.error("[linux-install-wizard] Failed to load releases", error);
|
|
264
|
+
setReleasesError(error instanceof Error ? error.message : "Failed to load releases");
|
|
265
|
+
} finally {
|
|
266
|
+
setIsLoadingReleases(false);
|
|
267
|
+
}
|
|
268
|
+
};
|
|
269
|
+
loadReleases();
|
|
270
|
+
}, [step, token, fetchChannelReleasesAction, selectedRelease]);
|
|
271
|
+
const hasAutoSelectedRelease = useRef(false);
|
|
272
|
+
useEffect(() => {
|
|
273
|
+
if (hasAutoSelectedRelease.current || selectedRelease) {
|
|
274
|
+
return;
|
|
275
|
+
}
|
|
276
|
+
const firstRelease = embeddedClusterReleases[0];
|
|
277
|
+
if (step === 2 && firstRelease) {
|
|
278
|
+
setSelectedRelease(firstRelease);
|
|
279
|
+
hasAutoSelectedRelease.current = true;
|
|
280
|
+
}
|
|
281
|
+
}, [step, embeddedClusterReleases, selectedRelease]);
|
|
282
|
+
useEffect(() => {
|
|
283
|
+
if (!selectedRelease || !installOptionsId || !updateInstallOptionsAction) {
|
|
284
|
+
return;
|
|
285
|
+
}
|
|
286
|
+
const channelId = selectedRelease.channelId;
|
|
287
|
+
const sequence = selectedRelease.channelSequence;
|
|
288
|
+
if (lastUpdateRef.current.channelId === channelId && lastUpdateRef.current.sequence === sequence) {
|
|
289
|
+
return;
|
|
290
|
+
}
|
|
291
|
+
const updateOptions = async () => {
|
|
292
|
+
setIsLoadingInstructions(true);
|
|
293
|
+
try {
|
|
294
|
+
const result = await updateInstallOptionsAction({
|
|
295
|
+
token,
|
|
296
|
+
installOptionsId,
|
|
297
|
+
channelId,
|
|
298
|
+
channelReleaseSequence: sequence,
|
|
299
|
+
includeInstructions: true,
|
|
300
|
+
proxyUrl: networkAvailability === "proxy" ? proxyUrl : void 0
|
|
301
|
+
});
|
|
302
|
+
lastUpdateRef.current = { channelId, sequence };
|
|
303
|
+
if (result.instructions) {
|
|
304
|
+
setInstructions(result.instructions);
|
|
305
|
+
}
|
|
306
|
+
} catch (error) {
|
|
307
|
+
console.error("[linux-install-wizard] Failed to update install options", error);
|
|
308
|
+
setApiError(error instanceof Error ? error.message : "Failed to update install options");
|
|
309
|
+
} finally {
|
|
310
|
+
setIsLoadingInstructions(false);
|
|
311
|
+
}
|
|
312
|
+
};
|
|
313
|
+
updateOptions();
|
|
314
|
+
}, [selectedRelease, installOptionsId, token, updateInstallOptionsAction, networkAvailability, proxyUrl]);
|
|
315
|
+
useEffect(() => {
|
|
316
|
+
if (hasResumedInstallation.current) {
|
|
317
|
+
return;
|
|
318
|
+
}
|
|
319
|
+
if (!initialInstallOptionsId || !getInstallOptionsAction || step !== 2) {
|
|
320
|
+
return;
|
|
321
|
+
}
|
|
322
|
+
hasResumedInstallation.current = true;
|
|
323
|
+
const resumeInstallation = async () => {
|
|
324
|
+
setIsLoadingInstructions(true);
|
|
325
|
+
try {
|
|
326
|
+
const result = await getInstallOptionsAction({
|
|
327
|
+
token,
|
|
328
|
+
installOptionsId: initialInstallOptionsId,
|
|
329
|
+
includeInstructions: true,
|
|
330
|
+
proxyUrl: networkAvailability === "proxy" ? proxyUrl : void 0
|
|
331
|
+
});
|
|
332
|
+
if (result.instance_name) {
|
|
333
|
+
setInstanceName(result.instance_name);
|
|
334
|
+
}
|
|
335
|
+
if (result.service_account_id) {
|
|
336
|
+
setServiceAccountId(result.service_account_id);
|
|
337
|
+
}
|
|
338
|
+
if (result.instructions) {
|
|
339
|
+
setInstructions(result.instructions);
|
|
340
|
+
}
|
|
341
|
+
if (result.admin_console_url) {
|
|
342
|
+
setAdminConsoleUrl(result.admin_console_url);
|
|
343
|
+
}
|
|
344
|
+
if (result.channel_id && result.channel_release_sequence) {
|
|
345
|
+
const matchingRelease = releases.find(
|
|
346
|
+
(r) => r.channelId === result.channel_id && r.channelSequence === result.channel_release_sequence
|
|
347
|
+
);
|
|
348
|
+
if (matchingRelease) {
|
|
349
|
+
setSelectedRelease(matchingRelease);
|
|
350
|
+
lastUpdateRef.current = {
|
|
351
|
+
channelId: result.channel_id,
|
|
352
|
+
sequence: result.channel_release_sequence
|
|
353
|
+
};
|
|
354
|
+
}
|
|
355
|
+
}
|
|
356
|
+
} catch (error) {
|
|
357
|
+
console.error("[linux-install-wizard] Failed to resume installation", error);
|
|
358
|
+
setApiError(error instanceof Error ? error.message : "Failed to resume installation");
|
|
359
|
+
} finally {
|
|
360
|
+
setIsLoadingInstructions(false);
|
|
361
|
+
}
|
|
362
|
+
};
|
|
363
|
+
resumeInstallation();
|
|
364
|
+
}, [initialInstallOptionsId, getInstallOptionsAction, token, step, releases, networkAvailability, proxyUrl]);
|
|
365
|
+
useEffect(() => {
|
|
366
|
+
if (step !== 2 || !installOptionsId || !getInstallOptionsAction) {
|
|
367
|
+
return;
|
|
368
|
+
}
|
|
369
|
+
if (completedSteps["download_assets"] && completedSteps["install"]) {
|
|
370
|
+
return;
|
|
371
|
+
}
|
|
372
|
+
const pollInterval = setInterval(async () => {
|
|
373
|
+
try {
|
|
374
|
+
const result = await getInstallOptionsAction({
|
|
375
|
+
token,
|
|
376
|
+
installOptionsId,
|
|
377
|
+
includeInstructions: false
|
|
378
|
+
// We don't need instructions for status polling
|
|
379
|
+
});
|
|
380
|
+
const newCompletedSteps = {};
|
|
381
|
+
if (result.assets_downloaded_at) {
|
|
382
|
+
newCompletedSteps["download_assets"] = true;
|
|
383
|
+
}
|
|
384
|
+
if (result.installation_completed_at) {
|
|
385
|
+
newCompletedSteps["install"] = true;
|
|
386
|
+
}
|
|
387
|
+
if (newCompletedSteps["download_assets"] !== completedSteps["download_assets"] || newCompletedSteps["install"] !== completedSteps["install"]) {
|
|
388
|
+
setCompletedSteps((prev) => ({ ...prev, ...newCompletedSteps }));
|
|
389
|
+
}
|
|
390
|
+
if (newCompletedSteps["download_assets"] && newCompletedSteps["install"]) {
|
|
391
|
+
clearInterval(pollInterval);
|
|
392
|
+
}
|
|
393
|
+
} catch {
|
|
394
|
+
}
|
|
395
|
+
}, 2e3);
|
|
396
|
+
return () => clearInterval(pollInterval);
|
|
397
|
+
}, [step, installOptionsId, getInstallOptionsAction, token, completedSteps]);
|
|
398
|
+
const handleContinue = async () => {
|
|
399
|
+
console.debug("[linux-install-wizard] handleContinue called, instanceName:", JSON.stringify(instanceName));
|
|
400
|
+
if (!instanceName.trim()) {
|
|
401
|
+
console.debug("[linux-install-wizard] Validation failed: instanceName is empty");
|
|
402
|
+
setShowErrors(true);
|
|
403
|
+
return;
|
|
404
|
+
}
|
|
405
|
+
if (!token) {
|
|
406
|
+
setApiError("Configuration error: authentication token is required");
|
|
407
|
+
console.error("[linux-install-wizard] token prop is required but was not provided");
|
|
408
|
+
return;
|
|
409
|
+
}
|
|
410
|
+
setShowErrors(false);
|
|
411
|
+
setApiError(null);
|
|
412
|
+
setIsCreatingServiceAccount(true);
|
|
413
|
+
try {
|
|
414
|
+
const trimmedInstanceName = instanceName.trim();
|
|
415
|
+
if (serviceAccountId && originalInstanceName === trimmedInstanceName && installOptionsId && updateInstallOptionsAction) {
|
|
416
|
+
console.debug("[linux-install-wizard] Reusing existing service account, updating install options...");
|
|
417
|
+
const firstRelease = embeddedClusterReleases[0];
|
|
418
|
+
const result = await updateInstallOptionsAction({
|
|
419
|
+
token,
|
|
420
|
+
installOptionsId,
|
|
421
|
+
channelId: firstRelease?.channelId,
|
|
422
|
+
channelReleaseSequence: firstRelease?.channelSequence,
|
|
423
|
+
includeInstructions: true
|
|
424
|
+
});
|
|
425
|
+
if (firstRelease) {
|
|
426
|
+
setSelectedRelease(firstRelease);
|
|
427
|
+
lastUpdateRef.current = {
|
|
428
|
+
channelId: firstRelease.channelId,
|
|
429
|
+
sequence: firstRelease.channelSequence
|
|
430
|
+
};
|
|
431
|
+
}
|
|
432
|
+
if (result.instructions) {
|
|
433
|
+
setInstructions(result.instructions);
|
|
434
|
+
}
|
|
435
|
+
console.debug("[linux-install-wizard] Transitioning to step 2 (reused service account)");
|
|
436
|
+
setStep(2);
|
|
437
|
+
return;
|
|
438
|
+
}
|
|
439
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
440
|
+
window.sessionStorage.removeItem(LINUX_INSTALL_SERVICE_ACCOUNT_KEY);
|
|
441
|
+
window.sessionStorage.removeItem(LINUX_INSTALL_OPTIONS_KEY);
|
|
442
|
+
}
|
|
443
|
+
const saData = await createServiceAccountAction(trimmedInstanceName, token);
|
|
444
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
445
|
+
window.sessionStorage.setItem(LINUX_INSTALL_SERVICE_ACCOUNT_KEY, JSON.stringify(saData));
|
|
446
|
+
}
|
|
447
|
+
setServiceAccountId(saData.service_account.id);
|
|
448
|
+
setOriginalInstanceName(trimmedInstanceName);
|
|
449
|
+
if (createInstallOptionsAction) {
|
|
450
|
+
console.debug("[linux-install-wizard] Creating install options...");
|
|
451
|
+
const firstRelease = embeddedClusterReleases[0];
|
|
452
|
+
const installOptionsResult = await createInstallOptionsAction({
|
|
453
|
+
token,
|
|
454
|
+
installType: "linux",
|
|
455
|
+
instanceName: trimmedInstanceName,
|
|
456
|
+
serviceAccountId: saData.service_account.id,
|
|
457
|
+
networkAvailability,
|
|
458
|
+
isMultiNode: false,
|
|
459
|
+
channelId: firstRelease?.channelId,
|
|
460
|
+
channelReleaseSequence: firstRelease?.channelSequence
|
|
461
|
+
});
|
|
462
|
+
console.debug("[linux-install-wizard] Install options result:", installOptionsResult);
|
|
463
|
+
if (firstRelease) {
|
|
464
|
+
setSelectedRelease(firstRelease);
|
|
465
|
+
lastUpdateRef.current = {
|
|
466
|
+
channelId: firstRelease.channelId,
|
|
467
|
+
sequence: firstRelease.channelSequence
|
|
468
|
+
};
|
|
469
|
+
}
|
|
470
|
+
const optionsId = installOptionsResult.install_options?.id ?? installOptionsResult.id;
|
|
471
|
+
if (!optionsId) {
|
|
472
|
+
throw new Error("Install options response did not contain an ID");
|
|
473
|
+
}
|
|
474
|
+
setInstallOptionsId(optionsId);
|
|
475
|
+
if (typeof window !== "undefined" && window.sessionStorage) {
|
|
476
|
+
window.sessionStorage.setItem(LINUX_INSTALL_OPTIONS_KEY, JSON.stringify(installOptionsResult));
|
|
477
|
+
}
|
|
478
|
+
if (installOptionsResult.instructions) {
|
|
479
|
+
setInstructions(installOptionsResult.instructions);
|
|
480
|
+
}
|
|
481
|
+
onInstallOptionsIdChange?.(optionsId);
|
|
482
|
+
}
|
|
483
|
+
console.debug("[linux-install-wizard] Transitioning to step 2");
|
|
484
|
+
setStep(2);
|
|
485
|
+
} catch (error) {
|
|
486
|
+
console.error("[linux-install-wizard] Failed to continue", error);
|
|
487
|
+
const errorMessage = error instanceof Error ? error.message : "Failed to continue";
|
|
488
|
+
if (errorMessage.toLowerCase().includes("already exists")) {
|
|
489
|
+
setApiError("Instance name must be unique. Please choose a different name.");
|
|
490
|
+
} else {
|
|
491
|
+
setApiError(errorMessage);
|
|
492
|
+
}
|
|
493
|
+
} finally {
|
|
494
|
+
setIsCreatingServiceAccount(false);
|
|
495
|
+
}
|
|
496
|
+
};
|
|
497
|
+
const handleBack = () => {
|
|
498
|
+
setApiError(null);
|
|
499
|
+
setShowErrors(false);
|
|
500
|
+
setStep(1);
|
|
501
|
+
};
|
|
502
|
+
const handleFinish = useCallback(async () => {
|
|
503
|
+
if (installOptionsId && updateInstallOptionsAction && adminConsoleUrl) {
|
|
504
|
+
try {
|
|
505
|
+
await updateInstallOptionsAction({
|
|
506
|
+
token,
|
|
507
|
+
installOptionsId,
|
|
508
|
+
adminConsoleUrl
|
|
509
|
+
});
|
|
510
|
+
} catch (error) {
|
|
511
|
+
console.error("[linux-install-wizard] Failed to save admin console URL", error);
|
|
512
|
+
}
|
|
513
|
+
}
|
|
514
|
+
navigateTo("/update");
|
|
515
|
+
}, [installOptionsId, updateInstallOptionsAction, adminConsoleUrl, token]);
|
|
516
|
+
const handleReleaseSelect = useCallback((release) => {
|
|
517
|
+
setSelectedRelease(release);
|
|
518
|
+
}, []);
|
|
519
|
+
const isProxy = networkAvailability === "proxy";
|
|
520
|
+
if (step === 2) {
|
|
521
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
522
|
+
/* @__PURE__ */ jsx(StepIndicator, { step: 2 }),
|
|
523
|
+
/* @__PURE__ */ jsx("div", { className: "overflow-hidden rounded-2xl border border-gray-100 bg-gray-50 p-6", children: /* @__PURE__ */ jsxs("div", { className: "min-w-0 space-y-6", children: [
|
|
524
|
+
/* @__PURE__ */ jsxs("div", { className: "min-w-0", children: [
|
|
525
|
+
/* @__PURE__ */ jsx("h2", { className: "text-xl font-semibold text-gray-900", children: isProxy ? "Linux Single Node Proxy Install" : "Linux Single Node Online Install" }),
|
|
526
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-6 space-y-6", children: [
|
|
527
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
528
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-indigo-500", children: [
|
|
529
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-indigo-100 font-semibold", children: "1" }),
|
|
530
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900", children: "Select a version" })
|
|
531
|
+
] }),
|
|
532
|
+
/* @__PURE__ */ jsx(
|
|
533
|
+
VersionDropdown,
|
|
534
|
+
{
|
|
535
|
+
releases: embeddedClusterReleases,
|
|
536
|
+
selectedRelease,
|
|
537
|
+
onSelect: handleReleaseSelect,
|
|
538
|
+
isLoading: isLoadingReleases,
|
|
539
|
+
error: releasesError
|
|
540
|
+
}
|
|
541
|
+
)
|
|
542
|
+
] }),
|
|
543
|
+
isProxy && /* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
544
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-indigo-500", children: [
|
|
545
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-indigo-100 font-semibold", children: "2" }),
|
|
546
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900", children: "Configure proxy URL" })
|
|
547
|
+
] }),
|
|
548
|
+
/* @__PURE__ */ jsx(
|
|
549
|
+
"input",
|
|
550
|
+
{
|
|
551
|
+
value: proxyUrl,
|
|
552
|
+
onChange: (event) => setProxyUrl(event.target.value),
|
|
553
|
+
placeholder: "Enter proxy URL",
|
|
554
|
+
className: "portal-input ml-8 w-full"
|
|
555
|
+
}
|
|
556
|
+
)
|
|
557
|
+
] }),
|
|
558
|
+
selectedRelease && /* @__PURE__ */ jsx(
|
|
559
|
+
InstallationInstructions,
|
|
560
|
+
{
|
|
561
|
+
instructions,
|
|
562
|
+
isLoading: isLoadingInstructions,
|
|
563
|
+
completedSteps
|
|
564
|
+
}
|
|
565
|
+
),
|
|
566
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-2", children: [
|
|
567
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center gap-2 text-indigo-500", children: [
|
|
568
|
+
/* @__PURE__ */ jsx("span", { className: "flex h-6 w-6 items-center justify-center rounded-full bg-indigo-100 font-semibold", children: (instructions?.steps?.length ?? 0) + (isProxy ? 3 : 2) }),
|
|
569
|
+
/* @__PURE__ */ jsx("span", { className: "font-medium text-gray-900", children: "(Optional) Add the Admin Console URL" })
|
|
570
|
+
] }),
|
|
571
|
+
/* @__PURE__ */ jsx(
|
|
572
|
+
"input",
|
|
573
|
+
{
|
|
574
|
+
value: adminConsoleUrl,
|
|
575
|
+
onChange: (event) => setAdminConsoleUrl(event.target.value),
|
|
576
|
+
placeholder: "https://admin-console.example.com",
|
|
577
|
+
className: "portal-input ml-8 w-full"
|
|
578
|
+
}
|
|
579
|
+
)
|
|
580
|
+
] })
|
|
581
|
+
] })
|
|
582
|
+
] }),
|
|
583
|
+
apiError && /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-rose-200 bg-rose-50 p-3 text-sm text-rose-600", children: apiError }),
|
|
584
|
+
/* @__PURE__ */ jsxs("div", { className: "flex items-center justify-between text-sm text-gray-500", children: [
|
|
585
|
+
/* @__PURE__ */ jsx(
|
|
586
|
+
"button",
|
|
587
|
+
{
|
|
588
|
+
type: "button",
|
|
589
|
+
onClick: handleBack,
|
|
590
|
+
className: "rounded-xl px-4 py-2 font-medium text-gray-500 transition hover:bg-gray-100",
|
|
591
|
+
children: "Back"
|
|
592
|
+
}
|
|
593
|
+
),
|
|
594
|
+
/* @__PURE__ */ jsx("span", { children: "Step 2 of 2" }),
|
|
595
|
+
/* @__PURE__ */ jsx(
|
|
596
|
+
"button",
|
|
597
|
+
{
|
|
598
|
+
type: "button",
|
|
599
|
+
onClick: handleFinish,
|
|
600
|
+
className: "rounded-xl bg-indigo-500 px-4 py-2 font-medium text-white transition hover:bg-indigo-600",
|
|
601
|
+
children: "Finish"
|
|
602
|
+
}
|
|
603
|
+
)
|
|
604
|
+
] }),
|
|
605
|
+
/* @__PURE__ */ jsxs("p", { className: "text-center text-xs text-gray-400", children: [
|
|
606
|
+
"Having trouble? ",
|
|
607
|
+
/* @__PURE__ */ jsx("a", { className: "text-indigo-500", href: "#", children: "Open an issue." })
|
|
608
|
+
] })
|
|
609
|
+
] }) })
|
|
610
|
+
] });
|
|
611
|
+
}
|
|
612
|
+
return /* @__PURE__ */ jsxs("div", { className: "space-y-6", children: [
|
|
613
|
+
/* @__PURE__ */ jsx(StepIndicator, { step: 1 }),
|
|
614
|
+
/* @__PURE__ */ jsxs("div", { className: "rounded-2xl border border-gray-100 bg-gray-50 p-6", children: [
|
|
615
|
+
/* @__PURE__ */ jsxs("div", { className: "space-y-4", children: [
|
|
616
|
+
/* @__PURE__ */ jsxs("label", { className: "block text-sm font-medium text-gray-700", children: [
|
|
617
|
+
"Instance Name",
|
|
618
|
+
/* @__PURE__ */ jsx(
|
|
619
|
+
"input",
|
|
620
|
+
{
|
|
621
|
+
value: instanceName,
|
|
622
|
+
onChange: (event) => setInstanceName(event.target.value),
|
|
623
|
+
placeholder: "Instance nickname",
|
|
624
|
+
"aria-invalid": showErrors && !instanceName.trim(),
|
|
625
|
+
className: `portal-input mt-1 w-full ${showErrors && !instanceName.trim() ? "border-rose-400 focus:border-rose-400 focus:ring-rose-200" : ""}`
|
|
626
|
+
}
|
|
627
|
+
),
|
|
628
|
+
showErrors && !instanceName.trim() ? /* @__PURE__ */ jsx("span", { className: "mt-1 block text-xs text-rose-500", children: "Instance name is required." }) : null
|
|
629
|
+
] }),
|
|
630
|
+
/* @__PURE__ */ jsxs("fieldset", { className: "space-y-2", children: [
|
|
631
|
+
/* @__PURE__ */ jsx("legend", { className: "text-sm font-medium text-gray-700", children: "Network Availability" }),
|
|
632
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-3 text-sm text-gray-600", children: [
|
|
633
|
+
/* @__PURE__ */ jsx(
|
|
634
|
+
"input",
|
|
635
|
+
{
|
|
636
|
+
type: "radio",
|
|
637
|
+
name: "network-availability",
|
|
638
|
+
checked: networkAvailability === "online",
|
|
639
|
+
onChange: () => setNetworkAvailability("online"),
|
|
640
|
+
className: "portal-radio"
|
|
641
|
+
}
|
|
642
|
+
),
|
|
643
|
+
"Outbound requests allowed"
|
|
644
|
+
] }),
|
|
645
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-3 text-sm text-gray-600", children: [
|
|
646
|
+
/* @__PURE__ */ jsx(
|
|
647
|
+
"input",
|
|
648
|
+
{
|
|
649
|
+
type: "radio",
|
|
650
|
+
name: "network-availability",
|
|
651
|
+
checked: networkAvailability === "proxy",
|
|
652
|
+
onChange: () => setNetworkAvailability("proxy"),
|
|
653
|
+
className: "portal-radio"
|
|
654
|
+
}
|
|
655
|
+
),
|
|
656
|
+
"Outbound requests require HTTPS Proxy"
|
|
657
|
+
] }),
|
|
658
|
+
/* @__PURE__ */ jsxs("label", { className: "flex items-center gap-3 text-sm text-gray-600", children: [
|
|
659
|
+
/* @__PURE__ */ jsx(
|
|
660
|
+
"input",
|
|
661
|
+
{
|
|
662
|
+
type: "radio",
|
|
663
|
+
name: "network-availability",
|
|
664
|
+
checked: networkAvailability === "airgap",
|
|
665
|
+
onChange: () => setNetworkAvailability("airgap"),
|
|
666
|
+
className: "portal-radio"
|
|
667
|
+
}
|
|
668
|
+
),
|
|
669
|
+
"No outbound requests allowed (air gap)"
|
|
670
|
+
] })
|
|
671
|
+
] }),
|
|
672
|
+
apiError ? /* @__PURE__ */ jsx("div", { className: "rounded-xl border border-rose-200 bg-rose-50 p-3 text-sm text-rose-600", children: apiError }) : null
|
|
673
|
+
] }),
|
|
674
|
+
/* @__PURE__ */ jsxs("div", { className: "mt-6 flex items-center justify-between text-sm text-gray-500", children: [
|
|
675
|
+
/* @__PURE__ */ jsx("span", { children: "Step 1 of 2" }),
|
|
676
|
+
/* @__PURE__ */ jsx(
|
|
677
|
+
"button",
|
|
678
|
+
{
|
|
679
|
+
type: "button",
|
|
680
|
+
onClick: handleContinue,
|
|
681
|
+
disabled: isCreatingServiceAccount,
|
|
682
|
+
className: "rounded-xl bg-indigo-500 px-4 py-2 font-medium text-white transition hover:bg-indigo-600 disabled:cursor-not-allowed disabled:opacity-50",
|
|
683
|
+
children: isCreatingServiceAccount ? "Creating..." : "Continue"
|
|
684
|
+
}
|
|
685
|
+
)
|
|
686
|
+
] })
|
|
687
|
+
] })
|
|
688
|
+
] });
|
|
689
|
+
};
|
|
690
|
+
LinuxInstallWizard.displayName = "LinuxInstallWizard";
|
|
691
|
+
|
|
692
|
+
// src/utils/api-client.ts
|
|
693
|
+
async function authenticatedFetch(url, options = {}) {
|
|
694
|
+
const { token, ...fetchOptions } = options;
|
|
695
|
+
const headers = new Headers(fetchOptions.headers);
|
|
696
|
+
if (token) {
|
|
697
|
+
headers.set("authorization", `Bearer ${token}`);
|
|
698
|
+
}
|
|
699
|
+
const response = await fetch(url, {
|
|
700
|
+
...fetchOptions,
|
|
701
|
+
headers
|
|
702
|
+
});
|
|
703
|
+
if (response.status === 401) {
|
|
704
|
+
await handle401();
|
|
705
|
+
}
|
|
706
|
+
if (response.status === 502 || response.status === 503 || response.status === 504) {
|
|
707
|
+
await handleServerError(response.status);
|
|
708
|
+
}
|
|
709
|
+
return response;
|
|
710
|
+
}
|
|
711
|
+
async function handle401() {
|
|
712
|
+
const { redirect } = await import('next/navigation');
|
|
713
|
+
return redirect("/?expired=1");
|
|
714
|
+
}
|
|
715
|
+
async function handleServerError(statusCode) {
|
|
716
|
+
const { redirect } = await import('next/navigation');
|
|
717
|
+
let sourceUrl;
|
|
718
|
+
try {
|
|
719
|
+
const { headers } = await import('next/headers');
|
|
720
|
+
const headersList = await headers();
|
|
721
|
+
const referer = headersList.get("referer");
|
|
722
|
+
const host = headersList.get("host");
|
|
723
|
+
const pathname = headersList.get("x-invoke-path") || headersList.get("x-forwarded-path");
|
|
724
|
+
if (referer) {
|
|
725
|
+
sourceUrl = referer;
|
|
726
|
+
} else if (host && pathname) {
|
|
727
|
+
const protocol = headersList.get("x-forwarded-proto") || "https";
|
|
728
|
+
sourceUrl = `${protocol}://${host}${pathname}`;
|
|
729
|
+
}
|
|
730
|
+
} catch (error) {
|
|
731
|
+
console.debug("[portal-components] Could not determine source URL", error);
|
|
732
|
+
}
|
|
733
|
+
const params = new URLSearchParams({ code: String(statusCode) });
|
|
734
|
+
if (sourceUrl) {
|
|
735
|
+
params.set("source", sourceUrl);
|
|
736
|
+
}
|
|
737
|
+
return redirect(`/error?${params.toString()}`);
|
|
738
|
+
}
|
|
739
|
+
|
|
740
|
+
// src/actions/index.ts
|
|
741
|
+
var getApiOrigin = () => {
|
|
742
|
+
return (process.env.REPLICATED_APP_ORIGIN || "https://replicated.app").replace(/\/+$/, "");
|
|
743
|
+
};
|
|
744
|
+
var defineServerAction = (definition) => definition;
|
|
745
|
+
var createServiceAccount = defineServerAction({
|
|
746
|
+
id: "service-account/create",
|
|
747
|
+
description: "Creates a service account for installing applications",
|
|
748
|
+
visibility: "customer",
|
|
749
|
+
tags: ["service-account", "install"],
|
|
750
|
+
async run({ token, name }) {
|
|
751
|
+
if (!token || typeof token !== "string") {
|
|
752
|
+
throw new Error("Service account creation requires a session token");
|
|
753
|
+
}
|
|
754
|
+
if (!name || typeof name !== "string" || !name.trim()) {
|
|
755
|
+
throw new Error("Service account name is required");
|
|
756
|
+
}
|
|
757
|
+
const endpoint = `${getApiOrigin()}/v3/service-account`;
|
|
758
|
+
if (process.env.NODE_ENV !== "production") {
|
|
759
|
+
console.debug(
|
|
760
|
+
"[portal-components] creating service account via %s",
|
|
761
|
+
endpoint
|
|
762
|
+
);
|
|
763
|
+
}
|
|
764
|
+
const response = await authenticatedFetch(endpoint, {
|
|
765
|
+
method: "POST",
|
|
766
|
+
token,
|
|
767
|
+
headers: {
|
|
768
|
+
"content-type": "application/json"
|
|
769
|
+
},
|
|
770
|
+
body: JSON.stringify({ account_name: name.trim() })
|
|
771
|
+
});
|
|
772
|
+
if (!response.ok) {
|
|
773
|
+
const errorText = await response.text();
|
|
774
|
+
throw new Error(
|
|
775
|
+
`Service account creation failed (${response.status} ${response.statusText}): ${errorText}`
|
|
776
|
+
);
|
|
777
|
+
}
|
|
778
|
+
const data = await response.json();
|
|
779
|
+
return data;
|
|
780
|
+
}
|
|
781
|
+
});
|
|
782
|
+
var fetchCustomBrandingImpl = async () => {
|
|
783
|
+
const appSlug = process.env.PORTAL_APP_SLUG;
|
|
784
|
+
if (!appSlug) {
|
|
785
|
+
throw new Error("PORTAL_APP_SLUG is not configured");
|
|
786
|
+
}
|
|
787
|
+
const url = `${getApiOrigin()}/v3/custom-branding?app_slug=${encodeURIComponent(
|
|
788
|
+
appSlug
|
|
789
|
+
)}`;
|
|
790
|
+
if (process.env.NODE_ENV !== "production") {
|
|
791
|
+
console.debug(
|
|
792
|
+
"[portal-components] fetching custom branding via %s",
|
|
793
|
+
url
|
|
794
|
+
);
|
|
795
|
+
}
|
|
796
|
+
const response = await fetch(url, {
|
|
797
|
+
headers: {
|
|
798
|
+
accept: "application/json"
|
|
799
|
+
}
|
|
800
|
+
});
|
|
801
|
+
if (!response.ok) {
|
|
802
|
+
throw new Error(
|
|
803
|
+
`Custom branding request failed (${response.status} ${response.statusText})`
|
|
804
|
+
);
|
|
805
|
+
}
|
|
806
|
+
const payload = await response.json();
|
|
807
|
+
const brandingData = payload?.branding_data;
|
|
808
|
+
if (typeof brandingData !== "string") {
|
|
809
|
+
throw new Error("Custom branding response missing branding_data string");
|
|
810
|
+
}
|
|
811
|
+
return {
|
|
812
|
+
brandingData,
|
|
813
|
+
documentation: payload?.documentation ?? null
|
|
814
|
+
};
|
|
815
|
+
};
|
|
816
|
+
cache(fetchCustomBrandingImpl);
|
|
817
|
+
var decodeJwtPayload = (token) => {
|
|
818
|
+
const parts = token.split(".");
|
|
819
|
+
if (parts.length !== 3) {
|
|
820
|
+
throw new Error("Invalid JWT received");
|
|
821
|
+
}
|
|
822
|
+
const payloadSegment = parts[1];
|
|
823
|
+
if (!payloadSegment) {
|
|
824
|
+
throw new Error("JWT payload segment missing");
|
|
825
|
+
}
|
|
826
|
+
const padded = payloadSegment.padEnd(
|
|
827
|
+
payloadSegment.length + (4 - payloadSegment.length % 4) % 4,
|
|
828
|
+
"="
|
|
829
|
+
);
|
|
830
|
+
const decoded = Buffer.from(padded, "base64").toString("utf-8");
|
|
831
|
+
return JSON.parse(decoded);
|
|
832
|
+
};
|
|
833
|
+
var getCustomerIdFromToken = (token) => {
|
|
834
|
+
const payload = decodeJwtPayload(token);
|
|
835
|
+
const customerId = payload?.customer_id || payload?.customerId;
|
|
836
|
+
if (typeof customerId !== "string" || !customerId.trim()) {
|
|
837
|
+
throw new Error("Unable to determine customer_id from session token");
|
|
838
|
+
}
|
|
839
|
+
return customerId.trim();
|
|
840
|
+
};
|
|
841
|
+
|
|
842
|
+
// src/actions/install.ts
|
|
843
|
+
async function fetchChannelReleases(input, context) {
|
|
844
|
+
const { token, channelId } = input;
|
|
845
|
+
if (!token || typeof token !== "string") {
|
|
846
|
+
throw new Error("fetchChannelReleases requires a session token");
|
|
847
|
+
}
|
|
848
|
+
const customerId = getCustomerIdFromToken(token);
|
|
849
|
+
const origin = getApiOrigin();
|
|
850
|
+
const url = new URL(`${origin}/v3/channel-releases`);
|
|
851
|
+
url.searchParams.set("customer_id", customerId);
|
|
852
|
+
if (channelId) {
|
|
853
|
+
url.searchParams.set("channel_id", channelId);
|
|
854
|
+
}
|
|
855
|
+
if (process.env.NODE_ENV !== "production") {
|
|
856
|
+
console.debug("[portal-components] fetching channel releases via %s", url.toString());
|
|
857
|
+
}
|
|
858
|
+
const response = await authenticatedFetch(url.toString(), {
|
|
859
|
+
method: "GET",
|
|
860
|
+
token,
|
|
861
|
+
headers: {
|
|
862
|
+
accept: "application/json"
|
|
863
|
+
},
|
|
864
|
+
signal: context?.signal
|
|
865
|
+
});
|
|
866
|
+
if (!response.ok) {
|
|
867
|
+
const errorText = await response.text();
|
|
868
|
+
throw new Error(
|
|
869
|
+
`Channel releases request failed (${response.status} ${response.statusText}): ${errorText}`
|
|
870
|
+
);
|
|
871
|
+
}
|
|
872
|
+
const payload = await response.json();
|
|
873
|
+
return {
|
|
874
|
+
channelReleases: payload.channelReleases || []
|
|
875
|
+
};
|
|
876
|
+
}
|
|
877
|
+
async function createInstallOptions(input, context) {
|
|
878
|
+
const {
|
|
879
|
+
token,
|
|
880
|
+
installType,
|
|
881
|
+
instanceName,
|
|
882
|
+
serviceAccountId,
|
|
883
|
+
networkAvailability,
|
|
884
|
+
isMultiNode = false,
|
|
885
|
+
channelId,
|
|
886
|
+
channelReleaseSequence,
|
|
887
|
+
registryAvailability,
|
|
888
|
+
kubernetesDistribution
|
|
889
|
+
} = input;
|
|
890
|
+
if (!token || typeof token !== "string") {
|
|
891
|
+
throw new Error("createInstallOptions requires a session token");
|
|
892
|
+
}
|
|
893
|
+
if (!instanceName?.trim()) {
|
|
894
|
+
throw new Error("Instance name is required");
|
|
895
|
+
}
|
|
896
|
+
if (!serviceAccountId?.trim()) {
|
|
897
|
+
throw new Error("Service account ID is required");
|
|
898
|
+
}
|
|
899
|
+
const customerId = getCustomerIdFromToken(token);
|
|
900
|
+
const origin = getApiOrigin();
|
|
901
|
+
const endpoint = `${origin}/v3/customers/${customerId}/install-options?includeInstructions=true`;
|
|
902
|
+
const body = {
|
|
903
|
+
install_type: installType,
|
|
904
|
+
instance_name: instanceName.trim(),
|
|
905
|
+
service_account_id: serviceAccountId.trim(),
|
|
906
|
+
network_availability: networkAvailability,
|
|
907
|
+
is_multi_node: isMultiNode
|
|
908
|
+
};
|
|
909
|
+
if (channelId) {
|
|
910
|
+
body.channel_id = channelId;
|
|
911
|
+
}
|
|
912
|
+
if (channelReleaseSequence !== void 0) {
|
|
913
|
+
body.channel_release_sequence = channelReleaseSequence;
|
|
914
|
+
}
|
|
915
|
+
if (registryAvailability) {
|
|
916
|
+
body.registry_availability = registryAvailability;
|
|
917
|
+
}
|
|
918
|
+
if (kubernetesDistribution) {
|
|
919
|
+
body.kubernetes_distribution = kubernetesDistribution;
|
|
920
|
+
}
|
|
921
|
+
if (process.env.NODE_ENV !== "production") {
|
|
922
|
+
console.debug("[portal-components] creating install options via %s", endpoint);
|
|
923
|
+
}
|
|
924
|
+
const response = await authenticatedFetch(endpoint, {
|
|
925
|
+
method: "POST",
|
|
926
|
+
token,
|
|
927
|
+
headers: {
|
|
928
|
+
"content-type": "application/json",
|
|
929
|
+
accept: "application/json"
|
|
930
|
+
},
|
|
931
|
+
body: JSON.stringify(body),
|
|
932
|
+
signal: context?.signal
|
|
933
|
+
});
|
|
934
|
+
if (!response.ok) {
|
|
935
|
+
const errorText = await response.text();
|
|
936
|
+
throw new Error(
|
|
937
|
+
`Create install options failed (${response.status} ${response.statusText}): ${errorText}`
|
|
938
|
+
);
|
|
939
|
+
}
|
|
940
|
+
return await response.json();
|
|
941
|
+
}
|
|
942
|
+
async function getInstallOptions(input, context) {
|
|
943
|
+
const {
|
|
944
|
+
token,
|
|
945
|
+
installOptionsId,
|
|
946
|
+
includeInstructions = true,
|
|
947
|
+
privateRegistryHostname,
|
|
948
|
+
proxyUrl
|
|
949
|
+
} = input;
|
|
950
|
+
if (!token || typeof token !== "string") {
|
|
951
|
+
throw new Error("getInstallOptions requires a session token");
|
|
952
|
+
}
|
|
953
|
+
if (!installOptionsId?.trim()) {
|
|
954
|
+
throw new Error("Install options ID is required");
|
|
955
|
+
}
|
|
956
|
+
const customerId = getCustomerIdFromToken(token);
|
|
957
|
+
const origin = getApiOrigin();
|
|
958
|
+
const url = new URL(`${origin}/v3/customers/${customerId}/install-options/${installOptionsId.trim()}`);
|
|
959
|
+
if (includeInstructions) {
|
|
960
|
+
url.searchParams.set("includeInstructions", "true");
|
|
961
|
+
}
|
|
962
|
+
if (privateRegistryHostname) {
|
|
963
|
+
url.searchParams.set("privateRegistryHostname", privateRegistryHostname);
|
|
964
|
+
}
|
|
965
|
+
if (proxyUrl) {
|
|
966
|
+
url.searchParams.set("proxyUrl", proxyUrl);
|
|
967
|
+
}
|
|
968
|
+
if (process.env.NODE_ENV !== "production") {
|
|
969
|
+
console.debug("[portal-components] fetching install options via %s", url.toString());
|
|
970
|
+
}
|
|
971
|
+
const response = await authenticatedFetch(url.toString(), {
|
|
972
|
+
method: "GET",
|
|
973
|
+
token,
|
|
974
|
+
headers: {
|
|
975
|
+
accept: "application/json"
|
|
976
|
+
},
|
|
977
|
+
signal: context?.signal
|
|
978
|
+
});
|
|
979
|
+
if (!response.ok) {
|
|
980
|
+
const errorText = await response.text();
|
|
981
|
+
throw new Error(
|
|
982
|
+
`Get install options failed (${response.status} ${response.statusText}): ${errorText}`
|
|
983
|
+
);
|
|
984
|
+
}
|
|
985
|
+
return await response.json();
|
|
986
|
+
}
|
|
987
|
+
async function updateInstallOptions(input, context) {
|
|
988
|
+
const {
|
|
989
|
+
token,
|
|
990
|
+
installOptionsId,
|
|
991
|
+
installType,
|
|
992
|
+
channelId,
|
|
993
|
+
channelReleaseSequence,
|
|
994
|
+
networkAvailability,
|
|
995
|
+
registryAvailability,
|
|
996
|
+
kubernetesDistribution,
|
|
997
|
+
isMultiNode,
|
|
998
|
+
serviceAccountId,
|
|
999
|
+
adminConsoleUrl,
|
|
1000
|
+
status,
|
|
1001
|
+
includeInstructions = true,
|
|
1002
|
+
privateRegistryHostname,
|
|
1003
|
+
proxyUrl
|
|
1004
|
+
} = input;
|
|
1005
|
+
if (!token || typeof token !== "string") {
|
|
1006
|
+
throw new Error("updateInstallOptions requires a session token");
|
|
1007
|
+
}
|
|
1008
|
+
if (!installOptionsId?.trim()) {
|
|
1009
|
+
throw new Error("Install options ID is required");
|
|
1010
|
+
}
|
|
1011
|
+
const customerId = getCustomerIdFromToken(token);
|
|
1012
|
+
const origin = getApiOrigin();
|
|
1013
|
+
const url = new URL(`${origin}/v3/customers/${customerId}/install-options/${installOptionsId.trim()}`);
|
|
1014
|
+
if (includeInstructions) {
|
|
1015
|
+
url.searchParams.set("includeInstructions", "true");
|
|
1016
|
+
}
|
|
1017
|
+
if (privateRegistryHostname) {
|
|
1018
|
+
url.searchParams.set("privateRegistryHostname", privateRegistryHostname);
|
|
1019
|
+
}
|
|
1020
|
+
if (proxyUrl) {
|
|
1021
|
+
url.searchParams.set("proxyUrl", proxyUrl);
|
|
1022
|
+
}
|
|
1023
|
+
const body = {};
|
|
1024
|
+
if (installType !== void 0) {
|
|
1025
|
+
body.install_type = installType;
|
|
1026
|
+
}
|
|
1027
|
+
if (channelId !== void 0) {
|
|
1028
|
+
body.channel_id = channelId;
|
|
1029
|
+
}
|
|
1030
|
+
if (channelReleaseSequence !== void 0) {
|
|
1031
|
+
body.channel_release_sequence = channelReleaseSequence;
|
|
1032
|
+
}
|
|
1033
|
+
if (networkAvailability !== void 0) {
|
|
1034
|
+
body.network_availability = networkAvailability;
|
|
1035
|
+
}
|
|
1036
|
+
if (registryAvailability !== void 0) {
|
|
1037
|
+
body.registry_availability = registryAvailability;
|
|
1038
|
+
}
|
|
1039
|
+
if (kubernetesDistribution !== void 0) {
|
|
1040
|
+
body.kubernetes_distribution = kubernetesDistribution;
|
|
1041
|
+
}
|
|
1042
|
+
if (isMultiNode !== void 0) {
|
|
1043
|
+
body.is_multi_node = isMultiNode;
|
|
1044
|
+
}
|
|
1045
|
+
if (serviceAccountId !== void 0) {
|
|
1046
|
+
body.service_account_id = serviceAccountId;
|
|
1047
|
+
}
|
|
1048
|
+
if (adminConsoleUrl !== void 0) {
|
|
1049
|
+
body.admin_console_url = adminConsoleUrl;
|
|
1050
|
+
}
|
|
1051
|
+
if (status !== void 0) {
|
|
1052
|
+
body.status = status;
|
|
1053
|
+
}
|
|
1054
|
+
if (process.env.NODE_ENV !== "production") {
|
|
1055
|
+
console.debug("[portal-components] updating install options via %s", url.toString());
|
|
1056
|
+
}
|
|
1057
|
+
const response = await authenticatedFetch(url.toString(), {
|
|
1058
|
+
method: "PATCH",
|
|
1059
|
+
token,
|
|
1060
|
+
headers: {
|
|
1061
|
+
"content-type": "application/json",
|
|
1062
|
+
accept: "application/json"
|
|
1063
|
+
},
|
|
1064
|
+
body: JSON.stringify(body),
|
|
1065
|
+
signal: context?.signal
|
|
1066
|
+
});
|
|
1067
|
+
if (!response.ok) {
|
|
1068
|
+
const errorText = await response.text();
|
|
1069
|
+
throw new Error(
|
|
1070
|
+
`Update install options failed (${response.status} ${response.statusText}): ${errorText}`
|
|
1071
|
+
);
|
|
1072
|
+
}
|
|
1073
|
+
return await response.json();
|
|
1074
|
+
}
|
|
1075
|
+
function filterEmbeddedClusterReleases(releases) {
|
|
1076
|
+
return releases.filter(
|
|
1077
|
+
(release) => release.installationTypes?.embeddedCluster?.version
|
|
1078
|
+
);
|
|
1079
|
+
}
|
|
1080
|
+
|
|
1081
|
+
export { LINUX_INSTALL_OPTIONS_KEY, LINUX_INSTALL_SERVICE_ACCOUNT_KEY, LinuxInstallWizard, createInstallOptions, createServiceAccount, fetchChannelReleases, filterEmbeddedClusterReleases, getInstallOptions, updateInstallOptions };
|
|
1082
|
+
//# sourceMappingURL=linux-install-wizard.js.map
|
|
1083
|
+
//# sourceMappingURL=linux-install-wizard.js.map
|