-
Notifications
You must be signed in to change notification settings - Fork 666
[WIP] CONSOLE-4806: Remove static extensions from knative-plugin #15641
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from 2 commits
8f5dc89
abbb2b4
18fba13
0dbd7a8
d16dafe
395122d
d28fbd5
dcf0f44
9a51df4
5b83c8a
96cb737
e733bb8
d204174
6ec040b
c69ab66
726f09e
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -1,29 +1,98 @@ | ||
| import * as React from 'react'; | ||
| import { useContext, useRef, useEffect, useMemo } from 'react'; | ||
| import { | ||
| WatchK8sResources, | ||
| WatchK8sResourcesGeneric, | ||
| WatchK8sResource, | ||
| } from '@console/dynamic-plugin-sdk'; | ||
| import { referenceForModel, modelForGroupKind } from '@console/internal/module/k8s'; | ||
| import { useDeepCompareMemoize } from '@console/shared'; | ||
| import { TopologyDataModelFactory } from '../extensions/topology'; | ||
| import { useResolvedResources } from '../hooks/useTopologyDataModelFactory'; | ||
| import { ModelContext, ExtensibleModel, ModelExtensionContext } from './ModelContext'; | ||
|
|
||
| interface DataModelExtensionProps { | ||
| dataModelFactory: TopologyDataModelFactory['properties']; | ||
| } | ||
|
|
||
| /** | ||
| * Converts a single resource from WatchK8sResourcesGeneric format to WatchK8sResource format. | ||
| * This handles the namespace injection and model reference resolution. | ||
| */ | ||
| const convertGenericResource = ( | ||
| namespace: string, | ||
| model?: { group?: string; version?: string; kind: string }, | ||
| opts?: Partial<WatchK8sResource>, | ||
| ): WatchK8sResource | null => { | ||
| if (!model) { | ||
| return { namespace, ...opts }; | ||
| } | ||
|
|
||
| // Try to find the internal model | ||
| const internalModel = modelForGroupKind(model.group, model.kind); | ||
| if (!internalModel) { | ||
| // CRD not found - log warning and skip | ||
| // eslint-disable-next-line no-console | ||
| console.warn( | ||
| `Could not find model (CRD) for group "${model.group}" and kind "${model.kind}". Resource will be skipped.`, | ||
| ); | ||
| return null; | ||
| } | ||
|
||
|
|
||
| const reference = referenceForModel(internalModel); | ||
| return { namespace, kind: reference, ...opts }; | ||
| }; | ||
|
|
||
| const DataModelExtension: React.FC<DataModelExtensionProps> = ({ dataModelFactory }) => { | ||
| const dataModelContext = React.useContext<ExtensibleModel>(ModelContext); | ||
| const { id, priority, resources } = dataModelFactory; | ||
| const dataModelContext = useContext<ExtensibleModel>(ModelContext); | ||
| const { id, priority, resources: rawResources } = dataModelFactory; | ||
| const workloadKeys = useDeepCompareMemoize(dataModelFactory.workloadKeys); | ||
| const extensionContext = React.useRef<ModelExtensionContext>({ | ||
| const { resolved: resolvedResources, isGeneric } = useResolvedResources( | ||
| rawResources, | ||
| dataModelContext.namespace, | ||
| ); | ||
|
|
||
| // Convert WatchK8sResourcesGeneric to WatchK8sResources if needed | ||
| const finalResources = useMemo<WatchK8sResources<any> | undefined>(() => { | ||
| if (!resolvedResources) { | ||
| return undefined; | ||
| } | ||
|
|
||
| if (isGeneric) { | ||
| // Resources are in WatchK8sResourcesGeneric format, need to be converted | ||
| const genericResources = resolvedResources as WatchK8sResourcesGeneric; | ||
| const converted: WatchK8sResources<any> = {}; | ||
|
|
||
| Object.entries(genericResources).forEach(([key, resource]) => { | ||
| const flattenedResource = convertGenericResource( | ||
| dataModelContext.namespace, | ||
| resource?.model, | ||
| resource?.opts, | ||
| ); | ||
| if (flattenedResource) { | ||
| converted[key] = flattenedResource; | ||
| } | ||
| }); | ||
|
|
||
| return converted; | ||
| } | ||
|
|
||
| // Already in the correct format | ||
| return resolvedResources as WatchK8sResources<any>; | ||
| }, [resolvedResources, isGeneric, dataModelContext.namespace]); | ||
|
|
||
| const extensionContext = useRef<ModelExtensionContext>({ | ||
| priority, | ||
| workloadKeys, | ||
| resources, | ||
| resources: undefined, | ||
| }); | ||
|
|
||
| React.useEffect(() => { | ||
| useEffect(() => { | ||
| const storedContext = dataModelContext.getExtension(id); | ||
| if (!storedContext) { | ||
| extensionContext.current = { | ||
| priority, | ||
| workloadKeys, | ||
| resources, | ||
| resources: finalResources, | ||
| }; | ||
| dataModelContext.updateExtension(id, extensionContext.current); | ||
|
|
||
|
|
@@ -73,7 +142,7 @@ const DataModelExtension: React.FC<DataModelExtensionProps> = ({ dataModelFactor | |
| dataModelContext.updateExtension(id, extensionContext.current); | ||
| } | ||
| } | ||
| }, [dataModelContext, dataModelFactory, id, priority, resources, workloadKeys]); | ||
| }, [dataModelContext, dataModelFactory, id, priority, finalResources, workloadKeys]); | ||
|
|
||
| return null; | ||
| }; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -10,7 +10,7 @@ import { | |
| referenceForExtensionModel, | ||
| referenceForModel, | ||
| } from '@console/internal/module/k8s'; | ||
| import { LoadedExtension, useExtensions } from '@console/plugin-sdk/src'; | ||
| import { LoadedExtension, useExtensions } from '@console/plugin-sdk'; | ||
| import { isTopologyDataModelFactory, TopologyDataModelFactory } from '../extensions/topology'; | ||
| import DataModelExtension from './DataModelExtension'; | ||
| import { ModelContext, ExtensibleModel } from './ModelContext'; | ||
|
|
@@ -58,12 +58,27 @@ export const getNamespacedDynamicModelFactories = ( | |
| extensions: LoadedExtension<DynamicTopologyDataModelFactory>[], | ||
| ) => | ||
| extensions.map((extension) => { | ||
| const { resources } = extension.properties; | ||
|
|
||
| // If resources is a CodeRef (function), keep it as-is for resolution in DataModelExtension | ||
| if (typeof resources === 'function') { | ||
| return { | ||
| ...extension, | ||
| properties: { | ||
| ...extension.properties, | ||
| // Keep the original CodeRef - it will be resolved by useResolvedResources hook | ||
| resources, | ||
| }, | ||
| }; | ||
|
||
| } | ||
|
|
||
| // Static WatchK8sResourcesGeneric - convert to function format for legacy compatibility | ||
| return { | ||
| ...extension, | ||
| properties: { | ||
| ...extension.properties, | ||
| resources: (namespace: string) => | ||
| Object.entries(extension.properties.resources || {}).reduce((acc, [key, resource]) => { | ||
| Object.entries(resources || {}).reduce((acc, [key, resource]: [string, any]) => { | ||
| const flattenedResource = flattenResource( | ||
| namespace, | ||
| extension, | ||
|
|
||
Uh oh!
There was an error while loading. Please reload this page.