Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/main'
Browse files Browse the repository at this point in the history
  • Loading branch information
dchourasia committed Dec 13, 2024
2 parents eeec810 + 5331d69 commit 46225dc
Show file tree
Hide file tree
Showing 7 changed files with 62 additions and 161 deletions.
129 changes: 1 addition & 128 deletions backend/src/utils/resourceUtils.ts
Original file line number Diff line number Diff line change
@@ -1,14 +1,6 @@
import * as _ from 'lodash';
import createError from 'http-errors';
import {
PatchUtils,
V1ConfigMap,
V1Namespace,
V1NamespaceList,
V1Role,
V1RoleBinding,
V1RoleBindingList,
} from '@kubernetes/client-node';
import { V1ConfigMap, V1Role, V1RoleBinding, V1RoleBindingList } from '@kubernetes/client-node';
import {
AcceleratorProfileKind,
BuildPhase,
Expand Down Expand Up @@ -40,7 +32,6 @@ import {
import { getComponentFeatureFlags } from './features';
import { blankDashboardCR } from './constants';
import { getIsAppEnabled, getRouteForApplication, getRouteForClusterId } from './componentUtils';
import { createCustomError } from './requestUtils';
import { getDetectedAccelerators } from '../routes/api/accelerators/acceleratorUtils';
import { FastifyRequest } from 'fastify';
import { fetchClusterStatus } from './dsc';
Expand Down Expand Up @@ -908,124 +899,6 @@ export const cleanupGPU = async (fastify: KubeFastifyInstance): Promise<void> =>
await createSuccessfulMigrationConfigMap(fastify, CONFIG_MAP_NAME, DESCRIPTION);
}
};
/**
* @deprecated - Look to remove asap (see comments below)
* Converts namespaces that have a display-name annotation suffixed with `[DSP]` over to using a label.
* This is migration code from 1.19 to 1.20+. When customers are no longer on 1.19, we should remove
* this code.
*/
export const cleanupDSPSuffix = async (fastify: KubeFastifyInstance): Promise<void> => {
const CONFIG_MAP_NAME = 'dsg-prune-flag';

const continueProcessing = await fastify.kube.coreV1Api
.readNamespacedConfigMap(CONFIG_MAP_NAME, fastify.kube.namespace)
.then(() => {
// Found configmap, we're note continuing
return false;
})
.catch((e) => {
if (e.statusCode === 404) {
// No config saying we have already pruned settings
return true;
}
throw e;
});

if (continueProcessing) {
const configMap: V1ConfigMap = {
metadata: {
name: CONFIG_MAP_NAME,
namespace: fastify.kube.namespace,
},
data: {
startedPrune: 'true',
},
};
await fastify.kube.coreV1Api
.createNamespacedConfigMap(fastify.kube.namespace, configMap)
.then(() => fastify.log.info('Successfully created prune setting'))
.catch((e) => {
throw createCustomError(
'Unable to create DSG prune setting configmap',
e.response?.body?.message || e.message,
);
});
} else {
// Already processed, exit early and save the processing
return;
}

let namespaces: V1Namespace[] = [];

let continueValue: string | undefined = undefined;
do {
const listNamespaces: V1NamespaceList = await fastify.kube.coreV1Api
.listNamespace(undefined, undefined, continueValue, undefined, undefined, 100)
.then((response) => response.body);

const {
metadata: { _continue: continueProp },
items,
} = listNamespaces;

namespaces = namespaces.concat(items);
continueValue = continueProp;
} while (continueValue);

const SUFFIX = '[DSP]';

const toChangeNamespaces = namespaces.filter(
(namespace) =>
// Don't touch any openshift or kube namespaces
!(
namespace.metadata.name.startsWith('openshift') ||
namespace.metadata.name.startsWith('kube')
) &&
// Just get the namespaces who are suffixed so we can convert them
namespace.metadata.annotations?.['openshift.io/display-name']?.endsWith(SUFFIX),
);

if (toChangeNamespaces.length === 0) {
return;
}

fastify.log.info(`Updating ${toChangeNamespaces.length} Namespace(s) over to DSG with labels.`);

const data = (namespace: V1Namespace) => {
const displayName = namespace.metadata.annotations['openshift.io/display-name'];

return {
metadata: {
annotations: {
'openshift.io/display-name': displayName.slice(0, displayName.length - SUFFIX.length),
},
labels: {
'opendatahub.io/dashboard': 'true',
},
},
};
};

const calls = toChangeNamespaces.map((namespace) =>
fastify.kube.coreV1Api
.patchNamespace(
namespace.metadata.name,
data(namespace),
undefined,
undefined,
undefined,
undefined,
{
headers: { 'Content-type': PatchUtils.PATCH_FORMAT_JSON_MERGE_PATCH },
},
)
.then(() => fastify.log.info(`Converted ${namespace.metadata.name} over to using labels.`)),
);

Promise.all(calls).then(() => {
fastify.log.info('Completed updating Namespaces');
});
};

/**
* TODO: There should be a better way to go about this... but the namespace is unlikely to ever change
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,10 @@ describe('Home page AI Flows', () => {

homeAISection.getProjectCard().find().should('not.exist');

homePage.initHomeIntercepts({ disableModelServing: true });
homePage.initHomeIntercepts({
disableModelServing: true,
disableModelRegistry: true,
});
homePage.visit();

homeAISection.getModelsFlowCard().find().should('not.exist');
Expand Down
63 changes: 46 additions & 17 deletions frontend/src/pages/home/aiFlows/DeployAndMonitorGallery.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,40 @@ import { Content } from '@patternfly/react-core';
import { ProjectObjectType, SectionType } from '~/concepts/design/utils';
import InfoGalleryItem from '~/concepts/design/InfoGalleryItem';
import useServingPlatformStatuses from '~/pages/modelServing/useServingPlatformStatuses';
import useIsAreaAvailable from '~/concepts/areas/useIsAreaAvailable';
import { SupportedArea } from '~/concepts/areas';
import InfoGallery from './InfoGallery';

const DeployAndMonitorGallery: React.FC<{ onClose: () => void }> = ({ onClose }) => {
const servingPlatformStatuses = useServingPlatformStatuses();
const { status: modelRegistryAvailable } = useIsAreaAvailable(SupportedArea.MODEL_REGISTRY);
const modelMeshEnabled = servingPlatformStatuses.modelMesh.enabled;
const kServeEnabled = servingPlatformStatuses.kServe.enabled;

const infoItems = [];

if (modelRegistryAvailable) {
infoItems.push(
<InfoGalleryItem
key="model-registry"
data-testid="ai-flows-model-registry-info"
title="Model registry"
resourceType={ProjectObjectType.modelRegistrySettings}
sectionType={SectionType.serving}
description={
<Content>
<Content component="small">
Model registries provide a structured and organized way to store, version, deploy, and
track models, ensuring that they are easily accessible and manageable throughout their
lifecycle.
</Content>
</Content>
}
isOpen
/>,
);
}

if (modelMeshEnabled) {
infoItems.push(
<InfoGalleryItem
Expand All @@ -34,24 +60,27 @@ const DeployAndMonitorGallery: React.FC<{ onClose: () => void }> = ({ onClose })
);
}

infoItems.push(
<InfoGalleryItem
key="model-deploy"
data-testid="ai-flows-model-deploy-info"
title="Deploying models"
resourceType={ProjectObjectType.deployingModels}
sectionType={SectionType.serving}
description={
<Content>
<Content component="small">
Deploy models to test them and integrate them into applications. Deploying a model makes
it accessible via an API, enabling you to return predictions based on data inputs.
if (modelMeshEnabled || kServeEnabled) {
infoItems.push(
<InfoGalleryItem
key="model-deploy"
data-testid="ai-flows-model-deploy-info"
title="Deploying models"
resourceType={ProjectObjectType.deployingModels}
sectionType={SectionType.serving}
description={
<Content>
<Content component="small">
Deploy models to test them and integrate them into applications. Deploying a model
makes it accessible via an API, enabling you to return predictions based on data
inputs.
</Content>
</Content>
</Content>
}
isOpen
/>,
);
}
isOpen
/>,
);
}

return (
<InfoGallery
Expand Down
8 changes: 5 additions & 3 deletions frontend/src/pages/home/aiFlows/useAIFlows.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@ export const useAIFlows = (): React.ReactNode => {
const { status: pipelinesAvailable } = useIsAreaAvailable(SupportedArea.DS_PIPELINES);
const { status: projectsAvailable } = useIsAreaAvailable(SupportedArea.DS_PROJECTS_VIEW);
const { status: modelServingAvailable } = useIsAreaAvailable(SupportedArea.MODEL_SERVING);
const { status: modelRegistryAvailable } = useIsAreaAvailable(SupportedArea.MODEL_REGISTRY);
const [selected, setSelected] = React.useState<string | undefined>();

return React.useMemo(() => {
Expand Down Expand Up @@ -55,12 +56,12 @@ export const useAIFlows = (): React.ReactNode => {
/>,
);
}
if (modelServingAvailable) {
if (modelServingAvailable || modelRegistryAvailable) {
cards.push(
<AIFlowCard
key="models"
data-testid="ai-flow-models-card"
title="Deploy and monitor models"
title="Manage models"
image={
<ModelIcon
aria-hidden="true"
Expand All @@ -82,7 +83,7 @@ export const useAIFlows = (): React.ReactNode => {
<PageSection hasBodyWrapper={false} data-testid="home-page-ai-flows">
<Stack hasGutter>
<Content>
<Content component="h1">Train, serve, monitor, and manage AI/ML models</Content>
<Content component="h1">Work with AI/ML models</Content>
</Content>
<EvenlySpacedGallery itemCount={cards.length} hasGutter>
{cards}
Expand All @@ -101,6 +102,7 @@ export const useAIFlows = (): React.ReactNode => {
);
}, [
modelServingAvailable,
modelRegistryAvailable,
pipelinesAvailable,
projectsAvailable,
selected,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
import React from 'react';
import { Link } from 'react-router-dom';

import { Alert, Stack } from '@patternfly/react-core';

import EmptyModelRegistryState from '~/pages/modelRegistry/screens/components/EmptyModelRegistryState';
import InferenceServiceTable from '~/pages/modelServing/screens/global/InferenceServiceTable';
import { getVersionDetailsInferenceServiceColumns } from '~/pages/modelServing/screens/global/data';
import { typedEmptyImage, ProjectObjectType } from '~/concepts/design/utils';
import ModelVersionDetailsTabs from './ModelVersionDetailsTabs';
import ModelVersionDetailsTabs from '~/pages/modelRegistry/screens/ModelVersionDetails/ModelVersionDetailsTabs';
import { ProjectObjectType, typedEmptyImage } from '~/concepts/design/utils';
import EmptyModelRegistryState from '~/pages/modelRegistry/screens/components/EmptyModelRegistryState';

type ModelVersionRegisteredDeploymentsViewProps = Pick<
React.ComponentProps<typeof ModelVersionDetailsTabs>,
Expand Down Expand Up @@ -45,12 +43,13 @@ const ModelVersionRegisteredDeploymentsView: React.FC<

<InferenceServiceTable
isGlobal
getColumns={(projects) => getVersionDetailsInferenceServiceColumns(projects)}
getColumns={getVersionDetailsInferenceServiceColumns}
inferenceServices={inferenceServices.data}
servingRuntimes={servingRuntimes.data}
isLoading={isLoading}
/>
</Stack>
);
};

export default ModelVersionRegisteredDeploymentsView;
1 change: 1 addition & 0 deletions frontend/src/pages/modelServing/screens/global/data.ts
Original file line number Diff line number Diff line change
Expand Up @@ -103,6 +103,7 @@ export const getVersionDetailsInferenceServiceColumns = (
COL_ENDPOINT,
COL_API_PROTOCOL,
COL_STATUS,
COL_KEBAB,
];

export const getProjectInferenceServiceColumns = (): SortableData<InferenceServiceKind>[] => [
Expand Down
6 changes: 0 additions & 6 deletions manifests/core-bases/base/cluster-role.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -127,13 +127,7 @@ rules:
- apiGroups:
- ''
verbs:
- get
- list
- watch
- create
- update
- patch
- delete
resources:
- namespaces
- apiGroups:
Expand Down

0 comments on commit 46225dc

Please sign in to comment.