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 Jan 8, 2025
2 parents 7185680 + 02a82a3 commit 57b20b2
Show file tree
Hide file tree
Showing 26 changed files with 433 additions and 170 deletions.
10 changes: 9 additions & 1 deletion frontend/src/__mocks__/mockNimAccount.ts
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,15 @@ export const mockNimAccount = ({
nimConfigName = 'mock-nvidia-nim-images-data',
runtimeTemplateName = 'mock-nvidia-nim-serving-template',
nimPullSecretName = 'mock-nvidia-nim-image-pull',
conditions = [],
conditions = [
{
type: 'AccountStatus',
status: 'True',
lastTransitionTime: new Date().toISOString(),
reason: 'AccountSuccessful',
message: 'reconciled successfully',
},
],
}: MockResourceConfigType): NIMAccountKind => ({
apiVersion: 'nim.opendatahub.io/v1',
kind: 'Account',
Expand Down
114 changes: 114 additions & 0 deletions frontend/src/__mocks__/mockOdhApplication.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
import { OdhApplication, OdhApplicationCategory } from '~/types';

type MockOdhApplicationConfig = {
name?: string;
displayName?: string;
provider?: string;
description?: string;
route?: string | null;
routeNamespace?: string | null;
routeSuffix?: string | null;
serviceName?: string | null;
endpoint?: string | null;
link?: string | null;
img?: string;
docsLink?: string;
hidden?: boolean | null;
getStartedLink?: string;
getStartedMarkDown?: string;
category?: OdhApplicationCategory | string;
support?: string;
quickStart?: string | null;
comingSoon?: boolean | null;
beta?: boolean | null;
betaTitle?: string | null;
betaText?: string | null;
shownOnEnabledPage?: boolean | null;
isEnabled?: boolean | null;
kfdefApplications?: string[];
csvName?: string;
annotations?: { [key: string]: string };
enable?: {
title: string;
actionLabel: string;
description?: string;
linkPreface?: string;
link?: string;
variables?: { [key: string]: string };
variableDisplayText?: { [key: string]: string };
variableHelpText?: { [key: string]: string };
validationSecret: string;
validationJob: string;
validationConfigMap?: string;
};
featureFlag?: string;
internalRoute?: string;
};

export const mockOdhApplication = ({
name = 'nvidia-nim',
displayName = 'Test Application',
provider = 'Test Provider',
description = 'Test Description',
route = null,
routeNamespace = null,
routeSuffix = null,
serviceName = null,
endpoint = null,
link = null,
img = 'test-image.png',
docsLink = 'https://test-docs.com',
hidden = null,
getStartedLink = 'https://test-getting-started.com',
getStartedMarkDown = '# Getting Started',
category = 'category-1',
support = 'test-support',
quickStart = null,
comingSoon = null,
beta = null,
betaTitle = null,
betaText = null,
shownOnEnabledPage = null,
isEnabled = null,
kfdefApplications = [],
csvName = undefined,
annotations = {},
enable = undefined,
featureFlag = undefined,
internalRoute = '/api/integrations/nim',
}: MockOdhApplicationConfig = {}): OdhApplication => ({
metadata: {
name,
annotations,
},
spec: {
displayName,
provider,
description,
route,
routeNamespace,
routeSuffix,
serviceName,
endpoint,
link,
img,
docsLink,
hidden,
getStartedLink,
getStartedMarkDown,
category,
support,
quickStart,
comingSoon,
beta,
betaTitle,
betaText,
shownOnEnabledPage,
isEnabled,
kfdefApplications,
csvName,
enable,
featureFlag,
internalRoute,
},
});
10 changes: 10 additions & 0 deletions frontend/src/__tests__/cypress/cypress/support/commands/odh.ts
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,7 @@ import type {
ClusterSettingsType,
DetectedAccelerators,
ImageInfo,
IntegrationAppStatus,
OdhApplication,
OdhDocument,
PrometheusQueryRangeResponse,
Expand Down Expand Up @@ -701,6 +702,15 @@ declare global {
},
response: OdhResponse<NimServingResponse>,
) => Cypress.Chainable<null>) &
((
type: 'GET /api/integrations/:internalRoute',
options: {
path: {
internalRoute: string;
};
},
response: OdhResponse<IntegrationAppStatus>,
) => Cypress.Chainable<null>) &
((
type: 'PATCH /api/service/modelregistry/:serviceName/api/model_registry/:apiVersion/registered_models/:registeredModelId',
options: {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ import { asProjectAdminUser } from '~/__tests__/cypress/cypress/utils/mockUsers'
import { NamespaceApplicationCase } from '~/pages/projects/types';
import { mockNimServingRuntimeTemplate } from '~/__mocks__/mockNimResource';
import { mockNimAccount } from '~/__mocks__/mockNimAccount';
import { mockOdhApplication } from '~/__mocks__/mockOdhApplication';

type HandlersProps = {
isEmpty?: boolean;
Expand Down Expand Up @@ -274,6 +275,17 @@ const initIntercepts = ({
buildMockPipelines(isEmpty ? [] : [mockPipelineKF({})]),
);

cy.interceptOdh('GET /api/components', null, [mockOdhApplication({})]);
cy.interceptOdh(
'GET /api/integrations/:internalRoute',
{ path: { internalRoute: 'nim' } },
{
isInstalled: true,
isEnabled: true,
canInstall: false,
error: '',
},
);
cy.interceptK8sList(NIMAccountModel, mockK8sResourceList([mockNimAccount({})]));
};

Expand Down
46 changes: 39 additions & 7 deletions frontend/src/__tests__/cypress/cypress/utils/nimUtils.ts
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ import {
import { mockAcceleratorProfile } from '~/__mocks__/mockAcceleratorProfile';
import type { InferenceServiceKind } from '~/k8sTypes';
import { mockNimAccount } from '~/__mocks__/mockNimAccount';
import { mockOdhApplication } from '~/__mocks__/mockOdhApplication';

/* ###################################################
###### Interception Initialization Utilities ######
Expand Down Expand Up @@ -62,6 +63,20 @@ export const initInterceptsToEnableNim = ({ hasAllModels = false }: EnableNimCon
}),
);

cy.interceptOdh('GET /api/components', null, [mockOdhApplication({})]);

cy.interceptOdh(
'GET /api/integrations/:internalRoute',
{ path: { internalRoute: 'nim' } },
{
isInstalled: true,
isEnabled: true,
canInstall: false,
error: '',
},
);

cy.interceptK8sList(NIMAccountModel, mockK8sResourceList([mockNimAccount({})]));
cy.interceptK8sList(ProjectModel, mockK8sResourceList([mockNimProject(hasAllModels)]));

const templateMock = mockNimServingRuntimeTemplate();
Expand All @@ -79,8 +94,6 @@ export const initInterceptsToEnableNim = ({ hasAllModels = false }: EnableNimCon
total: { 'nvidia.com/gpu': 1 },
allocated: { 'nvidia.com/gpu': 1 },
});

cy.interceptK8sList(NIMAccountModel, mockK8sResourceList([mockNimAccount({})]));
};

// intercept all APIs required for deploying new NIM models in existing projects
Expand Down Expand Up @@ -149,16 +162,35 @@ export const initInterceptorsValidatingNimEnablement = (
): void => {
cy.interceptOdh('GET /api/config', mockDashboardConfig(dashboardConfig));

cy.interceptOdh('GET /api/components', null, [mockOdhApplication({})]);

cy.interceptOdh(
'GET /api/integrations/:internalRoute',
{ path: { internalRoute: 'nim' } },
{
isInstalled: true,
isEnabled: false,
canInstall: false,
error: '',
},
);
cy.interceptK8sList(NIMAccountModel, mockK8sResourceList([mockNimAccount({})]));

if (!disableServingRuntime) {
const templateMock = mockNimServingRuntimeTemplate();
cy.interceptK8sList(TemplateModel, mockK8sResourceList([templateMock]));
cy.interceptK8s(TemplateModel, templateMock);
cy.interceptOdh(
'GET /api/integrations/:internalRoute',
{ path: { internalRoute: 'nim' } },
{
isInstalled: true,
isEnabled: true,
canInstall: false,
error: '',
},
);
}

cy.interceptK8sList(
ProjectModel,
mockK8sResourceList([mockProjectK8sResource({ hasAnnotations: true })]),
);

cy.interceptK8sList(NIMAccountModel, mockK8sResourceList([mockNimAccount({})]));
};
10 changes: 10 additions & 0 deletions frontend/src/app/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -65,3 +65,13 @@ body,
max-height: 65vh;
overflow: auto;
}

// Necessary to scroll select menus with grouped sections. Remove when https://github.com/patternfly/patternfly/issues/7256 is resolved
.pf-v6-c-menu {
&.pf-m-scrollable .pf-v6-c-menu__content {
overflow: auto;
}
&.pf-m-drilldown:not(.pf-m-scrollable) {
overflow: hidden;
}
}
17 changes: 10 additions & 7 deletions frontend/src/app/App.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,7 @@ import ProjectsContextProvider from '~/concepts/projects/ProjectsContext';
import { ModelRegistrySelectorContextProvider } from '~/concepts/modelRegistry/context/ModelRegistrySelectorContext';
import useStorageClasses from '~/concepts/k8s/useStorageClasses';
import AreaContextProvider from '~/concepts/areas/AreaContext';
import { NimContextProvider } from '~/concepts/nimServing/NIMAvailabilityContext';
import useDevFeatureFlags from './useDevFeatureFlags';
import Header from './Header';
import AppRoutes from './AppRoutes';
Expand Down Expand Up @@ -130,13 +131,15 @@ const App: React.FC = () => {
}
>
<ErrorBoundary>
<ProjectsContextProvider>
<ModelRegistrySelectorContextProvider>
<QuickStarts>
<AppRoutes />
</QuickStarts>
</ModelRegistrySelectorContextProvider>
</ProjectsContextProvider>
<NimContextProvider>
<ProjectsContextProvider>
<ModelRegistrySelectorContextProvider>
<QuickStarts>
<AppRoutes />
</QuickStarts>
</ModelRegistrySelectorContextProvider>
</ProjectsContextProvider>
</NimContextProvider>
<ToastNotifications />
<TelemetrySetup />
</ErrorBoundary>
Expand Down
37 changes: 37 additions & 0 deletions frontend/src/concepts/nimServing/NIMAvailabilityContext.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,37 @@
import * as React from 'react';
import { useIsNIMAvailable } from '~/pages/modelServing/screens/projects/useIsNIMAvailable';

export type NIMAvailabilityContextType = {
isNIMAvailable: boolean;
loaded: boolean;
};

type NIMAvailabilityContextProviderProps = {
children: React.ReactNode;
};

export const NIMAvailabilityContext = React.createContext<NIMAvailabilityContextType>({
isNIMAvailable: false,
loaded: false,
});

export const NimContextProvider: React.FC<NIMAvailabilityContextProviderProps> = ({
children,
...props
}) => {
return <EnabledNimContextProvider {...props}>{children}</EnabledNimContextProvider>;

return children;
};

const EnabledNimContextProvider: React.FC<NIMAvailabilityContextProviderProps> = ({ children }) => {
const [isNIMAvailable, loaded] = useIsNIMAvailable();

const contextValue = React.useMemo(() => ({ isNIMAvailable, loaded }), [isNIMAvailable, loaded]);

return (
<NIMAvailabilityContext.Provider value={contextValue}>
{children}
</NIMAvailabilityContext.Provider>
);
};
Loading

0 comments on commit 57b20b2

Please sign in to comment.