From 839f70a6dbd1af2c188a9f921d1ff747ba674d42 Mon Sep 17 00:00:00 2001 From: vitthalmagadum <122079046+vitthalmagadum@users.noreply.github.com> Date: Fri, 11 Oct 2024 16:31:40 +0530 Subject: [PATCH] feat(anta): Added test case to verify SNMP Trap PDUs counters (#828) --- anta/custom_types.py | 1 + anta/tests/snmp.py | 61 ++++++++++++++++++++- examples/tests.yaml | 3 + tests/units/anta_tests/test_snmp.py | 85 ++++++++++++++++++++++++++++- 4 files changed, 147 insertions(+), 3 deletions(-) diff --git a/anta/custom_types.py b/anta/custom_types.py index c1e1f6428..e0bcdd3ea 100644 --- a/anta/custom_types.py +++ b/anta/custom_types.py @@ -204,3 +204,4 @@ def validate_regex(value: str) -> str: ] BgpUpdateError = Literal["inUpdErrWithdraw", "inUpdErrIgnore", "inUpdErrDisableAfiSafi", "disabledAfiSafi", "lastUpdErrTime"] BfdProtocol = Literal["bgp", "isis", "lag", "ospf", "ospfv3", "pim", "route-input", "static-bfd", "static-route", "vrrp", "vxlan"] +SnmpPdu = Literal["inGetPdus", "inGetNextPdus", "inSetPdus", "outGetResponsePdus", "outTrapPdus"] diff --git a/anta/tests/snmp.py b/anta/tests/snmp.py index c7329b6d7..ffbae1c02 100644 --- a/anta/tests/snmp.py +++ b/anta/tests/snmp.py @@ -7,9 +7,9 @@ # mypy: disable-error-code=attr-defined from __future__ import annotations -from typing import TYPE_CHECKING, ClassVar +from typing import TYPE_CHECKING, ClassVar, get_args -from anta.custom_types import PositiveInteger +from anta.custom_types import PositiveInteger, SnmpPdu from anta.models import AntaCommand, AntaTest from anta.tools import get_value @@ -237,3 +237,60 @@ def test(self) -> None: self.result.is_failure(f"Expected `{self.inputs.contact}` as the contact, but found `{contact}` instead.") else: self.result.is_success() + + +class VerifySnmpPDUCounters(AntaTest): + """Verifies the SNMP PDU counters. + + By default, all SNMP PDU counters will be checked for any non-zero values. + An optional list of specific SNMP PDU(s) can be provided for granular testing. + + Expected Results + ---------------- + * Success: The test will pass if the SNMP PDU counter(s) are non-zero/greater than zero. + * Failure: The test will fail if the SNMP PDU counter(s) are zero/None/Not Found. + + Examples + -------- + ```yaml + anta.tests.snmp: + - VerifySnmpPDUCounters: + pdus: + - outTrapPdus + - inGetNextPdus + ``` + """ + + name = "VerifySnmpPDUCounters" + description = "Verifies the SNMP PDU counters." + categories: ClassVar[list[str]] = ["snmp"] + commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show snmp", revision=1)] + + class Input(AntaTest.Input): + """Input model for the VerifySnmpPDUCounters test.""" + + pdus: list[SnmpPdu] | None = None + """Optional list of SNMP PDU counters to be verified. If not provided, test will verifies all PDU counters.""" + + @AntaTest.anta_test + def test(self) -> None: + """Main test function for VerifySnmpPDUCounters.""" + snmp_pdus = self.inputs.pdus + command_output = self.instance_commands[0].json_output + + # Verify SNMP PDU counters. + if not (pdu_counters := get_value(command_output, "counters")): + self.result.is_failure("SNMP counters not found.") + return + + # In case SNMP PDUs not provided, It will check all the update error counters. + if not snmp_pdus: + snmp_pdus = list(get_args(SnmpPdu)) + + failures = {pdu: value for pdu in snmp_pdus if (value := pdu_counters.get(pdu, "Not Found")) == "Not Found" or value == 0} + + # Check if any failures + if not failures: + self.result.is_success() + else: + self.result.is_failure(f"The following SNMP PDU counters are not found or have zero PDU counters:\n{failures}") diff --git a/examples/tests.yaml b/examples/tests.yaml index ade4e7640..cf961f8e5 100644 --- a/examples/tests.yaml +++ b/examples/tests.yaml @@ -398,6 +398,9 @@ anta.tests.snmp: location: New York - VerifySnmpContact: contact: Jon@example.com + - VerifySnmpPDUCounters: + pdus: + - outTrapPdus anta.tests.software: - VerifyEOSVersion: diff --git a/tests/units/anta_tests/test_snmp.py b/tests/units/anta_tests/test_snmp.py index f6d964f83..88f1bcddc 100644 --- a/tests/units/anta_tests/test_snmp.py +++ b/tests/units/anta_tests/test_snmp.py @@ -7,7 +7,7 @@ from typing import Any -from anta.tests.snmp import VerifySnmpContact, VerifySnmpIPv4Acl, VerifySnmpIPv6Acl, VerifySnmpLocation, VerifySnmpStatus +from anta.tests.snmp import VerifySnmpContact, VerifySnmpIPv4Acl, VerifySnmpIPv6Acl, VerifySnmpLocation, VerifySnmpPDUCounters, VerifySnmpStatus from tests.units.anta_tests import test DATA: list[dict[str, Any]] = [ @@ -152,4 +152,87 @@ "messages": ["SNMP contact is not configured."], }, }, + { + "name": "success", + "test": VerifySnmpPDUCounters, + "eos_data": [ + { + "counters": { + "inGetPdus": 3, + "inGetNextPdus": 2, + "inSetPdus": 3, + "outGetResponsePdus": 3, + "outTrapPdus": 9, + }, + } + ], + "inputs": {}, + "expected": {"result": "success"}, + }, + { + "name": "success-specific-pdus", + "test": VerifySnmpPDUCounters, + "eos_data": [ + { + "counters": { + "inGetPdus": 3, + "inGetNextPdus": 0, + "inSetPdus": 0, + "outGetResponsePdus": 0, + "outTrapPdus": 9, + }, + } + ], + "inputs": {"pdus": ["inGetPdus", "outTrapPdus"]}, + "expected": {"result": "success"}, + }, + { + "name": "failure-counters-not-found", + "test": VerifySnmpPDUCounters, + "eos_data": [ + { + "counters": {}, + } + ], + "inputs": {}, + "expected": {"result": "failure", "messages": ["SNMP counters not found."]}, + }, + { + "name": "failure-incorrect-counters", + "test": VerifySnmpPDUCounters, + "eos_data": [ + { + "counters": { + "inGetPdus": 0, + "inGetNextPdus": 2, + "inSetPdus": 0, + "outGetResponsePdus": 3, + "outTrapPdus": 9, + }, + } + ], + "inputs": {}, + "expected": { + "result": "failure", + "messages": ["The following SNMP PDU counters are not found or have zero PDU counters:\n{'inGetPdus': 0, 'inSetPdus': 0}"], + }, + }, + { + "name": "failure-pdu-not-found", + "test": VerifySnmpPDUCounters, + "eos_data": [ + { + "counters": { + "inGetNextPdus": 0, + "inSetPdus": 0, + "outGetResponsePdus": 0, + }, + } + ], + "inputs": {"pdus": ["inGetPdus", "outTrapPdus"]}, + "expected": { + "result": "failure", + "messages": ["The following SNMP PDU counters are not found or have zero PDU counters:\n{'inGetPdus': 'Not Found', 'outTrapPdus': 'Not Found'}"], + }, + }, ]