Skip to content

Commit ea2a362

Browse files
committed
Improve VAC field on PVC details page
1 parent d00353d commit ea2a362

File tree

2 files changed

+109
-10
lines changed

2 files changed

+109
-10
lines changed

frontend/public/components/persistent-volume-claim.tsx

Lines changed: 102 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,11 @@
1-
import { useMemo, useCallback, Suspense } from 'react';
1+
import { useMemo, useCallback, Suspense, useState, useEffect } from 'react';
22
import * as _ from 'lodash';
33
import i18next, { TFunction } from 'i18next';
44
import { useTranslation } from 'react-i18next';
55
import { useDispatch, useSelector } from 'react-redux';
66
import {
7+
Alert,
8+
AlertActionCloseButton,
79
DescriptionList,
810
DescriptionListDescription,
911
DescriptionListGroup,
@@ -76,6 +78,30 @@ const tableColumnInfo = [
7678
{ id: '' },
7779
];
7880

81+
/**
82+
* Determines the VAC (VolumeAttributesClass) modification state for a PVC
83+
* @param pvc - The PersistentVolumeClaim resource
84+
* @returns Object containing error condition and pending state
85+
*/
86+
const getVACAlertState = (pvc: PersistentVolumeClaimKind) => {
87+
const volumeAttributesClassName = pvc?.spec?.volumeAttributesClassName;
88+
const currentVolumeAttributesClassName = pvc?.status?.currentVolumeAttributesClassName;
89+
const conditions = pvc?.status?.conditions;
90+
91+
// Check for explicit ModifyVolumeError condition
92+
const vacErrorCondition = conditions?.find(
93+
(condition) => condition.type === 'ModifyVolumeError' && condition.status === 'True',
94+
);
95+
96+
// Determine if modification is pending
97+
const isVacPending =
98+
!vacErrorCondition &&
99+
volumeAttributesClassName &&
100+
volumeAttributesClassName !== currentVolumeAttributesClassName;
101+
102+
return { vacErrorCondition, isVacPending };
103+
};
104+
79105
export const PVCStatusComponent: React.FCC<PVCStatusProps> = ({ pvc }) => {
80106
const { t } = useTranslation();
81107
const [pvcStatusExtensions, resolved] = useResolvedExtensions<PVCStatus>(isPVCStatus);
@@ -249,6 +275,16 @@ const PVCDetails: React.FCC<PVCDetailsProps> = ({ obj: pvc }) => {
249275
const volumeMode = pvc?.spec?.volumeMode;
250276
const conditions = pvc?.status?.conditions;
251277

278+
// State to track dismissed alerts
279+
const [isErrorAlertDismissed, setIsErrorAlertDismissed] = useState(false);
280+
const [isInfoAlertDismissed, setIsInfoAlertDismissed] = useState(false);
281+
282+
// Reset alert dismiss states when PVC changes
283+
useEffect(() => {
284+
setIsErrorAlertDismissed(false);
285+
setIsInfoAlertDismissed(false);
286+
}, [pvc?.metadata?.uid]);
287+
252288
const query =
253289
name && namespace
254290
? `kubelet_volume_stats_used_bytes{persistentvolumeclaim='${name}',namespace='${namespace}'}`
@@ -288,10 +324,51 @@ const PVCDetails: React.FCC<PVCDetailsProps> = ({ obj: pvc }) => {
288324
({ properties: { alert: AlertComponent }, uid }) => <AlertComponent key={uid} pvc={pvc} />,
289325
);
290326

327+
// Get VAC modification state using helper function
328+
const { vacErrorCondition, isVacPending } = getVACAlertState(pvc);
329+
291330
return (
292331
<>
293332
<PaneBody>
294333
{alertComponents}
334+
{isVACSupported && vacErrorCondition && !isErrorAlertDismissed && (
335+
<Alert
336+
isInline
337+
variant="danger"
338+
title={t('public~VolumeAttributesClass modification failed')}
339+
className="co-alert co-alert--margin-bottom-sm"
340+
actionClose={<AlertActionCloseButton onClose={() => setIsErrorAlertDismissed(true)} />}
341+
>
342+
{t(
343+
'public~VolumeAttributesClass modification failed. Your volume settings could not be updated. Please try again.',
344+
)}
345+
</Alert>
346+
)}
347+
{isVACSupported && isVacPending && !isInfoAlertDismissed && (
348+
<Alert
349+
isInline
350+
variant="info"
351+
title={
352+
volumeAttributesClassName && !currentVolumeAttributesClassName
353+
? t('public~VolumeAttributesClass application pending')
354+
: t('public~VolumeAttributesClass modification in progress')
355+
}
356+
className="co-alert co-alert--margin-bottom-sm"
357+
actionClose={<AlertActionCloseButton onClose={() => setIsInfoAlertDismissed(true)} />}
358+
>
359+
{!currentVolumeAttributesClassName
360+
? t('public~VolumeAttributesClass "{{target}}" is pending application.', {
361+
target: volumeAttributesClassName,
362+
})
363+
: t(
364+
'public~Your volume settings are being updated from "{{current}}" to "{{target}}". This may take a few moments.',
365+
{
366+
current: currentVolumeAttributesClassName,
367+
target: volumeAttributesClassName,
368+
},
369+
)}
370+
</Alert>
371+
)}
295372
<SectionHeading text={t('public~PersistentVolumeClaim details')} />
296373
{totalCapacityMetric && !loading && (
297374
<div className="co-pvc-donut">
@@ -383,19 +460,34 @@ const PVCDetails: React.FCC<PVCDetailsProps> = ({ obj: pvc }) => {
383460
)}
384461
</DescriptionListDescription>
385462
</DescriptionListGroup>
386-
{isVACSupported &&
387-
!!volumeAttributesClassName &&
388-
volumeAttributesClassName === currentVolumeAttributesClassName && (
389-
<DescriptionListGroup>
390-
<DescriptionListTerm>{t('public~VolumeAttributesClass')}</DescriptionListTerm>
391-
<DescriptionListDescription>
463+
{isVACSupported && volumeAttributesClassName !== currentVolumeAttributesClassName && (
464+
<DescriptionListGroup>
465+
<DescriptionListTerm>
466+
{t('public~Requested VolumeAttributesClass')}
467+
</DescriptionListTerm>
468+
<DescriptionListDescription data-test-id="pvc-requested-vac">
469+
{volumeAttributesClassName ? (
392470
<ResourceLink
393471
kind={referenceFor(VolumeAttributesClassModel)}
394472
name={volumeAttributesClassName}
395473
/>
396-
</DescriptionListDescription>
397-
</DescriptionListGroup>
398-
)}
474+
) : (
475+
DASH
476+
)}
477+
</DescriptionListDescription>
478+
</DescriptionListGroup>
479+
)}
480+
{isVACSupported && !!currentVolumeAttributesClassName && (
481+
<DescriptionListGroup>
482+
<DescriptionListTerm>{t('public~VolumeAttributesClass')}</DescriptionListTerm>
483+
<DescriptionListDescription data-test-id="pvc-current-vac">
484+
<ResourceLink
485+
kind={referenceFor(VolumeAttributesClassModel)}
486+
name={currentVolumeAttributesClassName}
487+
/>
488+
</DescriptionListDescription>
489+
</DescriptionListGroup>
490+
)}
399491
{volumeName && canListPV && (
400492
<DescriptionListGroup>
401493
<DescriptionListTerm>{t('public~PersistentVolumes')}</DescriptionListTerm>

frontend/public/locales/en/public.json

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1128,6 +1128,12 @@
11281128
"Used": "Used",
11291129
"StorageClass": "StorageClass",
11301130
"Total": "Total",
1131+
"VolumeAttributesClass modification failed": "VolumeAttributesClass modification failed",
1132+
"VolumeAttributesClass modification failed. Your volume settings could not be updated. Please try again.": "VolumeAttributesClass modification failed. Your volume settings could not be updated. Please try again.",
1133+
"VolumeAttributesClass application pending": "VolumeAttributesClass application pending",
1134+
"VolumeAttributesClass modification in progress": "VolumeAttributesClass modification in progress",
1135+
"VolumeAttributesClass \"{{target}}\" is pending application.": "VolumeAttributesClass \"{{target}}\" is pending application.",
1136+
"Your volume settings are being updated from \"{{current}}\" to \"{{target}}\". This may take a few moments.": "Your volume settings are being updated from \"{{current}}\" to \"{{target}}\". This may take a few moments.",
11311137
"PersistentVolumeClaim details": "PersistentVolumeClaim details",
11321138
"Available versus used capacity": "Available versus used capacity",
11331139
"Total capacity": "Total capacity",
@@ -1136,6 +1142,7 @@
11361142
"Access modes": "Access modes",
11371143
"Volume mode": "Volume mode",
11381144
"StorageClasses": "StorageClasses",
1145+
"Requested VolumeAttributesClass": "Requested VolumeAttributesClass",
11391146
"VolumeAttributesClass": "VolumeAttributesClass",
11401147
"PersistentVolumes": "PersistentVolumes",
11411148
"Bound": "Bound",

0 commit comments

Comments
 (0)