From 34d21fd25a9986a16718486819a2fd717c9d47af Mon Sep 17 00:00:00 2001 From: platex-rehor-bot Date: Tue, 25 Aug 2026 13:50:11 +0000 Subject: [PATCH 1/2] fix(topology): declare nullable return types for GetTopologyResourceObject and GetResource OCPBUGS-113709 The SDK types GetTopologyResourceObject and GetResource declared non-nullable returns, but implementations can return null. This mismatch meant TypeScript wouldn't warn consumers about potential null dereferences, leading to runtime TypeError crashes. Update both SDK type signatures to include `| null` in their return types and fix ~30 consumer sites across the topology, knative, helm, and console-shared packages to handle the nullable return. Make the useBuildConfigsWatcher, useMetricStats, and usePodsForVm hooks null-safe so they can be called unconditionally (React hooks rules). Co-Authored-By: Claude Opus 4.6 --- .../src/extensions/topology-types.ts | 8 +++- .../src/hooks/useBuildConfigsWatcher.ts | 34 ++++++++------ .../helm-plugin/src/actions/providers.ts | 2 +- .../components/edges/EventingPubSubLink.tsx | 2 +- .../components/groups/KnativeService.tsx | 10 ++--- .../components/nodes/EventingPubSubNode.tsx | 2 +- .../components/nodes/RevisionNode.tsx | 4 +- .../src/topology/knative-topology-utils.ts | 9 ++++ .../listView/KnativeRevisionListViewNode.tsx | 5 ++- .../sidebar/knative-common-tab-sections.tsx | 2 + .../sidebar/knative-resource-tab-sections.tsx | 2 + .../sidebar/knative-revision-tab-sections.tsx | 1 + .../sidebar/knative-service-tab-sections.tsx | 2 + .../graph-view/components/nodes/BaseNode.tsx | 6 +-- .../components/nodes/BindableNode.tsx | 2 +- .../components/nodes/WorkloadNode.tsx | 4 +- .../components/list-view/cells/StatusCell.tsx | 2 +- .../side-bar/TopologyEdgeResourcesPanel.tsx | 4 +- .../components/workload/vpa-tab-section.tsx | 3 ++ .../topology/src/utils/topology-utils.ts | 11 +++-- .../topology/src/utils/useMetricStats.ts | 12 +++-- .../topology/src/utils/usePodsForVM.ts | 45 ++++++++++--------- .../src/utils/withEditReviewAccess.tsx | 10 ++--- 23 files changed, 111 insertions(+), 71 deletions(-) diff --git a/frontend/packages/console-dynamic-plugin-sdk/src/extensions/topology-types.ts b/frontend/packages/console-dynamic-plugin-sdk/src/extensions/topology-types.ts index 81bbe0d984f..aa880057ab4 100644 --- a/frontend/packages/console-dynamic-plugin-sdk/src/extensions/topology-types.ts +++ b/frontend/packages/console-dynamic-plugin-sdk/src/extensions/topology-types.ts @@ -260,9 +260,13 @@ export type MetricStats = { export type GetPodMetricStats = (metrics: NamespaceMetrics, podData: PodRCData) => MetricStats; -export type GetTopologyResourceObject = (topologyObject: TopologyDataObject) => K8sResourceKind; +export type GetTopologyResourceObject = ( + topologyObject: TopologyDataObject, +) => K8sResourceKind | null; -export type GetResource = (node: GraphElement) => T; +export type GetResource = ( + node: GraphElement, +) => T | null; export type GetTopologyEdgeItems = ( resource: K8sResourceKind, diff --git a/frontend/packages/console-shared/src/hooks/useBuildConfigsWatcher.ts b/frontend/packages/console-shared/src/hooks/useBuildConfigsWatcher.ts index 5c64ee7829f..60b60d134c1 100644 --- a/frontend/packages/console-shared/src/hooks/useBuildConfigsWatcher.ts +++ b/frontend/packages/console-shared/src/hooks/useBuildConfigsWatcher.ts @@ -10,27 +10,33 @@ export type BuildConfigData = { buildConfigs: BuildConfigOverviewItem[]; }; -export const useBuildConfigsWatcher = (resource: K8sResourceKind): BuildConfigData => { - const { namespace } = resource.metadata; +export const useBuildConfigsWatcher = (resource: K8sResourceKind | null): BuildConfigData => { + const namespace = resource?.metadata?.namespace; const watchedResources = useMemo( - () => ({ - buildConfigs: { - isList: true, - kind: 'BuildConfig', - namespace, - }, - builds: { - isList: true, - kind: 'Build', - namespace, - }, - }), + () => + namespace + ? { + buildConfigs: { + isList: true, + kind: 'BuildConfig', + namespace, + }, + builds: { + isList: true, + kind: 'Build', + namespace, + }, + } + : {}, [namespace], ); const resources = useK8sWatchResources(watchedResources); const result = useMemo(() => { + if (!resource) { + return { loaded: true, loadError: null, buildConfigs: null }; + } const resourceWithLoadError = Object.values(resources).find((r) => r.loadError); if (resourceWithLoadError) { return { loaded: false, loadError: resourceWithLoadError.loadError, buildConfigs: null }; diff --git a/frontend/packages/helm-plugin/src/actions/providers.ts b/frontend/packages/helm-plugin/src/actions/providers.ts index fec9b841606..a41c7ed01e4 100644 --- a/frontend/packages/helm-plugin/src/actions/providers.ts +++ b/frontend/packages/helm-plugin/src/actions/providers.ts @@ -60,7 +60,7 @@ export const useHelmActionProviderForTopology = (element: GraphElement) => { const nodeType = element.getType(); if (nodeType !== TYPE_HELM_RELEASE) return undefined; const releaseName = element.getLabel(); - if (!resource?.metadata) return null; + if (!resource?.metadata?.labels) return null; const { namespace, labels: { version }, diff --git a/frontend/packages/knative-plugin/src/topology/components/edges/EventingPubSubLink.tsx b/frontend/packages/knative-plugin/src/topology/components/edges/EventingPubSubLink.tsx index 00a9dc6f17f..dfa496593d8 100644 --- a/frontend/packages/knative-plugin/src/topology/components/edges/EventingPubSubLink.tsx +++ b/frontend/packages/knative-plugin/src/topology/components/edges/EventingPubSubLink.tsx @@ -23,7 +23,7 @@ const EventingPubSubLink: FC = ({ element, children, .. const resourceSourceObj = getTopologyResourceObject(element.getSource().getData()); const edgeObj = getTopologyResourceObject(element.getData()); const edgeHasFilter = - resourceSourceObj.kind === EventingBrokerModel.kind && + resourceSourceObj?.kind === EventingBrokerModel.kind && Object.keys(edgeObj?.spec?.filter?.attributes ?? {}).length > 0; let filterMarker: JSX.Element; diff --git a/frontend/packages/knative-plugin/src/topology/components/groups/KnativeService.tsx b/frontend/packages/knative-plugin/src/topology/components/groups/KnativeService.tsx index 4d311c026b3..bbe5bd2f930 100644 --- a/frontend/packages/knative-plugin/src/topology/components/groups/KnativeService.tsx +++ b/frontend/packages/knative-plugin/src/topology/components/groups/KnativeService.tsx @@ -38,13 +38,13 @@ const KnativeService: FC = ({ const { element } = props; const { data } = element.getData(); const resourceObj = getResource(props.element); - const resourceModel = modelFor(referenceFor(resourceObj)); + const resourceModel = resourceObj ? modelFor(referenceFor(resourceObj)) : undefined; const editAccess = useAccessReview({ - group: resourceModel.apiGroup, + group: resourceModel?.apiGroup, verb: 'patch', - resource: resourceModel.plural, - name: resourceObj.metadata.name, - namespace: resourceObj.metadata.namespace, + resource: resourceModel?.plural, + name: resourceObj?.metadata?.name, + namespace: resourceObj?.metadata?.namespace, }); const { kindAbbr, kindStr, kindColor } = getKindStringAndAbbreviation(data.kind); const badgeClassName = css('odc-resource-icon', { diff --git a/frontend/packages/knative-plugin/src/topology/components/nodes/EventingPubSubNode.tsx b/frontend/packages/knative-plugin/src/topology/components/nodes/EventingPubSubNode.tsx index 6e09cf4e136..171f14cc893 100644 --- a/frontend/packages/knative-plugin/src/topology/components/nodes/EventingPubSubNode.tsx +++ b/frontend/packages/knative-plugin/src/topology/components/nodes/EventingPubSubNode.tsx @@ -59,7 +59,7 @@ const EventingPubSubNode: FC = ({ > = (props) => { const { element } = props; const resource = getTopologyResourceObject(element.getData()); const { loaded, loadError, pods } = usePodsForRevisions( - resource.metadata.uid, - resource.metadata.namespace, + resource?.metadata?.uid, + resource?.metadata?.namespace, ); const donutStatus = useMemo(() => { if (loaded && !loadError) { diff --git a/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts b/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts index fd6df3211d6..027456ee0c3 100644 --- a/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts +++ b/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts @@ -1372,6 +1372,9 @@ export const createSinkConnection = (source: Node, target: Node): Promise }) => { const resource = getTopologyResourceObject(item.getData()); const metrics = useOverviewMetrics(); - const { loaded, pods } = usePodsForRevisions(resource.metadata.uid, resource.metadata.namespace); + const { loaded, pods } = usePodsForRevisions( + resource?.metadata?.uid, + resource?.metadata?.namespace, + ); const podData = useMemo(() => { if (!loaded) { return null; diff --git a/frontend/packages/knative-plugin/src/topology/sidebar/knative-common-tab-sections.tsx b/frontend/packages/knative-plugin/src/topology/sidebar/knative-common-tab-sections.tsx index 2679950534a..61ae1019b37 100644 --- a/frontend/packages/knative-plugin/src/topology/sidebar/knative-common-tab-sections.tsx +++ b/frontend/packages/knative-plugin/src/topology/sidebar/knative-common-tab-sections.tsx @@ -84,6 +84,7 @@ export const getKnativeSidepanelPodsAdapterSection = ( ): AdapterDataType => { if (element.getType() === NodeType.KnService || element.getType() === NodeType.Revision) { const resource = getResource(element); + if (!resource) return undefined; return { resource, provider: usePodsAdapterForKnative }; } return undefined; @@ -126,6 +127,7 @@ export const useKnativeSidepanelRoutesSection: DetailsTabSectionExtensionHook = if (element.getType() === NodeType.KnService || element.getType() === NodeType.Revision) { const knObj = element.getData().resources; const resource = getResource(element); + if (!resource) return [undefined, true, undefined]; const section = ( diff --git a/frontend/packages/knative-plugin/src/topology/sidebar/knative-resource-tab-sections.tsx b/frontend/packages/knative-plugin/src/topology/sidebar/knative-resource-tab-sections.tsx index 33a524a18e7..e48b2cd06c8 100644 --- a/frontend/packages/knative-plugin/src/topology/sidebar/knative-resource-tab-sections.tsx +++ b/frontend/packages/knative-plugin/src/topology/sidebar/knative-resource-tab-sections.tsx @@ -144,6 +144,7 @@ const usePodsForEventSource = (resource: K8sResourceKind, data) => { export const getEventSinkPodsApdapter = (element: GraphElement) => { if (element.getType() === NodeType.EventSink) { const resource = getResource(element); + if (!resource) return undefined; const { revisions, associatedDeployment } = element.getData()?.resources ?? {}; return { resource, @@ -157,6 +158,7 @@ export const getEventSinkPodsApdapter = (element: GraphElement) => { export const getEventSourcePodsApdapter = (element: GraphElement) => { if (element.getType() === NodeType.EventSource) { const resource = getResource(element); + if (!resource) return undefined; const { associatedDeployment } = element.getData()?.resources ?? {}; return { resource, diff --git a/frontend/packages/knative-plugin/src/topology/sidebar/knative-revision-tab-sections.tsx b/frontend/packages/knative-plugin/src/topology/sidebar/knative-revision-tab-sections.tsx index 67ee6c1cfce..00b9333b051 100644 --- a/frontend/packages/knative-plugin/src/topology/sidebar/knative-revision-tab-sections.tsx +++ b/frontend/packages/knative-plugin/src/topology/sidebar/knative-revision-tab-sections.tsx @@ -13,6 +13,7 @@ export const useKnativeSidepanelDeploymentSection: DetailsTabSectionExtensionHoo return [undefined, true, undefined]; } const resource = getResource(element); + if (!resource) return [undefined, true, undefined]; const section = ( diff --git a/frontend/packages/knative-plugin/src/topology/sidebar/knative-service-tab-sections.tsx b/frontend/packages/knative-plugin/src/topology/sidebar/knative-service-tab-sections.tsx index 28133b4196e..a0d284076fe 100644 --- a/frontend/packages/knative-plugin/src/topology/sidebar/knative-service-tab-sections.tsx +++ b/frontend/packages/knative-plugin/src/topology/sidebar/knative-service-tab-sections.tsx @@ -22,6 +22,7 @@ export const useKnativeSidepanelRevisionSection: DetailsTabSectionExtensionHook } const knObj = element.getData().resources; const resource = getResource(element); + if (!resource) return [undefined, true, undefined]; const section = ( @@ -35,6 +36,7 @@ export const getKnativeSidepanelBuildAdapterSection = ( ): AdapterDataType | undefined => { if (element.getType() !== NodeType.KnService) return undefined; const resource = getResource(element); + if (!resource) return undefined; return { resource, provider: useBuildConfigsWatcher }; }; diff --git a/frontend/packages/topology/src/components/graph-view/components/nodes/BaseNode.tsx b/frontend/packages/topology/src/components/graph-view/components/nodes/BaseNode.tsx index 05b71d75429..cf63ee0e22d 100644 --- a/frontend/packages/topology/src/components/graph-view/components/nodes/BaseNode.tsx +++ b/frontend/packages/topology/src/components/graph-view/components/nodes/BaseNode.tsx @@ -50,14 +50,14 @@ const BaseNodeComponent: FC = ({ const cx = width / 2; const cy = height / 2; const resourceObj = getTopologyResourceObject(element.getData()); - const resourceModel = modelFor(referenceFor(resourceObj)); + const resourceModel = resourceObj ? modelFor(referenceFor(resourceObj)) : undefined; const iconRadius = innerRadius * 0.9; const editAccess = useAccessReview({ group: resourceModel?.apiGroup, verb: createConnectorAccessVerb, resource: resourceModel?.plural, - name: resourceObj.metadata.name, - namespace: resourceObj.metadata.namespace, + name: resourceObj?.metadata?.name, + namespace: resourceObj?.metadata?.namespace, }); const [filtered] = useSearchFilter(element.getLabel(), resourceObj?.metadata?.labels); const showLabel = useShowLabel(isHovering); diff --git a/frontend/packages/topology/src/components/graph-view/components/nodes/BindableNode.tsx b/frontend/packages/topology/src/components/graph-view/components/nodes/BindableNode.tsx index d3203f30713..20d850ea422 100644 --- a/frontend/packages/topology/src/components/graph-view/components/nodes/BindableNode.tsx +++ b/frontend/packages/topology/src/components/graph-view/components/nodes/BindableNode.tsx @@ -36,7 +36,7 @@ const BindableNode: FC = ({ const iconRadius = Math.min(width, height) * 0.25; const [dndDropProps, dndDropRef] = useDndDrop(spec, { element: nodeElement, ...rest }); const resourceObj = getTopologyResourceObject(element.getData()); - const resourceModel = modelFor(referenceFor(resourceObj)); + const resourceModel = resourceObj ? modelFor(referenceFor(resourceObj)) : undefined; const iconData = element.getData()?.data?.icon || openshiftImg; const kind = resourceModel && referenceForModel(resourceModel); diff --git a/frontend/packages/topology/src/components/graph-view/components/nodes/WorkloadNode.tsx b/frontend/packages/topology/src/components/graph-view/components/nodes/WorkloadNode.tsx index f77d388de14..236649792fe 100644 --- a/frontend/packages/topology/src/components/graph-view/components/nodes/WorkloadNode.tsx +++ b/frontend/packages/topology/src/components/graph-view/components/nodes/WorkloadNode.tsx @@ -234,8 +234,8 @@ const WorkloadNode: FC = observer(({ element, ...rest }) => { const resource = getTopologyResourceObject(element.getData()); const { podData, loadError, loaded } = usePodsWatcher( resource, - resource.kind, - resource.metadata.namespace, + resource?.kind, + resource?.metadata?.namespace, ); return ( = ({ item }) => { return (
- {loaded && !loadError ? ( + {loaded && !loadError && resource ? ( ) : null}
diff --git a/frontend/packages/topology/src/components/side-bar/TopologyEdgeResourcesPanel.tsx b/frontend/packages/topology/src/components/side-bar/TopologyEdgeResourcesPanel.tsx index f6af10e3e0a..098386fe6bc 100644 --- a/frontend/packages/topology/src/components/side-bar/TopologyEdgeResourcesPanel.tsx +++ b/frontend/packages/topology/src/components/side-bar/TopologyEdgeResourcesPanel.tsx @@ -27,9 +27,7 @@ const TopologyEdgeResourcesPanel: FC = ({ edge const target = getResource(edge.getTarget()); const data = edge.getData(); const resources = [source, target]; - const { - metadata: { namespace }, - } = resources[1]; + const namespace = target?.metadata?.namespace; return (
diff --git a/frontend/packages/topology/src/components/workload/vpa-tab-section.tsx b/frontend/packages/topology/src/components/workload/vpa-tab-section.tsx index abee1328070..113d157b04a 100644 --- a/frontend/packages/topology/src/components/workload/vpa-tab-section.tsx +++ b/frontend/packages/topology/src/components/workload/vpa-tab-section.tsx @@ -52,6 +52,9 @@ export const useVpaSideBarTabSection: DetailsTabSectionExtensionHook = (element: } const resource = getResource(element); + if (!resource) { + return [undefined, true, undefined]; + } const verticalPodAutoscalers = getVerticalPodAutoscalersForResource(vpas, resource); const section = diff --git a/frontend/packages/topology/src/utils/topology-utils.ts b/frontend/packages/topology/src/utils/topology-utils.ts index 72ed6ef6429..8a6329378ac 100644 --- a/frontend/packages/topology/src/utils/topology-utils.ts +++ b/frontend/packages/topology/src/utils/topology-utils.ts @@ -125,10 +125,13 @@ export const getResource: GetResource = (node: GraphElement return (resource as T) || (getTopologyResourceObject(node?.getData()) as T); }; -export const getResourceKind = (node: Node): K8sResourceKindReference => - node instanceof OdcBaseNode - ? (node as OdcBaseNode).getResourceKind() - : referenceFor(getTopologyResourceObject(node?.getData())); +export const getResourceKind = (node: Node): K8sResourceKindReference => { + if (node instanceof OdcBaseNode) { + return (node as OdcBaseNode).getResourceKind(); + } + const resource = getTopologyResourceObject(node?.getData()); + return resource ? referenceFor(resource) : undefined; +}; export const updateTopologyResourceApplication = ( item: Node, diff --git a/frontend/packages/topology/src/utils/useMetricStats.ts b/frontend/packages/topology/src/utils/useMetricStats.ts index c17e35a12a8..919116a5c82 100644 --- a/frontend/packages/topology/src/utils/useMetricStats.ts +++ b/frontend/packages/topology/src/utils/useMetricStats.ts @@ -6,15 +6,19 @@ import { usePodsWatcher } from '@console/shared/src/hooks/usePodsWatcher'; import { getPodMetricStats } from './metricStats'; import { useOverviewMetrics } from './useOverviewMetrics'; -export const useMetricStats = (resource: K8sResourceKind): MetricStats => { +export const useMetricStats = (resource: K8sResourceKind | null): MetricStats => { const metrics = useOverviewMetrics(); - const { podData, loaded } = usePodsWatcher(resource, resource.kind, resource.metadata.namespace); + const { podData, loaded } = usePodsWatcher( + resource, + resource?.kind, + resource?.metadata?.namespace, + ); const memoryStats = useMemo(() => { - if (_.isEmpty(metrics) || !loaded) { + if (!resource || _.isEmpty(metrics) || !loaded) { return null; } return getPodMetricStats(metrics, podData); - }, [loaded, metrics, podData]); + }, [resource, loaded, metrics, podData]); return memoryStats; }; diff --git a/frontend/packages/topology/src/utils/usePodsForVM.ts b/frontend/packages/topology/src/utils/usePodsForVM.ts index 66e4b84e9f8..02485d086fe 100644 --- a/frontend/packages/topology/src/utils/usePodsForVM.ts +++ b/frontend/packages/topology/src/utils/usePodsForVM.ts @@ -12,34 +12,37 @@ import { findVMIPod } from './kubevirt-utils'; import type { PodRCData } from './pod-utils'; export const usePodsForVm = ( - vm: K8sResourceKind, + vm: K8sResourceKind | null, ): { loaded: boolean; loadError: string; podData: PodRCData } => { - const { namespace } = vm.metadata; + const namespace = vm?.metadata?.namespace; const [loaded, setLoaded] = useState(false); const [loadError, setLoadError] = useState(''); const [podData, setPodData] = useState(); - const vmName = vm.metadata.name; + const vmName = vm?.metadata?.name; const vmRef = useRef(vm); const watchedResources = useMemo( - () => ({ - replicationControllers: { - isList: true, - groupVersionKind: getGroupVersionKindForModel(ReplicationControllerModel), - namespace, - }, - pods: { - isList: true, - groupVersionKind: getGroupVersionKindForModel(PodModel), - namespace, - }, - virtualmachineinstances: { - isList: true, - groupVersionKind: getGroupVersionKindForModel(VirtualMachineInstanceModel), - namespace, - optional: true, - }, - }), + () => + namespace + ? { + replicationControllers: { + isList: true, + groupVersionKind: getGroupVersionKindForModel(ReplicationControllerModel), + namespace, + }, + pods: { + isList: true, + groupVersionKind: getGroupVersionKindForModel(PodModel), + namespace, + }, + virtualmachineinstances: { + isList: true, + groupVersionKind: getGroupVersionKindForModel(VirtualMachineInstanceModel), + namespace, + optional: true, + }, + } + : {}, [namespace], ); diff --git a/frontend/packages/topology/src/utils/withEditReviewAccess.tsx b/frontend/packages/topology/src/utils/withEditReviewAccess.tsx index cc55007b1d4..a2e28fb7f12 100644 --- a/frontend/packages/topology/src/utils/withEditReviewAccess.tsx +++ b/frontend/packages/topology/src/utils/withEditReviewAccess.tsx @@ -11,13 +11,13 @@ import { getResource } from './topology-utils'; export const withEditReviewAccess: WithEditReviewAccess = (verb) => (WrappedComponent) => { const Component: FC = (props) => { const resourceObj = getResource(props.element); - const resourceModel = modelFor(referenceFor(resourceObj)); + const resourceModel = resourceObj ? modelFor(referenceFor(resourceObj)) : undefined; const editAccess = useAccessReview({ - group: resourceModel.apiGroup, + group: resourceModel?.apiGroup, verb, - resource: resourceModel.plural, - name: resourceObj.metadata.name, - namespace: resourceObj.metadata.namespace, + resource: resourceModel?.plural, + name: resourceObj?.metadata?.name, + namespace: resourceObj?.metadata?.namespace, }); return ; }; From ef5e44c9032242df29001fbe226e34d05eff845f Mon Sep 17 00:00:00 2001 From: platex-rehor-bot Date: Tue, 25 Aug 2026 14:09:30 +0000 Subject: [PATCH 2/2] fix(topology): address review feedback for null-safety improvements OCPBUGS-113709 - Replace bare Promise.reject() calls with Error objects so callers can read error.message in rejection handlers - Update vmRef in usePodsForVm to sync when VM resolves from null, preventing stale null references in getReplicationControllersForResource - Guard usePodsForRevisions against undefined namespace to prevent unscoped cluster-wide watches Co-Authored-By: Claude Opus 4.6 --- .../src/topology/knative-topology-utils.ts | 6 +-- .../src/utils/usePodsForRevisions.ts | 37 ++++++++++--------- .../topology/src/utils/usePodsForVM.ts | 5 ++- 3 files changed, 27 insertions(+), 21 deletions(-) diff --git a/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts b/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts index 027456ee0c3..5116c9e2be2 100644 --- a/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts +++ b/frontend/packages/knative-plugin/src/topology/knative-topology-utils.ts @@ -1368,12 +1368,12 @@ export const isOperatorBackedKnSinkService = ( export const createSinkConnection = (source: Node, target: Node): Promise => { if (!source || !target || source === target) { - return Promise.reject(); + return Promise.reject(new Error('Invalid source or target node')); } const sourceObj = getResource(source); const targetObj = getResource(target); if (!sourceObj || !targetObj) { - return Promise.reject(); + return Promise.reject(new Error('Source or target resource not found')); } return createKnativeEventSourceSink(sourceObj, targetObj); @@ -1381,7 +1381,7 @@ export const createSinkConnection = (source: Node, target: Node): Promise { if (!subObj || !target) { - return Promise.reject(); + return Promise.reject(new Error('Subscription or target resource not found')); } const subscriptionObj = _.omit(subObj, 'status'); const sink = { diff --git a/frontend/packages/knative-plugin/src/utils/usePodsForRevisions.ts b/frontend/packages/knative-plugin/src/utils/usePodsForRevisions.ts index 67a98808ea1..b59cbfe90c5 100644 --- a/frontend/packages/knative-plugin/src/utils/usePodsForRevisions.ts +++ b/frontend/packages/knative-plugin/src/utils/usePodsForRevisions.ts @@ -18,23 +18,26 @@ export const usePodsForRevisions = ( const [pods, setPods] = useState([]); const revisions = useDeepCompareMemoize(Array.isArray(revisionIds) ? revisionIds : [revisionIds]); const watchedResources = useMemo( - () => ({ - deployments: { - isList: true, - kind: 'Deployment', - namespace, - }, - replicaSets: { - isList: true, - kind: 'ReplicaSet', - namespace, - }, - pods: { - isList: true, - kind: 'Pod', - namespace, - }, - }), + () => + namespace + ? { + deployments: { + isList: true, + kind: 'Deployment', + namespace, + }, + replicaSets: { + isList: true, + kind: 'ReplicaSet', + namespace, + }, + pods: { + isList: true, + kind: 'Pod', + namespace, + }, + } + : {}, [namespace], ); diff --git a/frontend/packages/topology/src/utils/usePodsForVM.ts b/frontend/packages/topology/src/utils/usePodsForVM.ts index 02485d086fe..e6c0a847be7 100644 --- a/frontend/packages/topology/src/utils/usePodsForVM.ts +++ b/frontend/packages/topology/src/utils/usePodsForVM.ts @@ -19,7 +19,10 @@ export const usePodsForVm = ( const [loadError, setLoadError] = useState(''); const [podData, setPodData] = useState(); const vmName = vm?.metadata?.name; - const vmRef = useRef(vm); + const vmRef = useRef(vm); + if (vm) { + vmRef.current = vm; + } const watchedResources = useMemo( () =>