From 55275f2446cc9cfb38378a4dc887482469c04db2 Mon Sep 17 00:00:00 2001 From: Martin Sottnik Date: Thu, 1 Feb 2024 14:33:17 +0100 Subject: [PATCH] obsolete graphql endpoints removed (#395) * remove usage of linksAndDevices endpoint * remove hasAndInterfaces endpoint * add idHas to query * remove obsolete hasAndInterfaces/linksAndDevices graphql enpdoints * revert .env.example * idHas removed --- .../topology-discovery.graphql.ts | 31 ++++----- .../topology-discovery-graphql.ts | 48 ++------------ src/helpers/topology.helpers.ts | 65 ++++++++++++++++++- src/schema/topology.ts | 18 +++-- 4 files changed, 97 insertions(+), 65 deletions(-) diff --git a/src/__generated__/topology-discovery.graphql.ts b/src/__generated__/topology-discovery.graphql.ts index 56741662..38a25605 100644 --- a/src/__generated__/topology-discovery.graphql.ts +++ b/src/__generated__/topology-discovery.graphql.ts @@ -872,14 +872,25 @@ export type SyncResponse = { * JSON format: * { * "R1": [ - * ["GigabitEthernet0/0/0/0", "GigabitEthernet0/0/0/0", "R7"], - * ["GigabitEthernet0/0/0/1", "GigabitEthernet0/0/0/1", "R2"] + * { + * "from_interface": "GigabitEthernet0/0/0/0", + * "to_interface": "GigabitEthernet0/0/0/0", + * "to_device": "R7" + * }, + * { + * "from_interface": "GigabitEthernet0/0/0/1", + * "to_interface": "GigabitEthernet0/0/0/1", + * "to_device": "R2" + * } * ], * "R2": [ - * ["GigabitEthernet0/0/0/0", "GigabitEthernet0/0/0/0", "R3"] + * { + * "from_interface": "GigabitEthernet0/0/0/0", + * "to_interface": "GigabitEthernet0/0/0/0", + * "to_device": "R3" + * } * ] * } - * Format of Neighbor tuple: [local_interface, remote_interface, remote_device]. */ loaded_devices: Scalars['JSON']; }; @@ -1083,7 +1094,7 @@ export type GetShortestPathQuery = { __typename?: 'Query', netRoutingPaths: { __ export type TopologyDevicesQueryVariables = Exact<{ [key: string]: never; }>; -export type TopologyDevicesQuery = { __typename?: 'Query', phyDevices: { __typename?: 'PhyDeviceConnection', edges: Array<{ __typename?: 'PhyDeviceEdge', node: { __typename?: 'PhyDevice', id: string, name: string, coordinates: { __typename?: 'Coordinates', x: number, y: number }, details: { __typename?: 'PhyDeviceDetails', sw_version: string, device_type: string }, phyInterfaces: { __typename?: 'PhyInterfaceConnection', edges: Array<{ __typename?: 'PhyInterfaceEdge', node: { __typename?: 'PhyInterface', id: string, name: string, status: string, phyLink: { __typename?: 'PhyInterface', id: string, idLink: string | null, name: string, phyDevice: { __typename?: 'PhyDevice', id: string, name: string } | null } | null } | null } | null> | null } } | null } | null> | null } }; +export type TopologyDevicesQuery = { __typename?: 'Query', phyDevices: { __typename?: 'PhyDeviceConnection', edges: Array<{ __typename?: 'PhyDeviceEdge', node: { __typename?: 'PhyDevice', id: string, name: string, status: NodeStatus, labels: Array | null, routerId: string | null, coordinates: { __typename?: 'Coordinates', x: number, y: number }, details: { __typename?: 'PhyDeviceDetails', sw_version: string, device_type: string }, phyInterfaces: { __typename?: 'PhyInterfaceConnection', edges: Array<{ __typename?: 'PhyInterfaceEdge', node: { __typename?: 'PhyInterface', id: string, name: string, status: string, phyLink: { __typename?: 'PhyInterface', id: string, idLink: string | null, name: string, phyDevice: { __typename?: 'PhyDevice', id: string, name: string } | null } | null } | null } | null> | null } } | null } | null> | null } }; export type NetTopologyQueryVariables = Exact<{ [key: string]: never; }>; @@ -1103,16 +1114,6 @@ export type TopologyDiffQueryVariables = Exact<{ export type TopologyDiffQuery = { __typename?: 'Query', topologyDiff: { __typename?: 'TopologyResponse', diff_data: any | null } }; -export type GetLinksAndDevicesQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GetLinksAndDevicesQuery = { __typename?: 'Query', phyLinksAndDevices: { __typename?: 'PhyLinksAndDevicesResponse', phy_links_and_devices_data: any } }; - -export type GetHasAndInterfacesQueryVariables = Exact<{ [key: string]: never; }>; - - -export type GetHasAndInterfacesQuery = { __typename?: 'Query', phyHasAndInterfaces: { __typename?: 'PhyHasAndInterfacesResponse', phy_has_and_interfaces_data: any } }; - export type GetCommonNodesQueryVariables = Exact<{ selectedNodes: Array | Scalars['String']; }>; diff --git a/src/external-api/topology-discovery-graphql.ts b/src/external-api/topology-discovery-graphql.ts index 2de42131..1a5a4809 100644 --- a/src/external-api/topology-discovery-graphql.ts +++ b/src/external-api/topology-discovery-graphql.ts @@ -5,8 +5,6 @@ import { GetBackupsQuery, GetCommonNodesQuery, GetCommonNodesQueryVariables, - GetHasAndInterfacesQuery, - GetLinksAndDevicesQuery, GetShortestPathQuery, GetShortestPathQueryVariables, NetTopologyQuery, @@ -23,14 +21,7 @@ import { SyncePathToGrandMasterQuery, SyncePathToGrandMasterQueryVariables, } from '../__generated__/topology-discovery.graphql'; -import { - HasAndInterfacesOutput, - LinksAndDevicesOutput, - TopologyDiffOutput, - decodeHasAndInterfacesOutput, - decodeLinksAndDevicesOutput, - decodeTopologyDiffOutput, -} from './topology-network-types'; +import { TopologyDiffOutput, decodeTopologyDiffOutput } from './topology-network-types'; type CoordinatesParam = { device: string; @@ -59,6 +50,9 @@ const GET_TOPOLOGY_DEVICES = gql` node { id name + status + labels + routerId coordinates { x y @@ -159,22 +153,6 @@ const GET_TOPOLOGY_DIFF = gql` } `; -const GET_LINKS_AND_DEVICES = gql` - query getLinksAndDevices { - phyLinksAndDevices { - phy_links_and_devices_data - } - } -`; - -const GET_HAS_AND_INTERFACES = gql` - query getHasAndInterfaces { - phyHasAndInterfaces { - phy_has_and_interfaces_data - } - } -`; - const GET_COMMON_NODES = gql` query getCommonNodes($selectedNodes: [String!]!) { commonNodes(selected_nodes: $selectedNodes) { @@ -416,22 +394,6 @@ function getTopologyDiscoveryApi() { return json; } - async function getHasAndInterfaces(): Promise { - const response = await client.request(GET_HAS_AND_INTERFACES); - const { phyHasAndInterfaces } = response; - const json = decodeHasAndInterfacesOutput(phyHasAndInterfaces.phy_has_and_interfaces_data); - - return json; - } - - async function getLinksAndDevices(): Promise { - const response = await client.request(GET_LINKS_AND_DEVICES); - const { phyLinksAndDevices } = response; - const json = decodeLinksAndDevicesOutput(phyLinksAndDevices.phy_links_and_devices_data); - - return json; - } - async function getCommonNodes(selectedNodes: string[]): Promise { const response = await client.request(GET_COMMON_NODES, { selectedNodes, @@ -498,8 +460,6 @@ function getTopologyDiscoveryApi() { getShortestPath, getBackups, getTopologyDiff, - getHasAndInterfaces, - getLinksAndDevices, getCommonNodes, getPtpTopology, getPtpPathToGrandMaster, diff --git a/src/helpers/topology.helpers.ts b/src/helpers/topology.helpers.ts index 0f689392..3fef8026 100644 --- a/src/helpers/topology.helpers.ts +++ b/src/helpers/topology.helpers.ts @@ -1,6 +1,7 @@ import { device as PrismaDevice } from '@prisma/client'; import { NetTopologyQuery, + PhyDevice, PtpTopologyQuery, SynceTopologyQuery, TopologyDevicesQuery, @@ -73,6 +74,52 @@ export function getOldTopologyDevices(devices: ArangoDevice[], diffData: Topolog return oldDevices; } +type PhyDeviceWithoutInterfaces = Omit; + +export function convertPhyDeviceToArangoDevice(phyDevice: PhyDeviceWithoutInterfaces): ArangoDevice { + const { name, status, coordinates, details, labels } = phyDevice; + return { + _id: phyDevice.id, + _key: phyDevice.id, + coordinates, + details, + labels: labels ?? [], + name, + status, + }; +} + +export function getNodesFromTopologyQuery(query: TopologyDevicesQuery): ArangoDevice[] { + const nodes = + query.phyDevices.edges + ?.map((e) => e?.node) + .filter(omitNullValue) + .map(convertPhyDeviceToArangoDevice) ?? []; + return nodes; +} + +export function getEdgesFromTopologyQuery(query: TopologyDevicesQuery): ArangoEdge[] { + const currentEdges = query.phyDevices.edges?.flatMap( + (e) => + e?.node?.phyInterfaces.edges + ?.map((i) => i?.node) + .filter(omitNullValue) + .map((i) => { + if (!i.phyLink?.idLink) { + return null; + } + return { + _id: i.phyLink.idLink, + _key: i.phyLink.idLink, + _from: i.id, + _to: i.phyLink.id, + }; + }) + .filter(omitNullValue) ?? [], + ); + return currentEdges ?? []; +} + export function getOldTopologyInterfaceEdges( interfaceEdges: ArangoEdgeWithStatus[], diffData: TopologyDiffOutput, @@ -211,7 +258,7 @@ export function makeTopologyNodes(dbDevices: PrismaDevice[], topologyDevices?: T return nodes; } -function getTopologyInterfaces(topologyDevices: TopologyDevicesQuery) { +export function getTopologyInterfaces(topologyDevices: TopologyDevicesQuery) { return ( topologyDevices.phyDevices.edges?.flatMap((e) => { const node = e?.node; @@ -226,6 +273,7 @@ function getTopologyInterfaces(topologyDevices: TopologyDevicesQuery) { } return { ...inode, + _id: inode.id, nodeId: node.name, }; }) @@ -235,6 +283,21 @@ function getTopologyInterfaces(topologyDevices: TopologyDevicesQuery) { ); } +export function getDeviceInterfaceEdges(topologyDevices: TopologyDevicesQuery): ArangoEdgeWithStatus[] { + return ( + topologyDevices.phyDevices.edges?.flatMap( + (d) => + d?.node?.phyInterfaces.edges?.map((i) => ({ + _id: `${d.node?.id}-${i?.node?.id}`, + _key: i?.node?.phyLink?.id ?? '', // INFO: idHas was removed + _from: d.node?.id ?? '', + _to: i?.node?.id ?? '', + status: d.node?.status ?? 'unknown', + })) ?? [], + ) ?? [] + ); +} + export function makeTopologyEdges(topologyDevices?: TopologyDevicesQuery) { if (!topologyDevices) { return []; diff --git a/src/schema/topology.ts b/src/schema/topology.ts index 8e300e60..1b14c469 100644 --- a/src/schema/topology.ts +++ b/src/schema/topology.ts @@ -12,10 +12,14 @@ import { import config from '../config'; import { fromGraphId, toGraphId } from '../helpers/id-helper'; import { + getDeviceInterfaceEdges, + getEdgesFromTopologyQuery, getFilterQuery, + getNodesFromTopologyQuery, getOldTopologyConnectedEdges, getOldTopologyDevices, getOldTopologyInterfaceEdges, + getTopologyInterfaces, makeInterfaceDeviceMap, makeInterfaceMap, makeInterfaceNameMap, @@ -234,14 +238,18 @@ export const TopologyVersionDataQuery = extendType({ }; } - const { nodes, edges } = await topologyDiscoveryGraphQLAPI.getLinksAndDevices(); + const topologyDevicesResult = await topologyDiscoveryGraphQLAPI.getTopologyDevices(); + + const currentNodes = getNodesFromTopologyQuery(topologyDevicesResult); + const currentEdges = getEdgesFromTopologyQuery(topologyDevicesResult); + + const interfaces = getTopologyInterfaces(topologyDevicesResult); + const interfaceEdges = getDeviceInterfaceEdges(topologyDevicesResult); const { version } = args; const result = await topologyDiscoveryGraphQLAPI.getTopologyDiff(version); - const oldDevices = getOldTopologyDevices(nodes, result); + const oldDevices = getOldTopologyDevices(currentNodes, result); - // get interface edges for old version - const { has: interfaceEdges, interfaces } = await topologyDiscoveryGraphQLAPI.getHasAndInterfaces(); const oldInterfaceEdges = getOldTopologyInterfaceEdges(interfaceEdges, result); const interfaceDeviceMap = makeInterfaceDeviceMap(oldInterfaceEdges); const interfaceNameMap = makeInterfaceNameMap( @@ -257,7 +265,7 @@ export const TopologyVersionDataQuery = extendType({ const interfaceMap = makeInterfaceMap(oldInterfaceEdges, interfaceNameMap); const nodesMap = makeNodesMap(oldDevices, (d) => d.name); - const oldEdges = getOldTopologyConnectedEdges(edges, result) + const oldEdges = getOldTopologyConnectedEdges(currentEdges, result) .map((e) => ({ id: e._id, source: {