Skip to content

Commit

Permalink
Update cypress test for custom serving runtime file
Browse files Browse the repository at this point in the history
  • Loading branch information
ppadti committed Mar 15, 2024
1 parent c3756de commit 9e127b8
Show file tree
Hide file tree
Showing 4 changed files with 354 additions and 37 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -5,37 +5,40 @@ import { mockServingRuntimeTemplateK8sResource } from '~/__mocks__/mockServingRu
import { mockStatus } from '~/__mocks__/mockStatus';
import { servingRuntimes } from '~/__tests__/cypress/cypress/pages/servingRuntimes';
import { ServingRuntimeAPIProtocol, ServingRuntimePlatform } from '~/types';
import { deleteModal } from '~/__tests__/cypress/cypress/pages/components/DeleteModal';

const addfilePath = './cypress/e2e/customServingRuntimes/mock-custom-serving-runtime-add.yaml';
const editfilePath = './cypress/e2e/customServingRuntimes/mock-custom-serving-runtime-edit.yaml';

const initialMock = [
mockServingRuntimeTemplateK8sResource({
name: 'template-1',
displayName: 'Multi Platform',
platforms: [ServingRuntimePlatform.SINGLE],
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-2',
displayName: 'Caikit',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.GRPC,
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-3',
displayName: 'OVMS',
platforms: [ServingRuntimePlatform.MULTI],
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-4',
displayName: 'Serving Runtime with No Annotations',
}),
];

describe('Custom serving runtimes', () => {
beforeEach(() => {
cy.intercept('/api/status', mockStatus());
cy.intercept('/api/config', mockDashboardConfig({}));
cy.intercept('/api/dashboardConfig/opendatahub/odh-dashboard-config', mockDashboardConfig({}));
cy.intercept(
{ pathname: '/api/templates/opendatahub' },
mockK8sResourceList([
mockServingRuntimeTemplateK8sResource({
name: 'template-1',
displayName: 'Multi Platform',
platforms: [ServingRuntimePlatform.SINGLE],
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-2',
displayName: 'Caikit',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.GRPC,
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-3',
displayName: 'OVMS',
platforms: [ServingRuntimePlatform.MULTI],
}),
mockServingRuntimeTemplateK8sResource({
name: 'template-4',
displayName: 'Serving Runtime with No Annotations',
}),
]),
);
cy.intercept({ pathname: '/api/templates/opendatahub' }, mockK8sResourceList(initialMock));
cy.intercept(
'/api/k8s/apis/project.openshift.io/v1/projects',
mockK8sResourceList([mockProjectK8sResource({})]),
Expand All @@ -62,7 +65,23 @@ describe('Custom serving runtimes', () => {
servingRuntimes.getRowById('template-4').shouldHaveAPIProtocol(ServingRuntimeAPIProtocol.REST);
});

it('should add a new serving runtime', () => {
it('should add a new single model serving runtime', () => {
cy.intercept(
{
method: 'POST',
pathname: '/api/servingRuntimes',
},
mockServingRuntimeTemplateK8sResource({}).objects,
).as('createSingleModelServingRuntime');

cy.intercept(
{
method: 'POST',
pathname: '/api/templates/',
},
mockServingRuntimeTemplateK8sResource({}),
).as('createTemplate');

servingRuntimes.findAddButton().click();
servingRuntimes.findAppTitle().should('contain', 'Add serving runtime');

Expand All @@ -73,38 +92,239 @@ describe('Custom serving runtimes', () => {
]);
servingRuntimes.findSelectServingPlatformButton().click();

// Create with single model
servingRuntimes.findCreateButton().should('be.disabled');
servingRuntimes.findSubmitButton().should('be.disabled');
servingRuntimes.shouldSelectPlatform('Single-model serving platform');
servingRuntimes.shouldDisplayAPIProtocolValues([
ServingRuntimeAPIProtocol.REST,
ServingRuntimeAPIProtocol.GRPC,
]);
servingRuntimes.shouldSelectAPIProtocol(ServingRuntimeAPIProtocol.REST);
servingRuntimes.findStartFromScratchButton().click();
servingRuntimes.getDashboardCodeEditor().findInput().type('test');
servingRuntimes.findCreateButton().should('be.enabled');
servingRuntimes.findCancelButton().click();
servingRuntimes.uploadYaml(addfilePath);
servingRuntimes.getDashboardCodeEditor().findInput().should('not.be.empty');

servingRuntimes.findSubmitButton().should('be.enabled');
servingRuntimes.findSubmitButton().click();

cy.wait('@createSingleModelServingRuntime').then((interception) => {
expect(interception.request.url).to.include('?dryRun=All');
expect(interception.request.body.metadata).to.eql({
name: 'template-new',
annotations: { 'openshift.io/display-name': 'New OVMS Server' },
labels: { 'opendatahub.io/dashboard': 'true' },
namespace: 'opendatahub',
});
});

cy.wait('@createTemplate').then((interception) => {
expect(interception.request.body.metadata.annotations).to.eql({
'opendatahub.io/modelServingSupport': '["single"]',
'opendatahub.io/apiProtocol': 'REST',
});
expect(interception.request.body.objects[0].metadata).to.eql({
name: 'template-new',
annotations: { 'openshift.io/display-name': 'New OVMS Server' },
labels: { 'opendatahub.io/dashboard': 'true' },
});
});
});

it('should add a new multi model serving runtime', () => {
cy.intercept(
{
method: 'POST',
pathname: '/api/servingRuntimes',
},
mockServingRuntimeTemplateK8sResource({}).objects,
).as('createMultiModelServingRuntime');
cy.intercept(
{
method: 'POST',
pathname: '/api/templates/',
},
mockServingRuntimeTemplateK8sResource({}),
).as('createTemplate');

servingRuntimes.findAddButton().click();
servingRuntimes.findAppTitle().should('contain', 'Add serving runtime');

// Create with multi model
servingRuntimes.findCreateButton().should('be.disabled');
// Check serving runtime dropdown list
servingRuntimes.shouldDisplayServingRuntimeValues([
'Single-model serving platform',
'Multi-model serving platform',
]);
servingRuntimes.findSelectServingPlatformButton().click();

servingRuntimes.findSubmitButton().should('be.disabled');
servingRuntimes.shouldSelectPlatform('Multi-model serving platform');
servingRuntimes.findSelectAPIProtocolButton().should('not.be.enabled');
servingRuntimes.findSelectAPIProtocolButton().should('include.text', 'REST');
servingRuntimes.findStartFromScratchButton().click();
servingRuntimes.getDashboardCodeEditor().findInput().type('test');
servingRuntimes.findCreateButton().should('be.enabled');
servingRuntimes.uploadYaml(addfilePath);
servingRuntimes.findSubmitButton().should('be.enabled');
servingRuntimes.findSubmitButton().click();

cy.wait('@createMultiModelServingRuntime').then((interception) => {
expect(interception.request.url).to.include('?dryRun=All');
expect(interception.request.body.metadata).to.eql({
name: 'template-new',
annotations: { 'openshift.io/display-name': 'New OVMS Server' },
labels: { 'opendatahub.io/dashboard': 'true' },
namespace: 'opendatahub',
});
});

cy.wait('@createTemplate').then((interception) => {
expect(interception.request.body.metadata.annotations).to.eql({
'opendatahub.io/modelServingSupport': '["multi"]',
'opendatahub.io/apiProtocol': 'REST',
});
expect(interception.request.body.objects[0].metadata).to.eql({
name: 'template-new',
annotations: { 'openshift.io/display-name': 'New OVMS Server' },
labels: { 'opendatahub.io/dashboard': 'true' },
});
});
});

it('should duplicate a serving runtime', () => {
cy.intercept(
{
method: 'POST',
pathname: '/api/servingRuntimes',
},
mockServingRuntimeTemplateK8sResource({}).objects,
).as('duplicateServingRuntime');
cy.intercept(
{
method: 'POST',
pathname: '/api/templates/',
},
mockServingRuntimeTemplateK8sResource({}),
).as('duplicateTemplate');

const ServingRuntimeTemplateMock = mockServingRuntimeTemplateK8sResource({
name: 'serving-runtime-template-1',
displayName: 'Multi platform',
platforms: [ServingRuntimePlatform.SINGLE],
apiProtocol: ServingRuntimeAPIProtocol.GRPC,
});

cy.intercept(
{ pathname: '/api/templates/opendatahub' },
mockK8sResourceList([...initialMock, ServingRuntimeTemplateMock]),
).as('refreshServingRuntime');

servingRuntimes.getRowById('template-1').find().findKebabAction('Duplicate').click();
servingRuntimes.findAppTitle().should('have.text', 'Duplicate serving runtime');
cy.url().should('include', '/addServingRuntime');

servingRuntimes.shouldDisplayAPIProtocolValues([
ServingRuntimeAPIProtocol.REST,
ServingRuntimeAPIProtocol.GRPC,
]);
servingRuntimes.shouldSelectAPIProtocol(ServingRuntimeAPIProtocol.GRPC);
servingRuntimes.findSubmitButton().should('be.enabled');
servingRuntimes.findSubmitButton().click();

cy.wait('@duplicateServingRuntime').then((interception) => {
expect(interception.request.body.metadata).to.eql({
name: 'template-1-copy',
annotations: { 'openshift.io/display-name': 'Copy of Multi Platform' },
labels: { 'opendatahub.io/dashboard': 'true' },
namespace: 'opendatahub',
});
});

cy.wait('@duplicateTemplate').then((interception) => {
expect(interception.request.body.metadata.annotations).to.eql({
'opendatahub.io/modelServingSupport': '["single"]',
'opendatahub.io/apiProtocol': 'gRPC',
});
expect(interception.request.body.objects[0].metadata).to.eql({
name: 'template-1-copy',
annotations: { 'openshift.io/display-name': 'Copy of Multi Platform' },
labels: { 'opendatahub.io/dashboard': 'true' },
});
});
cy.wait('@refreshServingRuntime');

servingRuntimes
.getRowById('serving-runtime-template-1')
.shouldHaveAPIProtocol(ServingRuntimeAPIProtocol.GRPC);
});

it('should edit a serving runtime', () => {
cy.intercept(
{
method: 'POST',
pathname: '/api/servingRuntimes',
},
{
delay: 500,
body: mockServingRuntimeTemplateK8sResource({}).objects,
},
).as('editServingRuntime');
cy.intercept(
{
method: 'PATCH',
pathname: '/api/templates/opendatahub/template-1',
},
mockServingRuntimeTemplateK8sResource({}),
).as('editTemplate');

servingRuntimes.getRowById('template-1').find().findKebabAction('Edit').click();
servingRuntimes.findAppTitle().should('have.text', 'Edit Multi Platform');
cy.url().should('include', '/editServingRuntime/template-1');
cy.get('h1').should('contain', 'Edit Multi Platform');
servingRuntimes.findSubmitButton().should('be.disabled');
servingRuntimes.uploadYaml(editfilePath);
servingRuntimes.findSubmitButton().click();

cy.wait('@editServingRuntime').then((interception) => {
expect(interception.request.body.metadata).to.eql({
name: 'template-1',
annotations: { 'openshift.io/display-name': 'Updated Multi Platform' },
labels: { 'opendatahub.io/dashboard': 'true' },
namespace: 'opendatahub',
});
});

cy.wait('@editTemplate').then((interception) => {
expect(interception.request.body[0].value.metadata).to.eql({
name: 'template-1',
annotations: { 'openshift.io/display-name': 'Updated Multi Platform' },
labels: { 'opendatahub.io/dashboard': 'true' },
});
expect(interception.request.body[1]).to.eql({
op: 'replace',
path: '/metadata/annotations/opendatahub.io~1modelServingSupport',
value: '["single"]',
});
expect(interception.request.body[2]).to.eql({
op: 'replace',
path: '/metadata/annotations/opendatahub.io~1apiProtocol',
value: 'REST',
});
});
});

it('delete serving runtime', () => {
cy.intercept(
{
method: 'DELETE',
pathname: '/api/templates/opendatahub/template-1',
},
{},
).as('deleteServingRuntime');

servingRuntimes.getRowById('template-1').find().findKebabAction('Delete').click();
deleteModal.findSubmitButton().should('be.disabled');
deleteModal.findFooter().findByRole('button', { name: 'Delete serving runtime' });

// test delete form is enabled after filling out required fields
deleteModal.findInput().type('Multi Platform');
deleteModal.findSubmitButton().should('be.enabled').click();

cy.wait('@deleteServingRuntime');
});
});
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
apiVersion: serving.kserve.io/v1alpha1
kind: ServingRuntime
metadata:
name: template-new
annotations:
openshift.io/display-name: 'New OVMS Server'
labels:
opendatahub.io/dashboard: 'true'
spec:
builtInAdapter:
memBufferBytes: 134217728
modelLoadingTimeoutMillis: 90000
runtimeManagementPort: 8888
serverType: ovms
containers:
- args:
- '--port=8001'
- '--rest_port=8888'
- '--config_path=/models/model_config_list.json'
- '--file_system_poll_wait_seconds=0'
- '--grpc_bind_address=127.0.0.1'
- '--rest_bind_address=127.0.0.1'
image: >-
quay.io/opendatahub/openvino_model_server@sha256:c89f76386bc8b59f0748cf173868e5beef21ac7d2f78dada69089c4d37c44116
name: ovms
resources:
limits:
cpu: '0'
memory: 0Gi
requests:
cpu: '0'
memory: 0Gi
grpcDataEndpoint: 'port:8001'
grpcEndpoint: 'port:8085'
multiModel: true
protocolVersions:
- grpc-v1
replicas: 1
supportedModelFormats:
- autoSelect: true
name: openvino_ir
version: opset1
- autoSelect: true
name: onnx
version: '1'
Loading

0 comments on commit 9e127b8

Please sign in to comment.