From d4092c1f9e2ee0ec296f6eb4fe466e503c082a40 Mon Sep 17 00:00:00 2001
From: "th.l" <thl-cmk@outlook.com>
Date: Mon, 23 Dec 2024 17:22:19 +0100
Subject: [PATCH] fixed handling of anchors

---
 README.md                                     |   2 +-
 mkp/bgp_topology-0.0.2-20241223.mkp           | Bin 0 -> 9178 bytes
 .../bgp_topology/constants.py                 |   9 +-
 .../bgp_topology/lib/bgp_topology.py          | 217 +++++++-----------
 .../server_side_calls/bgp_topology.py         |   1 +
 source/packages/bgp_topology                  |   2 +-
 6 files changed, 87 insertions(+), 144 deletions(-)
 create mode 100644 mkp/bgp_topology-0.0.2-20241223.mkp

diff --git a/README.md b/README.md
index 9e11d58..b3c8c04 100644
--- a/README.md
+++ b/README.md
@@ -1,4 +1,4 @@
-[PACKAGE]: ../../raw/master/mkp/bgp_topology-0.0.1-20240722.mkp "bgp_topology-0.0.1-20240722.mkp"
+[PACKAGE]: ../../raw/master/mkp/bgp_topology-0.0.2-20241223.mkp "bgp_topology-0.0.2-20241223.mkp"
 # Title
 
 A short description about the plugin
diff --git a/mkp/bgp_topology-0.0.2-20241223.mkp b/mkp/bgp_topology-0.0.2-20241223.mkp
new file mode 100644
index 0000000000000000000000000000000000000000..aab7e559ec5897b550f05275b7ade84e77783b3a
GIT binary patch
literal 9178
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
E1OLnj_y7O^

literal 0
HcmV?d00001

diff --git a/source/cmk_addons_plugins/bgp_topology/constants.py b/source/cmk_addons_plugins/bgp_topology/constants.py
index 1213084..98a65ee 100644
--- a/source/cmk_addons_plugins/bgp_topology/constants.py
+++ b/source/cmk_addons_plugins/bgp_topology/constants.py
@@ -10,13 +10,17 @@
 
 # 2024-07-16: copied from bgp_topology/lib/ruleset_names.py
 
+__AUTHOR__ = 'thl-cmk[at]outlook[dot]com'
+__URL__ = 'https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/bgp_topology'
+__USAGE__ = '~/local/lib/python3/cmk_addons/plugins/bgp_topology/libexec/check_bgp_topology --make-default'
+__VERSION__ = '0.0.2-20241223'
 
 from typing import Final
 
 ARG_PARSER_ANCHOR: Final[str] = '--bgp-anchor'
-ARG_PARSER_ANCHOR_AS: Final[str] = 'bgp-as'
+ARG_PARSER_ANCHOR_AS: Final[str] = 'as'
 ARG_PARSER_ANCHOR_BOTH: Final[str] = 'both'
-ARG_PARSER_ANCHOR_ID: Final[str] = 'bgp-id'
+ARG_PARSER_ANCHOR_ID: Final[str] = 'id'
 ARG_PARSER_EMBLEM_AS: Final[str] = '--bgp-emblem-as'
 ARG_PARSER_EMBLEM_ID: Final[str] = '--bgp-emblem-id'
 ARG_PARSER_HOST: Final[str] = '--host'
@@ -24,6 +28,7 @@ ARG_PARSER_MAKE_DEFAULT: Final[str] = '--make-default'
 ARG_PARSER_NONE: Final[str] = 'none'
 ARG_PARSER_SITES_EXCLUDE: Final[str] = '--exclude-sites'
 ARG_PARSER_SITES_INCLUDE: Final[str] = '--include-sites'
+ARG_PARSER_DEBUG: Final[str] = '--debug'
 
 BGP_PEER_LOCAL_ADDR: Final[str] = 'local_addr'
 BGP_PEER_LOCAL_AS: Final[str] = 'local_as'
diff --git a/source/cmk_addons_plugins/bgp_topology/lib/bgp_topology.py b/source/cmk_addons_plugins/bgp_topology/lib/bgp_topology.py
index 76e4d0a..9b5f42d 100644
--- a/source/cmk_addons_plugins/bgp_topology/lib/bgp_topology.py
+++ b/source/cmk_addons_plugins/bgp_topology/lib/bgp_topology.py
@@ -9,30 +9,15 @@
 # File  : bgp_topology/lib/bgp_topology.py
 
 # 2024-07-20: moved to lib -> is now an active check
+# 2024-12-23: moved arg parser to lib/args.py
+#             fixed handling of anchors
 
-__AUTHOR__ = 'thl-cmk[at]outlook[dot]com'
-__URL__ = 'https://thl-cmk.hopto.org/gitlab/checkmk/vendor-independent/bgp_topology'
-__USAGE__ = '/local/lib/python3/cmk_addons/plugins/bgp_topology/libexec/check_bgp_topology --make-default'
-__VERSION__ = '0.0.1-20240721'
-
-from argparse import ArgumentParser, Namespace, RawTextHelpFormatter
 from collections.abc import MutableMapping, MutableSequence, Sequence
 from dataclasses import dataclass
 from time import time_ns
 
 from cmk.agent_based.v2 import render
 from cmk_addons.plugins.bgp_topology.constants import (
-    ARG_PARSER_ANCHOR,
-    ARG_PARSER_ANCHOR_AS,
-    ARG_PARSER_ANCHOR_BOTH,
-    ARG_PARSER_ANCHOR_ID,
-    ARG_PARSER_EMBLEM_AS,
-    ARG_PARSER_EMBLEM_ID,
-    ARG_PARSER_HOST,
-    ARG_PARSER_MAKE_DEFAULT,
-    ARG_PARSER_NONE,
-    ARG_PARSER_SITES_EXCLUDE,
-    ARG_PARSER_SITES_INCLUDE,
     BGP_PEER_LOCAL_ADDR,
     BGP_PEER_LOCAL_AS,
     BGP_PEER_LOCAL_ID,
@@ -41,19 +26,20 @@ from cmk_addons.plugins.bgp_topology.constants import (
     BGP_PEER_REMOTE_ID,
     BGP_PEER_STATE,
     BGP_PEER_UPTIME,
-    EMBLEM_BGP_AS,
-    EMBLEM_BGP_ID,
     METRIC_TIME_TAKEN,
     PARAM_BGP_EXT_ANCHOR_AS,
     PARAM_BGP_EXT_ANCHOR_BOTH,
     PARAM_BGP_EXT_ANCHOR_ID,
     TOPOLOGY_NAME,
 )
+from cmk_addons.plugins.bgp_topology.lib.args import (
+    Params,
+    parse_arguments,
+)
 from cmk_addons.plugins.bgp_topology.lib.utils import (
     BASE_TOPO_PATH,
     LiveStatusConnection,
     Metric,
-    OMD_ROOT,
     TopoConnections,
     TopoObjects,
     add_dummy_topologies,
@@ -67,16 +53,6 @@ from cmk_addons.plugins.bgp_topology.lib.utils import (
 )
 
 
-class Params(Namespace):
-    bgp_anchor: str
-    make_default: bool = False
-    bgp_emblem_as: str = EMBLEM_BGP_AS
-    bgp_emblem_id: str = EMBLEM_BGP_ID
-    include_sites: Sequence[str] | None = None
-    exclude_sites: Sequence[str] | None = None
-    host: str = ''
-
-
 @dataclass(frozen=True)
 class BgpPeer:
     host: str
@@ -104,7 +80,7 @@ class BgpPeer:
                 value = None
             key: str | None = get_bgp_peer_clean_key(key)
             value: str | None = get_bgp_peer_clean_value(key, value)
-            if key is not None and value is not None:
+            if key is not None and value not in [None, '0.0.0.0']:
                 bgp_peer[key] = value
 
         return cls(
@@ -122,6 +98,51 @@ class BgpPeer:
         )
 
 
+def add_bgp_anchor(
+        bgp_anchor : str,
+        bgp_peer: BgpPeer,
+        objects: TopoObjects,
+        connections: TopoConnections,
+        emblem_as: str,
+        emblem_id: str,
+):
+    ext_bgp_host_as: str | None = None
+    ext_bgp_host_id: str | None = None
+    if bgp_anchor in [
+        PARAM_BGP_EXT_ANCHOR_BOTH,
+        PARAM_BGP_EXT_ANCHOR_AS,
+    ] and bgp_peer.remote_as is not None:
+        ext_bgp_host_as: str = f'BGP-AS: {bgp_peer.remote_as}'
+        objects.add_host(
+            host=ext_bgp_host_as,
+            link2core=False,
+            emblem=emblem_as,
+        )
+    if bgp_anchor in [
+        PARAM_BGP_EXT_ANCHOR_BOTH,
+        PARAM_BGP_EXT_ANCHOR_ID
+    ] and bgp_peer.remote_id is not None:
+        ext_bgp_host_id: str = f'BGP-ID: {bgp_peer.remote_id}'
+        objects.add_host(
+            host=ext_bgp_host_id,
+            link2core=False,
+            emblem=emblem_id
+        )
+        connections.add_connection(
+            right=ext_bgp_host_id,
+            left=get_service(bgp_peer.host, bgp_peer.service),
+            left_state=bgp_peer.state
+        )
+        if ext_bgp_host_as is not None:
+            connections.add_connection(ext_bgp_host_id, ext_bgp_host_as)
+
+    if ext_bgp_host_as is not None and ext_bgp_host_id is None:
+        connections.add_connection(
+            right=get_service(bgp_peer.host, bgp_peer.service),
+            left=ext_bgp_host_as,
+            right_state=bgp_peer.state,
+        )
+
 def create_bgp_topology(params: Params | None) -> int:
     start_time = time_ns()
 
@@ -151,10 +172,12 @@ def create_bgp_topology(params: Params | None) -> int:
     query: str = (
         'GET services\n'
         'Columns: host_name state description long_plugin_output\n'
-        'Filter: description ~ BGP peer\n'
+        'Filter: description ~ BGP [Pp]eer\n'
         'OutputFormat: python3\n'
     )
     if (raw_bgp_peers := ls_connection.query(query=query)) is not None:
+        if params.debug:
+            print(raw_bgp_peers)
         bgp_peers: MutableSequence[BgpPeer] = [
             BgpPeer.parse(host, state, service, raw_peer_data) for host, state, service, raw_peer_data in raw_bgp_peers
         ]
@@ -170,18 +193,19 @@ def create_bgp_topology(params: Params | None) -> int:
                 left_state=bgp_peer.state
             )
 
-            if bgp_peer.local_address is not None:
+            if bgp_peer.local_address not in [None]:
                 if bgp_peers_by_local_addr.get(bgp_peer.local_address) is None:
                     bgp_peers_by_local_addr[bgp_peer.local_address]: MutableSequence[BgpPeer] = []
                 bgp_peers_by_local_addr[bgp_peer.local_address].append(bgp_peer)
             else:
-                bgp_peers_by_local_addr['0.0.0.0'].append(bgp_peer)
+               bgp_peers_by_local_addr['0.0.0.0'].append(bgp_peer)
 
         # find connections
         for bgp_peer in bgp_peers:
             if (peer_list := bgp_peers_by_local_addr.get(bgp_peer.remote_address)) is not None:
                 for peer in peer_list:
-                    if bgp_peer.local_as == peer.remote_as and bgp_peer.local_as is not None:
+                    # local_as is not available in the built-in plugins
+                    # if bgp_peer.local_as == peer.remote_as and bgp_peer.local_as is not None:
                         if bgp_peer.local_id == peer.remote_id and bgp_peer.local_id is not None:
                             if bgp_peer.local_address == peer.remote_address and bgp_peer.local_address is not None:
                                 connections.add_connection(
@@ -194,42 +218,24 @@ def create_bgp_topology(params: Params | None) -> int:
             # if there is no peer_list the peer is either external (to checkmk) or the connection is not
             # established, so we have no local address or remote id
             else:
-                ext_bgp_host_as: str | None = None
-                ext_bgp_host_id: str | None = None
-                if bgp_anchor in [
-                    PARAM_BGP_EXT_ANCHOR_BOTH,
-                    PARAM_BGP_EXT_ANCHOR_AS,
-                ] and bgp_peer.remote_as is not None:
-                    ext_bgp_host_as: str = f'BGP-AS: {bgp_peer.remote_as}'
-                    objects.add_host(
-                        host=ext_bgp_host_as,
-                        link2core=False,
-                        emblem=emblem_as,
-                    )
-                if bgp_anchor in [
-                    PARAM_BGP_EXT_ANCHOR_BOTH,
-                    PARAM_BGP_EXT_ANCHOR_ID
-                ] and bgp_peer.remote_id is not None:
-                    ext_bgp_host_id: str = f'BGP-ID: {bgp_peer.remote_id}'
-                    objects.add_host(
-                        host=ext_bgp_host_id,
-                        link2core=False,
-                        emblem=emblem_id
-                    )
-                    connections.add_connection(
-                        right=ext_bgp_host_id,
-                        left=get_service(bgp_peer.host, bgp_peer.service),
-                        left_state=bgp_peer.state
-                    )
-                    if ext_bgp_host_as is not None:
-                        connections.add_connection(ext_bgp_host_id, ext_bgp_host_as)
-
-                if ext_bgp_host_as is not None and ext_bgp_host_id is None:
-                    connections.add_connection(
-                        right=get_service(bgp_peer.host, bgp_peer.service),
-                        left=ext_bgp_host_as,
-                        right_state=bgp_peer.state,
-                    )
+                add_bgp_anchor(
+                    bgp_anchor=bgp_anchor,
+                    bgp_peer=bgp_peer,
+                    objects=objects,
+                    connections=connections,
+                    emblem_as=emblem_as,
+                    emblem_id=emblem_id,
+                )
+
+        for bgp_peer in bgp_peers_by_local_addr['0.0.0.0']:
+            add_bgp_anchor(
+                bgp_anchor=bgp_anchor,
+                bgp_peer=bgp_peer,
+                objects=objects,
+                connections=connections,
+                emblem_as=emblem_as,
+                emblem_id=emblem_id,
+            )
 
     connections.topo_connections.sort()
     data_set = {
@@ -270,75 +276,6 @@ def create_bgp_topology(params: Params | None) -> int:
     return 0
 
 
-def parse_arguments(argv: Sequence[str]) -> Params:
-    parser = ArgumentParser(
-        prog='bgp_topology',
-        formatter_class=RawTextHelpFormatter,
-        description=f"""Create BGP peer network topology for Checkmk""",
-        epilog=f"""
-Example usage:
-{OMD_ROOT}/{__USAGE__}        
-
-Version: {__VERSION__} | Written by {__AUTHOR__}
-for more information see: {__URL__}
-        """
-    )
-    parser.add_argument(
-        ARG_PARSER_ANCHOR,
-        choices=[
-            ARG_PARSER_ANCHOR_BOTH,
-            ARG_PARSER_ANCHOR_AS,
-            ARG_PARSER_ANCHOR_ID,
-            ARG_PARSER_NONE,
-        ],
-        default=ARG_PARSER_ANCHOR_BOTH,
-        help='Anchor for external BGP objects (default: %(default)s).',
-    )
-    parser.add_argument(
-        ARG_PARSER_EMBLEM_AS,
-        type=str,
-        default=EMBLEM_BGP_AS,
-        help='Emblem to use for BGP-AS objects (default: %(default)s).',
-    )
-    parser.add_argument(
-        ARG_PARSER_EMBLEM_ID,
-        type=str,
-        default=EMBLEM_BGP_ID,
-        help='Emblem to use for BGP-ID objects (default: %(default)s).',
-    )
-    parser.add_argument(
-        ARG_PARSER_MAKE_DEFAULT,
-        action='store_const', const=True,
-        default=False,
-        help='Make this topology the default (default: %(default)s).',
-    )
-    parser.add_argument(
-        ARG_PARSER_HOST,
-        type=str,
-        help="""The name of the Checkmk host to which the plugin is attached. This is set 
-automatically by Checkmk. If a site filter is active, the host name is 
-appended to the subdirectory where the topology is stored (“BGP” becomes 
-“BGP_host_name”). This way we can have more than one BGP topology without 
-overwriting each other.""",
-    )
-    site_filter = parser.add_mutually_exclusive_group()
-    site_filter.add_argument(
-        ARG_PARSER_SITES_INCLUDE,
-        type=str,
-        nargs='+',
-        help=f"""List of Checkmk site names to include in the topology creation. 
-Can not used together with {ARG_PARSER_SITES_EXCLUDE}""",
-    )
-    site_filter.add_argument(
-        ARG_PARSER_SITES_EXCLUDE,
-        type=str,
-        nargs='+',
-        help=f"""List of Checkmk site names to exclude from the topology creation. 
-Can not used together with {ARG_PARSER_SITES_INCLUDE}""",
-    )
-
-    return parser.parse_args(argv)
-
 
 def main(argv: Sequence[str] | None = None) -> int:
     return create_bgp_topology(parse_arguments(argv=argv))
diff --git a/source/cmk_addons_plugins/bgp_topology/server_side_calls/bgp_topology.py b/source/cmk_addons_plugins/bgp_topology/server_side_calls/bgp_topology.py
index 37baa8e..e023007 100644
--- a/source/cmk_addons_plugins/bgp_topology/server_side_calls/bgp_topology.py
+++ b/source/cmk_addons_plugins/bgp_topology/server_side_calls/bgp_topology.py
@@ -56,6 +56,7 @@ FILTER_SITES = (
     tuple[Literal['include_sites'], Sequence[str]]
 )
 
+
 class BgpAnchorType:
     anchor_both: str = PARAM_BGP_EXT_ANCHOR_BOTH
     anchor_as: str = PARAM_BGP_EXT_ANCHOR_AS
diff --git a/source/packages/bgp_topology b/source/packages/bgp_topology
index 7ebfba5..acc7bf8 100644
--- a/source/packages/bgp_topology
+++ b/source/packages/bgp_topology
@@ -10,7 +10,7 @@
                                   'bgp_topology/graphing/bgp_topology.py']},
  'name': 'bgp_topology',
  'title': 'BGP peer topology',
- 'version': '0.0.1-20240722',
+ 'version': '0.0.2-20241223',
  'version.min_required': '2.3.0b1',
  'version.packaged': 'cmk-mkp-tool 0.2.0',
  'version.usable_until': '2.4.0b1'}
-- 
GitLab