diff --git a/web/src/components/netflow-traffic-tab.tsx b/web/src/components/netflow-traffic-tab.tsx index 67b710220..fabf5ce52 100644 --- a/web/src/components/netflow-traffic-tab.tsx +++ b/web/src/components/netflow-traffic-tab.tsx @@ -132,6 +132,18 @@ export const NetflowTrafficTab: React.FC = ({ match, obj backAndForth: false }); break; + case 'Gateway': + // NOTE: Gateways can be both ingress (receive traffic) and egress (send traffic) + setForcedFilters({ + list: [ + { + def: findFilter(filterDefinitions, 'src_resource')!, + values: [{ v: `${obj.kind}.${obj.metadata!.namespace}.${obj.metadata!.name}` }] + } + ], + backAndForth: true + }); + break; case 'Route': const route = obj as RouteProps; setForcedFilters({ diff --git a/web/src/components/tabs/netflow-topology/2d/styles/styleNode.tsx b/web/src/components/tabs/netflow-topology/2d/styles/styleNode.tsx index 82970d0ff..20275cdd8 100644 --- a/web/src/components/tabs/netflow-topology/2d/styles/styleNode.tsx +++ b/web/src/components/tabs/netflow-topology/2d/styles/styleNode.tsx @@ -3,6 +3,7 @@ import { CubeIcon, CubesIcon, ExternalLinkAltIcon, + GlobeRouteIcon, NetworkIcon, OutlinedHddIcon, QuestionCircleIcon, @@ -68,6 +69,8 @@ const getTypeIcon = (peer: TopologyMetricPeer): React.ComponentClass = return ZoneIcon; case 'UDN': return NetworkIcon; + case 'Gateway': + return GlobeRouteIcon; case 'CatalogSource': case 'DaemonSet': case 'Deployment': diff --git a/web/src/components/tabs/netflow-topology/peer-resource-link.tsx b/web/src/components/tabs/netflow-topology/peer-resource-link.tsx index dfb5dd50b..b44636f30 100644 --- a/web/src/components/tabs/netflow-topology/peer-resource-link.tsx +++ b/web/src/components/tabs/netflow-topology/peer-resource-link.tsx @@ -7,11 +7,19 @@ export interface PeerResourceLinkProps { peer: TopologyMetricPeer; } +// Map of resource kinds that need explicit group-version-kind string +const customResourceGVK: { [kind: string]: string } = { + Gateway: 'gateway.networking.k8s.io~v1~Gateway' +}; + export const PeerResourceLink: React.FC = ({ peer }) => { const name = peer.getDisplayName(false, false); if (name) { if (peer.resourceKind) { - return ; + const gvkString = customResourceGVK[peer.resourceKind]; + // Use group~version~kind format for custom resources, or plain kind for standard resources + const kind = gvkString || peer.resourceKind; + return ; } else { return {name}; } diff --git a/web/src/utils/k8s-models-hook.ts b/web/src/utils/k8s-models-hook.ts index 7cef780fe..2725e9956 100644 --- a/web/src/utils/k8s-models-hook.ts +++ b/web/src/utils/k8s-models-hook.ts @@ -9,6 +9,29 @@ export function useK8sModelsWithColors() { } } + function setModel(kind: string, abbr: string, color: string) { + if (k8sModels && !k8sModels[kind]) { + k8sModels[kind] = { + abbr, + color, + kind, + label: kind, + labelKey: kind, + labelPlural: `${kind}s`, + labelPluralKey: `${kind}s`, + plural: `${kind.toLowerCase()}s`, + apiGroup: '', + apiVersion: 'v1', + id: kind.toLowerCase(), + crd: true, + namespaced: true + }; + } else if (k8sModels && k8sModels[kind]) { + k8sModels[kind].abbr = abbr; + k8sModels[kind].color = color; + } + } + if (k8sModels && !inFlight) { /* This part inject missing colors in k8sModels * check console/frontend/public/style/_vars.scss for values @@ -73,6 +96,9 @@ export function useK8sModelsWithColors() { //$color-ingress-dark = $pf-v5-color-purple-700 = #1F0066 setColor('Ingress', '#1F0066'); + + //$color-gateway-dark = $pf-v5-color-blue-500 = #004080 (same as deployments) + setModel('Gateway', 'G', '#004080'); } return k8sModels; diff --git a/web/webpack.config.ts b/web/webpack.config.ts index dd99798f9..742d49898 100644 --- a/web/webpack.config.ts +++ b/web/webpack.config.ts @@ -375,6 +375,23 @@ module.exports = { } } }, + { + type: "console.tab/horizontalNav", + properties: { + model: { + version: "v1", + group: "gateway.networking.k8s.io", + kind: "Gateway" + }, + component: { + "$codeRef": "netflowTab.default" + }, + "page": { + name: "%plugin__netobserv-plugin~Network Traffic%", + "href": "netflow" + } + } + }, { type: "console.tab/horizontalNav", properties: {