Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
112 changes: 102 additions & 10 deletions frontend/public/components/persistent-volume-claim.tsx
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
import { useMemo, useCallback, Suspense } from 'react';
import { useMemo, useCallback, Suspense, useState, useEffect } from 'react';
import * as _ from 'lodash';
import i18next, { TFunction } from 'i18next';
import { useTranslation } from 'react-i18next';
import { useDispatch, useSelector } from 'react-redux';
import {
Alert,
AlertActionCloseButton,
DescriptionList,
DescriptionListDescription,
DescriptionListGroup,
Expand Down Expand Up @@ -76,6 +78,30 @@ const tableColumnInfo = [
{ id: '' },
];

/**
* Determines the VAC (VolumeAttributesClass) modification state for a PVC
* @param pvc - The PersistentVolumeClaim resource
* @returns Object containing error condition and pending state
*/
const getVACAlertState = (pvc: PersistentVolumeClaimKind) => {
const volumeAttributesClassName = pvc?.spec?.volumeAttributesClassName;
const currentVolumeAttributesClassName = pvc?.status?.currentVolumeAttributesClassName;
const conditions = pvc?.status?.conditions;

// Check for explicit ModifyVolumeError condition
const vacErrorCondition = conditions?.find(
(condition) => condition.type === 'ModifyVolumeError' && condition.status === 'True',
);

// Determine if modification is pending
const isVacPending =
!vacErrorCondition &&
volumeAttributesClassName &&
volumeAttributesClassName !== currentVolumeAttributesClassName;

return { vacErrorCondition, isVacPending };
};

export const PVCStatusComponent: React.FCC<PVCStatusProps> = ({ pvc }) => {
const { t } = useTranslation();
const [pvcStatusExtensions, resolved] = useResolvedExtensions<PVCStatus>(isPVCStatus);
Expand Down Expand Up @@ -249,6 +275,16 @@ const PVCDetails: React.FCC<PVCDetailsProps> = ({ obj: pvc }) => {
const volumeMode = pvc?.spec?.volumeMode;
const conditions = pvc?.status?.conditions;

// State to track dismissed alerts
const [isErrorAlertDismissed, setIsErrorAlertDismissed] = useState(false);
const [isInfoAlertDismissed, setIsInfoAlertDismissed] = useState(false);

// Reset alert dismiss states when PVC changes
useEffect(() => {
setIsErrorAlertDismissed(false);
setIsInfoAlertDismissed(false);
}, [pvc?.metadata?.uid]);

const query =
name && namespace
? `kubelet_volume_stats_used_bytes{persistentvolumeclaim='${name}',namespace='${namespace}'}`
Expand Down Expand Up @@ -288,10 +324,51 @@ const PVCDetails: React.FCC<PVCDetailsProps> = ({ obj: pvc }) => {
({ properties: { alert: AlertComponent }, uid }) => <AlertComponent key={uid} pvc={pvc} />,
);

// Get VAC modification state using helper function
const { vacErrorCondition, isVacPending } = getVACAlertState(pvc);

return (
<>
<PaneBody>
{alertComponents}
{isVACSupported && vacErrorCondition && !isErrorAlertDismissed && (
<Alert
isInline
variant="danger"
title={t('public~VolumeAttributesClass modification failed')}
className="co-alert co-alert--margin-bottom-sm"
actionClose={<AlertActionCloseButton onClose={() => setIsErrorAlertDismissed(true)} />}
>
{t(
'public~VolumeAttributesClass modification failed. Your volume settings could not be updated. Please try again.',
)}
</Alert>
)}
{isVACSupported && isVacPending && !isInfoAlertDismissed && (
<Alert
isInline
variant="info"
title={
volumeAttributesClassName && !currentVolumeAttributesClassName
? t('public~VolumeAttributesClass application pending')
: t('public~VolumeAttributesClass modification in progress')
}
className="co-alert co-alert--margin-bottom-sm"
actionClose={<AlertActionCloseButton onClose={() => setIsInfoAlertDismissed(true)} />}
>
{!currentVolumeAttributesClassName
? t('public~VolumeAttributesClass "{{target}}" is pending application.', {
target: volumeAttributesClassName,
})
: t(
'public~Your volume settings are being updated from "{{current}}" to "{{target}}". This may take a few moments.',
{
current: currentVolumeAttributesClassName,
target: volumeAttributesClassName,
},
)}
</Alert>
)}
<SectionHeading text={t('public~PersistentVolumeClaim details')} />
{totalCapacityMetric && !loading && (
<div className="co-pvc-donut">
Expand Down Expand Up @@ -383,19 +460,34 @@ const PVCDetails: React.FCC<PVCDetailsProps> = ({ obj: pvc }) => {
)}
</DescriptionListDescription>
</DescriptionListGroup>
{isVACSupported &&
!!volumeAttributesClassName &&
volumeAttributesClassName === currentVolumeAttributesClassName && (
<DescriptionListGroup>
<DescriptionListTerm>{t('public~VolumeAttributesClass')}</DescriptionListTerm>
<DescriptionListDescription>
{isVACSupported && volumeAttributesClassName !== currentVolumeAttributesClassName && (
<DescriptionListGroup>
<DescriptionListTerm>
{t('public~Requested VolumeAttributesClass')}
</DescriptionListTerm>
<DescriptionListDescription data-test-id="pvc-requested-vac">
{volumeAttributesClassName ? (
<ResourceLink
kind={referenceFor(VolumeAttributesClassModel)}
name={volumeAttributesClassName}
/>
</DescriptionListDescription>
</DescriptionListGroup>
)}
) : (
DASH
)}
</DescriptionListDescription>
</DescriptionListGroup>
)}
{isVACSupported && !!currentVolumeAttributesClassName && (
<DescriptionListGroup>
<DescriptionListTerm>{t('public~VolumeAttributesClass')}</DescriptionListTerm>
<DescriptionListDescription data-test-id="pvc-current-vac">
<ResourceLink
kind={referenceFor(VolumeAttributesClassModel)}
name={currentVolumeAttributesClassName}
/>
</DescriptionListDescription>
</DescriptionListGroup>
)}
{volumeName && canListPV && (
<DescriptionListGroup>
<DescriptionListTerm>{t('public~PersistentVolumes')}</DescriptionListTerm>
Expand Down
7 changes: 7 additions & 0 deletions frontend/public/locales/en/public.json
Original file line number Diff line number Diff line change
Expand Up @@ -1128,6 +1128,12 @@
"Used": "Used",
"StorageClass": "StorageClass",
"Total": "Total",
"VolumeAttributesClass modification failed": "VolumeAttributesClass modification failed",
"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.",
"VolumeAttributesClass application pending": "VolumeAttributesClass application pending",
"VolumeAttributesClass modification in progress": "VolumeAttributesClass modification in progress",
"VolumeAttributesClass \"{{target}}\" is pending application.": "VolumeAttributesClass \"{{target}}\" is pending application.",

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For the application pending alert:
"VolumeAttributesClass application in progress
{{target}} is being applied to replace {{current}}. Your volume remains available during this update." WYDT @kevinhatchoua @cajieh ?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

@wolfeallison Actually, the "Pending" state is different form the "inProgress".

Pending: The volume modification cannot proceed because of unmet requirements or conditions. For example, this could mean the specified VolumeAttributesClass does not exist or there are other resource constraints preventing the operation from starting .i.e. Unbound PVC.

InProgress: The volume modification is actively being carried out by the underlying Container Storage Interface (CSI) driver and the storage provider. The operation has started and is currently running.

This message would be appropriate for the 'inProgress' alert. I can add that.
Thank you for sharing.

"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.",
"PersistentVolumeClaim details": "PersistentVolumeClaim details",
"Available versus used capacity": "Available versus used capacity",
"Total capacity": "Total capacity",
Expand All @@ -1136,6 +1142,7 @@
"Access modes": "Access modes",
"Volume mode": "Volume mode",
"StorageClasses": "StorageClasses",
"Requested VolumeAttributesClass": "Requested VolumeAttributesClass",
"VolumeAttributesClass": "VolumeAttributesClass",
"PersistentVolumes": "PersistentVolumes",
"Bound": "Bound",
Expand Down