Skip to content

Commit b8fa7f7

Browse files
Leo6Leoclaudelogonoff
authored
CONSOLE-4806: Remove static extensions from knative-plugin (#15641)
* feat: Refactor Knative plugin: replace plugin.tsx with plugin.ts, update console-extensions.json to include new topology data model factories for serving, eventing, and kamelets, and remove deprecated topology-plugin.ts file * CONSOLE-4806: Support CodeRef for topology resources property Enable dynamic plugin extensions to use CodeRef for the resources property in topology data model factories. This allows plugins to fetch resources dynamically at runtime (e.g., discovering CRDs). Changes: - Update TopologyDataModelFactory type to accept CodeRef<() => Promise<WatchK8sResourcesGeneric>> - Add Promise resolution in DataModelExtension for CodeRef resources - Update get-knative-resources functions to return Promises with resource definitions - Maintain backward compatibility with static resource definitions The implementation follows the same pattern as other CodeRef properties (getDataModel, isResourceDepicted) by resolving the Promise eagerly during extension initialization and caching the result. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Apply suggestions from code review Co-authored-by: logonoff <[email protected]> * fix: fix the review comments from @logonoff * OCPBUGS-4806: Convert knative topology resources from CodeRef to static definitions Replaces dynamic CodeRef-based resource definitions with inline static definitions for knative-serving and kamelets topology model factories, removing the need for runtime resolution. Adds compatibility layer for converting dynamic model factories to internal plugin format. 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * OCPBUGS-4806: Remove static topology data model factory extensions Refactor topology package to remove static extension support and rely exclusively on dynamic plugin SDK for topology data model factories. Key changes: - Remove TopologyDataModelFactory extension interface and related types - Simplify ApplicationDropdown to use only base watched resources - Remove legacy function format support in useTopologyDataModelFactory - Eliminate conversion layer between dynamic and static factories - Update DataModelProvider to handle only dynamic extensions 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * Apply suggestions from code review Co-authored-by: logonoff <[email protected]> * Update frontend/packages/knative-plugin/src/utils/get-knative-resources.ts Co-authored-by: logonoff <[email protected]> * OCPBUGS-4806: Refactor topology data model to use useResolvedExtensions Replace custom useResolvedResources hook with built-in useResolvedExtensions to simplify the topology data model extension handling. This removes the need for manual CodeRef resolution and improves error messaging with plugin context. Changes: - Use useResolvedExtensions instead of useExtensions in DataModelProvider - Remove useTopologyDataModelFactory hook (no longer needed) - Simplify DataModelExtension to work with pre-resolved extensions - Add plugin ID to error messages for better debugging - Use referenceForExtensionModel for better CRD reference resolution 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-Authored-By: Claude <[email protected]> * fix: Refactor DataModelExtension to streamline resource conversion * Implement async resource resolution for dynamic model factories in DataModelProvider --------- Co-authored-by: Claude <[email protected]> Co-authored-by: logonoff <[email protected]>
1 parent 80b3db5 commit b8fa7f7

File tree

13 files changed

+317
-326
lines changed

13 files changed

+317
-326
lines changed

frontend/packages/console-dynamic-plugin-sdk/docs/console-extensions.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1158,7 +1158,7 @@ Topology Data Model Factory Extension
11581158
| ---- | ---------- | -------- | ----------- |
11591159
| `id` | `string` | no | Unique ID for the factory. |
11601160
| `priority` | `number` | no | Priority for the factory |
1161-
| `resources` | `WatchK8sResourcesGeneric` | yes | Resources to be fetched from useK8sWatchResources hook. |
1161+
| `resources` | `WatchK8sResourcesGeneric \| CodeRef<() => Promise<WatchK8sResourcesGeneric>>` | yes | Resources to be fetched from useK8sWatchResources hook. |
11621162
| `workloadKeys` | `string[]` | yes | Keys in resources containing workloads. |
11631163
| `getDataModel` | `CodeRef<TopologyDataModelGetter>` | yes | Getter for the data model factory |
11641164
| `isResourceDepicted` | `CodeRef<TopologyDataModelDepicted>` | yes | Getter for function to determine if a resource is depicted by this model factory |

frontend/packages/console-dynamic-plugin-sdk/src/extensions/topology.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,7 +41,7 @@ export type TopologyDataModelFactory = ExtensionDeclaration<
4141
/** Priority for the factory */
4242
priority: number;
4343
/** Resources to be fetched from useK8sWatchResources hook. */
44-
resources?: WatchK8sResourcesGeneric;
44+
resources?: WatchK8sResourcesGeneric | CodeRef<() => Promise<WatchK8sResourcesGeneric>>;
4545
/** Keys in resources containing workloads. */
4646
workloadKeys?: string[];
4747
/** Getter for the data model factory */

frontend/packages/knative-plugin/console-extensions.json

Lines changed: 100 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2008,5 +2008,105 @@
20082008
"flags": {
20092009
"required": ["KNATIVE_EVENTING"]
20102010
}
2011+
},
2012+
{
2013+
"type": "console.topology/data/factory",
2014+
"properties": {
2015+
"id": "knative-serving-topology-model-factory",
2016+
"priority": 100,
2017+
"resources": {
2018+
"revisions": {
2019+
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Revision" },
2020+
"opts": { "isList": true, "optional": true, "namespaced": true }
2021+
},
2022+
"configurations": {
2023+
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Configuration" },
2024+
"opts": { "isList": true, "optional": true, "namespaced": true }
2025+
},
2026+
"ksroutes": {
2027+
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Route" },
2028+
"opts": { "isList": true, "optional": true, "namespaced": true }
2029+
},
2030+
"ksservices": {
2031+
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Service" },
2032+
"opts": { "isList": true, "optional": true, "namespaced": true }
2033+
},
2034+
"domainmappings": {
2035+
"model": { "group": "serving.knative.dev", "version": "v1beta1", "kind": "DomainMapping" },
2036+
"opts": { "isList": true, "optional": true, "namespaced": true }
2037+
}
2038+
},
2039+
"workloadKeys": ["ksservices"],
2040+
"getDataModel": {
2041+
"$codeRef": "dataTransformer.getKnativeServingTopologyDataModel"
2042+
},
2043+
"isResourceDepicted": {
2044+
"$codeRef": "isKnativeResource.isKnativeResource"
2045+
}
2046+
},
2047+
"flags": {
2048+
"required": [
2049+
"KNATIVE_SERVING_CONFIGURATION",
2050+
"KNATIVE_SERVING",
2051+
"KNATIVE_SERVING_REVISION",
2052+
"KNATIVE_SERVING_ROUTE",
2053+
"KNATIVE_SERVING_SERVICE"
2054+
]
2055+
}
2056+
},
2057+
{
2058+
"type": "console.topology/data/factory",
2059+
"properties": {
2060+
"id": "knative-eventing-topology-model-factory",
2061+
"priority": 100,
2062+
"resources": {
2063+
"$codeRef": "getKnativeResources.getKnativeEventingResources"
2064+
},
2065+
"workloadKeys": ["eventingsubscription"],
2066+
"getDataModel": {
2067+
"$codeRef": "dataTransformer.getKnativeEventingTopologyDataModel"
2068+
},
2069+
"isResourceDepicted": {
2070+
"$codeRef": "isKnativeResource.isKnativeResource"
2071+
}
2072+
},
2073+
"flags": {
2074+
"required": ["KNATIVE_EVENTING", "FLAG_KNATIVE_EVENTING_ENABLED"]
2075+
}
2076+
},
2077+
{
2078+
"type": "console.topology/data/factory",
2079+
"properties": {
2080+
"id": "knative-kamelets-topology-model-factory",
2081+
"priority": 100,
2082+
"resources": {
2083+
"integrations": {
2084+
"model": { "group": "camel.apache.org", "version": "v1", "kind": "Integration" },
2085+
"opts": { "isList": true, "optional": true, "namespaced": true }
2086+
},
2087+
"kameletbindings": {
2088+
"model": { "group": "camel.apache.org", "version": "v1alpha1", "kind": "KameletBinding" },
2089+
"opts": { "isList": true, "optional": true, "namespaced": true }
2090+
},
2091+
"domainmappings": {
2092+
"model": { "group": "serving.knative.dev", "version": "v1beta1", "kind": "DomainMapping" },
2093+
"opts": { "isList": true, "optional": true, "namespaced": true }
2094+
},
2095+
"kamelets": {
2096+
"model": { "group": "camel.apache.org", "version": "v1alpha1", "kind": "Kamelet" },
2097+
"opts": { "isList": true, "optional": true, "namespaced": true }
2098+
}
2099+
},
2100+
"workloadKeys": ["kameletbindings"],
2101+
"getDataModel": {
2102+
"$codeRef": "dataTransformer.getKnativeKameletsTopologyDataModel"
2103+
},
2104+
"isResourceDepicted": {
2105+
"$codeRef": "isKnativeResource.isKnativeResource"
2106+
}
2107+
},
2108+
"flags": {
2109+
"required": ["KNATIVE_EVENTING", "FLAG_CAMEL_KAMELETS"]
2110+
}
20112111
}
20122112
]

frontend/packages/knative-plugin/package.json

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@
1414
"@console/topology": "0.0.0-fixed"
1515
},
1616
"consolePlugin": {
17-
"entry": "src/plugin.tsx",
17+
"entry": "src/plugin.ts",
1818
"exposedModules": {
1919
"actions": "src/actions/providers.ts",
2020
"icons": "src/utils/icons.tsx",
@@ -65,7 +65,9 @@
6565
"fetchDynamicEventSourcesUtils": "src/utils/fetch-dynamic-eventsources-utils.ts",
6666
"EventSourceBreadcrumbs": "src/providers/useEventSourceDetailPageBreadcrumbs.ts",
6767
"ChannelBreadcrumbs": "src/providers/useChannelDetailPageBreadcrumbs.ts",
68-
"BrokerBreadcrumbs": "src/providers/useBrokerDetailPageBreadcrumbs.ts"
68+
"BrokerBreadcrumbs": "src/providers/useBrokerDetailPageBreadcrumbs.ts",
69+
"getKnativeResources": "src/utils/get-knative-resources.ts",
70+
"isKnativeResource": "src/topology/isKnativeResource.ts"
6971
}
7072
}
7173
}
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
// See console-extensions.json instead
2+
export default [];

frontend/packages/knative-plugin/src/plugin.tsx

Lines changed: 0 additions & 3 deletions
This file was deleted.

frontend/packages/knative-plugin/src/topology/topology-plugin.ts

Lines changed: 0 additions & 91 deletions
This file was deleted.

frontend/packages/knative-plugin/src/utils/get-knative-resources.ts

Lines changed: 38 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
import * as _ from 'lodash';
2-
import { WatchK8sResources } from '@console/dynamic-plugin-sdk';
2+
import { WatchK8sResources, WatchK8sResourcesGeneric } from '@console/dynamic-plugin-sdk';
33
import { FirehoseResource } from '@console/internal/components/utils';
44
import { K8sResourceKind, PodKind, referenceForModel } from '@console/internal/module/k8s';
55
import { GLOBAL_OPERATOR_NS, KNATIVE_SERVING_LABEL } from '../const';
@@ -21,10 +21,7 @@ import {
2121
KafkaConnectionModel,
2222
} from '../models';
2323
import { Traffic } from '../types';
24-
import {
25-
getDynamicEventSourcesWatchers,
26-
getDynamicEventingChannelWatchers,
27-
} from './fetch-dynamic-eventsources-utils';
24+
import { fetchEventSourcesCrd, fetchChannelsCrd } from './fetch-dynamic-eventsources-utils';
2825

2926
export type KnativeItem = {
3027
revisions?: K8sResourceKind[];
@@ -438,31 +435,43 @@ export const getSinkableResources = (namespace: string): FirehoseResource[] => {
438435
: [];
439436
};
440437

441-
export const getKnativeServingResources = (namespace: string) => {
442-
return {
443-
...knativeServingResourcesRevisionWatchers(namespace),
444-
...knativeServingResourcesConfigurationsWatchers(namespace),
445-
...knativeServingResourcesRoutesWatchers(namespace),
446-
...knativeServingResourcesServicesWatchers(namespace),
447-
...knativeCamelDomainMappingResourceWatchers(namespace),
448-
};
449-
};
450-
451-
export const getKnativeEventingResources = (namespace: string) => {
452-
return {
453-
...knativeEventingResourcesSubscriptionWatchers(namespace),
454-
...getDynamicEventSourcesWatchers(namespace),
455-
...getDynamicEventingChannelWatchers(namespace),
456-
...knativeEventingBrokerResourceWatchers(namespace),
457-
...knativeEventingTriggerResourceWatchers(namespace),
458-
};
459-
};
438+
export const getKnativeEventingResources = async (): Promise<WatchK8sResourcesGeneric> => {
439+
// Fetch dynamic event sources and channels at runtime
440+
const eventSourceModels = await fetchEventSourcesCrd();
441+
const eventingChannels = await fetchChannelsCrd();
442+
443+
const dynamicEventSources = eventSourceModels.reduce((acc, model) => {
444+
const ref = referenceForModel(model);
445+
acc[ref] = {
446+
model: { group: model.apiGroup, version: model.apiVersion, kind: model.kind },
447+
opts: { isList: true, optional: true, namespaced: true },
448+
};
449+
return acc;
450+
}, {});
451+
452+
const dynamicChannels = eventingChannels.reduce((acc, model) => {
453+
const ref = referenceForModel(model);
454+
acc[ref] = {
455+
model: { group: model.apiGroup, version: model.apiVersion, kind: model.kind },
456+
opts: { isList: true, optional: true, namespaced: true },
457+
};
458+
return acc;
459+
}, {});
460460

461-
export const getKnativeEventingKameletsResources = (namespace: string) => {
462461
return {
463-
...knativeCamelIntegrationsResourceWatchers(namespace),
464-
...knativeCamelKameletBindingResourceWatchers(namespace),
465-
...knativeCamelDomainMappingResourceWatchers(namespace),
466-
...knativeCamelKameletResourceWatchers(namespace),
462+
eventingsubscription: {
463+
model: { group: 'messaging.knative.dev', version: 'v1', kind: 'Subscription' },
464+
opts: { isList: true, optional: true, namespaced: true },
465+
},
466+
brokers: {
467+
model: { group: 'eventing.knative.dev', version: 'v1', kind: 'Broker' },
468+
opts: { isList: true, optional: true, namespaced: true },
469+
},
470+
triggers: {
471+
model: { group: 'eventing.knative.dev', version: 'v1', kind: 'Trigger' },
472+
opts: { isList: true, optional: true, namespaced: true },
473+
},
474+
...dynamicEventSources,
475+
...dynamicChannels,
467476
};
468477
};

frontend/packages/topology/src/components/dropdowns/ApplicationDropdown.tsx

Lines changed: 4 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,49 +1,26 @@
11
import * as React from 'react';
22
import { useTranslation } from 'react-i18next';
3-
import {
4-
isTopologyDataModelFactory as isDynamicTopologyDataModelFactory,
5-
TopologyDataModelFactory as DynamicTopologyDataModelFactory,
6-
} from '@console/dynamic-plugin-sdk';
73
import { Firehose } from '@console/internal/components/utils';
8-
import { useExtensions } from '@console/plugin-sdk/src/api/useExtensions';
94
import { ResourceDropdown } from '@console/shared';
105
import { ResourceDropdownProps } from '../../../../console-shared/src/components/dropdown/ResourceDropdown';
11-
import { getNamespacedDynamicModelFactories } from '../../data-transforms/DataModelProvider';
126
import { getBaseWatchedResources } from '../../data-transforms/transform-utils';
13-
import { isTopologyDataModelFactory, TopologyDataModelFactory } from '../../extensions';
147

158
type ApplicationDropdownProps = Omit<ResourceDropdownProps, 'dataSelector' | 'placeholder'> & {
169
namespace?: string;
1710
};
1811

1912
const ApplicationDropdown: React.FC<ApplicationDropdownProps> = ({ namespace, ...props }) => {
2013
const { t } = useTranslation();
21-
const modelFactories = useExtensions<TopologyDataModelFactory>(isTopologyDataModelFactory);
22-
const dynamicModelFactories = useExtensions<DynamicTopologyDataModelFactory>(
23-
isDynamicTopologyDataModelFactory,
24-
);
25-
26-
const namespacedDynamicFactories = React.useMemo(
27-
() => getNamespacedDynamicModelFactories(dynamicModelFactories),
28-
[dynamicModelFactories],
29-
);
3014

3115
const resources = React.useMemo(() => {
32-
let watchedBaseResources = getBaseWatchedResources(namespace);
33-
[...modelFactories, ...namespacedDynamicFactories].forEach((modelFactory) => {
34-
const factoryResources = modelFactory.properties.resources?.(namespace);
35-
if (factoryResources) {
36-
watchedBaseResources = {
37-
...factoryResources,
38-
...watchedBaseResources,
39-
};
40-
}
41-
});
16+
// Use only base watched resources since dynamic factories are handled separately
17+
// and ApplicationDropdown primarily needs the base resources for application labels
18+
const watchedBaseResources = getBaseWatchedResources(namespace);
4219
return Object.keys(watchedBaseResources).map((key) => ({
4320
...watchedBaseResources[key],
4421
prop: key,
4522
}));
46-
}, [namespacedDynamicFactories, modelFactories, namespace]);
23+
}, [namespace]);
4724

4825
return (
4926
<Firehose resources={resources}>

0 commit comments

Comments
 (0)