Skip to content

Commit

Permalink
Merge pull request #1969 from DaoDaoNoCode/upstream-issue-1912
Browse files Browse the repository at this point in the history
Adapt custom serving runtimes to KServe
  • Loading branch information
openshift-ci[bot] authored Oct 19, 2023
2 parents aa6fb2b + 390a3a1 commit 4f62765
Show file tree
Hide file tree
Showing 19 changed files with 427 additions and 63 deletions.
18 changes: 10 additions & 8 deletions frontend/src/__mocks__/mockServingRuntimeTemplateK8sResource.ts
Original file line number Diff line number Diff line change
@@ -1,27 +1,29 @@
import { TemplateKind } from '~/k8sTypes';
import { ServingRuntimePlatform } from '~/types';

type MockResourceConfigType = {
name?: string;
namespace?: string;
displayName?: string;
platforms?: ServingRuntimePlatform[];
};

export const mockTemplateK8sResource = ({
name = 'test-model',
export const mockServingRuntimeTemplateK8sResource = ({
name = 'template-1',
namespace = 'opendatahub',
displayName = 'New OVMS Server',
platforms,
}: MockResourceConfigType): TemplateKind => ({
apiVersion: 'template.openshift.io/v1',
kind: 'Template',
metadata: {
name: 'template-ar2pcc',
name,
namespace,
uid: '31277020-b60a-40c9-91bc-5ee3e2bb25ec',
resourceVersion: '164740435',
creationTimestamp: '2023-05-03T21:58:17Z',
labels: {
'opendatahub.io/dashboard': 'true',
},
annotations: {
tags: 'new-one,servingruntime',
'opendatahub.io/modelServingSupport': JSON.stringify(platforms),
},
},
objects: [
Expand All @@ -31,7 +33,7 @@ export const mockTemplateK8sResource = ({
metadata: {
name,
annotations: {
'openshift.io/display-name': 'New OVMS Server',
'openshift.io/display-name': displayName,
},
labels: {
'opendatahub.io/dashboard': 'true',
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { test, expect } from '@playwright/test';

test('Custom serving runtimes', async ({ page }) => {
await page.goto(
'./iframe.html?args=&id=tests-integration-pages-customservingruntimes-customservingruntimes--default&viewMode=story',
);
// wait for page to load
await page.waitForSelector('text=Serving runtimes');

// check the platform setting labels in the header
await expect(page.getByText('Single model serving enabled')).toBeVisible();
await expect(page.getByText('Multi-model serving enabled')).toBeHidden();

// check the platform labels in the table row
await expect(page.locator('#template-1').getByLabel('Label group category')).toHaveText(
'Single modelMulti-model',
);
await expect(page.locator('#template-2').getByLabel('Label group category')).toHaveText(
'Multi-model',
);
await expect(page.locator('#template-3').getByLabel('Label group category')).toHaveText(
'Single modelMulti-model',
);
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
import React from 'react';

import { StoryFn, Meta, StoryObj } from '@storybook/react';
import { rest } from 'msw';
import { within } from '@storybook/testing-library';
import { Route, Routes } from 'react-router-dom';
import { mockK8sResourceList } from '~/__mocks__/mockK8sResourceList';
import CustomServingRuntimeView from '~/pages/modelServing/customServingRuntimes/CustomServingRuntimeView';
import { mockServingRuntimeTemplateK8sResource } from '~/__mocks__/mockServingRuntimeTemplateK8sResource';
import CustomServingRuntimeContextProvider from '~/pages/modelServing/customServingRuntimes/CustomServingRuntimeContext';
import { mockStatus } from '~/__mocks__/mockStatus';
import { mockProjectK8sResource } from '~/__mocks__/mockProjectK8sResource';
import useDetectUser from '~/utilities/useDetectUser';
import { mockDashboardConfig } from '~/__mocks__/mockDashboardConfig';
import { ServingRuntimePlatform } from '~/types';

export default {
component: CustomServingRuntimeView,
parameters: {
msw: {
handlers: [
rest.get('/api/status', (req, res, ctx) => res(ctx.json(mockStatus()))),
rest.get('/api/templates/opendatahub', (req, res, ctx) =>
res(
ctx.json(
mockK8sResourceList([
mockServingRuntimeTemplateK8sResource({
platforms: [ServingRuntimePlatform.SINGLE, ServingRuntimePlatform.MULTI],
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-2',
displayName: 'Multi-model Serving Runtime',
platforms: [ServingRuntimePlatform.MULTI],
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-3',
displayName: 'Serving Runtime with No Annotations',
}),
]),
),
),
),
rest.get('/api/k8s/apis/project.openshift.io/v1/projects', (req, res, ctx) =>
res(ctx.json(mockK8sResourceList([mockProjectK8sResource({})]))),
),
rest.get('/api/dashboardConfig/opendatahub/odh-dashboard-config', (req, res, ctx) =>
res(ctx.json(mockDashboardConfig({}))),
),
],
},
},
} as Meta<typeof CustomServingRuntimeView>;

const Template: StoryFn<typeof CustomServingRuntimeView> = (args) => {
useDetectUser();
return (
<Routes>
<Route path="/" element={<CustomServingRuntimeContextProvider />}>
<Route index element={<CustomServingRuntimeView {...args} />} />
</Route>
</Routes>
);
};

export const Default: StoryObj = {
render: Template,

play: async ({ canvasElement }) => {
// load page and wait until settled
const canvas = within(canvasElement);
await canvas.findByText('Serving runtimes', undefined, { timeout: 5000 });
},
};
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { mockPVCK8sResource } from '~/__mocks__/mockPVCK8sResource';
import ProjectsRoutes from '~/concepts/projects/ProjectsRoutes';
import {
mockInvalidTemplateK8sResource,
mockTemplateK8sResource,
mockServingRuntimeTemplateK8sResource,
} from '~/__mocks__/mockServingRuntimeTemplateK8sResource';
import { mockDashboardConfig } from '~/__mocks__/mockDashboardConfig';
import { mockStatus } from '~/__mocks__/mockStatus';
Expand Down Expand Up @@ -114,7 +114,7 @@ export default {
res(
ctx.json(
mockK8sResourceList([
mockTemplateK8sResource({}),
mockServingRuntimeTemplateK8sResource({}),
mockInvalidTemplateK8sResource({}),
]),
),
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ import { mockPVCK8sResource } from '~/__mocks__/mockPVCK8sResource';
import useDetectUser from '~/utilities/useDetectUser';
import ProjectsRoutes from '~/concepts/projects/ProjectsRoutes';
import { mockStatus } from '~/__mocks__/mockStatus';
import { mockTemplateK8sResource } from '~/__mocks__/mockServingRuntimeTemplateK8sResource';
import { mockServingRuntimeTemplateK8sResource } from '~/__mocks__/mockServingRuntimeTemplateK8sResource';
import { mockDashboardConfig } from '~/__mocks__/mockDashboardConfig';
import ProjectDetails from '~/pages/projects/screens/detail/ProjectDetails';

Expand Down Expand Up @@ -119,7 +119,8 @@ const handlers = (isEmpty: boolean): RestHandler<MockedRequest<DefaultBodyType>>
),
rest.get(
'/api/k8s/apis/template.openshift.io/v1/namespaces/opendatahub/templates',
(req, res, ctx) => res(ctx.json(mockK8sResourceList([mockTemplateK8sResource({})]))),
(req, res, ctx) =>
res(ctx.json(mockK8sResourceList([mockServingRuntimeTemplateK8sResource({})]))),
),
rest.get(
'/api/k8s/apis/opendatahub.io/v1alpha/namespaces/opendatahub/odhdashboardconfigs/odh-dashboard-config',
Expand Down
27 changes: 24 additions & 3 deletions frontend/src/api/k8s/templates.ts
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,12 @@ import { ServingRuntimeKind, TemplateKind } from '~/k8sTypes';
import { ServingRuntimeModel, TemplateModel } from '~/api/models';
import { applyK8sAPIOptions } from '~/api/apiMergeUtils';
import { genRandomChars } from '~/utilities/string';
import { ServingRuntimePlatform } from '~/types';

export const assembleServingRuntimeTemplate = (
body: string,
namespace: string,
platforms: ServingRuntimePlatform[],
templateName?: string,
): TemplateKind & { objects: ServingRuntimeKind[] } => {
const servingRuntime: ServingRuntimeKind = YAML.parse(body);
Expand All @@ -32,6 +34,9 @@ export const assembleServingRuntimeTemplate = (
labels: {
'opendatahub.io/dashboard': 'true',
},
annotations: {
'opendatahub.io/modelServingSupport': JSON.stringify(platforms),
},
},
objects: [servingRuntime],
parameters: [],
Expand Down Expand Up @@ -86,9 +91,10 @@ const dryRunServingRuntimeForTemplateCreation = (
export const createServingRuntimeTemplate = async (
body: string,
namespace: string,
platforms: ServingRuntimePlatform[],
): Promise<TemplateKind> => {
try {
const template = assembleServingRuntimeTemplate(body, namespace);
const template = assembleServingRuntimeTemplate(body, namespace, platforms);
const servingRuntime = template.objects[0];
const servingRuntimeName = servingRuntime.metadata.name;

Expand All @@ -109,12 +115,14 @@ export const createServingRuntimeTemplate = async (
};

export const updateServingRuntimeTemplate = (
templateName: string,
servingRuntimeName: string,
existingTemplate: TemplateKind,
body: string,
namespace: string,
platforms: ServingRuntimePlatform[],
): Promise<TemplateKind> => {
try {
const templateName = existingTemplate.metadata.name;
const servingRuntimeName = existingTemplate.objects[0].metadata.name;
const servingRuntime: ServingRuntimeKind = YAML.parse(body);
if (!servingRuntime.metadata.name) {
throw new Error('Serving runtime name is required.');
Expand All @@ -134,6 +142,19 @@ export const updateServingRuntimeTemplate = (
path: '/objects/0',
value: servingRuntime,
},
existingTemplate.metadata.annotations
? {
op: 'replace',
path: '/metadata/annotations/opendatahub.io~1modelServingSupport',
value: JSON.stringify(platforms),
}
: {
op: 'add',
path: '/metadata/annotations',
value: {
'opendatahub.io/modelServingSupport': JSON.stringify(platforms),
},
},
],
}),
);
Expand Down
1 change: 1 addition & 0 deletions frontend/src/k8sTypes.ts
Original file line number Diff line number Diff line change
Expand Up @@ -705,6 +705,7 @@ export type TemplateKind = K8sResourceCommon & {
tags: string;
iconClass?: string;
'opendatahub.io/template-enabled': string;
'opendatahub.io/modelServingSupport': string;
}>;
name: string;
namespace: string;
Expand Down
Loading

0 comments on commit 4f62765

Please sign in to comment.