Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main' into rhoai-2.17
Browse files Browse the repository at this point in the history
  • Loading branch information
dchourasia committed Dec 19, 2024
2 parents edad8a6 + 4eeb700 commit 1316cb0
Show file tree
Hide file tree
Showing 48 changed files with 1,112 additions and 268 deletions.
24 changes: 24 additions & 0 deletions backend/src/routes/api/modelRegistryCertificates/index.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
import { secureAdminRoute } from '../../../utils/route-security';
import { KubeFastifyInstance } from '../../../types';
import { getModelRegistryNamespace } from '../modelRegistries/modelRegistryUtils';
import { listModelRegistryCertificateNames } from './modelRegistryCertificatesUtils';
import { FastifyReply, FastifyRequest } from 'fastify';

export default async (fastify: KubeFastifyInstance): Promise<void> => {
fastify.get(
'/',
secureAdminRoute(fastify)(async (request: FastifyRequest, reply: FastifyReply) => {
try {
const modelRegistryNamespace = getModelRegistryNamespace(fastify);
return listModelRegistryCertificateNames(fastify, modelRegistryNamespace);
} catch (e) {
fastify.log.error(
`Model registry certificate names could not be listed, ${
e.response?.body?.message || e.message
}`,
);
reply.send(e);
}
}),
);
};
Original file line number Diff line number Diff line change
@@ -0,0 +1,63 @@
import { V1ConfigMap, V1Secret } from '@kubernetes/client-node';
import { ConfigSecretItem, KubeFastifyInstance } from '../../../types';

export const listSecrets = async (
fastify: KubeFastifyInstance,
modelRegistryNamespace: string,
): Promise<{ items: V1Secret[] }> => {
const response = await (fastify.kube.coreV1Api.listNamespacedSecret(
modelRegistryNamespace,
) as Promise<{ body: { items: V1Secret[] } }>);
return response.body;
};

export const listConfigMaps = async (
fastify: KubeFastifyInstance,
modelRegistryNamespace: string,
): Promise<{ items: V1ConfigMap[] }> => {
const response = await (fastify.kube.coreV1Api.listNamespacedConfigMap(
modelRegistryNamespace,
) as Promise<{ body: { items: V1ConfigMap[] } }>);
return response.body;
};

export const listModelRegistryCertificateNames = async (
fastify: KubeFastifyInstance,
namespace: string,
): Promise<{
secrets: ConfigSecretItem[];
configMaps: ConfigSecretItem[];
}> => {
try {
const [secretsResponse, configMapsResponse] = await Promise.all([
listSecrets(fastify, namespace),
listConfigMaps(fastify, namespace),
]);

const secrets = secretsResponse.items
.filter((secret) => secret.type === 'Opaque')
.map((secret) => {
const keys = Object.keys(secret.data || {}).filter(
(key) => secret.data?.[key] !== undefined && secret.data[key] !== '',
);
return { name: secret.metadata?.name || 'unknown', keys };
})
.filter((secret) => secret.keys.length > 0);

const configMaps = configMapsResponse.items
.map((configMap) => {
const keys = Object.keys(configMap.data || {}).filter(
(key) => configMap.data?.[key] !== undefined && configMap.data[key] !== '',
);
return { name: configMap.metadata?.name || 'unknown', keys };
})
.filter((configMap) => configMap.keys.length > 0);

return { secrets, configMaps };
} catch (e: any) {
fastify.log.error(
`Error fetching config maps and secrets, ${e.response?.body?.message || e.message}`,
);
throw e;
}
};
10 changes: 10 additions & 0 deletions backend/src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -1261,3 +1261,13 @@ export type ResourceAccessReviewResponse = {
groups?: string[];
users?: string[];
};

export type ConfigSecretItem = {
name: string;
keys: string[];
};

export type ListConfigSecretsResponse = {
secrets: ConfigSecretItem[];
configMaps: ConfigSecretItem[];
};
2 changes: 2 additions & 0 deletions frontend/src/__mocks__/mockInferenceServiceModalData.ts
Original file line number Diff line number Diff line change
Expand Up @@ -38,6 +38,7 @@ export const mockInferenceServiceModalData = ({
},
},
},
isKServeRawDeployment,
}: MockResourceConfigType): CreatingInferenceServiceObject => ({
name,
k8sName,
Expand All @@ -51,4 +52,5 @@ export const mockInferenceServiceModalData = ({
tokenAuth,
tokens,
modelSize,
isKServeRawDeployment,
});
28 changes: 27 additions & 1 deletion frontend/src/__tests__/cypress/cypress/pages/clusterStorage.ts
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,19 @@ class ClusterStorageRow extends TableRow {
findStorageClassResourceKindText() {
return cy.findByTestId('resource-kind-text');
}

findStorageSizeWarning() {
return cy.findByTestId('size-warning-popover').click();
}

findStorageSizeWarningText() {
return cy
.findByTestId('size-warning-popover-text')
.should(
'have.text',
'To complete the storage size update, you must connect and run a workbench.',
);
}
}

class ClusterStorageModal extends Modal {
Expand All @@ -64,10 +77,23 @@ class ClusterStorageModal extends Modal {
}

selectWorkbenchName(row: number, name: string) {
this.findWorkbenchTable().find(`[data-label=Name]`).eq(row).find('button').click();
this.findWorkbenchSelect(row).click();
cy.findByRole('option', { name, hidden: true }).click();
}

findWorkbenchSelect(row: number) {
return this.findWorkbenchTable()
.find(`[data-label=Name]`)
.eq(row)
.findByTestId('cluster-storage-workbench-select');
}

findWorkbenchSelectValueField(row: number) {
return this.findWorkbenchSelect(row).findByRole('combobox', {
name: 'Type to filter',
});
}

selectCustomPathFormat(row: number) {
this.findWorkbenchTable().find(`[data-label="Path format"]`).eq(row).find('button').click();
cy.findByRole('option', {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ class ModelVersionDeployModal extends Modal {
}

selectProjectByName(name: string) {
this.findProjectSelector().click();
this.find().findByRole('option', { name, timeout: 5000 }).click();
this.findProjectSelector().findSelectOption(name).click();
}
}

Expand Down
4 changes: 4 additions & 0 deletions frontend/src/__tests__/cypress/cypress/pages/modelServing.ts
Original file line number Diff line number Diff line change
Expand Up @@ -101,6 +101,10 @@ class InferenceServiceModal extends Modal {
return this.find().findByTestId('inference-service-framework-selection');
}

findDeploymentModeSelect() {
return this.find().findByTestId('deployment-mode-select');
}

findExistingDataConnectionOption() {
return this.find().findByTestId('existing-data-connection-radio');
}
Expand Down
13 changes: 8 additions & 5 deletions frontend/src/__tests__/cypress/cypress/pages/workbench.ts
Original file line number Diff line number Diff line change
Expand Up @@ -353,11 +353,14 @@ class CreateSpawnerPage {
return cy.findByTestId('existing-data-connection-type-radio');
}

selectExistingDataConnection(name: string) {
cy.findByTestId('data-connection-group')
.findByRole('button', { name: 'Typeahead menu toggle' })
.findSelectOption(name)
.click();
findExistingDataConnectionSelect() {
return cy.findByTestId('existing-data-connection-select');
}

findExistingDataConnectionSelectValueField() {
return this.findExistingDataConnectionSelect().findByRole('combobox', {
name: 'Type to filter',
});
}

findAwsNameInput() {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -184,14 +184,21 @@ const initIntercepts = ({
};

describe('Deploy model version', () => {
it('Deploy model version on unsupported platform', () => {
initIntercepts({ kServeInstalled: false, modelMeshInstalled: false });
it('Deploy model version on unsupported multi-model platform', () => {
initIntercepts({ modelMeshInstalled: false });
cy.visit(`/modelRegistry/modelregistry-sample/registeredModels/1/versions`);
const modelVersionRow = modelRegistry.getModelVersionRow('test model version');
modelVersionRow.findKebabAction('Deploy').click();
cy.wait('@getProjects');
modelVersionDeployModal.selectProjectByName('Model mesh project');
cy.findByText('Multi-model platform is not installed').should('exist');
});

it('Deploy model version on unsupported single-model platform', () => {
initIntercepts({ kServeInstalled: false });
cy.visit(`/modelRegistry/modelregistry-sample/registeredModels/1/versions`);
const modelVersionRow = modelRegistry.getModelVersionRow('test model version');
modelVersionRow.findKebabAction('Deploy').click();
cy.wait('@getProjects');
modelVersionDeployModal.selectProjectByName('KServe project');
cy.findByText('Single-model platform is not installed').should('exist');
Expand Down
Loading

0 comments on commit 1316cb0

Please sign in to comment.