diff --git a/anta/tests/routing/bgp.py b/anta/tests/routing/bgp.py index 566f99722..08ebce5cd 100644 --- a/anta/tests/routing/bgp.py +++ b/anta/tests/routing/bgp.py @@ -875,3 +875,65 @@ def test(self) -> None: self.result.is_failure(f"The following VXLAN endpoint do not have any EVPN Type-2 route: {no_evpn_routes}") if bad_evpn_routes: self.result.is_failure(f"The following EVPN Type-2 routes do not have at least one valid and active path: {bad_evpn_routes}") + + +class VerifyBGPAdvCommunities(AntaTest): + """ + Verifies if the advertised communities of BGP peers are standard, extended, and large in the specified VRF. + Expected results: + * success: The test will pass if the advertised communities of BGP peers are standard, extended, and large in the specified VRF. + * failure: The test will fail if the advertised communities of BGP peers are not standard, extended, and large in the specified VRF. + """ + + name = "VerifyBGPAdvCommunities" + description = "Verifies if the advertised communities of BGP peers are standard, extended, and large in the specified VRF." + categories = ["routing", "bgp"] + commands = [AntaCommand(command="show bgp neighbors vrf all")] + + class Input(AntaTest.Input): + """ + Input parameters for the test. + """ + + bgp_peers: List[BgpPeers] + """List of BGP peers""" + + class BgpPeers(BaseModel): + """ + This class defines the details of a BGP peer. + """ + + peer_address: IPv4Address + """IPv4 address of a BGP peer.""" + vrf: str = "default" + """Optional VRF for BGP peer. If not provided, it defaults to `default`.""" + + @AntaTest.anta_test + def test(self) -> None: + failures: dict[str, Any] = {"bgp_peers": {}} + + # Iterate over each bgp peer + for bgp_peer in self.inputs.bgp_peers: + peer = str(bgp_peer.peer_address) + vrf = bgp_peer.vrf + failure: dict[str, dict[str, dict[str, Any]]] = {"bgp_peers": {peer: {vrf: {}}}} + + # Verify BGP peer + if ( + not (bgp_output := get_value(self.instance_commands[0].json_output, f"vrfs.{vrf}.peerList")) + or (bgp_output := get_item(bgp_output, "peerAddress", peer)) is None + ): + failure["bgp_peers"][peer][vrf] = {"status": "Not configured"} + failures = utils.deep_update(failures, failure) + continue + + # Verify BGP peer's advertised communities + bgp_output = bgp_output.get("advertisedCommunities") + if not bgp_output["standard"] or not bgp_output["extended"] or not bgp_output["large"]: + failure["bgp_peers"][peer][vrf] = {"advertised_communities": bgp_output} + failures = utils.deep_update(failures, failure) + + if not failures["bgp_peers"]: + self.result.is_success() + else: + self.result.is_failure(f"Following BGP peers are not configured or advertised communities are not standard, extended, and large:\n{failures}") diff --git a/examples/tests.yaml b/examples/tests.yaml index 0773a0ee6..bfb34d7da 100644 --- a/examples/tests.yaml +++ b/examples/tests.yaml @@ -401,6 +401,12 @@ anta.tests.routing: vni: 10020 - address: aac1.ab5d.b41e vni: 10010 + - VerifyBGPAdvCommunities: + bgp_peers: + - peer_address: 172.30.11.17 + vrf: default + - peer_address: 172.30.11.21 + vrf: default ospf: - VerifyOSPFNeighborState: - VerifyOSPFNeighborCount: diff --git a/tests/units/anta_tests/routing/test_bgp.py b/tests/units/anta_tests/routing/test_bgp.py index f10d13924..e77a4fa9a 100644 --- a/tests/units/anta_tests/routing/test_bgp.py +++ b/tests/units/anta_tests/routing/test_bgp.py @@ -12,6 +12,7 @@ # pylint: disable=C0413 # because of the patch above from anta.tests.routing.bgp import ( # noqa: E402 + VerifyBGPAdvCommunities, VerifyBGPExchangedRoutes, VerifyBGPPeerASNCap, VerifyBGPPeerCount, @@ -3078,4 +3079,166 @@ "messages": ["The following VXLAN endpoint do not have any EVPN Type-2 route: [('aa:c1:ab:4e:be:c2', 10020), ('192.168.10.101', 10010)]"], }, }, + { + "name": "success", + "test": VerifyBGPAdvCommunities, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "172.30.11.1", + "advertisedCommunities": {"standard": True, "extended": True, "large": True}, + } + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "172.30.11.10", + "advertisedCommunities": {"standard": True, "extended": True, "large": True}, + } + ] + }, + } + } + ], + "inputs": { + "bgp_peers": [ + { + "peer_address": "172.30.11.1", + }, + { + "peer_address": "172.30.11.10", + "vrf": "MGMT", + }, + ] + }, + "expected": {"result": "success"}, + }, + { + "name": "failure-no-vrf", + "test": VerifyBGPAdvCommunities, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "172.30.11.1", + "advertisedCommunities": {"standard": True, "extended": True, "large": True}, + } + ] + }, + } + } + ], + "inputs": { + "bgp_peers": [ + { + "peer_address": "172.30.11.17", + "vrf": "MGMT", + } + ] + }, + "expected": { + "result": "failure", + "messages": [ + "Following BGP peers are not configured or advertised communities are not standard, extended, and large:\n" + "{'bgp_peers': {'172.30.11.17': {'MGMT': {'status': 'Not configured'}}}}" + ], + }, + }, + { + "name": "failure-no-peer", + "test": VerifyBGPAdvCommunities, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "172.30.11.1", + "advertisedCommunities": {"standard": True, "extended": True, "large": True}, + } + ] + }, + "MGMT": { + "peerList": [ + { + "peerAddress": "172.30.11.1", + "advertisedCommunities": {"standard": True, "extended": True, "large": True}, + } + ] + }, + } + } + ], + "inputs": { + "bgp_peers": [ + { + "peer_address": "172.30.11.10", + "vrf": "default", + }, + { + "peer_address": "172.30.11.12", + "vrf": "MGMT", + }, + ] + }, + "expected": { + "result": "failure", + "messages": [ + "Following BGP peers are not configured or advertised communities are not standard, extended, and large:\n" + "{'bgp_peers': {'172.30.11.10': {'default': {'status': 'Not configured'}}, '172.30.11.12': {'MGMT': {'status': 'Not configured'}}}}" + ], + }, + }, + { + "name": "failure-not-correct-communities", + "test": VerifyBGPAdvCommunities, + "eos_data": [ + { + "vrfs": { + "default": { + "peerList": [ + { + "peerAddress": "172.30.11.1", + "advertisedCommunities": {"standard": False, "extended": False, "large": False}, + } + ] + }, + "CS": { + "peerList": [ + { + "peerAddress": "172.30.11.10", + "advertisedCommunities": {"standard": True, "extended": True, "large": False}, + } + ] + }, + } + } + ], + "inputs": { + "bgp_peers": [ + { + "peer_address": "172.30.11.1", + "vrf": "default", + }, + { + "peer_address": "172.30.11.10", + "vrf": "CS", + }, + ] + }, + "expected": { + "result": "failure", + "messages": [ + "Following BGP peers are not configured or advertised communities are not standard, extended, and large:\n" + "{'bgp_peers': {'172.30.11.1': {'default': {'advertised_communities': {'standard': False, 'extended': False, 'large': False}}}, " + "'172.30.11.10': {'CS': {'advertised_communities': {'standard': True, 'extended': True, 'large': False}}}}}" + ], + }, + }, ]