Skip to content

Commit

Permalink
Enhance hardware profile migration and configuration
Browse files Browse the repository at this point in the history
- Update config route to support cache control and force refresh
- Modify migration tooltip to improve user experience
- Remove out-of-the-box (OOTB) hardware profile specific logic
- Update hardware profile table row and migration utilities
- Add tooltips and help text for node resource configuration
- Improve dashboard config service to support force refresh
  • Loading branch information
Gkrumbach07 committed Feb 27, 2025
1 parent 4dfb76e commit afb43fa
Show file tree
Hide file tree
Showing 17 changed files with 385 additions and 284 deletions.
10 changes: 8 additions & 2 deletions backend/src/routes/api/config/index.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,20 @@
import { FastifyReply, FastifyRequest } from 'fastify';
import { setDashboardConfig } from './configUtils';
import { KubeFastifyInstance } from '../../../types';
import { getDashboardConfig } from '../../../utils/resourceUtils';
import { getDashboardConfig, updateDashboardConfig } from '../../../utils/resourceUtils';
import { secureAdminRoute, secureRoute } from '../../../utils/route-security';

module.exports = async (fastify: KubeFastifyInstance) => {
fastify.get(
'/',
secureRoute(fastify)(async (request: FastifyRequest, reply: FastifyReply) => {
reply.send(getDashboardConfig());
const forceRefresh = request.headers['cache-control'] === 'no-cache';

if (forceRefresh) {
await updateDashboardConfig();
}

reply.header('Cache-Control', 'no-cache').send(getDashboardConfig(request));
}),
);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -203,9 +203,6 @@ describe('Hardware Profile', () => {
name: 'Test Hardware Profile - 1',
displayName: 'Test Hardware Profile - 1',
description: 'hardware profile 1',
labels: {
'opendatahub.io/ootb': 'true',
},
identifiers: [
{
displayName: 'CPU',
Expand Down Expand Up @@ -239,9 +236,6 @@ describe('Hardware Profile', () => {
name: 'Test Hardware Profile - 1',
displayName: 'Test Hardware Profile - 1',
description: 'hardware profile 1',
labels: {
'opendatahub.io/ootb': 'true',
},
identifiers: [
{
displayName: 'CPU',
Expand Down Expand Up @@ -286,37 +280,6 @@ describe('Hardware Profile', () => {
);
});

it('restore hardware profile', () => {
cy.interceptK8sList(
{ model: HardwareProfileModel, ns: 'opendatahub' },
mockK8sResourceList([
mockHardwareProfile({
name: 'test-hardware-profile-restore',
displayName: 'Test Hardware Profile Restore',
labels: {
'opendatahub.io/ootb': 'true',
},
identifiers: [],
}),
]),
);
cy.interceptK8s(
'PUT',
{
model: HardwareProfileModel,
ns: 'opendatahub',
name: 'test-hardware-profile-restore',
},
mock200Status({}),
).as('restore');
hardwareProfile.visit();
const row = hardwareProfile.getRow('Test Hardware Profile Restore');
row.findEnableSwitch().should('not.be.checked');
row.findWarningIconButton().click();
hardwareProfile.findRestoreDefaultHardwareProfileButton().click();
cy.wait('@restore');
});

it('shows errors for all invalid.', () => {
const mockedHardwareProfiles = [
mockHardwareProfile({
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/pages/clusterSettings/ClusterSettings.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -239,7 +239,7 @@ const ClusterSettings: React.FC = () => {
/>
</StackItem>
)}
{isJupyterEnabled && isHardwareProfileEnabled && (
{isJupyterEnabled && !isHardwareProfileEnabled && (
<StackItem>
<TolerationSettings
initialValue={clusterSettings.notebookTolerationSettings}
Expand Down
58 changes: 22 additions & 36 deletions frontend/src/pages/hardwareProfiles/DeleteHardwareProfileModal.tsx
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import React from 'react';
import { Alert, Stack, StackItem } from '@patternfly/react-core';
import { Stack, StackItem } from '@patternfly/react-core';
import { deleteHardwareProfile } from '~/api';
import { HardwareProfileKind } from '~/k8sTypes';
import DeleteModal from '~/pages/projects/components/DeleteModal';
Expand All @@ -11,26 +11,6 @@ type DeleteHardwareProfileModalProps = {
onClose: (deleted: boolean) => void;
};

const migrationAlertMessage = (migrationAction: MigrationAction) => {
switch (migrationAction.source.type) {
case MigrationSourceType.ACCELERATOR_PROFILE:
return (
<>
This action will delete the source accelerator profile,{' '}
<b>{migrationAction.source.resource.metadata?.name ?? migrationAction.source.label}</b>,
resulting in any dependent translated hardware profiles being lost.
</>
);
case MigrationSourceType.SERVING_CONTAINER_SIZE:
case MigrationSourceType.NOTEBOOK_CONTAINER_SIZE:
return (
<>
This action will delete the source container size, <b>{migrationAction.source.label}</b>,
from the dashboard config.
</>
);
}
};
const DeleteHardwareProfileModal: React.FC<DeleteHardwareProfileModalProps> = ({
hardwareProfile,
migrationAction,
Expand All @@ -47,9 +27,14 @@ const DeleteHardwareProfileModal: React.FC<DeleteHardwareProfileModalProps> = ({

return (
<DeleteModal
title="Delete hardware profile?"
title={migrationAction ? 'Delete hardware profile and source?' : 'Delete hardware profile?'}
onClose={() => onBeforeClose(false)}
submitButtonLabel="Delete"
deleteName={
migrationAction
? `Delete ${migrationAction.targetProfiles.length + 1} and hardware profile`
: hardwareProfile.spec.displayName
}
onDelete={() => {
setIsDeleting(true);

Expand All @@ -75,24 +60,25 @@ const DeleteHardwareProfileModal: React.FC<DeleteHardwareProfileModalProps> = ({
}}
deleting={isDeleting}
error={error}
deleteName={hardwareProfile.spec.displayName}
>
<Stack hasGutter>
<StackItem>
This action cannot be undone. Workloads already deployed using this profile will not be
affected by this action.
{migrationAction ? (
<>
The <b>{hardwareProfile.spec.displayName}</b> simulated hardware profile and its
source
{migrationAction.source.type === MigrationSourceType.ACCELERATOR_PROFILE
? ' accelerator profile'
: migrationAction.source.type === MigrationSourceType.SERVING_CONTAINER_SIZE
? ' model serving container size'
: ' notebook container size'}
, {migrationAction.source.label}, will be deleted. Deployed workloads using this
profile will not be affected.
</>
) : (
'This action cannot be undone. Workloads already deployed using this profile will not be affected by this action.'
)}
</StackItem>
{migrationAction && (
<StackItem>
<Alert
isInline
variant="warning"
title="You are deleting a translated hardware profile's source."
>
{migrationAlertMessage(migrationAction)}
</Alert>
</StackItem>
)}
</Stack>
</DeleteModal>
);
Expand Down
11 changes: 11 additions & 0 deletions frontend/src/pages/hardwareProfiles/HardwareProfilesTable.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ import HardwareProfilesTableRow from '~/pages/hardwareProfiles/HardwareProfilesT
import DeleteHardwareProfileModal from '~/pages/hardwareProfiles/DeleteHardwareProfileModal';
import HardwareProfilesToolbar from '~/pages/hardwareProfiles/HardwareProfilesToolbar';
import { MigrationAction } from './migration/types';
import MigrationModal from './migration/MigrationModal';

type HardwareProfilesTableProps = {
hardwareProfiles: HardwareProfileKind[];
Expand All @@ -25,6 +26,9 @@ const HardwareProfilesTable: React.FC<HardwareProfilesTableProps> = ({
const [deleteHardwareProfile, setDeleteHardwareProfile] = React.useState<
{ hardwareProfile: HardwareProfileKind; migrationAction?: MigrationAction } | undefined
>();
const [migrateModalMigrationAction, setMigrateModalMigrationAction] = React.useState<
MigrationAction | undefined
>();
const [filterData, setFilterData] = React.useState<HardwareProfileFilterDataType>(
initialHardwareProfileFilterData,
);
Expand Down Expand Up @@ -83,6 +87,7 @@ const HardwareProfilesTable: React.FC<HardwareProfilesTableProps> = ({
handleDelete={(hardwareProfile) =>
setDeleteHardwareProfile({ hardwareProfile, migrationAction })
}
handleMigrate={(ma) => setMigrateModalMigrationAction(ma)}
migrationAction={migrationAction}
/>
);
Expand All @@ -91,6 +96,12 @@ const HardwareProfilesTable: React.FC<HardwareProfilesTableProps> = ({
<HardwareProfilesToolbar onFilterUpdate={onFilterUpdate} filterData={filterData} />
}
/>
{migrateModalMigrationAction && (
<MigrationModal
migrationAction={migrateModalMigrationAction}
onClose={() => setMigrateModalMigrationAction(undefined)}
/>
)}
{deleteHardwareProfile ? (
<DeleteHardwareProfileModal
hardwareProfile={deleteHardwareProfile.hardwareProfile}
Expand Down
76 changes: 29 additions & 47 deletions frontend/src/pages/hardwareProfiles/HardwareProfilesTableRow.tsx
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
import * as React from 'react';
import {
Button,
Divider,
Label,
LabelGroup,
Expand All @@ -27,27 +26,26 @@ import TolerationTable from '~/pages/hardwareProfiles/toleration/TolerationTable
import { useKebabAccessAllowed, verbModelAccess } from '~/concepts/userSSAR';
import {
createHardwareProfileWarningTitle,
isHardwareProfileOOTB,
validateProfileWarning,
} from '~/pages/hardwareProfiles/utils';
import { HardwareProfileModel, updateHardwareProfile } from '~/api';
import { useDashboardNamespace } from '~/redux/selectors';
import { HardwareProfileModel } from '~/api';
import MigrationTooltip from './migration/MigrationTooltip';
import { MigrationAction } from './migration/types';
import { DEFAULT_HARDWARE_PROFILE_SPEC } from './const';

type HardwareProfilesTableRowProps = {
rowIndex: number;
hardwareProfile: HardwareProfileKind;
migrationAction?: MigrationAction;
handleDelete: (cr: HardwareProfileKind) => void;
handleMigrate: (migrationAction: MigrationAction) => void;
};

const HardwareProfilesTableRow: React.FC<HardwareProfilesTableRowProps> = ({
hardwareProfile,
rowIndex,
migrationAction,
handleDelete,
handleMigrate,
}) => {
const modifiedDate = hardwareProfile.metadata.annotations?.['opendatahub.io/modified-date'];
const [isExpanded, setExpanded] = React.useState(false);
Expand All @@ -65,13 +63,16 @@ const HardwareProfilesTableRow: React.FC<HardwareProfilesTableRowProps> = ({
}, [hardwareProfile.metadata.annotations]);

const title = migrationAction ? (
<MigrationTooltip migrationAction={migrationAction} wrap={false}>
<MigrationTooltip
migrationAction={migrationAction}
wrap={false}
onMigrate={() => handleMigrate(migrationAction)}
>
<Truncate content={hardwareProfile.spec.displayName} />
</MigrationTooltip>
) : (
<Truncate content={hardwareProfile.spec.displayName} />
);
const { dashboardNamespace } = useDashboardNamespace();
const hardwareProfileWarnings = validateProfileWarning(hardwareProfile);

return (
Expand Down Expand Up @@ -102,7 +103,7 @@ const HardwareProfilesTableRow: React.FC<HardwareProfilesTableRowProps> = ({
</Icon>
}
headerContent={createHardwareProfileWarningTitle(hardwareProfile)}
bodyContent={(hide) => (
bodyContent={() => (
<>
{hardwareProfileWarnings.length === 1 ? (
<div>{hardwareProfileWarnings[0].message}</div>
Expand All @@ -113,27 +114,6 @@ const HardwareProfilesTableRow: React.FC<HardwareProfilesTableRowProps> = ({
))}
</List>
)}
{isHardwareProfileOOTB(hardwareProfile) && (
<Button
variant="link"
component="a"
onClick={async () => {
await updateHardwareProfile(
{
...DEFAULT_HARDWARE_PROFILE_SPEC,
displayName: hardwareProfile.spec.displayName,
description: hardwareProfile.spec.description,
},
hardwareProfile,
dashboardNamespace,
);
hide();
}}
data-testid="restore-default-hardware-profile"
>
Restore default hardware profile
</Button>
)}
</>
)}
>
Expand Down Expand Up @@ -185,15 +165,13 @@ const HardwareProfilesTableRow: React.FC<HardwareProfilesTableRowProps> = ({
<ActionsColumn
items={[
...useKebabAccessAllowed(
isHardwareProfileOOTB(hardwareProfile)
? []
: [
{
title: 'Edit',
onClick: () =>
navigate(`/hardwareProfiles/edit/${hardwareProfile.metadata.name}`),
},
],
[
{
title: 'Edit',
onClick: () =>
navigate(`/hardwareProfiles/edit/${hardwareProfile.metadata.name}`),
},
],
verbModelAccess('update', HardwareProfileModel),
),
...useKebabAccessAllowed(
Expand All @@ -207,15 +185,19 @@ const HardwareProfilesTableRow: React.FC<HardwareProfilesTableRowProps> = ({
verbModelAccess('create', HardwareProfileModel),
),
...useKebabAccessAllowed(
isHardwareProfileOOTB(hardwareProfile)
? []
: [
{ isSeparator: true },
{
title: 'Delete',
onClick: () => handleDelete(hardwareProfile),
},
],
migrationAction
? [{ title: 'Migrate', onClick: () => handleMigrate(migrationAction) }]
: [],
verbModelAccess('create', HardwareProfileModel),
),
...useKebabAccessAllowed(
[
{ isSeparator: true },
{
title: 'Delete',
onClick: () => handleDelete(hardwareProfile),
},
],
verbModelAccess('delete', HardwareProfileModel),
),
]}
Expand Down
Loading

0 comments on commit afb43fa

Please sign in to comment.