Skip to content

Commit ef678fb

Browse files
authored
E2E test for model deployment with Kserve Raw (opendatahub-io#4583)
* Cypress E2E test for model deployment with Kserve Raw -20579 * refactored code * Addressed review comments * Add [Product Bug: RHOAIENG-31261] and Bug Tag to Quarantine the test * update checkInferenceServiceState utility method to check deployment mode * Update deployment mode conditions * remove getDeploymentModeLength() function. * refactored code * refactored code
1 parent 97dc0df commit ef678fb

File tree

3 files changed

+148
-0
lines changed

3 files changed

+148
-0
lines changed
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
#testDeployKserveRaw.cy.ts Test Data #
2+
projectDisplayName: KServe Raw Test Project
3+
projectDescription: Test project for KServe Raw deployment mode testing
4+
projectResourceName: test-kserve-raw-project
5+
singleModelName: 'test-model'
6+
modelOpenVinoPath: kserve-openvino-test/openvino-example-model
Lines changed: 117 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,117 @@
1+
import {
2+
inferenceServiceModal,
3+
modelServingGlobal,
4+
modelServingSection,
5+
} from '#~/__tests__/cypress/cypress/pages/modelServing';
6+
import { projectDetails, projectListPage } from '#~/__tests__/cypress/cypress/pages/projects';
7+
import type { DataScienceProjectData } from '#~/__tests__/cypress/cypress/types';
8+
import { loadDSPFixture } from '#~/__tests__/cypress/cypress/utils/dataLoader';
9+
import { HTPASSWD_CLUSTER_ADMIN_USER } from '#~/__tests__/cypress/cypress/utils/e2eUsers';
10+
import {
11+
checkInferenceServiceState,
12+
provisionProjectForModelServing,
13+
} from '#~/__tests__/cypress/cypress/utils/oc_commands/modelServing';
14+
import { deleteOpenShiftProject } from '#~/__tests__/cypress/cypress/utils/oc_commands/project';
15+
import { retryableBefore } from '#~/__tests__/cypress/cypress/utils/retryableHooks';
16+
import { generateTestUUID } from '#~/__tests__/cypress/cypress/utils/uuidGenerator';
17+
18+
let testData: DataScienceProjectData;
19+
let projectName: string;
20+
let modelName: string;
21+
let modelFilePath: string;
22+
const awsBucket = 'BUCKET_1' as const;
23+
const uuid = generateTestUUID();
24+
25+
describe('[Product Bug: RHOAIENG-31261] Verify a user can deploy KServe Raw Deployment Model', () => {
26+
retryableBefore(() => {
27+
cy.log('Loading test data');
28+
return loadDSPFixture('e2e/dataScienceProjects/testDeployKserveRaw.yaml').then(
29+
(fixtureData: DataScienceProjectData) => {
30+
testData = fixtureData;
31+
projectName = `${testData.projectResourceName}-${uuid}`;
32+
modelName = testData.singleModelName;
33+
modelFilePath = testData.modelOpenVinoPath;
34+
35+
if (!projectName) {
36+
throw new Error('Project name is undefined or empty in the loaded fixture');
37+
}
38+
cy.log(`Loaded project name: ${projectName}`);
39+
40+
// Provision project with data connection for model serving
41+
provisionProjectForModelServing(
42+
projectName,
43+
awsBucket,
44+
'resources/yaml/data_connection_model_serving.yaml',
45+
);
46+
},
47+
);
48+
});
49+
50+
after(() => {
51+
cy.log(`Cleaning up project: ${projectName}`);
52+
// Delete provisioned Project - wait for completion due to RHOAIENG-19969 to support test retries, 5 minute timeout
53+
// TODO: Review this timeout once RHOAIENG-19969 is resolved
54+
deleteOpenShiftProject(projectName, { wait: true, ignoreNotFound: true, timeout: 300000 });
55+
});
56+
57+
it(
58+
'Verify model deployment with Standard deployment mode (KServe Raw)',
59+
{
60+
tags: ['@Smoke', '@SmokeSet3', '@Dashboard', '@Modelserving', '@NonConcurrent', '@Bug'],
61+
},
62+
() => {
63+
cy.step(`Log into the application with ${HTPASSWD_CLUSTER_ADMIN_USER.USERNAME}`);
64+
cy.visitWithLogin('/', HTPASSWD_CLUSTER_ADMIN_USER);
65+
// Project navigation
66+
cy.step(`Navigate to the Project list tab and search for ${projectName}`);
67+
projectListPage.navigate();
68+
projectListPage.filterProjectByName(projectName);
69+
projectListPage.findProjectLink(projectName).click();
70+
// Navigate to Model Serving section and Deploy a Model
71+
cy.step('Navigate to Model Serving and click to Deploy a Single Model');
72+
projectDetails.findSectionTab('model-server').click();
73+
modelServingGlobal.findSingleServingModelButton().click();
74+
modelServingGlobal.findDeployModelButton().click();
75+
inferenceServiceModal.shouldBeOpen();
76+
cy.step('Launch a Single Serving Model and configure deployment mode');
77+
inferenceServiceModal.findModelNameInput().type(modelName);
78+
inferenceServiceModal.findServingRuntimeTemplateSearchSelector().click();
79+
inferenceServiceModal.findGlobalScopedTemplateOption('OpenVINO Model Server').click();
80+
inferenceServiceModal.findModelFrameworkSelect().click();
81+
inferenceServiceModal.findOpenVinoIROpSet13().click();
82+
// Select Standard Deployment mode (KServe Raw)
83+
cy.step(
84+
'Verify deployment mode dropdown exists and Select Standard Deployment mode (KServe Raw)',
85+
);
86+
inferenceServiceModal.findDeploymentModeSelect().should('exist');
87+
inferenceServiceModal.findDeploymentModeSelect().findSelectOption('Standard').click();
88+
inferenceServiceModal
89+
.findDeploymentModeSelect()
90+
.findSelectOption('Standard')
91+
.should('have.attr', 'aria-selected', 'true');
92+
93+
inferenceServiceModal
94+
.findDeploymentModeSelect()
95+
.findSelectOption('Advanced')
96+
.should('have.attr', 'aria-selected', 'false');
97+
inferenceServiceModal.findLocationPathInput().type(modelFilePath);
98+
cy.step('Deploy the model');
99+
inferenceServiceModal.findSubmitButton().click();
100+
inferenceServiceModal.shouldBeOpen(false);
101+
modelServingSection.findModelServerDeployedName(modelName);
102+
103+
cy.step('Verify that the Model is created Successfully on the backend and frontend');
104+
// For KServe Raw deployments, we only need to check Ready condition
105+
// LatestDeploymentReady is specific to Serverless deployments
106+
// Validate DeploymentMode parameter in inferenceService is RawDeployment
107+
checkInferenceServiceState(
108+
modelName,
109+
projectName,
110+
{
111+
checkReady: true,
112+
},
113+
'RawDeployment',
114+
);
115+
},
116+
);
117+
});

frontend/src/__tests__/cypress/cypress/utils/oc_commands/modelServing.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ type InferenceServiceState = {
5959
activeModelState?: string;
6060
};
6161
};
62+
deploymentMode?: string;
6263
};
6364
};
6465

@@ -99,6 +100,7 @@ export const checkInferenceServiceState = (
99100
serviceName: string,
100101
namespace: string,
101102
options: ConditionCheckOptions = {},
103+
DeploymentMode?: 'RawDeployment' | 'Serverless',
102104
): Cypress.Chainable<Cypress.Exec> => {
103105
const ocCommand = `oc get inferenceService ${serviceName} -n ${namespace} -o json`;
104106
const maxAttempts = 96; // 8 minutes / 5 seconds = 96 attempts
@@ -147,10 +149,14 @@ export const checkInferenceServiceState = (
147149
serviceState.status?.modelStatus?.states?.activeModelState || 'EMPTY';
148150
const conditions = serviceState.status?.conditions || [];
149151

152+
// Check deployment mode
153+
const actualDeploymentMode = serviceState.status?.deploymentMode || 'EMPTY';
154+
150155
// Detailed initial logging
151156
cy.log(`🧐 Attempt ${attempts}: Checking InferenceService state
152157
Service Name: ${serviceName}
153158
Active Model State: ${activeModelState}
159+
Deployment Mode: ${actualDeploymentMode}
154160
Total Conditions: ${conditions.length}`);
155161

156162
// Prepare condition checks with logging
@@ -214,6 +220,24 @@ export const checkInferenceServiceState = (
214220
const isModelLoaded = activeModelState === 'Loaded';
215221
cy.log(`Active Model State Check: ${isModelLoaded ? '✅ Loaded' : '❌ Not Loaded'}`);
216222

223+
if (DeploymentMode) {
224+
const expectedDeploymentMode = DeploymentMode;
225+
cy.log(`🔍 InferenceService deployment mode check:
226+
Service: ${serviceName}
227+
Expected: ${expectedDeploymentMode}
228+
Actual: ${actualDeploymentMode}
229+
Match: ${actualDeploymentMode === expectedDeploymentMode ? '✅' : '❌'}`);
230+
231+
if (actualDeploymentMode !== expectedDeploymentMode) {
232+
throw new Error(
233+
`Deployment mode mismatch. Expected: ${expectedDeploymentMode}, Actual: ${actualDeploymentMode}`,
234+
);
235+
}
236+
237+
cy.log(
238+
`✅ InferenceService ${serviceName} has correct deployment mode: ${expectedDeploymentMode}`,
239+
);
240+
}
217241
// Determine overall success
218242
// If no condition checks were specified, only check model state
219243
const allConditionsPassed =
@@ -459,6 +483,7 @@ export const verifyS3CopyCompleted = (
459483
}
460484
});
461485
};
486+
462487
/**
463488
* Retrieve the token for a given service account and model
464489
*

0 commit comments

Comments
 (0)