-
Notifications
You must be signed in to change notification settings - Fork 28
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 testcases to verifying Route Type #925
base: main
Are you sure you want to change the base?
Changes from 2 commits
33aabce
c5f0eeb
53bdf21
841ffc5
ca30b7c
beddaa3
640e2d0
0cc3709
a8fa24e
773dc39
cede693
d3d3267
b37059f
52d6c1a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change | ||||
---|---|---|---|---|---|---|
|
@@ -208,3 +208,34 @@ def validate_regex(value: str) -> str: | |||||
SnmpErrorCounter = Literal[ | ||||||
"inVersionErrs", "inBadCommunityNames", "inBadCommunityUses", "inParseErrs", "outTooBigErrs", "outNoSuchNameErrs", "outBadValueErrs", "outGeneralErrs" | ||||||
] | ||||||
# TODO: Needs to update the route types with confirmation. | ||||||
|
||||||
RouteType = Literal[ | ||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||
"connected", | ||||||
"static", | ||||||
"kernel", | ||||||
"OSPF", | ||||||
"OSPF inter area", | ||||||
"OSPF external type 1", | ||||||
"OSPF external type 2", | ||||||
"OSPF NSSA external type 1", | ||||||
"OSPF NSSA external type2", | ||||||
"Other BGP Routes", | ||||||
"iBGP", | ||||||
"eBGP", | ||||||
"RIP", | ||||||
"IS-IS level 1", | ||||||
"IS-IS level 2", | ||||||
"OSPFv3", | ||||||
"BGP Aggregate", | ||||||
"OSPF Summary", | ||||||
"Nexthop Group Static Route", | ||||||
"VXLAN Control Service", | ||||||
"Martian", | ||||||
"DHCP client installed default route", | ||||||
"Dynamic Policy Route", | ||||||
"VRF Leaked", | ||||||
"gRIBI", | ||||||
"Route Cache Route", | ||||||
"CBF Leaked Route", | ||||||
] |
Original file line number | Diff line number | Diff line change | ||||||||||||||
---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|---|
|
@@ -8,13 +8,14 @@ | |||||||||||||||
from __future__ import annotations | ||||||||||||||||
|
||||||||||||||||
from functools import cache | ||||||||||||||||
from ipaddress import IPv4Address, IPv4Interface | ||||||||||||||||
from ipaddress import IPv4Address, IPv4Interface, IPv4Network | ||||||||||||||||
from typing import TYPE_CHECKING, ClassVar, Literal | ||||||||||||||||
|
||||||||||||||||
from pydantic import model_validator | ||||||||||||||||
from pydantic import BaseModel, model_validator | ||||||||||||||||
|
||||||||||||||||
from anta.custom_types import PositiveInteger | ||||||||||||||||
from anta.custom_types import PositiveInteger, RouteType | ||||||||||||||||
from anta.models import AntaCommand, AntaTemplate, AntaTest | ||||||||||||||||
from anta.tools import get_value | ||||||||||||||||
|
||||||||||||||||
if TYPE_CHECKING: | ||||||||||||||||
import sys | ||||||||||||||||
|
@@ -181,3 +182,95 @@ def test(self) -> None: | |||||||||||||||
self.result.is_success() | ||||||||||||||||
else: | ||||||||||||||||
self.result.is_failure(f"The following route(s) are missing from the routing table of VRF {self.inputs.vrf}: {missing_routes}") | ||||||||||||||||
|
||||||||||||||||
|
||||||||||||||||
class VerifyRouteType(AntaTest): | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
"""Verifies the type of the provided route in the routing table of a specified VRF. | ||||||||||||||||
|
||||||||||||||||
Expected Results | ||||||||||||||||
---------------- | ||||||||||||||||
* Success: The test will pass if the provided route is of the expected type. | ||||||||||||||||
* Failure: The test will fail if the provided route is not of the expected type. | ||||||||||||||||
|
||||||||||||||||
Examples | ||||||||||||||||
-------- | ||||||||||||||||
```yaml | ||||||||||||||||
anta.tests.routing: | ||||||||||||||||
generic: | ||||||||||||||||
VerifyRouteType: | ||||||||||||||||
routes_entries: | ||||||||||||||||
- vrf: default | ||||||||||||||||
prefix: 10.10.0.1/32 | ||||||||||||||||
route_type: eBGP | ||||||||||||||||
- vrf: default | ||||||||||||||||
prefix: 10.100.0.12/31 | ||||||||||||||||
route_type: connected | ||||||||||||||||
- vrf: default | ||||||||||||||||
prefix: 10.100.0.14/31 | ||||||||||||||||
route_type: connected | ||||||||||||||||
- vrf: default | ||||||||||||||||
prefix: 10.100.0.128/31 | ||||||||||||||||
route_type: eBGP | ||||||||||||||||
- vrf: default | ||||||||||||||||
prefix: 10.100.1.5/32 | ||||||||||||||||
route_type: iBGP``` | ||||||||||||||||
""" | ||||||||||||||||
|
||||||||||||||||
categories: ClassVar[list[str]] = ["routing"] | ||||||||||||||||
commands: ClassVar[list[AntaCommand | AntaTemplate]] = [ | ||||||||||||||||
AntaCommand(command="show ip route vrf all", revision=4), | ||||||||||||||||
] | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. I would expect this can be one line with out ruff config - maybe you need to check your IDE for the settings (you need to remove the |
||||||||||||||||
|
||||||||||||||||
class Input(AntaTest.Input): | ||||||||||||||||
"""Input model for the VerifyRouteType test.""" | ||||||||||||||||
|
||||||||||||||||
routes_entries: list[Routes] | ||||||||||||||||
|
||||||||||||||||
class Routes(BaseModel): | ||||||||||||||||
"""Model for a list of route entries.""" | ||||||||||||||||
|
||||||||||||||||
vrf: str = "default" | ||||||||||||||||
""" VRF context. Defaults to `default` VRF.""" | ||||||||||||||||
prefix: IPv4Network | ||||||||||||||||
""" IPV4network to validate the rout type. """ | ||||||||||||||||
route_type: RouteType | ||||||||||||||||
""" List of Route type to validate the valid rout type. """ | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. so there is an effort now to move the nested base models to |
||||||||||||||||
|
||||||||||||||||
@AntaTest.anta_test | ||||||||||||||||
def test(self) -> None: | ||||||||||||||||
"""Main test function for VerifyRouteType.""" | ||||||||||||||||
self.result.is_success() | ||||||||||||||||
|
||||||||||||||||
# Forming a dictionary for the test failure message. | ||||||||||||||||
failures: dict[str, any] = {"routes_entries": {}} | ||||||||||||||||
|
||||||||||||||||
# Collecting the 'show ip route vrf all' command output. | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
output = self.instance_commands[0].json_output | ||||||||||||||||
|
||||||||||||||||
# Iterating over the all routes entries mentioned in the inputs. | ||||||||||||||||
for entries in self.inputs.routes_entries: | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
vrf = entries.vrf | ||||||||||||||||
network = str(entries.prefix) | ||||||||||||||||
expected_route_type = entries.route_type | ||||||||||||||||
|
||||||||||||||||
# Verifying that on device, expected VRF is configured. | ||||||||||||||||
if (routes_details := get_value(output, f"vrfs.{vrf}.routes")) is None: | ||||||||||||||||
failures["routes_entries"][network] = {vrf: "Not configured"} | ||||||||||||||||
continue | ||||||||||||||||
|
||||||||||||||||
# Verifying that the expected route is present or not on the device | ||||||||||||||||
if (route_data := get_value(routes_details, network, separator="..")) is None: | ||||||||||||||||
failures["routes_entries"][network] = {vrf: "Routes not found."} | ||||||||||||||||
continue | ||||||||||||||||
|
||||||||||||||||
actual_route_type = route_data.get("routeType") | ||||||||||||||||
|
||||||||||||||||
# Verifying that the expected route-type and the actual routes are the same. | ||||||||||||||||
if expected_route_type != actual_route_type: | ||||||||||||||||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Suggested change
|
||||||||||||||||
failures["routes_entries"][network] = { | ||||||||||||||||
vrf: {"route_type": f"Expected route type is '{expected_route_type}' " f"however in actual it is found as '{actual_route_type}'"} | ||||||||||||||||
} | ||||||||||||||||
|
||||||||||||||||
# Updating the result, as per the testcase failure message. | ||||||||||||||||
if failures["routes_entries"]: | ||||||||||||||||
self.result.is_failure(f"For following routes, VRF is not configured or Route types are invalid:\n{failures}") |
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -508,6 +508,23 @@ anta.tests.routing: | |
routes: | ||
- 10.1.0.1 | ||
- 10.1.0.2 | ||
- VerifyRouteType: | ||
routes_entries: | ||
- vrf: default | ||
prefix: 10.10.0.1/32 | ||
route_type: eBGP | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Update all places |
||
- vrf: default | ||
prefix: 10.100.0.12/31 | ||
route_type: connected | ||
- vrf: default | ||
prefix: 10.100.0.14/31 | ||
route_type: connected | ||
- vrf: default | ||
prefix: 10.100.0.128/31 | ||
route_type: eBGP | ||
- vrf: default | ||
prefix: 10.100.1.5/32 | ||
route_type: iBGP | ||
bgp: | ||
- VerifyBGPPeerCount: | ||
address_families: | ||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Just for my information, how did you come up with this list of route-types?
This is good to help for the input but it may be tricky to maintain (though I suppose it is life)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Hi, @gmuloc ,
The mentioned route types are collected from the following command output.
Vitthal shared a JSON output with me, so with that help, I verified a few route types, such as connected, iBGP, and eBGP, to validate that the other route type needs some more configuration. Hence, I added TODO over there.