Skip to content

Commit

Permalink
Added accelerator column and field
Browse files Browse the repository at this point in the history
added tests

tooltip to popover

naming fix, and new ux

added new disbaled state

make label compact

added navigate to create
  • Loading branch information
Gkrumbach07 committed Nov 14, 2023
1 parent 3fcf749 commit 16b84be
Show file tree
Hide file tree
Showing 16 changed files with 583 additions and 122 deletions.
20 changes: 20 additions & 0 deletions backend/src/routes/api/images/imageUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -236,6 +236,9 @@ const mapImageStreamToBYONImage = (is: ImageStream): BYONImage => ({
imported_time: is.metadata.creationTimestamp,
url: is.metadata.annotations['opendatahub.io/notebook-image-url'],
provider: is.metadata.annotations['opendatahub.io/notebook-image-creator'],
recommendedAcceleratorIdentifiers: jsonParseRecommendedAcceleratorIdentifiers(
is.metadata.annotations['opendatahub.io/recommended-accelerators'],
),
});

export const postImage = async (
Expand Down Expand Up @@ -276,6 +279,9 @@ export const postImage = async (
'opendatahub.io/notebook-image-name': body.display_name,
'opendatahub.io/notebook-image-url': fullURL,
'opendatahub.io/notebook-image-creator': body.provider,
'opendatahub.io/recommended-accelerators': JSON.stringify(
body.recommendedAcceleratorIdentifiers ?? [],
),
},
name: `custom-${translateDisplayNameForK8s(body.display_name)}`,
namespace: namespace,
Expand Down Expand Up @@ -413,6 +419,12 @@ export const updateImage = async (
imageStream.metadata.annotations['opendatahub.io/notebook-image-desc'] = body.description;
}

if (body.recommendedAcceleratorIdentifiers !== undefined) {
imageStream.metadata.annotations['opendatahub.io/recommended-accelerators'] = JSON.stringify(
body.recommendedAcceleratorIdentifiers,
);
}

await customObjectsApi
.patchNamespacedCustomObject(
'image.openshift.io',
Expand Down Expand Up @@ -446,3 +458,11 @@ const jsonParsePackage = (unparsedPackage: string): BYONImagePackage[] => {
return [];
}
};

const jsonParseRecommendedAcceleratorIdentifiers = (unparsedRecommendations: string): string[] => {
try {
return JSON.parse(unparsedRecommendations) || [];
} catch {
return [];
}
};
1 change: 1 addition & 0 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -485,6 +485,7 @@ export type BYONImage = {
visible: boolean;
software: BYONImagePackage[];
packages: BYONImagePackage[];
recommendedAcceleratorIdentifiers: string[];
};

export type ImageTag = {
Expand Down
1 change: 1 addition & 0 deletions frontend/src/__mocks__/mockByon.ts
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ export const mockByon = (opts?: RecursivePartial<BYONImage[]>): BYONImage[] =>
name: 'byon-123',
display_name: 'Testing Custom Image',
description: 'A custom notebook image',
recommendedAcceleratorIdentifiers: [],
visible: true,
packages: [
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -155,3 +155,30 @@ test('Invalid id in edit page', async ({ page }) => {
page.getByText('acceleratorprofiles.dashboard.opendatahub.io "test-accelerator" not found'),
).toHaveCount(1);
});

test('One preset identifier is auto filled and disabled', async ({ page }) => {
await page.goto(
navigateToStory(
'pages-acceleratorprofiles-manageacceleratorprofile',
'create-accelerator-with-one-set-identifier',
),
);

expect(await page.getByTestId('accelerator-identifier-input').inputValue()).toBe(
'test-identifier',
);

await expect(page.getByTestId('accelerator-identifier-input')).toBeDisabled();
});

test('Multiple preset identifiers show dropdown', async ({ page }) => {
await page.goto(
navigateToStory(
'pages-acceleratorprofiles-manageacceleratorprofile',
'create-accelerator-with-multiple-set-identifiers',
),
);

await page.getByRole('button', { name: 'Options menu' }).click();
await expect(page.getByRole('option', { name: 'test-identifier-3' })).toHaveCount(1);
});
Original file line number Diff line number Diff line change
Expand Up @@ -144,3 +144,54 @@ export const TolerationsModal: StoryObj = {
await userEvent.click(canvas.getByText('Add toleration', { selector: 'button' }));
},
};

export const CreateAcceleratorWithOneSetIdentifier: StoryObj = {
render: () => (
<RenderComponent>
<ManageAcceleratorProfileComponent />
</RenderComponent>
),
play: async ({ canvasElement }) => {
// load page and wait until settled
const canvas = within(canvasElement);
await canvas.findByText('Identifier', undefined, {
timeout: 5000,
});
},
parameters: {
reactRouter: {
routePath: '/create',
routeState: {
acceleratorIdentifiers: ['test-identifier'],
},
},
},
};

export const CreateAcceleratorWithMultipleSetIdentifiers: StoryObj = {
render: () => (
<RenderComponent>
<ManageAcceleratorProfileComponent />
</RenderComponent>
),
play: async ({ canvasElement }) => {
// load page and wait until settled
const canvas = within(canvasElement);
await canvas.findByText('Identifier', undefined, {
timeout: 5000,
});
},
parameters: {
reactRouter: {
routePath: '/create',
routeState: {
acceleratorIdentifiers: [
'test-identifier-1',
'test-identifier-2',
'test-identifier-3',
'test-identifier-3',
],
},
},
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,12 @@ test('Table filtering, sorting, searching', async ({ page }) => {
await page.getByRole('button', { name: 'Provider' }).click();
expect(page.getByText('image-0'));

// by accelerator
await page.getByRole('button', { name: 'Recommended accelerators' }).click();
expect(page.getByText('test-accelerator')).toHaveCount(0);
await page.getByRole('button', { name: 'Recommended accelerators' }).click();
expect(page.getByText('test-accelerator'));

// by enabled
await page.getByRole('button', { name: 'Enable', exact: true }).click();
expect(page.getByText('image-14'));
Expand Down Expand Up @@ -114,6 +120,30 @@ test('Import form fields', async ({ page }) => {
await page.getByLabel('Name *').fill('image');
await expect(page.getByRole('button', { name: 'Import' })).toBeEnabled();

// test accelerator select field
// select accelerator from api call
await page.getByPlaceholder('Example, nvidia.com/gpu').click();
await page.getByRole('option', { name: 'nvidia.com/gpu' }).click();

// create new and select
await page.getByPlaceholder('Example, nvidia.com/gpu').click();
await page.getByPlaceholder('Example, nvidia.com/gpu').fill('test.com/gpu');
await page.getByRole('option', { name: 'Create "test.com/gpu"' }).click();
await page.getByRole('button', { name: 'Options menu' }).click();
expect(page.getByText('test.com/gpu'));

// remove custom
await page.getByRole('button', { name: 'Remove test.com/gpu' }).click();
await page.getByRole('button', { name: 'Options menu' }).click();
await expect(page.getByText('test.com/gpu')).toHaveCount(0);

// reselect custom
await page
.getByRole('dialog', { name: 'Import notebook image' })
.getByRole('button', { name: 'Options menu' })
.click();
await page.getByRole('option', { name: 'test.com/gpu' }).click();

// test form is disabled after entering software add form
await page.getByTestId('add-software-button').click();
await expect(page.getByRole('button', { name: 'Import' })).toBeDisabled();
Expand Down Expand Up @@ -204,7 +234,7 @@ test('Edit form fields match', async ({ page }) => {
expect(await page.getByLabel('Image Location *').inputValue()).toBe('test-image:latest');
expect(await page.getByLabel('Name *').inputValue()).toBe('Testing Custom Image');
expect(await page.getByLabel('Description').inputValue()).toBe('A custom notebook image');

expect(page.getByText('nvidia.com/gpu'));
// test software and packages have correct values
expect(page.getByRole('gridcell', { name: 'test-software' }));
expect(page.getByRole('gridcell', { name: '2.0' }));
Expand Down
Loading

0 comments on commit 16b84be

Please sign in to comment.