Skip to content

Commit 528d3c8

Browse files
committed
Adds changes to VolumeSnapshot deletion and other changes
Signed-off-by: vbadrina <[email protected]>
1 parent 0efec1a commit 528d3c8

20 files changed

+896
-536
lines changed

frontend/packages/console-app/console-extensions.json

Lines changed: 14 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -411,13 +411,22 @@
411411
"kind": "StorageClass",
412412
"group": "storage.k8s.io"
413413
},
414-
<<<<<<< HEAD
415-
"provider": { "$codeRef": "storageClassProvider.useStorageClassActions" }
416-
=======
417414
"provider": {
418-
"$codeRef": "defaultProvider.useDefaultActionsProvider"
415+
"$codeRef": "storageClassProvider.useStorageClassActions"
416+
}
417+
}
418+
},
419+
{
420+
"type": "console.action/resource-provider",
421+
"properties": {
422+
"model": {
423+
"version": "v1",
424+
"kind": "VolumeSnapshot",
425+
"group": "snapshot.storage.k8s.io"
426+
},
427+
"provider": {
428+
"$codeRef": "volumeSnapshotActions.useVolumeSnapshotActions"
419429
}
420-
>>>>>>> 028e543d17 (Adds CRUD action support for VolumeGroupSnapshots)
421430
}
422431
},
423432
{

frontend/packages/console-app/locales/en/console-app.json

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -233,6 +233,7 @@
233233
"This action is only enabled when the latest revision of the ReplicationController resource is in a failed state.": "This action is only enabled when the latest revision of the ReplicationController resource is in a failed state.",
234234
"Current default StorageClass": "Current default StorageClass",
235235
"Set as default": "Set as default",
236+
"Cannot delete a snapshot that belongs to a VolumeGroupSnapshot. Delete the group instead.": "Cannot delete a snapshot that belongs to a VolumeGroupSnapshot. Delete the group instead.",
236237
"Access mode": "Access mode",
237238
"Cluster configuration": "Cluster configuration",
238239
"Set cluster-wide configuration for the console experience. Your changes will be autosaved and will affect after a refresh.": "Set cluster-wide configuration for the console experience. Your changes will be autosaved and will affect after a refresh.",
@@ -630,12 +631,36 @@
630631
"GroupSnapshot Class": "GroupSnapshot Class",
631632
"Persistent Volume Claim": "Persistent Volume Claim",
632633
"Select PVCs in the {{namespace}} namespace using label selectors to form a volume group to take VolumeGroupSnapshots.": "Select PVCs in the {{namespace}} namespace using label selectors to form a volume group to take VolumeGroupSnapshots.",
634+
"Filter PVCs by Label": "Filter PVCs by Label",
635+
"Expand to fix validation errors": "Expand to fix validation errors",
636+
"unknown": "unknown",
637+
"equals any of": "equals any of",
638+
"equals": "equals",
639+
"does not equal any of": "does not equal any of",
640+
"does not equal": "does not equal",
641+
"exists": "exists",
642+
"does not exist": "does not exist",
643+
"Expand to enter expression": "Expand to enter expression",
644+
"Select a label": "Select a label",
645+
"Operator": "Operator",
646+
"Values": "Values",
647+
"{{count}} selected_one": "{{count}} selected",
648+
"{{count}} selected_other": "{{count}} selecteds",
649+
"Select the values": "Select the values",
650+
"Add label expression": "Add label expression",
651+
"Source PVCs": "Source PVCs",
652+
"{{count}} more PVCs _one": "{{count}} more PVCs ",
653+
"{{count}} more PVCs _other": "{{count}} more PVCs s",
654+
"{{count}} PVCs_one": "{{count}} PVCs",
655+
"{{count}} PVCs_other": "{{count}} PVCs",
633656
"PVC Name": "PVC Name",
634657
"Storage class": "Storage class",
635658
"Applied filters:": "Applied filters:",
659+
"No PVCs have been selected": "No PVCs have been selected",
636660
"Error loading PVCs": "Error loading PVCs",
637661
"There was an error loading the PersistentVolumeClaims. Please try again.": "There was an error loading the PersistentVolumeClaims. Please try again.",
638662
"Filter PVCs with label selector expressions": "Filter PVCs with label selector expressions",
663+
"PVCs table": "PVCs table",
639664
"No PVCs have been identified for the volume group yet.": "No PVCs have been identified for the volume group yet.",
640665
"Use the label selector to filter and display PVCs that match your criteria. These PVCs will be used to form the volume group.": "Use the label selector to filter and display PVCs that match your criteria. These PVCs will be used to form the volume group.",
641666
"PVCs": "PVCs",

frontend/packages/console-app/package.json

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,8 @@
7171
"consolePluginProxyDetail": "src/components/console-operator/ConsolePluginProxyDetail.tsx",
7272
"getConsoleOperatorConfigFlag": "src/hooks/useCanGetConsoleOperatorConfig.ts",
7373
"usePerspectivesAvailable": "src/components/user-preferences/perspective/usePerspectivesAvailable.ts",
74-
"defaultProvider": "src/actions/providers/default-provider.ts"
74+
"defaultProvider": "src/actions/providers/default-provider.ts",
75+
"volumeSnapshotActions": "src/actions/providers/volume-snapshot-provider.ts"
7576
}
7677
}
7778
}
Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
import * as React from 'react';
2+
import { useTranslation } from 'react-i18next';
3+
import { Action } from '@console/dynamic-plugin-sdk';
4+
import { restorePVCModal } from '@console/internal/components/modals';
5+
import { asAccessReview } from '@console/internal/components/utils';
6+
import { K8sResourceKind, referenceFor, VolumeSnapshotKind } from '@console/internal/module/k8s';
7+
import { useK8sModel } from '@console/shared/src/hooks/useK8sModel';
8+
import { getCommonResourceActions } from '../creators/common-factory';
9+
10+
export const useVolumeSnapshotActions = (
11+
volumeSnapshot: K8sResourceKind,
12+
): [Action[], boolean, boolean] => {
13+
const [volumeSnapshotModel, inFlight] = useK8sModel(referenceFor(volumeSnapshot));
14+
const { t } = useTranslation();
15+
const isPartOfSnapshotGroup = React.useMemo(() => {
16+
return volumeSnapshot?.metadata?.ownerReferences?.some(
17+
(ref) => ref.kind === 'VolumeGroupSnapshot',
18+
);
19+
}, [volumeSnapshot]);
20+
21+
const allActions = React.useMemo(() => {
22+
if (!volumeSnapshotModel || inFlight) {
23+
return [];
24+
}
25+
26+
const RestorePVC: Action = {
27+
id: 'restore-pvc',
28+
label: t('console-app~Restore as new PVC'),
29+
cta: () =>
30+
restorePVCModal({
31+
kind: volumeSnapshotModel,
32+
resource: volumeSnapshot as VolumeSnapshotKind,
33+
}),
34+
disabled: !(volumeSnapshot as VolumeSnapshotKind)?.status?.readyToUse,
35+
tooltip: !(volumeSnapshot as VolumeSnapshotKind)?.status?.readyToUse
36+
? t('console-app~Volume Snapshot is not Ready')
37+
: undefined,
38+
accessReview: asAccessReview(volumeSnapshotModel, volumeSnapshot, 'create'),
39+
};
40+
41+
const actions = [RestorePVC, ...getCommonResourceActions(volumeSnapshotModel, volumeSnapshot)];
42+
43+
if (isPartOfSnapshotGroup) {
44+
return actions.map((action) => {
45+
if (action.id === 'delete-resource') {
46+
return {
47+
...action,
48+
disabled: true,
49+
disabledTooltip: t(
50+
'console-app~Cannot delete a snapshot that belongs to a VolumeGroupSnapshot. Delete the group instead.',
51+
),
52+
};
53+
}
54+
return action;
55+
});
56+
}
57+
58+
return actions;
59+
}, [t, volumeSnapshotModel, volumeSnapshot, inFlight, isPartOfSnapshotGroup]);
60+
61+
return [allActions, !inFlight, undefined];
62+
};

frontend/packages/console-app/src/components/access-modes/access-mode.tsx

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ export const getPVCAccessModes = (resource: PersistentVolumeClaimKind, key: stri
1919
_.reduce(
2020
resource?.spec?.accessModes,
2121
(res, value) => {
22-
const mode = getAccessModeOptions().find((accessMode) => accessMode.value === value);
22+
const mode = getAccessModeOptions()?.find((accessMode) => accessMode.value === value);
2323
if (mode) {
2424
res.push(mode[key]);
2525
}
@@ -59,9 +59,15 @@ export const AccessModeSelector: React.FC<AccessModeSelectorProps> = (props) =>
5959
);
6060

6161
const [isOpen, setIsOpen] = React.useState(false);
62-
const [selected, setSelected] = React.useState<string>(
63-
getAccessModeOptions().find((mode) => mode.value === pvcInitialAccessMode[0]).title,
64-
);
62+
63+
// Fix: Add a null check and provide a default value if the mode isn't found as in case of VolumeSnapshotGroup
64+
const defaultOption = getAccessModeOptions()[0] || { title: '', value: '' };
65+
const foundMode =
66+
pvcInitialAccessMode?.length > 0
67+
? getAccessModeOptions().find((mode) => mode.value === pvcInitialAccessMode[0])
68+
: null;
69+
70+
const [selected, setSelected] = React.useState<string>(foundMode?.title || defaultOption.title);
6571

6672
const onToggleClick = () => {
6773
setIsOpen(!isOpen);
@@ -115,11 +121,15 @@ export const AccessModeSelector: React.FC<AccessModeSelectorProps> = (props) =>
115121

116122
React.useEffect(() => {
117123
// Make sure the default or already checked option button value is from any one of allowed the access mode
118-
if (allowedAccessModes) {
119-
if (!accessMode && allowedAccessModes.includes(pvcInitialAccessMode[0])) {
124+
if (allowedAccessModes?.length) {
125+
if (
126+
!accessMode &&
127+
pvcInitialAccessMode?.length &&
128+
allowedAccessModes.includes(pvcInitialAccessMode[0])
129+
) {
120130
// To view the same access mode value of pvc
121131
changeAccessMode(pvcInitialAccessMode[0]);
122-
} else if (!allowedAccessModes.includes(accessMode)) {
132+
} else if (!accessMode || !allowedAccessModes.includes(accessMode)) {
123133
// Old access mode will be disabled
124134
changeAccessMode(allowedAccessModes[0]);
125135
}
@@ -133,7 +143,7 @@ export const AccessModeSelector: React.FC<AccessModeSelectorProps> = (props) =>
133143
fieldId="access-mode"
134144
className={className}
135145
>
136-
{loaded && allowedAccessModes && (
146+
{loaded && allowedAccessModes?.length > 0 && (
137147
<Select
138148
isOpen={isOpen}
139149
selected={selected}
@@ -147,12 +157,12 @@ export const AccessModeSelector: React.FC<AccessModeSelectorProps> = (props) =>
147157
</Select>
148158
)}
149159

150-
{allowedAccessModes && allowedAccessModes && description && (
160+
{allowedAccessModes?.length > 0 && description && (
151161
<p className="help-block" id="access-mode-help">
152162
{description}
153163
</p>
154164
)}
155-
{(!loaded || !allowedAccessModes) && <div className="skeleton-text" />}
165+
{(!loaded || !allowedAccessModes?.length) && <div className="skeleton-text" />}
156166
</FormGroup>
157167
);
158168
};

0 commit comments

Comments
 (0)