Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(anta): Added test case to verify Inbound route map and Outbound route map in BGP neighbor details #793

Merged
merged 6 commits into from
Sep 17, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
97 changes: 97 additions & 0 deletions anta/tests/routing/bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -1437,3 +1437,100 @@ def test(self) -> None:
self.result.is_success()
else:
self.result.is_failure(f"The following BGP peers are not configured or have non-zero update error counters:\n{failures}")


class VerifyBgpRouteMaps(AntaTest):
"""Verifies BGP inbound and outbound route-maps of BGP IPv4 peer(s).

Expected Results
----------------
* Success: The test will pass if the correct route maps are applied in the correct direction (inbound or outbound) for IPv4 BGP peers in the specified VRF.
* Failure: The test will fail if BGP peers are not configured or any neighbor has an incorrect or missing route map in either the inbound or outbound direction.

Examples
--------
```yaml
anta.tests.routing:
bgp:
- VerifyBgpRouteMaps:
bgp_peers:
- peer_address: 172.30.11.1
vrf: default
inbound_route_map: RM-MLAG-PEER-IN
outbound_route_map: RM-MLAG-PEER-OUT
```
"""

name = "VerifyBgpRouteMaps"
description = "Verifies BGP inbound and outbound route-maps of BGP IPv4 peer(s)."
categories: ClassVar[list[str]] = ["bgp"]
commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaTemplate(template="show bgp neighbors {peer} vrf {vrf}", revision=3)]

class Input(AntaTest.Input):
"""Input model for the VerifyBgpRouteMaps test."""

bgp_peers: list[BgpPeer]
"""List of BGP peers"""

class BgpPeer(BaseModel):
"""Model for 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`."""
inbound_route_map: str | None = None
"""Inbound route map applied, defaults to None."""
outbound_route_map: str | None = None
"""Outbound route map applied, defaults to None."""

@model_validator(mode="after")
def validate_inputs(self: BaseModel) -> BaseModel:
"""Validate the inputs provided to the BgpPeer class.

At least one of 'inbound' or 'outbound' route-map must be provided.
"""
if not (self.inbound_route_map or self.outbound_route_map):
msg = "At least one of 'inbound_route_map' or 'outbound_route_map' must be provided."
raise ValueError(msg)
return self

def render(self, template: AntaTemplate) -> list[AntaCommand]:
"""Render the template for each BGP peer in the input list."""
return [template.render(peer=str(bgp_peer.peer_address), vrf=bgp_peer.vrf) for bgp_peer in self.inputs.bgp_peers]

@AntaTest.anta_test
def test(self) -> None:
"""Main test function for VerifyBgpRouteMaps."""
failures: dict[Any, Any] = {}

for command, input_entry in zip(self.instance_commands, self.inputs.bgp_peers):
peer = str(input_entry.peer_address)
vrf = input_entry.vrf
inbound_route_map = input_entry.inbound_route_map
outbound_route_map = input_entry.outbound_route_map
failure: dict[Any, Any] = {vrf: {}}

# Verify BGP peer.
if not (peer_list := get_value(command.json_output, f"vrfs.{vrf}.peerList")) or (peer_detail := get_item(peer_list, "peerAddress", peer)) is None:
failures[peer] = {vrf: "Not configured"}
continue

# Verify Inbound route-map
if inbound_route_map and (inbound_map := peer_detail.get("routeMapInbound", "Not Configured")) != inbound_route_map:
failure[vrf].update({"Inbound route-map": inbound_map})

# Verify Outbound route-map
if outbound_route_map and (outbound_map := peer_detail.get("routeMapOutbound", "Not Configured")) != outbound_route_map:
failure[vrf].update({"Outbound route-map": outbound_map})

if failure[vrf]:
failures[peer] = failure

# Check if any failures
if not failures:
self.result.is_success()
else:
self.result.is_failure(
f"The following BGP peers are not configured or has an incorrect or missing route map in either the inbound or outbound direction:\n{failures}"
)
6 changes: 6 additions & 0 deletions examples/tests.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -609,6 +609,12 @@ anta.tests.routing:
update_errors:
- inUpdErrWithdraw
- inUpdErrIgnore
- VerifyBgpRouteMaps:
bgp_peers:
- peer_address: 10.100.4.1
vrf: default
inbound_route_map: RM-MLAG-PEER-IN
outbound_route_map: RM-MLAG-PEER-IN
ospf:
- VerifyOSPFNeighborState:
- VerifyOSPFNeighborCount:
Expand Down
202 changes: 202 additions & 0 deletions tests/units/anta_tests/routing/test_bgp.py
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
VerifyBGPPeerRouteRefreshCap,
VerifyBGPPeersHealth,
VerifyBGPPeerUpdateErrors,
VerifyBgpRouteMaps,
VerifyBGPSpecificPeers,
VerifyBGPTimers,
VerifyEVPNType2Route,
Expand Down Expand Up @@ -4503,4 +4504,205 @@
],
},
},
{
"name": "success",
"test": VerifyBgpRouteMaps,
"eos_data": [
{
"vrfs": {
"default": {
carl-baillargeon marked this conversation as resolved.
Show resolved Hide resolved
"peerList": [
{
"peerAddress": "10.100.0.8",
"routeMapInbound": "RM-MLAG-PEER-IN",
"routeMapOutbound": "RM-MLAG-PEER-OUT",
}
]
},
},
},
{
"vrfs": {
"MGMT": {
"peerList": [
{
"peerAddress": "10.100.0.10",
"routeMapInbound": "RM-MLAG-PEER-IN",
"routeMapOutbound": "RM-MLAG-PEER-OUT",
}
]
},
},
},
],
"inputs": {
"bgp_peers": [
{"peer_address": "10.100.0.8", "vrf": "default", "inbound_route_map": "RM-MLAG-PEER-IN", "outbound_route_map": "RM-MLAG-PEER-OUT"},
{"peer_address": "10.100.0.10", "vrf": "MGMT", "inbound_route_map": "RM-MLAG-PEER-IN", "outbound_route_map": "RM-MLAG-PEER-OUT"},
]
},
"expected": {"result": "success"},
},
{
"name": "failure-incorrect-route-map",
"test": VerifyBgpRouteMaps,
"eos_data": [
{
"vrfs": {
"default": {
"peerList": [
{
"peerAddress": "10.100.0.8",
"routeMapInbound": "RM-MLAG-PEER",
"routeMapOutbound": "RM-MLAG-PEER",
}
]
},
},
},
{
"vrfs": {
"MGMT": {
"peerList": [
{
"peerAddress": "10.100.0.10",
"routeMapInbound": "RM-MLAG-PEER",
"routeMapOutbound": "RM-MLAG-PEER",
}
]
},
},
},
],
"inputs": {
"bgp_peers": [
{"peer_address": "10.100.0.8", "vrf": "default", "inbound_route_map": "RM-MLAG-PEER-IN", "outbound_route_map": "RM-MLAG-PEER-OUT"},
{"peer_address": "10.100.0.10", "vrf": "MGMT", "inbound_route_map": "RM-MLAG-PEER-IN", "outbound_route_map": "RM-MLAG-PEER-OUT"},
]
},
"expected": {
"result": "failure",
"messages": [
"The following BGP peers are not configured or has an incorrect or missing route map in either the inbound or outbound direction:\n"
"{'10.100.0.8': {'default': {'Inbound route-map': 'RM-MLAG-PEER', 'Outbound route-map': 'RM-MLAG-PEER'}}, "
"'10.100.0.10': {'MGMT': {'Inbound route-map': 'RM-MLAG-PEER', 'Outbound route-map': 'RM-MLAG-PEER'}}}"
],
},
},
{
"name": "failure-incorrect-inbound-map",
"test": VerifyBgpRouteMaps,
"eos_data": [
{
"vrfs": {
"default": {
"peerList": [
{
"peerAddress": "10.100.0.8",
"routeMapInbound": "RM-MLAG-PEER",
"routeMapOutbound": "RM-MLAG-PEER",
}
]
},
},
},
{
"vrfs": {
"MGMT": {
"peerList": [
{
"peerAddress": "10.100.0.10",
"routeMapInbound": "RM-MLAG-PEER",
"routeMapOutbound": "RM-MLAG-PEER",
}
]
},
},
},
],
"inputs": {
"bgp_peers": [
{"peer_address": "10.100.0.8", "vrf": "default", "inbound_route_map": "RM-MLAG-PEER-IN"},
{"peer_address": "10.100.0.10", "vrf": "MGMT", "inbound_route_map": "RM-MLAG-PEER-IN"},
]
},
"expected": {
"result": "failure",
"messages": [
"The following BGP peers are not configured or has an incorrect or missing route map in either the inbound or outbound direction:\n"
"{'10.100.0.8': {'default': {'Inbound route-map': 'RM-MLAG-PEER'}}, '10.100.0.10': {'MGMT': {'Inbound route-map': 'RM-MLAG-PEER'}}}"
],
},
},
{
"name": "failure-route-maps-not-configured",
"test": VerifyBgpRouteMaps,
"eos_data": [
{
"vrfs": {
"default": {
"peerList": [
{
"peerAddress": "10.100.0.8",
}
]
},
},
},
{
"vrfs": {
"MGMT": {
"peerList": [
{
"peerAddress": "10.100.0.10",
}
]
},
},
},
],
"inputs": {
"bgp_peers": [
{"peer_address": "10.100.0.8", "vrf": "default", "inbound_route_map": "RM-MLAG-PEER-IN", "outbound_route_map": "RM-MLAG-PEER-OUT"},
{"peer_address": "10.100.0.10", "vrf": "MGMT", "inbound_route_map": "RM-MLAG-PEER-IN", "outbound_route_map": "RM-MLAG-PEER-OUT"},
]
},
"expected": {
"result": "failure",
"messages": [
"The following BGP peers are not configured or has an incorrect or missing route map in either the inbound or outbound direction:\n"
"{'10.100.0.8': {'default': {'Inbound route-map': 'Not Configured', 'Outbound route-map': 'Not Configured'}}, "
"'10.100.0.10': {'MGMT': {'Inbound route-map': 'Not Configured', 'Outbound route-map': 'Not Configured'}}}"
],
},
},
{
"name": "failure-peer-not-found",
"test": VerifyBgpRouteMaps,
"eos_data": [
{
"vrfs": {
"default": {"peerList": []},
},
},
{
"vrfs": {
"MGMT": {"peerList": []},
},
},
],
"inputs": {
"bgp_peers": [
{"peer_address": "10.100.0.8", "vrf": "default", "inbound_route_map": "RM-MLAG-PEER-IN"},
{"peer_address": "10.100.0.10", "vrf": "MGMT", "inbound_route_map": "RM-MLAG-PEER-IN"},
]
},
"expected": {
"result": "failure",
"messages": [
"The following BGP peers are not configured or has an incorrect or missing route map in either the inbound or outbound direction:\n"
"{'10.100.0.8': {'default': 'Not configured'}, '10.100.0.10': {'MGMT': 'Not configured'}}"
],
},
},
]
Loading