Skip to content
Open
Show file tree
Hide file tree
Changes from 9 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -1158,7 +1158,7 @@ Topology Data Model Factory Extension
| ---- | ---------- | -------- | ----------- |
| `id` | `string` | no | Unique ID for the factory. |
| `priority` | `number` | no | Priority for the factory |
| `resources` | `WatchK8sResourcesGeneric` | yes | Resources to be fetched from useK8sWatchResources hook. |
| `resources` | `WatchK8sResourcesGeneric \| CodeRef<() => Promise<WatchK8sResourcesGeneric>>` | yes | Resources to be fetched from useK8sWatchResources hook. |
| `workloadKeys` | `string[]` | yes | Keys in resources containing workloads. |
| `getDataModel` | `CodeRef<TopologyDataModelGetter>` | yes | Getter for the data model factory |
| `isResourceDepicted` | `CodeRef<TopologyDataModelDepicted>` | yes | Getter for function to determine if a resource is depicted by this model factory |
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -41,7 +41,7 @@ export type TopologyDataModelFactory = ExtensionDeclaration<
/** Priority for the factory */
priority: number;
/** Resources to be fetched from useK8sWatchResources hook. */
resources?: WatchK8sResourcesGeneric;
resources?: WatchK8sResourcesGeneric | CodeRef<() => Promise<WatchK8sResourcesGeneric>>;
/** Keys in resources containing workloads. */
workloadKeys?: string[];
/** Getter for the data model factory */
Expand Down
100 changes: 100 additions & 0 deletions frontend/packages/knative-plugin/console-extensions.json
Original file line number Diff line number Diff line change
Expand Up @@ -2008,5 +2008,105 @@
"flags": {
"required": ["KNATIVE_EVENTING"]
}
},
{
"type": "console.topology/data/factory",
"properties": {
"id": "knative-serving-topology-model-factory",
"priority": 100,
"resources": {
"revisions": {
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Revision" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"configurations": {
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Configuration" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"ksroutes": {
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Route" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"ksservices": {
"model": { "group": "serving.knative.dev", "version": "v1", "kind": "Service" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"domainmappings": {
"model": { "group": "serving.knative.dev", "version": "v1beta1", "kind": "DomainMapping" },
"opts": { "isList": true, "optional": true, "namespaced": true }
}
},
"workloadKeys": ["ksservices"],
"getDataModel": {
"$codeRef": "dataTransformer.getKnativeServingTopologyDataModel"
},
"isResourceDepicted": {
"$codeRef": "isKnativeResource.isKnativeResource"
}
},
"flags": {
"required": [
"KNATIVE_SERVING_CONFIGURATION",
"KNATIVE_SERVING",
"KNATIVE_SERVING_REVISION",
"KNATIVE_SERVING_ROUTE",
"KNATIVE_SERVING_SERVICE"
]
}
},
{
"type": "console.topology/data/factory",
"properties": {
"id": "knative-eventing-topology-model-factory",
"priority": 100,
"resources": {
"$codeRef": "getKnativeResources.getKnativeEventingResources"
},
Comment on lines +2062 to +2064
Copy link
Member

@logonoff logonoff Oct 24, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

resources expects a WatchK8sResourcesGeneric and not a codeRef.

The challenge of this ticket is that getKnativeEventingResources is dynamic, so we need to modify console.topology/data/factory to also allow codeRefs.

We discussed in the dynamic plugin sync that this coderef should be typed with

resources: WatchK8sResourcesGeneric | CodeRef<() => Promise<WatchK8sResourcesGeneric>>.

The promise is needed as plugins may want to do some fetching in order to determine which k8s resources should be wtached.

This will require changes to any code which consumes the TopologyDataModelFactory extension. I suggest possibly writing a useTopologyDataModelFactory hook in the topology package to allow resolve the codeRefs

This API change is already approved by @spadgett so you will get plugin-api-approved with this change

"workloadKeys": ["eventingsubscription"],
"getDataModel": {
"$codeRef": "dataTransformer.getKnativeEventingTopologyDataModel"
},
"isResourceDepicted": {
"$codeRef": "isKnativeResource.isKnativeResource"
}
},
"flags": {
"required": ["KNATIVE_EVENTING", "FLAG_KNATIVE_EVENTING_ENABLED"]
}
},
{
"type": "console.topology/data/factory",
"properties": {
"id": "knative-kamelets-topology-model-factory",
"priority": 100,
"resources": {
"integrations": {
"model": { "group": "camel.apache.org", "version": "v1", "kind": "Integration" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"kameletbindings": {
"model": { "group": "camel.apache.org", "version": "v1alpha1", "kind": "KameletBinding" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"domainmappings": {
"model": { "group": "serving.knative.dev", "version": "v1beta1", "kind": "DomainMapping" },
"opts": { "isList": true, "optional": true, "namespaced": true }
},
"kamelets": {
"model": { "group": "camel.apache.org", "version": "v1alpha1", "kind": "Kamelet" },
"opts": { "isList": true, "optional": true, "namespaced": true }
}
},
"workloadKeys": ["kameletbindings"],
"getDataModel": {
"$codeRef": "dataTransformer.getKnativeKameletsTopologyDataModel"
},
"isResourceDepicted": {
"$codeRef": "isKnativeResource.isKnativeResource"
}
},
"flags": {
"required": ["KNATIVE_EVENTING", "FLAG_CAMEL_KAMELETS"]
}
}
]
6 changes: 4 additions & 2 deletions frontend/packages/knative-plugin/package.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@
"@console/topology": "0.0.0-fixed"
},
"consolePlugin": {
"entry": "src/plugin.tsx",
"entry": "src/plugin.ts",
"exposedModules": {
"actions": "src/actions/providers.ts",
"icons": "src/utils/icons.tsx",
Expand Down Expand Up @@ -65,7 +65,9 @@
"fetchDynamicEventSourcesUtils": "src/utils/fetch-dynamic-eventsources-utils.ts",
"EventSourceBreadcrumbs": "src/providers/useEventSourceDetailPageBreadcrumbs.ts",
"ChannelBreadcrumbs": "src/providers/useChannelDetailPageBreadcrumbs.ts",
"BrokerBreadcrumbs": "src/providers/useBrokerDetailPageBreadcrumbs.ts"
"BrokerBreadcrumbs": "src/providers/useBrokerDetailPageBreadcrumbs.ts",
"getKnativeResources": "src/utils/get-knative-resources.ts",
"isKnativeResource": "src/topology/isKnativeResource.ts"
}
}
}
2 changes: 2 additions & 0 deletions frontend/packages/knative-plugin/src/plugin.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
// See console-extensions.json instead
export default [];
3 changes: 0 additions & 3 deletions frontend/packages/knative-plugin/src/plugin.tsx

This file was deleted.

91 changes: 0 additions & 91 deletions frontend/packages/knative-plugin/src/topology/topology-plugin.ts

This file was deleted.

67 changes: 38 additions & 29 deletions frontend/packages/knative-plugin/src/utils/get-knative-resources.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
import * as _ from 'lodash';
import { WatchK8sResources } from '@console/dynamic-plugin-sdk';
import { WatchK8sResources, WatchK8sResourcesGeneric } from '@console/dynamic-plugin-sdk';
import { FirehoseResource } from '@console/internal/components/utils';
import { K8sResourceKind, PodKind, referenceForModel } from '@console/internal/module/k8s';
import { GLOBAL_OPERATOR_NS, KNATIVE_SERVING_LABEL } from '../const';
Expand All @@ -21,10 +21,7 @@ import {
KafkaConnectionModel,
} from '../models';
import { Traffic } from '../types';
import {
getDynamicEventSourcesWatchers,
getDynamicEventingChannelWatchers,
} from './fetch-dynamic-eventsources-utils';
import { fetchEventSourcesCrd, fetchChannelsCrd } from './fetch-dynamic-eventsources-utils';

export type KnativeItem = {
revisions?: K8sResourceKind[];
Expand Down Expand Up @@ -438,31 +435,43 @@ export const getSinkableResources = (namespace: string): FirehoseResource[] => {
: [];
};

export const getKnativeServingResources = (namespace: string) => {
return {
...knativeServingResourcesRevisionWatchers(namespace),
...knativeServingResourcesConfigurationsWatchers(namespace),
...knativeServingResourcesRoutesWatchers(namespace),
...knativeServingResourcesServicesWatchers(namespace),
...knativeCamelDomainMappingResourceWatchers(namespace),
};
};

export const getKnativeEventingResources = (namespace: string) => {
return {
...knativeEventingResourcesSubscriptionWatchers(namespace),
...getDynamicEventSourcesWatchers(namespace),
...getDynamicEventingChannelWatchers(namespace),
...knativeEventingBrokerResourceWatchers(namespace),
...knativeEventingTriggerResourceWatchers(namespace),
};
};
export const getKnativeEventingResources = async () => {
// Fetch dynamic event sources and channels at runtime
const eventSourceModels = await fetchEventSourcesCrd();
const eventingChannels = await fetchChannelsCrd();

const dynamicEventSources = eventSourceModels.reduce((acc, model) => {
const ref = referenceForModel(model);
acc[ref] = {
model: { group: model.apiGroup, version: model.apiVersion, kind: model.kind },
opts: { isList: true, optional: true, namespaced: true },
};
return acc;
}, {} as WatchK8sResourcesGeneric);

const dynamicChannels = eventingChannels.reduce((acc, model) => {
const ref = referenceForModel(model);
acc[ref] = {
model: { group: model.apiGroup, version: model.apiVersion, kind: model.kind },
opts: { isList: true, optional: true, namespaced: true },
};
return acc;
}, {} as WatchK8sResourcesGeneric);

export const getKnativeEventingKameletsResources = (namespace: string) => {
return {
...knativeCamelIntegrationsResourceWatchers(namespace),
...knativeCamelKameletBindingResourceWatchers(namespace),
...knativeCamelDomainMappingResourceWatchers(namespace),
...knativeCamelKameletResourceWatchers(namespace),
eventingsubscription: {
model: { group: 'messaging.knative.dev', version: 'v1', kind: 'Subscription' },
opts: { isList: true, optional: true, namespaced: true },
},
brokers: {
model: { group: 'eventing.knative.dev', version: 'v1', kind: 'Broker' },
opts: { isList: true, optional: true, namespaced: true },
},
triggers: {
model: { group: 'eventing.knative.dev', version: 'v1', kind: 'Trigger' },
opts: { isList: true, optional: true, namespaced: true },
},
...dynamicEventSources,
...dynamicChannels,
};
};
Original file line number Diff line number Diff line change
@@ -1,49 +1,26 @@
import * as React from 'react';
import { useTranslation } from 'react-i18next';
import {
isTopologyDataModelFactory as isDynamicTopologyDataModelFactory,
TopologyDataModelFactory as DynamicTopologyDataModelFactory,
} from '@console/dynamic-plugin-sdk';
import { Firehose } from '@console/internal/components/utils';
import { useExtensions } from '@console/plugin-sdk/src';
import { ResourceDropdown } from '@console/shared';
import { ResourceDropdownProps } from '../../../../console-shared/src/components/dropdown/ResourceDropdown';
import { getNamespacedDynamicModelFactories } from '../../data-transforms/DataModelProvider';
import { getBaseWatchedResources } from '../../data-transforms/transform-utils';
import { isTopologyDataModelFactory, TopologyDataModelFactory } from '../../extensions';

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

const ApplicationDropdown: React.FC<ApplicationDropdownProps> = ({ namespace, ...props }) => {
const { t } = useTranslation();
const modelFactories = useExtensions<TopologyDataModelFactory>(isTopologyDataModelFactory);
const dynamicModelFactories = useExtensions<DynamicTopologyDataModelFactory>(
isDynamicTopologyDataModelFactory,
);

const namespacedDynamicFactories = React.useMemo(
() => getNamespacedDynamicModelFactories(dynamicModelFactories),
[dynamicModelFactories],
);

const resources = React.useMemo(() => {
let watchedBaseResources = getBaseWatchedResources(namespace);
[...modelFactories, ...namespacedDynamicFactories].forEach((modelFactory) => {
const factoryResources = modelFactory.properties.resources?.(namespace);
if (factoryResources) {
watchedBaseResources = {
...factoryResources,
...watchedBaseResources,
};
}
});
// Use only base watched resources since dynamic factories are handled separately
// and ApplicationDropdown primarily needs the base resources for application labels
const watchedBaseResources = getBaseWatchedResources(namespace);
return Object.keys(watchedBaseResources).map((key) => ({
...watchedBaseResources[key],
prop: key,
}));
}, [namespacedDynamicFactories, modelFactories, namespace]);
}, [namespace]);

return (
<Firehose resources={resources}>
Expand Down
Loading