Skip to content

Commit

Permalink
Cluster storage that was disconnected from the workbench doesn't upda…
Browse files Browse the repository at this point in the history
…te it's size info
  • Loading branch information
dpanshug committed Nov 19, 2024
1 parent fbeb889 commit d77bc2b
Show file tree
Hide file tree
Showing 6 changed files with 78 additions and 3 deletions.
13 changes: 13 additions & 0 deletions frontend/src/__tests__/cypress/cypress/pages/clusterStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ class ClusterStorageRow extends TableRow {
findStorageClassResourceKindText() {
return cy.findByTestId('resource-kind-text');
}

findStorageSizeWarning() {
return cy.findByTestId('size-warning-popover').click();
}

findStorageSizeWarningText() {
return cy
.findByTestId('size-warning-popover-text')
.should(
'have.text',
'To complete the storage size update, you must connect and run a workbench.',
);
}
}

class ClusterStorageModal extends Modal {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,28 @@ const initInterceptors = ({ isEmpty = false, storageClassName }: HandlersProps)
storageClassName,
status: { phase: 'Pending' },
}),
mockPVCK8sResource({
displayName: 'Updated storage with no workbench',
storageClassName,
storage: '13Gi',
status: {
phase: 'Bound',
accessModes: ['ReadWriteOnce'],
capacity: {
storage: '12Gi',
},
conditions: [
{
type: 'FileSystemResizePending',
status: 'True',
lastProbeTime: null,
lastTransitionTime: '2024-11-15T14:04:04Z',
message:
'Waiting for user to (re-)start a pod to finish file system resize of volume on node.',
},
],
},
}),
],
),
);
Expand Down Expand Up @@ -334,6 +356,18 @@ describe('ClusterStorage', () => {
clusterStorage.findClusterStorageTableHeaderButton('Name').should(be.sortDescending);
});

it('should show warning when cluster storage size is updated but no workbench is connected', () => {
initInterceptors({});
clusterStorage.visit('test-project');
const clusterStorageRow = clusterStorage.getClusterStorageRow(
'Updated storage with no workbench',
);
clusterStorageRow.toggleExpandableContent();
clusterStorageRow.shouldHaveStorageSize('Max 13Gi');
clusterStorageRow.findStorageSizeWarning();
clusterStorageRow.findStorageSizeWarning().should('exist');
});

it('Edit cluster storage', () => {
initInterceptors({});
clusterStorage.visit('test-project');
Expand Down
4 changes: 3 additions & 1 deletion frontend/src/concepts/dashboard/DashboardPopupIconButton.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,17 +3,19 @@ import { Button, ButtonProps, Icon } from '@patternfly/react-core';

type DashboardPopupIconButtonProps = Omit<ButtonProps, 'variant' | 'isInline' | 'style'> & {
icon: React.ReactNode;
iconStatus?: 'custom' | 'info' | 'success' | 'warning' | 'danger';
};

/**
* Overriding PF's button styles to allow for a11y in opening tooltips or popovers on a single item
*/
const DashboardPopupIconButton = ({
icon,
iconStatus,
...props
}: DashboardPopupIconButtonProps): React.JSX.Element => (
<Button variant="plain" isInline style={{ padding: 0 }} {...props}>
<Icon isInline style={{ marginLeft: 'var(--pf-v5-global--spacer--xs)' }}>
<Icon isInline style={{ marginLeft: 'var(--pf-v5-global--spacer--xs)' }} status={iconStatus}>
{icon}
</Icon>
</Button>
Expand Down
1 change: 1 addition & 0 deletions frontend/src/k8sTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -311,6 +311,7 @@ export type PersistentVolumeClaimKind = K8sResourceCommon & {
capacity?: {
storage: string;
};
conditions?: K8sCondition[];
} & Record<string, unknown>;
};

Expand Down
26 changes: 24 additions & 2 deletions frontend/src/pages/projects/components/StorageSizeBars.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
import * as React from 'react';
import {
Bullseye,
Popover,
Progress,
ProgressMeasureLocation,
Spinner,
Expand All @@ -9,11 +10,12 @@ import {
Text,
Tooltip,
} from '@patternfly/react-core';
import { ExclamationCircleIcon } from '@patternfly/react-icons';
import { ExclamationCircleIcon, ExclamationTriangleIcon } from '@patternfly/react-icons';
import { PersistentVolumeClaimKind } from '~/k8sTypes';
import { getPvcTotalSize } from '~/pages/projects/utils';
import { getPvcRequestSize, getPvcTotalSize } from '~/pages/projects/utils';
import { usePVCFreeAmount } from '~/api';
import { bytesAsRoundedGiB } from '~/utilities/number';
import DashboardPopupIconButton from '~/concepts/dashboard/DashboardPopupIconButton';

type StorageSizeBarProps = {
pvc: PersistentVolumeClaimKind;
Expand All @@ -22,6 +24,7 @@ type StorageSizeBarProps = {
const StorageSizeBar: React.FC<StorageSizeBarProps> = ({ pvc }) => {
const [inUseInBytes, loaded, error] = usePVCFreeAmount(pvc);
const maxValue = getPvcTotalSize(pvc);
const requestedValue = getPvcRequestSize(pvc);

if (!error && Number.isNaN(inUseInBytes)) {
return (
Expand All @@ -33,6 +36,25 @@ const StorageSizeBar: React.FC<StorageSizeBarProps> = ({ pvc }) => {
);
}

if (pvc.status?.conditions?.find((c) => c.type === 'FileSystemResizePending')) {
return (
<div>
<Text component="small">Max {requestedValue}</Text>
<Popover
bodyContent="To complete the storage size update, you must connect and run a workbench."
data-testid="size-warning-popover-text"
>
<DashboardPopupIconButton
icon={<ExclamationTriangleIcon />}
aria-label="Size warning"
iconStatus="warning"
data-testid="size-warning-popover"
/>
</Popover>
</div>
);
}

const inUseValue = `${bytesAsRoundedGiB(inUseInBytes)}GiB`;
const percentage = ((parseFloat(inUseValue) / parseFloat(maxValue)) * 100).toFixed(2);
const percentageLabel = error ? '' : `Storage is ${percentage}% full`;
Expand Down
3 changes: 3 additions & 0 deletions frontend/src/pages/projects/utils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@ export const getNotebookStatusPriority = (notebookState: NotebookState): number
export const getPvcTotalSize = (pvc: PersistentVolumeClaimKind): string =>
formatMemory(pvc.status?.capacity?.storage || pvc.spec.resources.requests.storage);

export const getPvcRequestSize = (pvc: PersistentVolumeClaimKind): string =>
formatMemory(pvc.spec.resources.requests.storage);

export const getCustomNotebookSize = (
existingNotebook: NotebookKind | undefined,
): NotebookSize => ({
Expand Down

0 comments on commit d77bc2b

Please sign in to comment.