diff --git a/hack/dev/skaffoldcache.Dockerfile b/hack/dev/skaffoldcache.Dockerfile
index 6669108557..70f7d7efc7 100644
--- a/hack/dev/skaffoldcache.Dockerfile
+++ b/hack/dev/skaffoldcache.Dockerfile
@@ -1,4 +1,4 @@
-FROM golang:1.21 as deps
+FROM golang:1.22 as deps
RUN go install github.com/go-delve/delve/cmd/dlv@v1.7.2
diff --git a/pkg/handlers/backup.go b/pkg/handlers/backup.go
index 2d932c7f1a..2d850f2e1c 100644
--- a/pkg/handlers/backup.go
+++ b/pkg/handlers/backup.go
@@ -34,6 +34,12 @@ func (h *Handler) CreateApplicationBackup(w http.ResponseWriter, r *http.Request
Success: false,
}
+ if util.IsEmbeddedCluster() {
+ createApplicationBackupResponse.Error = "application backups are not supported in embedded clusters"
+ JSON(w, http.StatusForbidden, createApplicationBackupResponse)
+ return
+ }
+
// check minimal rbac
if err := requiresKotsadmVeleroAccess(w, r); err != nil {
return
diff --git a/pkg/snapshot/store.go b/pkg/snapshot/store.go
index 17ddf21e84..af13c7b17e 100644
--- a/pkg/snapshot/store.go
+++ b/pkg/snapshot/store.go
@@ -35,6 +35,7 @@ import (
kotss3 "github.com/replicatedhq/kots/pkg/s3"
"github.com/replicatedhq/kots/pkg/snapshot/providers"
"github.com/replicatedhq/kots/pkg/snapshot/types"
+ "github.com/replicatedhq/kots/pkg/util"
velerov1 "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
veleroclientv1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
"google.golang.org/api/option"
@@ -1023,7 +1024,12 @@ func mapAWSBackupStorageLocationToStore(kotsadmVeleroBackendStorageLocation *vel
return errors.Wrap(err, "failed to parse s3 url")
}
// without endpoint, the ui has no logic to figure if it is amazon-s3 or other-s3 compatible storages
- if !isS3Compatible || strings.HasSuffix(u.Hostname(), ".amazonaws.com") {
+ shouldMapToAWS := !isS3Compatible || strings.HasSuffix(u.Hostname(), ".amazonaws.com")
+ if util.IsEmbeddedCluster() {
+ // embedded clusters only support other s3 compatible storage
+ shouldMapToAWS = false
+ }
+ if shouldMapToAWS {
store.AWS = &types.StoreAWS{
Region: kotsadmVeleroBackendStorageLocation.Spec.Config["region"],
}
diff --git a/pkg/snapshot/velero.go b/pkg/snapshot/velero.go
index b92f3bf625..4af14711b0 100644
--- a/pkg/snapshot/velero.go
+++ b/pkg/snapshot/velero.go
@@ -12,6 +12,7 @@ import (
"github.com/replicatedhq/kots/pkg/k8sutil"
kotsadmresources "github.com/replicatedhq/kots/pkg/kotsadm/resources"
kotsadmtypes "github.com/replicatedhq/kots/pkg/kotsadm/types"
+ "github.com/replicatedhq/kots/pkg/util"
velerov1api "github.com/vmware-tanzu/velero/pkg/apis/velero/v1"
"github.com/vmware-tanzu/velero/pkg/cmd/cli/serverstatus"
veleroclientv1 "github.com/vmware-tanzu/velero/pkg/generated/clientset/versioned/typed/velero/v1"
@@ -388,9 +389,16 @@ func getVeleroPod(ctx context.Context, clientset *kubernetes.Clientset, namespac
"component": "velero",
"deploy": "velero",
}
+ labelSelector := labels.SelectorFromSet(veleroLabels)
+
+ if util.IsEmbeddedCluster() {
+ labelSelector = labels.SelectorFromSet(map[string]string{
+ "name": "velero",
+ })
+ }
veleroPods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{
- LabelSelector: labels.SelectorFromSet(veleroLabels).String(),
+ LabelSelector: labelSelector.String(),
})
if err != nil {
return "", errors.Wrap(err, "failed to list velero pods before restarting")
@@ -421,6 +429,12 @@ func getNodeAgentPods(ctx context.Context, clientset *kubernetes.Clientset, name
labelSelector := labels.NewSelector()
labelSelector = labelSelector.Add(*componentReq, *nameReq)
+ if util.IsEmbeddedCluster() {
+ labelSelector = labels.SelectorFromSet(map[string]string{
+ "name": "node-agent",
+ })
+ }
+
nodeAgentPods, err := clientset.CoreV1().Pods(namespace).List(context.TODO(), metav1.ListOptions{
LabelSelector: labelSelector.String(),
})
diff --git a/web/src/Root.tsx b/web/src/Root.tsx
index 35110e0db9..2aa10be0e6 100644
--- a/web/src/Root.tsx
+++ b/web/src/Root.tsx
@@ -635,6 +635,9 @@ const Root = () => {
}
@@ -644,6 +647,9 @@ const Root = () => {
element={
}
@@ -655,6 +661,9 @@ const Root = () => {
// @ts-ignore
}
@@ -664,6 +673,9 @@ const Root = () => {
element={
}
diff --git a/web/src/components/apps/AppDetailPage.tsx b/web/src/components/apps/AppDetailPage.tsx
index 824b40003e..9b3656ecfd 100644
--- a/web/src/components/apps/AppDetailPage.tsx
+++ b/web/src/components/apps/AppDetailPage.tsx
@@ -488,6 +488,7 @@ function AppDetailPage(props: Props) {
app={selectedApp}
isVeleroInstalled={isVeleroInstalled}
isHelmManaged={props.isHelmManaged}
+ isEmbeddedCluster={props.isEmbeddedCluster}
/>
diff --git a/web/src/components/modals/DeleteSnapshotModal.tsx b/web/src/components/modals/DeleteSnapshotModal.tsx
index 58ef8dbe89..722cedb57d 100644
--- a/web/src/components/modals/DeleteSnapshotModal.tsx
+++ b/web/src/components/modals/DeleteSnapshotModal.tsx
@@ -3,6 +3,7 @@ import { Utilities } from "@src/utilities/utilities";
import { Snapshot } from "@src/types";
interface DeleteSnapshotModalProps {
+ featureName: string;
deleteSnapshotModal: boolean;
toggleConfirmDeleteModal: (snapshot: Snapshot | {}) => void;
snapshotToDelete: Snapshot;
@@ -14,6 +15,7 @@ interface DeleteSnapshotModalProps {
export default function DeleteSnapshotModal(props: DeleteSnapshotModalProps) {
const {
+ featureName,
deleteSnapshotModal,
toggleConfirmDeleteModal,
snapshotToDelete,
@@ -37,7 +39,7 @@ export default function DeleteSnapshotModal(props: DeleteSnapshotModalProps) {
- Delete snapshot
+ Delete {featureName}
{deleteErr ? (
@@ -45,8 +47,8 @@ export default function DeleteSnapshotModal(props: DeleteSnapshotModalProps) {
) : null}
- Are you sure you want do permanently delete a snapshot? This action
- cannot be reversed.
+ Are you sure you want to permanently delete a {featureName}? This
+ action cannot be reversed.
@@ -87,7 +89,9 @@ export default function DeleteSnapshotModal(props: DeleteSnapshotModalProps) {
}}
disabled={deletingSnapshot}
>
- {deletingSnapshot ? "Deleting snapshot" : "Delete snapshot"}
+ {deletingSnapshot
+ ? `Deleting ${featureName}`
+ : `Delete ${featureName}`}
diff --git a/web/src/components/shared/NavBar.tsx b/web/src/components/shared/NavBar.tsx
index 182e2fc3cd..4495573810 100644
--- a/web/src/components/shared/NavBar.tsx
+++ b/web/src/components/shared/NavBar.tsx
@@ -264,7 +264,9 @@ export class NavBar extends PureComponent
{
onClick={this.handleGoToSnapshots}
className="flex flex1 u-cursor--pointer alignItems--center text u-fontSize--normal u-fontWeight--medium flex"
>
- Snapshots
+ {isEmbeddedClusterEnabled
+ ? "Disaster Recovery"
+ : "Snapshots"}
)}
@@ -290,6 +292,7 @@ export class NavBar extends PureComponent
{
>
)}
diff --git a/web/src/components/shared/NavBarDropdown.jsx b/web/src/components/shared/NavBarDropdown.jsx
index 8a401b1362..ee62dd1595 100644
--- a/web/src/components/shared/NavBarDropdown.jsx
+++ b/web/src/components/shared/NavBarDropdown.jsx
@@ -3,7 +3,7 @@ import Icon from "../Icon";
import ChangePasswordModal from "../modals/ChangePasswordModal/ChangePasswordModal";
import { useEffect, useRef, useState } from "react";
-const NavBarDropdown = ({ handleLogOut, isHelmManaged }) => {
+const NavBarDropdown = ({ handleLogOut, isHelmManaged, isEmbeddedCluster }) => {
const [showDropdown, setShowDropdown] = useState(false);
const [showModal, setShowModal] = useState(false);
const testRef = useRef(null);
@@ -49,7 +49,7 @@ const NavBarDropdown = ({ handleLogOut, isHelmManaged }) => {
setShowModal(true)}>Change password
- {!isHelmManaged && (
+ {!isHelmManaged && !isEmbeddedCluster && (
Add new application
diff --git a/web/src/components/shared/SubNavBar/SubNavBar.jsx b/web/src/components/shared/SubNavBar/SubNavBar.jsx
index 3ca867a273..63c7a341ff 100644
--- a/web/src/components/shared/SubNavBar/SubNavBar.jsx
+++ b/web/src/components/shared/SubNavBar/SubNavBar.jsx
@@ -13,6 +13,7 @@ export default function SubNavBar({
isAccess = false,
isSnapshots = false,
isHelmManaged,
+ isEmbeddedCluster,
}) {
let { slug } = app;
@@ -50,13 +51,14 @@ export default function SubNavBar({
const snapshotsConfig = [
{
tabName: activeTab === slug ? slug : "snapshots",
- displayName: "Full Snapshots (Instance)",
+ displayName: isEmbeddedCluster ? "Backups" : "Full Snapshots (Instance)",
to: () => `/snapshots`,
},
{
tabName: "partial",
displayName: "Partial Snapshots (Application)",
to: (slug) => `/snapshots/partial/${slug}`,
+ hide: isEmbeddedCluster,
},
{
tabName: "settings",
@@ -86,6 +88,7 @@ export default function SubNavBar({
.filter(Boolean)
: isSnapshots
? snapshotsConfig
+ .filter((link) => !link.hide)
.map((link, idx) => {
const generatedMenuItem = (
{" "}
{isVeleroInstalled
- ? "No snapshots yet"
- : "Get started with Snapshots"}{" "}
+ ? `No ${featureName}s yet`
+ : `Get started with ${Utilities.toTitleCase(featureName)}s`}{" "}
{isApp ? (
- There have been no snapshots made for {app?.name} yet. You can
- manually trigger snapshots or you can set up automatic snapshots to be
- made on a custom schedule.{" "}
+ There have been no {featureName}s made for {app?.name} yet. You can
+ manually trigger {featureName}s or you can set up automatic{" "}
+ {featureName}s to be made on a custom schedule.{" "}
) : isVeleroInstalled ? (
- Now that Velero is configured, you can start making snapshots. You can{" "}
- create a schedule{" "}
-
- for automatic snapshots or you can trigger one manually whenever you’d
- like.
+ Create a schedule
+ {" "}
+ for automatic {featureName}s or take a {featureName} manually.
) : (
@@ -50,7 +55,7 @@ export default function GettingStartedSnapshots(props) {
Velero
{" "}
installed in the cluster and configured to connect with the cloud
- provider you want to send your backups to
+ provider you want to send your {featureName}s to
)}
@@ -65,8 +70,8 @@ export default function GettingStartedSnapshots(props) {
>
{" "}
{isVeleroInstalled
- ? "Start a snapshot"
- : "Configure snapshot settings"}
+ ? `Start a ${featureName}`
+ : `Configure ${featureName} settings`}
) : (
{" "}
{isVeleroInstalled
- ? "Start a snapshot"
- : "Configure snapshot settings"}
+ ? `Start a ${featureName}`
+ : `Configure ${featureName} settings`}
)}
diff --git a/web/src/components/snapshots/SnapshotDetails.jsx b/web/src/components/snapshots/SnapshotDetails.jsx
index 901e30eb53..27b0f4d34a 100644
--- a/web/src/components/snapshots/SnapshotDetails.jsx
+++ b/web/src/components/snapshots/SnapshotDetails.jsx
@@ -360,7 +360,9 @@ class SnapshotDetails extends Component {
key={tab}
onClick={() => this.setState({ selectedScriptTab: tab })}
>
- {tab}
+ {this.props.isEmbeddedCluster
+ ? tab.replace("snapshot", "backup")
+ : tab}
))}
@@ -641,6 +643,8 @@ class SnapshotDetails extends Component {
};
render() {
+ const { isEmbeddedCluster } = this.props;
+
const {
loading,
showScriptsOutput,
@@ -659,6 +663,11 @@ class SnapshotDetails extends Component {
errorTitle,
} = this.state;
+ let featureName = "snapshot";
+ if (isEmbeddedCluster) {
+ featureName = "backup";
+ }
+
if (loading) {
return (
@@ -671,7 +680,7 @@ class SnapshotDetails extends Component {
this.props.navigate(-1)}>
- Snapshots
+ {Utilities.toTitleCase(featureName)}s
>
{snapshotDetails?.name}
@@ -715,7 +724,7 @@ class SnapshotDetails extends Component {
{" "}
- This snapshot has not completed yet, check back soon{" "}
+ This {featureName} has not completed yet, check back soon{" "}
) : (
@@ -725,7 +734,7 @@ class SnapshotDetails extends Component {
!isEmpty(this.postSnapshotScripts()) ? (
- Snapshot timeline
+ {Utilities.toTitleCase(featureName)} timeline
{" "}
- No pre-snapshot scripts to display{" "}
+ No pre-{featureName} scripts to display{" "}
)
@@ -828,7 +837,7 @@ class SnapshotDetails extends Component {
{" "}
- No post-snapshot scripts to display{" "}
+ No post-{featureName} scripts to display{" "}
)}
@@ -969,7 +978,7 @@ class SnapshotDetails extends Component {
displayShowAllModal={showAllPreSnapshotScripts}
toggleShowAllModal={this.toggleShowAllPreScripts}
dataToShow={this.renderShowAllScripts(this.preSnapshotScripts())}
- name="Pre-snapshot scripts"
+ name={`Pre-${featureName} scripts`}
/>
)}
{showAllPostSnapshotScripts && (
@@ -977,7 +986,7 @@ class SnapshotDetails extends Component {
displayShowAllModal={showAllPostSnapshotScripts}
toggleShowAllModal={this.toggleShowAllPostScripts}
dataToShow={this.renderShowAllScripts(this.postSnapshotScripts())}
- name="Post-snapshot scripts"
+ name={`Post-${featureName} scripts`}
/>
)}
{showAllWarnings && (
diff --git a/web/src/components/snapshots/SnapshotRow.jsx b/web/src/components/snapshots/SnapshotRow.jsx
index 9ee583fec7..b7d204fed3 100644
--- a/web/src/components/snapshots/SnapshotRow.jsx
+++ b/web/src/components/snapshots/SnapshotRow.jsx
@@ -34,7 +34,7 @@ class SnapshotRow extends Component {
};
render() {
- const { snapshot, app } = this.props;
+ const { snapshot, app, hideRestore } = this.props;
const isExpired = dayjs(new Date()).isSameOrAfter(snapshot?.expiresAt);
return (
@@ -114,7 +114,7 @@ class SnapshotRow extends Component {
{!isExpired && snapshot?.status !== "Deleting" && (
- {snapshot?.status === "Completed" && (
+ {snapshot?.status === "Completed" && !hideRestore && (
@@ -449,33 +455,35 @@ class SnapshotSchedule extends Component {
)}
-
Automatic snapshots
+
Automatic {featureName}s
- Set up a custom schedule and retention policy for automatic
- snapshots of the Admin Console and all application data.
+ Configure a schedule and retention policy for {featureName}s of
+ the admin console and all application data.
-
-
-
this.toggleScheduleAction("full")}
- >
- Full snapshots (Instance)
-
-
this.toggleScheduleAction("partial")}
- >
- Partial snapshots (Application)
-
+ {!isEmbeddedCluster && (
+
+
+ this.toggleScheduleAction("full")}
+ >
+ Full snapshots (Instance)
+
+ this.toggleScheduleAction("partial")}
+ >
+ Partial snapshots (Application)
+
+
-
+ )}
{this.state.activeTab === "partial" && (
)}
-
-
- Enable automatic scheduled snapshots
+ Enable automatic scheduled {featureName}s
@@ -586,11 +592,8 @@ class SnapshotSchedule extends Component {
Retention policy
- The Admin Console can reclaim space by automatically deleting
- older scheduled snapshots.
-
-
- Snapshots older than this will be deleted.
+ Choose how long to retain {featureName}s before they are
+ automatically deleted.
diff --git a/web/src/components/snapshots/SnapshotSettings.tsx b/web/src/components/snapshots/SnapshotSettings.tsx
index 991b8cb769..225f4ea357 100644
--- a/web/src/components/snapshots/SnapshotSettings.tsx
+++ b/web/src/components/snapshots/SnapshotSettings.tsx
@@ -16,6 +16,7 @@ import Icon from "../Icon";
type Props = {
appsList: App[];
isKurlEnabled?: boolean;
+ isEmbeddedCluster?: boolean;
} & RouterProps;
type State = {
@@ -399,6 +400,7 @@ class SnapshotSettings extends Component
{
this.hideResetFileSystemWarningModal
}
isKurlEnabled={this.props.isKurlEnabled}
+ isEmbeddedCluster={this.props.isEmbeddedCluster}
apps={this.props.appsList}
/>
diff --git a/web/src/components/snapshots/SnapshotStorageDestination.data.jsx b/web/src/components/snapshots/SnapshotStorageDestination.data.jsx
index 8156c9a312..bb12232fb7 100644
--- a/web/src/components/snapshots/SnapshotStorageDestination.data.jsx
+++ b/web/src/components/snapshots/SnapshotStorageDestination.data.jsx
@@ -13,7 +13,7 @@ const DESTINATIONS = [
},
{
value: "other",
- label: "Other S3-Compatible Storage",
+ label: "S3-Compatible Storage",
},
{
value: "internal",
diff --git a/web/src/components/snapshots/SnapshotStorageDestination.tsx b/web/src/components/snapshots/SnapshotStorageDestination.tsx
index ca0ff2a3da..550a737c6b 100644
--- a/web/src/components/snapshots/SnapshotStorageDestination.tsx
+++ b/web/src/components/snapshots/SnapshotStorageDestination.tsx
@@ -20,6 +20,7 @@ import {
FILE_SYSTEM_HOSTPATH_TYPE,
} from "./SnapshotStorageDestination.data";
import InputField from "@components/shared/forms/InputField";
+import { Utilities } from "@src/utilities/utilities";
type ValueType = {
value?: string;
@@ -205,6 +206,7 @@ type Props = {
isEmptyView?: boolean;
isLicenseUpload: boolean;
isKurlEnabled?: boolean;
+ isEmbeddedCluster?: boolean;
kotsadmRequiresVeleroAccess: boolean;
minimalRBACKotsadmNamespace: string;
openConfigureSnapshotsMinimalRBACModal: (
@@ -566,9 +568,13 @@ class SnapshotStorageDestination extends Component
{
}
// if nothing exists yet, we've determined default state is good
+ let defaultDestination = "aws";
+ if (this.props.isEmbeddedCluster) {
+ defaultDestination = "other";
+ }
this.setState({
determiningDestination: false,
- selectedDestination: find(DESTINATIONS, ["value", "aws"]),
+ selectedDestination: find(DESTINATIONS, ["value", defaultDestination]),
});
};
@@ -1604,6 +1610,7 @@ class SnapshotStorageDestination extends Component {
updatingSettings,
updateConfirm,
updateErrorMsg,
+ isEmbeddedCluster,
isKurlEnabled,
checkForVeleroAndNodeAgent,
} = this.props;
@@ -1611,6 +1618,16 @@ class SnapshotStorageDestination extends Component {
const availableDestinations = [];
if (snapshotSettings?.veleroPlugins) {
for (const veleroPlugin of snapshotSettings?.veleroPlugins) {
+ if (isEmbeddedCluster) {
+ if (veleroPlugin.includes("velero-plugin-for-aws")) {
+ availableDestinations.push({
+ value: "other",
+ label: "S3-Compatible Storage",
+ });
+ }
+ continue;
+ }
+
if (veleroPlugin.includes("velero-plugin-for-gcp")) {
availableDestinations.push({
value: "gcp",
@@ -1623,7 +1640,7 @@ class SnapshotStorageDestination extends Component {
});
availableDestinations.push({
value: "other",
- label: "Other S3-Compatible Storage",
+ label: "S3-Compatible Storage",
});
if (snapshotSettings.isKurl && !snapshotSettings?.isMinioDisabled) {
availableDestinations.push({
@@ -1679,6 +1696,11 @@ class SnapshotStorageDestination extends Component {
const resetFileSystemWarningMessage =
this.props.resetFileSystemWarningMessage;
+ let featureName = "snapshot";
+ if (isEmbeddedCluster) {
+ featureName = "backup";
+ }
+
return (
@@ -1688,23 +1710,29 @@ class SnapshotStorageDestination extends Component
{
>
- Snapshot settings
+ {Utilities.toTitleCase(featureName)} settings
-
- + Add a new destination
-
-
-
-
-
- Full (Instance) and Partial (Application) snapshots share
- share the same Velero configuration and storage destination.
-
+
+ {!isEmbeddedCluster && (
+
+ + Add a new destination
+
+ )}
+ {!isEmbeddedCluster && (
+
+
+
+ Full (Instance) and Partial (Application) snapshots share
+ the same Velero configuration and storage destination.
+
+
+
+ )}
Destination
@@ -1809,17 +1837,20 @@ class SnapshotStorageDestination extends Component {
>
)}
-
- All data in your snapshots will be deduplicated. Snapshots
- makes use of Restic, a fast and secure backup technology with
- native deduplication.
-
+ {!isEmbeddedCluster && (
+
+ All data in your snapshots will be deduplicated. Snapshots
+ makes use of Restic, a fast and secure backup technology
+ with native deduplication.
+
+ )}
{
const fakeProgressSnapshot = {
- name: "Preparing snapshot",
+ name: `Preparing ${this.props.isEmbeddedCluster ? "backup" : "snapshot"}`,
status: "InProgress",
trigger: "manual",
sequence: "",
@@ -519,7 +519,10 @@ class Snapshots extends Component {
return (
-
+
{!isVeleroCorrectVersion(snapshotSettings) ? (
@@ -538,7 +541,9 @@ class Snapshots extends Component {
- Full Snapshots (Instance){" "}
+ {this.props.isEmbeddedCluster
+ ? "Backups"
+ : "Full Snapshots (Instance)"}
@@ -569,7 +574,11 @@ class Snapshots extends Component {
>
{startingSnapshot
? "Starting a snapshot..."
- : "Start a snapshot"}
+ : `Start a ${
+ this.props.isEmbeddedCluster
+ ? "backup"
+ : "snapshot"
+ }`}
)}
@@ -588,18 +597,19 @@ class Snapshots extends Component {
- {" "}
- Full snapshots (Instance) back up the Admin Console and all
- application data. They can be used for full Disaster Recovery;
- by restoring over top of this instance, or into a new cluster.
-
- {" "}
- Learn more
-
- .
+ Back up the admin console and all application data for
+ disaster recovery.{" "}
+ {!this.props.isEmbeddedCluster && (
+ <>
+
+ Learn more
+
+ .
+ >
+ )}
@@ -618,6 +628,7 @@ class Snapshots extends Component {
snapshot={snapshot}
toggleConfirmDeleteModal={this.toggleConfirmDeleteModal}
toggleRestoreModal={this.toggleRestoreModal}
+ hideRestore={this.props.isEmbeddedCluster}
/>
))}
@@ -628,12 +639,14 @@ class Snapshots extends Component {
isVeleroInstalled={!!snapshotSettings?.veleroVersion}
history={this.props.history}
startInstanceSnapshot={this.startInstanceSnapshot}
+ isEmbeddedCluster={this.props.isEmbeddedCluster}
/>
)}
{this.state.deleteSnapshotModal && (
app.allowSnapshots);
const selectedApp =
@@ -36,6 +36,7 @@ class SnapshotsWrapper extends Component {
`/app/${slug}/registry-settings`,
- displayRule: ({ isHelmManaged }) => !isHelmManaged,
+ displayRule: ({ isHelmManaged, isEmbeddedCluster }) =>
+ !isHelmManaged && !isEmbeddedCluster,
},
{
tabName: "access",
diff --git a/web/src/features/Dashboard/components/Dashboard.tsx b/web/src/features/Dashboard/components/Dashboard.tsx
index 47c6ad87d1..42425a3d3c 100644
--- a/web/src/features/Dashboard/components/Dashboard.tsx
+++ b/web/src/features/Dashboard/components/Dashboard.tsx
@@ -712,6 +712,7 @@ const Dashboard = () => {
isSnapshotAllowed={
app.allowSnapshots && isVeleroInstalled
}
+ isEmbeddedCluster={isEmbeddedCluster}
/>
) : null}
diff --git a/web/src/features/Dashboard/components/DashboardSnapshotsCard.tsx b/web/src/features/Dashboard/components/DashboardSnapshotsCard.tsx
index 1b3717896b..f746b1f13d 100644
--- a/web/src/features/Dashboard/components/DashboardSnapshotsCard.tsx
+++ b/web/src/features/Dashboard/components/DashboardSnapshotsCard.tsx
@@ -26,7 +26,7 @@ const DESTINATIONS = [
},
{
value: "other",
- label: "Other S3-Compatible Storage",
+ label: "S3-Compatible Storage",
},
{
value: "internal",
@@ -45,6 +45,7 @@ const DESTINATIONS = [
type Props = {
app: App;
isSnapshotAllowed: boolean;
+ isEmbeddedCluster: boolean;
ping: (clusterId?: string) => void;
};
@@ -88,7 +89,7 @@ export const DashboardSnapshotsCard = (props: Props) => {
startSnapshotErrorMsg: "",
}
);
- const { app, ping, isSnapshotAllowed } = props;
+ const { app, ping, isSnapshotAllowed, isEmbeddedCluster } = props;
const { selectedDestination } = state;
const setCurrentProvider = (
@@ -101,7 +102,7 @@ export const DashboardSnapshotsCard = (props: Props) => {
if (store?.aws) {
return setState({
- readableName: find(DESTINATIONS, ["value", "aws"])?.label,
+ selectedDestination: find(DESTINATIONS, ["value", "aws"]),
locationStr: `${store?.bucket}${store?.path ? `/${store?.path}` : ""}`,
});
}
@@ -147,9 +148,13 @@ export const DashboardSnapshotsCard = (props: Props) => {
}
// if nothing exists yet, we've determined default state is good
+ let defaultDestination = "aws";
+ if (isEmbeddedCluster) {
+ defaultDestination = "other";
+ }
setState({
determiningDestination: false,
- selectedDestination: find(DESTINATIONS, ["value", "aws"]),
+ selectedDestination: find(DESTINATIONS, ["value", defaultDestination]),
});
};
@@ -221,7 +226,9 @@ export const DashboardSnapshotsCard = (props: Props) => {
return (
-
Snapshots
+
+ {isEmbeddedCluster ? "Disaster Recovery" : "Snapshots"}
+
{
size={16}
className="clickable u-marginRight--5"
/>
- Snapshot settings
+ {isEmbeddedCluster ? "Backup settings" : "Snapshot settings"}
-
- createSnapshot("partial"),
- },
- {
- displayText: "Start a Full snapshot",
- onClick: () => createSnapshot("full"),
- },
- {
- displayText: "Learn about the difference",
- onClick: () => toggleSnaphotDifferencesModal(),
- },
- ]}
- />
+ {!isEmbeddedCluster && (
+ <>
+
+ createSnapshot("partial"),
+ },
+ {
+ displayText: "Start a Full snapshot",
+ onClick: () => createSnapshot("full"),
+ },
+ {
+ displayText: "Learn about the difference",
+ onClick: () => toggleSnaphotDifferencesModal(),
+ },
+ ]}
+ />
+ >
+ )}
+ {isEmbeddedCluster && (
+ createSnapshot("full")}
+ to=""
+ >
+
+ Start backup
+
+ )}
-
-
+
+
+ {isSnapshotAllowed ? "Enabled" : "Disabled"}
+
+ >
+ )}
+
- {isSnapshotAllowed ? "Enabled" : "Disabled"}
-
-
@@ -296,7 +329,7 @@ export const DashboardSnapshotsCard = (props: Props) => {
- See all snapshots
+ See all {isEmbeddedCluster ? "backups" : "snapshots"}
= (args) => (
export const DeleteSnapshotModalExample = Template.bind({});
DeleteSnapshotModalExample.args = {
+ featureName: "snapshot",
deleteSnapshotModal: true,
toggleConfirmDeleteModal: () => alert("toggle modal"),
snapshotToDelete: {
diff --git a/web/src/utilities/utilities.js b/web/src/utilities/utilities.js
index 3c8f189c1d..e72dafffec 100644
--- a/web/src/utilities/utilities.js
+++ b/web/src/utilities/utilities.js
@@ -516,24 +516,6 @@ export function isVeleroCorrectVersion(snapshotSettings) {
return false;
}
-/**
- * Get readable label for a snapshot storage destination
- * @param {String} provider - storage provider string
- * @return {String}
- */
-export function getSnapshotDestinationLabel(provider) {
- const DESTINATIONS = {
- aws: "Amazon S3",
- azure: "Azure Blob Storage",
- gcp: "Google Cloud Storage",
- other: "Other S3-Compatible Storage",
- internal: "Internal Storage (Default)",
- nfs: "Network File System (NFS)",
- hostpath: "Host Path",
- };
- return DESTINATIONS[provider] || "Unknown storage provider";
-}
-
export const Utilities = {
getSessionRoles() {
if (this.localStorageEnabled()) {