Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
dchourasia committed Nov 7, 2024
2 parents 800b302 + 7023236 commit fa79825
Show file tree
Hide file tree
Showing 80 changed files with 2,419 additions and 789 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,14 @@ export const postAcceleratorProfile = async (
): Promise<{ success: boolean; error: string }> => {
const { customObjectsApi } = fastify.kube;
const { namespace } = fastify.kube;
const body = request.body as AcceleratorProfileKind['spec'];
const requestBody = request.body as { name?: string } & AcceleratorProfileKind['spec'];
const { name, ...body } = requestBody;

const payload: AcceleratorProfileKind = {
apiVersion: 'dashboard.opendatahub.io/v1',
kind: 'AcceleratorProfile',
metadata: {
name: translateDisplayNameForK8s(body.displayName),
name: name || translateDisplayNameForK8s(body.displayName),
namespace,
annotations: {
'opendatahub.io/modified-date': new Date().toISOString(),
Expand Down
4 changes: 4 additions & 0 deletions backend/src/routes/api/namespaces/const.ts
Original file line number Diff line number Diff line change
Expand Up @@ -15,4 +15,8 @@ export enum NamespaceApplicationCase {
* Nvidia NIMs run on KServe but have different requirements than regular models.
*/
KSERVE_NIM_PROMOTION,
/**
* Downgrade a project from Modelmesh, Kserve or NIM so the platform can be selected again.
*/
RESET_MODEL_SERVING_PLATFORM,
}
7 changes: 7 additions & 0 deletions backend/src/routes/api/namespaces/namespaceUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,13 @@ export const applyNamespaceChange = async (
checkPermissionsFn = checkEditNamespacePermission;
}
break;
case NamespaceApplicationCase.RESET_MODEL_SERVING_PLATFORM:
{
annotations = { 'opendatahub.io/nim-support': null };
labels = { 'modelmesh-enabled': null };
checkPermissionsFn = checkEditNamespacePermission;
}
break;
default:
throw createCustomError('Unknown configuration', 'Cannot apply namespace change', 400);
}
Expand Down
4 changes: 2 additions & 2 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -834,15 +834,15 @@ export type NotebookData = {
notebookSizeName: string;
imageName: string;
imageTagName: string;
acceleratorProfile: AcceleratorProfileState;
acceleratorProfile?: AcceleratorProfileState;
envVars: EnvVarReducedTypeKeyValues;
state: NotebookState;
username?: string;
storageClassName?: string;
};

export type AcceleratorProfileState = {
acceleratorProfile?: AcceleratorProfileKind;
acceleratorProfile: AcceleratorProfileKind;
count: number;
};

Expand Down
18 changes: 9 additions & 9 deletions backend/src/utils/notebookUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -160,7 +160,7 @@ export const assembleNotebook = async (
envName: string,
tolerationSettings: NotebookTolerationSettings,
): Promise<Notebook> => {
const { notebookSizeName, imageName, imageTagName, acceleratorProfile, envVars } = data;
const { notebookSizeName, imageName, imageTagName, envVars } = data;

const notebookSize = getNotebookSize(notebookSizeName);

Expand Down Expand Up @@ -196,17 +196,17 @@ export const assembleNotebook = async (
const tolerations: Toleration[] = [];

const affinity: NotebookAffinity = {};
if (acceleratorProfile.count > 0 && acceleratorProfile.acceleratorProfile) {
if (data.acceleratorProfile?.count > 0) {
if (!resources.limits) {
resources.limits = {};
}
if (!resources.requests) {
resources.requests = {};
}
resources.limits[acceleratorProfile.acceleratorProfile.spec.identifier] =
acceleratorProfile.count;
resources.requests[acceleratorProfile.acceleratorProfile.spec.identifier] =
acceleratorProfile.count;
resources.limits[data.acceleratorProfile.acceleratorProfile.spec.identifier] =
data.acceleratorProfile.count;
resources.requests[data.acceleratorProfile.acceleratorProfile.spec.identifier] =
data.acceleratorProfile.count;
} else {
// step type down to string to avoid type errors
const containerResourceKeys: string[] = Object.values(ContainerResourceAttributes);
Expand All @@ -224,8 +224,8 @@ export const assembleNotebook = async (
});
}

if (acceleratorProfile.acceleratorProfile?.spec.tolerations) {
tolerations.push(...acceleratorProfile.acceleratorProfile.spec.tolerations);
if (data.acceleratorProfile?.acceleratorProfile?.spec.tolerations) {
tolerations.push(...data.acceleratorProfile.acceleratorProfile.spec.tolerations);
}

if (tolerationSettings?.enabled) {
Expand Down Expand Up @@ -274,7 +274,7 @@ export const assembleNotebook = async (
'opendatahub.io/username': username,
'kubeflow-resource-stopped': null,
'opendatahub.io/accelerator-name':
acceleratorProfile.acceleratorProfile?.metadata.name || '',
data.acceleratorProfile?.acceleratorProfile.metadata.name || '',
},
name: name,
namespace: namespace,
Expand Down
5 changes: 5 additions & 0 deletions frontend/src/__mocks__/mockProjectK8sResource.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ type MockResourceConfigType = {
k8sName?: string;
creationTimestamp?: string;
enableModelMesh?: boolean;
enableNIM?: boolean;
isDSProject?: boolean;
phase?: 'Active' | 'Terminating';
};
Expand All @@ -21,6 +22,7 @@ export const mockProjectK8sResource = ({
k8sName = 'test-project',
creationTimestamp = '2023-02-14T21:43:59Z',
enableModelMesh,
enableNIM = false,
description = '',
isDSProject = true,
phase = 'Active',
Expand All @@ -36,6 +38,9 @@ export const mockProjectK8sResource = ({
...(enableModelMesh !== undefined && {
[KnownLabels.MODEL_SERVING_PROJECT]: enableModelMesh ? 'true' : 'false',
}),
...(enableNIM && {
'opendatahub.io/nim-support': 'true',
}),
...(isDSProject && { [KnownLabels.DASHBOARD_RESOURCE]: 'true' }),
},
...(hasAnnotations && {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
import { K8sNameDescriptionField } from '~/__tests__/cypress/cypress/pages/components/subComponents/K8sNameDescriptionField';
import { Modal } from './components/Modal';
import { TableToolbar } from './components/TableToolbar';
import { TableRow } from './components/table';
Expand Down Expand Up @@ -86,9 +87,7 @@ class AcceleratorProfile {
}

class ManageAcceleratorProfile {
findAcceleratorNameInput() {
return cy.findByTestId('accelerator-name-input');
}
k8sNameDescription = new K8sNameDescriptionField('accelerator-profile');

findIdentifierInput() {
return cy.findByTestId('accelerator-identifier-input');
Expand All @@ -103,10 +102,6 @@ class ManageAcceleratorProfile {
return cy.findByTestId('add-toleration-button');
}

findDescriptionInput() {
return cy.findByTestId('accelerator-description-input');
}

findSubmitButton() {
return cy.findByTestId('accelerator-profile-create-button');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ class CategorySection extends Contextual<HTMLElement> {
}

findMultiGroupSelectButton(name: string) {
return cy.findByTestId(`select-multi-typeahead-${name}`).click();
return cy.findByTestId(`select-multi-typeahead-${name}`);
}
}

Expand Down
13 changes: 0 additions & 13 deletions frontend/src/__tests__/cypress/cypress/pages/modelServing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,6 @@ import { appChrome } from '~/__tests__/cypress/cypress/pages/appChrome';
import { Modal } from '~/__tests__/cypress/cypress/pages/components/Modal';
import { TableRow } from '~/__tests__/cypress/cypress/pages/components/table';
import { mixin } from '~/__tests__/cypress/cypress/utils/mixin';
import { Contextual } from './components/Contextual';
import { TableToolbar } from './components/TableToolbar';

class ModelServingToolbar extends TableToolbar {}
Expand Down Expand Up @@ -356,24 +355,12 @@ class InferenceServiceRow extends TableRow {
return this.find().find(`[data-label=Project]`);
}
}
class ServingPlatformCard extends Contextual<HTMLElement> {
findDeployModelButton() {
return this.find().findByTestId('single-serving-deploy-button');
}

findAddModelServerButton() {
return this.find().findByTestId('multi-serving-add-server-button');
}
}
class ModelServingSection {
find() {
return cy.findByTestId('section-model-server');
}

getServingPlatformCard(name: string) {
return new ServingPlatformCard(() => cy.findAllByTestId(`${name}-platform-card`));
}

private findKServeTable() {
return this.find().findByTestId('kserve-inference-service-table');
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,10 @@ class NotebookServer {
findStopNotebookServerButton() {
return cy.findByTestId('stop-nb-server-button');
}

findAcceleratorProfileSelect() {
return cy.findByTestId('accelerator-profile-select');
}
}

export const notebookServer = new NotebookServer();
32 changes: 26 additions & 6 deletions frontend/src/__tests__/cypress/cypress/pages/projects.ts
Original file line number Diff line number Diff line change
Expand Up @@ -184,8 +184,8 @@ class ProjectDetails {
this.wait();
}

visitSection(project: string, section: string) {
cy.visitWithLogin(`/projects/${project}?section=${section}`);
visitSection(project: string, section: string, extraUrlParams = '') {
cy.visitWithLogin(`/projects/${project}?section=${section}${extraUrlParams}`);
this.wait(section);
}

Expand Down Expand Up @@ -248,12 +248,32 @@ class ProjectDetails {
return cy.findByTestId('import-pipeline-button', { timeout });
}

findSingleModelDeployButton() {
return this.findModelServingPlatform('single').findByTestId('single-serving-deploy-button');
findSelectPlatformButton(platform: string) {
return cy.findByTestId(`${platform}-serving-select-button`);
}

findMultiModelButton() {
return this.findModelServingPlatform('multi').findByTestId('multi-serving-add-server-button');
findResetPlatformButton() {
return cy.findByTestId('change-serving-platform-button');
}

findErrorSelectingPlatform() {
return cy.findByTestId('error-selecting-serving-platform');
}

findDeployModelDropdown() {
return cy.findByTestId('deploy-model-dropdown');
}

findBackToRegistryButton() {
return cy.findByTestId('deploy-from-registry');
}

findTopLevelDeployModelButton() {
return cy.findByTestId('deploy-button');
}

findTopLevelAddModelServerButton() {
return cy.findByTestId('add-server-button');
}

findDeployModelTooltip() {
Expand Down
2 changes: 1 addition & 1 deletion frontend/src/__tests__/cypress/cypress/pages/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -234,7 +234,7 @@ class CreateSpawnerPage {
cy.findByTestId('persistent-storage-group')
.findByRole('button', { name: 'Typeahead menu toggle' })
.click();
cy.get('[id="dashboard-page-main"]').findByRole('option', { name }).click();
cy.get('[id="dashboard-page-main"]').contains('button.pf-v5-c-menu__item', name).click();
}

selectPVSize(name: string) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -50,11 +50,34 @@ describe('Manage Accelerator Profile', () => {
createAcceleratorProfile.findSubmitButton().should('be.disabled');

// test required fields
createAcceleratorProfile.findAcceleratorNameInput().fill('test-accelerator');
createAcceleratorProfile.k8sNameDescription.findDisplayNameInput().fill('test-accelerator');
createAcceleratorProfile.findSubmitButton().should('be.disabled');
createAcceleratorProfile.findIdentifierInput().fill('nvidia.com/gpu');
createAcceleratorProfile.findSubmitButton().should('be.enabled');

// test resource name validation
createAcceleratorProfile.k8sNameDescription.findResourceEditLink().click();
createAcceleratorProfile.k8sNameDescription
.findResourceNameInput()
.should('have.attr', 'aria-invalid', 'false');
createAcceleratorProfile.k8sNameDescription
.findResourceNameInput()
.should('have.value', 'test-accelerator');
// Invalid character k8s names fail
createAcceleratorProfile.k8sNameDescription
.findResourceNameInput()
.clear()
.type('InVaLiD vAlUe!');
createAcceleratorProfile.k8sNameDescription
.findResourceNameInput()
.should('have.attr', 'aria-invalid', 'true');
createAcceleratorProfile.findSubmitButton().should('be.disabled');
createAcceleratorProfile.k8sNameDescription
.findResourceNameInput()
.clear()
.type('test-accelerator-name');
createAcceleratorProfile.findSubmitButton().should('be.enabled');

// test tolerations
createAcceleratorProfile.shouldHaveModalEmptyState();

Expand Down Expand Up @@ -127,7 +150,9 @@ describe('Manage Accelerator Profile', () => {

cy.wait('@createAccelerator').then((interception) => {
expect(interception.request.body).to.be.eql({
name: 'test-accelerator-name',
displayName: 'test-accelerator',
description: '',
identifier: 'nvidia.com/gpu',
enabled: true,
tolerations: [],
Expand All @@ -138,9 +163,13 @@ describe('Manage Accelerator Profile', () => {
it('edit page has expected values', () => {
initIntercepts({});
editAcceleratorProfile.visit('test-accelerator');
editAcceleratorProfile.findAcceleratorNameInput().should('have.value', 'Test Accelerator');
editAcceleratorProfile.k8sNameDescription
.findDisplayNameInput()
.should('have.value', 'Test Accelerator');
editAcceleratorProfile.findIdentifierInput().should('have.value', 'nvidia.com/gpu');
editAcceleratorProfile.findDescriptionInput().should('have.value', 'Test description');
editAcceleratorProfile.k8sNameDescription
.findDescriptionInput()
.should('have.value', 'Test description');
editAcceleratorProfile
.getRow('nvidia.com/gpu')
.shouldHaveEffect('NoSchedule')
Expand All @@ -153,10 +182,11 @@ describe('Manage Accelerator Profile', () => {
{ path: { name: 'test-accelerator' } },
{ success: true },
).as('updatedAccelerator');
editAcceleratorProfile.findDescriptionInput().fill('Updated description');
editAcceleratorProfile.k8sNameDescription.findDescriptionInput().fill('Updated description');
editAcceleratorProfile.findSubmitButton().click();
cy.wait('@updatedAccelerator').then((interception) => {
expect(interception.request.body).to.eql({
name: 'test-accelerator',
displayName: 'Test Accelerator',
identifier: 'nvidia.com/gpu',
enabled: true,
Expand Down
Loading

0 comments on commit fa79825

Please sign in to comment.