Adding upstream version 1.4.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
dc7df702ea
commit
7996c81031
166 changed files with 13787 additions and 11959 deletions
|
@ -37,6 +37,7 @@ def test_anta_dry_run(
|
|||
|
||||
results = session_results[request.node.callspec.id]
|
||||
|
||||
# TODO: Use AntaRunner directly in ANTA v2.0.0
|
||||
@benchmark
|
||||
def _() -> None:
|
||||
results.reset()
|
||||
|
@ -69,6 +70,7 @@ def test_anta(
|
|||
|
||||
results = session_results[request.node.callspec.id]
|
||||
|
||||
# TODO: Use AntaRunner directly in ANTA v2.0.0
|
||||
@benchmark
|
||||
def _() -> None:
|
||||
results.reset()
|
||||
|
@ -77,21 +79,6 @@ def test_anta(
|
|||
|
||||
logging.disable(logging.NOTSET)
|
||||
|
||||
if len(catalog.tests) * len(inventory) != len(results.results):
|
||||
# This could mean duplicates exist.
|
||||
# TODO: consider removing this code and refactor unit test data as a dictionary with tuple keys instead of a list
|
||||
seen = set()
|
||||
dupes = []
|
||||
for test in catalog.tests:
|
||||
if test in seen:
|
||||
dupes.append(test)
|
||||
else:
|
||||
seen.add(test)
|
||||
if dupes:
|
||||
for test in dupes:
|
||||
msg = f"Found duplicate in test catalog: {test}"
|
||||
logger.error(msg)
|
||||
pytest.fail(f"Expected {len(catalog.tests) * len(inventory)} tests but got {len(results.results)}", pytrace=False)
|
||||
bench_info = (
|
||||
"\n--- ANTA NRFU Benchmark Information ---\n"
|
||||
f"Test results: {len(results.results)}\n"
|
||||
|
|
|
@ -67,5 +67,6 @@ def test_csv(results: ResultManager, tmp_path: Path) -> None:
|
|||
@pytest.mark.benchmark
|
||||
@pytest.mark.dependency(depends=["anta_benchmark"], scope="package")
|
||||
def test_markdown(results: ResultManager, tmp_path: Path) -> None:
|
||||
"""Benchmark MDReportGenerator.generate()."""
|
||||
MDReportGenerator.generate(results=results, md_filename=tmp_path / "report.md")
|
||||
"""Benchmark MDReportGenerator.generate_sections()."""
|
||||
sections = [(section, results) for section in MDReportGenerator.DEFAULT_SECTIONS]
|
||||
MDReportGenerator.generate_sections(sections=sections, md_filename=tmp_path / "report.md")
|
||||
|
|
|
@ -7,6 +7,9 @@ from __future__ import annotations
|
|||
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import pytest
|
||||
|
||||
from anta._runner import AntaRunContext, AntaRunFilters, AntaRunner
|
||||
from anta.result_manager import ResultManager
|
||||
from anta.runner import get_coroutines, prepare_tests
|
||||
|
||||
|
@ -22,6 +25,8 @@ if TYPE_CHECKING:
|
|||
from anta.result_manager.models import TestResult
|
||||
|
||||
|
||||
# TODO: Remove this in ANTA v2.0.0
|
||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
||||
def test_prepare_tests(benchmark: BenchmarkFixture, catalog: AntaCatalog, inventory: AntaInventory) -> None:
|
||||
"""Benchmark `anta.runner.prepare_tests`."""
|
||||
|
||||
|
@ -36,6 +41,8 @@ def test_prepare_tests(benchmark: BenchmarkFixture, catalog: AntaCatalog, invent
|
|||
assert sum(len(tests) for tests in selected_tests.values()) == len(inventory) * len(catalog.tests)
|
||||
|
||||
|
||||
# TODO: Remove this in ANTA v2.0.0
|
||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
||||
def test_get_coroutines(benchmark: BenchmarkFixture, catalog: AntaCatalog, inventory: AntaInventory) -> None:
|
||||
"""Benchmark `anta.runner.get_coroutines`."""
|
||||
selected_tests = prepare_tests(inventory=inventory, catalog=catalog, tests=None, tags=None)
|
||||
|
@ -52,3 +59,38 @@ def test_get_coroutines(benchmark: BenchmarkFixture, catalog: AntaCatalog, inven
|
|||
|
||||
count = sum(len(tests) for tests in selected_tests.values())
|
||||
assert count == len(coroutines)
|
||||
|
||||
|
||||
def test__setup_tests(benchmark: BenchmarkFixture, catalog: AntaCatalog, inventory: AntaInventory) -> None:
|
||||
"""Benchmark `anta._runner.AntaRunner._setup_tests`."""
|
||||
runner = AntaRunner()
|
||||
ctx = AntaRunContext(inventory=inventory, catalog=catalog, manager=ResultManager(), filters=AntaRunFilters(), selected_inventory=inventory)
|
||||
|
||||
def bench() -> None:
|
||||
catalog.clear_indexes()
|
||||
runner._setup_tests(ctx)
|
||||
|
||||
benchmark(bench)
|
||||
|
||||
assert ctx.total_tests_scheduled != 0
|
||||
assert ctx.total_devices_selected_for_testing == len(inventory)
|
||||
assert ctx.total_tests_scheduled == len(inventory) * len(catalog.tests)
|
||||
|
||||
|
||||
def test__get_test_coroutines(benchmark: BenchmarkFixture, catalog: AntaCatalog, inventory: AntaInventory) -> None:
|
||||
"""Benchmark `anta._runner.AntaRunner._get_test_coroutines`."""
|
||||
runner = AntaRunner()
|
||||
ctx = AntaRunContext(inventory=inventory, catalog=catalog, manager=ResultManager(), filters=AntaRunFilters(), selected_inventory=inventory)
|
||||
runner._setup_tests(ctx)
|
||||
|
||||
assert ctx.selected_tests is not None
|
||||
|
||||
def bench() -> list[Coroutine[Any, Any, TestResult]]:
|
||||
coros = runner._get_test_coroutines(ctx)
|
||||
for c in coros:
|
||||
c.close()
|
||||
return coros
|
||||
|
||||
coroutines = benchmark(bench)
|
||||
|
||||
assert ctx.total_tests_scheduled == len(coroutines)
|
||||
|
|
|
@ -50,13 +50,21 @@ class AntaMockEnvironment: # pylint: disable=too-few-public-methods
|
|||
Also provide the attribute 'eos_data_catalog` with the output of all the commands used in the test catalog.
|
||||
|
||||
Each module in `tests.units.anta_tests` has a `DATA` constant.
|
||||
The `DATA` structure is a list of dictionaries used to parametrize the test. The list elements have the following keys:
|
||||
- `name` (str): Test name as displayed by Pytest.
|
||||
- `test` (AntaTest): An AntaTest subclass imported in the test module - e.g. VerifyUptime.
|
||||
- `eos_data` (list[dict]): List of data mocking EOS returned data to be passed to the test.
|
||||
- `inputs` (dict): Dictionary to instantiate the `test` inputs as defined in the class from `test`.
|
||||
|
||||
The keys of `eos_data_catalog` is the tuple (DATA['test'], DATA['name']). The values are `eos_data`.
|
||||
The `DATA` structure is a dictionary where:
|
||||
- Each key is a tuple of size 2 containing:
|
||||
- An AntaTest subclass imported in the test module as first element - e.g. VerifyUptime.
|
||||
- A string used as name displayed by pytest as second element.
|
||||
- Each value is an instance of AntaUnitTest, which is a Python TypedDict.
|
||||
|
||||
And AntaUnitTest have the following keys:
|
||||
- `eos_data` (list[dict]): List of data mocking EOS returned data to be passed to the test.
|
||||
- `inputs` (dict): Dictionary to instantiate the `test` inputs as defined in the class from `test`.
|
||||
- `expected` (dict): Expected test result structure, a dictionary containing a key `result` containing one of the allowed status
|
||||
(`Literal[AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.SKIPPED]`) and
|
||||
optionally a key `messages` which is a list(str) and each message is expected to be a substring of one of the actual messages in the TestResult object.
|
||||
|
||||
The keys of `eos_data_catalog` is the tuple (AntaTest subclass, A string used as name displayed by pytest). The values are `eos_data`.
|
||||
"""
|
||||
|
||||
def __init__(self) -> None:
|
||||
|
@ -87,10 +95,11 @@ class AntaMockEnvironment: # pylint: disable=too-few-public-methods
|
|||
test_definitions = []
|
||||
eos_data_catalog = {}
|
||||
for module in import_test_modules():
|
||||
for test_data in module.DATA:
|
||||
test = test_data["test"]
|
||||
result_overwrite = AntaTest.Input.ResultOverwrite(custom_field=test_data["name"])
|
||||
if test_data["inputs"] is None:
|
||||
for (test, name), test_data in module.DATA.items():
|
||||
# Extract the test class, name and test data from a nested tuple structure:
|
||||
# unit test: Tuple[Tuple[Type[AntaTest], str], AntaUnitTest]
|
||||
result_overwrite = AntaTest.Input.ResultOverwrite(custom_field=name)
|
||||
if test_data.get("inputs") is None:
|
||||
inputs = test.Input(result_overwrite=result_overwrite)
|
||||
else:
|
||||
inputs = test.Input(**test_data["inputs"], result_overwrite=result_overwrite)
|
||||
|
@ -98,7 +107,7 @@ class AntaMockEnvironment: # pylint: disable=too-few-public-methods
|
|||
test=test,
|
||||
inputs=inputs,
|
||||
)
|
||||
eos_data_catalog[(test.__name__, test_data["name"])] = test_data["eos_data"]
|
||||
eos_data_catalog[(test.__name__, name)] = test_data["eos_data"]
|
||||
test_definitions.append(test_definition)
|
||||
|
||||
return (AntaCatalog(tests=test_definitions), eos_data_catalog)
|
||||
|
|
|
@ -3,10 +3,8 @@
|
|||
# that can be found in the LICENSE file.
|
||||
"""See https://docs.pytest.org/en/stable/reference/fixtures.html#conftest-py-sharing-fixtures-across-multiple-files."""
|
||||
|
||||
import asyncio
|
||||
from collections.abc import Iterator
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, Mock, patch
|
||||
|
||||
import pytest
|
||||
import respx
|
||||
|
@ -42,7 +40,8 @@ def inventory(request: pytest.FixtureRequest) -> Iterator[AntaInventory]:
|
|||
)
|
||||
if reachable:
|
||||
# This context manager makes all devices reachable
|
||||
with patch("asyncio.open_connection", AsyncMock(spec=asyncio.open_connection, return_value=(Mock(), Mock()))), respx.mock:
|
||||
with respx.mock:
|
||||
respx.head(path="/command-api")
|
||||
respx.post(path="/command-api", headers={"Content-Type": "application/json-rpc"}, json__params__cmds__0__cmd="show version").respond(
|
||||
json={
|
||||
"result": [
|
||||
|
@ -54,5 +53,6 @@ def inventory(request: pytest.FixtureRequest) -> Iterator[AntaInventory]:
|
|||
)
|
||||
yield inv
|
||||
else:
|
||||
with patch("asyncio.open_connection", AsyncMock(spec=asyncio.open_connection, side_effect=TimeoutError)):
|
||||
with respx.mock:
|
||||
respx.head(path="/command-api").respond(status_code=401)
|
||||
yield inv
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
# Copyright (c) 2023-2025 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Syntax Error in file."""
|
||||
|
||||
# pylint: skip-file
|
||||
# flake8: noqa
|
||||
# type: ignore
|
||||
typo
|
||||
typo # type: ignore[name-defined] # noqa: B018
|
||||
|
|
|
@ -15,78 +15,233 @@
|
|||
|
||||
| Total Tests | Total Tests Success | Total Tests Skipped | Total Tests Failure | Total Tests Error |
|
||||
| ----------- | ------------------- | ------------------- | ------------------- | ------------------|
|
||||
| 30 | 4 | 9 | 15 | 2 |
|
||||
| 181 | 43 | 34 | 103 | 1 |
|
||||
|
||||
### Summary Totals Device Under Test
|
||||
|
||||
| Device Under Test | Total Tests | Tests Success | Tests Skipped | Tests Failure | Tests Error | Categories Skipped | Categories Failed |
|
||||
| ------------------| ----------- | ------------- | ------------- | ------------- | ----------- | -------------------| ------------------|
|
||||
| s1-spine1 | 30 | 4 | 9 | 15 | 2 | AVT, Field Notices, Hardware, ISIS, LANZ, OSPF, PTP, Path-Selection, Profiles | AAA, BFD, BGP, Connectivity, Cvx, Interfaces, Logging, MLAG, SNMP, STUN, Security, Services, Software, System, VLAN |
|
||||
| s1-spine1 | 181 | 43 | 34 | 103 | 1 | AVT, Field Notices, Flow Tracking, Hardware, ISIS, Interfaces, LANZ, OSPF, PTP, Path-Selection, Profiles, Segment-Routing | AAA, BFD, BGP, Configuration, Connectivity, Cvx, Greent, Interfaces, Logging, MLAG, Multicast, Routing, SNMP, STP, STUN, Security, Services, Software, VLAN, VXLAN |
|
||||
|
||||
### Summary Totals Per Category
|
||||
|
||||
| Test Category | Total Tests | Tests Success | Tests Skipped | Tests Failure | Tests Error |
|
||||
| ------------- | ----------- | ------------- | ------------- | ------------- | ----------- |
|
||||
| AAA | 1 | 0 | 0 | 1 | 0 |
|
||||
| AVT | 1 | 0 | 1 | 0 | 0 |
|
||||
| BFD | 1 | 0 | 0 | 1 | 0 |
|
||||
| BGP | 1 | 0 | 0 | 0 | 1 |
|
||||
| Configuration | 1 | 1 | 0 | 0 | 0 |
|
||||
| Connectivity | 1 | 0 | 0 | 1 | 0 |
|
||||
| Cvx | 1 | 0 | 0 | 0 | 1 |
|
||||
| Field Notices | 1 | 0 | 1 | 0 | 0 |
|
||||
| Hardware | 1 | 0 | 1 | 0 | 0 |
|
||||
| Interfaces | 1 | 0 | 0 | 1 | 0 |
|
||||
| ISIS | 1 | 0 | 1 | 0 | 0 |
|
||||
| AAA | 7 | 0 | 0 | 7 | 0 |
|
||||
| AVT | 3 | 0 | 3 | 0 | 0 |
|
||||
| BFD | 4 | 1 | 0 | 3 | 0 |
|
||||
| BGP | 25 | 3 | 0 | 21 | 1 |
|
||||
| Configuration | 3 | 1 | 0 | 2 | 0 |
|
||||
| Connectivity | 2 | 1 | 0 | 1 | 0 |
|
||||
| Cvx | 5 | 0 | 0 | 5 | 0 |
|
||||
| Field Notices | 2 | 0 | 2 | 0 | 0 |
|
||||
| Flow Tracking | 1 | 0 | 1 | 0 | 0 |
|
||||
| Greent | 2 | 0 | 0 | 2 | 0 |
|
||||
| Hardware | 7 | 0 | 7 | 0 | 0 |
|
||||
| Interfaces | 16 | 7 | 1 | 8 | 0 |
|
||||
| ISIS | 7 | 0 | 7 | 0 | 0 |
|
||||
| LANZ | 1 | 0 | 1 | 0 | 0 |
|
||||
| Logging | 1 | 0 | 0 | 1 | 0 |
|
||||
| MLAG | 1 | 0 | 0 | 1 | 0 |
|
||||
| OSPF | 1 | 0 | 1 | 0 | 0 |
|
||||
| Path-Selection | 1 | 0 | 1 | 0 | 0 |
|
||||
| Profiles | 1 | 0 | 1 | 0 | 0 |
|
||||
| PTP | 1 | 0 | 1 | 0 | 0 |
|
||||
| Routing | 1 | 1 | 0 | 0 | 0 |
|
||||
| Security | 2 | 0 | 0 | 2 | 0 |
|
||||
| Services | 1 | 0 | 0 | 1 | 0 |
|
||||
| SNMP | 1 | 0 | 0 | 1 | 0 |
|
||||
| Software | 1 | 0 | 0 | 1 | 0 |
|
||||
| STP | 1 | 1 | 0 | 0 | 0 |
|
||||
| STUN | 2 | 0 | 0 | 2 | 0 |
|
||||
| System | 1 | 0 | 0 | 1 | 0 |
|
||||
| VLAN | 1 | 0 | 0 | 1 | 0 |
|
||||
| VXLAN | 1 | 1 | 0 | 0 | 0 |
|
||||
| Logging | 10 | 3 | 0 | 7 | 0 |
|
||||
| MLAG | 6 | 4 | 0 | 2 | 0 |
|
||||
| Multicast | 2 | 1 | 0 | 1 | 0 |
|
||||
| OSPF | 3 | 0 | 3 | 0 | 0 |
|
||||
| Path-Selection | 2 | 0 | 2 | 0 | 0 |
|
||||
| Profiles | 2 | 0 | 2 | 0 | 0 |
|
||||
| PTP | 5 | 0 | 5 | 0 | 0 |
|
||||
| Routing | 6 | 2 | 0 | 4 | 0 |
|
||||
| Security | 15 | 3 | 0 | 12 | 0 |
|
||||
| Segment-Routing | 3 | 0 | 3 | 0 | 0 |
|
||||
| Services | 4 | 1 | 0 | 3 | 0 |
|
||||
| SNMP | 12 | 0 | 0 | 12 | 0 |
|
||||
| Software | 3 | 1 | 0 | 2 | 0 |
|
||||
| STP | 7 | 4 | 0 | 3 | 0 |
|
||||
| STUN | 3 | 0 | 0 | 3 | 0 |
|
||||
| System | 8 | 8 | 0 | 0 | 0 |
|
||||
| VLAN | 3 | 0 | 0 | 3 | 0 |
|
||||
| VXLAN | 5 | 3 | 0 | 2 | 0 |
|
||||
|
||||
## Test Results
|
||||
|
||||
| Device Under Test | Categories | Test | Description | Custom Field | Result | Messages |
|
||||
| ----------------- | ---------- | ---- | ----------- | ------------ | ------ | -------- |
|
||||
| s1-spine1 | AAA | VerifyAcctConsoleMethods | Verifies the AAA accounting console method lists for different accounting types (system, exec, commands, dot1x). | - | failure | AAA console accounting is not configured for commands, exec, system, dot1x |
|
||||
| s1-spine1 | AVT | VerifyAVTPathHealth | Verifies the status of all AVT paths for all VRFs. | - | skipped | VerifyAVTPathHealth test is not supported on cEOSLab. |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersHealth | Verifies the health of IPv4 BFD peers across all VRFs. | - | failure | No IPv4 BFD peers are configured for any VRF. |
|
||||
| s1-spine1 | BGP | VerifyBGPAdvCommunities | Verifies that advertised communities are standard, extended and large for BGP IPv4 peer(s). | - | error | show bgp neighbors vrf all has failed: The command is only supported in the multi-agent routing protocol model., The command is only supported in the multi-agent routing protocol model., The command is only supported in the multi-agent routing protocol model., The command is only supported in the multi-agent routing protocol model. |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigDiffs | Verifies there is no difference between the running-config and the startup-config. | - | success | - |
|
||||
| s1-spine1 | AAA | VerifyAcctDefaultMethods | Verifies the AAA accounting default method lists for different accounting types (system, exec, commands, dot1x). | - | failure | AAA default accounting is not configured for commands, exec, system, dot1x |
|
||||
| s1-spine1 | AAA | VerifyAuthenMethods | Verifies the AAA authentication method lists for different authentication types (login, enable, dot1x). | - | failure | AAA authentication methods are not configured for login console |
|
||||
| s1-spine1 | AAA | VerifyAuthzMethods | Verifies the AAA authorization method lists for different authorization types (commands, exec). | - | failure | AAA authorization methods local, none, logging are not matching for commands, exec |
|
||||
| s1-spine1 | AAA | VerifyTacacsServerGroups | Verifies if the provided TACACS server group(s) are configured. | - | failure | No TACACS server group(s) are configured |
|
||||
| s1-spine1 | AAA | VerifyTacacsServers | Verifies TACACS servers are configured for a specified VRF. | - | failure | No TACACS servers are configured |
|
||||
| s1-spine1 | AAA | VerifyTacacsSourceIntf | Verifies TACACS source-interface for a specified VRF. | - | failure | VRF: MGMT Source Interface: Management0 - Not configured |
|
||||
| s1-spine1 | AVT | VerifyAVTPathHealth | Verifies the status of all AVT paths for all VRFs. | - | skipped | VerifyAVTPathHealth test is not supported on cEOSLab |
|
||||
| s1-spine1 | AVT | VerifyAVTRole | Verifies the AVT role of a device. | - | skipped | VerifyAVTRole test is not supported on cEOSLab |
|
||||
| s1-spine1 | AVT | VerifyAVTSpecificPath | Verifies the Adaptive Virtual Topology (AVT) path. | - | skipped | VerifyAVTSpecificPath test is not supported on cEOSLab |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersHealth | Verifies the health of IPv4 BFD peers across all VRFs. | - | success | - |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersIntervals | Verifies the timers of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.8 VRF: default - Not found<br>Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersRegProtocols | Verifies the registered routing protocol of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BFD | VerifyBFDSpecificPeers | Verifies the state of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.8 VRF: default - Not found<br>Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPAdvCommunities | Verifies the advertised communities of BGP peers. | - | failure | Peer: 172.30.11.17 VRF: default - Not found<br>Peer: 172.30.11.21 VRF: MGMT - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPExchangedRoutes | Verifies the advertised and received routes of BGP IPv4 peer(s). | - | failure | Peer: 172.30.255.5 VRF: default Advertised route: 192.0.254.5/32 - Not found<br>Peer: 172.30.255.5 VRF: default Received route: 192.0.255.4/32 - Not found<br>Peer: 172.30.255.1 VRF: default Advertised route: 192.0.255.1/32 - Not found<br>Peer: 172.30.255.1 VRF: default Advertised route: 192.0.254.5/32 - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPNlriAcceptance | Verifies that all received NLRI are accepted for all AFI/SAFI configured for BGP peers. | - | failure | Peer: 10.100.0.128 VRF: default - Not found<br>Peer: 2001:db8:1::2 VRF: default - Not found<br>Peer: fe80::2%Et1 VRF: default - Not found<br>Peer: fe80::2%Et1 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerASNCap | Verifies the four octet ASN capability of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerCount | Verifies the count of BGP peers for given address families. | - | failure | AFI: ipv4 SAFI: unicast VRF: PROD - VRF not configured<br>AFI: ipv4 SAFI: multicast VRF: DEV - VRF not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerDropStats | Verifies BGP NLRI drop statistics of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerGroup | Verifies BGP peer group of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerMD5Auth | Verifies the MD5 authentication and state of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.5 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: default - Session does not have MD5 authentication enabled |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerMPCaps | Verifies the multiprotocol capabilities of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: default - ipv4MplsLabels not found<br>Interface: Ethernet1 VRF: default - ipv4MplsVpn not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerRouteLimit | Verifies maximum routes and warning limit for BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerRouteRefreshCap | Verifies the route refresh capabilities of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerSession | Verifies the session state of BGP peers. | - | failure | Peer: 10.1.0.1 VRF: default - Not found<br>Peer: 10.1.0.2 VRF: default - Not found<br>Peer: 10.1.255.2 VRF: DEV - Not found<br>Peer: 10.1.255.4 VRF: DEV - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Vlan3499 VRF: PROD - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerSessionRibd | Verifies the session state of BGP peers. | - | failure | Peer: 10.1.0.1 VRF: default - Not found<br>Peer: 10.1.255.4 VRF: DEV - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerTtlMultiHops | Verifies BGP TTL and max-ttl-hops count for BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.2 VRF: test - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerUpdateErrors | Verifies BGP update error counters of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeersHealth | Verifies the health of BGP peers for given address families. | - | failure | AFI: ipv6 SAFI: unicast VRF: DEV - VRF not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPPeersHealthRibd | Verifies the health of all the BGP peers. | - | success | - |
|
||||
| s1-spine1 | BGP | VerifyBGPRedistribution | Verifies BGP redistribution. | - | error | show bgp instance vrf all has failed: Invalid requested version for ModelMetaClass: no such revision 4, most current is 3 |
|
||||
| s1-spine1 | BGP | VerifyBGPRouteECMP | Verifies BGP IPv4 route ECMP paths. | - | success | - |
|
||||
| s1-spine1 | BGP | VerifyBGPRoutePaths | Verifies BGP IPv4 route paths. | - | success | - |
|
||||
| s1-spine1 | BGP | VerifyBGPSpecificPeers | Verifies the health of specific BGP peer(s) for given address families. | - | failure | AFI: evpn Peer: 10.1.0.1 - Not configured<br>AFI: evpn Peer: 10.1.0.2 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.254.1 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.0 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.2 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.4 - Not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPTimers | Verifies the timers of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.5 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBgpRouteMaps | Verifies BGP inbound and outbound route-maps of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyEVPNType2Route | Verifies the EVPN Type-2 routes for a given IPv4 or MAC address and VNI. | - | failure | Address: 192.168.20.102 VNI: 10020 - No EVPN Type-2 route<br>Address: aa:c1:ab:5d:b4:1e VNI: 10010 - No EVPN Type-2 route |
|
||||
| s1-spine1 | BGP | VerifyEVPNType5Routes | Verifies EVPN Type-5 routes for given IP prefixes and VNIs. | - | failure | Prefix: 192.168.10.0/24 VNI: 10 - No EVPN Type-5 routes found<br>Prefix: 192.168.20.0/24 VNI: 20 - No EVPN Type-5 routes found<br>Prefix: 192.168.30.0/24 VNI: 30 - No EVPN Type-5 routes found<br>Prefix: 192.168.40.0/24 VNI: 40 - No EVPN Type-5 routes found |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigDiffs | Verifies there is no difference between the running-config and the startup-config. | - | failure | --- flash:/startup-config<br>+++ system:/running-config<br>@@ -18,6 +18,7 @@<br> hostname leaf1-dc1<br> ip name-server vrf MGMT 10.14.0.1<br> dns domain fun.aristanetworks.com<br>+ip host vitthal 192.168.66.220<br> !<br> platform tfa<br> personality arfa<br> |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigLines | Search the Running-Config for the given RegEx patterns. | - | failure | Following patterns were not found: '^enable password.*$', 'bla bla' |
|
||||
| s1-spine1 | Configuration | VerifyZeroTouch | Verifies ZeroTouch is disabled. | - | success | - |
|
||||
| s1-spine1 | Connectivity | VerifyLLDPNeighbors | Verifies the connection status of the specified LLDP (Link Layer Discovery Protocol) neighbors. | - | failure | Port: Ethernet1 Neighbor: DC1-SPINE1 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: spine1-dc1.fun.aristanetworks.com/Ethernet3<br>Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: spine2-dc1.fun.aristanetworks.com/Ethernet3 |
|
||||
| s1-spine1 | Cvx | VerifyActiveCVXConnections | Verifies the number of active CVX Connections. | - | error | show cvx connections brief has failed: Unavailable command (controller not ready) (at token 2: 'connections') |
|
||||
| s1-spine1 | Field Notices | VerifyFieldNotice44Resolution | Verifies that the device is using the correct Aboot version per FN0044. | - | skipped | VerifyFieldNotice44Resolution test is not supported on cEOSLab. |
|
||||
| s1-spine1 | Hardware | VerifyTemperature | Verifies if the device temperature is within acceptable limits. | - | skipped | VerifyTemperature test is not supported on cEOSLab. |
|
||||
| s1-spine1 | Connectivity | VerifyReachability | Test network reachability to one or many destination IP(s). | - | success | - |
|
||||
| s1-spine1 | Cvx | VerifyActiveCVXConnections | Verifies the number of active CVX Connections. | - | failure | 'show cvx connections brief' failed on s1-spine1: Unavailable command (controller not ready) (at token 2: 'connections') |
|
||||
| s1-spine1 | Cvx | VerifyCVXClusterStatus | Verifies the CVX Server Cluster status. | - | failure | CVX Server status is not enabled<br>CVX Server is not a cluster |
|
||||
| s1-spine1 | Cvx | VerifyManagementCVX | Verifies the management CVX global status. | - | failure | Management CVX status is not valid: Expected: enabled Actual: disabled |
|
||||
| s1-spine1 | Cvx | VerifyMcsClientMounts | Verify if all MCS client mounts are in mountStateMountComplete. | - | failure | MCS Client mount states are not present |
|
||||
| s1-spine1 | Cvx | VerifyMcsServerMounts | Verify if all MCS server mounts are in a MountComplete state. | - | failure | 'show cvx mounts' failed on s1-spine1: Unavailable command (controller not ready) (at token 2: 'mounts') |
|
||||
| s1-spine1 | Field Notices | VerifyFieldNotice44Resolution | Verifies that the device is using the correct Aboot version per FN0044. | - | skipped | VerifyFieldNotice44Resolution test is not supported on cEOSLab |
|
||||
| s1-spine1 | Field Notices | VerifyFieldNotice72Resolution | Verifies if the device is exposed to FN0072, and if the issue has been mitigated. | - | skipped | VerifyFieldNotice72Resolution test is not supported on cEOSLab |
|
||||
| s1-spine1 | Flow Tracking | VerifyHardwareFlowTrackerStatus | Verifies the hardware flow tracking state. | - | skipped | VerifyHardwareFlowTrackerStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | Greent | VerifyGreenT | Verifies if a GreenT policy other than the default is created. | - | failure | No GreenT policy is created |
|
||||
| s1-spine1 | Greent | VerifyGreenTCounters | Verifies if the GreenT counters are incremented. | - | failure | GreenT counters are not incremented |
|
||||
| s1-spine1 | Hardware | VerifyAdverseDrops | Verifies there are no adverse drops on DCS-7280 and DCS-7500 family switches. | - | skipped | VerifyAdverseDrops test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyEnvironmentCooling | Verifies the status of power supply fans and all fan trays. | - | skipped | VerifyEnvironmentCooling test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyEnvironmentPower | Verifies the power supplies status. | - | skipped | VerifyEnvironmentPower test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyEnvironmentSystemCooling | Verifies the device's system cooling status. | - | skipped | VerifyEnvironmentSystemCooling test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyTemperature | Verifies if the device temperature is within acceptable limits. | - | skipped | VerifyTemperature test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyTransceiversManufacturers | Verifies if all the transceivers come from approved manufacturers. | - | skipped | VerifyTransceiversManufacturers test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyTransceiversTemperature | Verifies if all the transceivers are operating at an acceptable temperature. | - | skipped | VerifyTransceiversTemperature test is not supported on cEOSLab |
|
||||
| s1-spine1 | Interfaces | VerifyIPProxyARP | Verifies if Proxy ARP is enabled. | - | failure | Interface: Ethernet1 - Proxy-ARP disabled<br>Interface: Ethernet2 - Proxy-ARP disabled |
|
||||
| s1-spine1 | Interfaces | VerifyIllegalLACP | Verifies there are no illegal LACP packets in all port channels. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceErrDisabled | Verifies there are no interfaces in the errdisabled state. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceErrors | Verifies that the interfaces error counters are equal to zero. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceIPv4 | Verifies the interface IPv4 addresses. | - | failure | Interface: Ethernet2 - IP address mismatch - Expected: 172.30.11.1/31 Actual: 10.100.0.11/31<br>Interface: Ethernet2 - Secondary IP address is not configured |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceUtilization | Verifies that the utilization of interfaces is below a certain threshold. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfacesSpeed | Verifies the speed, lanes, auto-negotiation status, and mode as full duplex for interfaces. | - | failure | Interface: Ethernet2 - Bandwidth mismatch - Expected: 10.0Gbps Actual: 1Gbps<br>Interface: Ethernet3 - Bandwidth mismatch - Expected: 100.0Gbps Actual: 1Gbps<br>Interface: Ethernet3 - Auto-negotiation mismatch - Expected: success Actual: unknown<br>Interface: Ethernet3 - Data lanes count mismatch - Expected: 1 Actual: 0<br>Interface: Ethernet2 - Bandwidth mismatch - Expected: 2.5Gbps Actual: 1Gbps |
|
||||
| s1-spine1 | Interfaces | VerifyInterfacesStatus | Verifies the operational states of specified interfaces to ensure they match expected configurations. | interface | failure | Port-Channel100 - Not configured<br>Ethernet49/1 - Not configured |
|
||||
| s1-spine1 | Interfaces | VerifyIpVirtualRouterMac | Verifies the IP virtual router MAC address. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyL2MTU | Verifies the global L2 MTU of all L2 interfaces. | - | failure | Interface: Ethernet3 - Incorrect MTU configured - Expected: 1500 Actual: 9214<br>Interface: Port-Channel5 - Incorrect MTU configured - Expected: 1500 Actual: 9214 |
|
||||
| s1-spine1 | Interfaces | VerifyL3MTU | Verifies the global L3 MTU of all L3 interfaces. | - | failure | Interface: Ethernet2 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Ethernet1 - Incorrect MTU - Expected: 2500 Actual: 9214<br>Interface: Loopback0 - Incorrect MTU - Expected: 1500 Actual: 65535<br>Interface: Loopback1 - Incorrect MTU - Expected: 1500 Actual: 65535<br>Interface: Vlan1006 - Incorrect MTU - Expected: 1500 Actual: 9164<br>Interface: Vlan1199 - Incorrect MTU - Expected: 1500 Actual: 9164<br>Interface: Vlan4093 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan4094 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan3019 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan3009 - Incorrect MTU - Expected: 1500 Actual: 9214 |
|
||||
| s1-spine1 | Interfaces | VerifyLACPInterfacesStatus | Verifies the Link Aggregation Control Protocol (LACP) status of the interface. | - | failure | Interface: Ethernet1 Port-Channel: Port-Channel100 - Not configured |
|
||||
| s1-spine1 | Interfaces | VerifyLoopbackCount | Verifies the number of loopback interfaces and their status. | - | failure | Loopback interface(s) count mismatch: Expected 3 Actual: 2 |
|
||||
| s1-spine1 | Interfaces | VerifyPortChannels | Verifies there are no inactive ports in all port channels. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifySVI | Verifies the status of all SVIs. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyStormControlDrops | Verifies there are no interface storm-control drop counters. | - | skipped | VerifyStormControlDrops test is not supported on cEOSLab |
|
||||
| s1-spine1 | ISIS | VerifyISISGracefulRestart | Verifies the IS-IS graceful restart feature. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS | VerifyISISInterfaceMode | Verifies IS-IS interfaces are running in the correct mode. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS | VerifyISISNeighborCount | Verifies the number of IS-IS neighbors per interface and level. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS | VerifyISISNeighborState | Verifies the health of IS-IS neighbors. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | LANZ | VerifyLANZ | Verifies if LANZ is enabled. | - | skipped | VerifyLANZ test is not supported on cEOSLab. |
|
||||
| s1-spine1 | ISIS, Segment-Routing | VerifyISISSegmentRoutingAdjacencySegments | Verifies IS-IS segment routing adjacency segments. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS, Segment-Routing | VerifyISISSegmentRoutingDataplane | Verifies IS-IS segment routing data-plane configuration. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS, Segment-Routing | VerifyISISSegmentRoutingTunnels | Verify ISIS-SR tunnels computed by device. | - | skipped | IS-IS-SR not configured |
|
||||
| s1-spine1 | LANZ | VerifyLANZ | Verifies if LANZ is enabled. | - | skipped | VerifyLANZ test is not supported on cEOSLab |
|
||||
| s1-spine1 | Logging | VerifyLoggingAccounting | Verifies if AAA accounting logs are generated. | - | success | - |
|
||||
| s1-spine1 | Logging | VerifyLoggingEntries | Verifies that the expected log string is present in the last specified log messages. | - | failure | Pattern: `.*ACCOUNTING-5-EXEC: cvpadmin ssh.*` - Not found in last 30 alerts log entries<br>Pattern: `.*SPANTREE-6-INTERFACE_ADD:.*` - Not found in last 10 critical log entries |
|
||||
| s1-spine1 | Logging | VerifyLoggingErrors | Verifies there are no syslog messages with a severity of ERRORS or higher. | - | failure | Device has reported syslog messages with a severity of ERRORS or higher:<br>Apr 29 08:01:27 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: sent to neighbor 10.100.4.5 (VRF data AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> Apr 29 08:01:27 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: sent to neighbor 10.100.4.5 (VRF guest AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> Apr 29 08:01:29 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: received from neighbor 10.100.4.5 (VRF guest AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> <br> |
|
||||
| s1-spine1 | Logging | VerifyLoggingHostname | Verifies if logs are generated with the device FQDN. | - | failure | Logs are not generated with the device FQDN |
|
||||
| s1-spine1 | Logging | VerifyLoggingHosts | Verifies logging hosts (syslog servers) for a specified VRF. | - | failure | Syslog servers 1.1.1.1, 2.2.2.2 are not configured in VRF default |
|
||||
| s1-spine1 | Logging | VerifyLoggingLogsGeneration | Verifies if logs are generated. | - | success | - |
|
||||
| s1-spine1 | Logging | VerifyLoggingPersistent | Verifies if logging persistent is enabled and logs are saved in flash. | - | failure | Persistent logging is disabled |
|
||||
| s1-spine1 | Logging | VerifyLoggingSourceIntf | Verifies logging source-interface for a specified VRF. | - | failure | Source-interface: Management0 VRF: default - Not configured |
|
||||
| s1-spine1 | Logging | VerifyLoggingTimestamp | Verifies if logs are generated with the appropriate timestamp. | - | failure | Logs are not generated with the appropriate timestamp format |
|
||||
| s1-spine1 | Logging | VerifySyslogLogging | Verifies if syslog logging is enabled. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagConfigSanity | Verifies there are no MLAG config-sanity inconsistencies. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagDualPrimary | Verifies the MLAG dual-primary detection parameters. | - | failure | Dual-primary detection is disabled |
|
||||
| s1-spine1 | OSPF | VerifyOSPFMaxLSA | Verifies all OSPF instances did not cross the maximum LSA threshold. | - | skipped | No OSPF instance found. |
|
||||
| s1-spine1 | Path-Selection | VerifyPathsHealth | Verifies the path and telemetry state of all paths under router path-selection. | - | skipped | VerifyPathsHealth test is not supported on cEOSLab. |
|
||||
| s1-spine1 | Profiles | VerifyTcamProfile | Verifies the device TCAM profile. | - | skipped | VerifyTcamProfile test is not supported on cEOSLab. |
|
||||
| s1-spine1 | PTP | VerifyPtpGMStatus | Verifies that the device is locked to a valid PTP Grandmaster. | - | skipped | VerifyPtpGMStatus test is not supported on cEOSLab. |
|
||||
| s1-spine1 | MLAG | VerifyMlagInterfaces | Verifies there are no inactive or active-partial MLAG ports. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagPrimaryPriority | Verifies the configuration of the MLAG primary priority. | - | failure | MLAG primary priority mismatch - Expected: 3276 Actual: 32767 |
|
||||
| s1-spine1 | MLAG | VerifyMlagReloadDelay | Verifies the reload-delay parameters of the MLAG configuration. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagStatus | Verifies the health status of the MLAG configuration. | - | success | - |
|
||||
| s1-spine1 | Multicast | VerifyIGMPSnoopingGlobal | Verifies the IGMP snooping global status. | - | success | - |
|
||||
| s1-spine1 | Multicast | VerifyIGMPSnoopingVlans | Verifies the IGMP snooping status for the provided VLANs. | - | failure | VLAN10 - Incorrect IGMP state - Expected: disabled Actual: enabled<br>Supplied vlan 12 is not present on the device |
|
||||
| s1-spine1 | OSPF | VerifyOSPFMaxLSA | Verifies all OSPF instances did not cross the maximum LSA threshold. | - | skipped | OSPF not configured |
|
||||
| s1-spine1 | OSPF | VerifyOSPFNeighborCount | Verifies the number of OSPF neighbors in FULL state is the one we expect. | - | skipped | OSPF not configured |
|
||||
| s1-spine1 | OSPF | VerifyOSPFNeighborState | Verifies all OSPF neighbors are in FULL state. | - | skipped | OSPF not configured |
|
||||
| s1-spine1 | Path-Selection | VerifyPathsHealth | Verifies the path and telemetry state of all paths under router path-selection. | - | skipped | VerifyPathsHealth test is not supported on cEOSLab |
|
||||
| s1-spine1 | Path-Selection | VerifySpecificPath | Verifies the DPS path and telemetry state of an IPv4 peer. | - | skipped | VerifySpecificPath test is not supported on cEOSLab |
|
||||
| s1-spine1 | Profiles | VerifyTcamProfile | Verifies the device TCAM profile. | - | skipped | VerifyTcamProfile test is not supported on cEOSLab |
|
||||
| s1-spine1 | Profiles | VerifyUnifiedForwardingTableMode | Verifies the device is using the expected UFT mode. | - | skipped | VerifyUnifiedForwardingTableMode test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpGMStatus | Verifies that the device is locked to a valid PTP Grandmaster. | - | skipped | VerifyPtpGMStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpLockStatus | Verifies that the device was locked to the upstream PTP GM in the last minute. | - | skipped | VerifyPtpLockStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpModeStatus | Verifies that the device is configured as a PTP Boundary Clock. | - | skipped | VerifyPtpModeStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpOffset | Verifies that the PTP timing offset is within +/- 1000ns from the master clock. | - | skipped | VerifyPtpOffset test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpPortModeStatus | Verifies the PTP interfaces state. | - | skipped | VerifyPtpPortModeStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | Routing | VerifyIPv4RouteNextHops | Verifies the next-hops of the IPv4 prefixes. | - | success | - |
|
||||
| s1-spine1 | Security | VerifyBannerLogin | Verifies the login banner of a device. | - | failure | Expected '# Copyright (c) 2023-2024 Arista Networks, Inc.<br># Use of this source code is governed by the Apache License 2.0<br># that can be found in the LICENSE file.<br>' as the login banner, but found '' instead. |
|
||||
| s1-spine1 | Security | VerifyBannerMotd | Verifies the motd banner of a device. | - | failure | Expected '# Copyright (c) 2023-2024 Arista Networks, Inc.<br># Use of this source code is governed by the Apache License 2.0<br># that can be found in the LICENSE file.<br>' as the motd banner, but found '' instead. |
|
||||
| s1-spine1 | Routing | VerifyIPv4RouteType | Verifies the route-type of the IPv4 prefixes. | - | failure | Prefix: 10.100.0.12/31 VRF: default - Route not found<br>Prefix: 10.100.1.5/32 VRF: default - Incorrect route type - Expected: iBGP Actual: connected |
|
||||
| s1-spine1 | Routing | VerifyRoutingProtocolModel | Verifies the configured routing protocol model. | - | success | - |
|
||||
| s1-spine1 | Routing | VerifyRoutingStatus | Verifies the routing status for IPv4/IPv6 unicast, multicast, and IPv6 interfaces (RFC5549). | - | failure | IPv6 unicast routing enabled status mismatch - Expected: True Actual: False |
|
||||
| s1-spine1 | Routing | VerifyRoutingTableEntry | Verifies that the provided routes are present in the routing table of a specified VRF. | - | failure | The following route(s) are missing from the routing table of VRF default: 10.1.0.1, 10.1.0.2 |
|
||||
| s1-spine1 | Routing | VerifyRoutingTableSize | Verifies the size of the IP routing table of the default VRF. | - | failure | Routing table routes are outside the routes range - Expected: 2 <= to >= 20 Actual: 35 |
|
||||
| s1-spine1 | Security | VerifyAPIHttpStatus | Verifies if eAPI HTTP server is disabled globally. | - | success | - |
|
||||
| s1-spine1 | Security | VerifyAPIHttpsSSL | Verifies if the eAPI has a valid SSL profile. | - | failure | eAPI HTTPS server SSL profile default is not configured |
|
||||
| s1-spine1 | Security | VerifyAPIIPv4Acl | Verifies if eAPI has the right number IPv4 ACL(s) configured for a specified VRF. | - | failure | VRF: default - eAPI IPv4 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifyAPIIPv6Acl | Verifies if eAPI has the right number IPv6 ACL(s) configured for a specified VRF. | - | failure | VRF: default - eAPI IPv6 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifyAPISSLCertificate | Verifies the eAPI SSL certificate expiry, common subject name, encryption algorithm and key size. | - | success | - |
|
||||
| s1-spine1 | Security | VerifyBannerLogin | Verifies the login banner of a device. | - | failure | Login banner is not configured |
|
||||
| s1-spine1 | Security | VerifyBannerMotd | Verifies the motd banner of a device. | - | failure | MOTD banner is not configured |
|
||||
| s1-spine1 | Security | VerifyHardwareEntropy | Verifies hardware entropy generation is enabled on device. | - | failure | Hardware entropy generation is disabled |
|
||||
| s1-spine1 | Security | VerifyIPSecConnHealth | Verifies all IPv4 security connections. | - | failure | No IPv4 security connection configured |
|
||||
| s1-spine1 | Security | VerifyIPv4ACL | Verifies the configuration of IPv4 ACLs. | - | failure | ACL name: LabTest - Not configured |
|
||||
| s1-spine1 | Security | VerifySSHIPv4Acl | Verifies if the SSHD agent has IPv4 ACL(s) configured. | - | failure | VRF: default - SSH IPv4 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifySSHIPv6Acl | Verifies if the SSHD agent has IPv6 ACL(s) configured. | - | failure | VRF: default - SSH IPv6 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifySSHStatus | Verifies if the SSHD agent is disabled in the default VRF. | - | failure | SSHD status for Default VRF is enabled |
|
||||
| s1-spine1 | Security | VerifySpecificIPSecConn | Verifies the IPv4 security connections. | - | failure | Peer: 10.255.0.1 VRF: default - Not configured<br>Peer: 10.255.0.2 VRF: default - Not configured |
|
||||
| s1-spine1 | Security | VerifyTelnetStatus | Verifies if Telnet is disabled in the default VRF. | - | success | - |
|
||||
| s1-spine1 | Services | VerifyDNSLookup | Verifies the DNS name to IP address resolution. | - | success | - |
|
||||
| s1-spine1 | Services | VerifyDNSServers | Verifies if the DNS (Domain Name Service) servers are correctly configured. | - | failure | Server 10.14.0.1 VRF: default Priority: 1 - Not configured<br>Server 10.14.0.11 VRF: MGMT Priority: 0 - Not configured |
|
||||
| s1-spine1 | Services | VerifyErrdisableRecovery | Verifies the error disable recovery functionality. | - | failure | Reason: acl Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300<br>Reason: bpduguard Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300 |
|
||||
| s1-spine1 | Services | VerifyHostname | Verifies the hostname of a device. | - | failure | Incorrect Hostname - Expected: s1-spine1 Actual: leaf1-dc1 |
|
||||
| s1-spine1 | SNMP | VerifySnmpContact | Verifies the SNMP contact of a device. | - | failure | SNMP contact is not configured. |
|
||||
| s1-spine1 | SNMP | VerifySnmpContact | Verifies the SNMP contact of a device. | - | failure | SNMP contact is not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpErrorCounters | Verifies the SNMP error counters. | - | failure | SNMP counters not found |
|
||||
| s1-spine1 | SNMP | VerifySnmpGroup | Verifies the SNMP group configurations for specified version(s). | - | failure | Group: Group1 Version: v1 - Not configured<br>Group: Group2 Version: v3 - Not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpHostLogging | Verifies SNMP logging configurations. | - | failure | SNMP logging is disabled |
|
||||
| s1-spine1 | SNMP | VerifySnmpIPv4Acl | Verifies if the SNMP agent has IPv4 ACL(s) configured. | - | failure | VRF: default - Incorrect SNMP IPv4 ACL(s) - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | SNMP | VerifySnmpIPv6Acl | Verifies if the SNMP agent has IPv6 ACL(s) configured. | - | failure | VRF: default - Incorrect SNMP IPv6 ACL(s) - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | SNMP | VerifySnmpLocation | Verifies the SNMP location of a device. | - | failure | SNMP location is not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpNotificationHost | Verifies the SNMP notification host(s) (SNMP manager) configurations. | - | failure | No SNMP host is configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpPDUCounters | Verifies the SNMP PDU counters. | - | failure | SNMP counters not found |
|
||||
| s1-spine1 | SNMP | VerifySnmpSourceInterface | Verifies SNMP source interfaces. | - | failure | SNMP source interface(s) not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpStatus | Verifies if the SNMP agent is enabled. | - | failure | VRF: default - SNMP agent disabled |
|
||||
| s1-spine1 | SNMP | VerifySnmpUser | Verifies the SNMP user configurations. | - | failure | User: test Group: test_group Version: v3 - Not found |
|
||||
| s1-spine1 | Software | VerifyEOSExtensions | Verifies that all EOS extensions installed on the device are enabled for boot persistence. | - | success | - |
|
||||
| s1-spine1 | Software | VerifyEOSVersion | Verifies the EOS version of the device. | - | failure | EOS version mismatch - Actual: 4.31.0F-33804048.4310F (engineering build) not in Expected: 4.25.4M, 4.26.1F |
|
||||
| s1-spine1 | Software | VerifyTerminAttrVersion | Verifies the TerminAttr version of the device. | - | failure | TerminAttr version mismatch - Actual: v1.29.0 not in Expected: v1.13.6, v1.8.0 |
|
||||
| s1-spine1 | STP | VerifySTPBlockedPorts | Verifies there is no STP blocked ports. | - | success | - |
|
||||
| s1-spine1 | STUN | VerifyStunClient | (Deprecated) Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found. |
|
||||
| s1-spine1 | STUN | VerifyStunClientTranslation | Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found.<br>Client 100.64.3.2 Port: 4500 - STUN client translation not found. |
|
||||
| s1-spine1 | System | VerifyNTPAssociations | Verifies the Network Time Protocol (NTP) associations. | - | failure | NTP Server: 1.1.1.1 Preferred: True Stratum: 1 - Not configured<br>NTP Server: 2.2.2.2 Preferred: False Stratum: 2 - Not configured<br>NTP Server: 3.3.3.3 Preferred: False Stratum: 2 - Not configured |
|
||||
| s1-spine1 | STP | VerifySTPCounters | Verifies there is no errors in STP BPDU packets. | - | success | - |
|
||||
| s1-spine1 | STP | VerifySTPDisabledVlans | Verifies the STP disabled VLAN(s). | - | failure | VLAN: 6 - Not configured |
|
||||
| s1-spine1 | STP | VerifySTPForwardingPorts | Verifies that all interfaces are forwarding for a provided list of VLAN(s). | - | success | - |
|
||||
| s1-spine1 | STP | VerifySTPMode | Verifies the configured STP mode for a provided list of VLAN(s). | - | failure | VLAN 10 - Incorrect STP mode - Expected: rapidPvst Actual: mstp<br>VLAN 20 - Incorrect STP mode - Expected: rapidPvst Actual: mstp |
|
||||
| s1-spine1 | STP | VerifySTPRootPriority | Verifies the STP root priority for a provided list of VLAN or MST instance ID(s). | - | failure | Instance: MST10 - Not configured<br>Instance: MST20 - Not configured |
|
||||
| s1-spine1 | STP | VerifyStpTopologyChanges | Verifies the number of changes across all interfaces in the Spanning Tree Protocol (STP) topology is below a threshold. | - | success | - |
|
||||
| s1-spine1 | STUN | VerifyStunClient | (Deprecated) Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found |
|
||||
| s1-spine1 | STUN | VerifyStunClientTranslation | Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found<br>Client 100.64.3.2 Port: 4500 - STUN client translation not found |
|
||||
| s1-spine1 | STUN | VerifyStunServer | Verifies the STUN server status is enabled and running. | - | failure | STUN server status is disabled and not running |
|
||||
| s1-spine1 | System | VerifyAgentLogs | Verifies there are no agent crash reports. | - | success | - |
|
||||
| s1-spine1 | System | VerifyCPUUtilization | Verifies whether the CPU utilization is below 75%. | - | success | - |
|
||||
| s1-spine1 | System | VerifyCoredump | Verifies there are no core dump files. | - | success | - |
|
||||
| s1-spine1 | System | VerifyFileSystemUtilization | Verifies that no partition is utilizing more than 75% of its disk space. | - | success | - |
|
||||
| s1-spine1 | System | VerifyMaintenance | Verifies that the device is not currently under or entering maintenance. | - | success | - |
|
||||
| s1-spine1 | System | VerifyNTP | Verifies if NTP is synchronised. | - | success | - |
|
||||
| s1-spine1 | System | VerifyReloadCause | Verifies the last reload cause of the device. | reload-cause | success | - |
|
||||
| s1-spine1 | System | VerifyUptime | Verifies the device uptime. | - | success | - |
|
||||
| s1-spine1 | VLAN | VerifyDynamicVlanSource | Verifies dynamic VLAN allocation for specified VLAN sources. | - | failure | Dynamic VLAN source(s) exist but have no VLANs allocated: mlagsync |
|
||||
| s1-spine1 | VXLAN | VerifyVxlan1ConnSettings | Verifies the interface vxlan1 source interface and UDP port. | - | success | - |
|
||||
| s1-spine1 | VLAN | VerifyVlanInternalPolicy | Verifies the VLAN internal allocation policy and the range of VLANs. | - | failure | VLAN internal allocation policy: ascending - Incorrect end VLAN id configured - Expected: 4094 Actual: 1199 |
|
||||
| s1-spine1 | VLAN | VerifyVlanStatus | Verifies the administrative status of specified VLANs. | - | failure | VLAN: Vlan10 - Incorrect administrative status - Expected: suspended Actual: active |
|
||||
| s1-spine1 | VXLAN | VerifyVxlan1ConnSettings | Verifies Vxlan1 source interface and UDP port. | - | success | - |
|
||||
| s1-spine1 | VXLAN | VerifyVxlan1Interface | Verifies the Vxlan1 interface status. | - | success | - |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanConfigSanity | Verifies there are no VXLAN config-sanity inconsistencies. | - | success | - |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanVniBinding | Verifies the VNI-VLAN, VNI-VRF bindings of the Vxlan1 interface. | - | failure | Interface: Vxlan1 VNI: 500 - Binding not found |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanVtep | Verifies Vxlan1 VTEP peers. | - | failure | The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.5, 10.1.1.6<br>Unexpected VTEP peer(s) on Vxlan1 interface: 10.100.2.3 |
|
||||
|
|
355
tests/data/test_md_report_custom_sections.md
Normal file
355
tests/data/test_md_report_custom_sections.md
Normal file
|
@ -0,0 +1,355 @@
|
|||
# ANTA Report
|
||||
|
||||
**Table of Contents:**
|
||||
|
||||
- [ANTA Report](#anta-report)
|
||||
- [Test Results Summary](#test-results-summary)
|
||||
- [Summary Totals](#summary-totals)
|
||||
- [Summary Totals Device Under Test](#summary-totals-device-under-test)
|
||||
- [Summary Totals Per Category](#summary-totals-per-category)
|
||||
- [Test Results](#test-results)
|
||||
|
||||
## Test Results Summary
|
||||
|
||||
### Summary Totals
|
||||
|
||||
| Total Tests | Total Tests Success | Total Tests Skipped | Total Tests Failure | Total Tests Error |
|
||||
| ----------- | ------------------- | ------------------- | ------------------- | ------------------|
|
||||
| 181 | 43 | 34 | 103 | 1 |
|
||||
|
||||
### Summary Totals Device Under Test
|
||||
|
||||
| Device Under Test | Total Tests | Tests Success | Tests Skipped | Tests Failure | Tests Error | Categories Skipped | Categories Failed |
|
||||
| ------------------| ----------- | ------------- | ------------- | ------------- | ----------- | -------------------| ------------------|
|
||||
| s1-spine1 | 181 | 43 | 34 | 103 | 1 | AVT, Field Notices, Flow Tracking, Hardware, ISIS, Interfaces, LANZ, OSPF, PTP, Path-Selection, Profiles, Segment-Routing | AAA, BFD, BGP, Configuration, Connectivity, Cvx, Greent, Interfaces, Logging, MLAG, Multicast, Routing, SNMP, STP, STUN, Security, Services, Software, VLAN, VXLAN |
|
||||
|
||||
### Summary Totals Per Category
|
||||
|
||||
| Test Category | Total Tests | Tests Success | Tests Skipped | Tests Failure | Tests Error |
|
||||
| ------------- | ----------- | ------------- | ------------- | ------------- | ----------- |
|
||||
| AAA | 7 | 0 | 0 | 7 | 0 |
|
||||
| AVT | 3 | 0 | 3 | 0 | 0 |
|
||||
| BFD | 4 | 1 | 0 | 3 | 0 |
|
||||
| BGP | 25 | 3 | 0 | 21 | 1 |
|
||||
| Configuration | 3 | 1 | 0 | 2 | 0 |
|
||||
| Connectivity | 2 | 1 | 0 | 1 | 0 |
|
||||
| Cvx | 5 | 0 | 0 | 5 | 0 |
|
||||
| Field Notices | 2 | 0 | 2 | 0 | 0 |
|
||||
| Flow Tracking | 1 | 0 | 1 | 0 | 0 |
|
||||
| Greent | 2 | 0 | 0 | 2 | 0 |
|
||||
| Hardware | 7 | 0 | 7 | 0 | 0 |
|
||||
| Interfaces | 16 | 7 | 1 | 8 | 0 |
|
||||
| ISIS | 7 | 0 | 7 | 0 | 0 |
|
||||
| LANZ | 1 | 0 | 1 | 0 | 0 |
|
||||
| Logging | 10 | 3 | 0 | 7 | 0 |
|
||||
| MLAG | 6 | 4 | 0 | 2 | 0 |
|
||||
| Multicast | 2 | 1 | 0 | 1 | 0 |
|
||||
| OSPF | 3 | 0 | 3 | 0 | 0 |
|
||||
| Path-Selection | 2 | 0 | 2 | 0 | 0 |
|
||||
| Profiles | 2 | 0 | 2 | 0 | 0 |
|
||||
| PTP | 5 | 0 | 5 | 0 | 0 |
|
||||
| Routing | 6 | 2 | 0 | 4 | 0 |
|
||||
| Security | 15 | 3 | 0 | 12 | 0 |
|
||||
| Segment-Routing | 3 | 0 | 3 | 0 | 0 |
|
||||
| Services | 4 | 1 | 0 | 3 | 0 |
|
||||
| SNMP | 12 | 0 | 0 | 12 | 0 |
|
||||
| Software | 3 | 1 | 0 | 2 | 0 |
|
||||
| STP | 7 | 4 | 0 | 3 | 0 |
|
||||
| STUN | 3 | 0 | 0 | 3 | 0 |
|
||||
| System | 8 | 8 | 0 | 0 | 0 |
|
||||
| VLAN | 3 | 0 | 0 | 3 | 0 |
|
||||
| VXLAN | 5 | 3 | 0 | 2 | 0 |
|
||||
|
||||
## Failed Test Results Summary
|
||||
|
||||
| Device Under Test | Categories | Test | Description | Custom Field | Result | Messages |
|
||||
| ----------------- | ---------- | ---- | ----------- | ------------ | ------ | -------- |
|
||||
| s1-spine1 | AAA | VerifyAcctConsoleMethods | Verifies the AAA accounting console method lists for different accounting types (system, exec, commands, dot1x). | - | failure | AAA console accounting is not configured for commands, exec, system, dot1x |
|
||||
| s1-spine1 | AAA | VerifyAcctDefaultMethods | Verifies the AAA accounting default method lists for different accounting types (system, exec, commands, dot1x). | - | failure | AAA default accounting is not configured for commands, exec, system, dot1x |
|
||||
| s1-spine1 | AAA | VerifyAuthenMethods | Verifies the AAA authentication method lists for different authentication types (login, enable, dot1x). | - | failure | AAA authentication methods are not configured for login console |
|
||||
| s1-spine1 | AAA | VerifyAuthzMethods | Verifies the AAA authorization method lists for different authorization types (commands, exec). | - | failure | AAA authorization methods local, none, logging are not matching for commands, exec |
|
||||
| s1-spine1 | AAA | VerifyTacacsServerGroups | Verifies if the provided TACACS server group(s) are configured. | - | failure | No TACACS server group(s) are configured |
|
||||
| s1-spine1 | AAA | VerifyTacacsServers | Verifies TACACS servers are configured for a specified VRF. | - | failure | No TACACS servers are configured |
|
||||
| s1-spine1 | AAA | VerifyTacacsSourceIntf | Verifies TACACS source-interface for a specified VRF. | - | failure | VRF: MGMT Source Interface: Management0 - Not configured |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersIntervals | Verifies the timers of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.8 VRF: default - Not found<br>Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersRegProtocols | Verifies the registered routing protocol of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BFD | VerifyBFDSpecificPeers | Verifies the state of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.8 VRF: default - Not found<br>Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPAdvCommunities | Verifies the advertised communities of BGP peers. | - | failure | Peer: 172.30.11.17 VRF: default - Not found<br>Peer: 172.30.11.21 VRF: MGMT - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPExchangedRoutes | Verifies the advertised and received routes of BGP IPv4 peer(s). | - | failure | Peer: 172.30.255.5 VRF: default Advertised route: 192.0.254.5/32 - Not found<br>Peer: 172.30.255.5 VRF: default Received route: 192.0.255.4/32 - Not found<br>Peer: 172.30.255.1 VRF: default Advertised route: 192.0.255.1/32 - Not found<br>Peer: 172.30.255.1 VRF: default Advertised route: 192.0.254.5/32 - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPNlriAcceptance | Verifies that all received NLRI are accepted for all AFI/SAFI configured for BGP peers. | - | failure | Peer: 10.100.0.128 VRF: default - Not found<br>Peer: 2001:db8:1::2 VRF: default - Not found<br>Peer: fe80::2%Et1 VRF: default - Not found<br>Peer: fe80::2%Et1 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerASNCap | Verifies the four octet ASN capability of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerCount | Verifies the count of BGP peers for given address families. | - | failure | AFI: ipv4 SAFI: unicast VRF: PROD - VRF not configured<br>AFI: ipv4 SAFI: multicast VRF: DEV - VRF not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerDropStats | Verifies BGP NLRI drop statistics of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerGroup | Verifies BGP peer group of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerMD5Auth | Verifies the MD5 authentication and state of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.5 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: default - Session does not have MD5 authentication enabled |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerMPCaps | Verifies the multiprotocol capabilities of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: default - ipv4MplsLabels not found<br>Interface: Ethernet1 VRF: default - ipv4MplsVpn not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerRouteLimit | Verifies maximum routes and warning limit for BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerRouteRefreshCap | Verifies the route refresh capabilities of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerSession | Verifies the session state of BGP peers. | - | failure | Peer: 10.1.0.1 VRF: default - Not found<br>Peer: 10.1.0.2 VRF: default - Not found<br>Peer: 10.1.255.2 VRF: DEV - Not found<br>Peer: 10.1.255.4 VRF: DEV - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Vlan3499 VRF: PROD - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerSessionRibd | Verifies the session state of BGP peers. | - | failure | Peer: 10.1.0.1 VRF: default - Not found<br>Peer: 10.1.255.4 VRF: DEV - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerTtlMultiHops | Verifies BGP TTL and max-ttl-hops count for BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.2 VRF: test - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerUpdateErrors | Verifies BGP update error counters of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeersHealth | Verifies the health of BGP peers for given address families. | - | failure | AFI: ipv6 SAFI: unicast VRF: DEV - VRF not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPSpecificPeers | Verifies the health of specific BGP peer(s) for given address families. | - | failure | AFI: evpn Peer: 10.1.0.1 - Not configured<br>AFI: evpn Peer: 10.1.0.2 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.254.1 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.0 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.2 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.4 - Not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPTimers | Verifies the timers of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.5 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBgpRouteMaps | Verifies BGP inbound and outbound route-maps of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyEVPNType2Route | Verifies the EVPN Type-2 routes for a given IPv4 or MAC address and VNI. | - | failure | Address: 192.168.20.102 VNI: 10020 - No EVPN Type-2 route<br>Address: aa:c1:ab:5d:b4:1e VNI: 10010 - No EVPN Type-2 route |
|
||||
| s1-spine1 | BGP | VerifyEVPNType5Routes | Verifies EVPN Type-5 routes for given IP prefixes and VNIs. | - | failure | Prefix: 192.168.10.0/24 VNI: 10 - No EVPN Type-5 routes found<br>Prefix: 192.168.20.0/24 VNI: 20 - No EVPN Type-5 routes found<br>Prefix: 192.168.30.0/24 VNI: 30 - No EVPN Type-5 routes found<br>Prefix: 192.168.40.0/24 VNI: 40 - No EVPN Type-5 routes found |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigDiffs | Verifies there is no difference between the running-config and the startup-config. | - | failure | --- flash:/startup-config<br>+++ system:/running-config<br>@@ -18,6 +18,7 @@<br> hostname leaf1-dc1<br> ip name-server vrf MGMT 10.14.0.1<br> dns domain fun.aristanetworks.com<br>+ip host vitthal 192.168.66.220<br> !<br> platform tfa<br> personality arfa<br> |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigLines | Search the Running-Config for the given RegEx patterns. | - | failure | Following patterns were not found: '^enable password.*$', 'bla bla' |
|
||||
| s1-spine1 | Connectivity | VerifyLLDPNeighbors | Verifies the connection status of the specified LLDP (Link Layer Discovery Protocol) neighbors. | - | failure | Port: Ethernet1 Neighbor: DC1-SPINE1 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: spine1-dc1.fun.aristanetworks.com/Ethernet3<br>Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: spine2-dc1.fun.aristanetworks.com/Ethernet3 |
|
||||
| s1-spine1 | Cvx | VerifyActiveCVXConnections | Verifies the number of active CVX Connections. | - | failure | 'show cvx connections brief' failed on s1-spine1: Unavailable command (controller not ready) (at token 2: 'connections') |
|
||||
| s1-spine1 | Cvx | VerifyCVXClusterStatus | Verifies the CVX Server Cluster status. | - | failure | CVX Server status is not enabled<br>CVX Server is not a cluster |
|
||||
| s1-spine1 | Cvx | VerifyManagementCVX | Verifies the management CVX global status. | - | failure | Management CVX status is not valid: Expected: enabled Actual: disabled |
|
||||
| s1-spine1 | Cvx | VerifyMcsClientMounts | Verify if all MCS client mounts are in mountStateMountComplete. | - | failure | MCS Client mount states are not present |
|
||||
| s1-spine1 | Cvx | VerifyMcsServerMounts | Verify if all MCS server mounts are in a MountComplete state. | - | failure | 'show cvx mounts' failed on s1-spine1: Unavailable command (controller not ready) (at token 2: 'mounts') |
|
||||
| s1-spine1 | Greent | VerifyGreenT | Verifies if a GreenT policy other than the default is created. | - | failure | No GreenT policy is created |
|
||||
| s1-spine1 | Greent | VerifyGreenTCounters | Verifies if the GreenT counters are incremented. | - | failure | GreenT counters are not incremented |
|
||||
| s1-spine1 | Interfaces | VerifyIPProxyARP | Verifies if Proxy ARP is enabled. | - | failure | Interface: Ethernet1 - Proxy-ARP disabled<br>Interface: Ethernet2 - Proxy-ARP disabled |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceIPv4 | Verifies the interface IPv4 addresses. | - | failure | Interface: Ethernet2 - IP address mismatch - Expected: 172.30.11.1/31 Actual: 10.100.0.11/31<br>Interface: Ethernet2 - Secondary IP address is not configured |
|
||||
| s1-spine1 | Interfaces | VerifyInterfacesSpeed | Verifies the speed, lanes, auto-negotiation status, and mode as full duplex for interfaces. | - | failure | Interface: Ethernet2 - Bandwidth mismatch - Expected: 10.0Gbps Actual: 1Gbps<br>Interface: Ethernet3 - Bandwidth mismatch - Expected: 100.0Gbps Actual: 1Gbps<br>Interface: Ethernet3 - Auto-negotiation mismatch - Expected: success Actual: unknown<br>Interface: Ethernet3 - Data lanes count mismatch - Expected: 1 Actual: 0<br>Interface: Ethernet2 - Bandwidth mismatch - Expected: 2.5Gbps Actual: 1Gbps |
|
||||
| s1-spine1 | Interfaces | VerifyInterfacesStatus | Verifies the operational states of specified interfaces to ensure they match expected configurations. | interface | failure | Port-Channel100 - Not configured<br>Ethernet49/1 - Not configured |
|
||||
| s1-spine1 | Interfaces | VerifyL2MTU | Verifies the global L2 MTU of all L2 interfaces. | - | failure | Interface: Ethernet3 - Incorrect MTU configured - Expected: 1500 Actual: 9214<br>Interface: Port-Channel5 - Incorrect MTU configured - Expected: 1500 Actual: 9214 |
|
||||
| s1-spine1 | Interfaces | VerifyL3MTU | Verifies the global L3 MTU of all L3 interfaces. | - | failure | Interface: Ethernet2 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Ethernet1 - Incorrect MTU - Expected: 2500 Actual: 9214<br>Interface: Loopback0 - Incorrect MTU - Expected: 1500 Actual: 65535<br>Interface: Loopback1 - Incorrect MTU - Expected: 1500 Actual: 65535<br>Interface: Vlan1006 - Incorrect MTU - Expected: 1500 Actual: 9164<br>Interface: Vlan1199 - Incorrect MTU - Expected: 1500 Actual: 9164<br>Interface: Vlan4093 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan4094 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan3019 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan3009 - Incorrect MTU - Expected: 1500 Actual: 9214 |
|
||||
| s1-spine1 | Interfaces | VerifyLACPInterfacesStatus | Verifies the Link Aggregation Control Protocol (LACP) status of the interface. | - | failure | Interface: Ethernet1 Port-Channel: Port-Channel100 - Not configured |
|
||||
| s1-spine1 | Interfaces | VerifyLoopbackCount | Verifies the number of loopback interfaces and their status. | - | failure | Loopback interface(s) count mismatch: Expected 3 Actual: 2 |
|
||||
| s1-spine1 | Logging | VerifyLoggingEntries | Verifies that the expected log string is present in the last specified log messages. | - | failure | Pattern: `.*ACCOUNTING-5-EXEC: cvpadmin ssh.*` - Not found in last 30 alerts log entries<br>Pattern: `.*SPANTREE-6-INTERFACE_ADD:.*` - Not found in last 10 critical log entries |
|
||||
| s1-spine1 | Logging | VerifyLoggingErrors | Verifies there are no syslog messages with a severity of ERRORS or higher. | - | failure | Device has reported syslog messages with a severity of ERRORS or higher:<br>Apr 29 08:01:27 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: sent to neighbor 10.100.4.5 (VRF data AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> Apr 29 08:01:27 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: sent to neighbor 10.100.4.5 (VRF guest AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> Apr 29 08:01:29 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: received from neighbor 10.100.4.5 (VRF guest AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> <br> |
|
||||
| s1-spine1 | Logging | VerifyLoggingHostname | Verifies if logs are generated with the device FQDN. | - | failure | Logs are not generated with the device FQDN |
|
||||
| s1-spine1 | Logging | VerifyLoggingHosts | Verifies logging hosts (syslog servers) for a specified VRF. | - | failure | Syslog servers 1.1.1.1, 2.2.2.2 are not configured in VRF default |
|
||||
| s1-spine1 | Logging | VerifyLoggingPersistent | Verifies if logging persistent is enabled and logs are saved in flash. | - | failure | Persistent logging is disabled |
|
||||
| s1-spine1 | Logging | VerifyLoggingSourceIntf | Verifies logging source-interface for a specified VRF. | - | failure | Source-interface: Management0 VRF: default - Not configured |
|
||||
| s1-spine1 | Logging | VerifyLoggingTimestamp | Verifies if logs are generated with the appropriate timestamp. | - | failure | Logs are not generated with the appropriate timestamp format |
|
||||
| s1-spine1 | MLAG | VerifyMlagDualPrimary | Verifies the MLAG dual-primary detection parameters. | - | failure | Dual-primary detection is disabled |
|
||||
| s1-spine1 | MLAG | VerifyMlagPrimaryPriority | Verifies the configuration of the MLAG primary priority. | - | failure | MLAG primary priority mismatch - Expected: 3276 Actual: 32767 |
|
||||
| s1-spine1 | Multicast | VerifyIGMPSnoopingVlans | Verifies the IGMP snooping status for the provided VLANs. | - | failure | VLAN10 - Incorrect IGMP state - Expected: disabled Actual: enabled<br>Supplied vlan 12 is not present on the device |
|
||||
| s1-spine1 | Routing | VerifyIPv4RouteType | Verifies the route-type of the IPv4 prefixes. | - | failure | Prefix: 10.100.0.12/31 VRF: default - Route not found<br>Prefix: 10.100.1.5/32 VRF: default - Incorrect route type - Expected: iBGP Actual: connected |
|
||||
| s1-spine1 | Routing | VerifyRoutingStatus | Verifies the routing status for IPv4/IPv6 unicast, multicast, and IPv6 interfaces (RFC5549). | - | failure | IPv6 unicast routing enabled status mismatch - Expected: True Actual: False |
|
||||
| s1-spine1 | Routing | VerifyRoutingTableEntry | Verifies that the provided routes are present in the routing table of a specified VRF. | - | failure | The following route(s) are missing from the routing table of VRF default: 10.1.0.1, 10.1.0.2 |
|
||||
| s1-spine1 | Routing | VerifyRoutingTableSize | Verifies the size of the IP routing table of the default VRF. | - | failure | Routing table routes are outside the routes range - Expected: 2 <= to >= 20 Actual: 35 |
|
||||
| s1-spine1 | Security | VerifyAPIHttpsSSL | Verifies if the eAPI has a valid SSL profile. | - | failure | eAPI HTTPS server SSL profile default is not configured |
|
||||
| s1-spine1 | Security | VerifyAPIIPv4Acl | Verifies if eAPI has the right number IPv4 ACL(s) configured for a specified VRF. | - | failure | VRF: default - eAPI IPv4 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifyAPIIPv6Acl | Verifies if eAPI has the right number IPv6 ACL(s) configured for a specified VRF. | - | failure | VRF: default - eAPI IPv6 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifyBannerLogin | Verifies the login banner of a device. | - | failure | Login banner is not configured |
|
||||
| s1-spine1 | Security | VerifyBannerMotd | Verifies the motd banner of a device. | - | failure | MOTD banner is not configured |
|
||||
| s1-spine1 | Security | VerifyHardwareEntropy | Verifies hardware entropy generation is enabled on device. | - | failure | Hardware entropy generation is disabled |
|
||||
| s1-spine1 | Security | VerifyIPSecConnHealth | Verifies all IPv4 security connections. | - | failure | No IPv4 security connection configured |
|
||||
| s1-spine1 | Security | VerifyIPv4ACL | Verifies the configuration of IPv4 ACLs. | - | failure | ACL name: LabTest - Not configured |
|
||||
| s1-spine1 | Security | VerifySSHIPv4Acl | Verifies if the SSHD agent has IPv4 ACL(s) configured. | - | failure | VRF: default - SSH IPv4 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifySSHIPv6Acl | Verifies if the SSHD agent has IPv6 ACL(s) configured. | - | failure | VRF: default - SSH IPv6 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifySSHStatus | Verifies if the SSHD agent is disabled in the default VRF. | - | failure | SSHD status for Default VRF is enabled |
|
||||
| s1-spine1 | Security | VerifySpecificIPSecConn | Verifies the IPv4 security connections. | - | failure | Peer: 10.255.0.1 VRF: default - Not configured<br>Peer: 10.255.0.2 VRF: default - Not configured |
|
||||
| s1-spine1 | Services | VerifyDNSServers | Verifies if the DNS (Domain Name Service) servers are correctly configured. | - | failure | Server 10.14.0.1 VRF: default Priority: 1 - Not configured<br>Server 10.14.0.11 VRF: MGMT Priority: 0 - Not configured |
|
||||
| s1-spine1 | Services | VerifyErrdisableRecovery | Verifies the error disable recovery functionality. | - | failure | Reason: acl Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300<br>Reason: bpduguard Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300 |
|
||||
| s1-spine1 | Services | VerifyHostname | Verifies the hostname of a device. | - | failure | Incorrect Hostname - Expected: s1-spine1 Actual: leaf1-dc1 |
|
||||
| s1-spine1 | SNMP | VerifySnmpContact | Verifies the SNMP contact of a device. | - | failure | SNMP contact is not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpErrorCounters | Verifies the SNMP error counters. | - | failure | SNMP counters not found |
|
||||
| s1-spine1 | SNMP | VerifySnmpGroup | Verifies the SNMP group configurations for specified version(s). | - | failure | Group: Group1 Version: v1 - Not configured<br>Group: Group2 Version: v3 - Not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpHostLogging | Verifies SNMP logging configurations. | - | failure | SNMP logging is disabled |
|
||||
| s1-spine1 | SNMP | VerifySnmpIPv4Acl | Verifies if the SNMP agent has IPv4 ACL(s) configured. | - | failure | VRF: default - Incorrect SNMP IPv4 ACL(s) - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | SNMP | VerifySnmpIPv6Acl | Verifies if the SNMP agent has IPv6 ACL(s) configured. | - | failure | VRF: default - Incorrect SNMP IPv6 ACL(s) - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | SNMP | VerifySnmpLocation | Verifies the SNMP location of a device. | - | failure | SNMP location is not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpNotificationHost | Verifies the SNMP notification host(s) (SNMP manager) configurations. | - | failure | No SNMP host is configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpPDUCounters | Verifies the SNMP PDU counters. | - | failure | SNMP counters not found |
|
||||
| s1-spine1 | SNMP | VerifySnmpSourceInterface | Verifies SNMP source interfaces. | - | failure | SNMP source interface(s) not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpStatus | Verifies if the SNMP agent is enabled. | - | failure | VRF: default - SNMP agent disabled |
|
||||
| s1-spine1 | SNMP | VerifySnmpUser | Verifies the SNMP user configurations. | - | failure | User: test Group: test_group Version: v3 - Not found |
|
||||
| s1-spine1 | Software | VerifyEOSVersion | Verifies the EOS version of the device. | - | failure | EOS version mismatch - Actual: 4.31.0F-33804048.4310F (engineering build) not in Expected: 4.25.4M, 4.26.1F |
|
||||
| s1-spine1 | Software | VerifyTerminAttrVersion | Verifies the TerminAttr version of the device. | - | failure | TerminAttr version mismatch - Actual: v1.29.0 not in Expected: v1.13.6, v1.8.0 |
|
||||
| s1-spine1 | STP | VerifySTPDisabledVlans | Verifies the STP disabled VLAN(s). | - | failure | VLAN: 6 - Not configured |
|
||||
| s1-spine1 | STP | VerifySTPMode | Verifies the configured STP mode for a provided list of VLAN(s). | - | failure | VLAN 10 - Incorrect STP mode - Expected: rapidPvst Actual: mstp<br>VLAN 20 - Incorrect STP mode - Expected: rapidPvst Actual: mstp |
|
||||
| s1-spine1 | STP | VerifySTPRootPriority | Verifies the STP root priority for a provided list of VLAN or MST instance ID(s). | - | failure | Instance: MST10 - Not configured<br>Instance: MST20 - Not configured |
|
||||
| s1-spine1 | STUN | VerifyStunClient | (Deprecated) Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found |
|
||||
| s1-spine1 | STUN | VerifyStunClientTranslation | Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found<br>Client 100.64.3.2 Port: 4500 - STUN client translation not found |
|
||||
| s1-spine1 | STUN | VerifyStunServer | Verifies the STUN server status is enabled and running. | - | failure | STUN server status is disabled and not running |
|
||||
| s1-spine1 | VLAN | VerifyDynamicVlanSource | Verifies dynamic VLAN allocation for specified VLAN sources. | - | failure | Dynamic VLAN source(s) exist but have no VLANs allocated: mlagsync |
|
||||
| s1-spine1 | VLAN | VerifyVlanInternalPolicy | Verifies the VLAN internal allocation policy and the range of VLANs. | - | failure | VLAN internal allocation policy: ascending - Incorrect end VLAN id configured - Expected: 4094 Actual: 1199 |
|
||||
| s1-spine1 | VLAN | VerifyVlanStatus | Verifies the administrative status of specified VLANs. | - | failure | VLAN: Vlan10 - Incorrect administrative status - Expected: suspended Actual: active |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanVniBinding | Verifies the VNI-VLAN, VNI-VRF bindings of the Vxlan1 interface. | - | failure | Interface: Vxlan1 VNI: 500 - Binding not found |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanVtep | Verifies Vxlan1 VTEP peers. | - | failure | The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.5, 10.1.1.6<br>Unexpected VTEP peer(s) on Vxlan1 interface: 10.100.2.3 |
|
||||
|
||||
## Test Results
|
||||
|
||||
| Device Under Test | Categories | Test | Description | Custom Field | Result | Messages |
|
||||
| ----------------- | ---------- | ---- | ----------- | ------------ | ------ | -------- |
|
||||
| s1-spine1 | AAA | VerifyAcctConsoleMethods | Verifies the AAA accounting console method lists for different accounting types (system, exec, commands, dot1x). | - | failure | AAA console accounting is not configured for commands, exec, system, dot1x |
|
||||
| s1-spine1 | AAA | VerifyAcctDefaultMethods | Verifies the AAA accounting default method lists for different accounting types (system, exec, commands, dot1x). | - | failure | AAA default accounting is not configured for commands, exec, system, dot1x |
|
||||
| s1-spine1 | AAA | VerifyAuthenMethods | Verifies the AAA authentication method lists for different authentication types (login, enable, dot1x). | - | failure | AAA authentication methods are not configured for login console |
|
||||
| s1-spine1 | AAA | VerifyAuthzMethods | Verifies the AAA authorization method lists for different authorization types (commands, exec). | - | failure | AAA authorization methods local, none, logging are not matching for commands, exec |
|
||||
| s1-spine1 | AAA | VerifyTacacsServerGroups | Verifies if the provided TACACS server group(s) are configured. | - | failure | No TACACS server group(s) are configured |
|
||||
| s1-spine1 | AAA | VerifyTacacsServers | Verifies TACACS servers are configured for a specified VRF. | - | failure | No TACACS servers are configured |
|
||||
| s1-spine1 | AAA | VerifyTacacsSourceIntf | Verifies TACACS source-interface for a specified VRF. | - | failure | VRF: MGMT Source Interface: Management0 - Not configured |
|
||||
| s1-spine1 | AVT | VerifyAVTPathHealth | Verifies the status of all AVT paths for all VRFs. | - | skipped | VerifyAVTPathHealth test is not supported on cEOSLab |
|
||||
| s1-spine1 | AVT | VerifyAVTRole | Verifies the AVT role of a device. | - | skipped | VerifyAVTRole test is not supported on cEOSLab |
|
||||
| s1-spine1 | AVT | VerifyAVTSpecificPath | Verifies the Adaptive Virtual Topology (AVT) path. | - | skipped | VerifyAVTSpecificPath test is not supported on cEOSLab |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersHealth | Verifies the health of IPv4 BFD peers across all VRFs. | - | success | - |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersIntervals | Verifies the timers of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.8 VRF: default - Not found<br>Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BFD | VerifyBFDPeersRegProtocols | Verifies the registered routing protocol of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BFD | VerifyBFDSpecificPeers | Verifies the state of IPv4 BFD peer sessions. | - | failure | Peer: 192.0.255.8 VRF: default - Not found<br>Peer: 192.0.255.7 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPAdvCommunities | Verifies the advertised communities of BGP peers. | - | failure | Peer: 172.30.11.17 VRF: default - Not found<br>Peer: 172.30.11.21 VRF: MGMT - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPExchangedRoutes | Verifies the advertised and received routes of BGP IPv4 peer(s). | - | failure | Peer: 172.30.255.5 VRF: default Advertised route: 192.0.254.5/32 - Not found<br>Peer: 172.30.255.5 VRF: default Received route: 192.0.255.4/32 - Not found<br>Peer: 172.30.255.1 VRF: default Advertised route: 192.0.255.1/32 - Not found<br>Peer: 172.30.255.1 VRF: default Advertised route: 192.0.254.5/32 - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPNlriAcceptance | Verifies that all received NLRI are accepted for all AFI/SAFI configured for BGP peers. | - | failure | Peer: 10.100.0.128 VRF: default - Not found<br>Peer: 2001:db8:1::2 VRF: default - Not found<br>Peer: fe80::2%Et1 VRF: default - Not found<br>Peer: fe80::2%Et1 VRF: default - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerASNCap | Verifies the four octet ASN capability of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerCount | Verifies the count of BGP peers for given address families. | - | failure | AFI: ipv4 SAFI: unicast VRF: PROD - VRF not configured<br>AFI: ipv4 SAFI: multicast VRF: DEV - VRF not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerDropStats | Verifies BGP NLRI drop statistics of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerGroup | Verifies BGP peer group of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerMD5Auth | Verifies the MD5 authentication and state of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.5 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: default - Session does not have MD5 authentication enabled |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerMPCaps | Verifies the multiprotocol capabilities of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: default - ipv4MplsLabels not found<br>Interface: Ethernet1 VRF: default - ipv4MplsVpn not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerRouteLimit | Verifies maximum routes and warning limit for BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerRouteRefreshCap | Verifies the route refresh capabilities of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerSession | Verifies the session state of BGP peers. | - | failure | Peer: 10.1.0.1 VRF: default - Not found<br>Peer: 10.1.0.2 VRF: default - Not found<br>Peer: 10.1.255.2 VRF: DEV - Not found<br>Peer: 10.1.255.4 VRF: DEV - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Vlan3499 VRF: PROD - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerSessionRibd | Verifies the session state of BGP peers. | - | failure | Peer: 10.1.0.1 VRF: default - Not found<br>Peer: 10.1.255.4 VRF: DEV - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerTtlMultiHops | Verifies BGP TTL and max-ttl-hops count for BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.2 VRF: test - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeerUpdateErrors | Verifies BGP update error counters of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBGPPeersHealth | Verifies the health of BGP peers for given address families. | - | failure | AFI: ipv6 SAFI: unicast VRF: DEV - VRF not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPPeersHealthRibd | Verifies the health of all the BGP peers. | - | success | - |
|
||||
| s1-spine1 | BGP | VerifyBGPRedistribution | Verifies BGP redistribution. | - | error | show bgp instance vrf all has failed: Invalid requested version for ModelMetaClass: no such revision 4, most current is 3 |
|
||||
| s1-spine1 | BGP | VerifyBGPRouteECMP | Verifies BGP IPv4 route ECMP paths. | - | success | - |
|
||||
| s1-spine1 | BGP | VerifyBGPRoutePaths | Verifies BGP IPv4 route paths. | - | success | - |
|
||||
| s1-spine1 | BGP | VerifyBGPSpecificPeers | Verifies the health of specific BGP peer(s) for given address families. | - | failure | AFI: evpn Peer: 10.1.0.1 - Not configured<br>AFI: evpn Peer: 10.1.0.2 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.254.1 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.0 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.2 - Not configured<br>AFI: ipv4 SAFI: unicast VRF: default Peer: 10.1.255.4 - Not configured |
|
||||
| s1-spine1 | BGP | VerifyBGPTimers | Verifies the timers of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: 172.30.11.5 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyBgpRouteMaps | Verifies BGP inbound and outbound route-maps of BGP peers. | - | failure | Peer: 172.30.11.1 VRF: default - Not found<br>Peer: fd00:dc:1::1 VRF: default - Not found<br>Interface: Ethernet1 VRF: MGMT - Not found |
|
||||
| s1-spine1 | BGP | VerifyEVPNType2Route | Verifies the EVPN Type-2 routes for a given IPv4 or MAC address and VNI. | - | failure | Address: 192.168.20.102 VNI: 10020 - No EVPN Type-2 route<br>Address: aa:c1:ab:5d:b4:1e VNI: 10010 - No EVPN Type-2 route |
|
||||
| s1-spine1 | BGP | VerifyEVPNType5Routes | Verifies EVPN Type-5 routes for given IP prefixes and VNIs. | - | failure | Prefix: 192.168.10.0/24 VNI: 10 - No EVPN Type-5 routes found<br>Prefix: 192.168.20.0/24 VNI: 20 - No EVPN Type-5 routes found<br>Prefix: 192.168.30.0/24 VNI: 30 - No EVPN Type-5 routes found<br>Prefix: 192.168.40.0/24 VNI: 40 - No EVPN Type-5 routes found |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigDiffs | Verifies there is no difference between the running-config and the startup-config. | - | failure | --- flash:/startup-config<br>+++ system:/running-config<br>@@ -18,6 +18,7 @@<br> hostname leaf1-dc1<br> ip name-server vrf MGMT 10.14.0.1<br> dns domain fun.aristanetworks.com<br>+ip host vitthal 192.168.66.220<br> !<br> platform tfa<br> personality arfa<br> |
|
||||
| s1-spine1 | Configuration | VerifyRunningConfigLines | Search the Running-Config for the given RegEx patterns. | - | failure | Following patterns were not found: '^enable password.*$', 'bla bla' |
|
||||
| s1-spine1 | Configuration | VerifyZeroTouch | Verifies ZeroTouch is disabled. | - | success | - |
|
||||
| s1-spine1 | Connectivity | VerifyLLDPNeighbors | Verifies the connection status of the specified LLDP (Link Layer Discovery Protocol) neighbors. | - | failure | Port: Ethernet1 Neighbor: DC1-SPINE1 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: spine1-dc1.fun.aristanetworks.com/Ethernet3<br>Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: spine2-dc1.fun.aristanetworks.com/Ethernet3 |
|
||||
| s1-spine1 | Connectivity | VerifyReachability | Test network reachability to one or many destination IP(s). | - | success | - |
|
||||
| s1-spine1 | Cvx | VerifyActiveCVXConnections | Verifies the number of active CVX Connections. | - | failure | 'show cvx connections brief' failed on s1-spine1: Unavailable command (controller not ready) (at token 2: 'connections') |
|
||||
| s1-spine1 | Cvx | VerifyCVXClusterStatus | Verifies the CVX Server Cluster status. | - | failure | CVX Server status is not enabled<br>CVX Server is not a cluster |
|
||||
| s1-spine1 | Cvx | VerifyManagementCVX | Verifies the management CVX global status. | - | failure | Management CVX status is not valid: Expected: enabled Actual: disabled |
|
||||
| s1-spine1 | Cvx | VerifyMcsClientMounts | Verify if all MCS client mounts are in mountStateMountComplete. | - | failure | MCS Client mount states are not present |
|
||||
| s1-spine1 | Cvx | VerifyMcsServerMounts | Verify if all MCS server mounts are in a MountComplete state. | - | failure | 'show cvx mounts' failed on s1-spine1: Unavailable command (controller not ready) (at token 2: 'mounts') |
|
||||
| s1-spine1 | Field Notices | VerifyFieldNotice44Resolution | Verifies that the device is using the correct Aboot version per FN0044. | - | skipped | VerifyFieldNotice44Resolution test is not supported on cEOSLab |
|
||||
| s1-spine1 | Field Notices | VerifyFieldNotice72Resolution | Verifies if the device is exposed to FN0072, and if the issue has been mitigated. | - | skipped | VerifyFieldNotice72Resolution test is not supported on cEOSLab |
|
||||
| s1-spine1 | Flow Tracking | VerifyHardwareFlowTrackerStatus | Verifies the hardware flow tracking state. | - | skipped | VerifyHardwareFlowTrackerStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | Greent | VerifyGreenT | Verifies if a GreenT policy other than the default is created. | - | failure | No GreenT policy is created |
|
||||
| s1-spine1 | Greent | VerifyGreenTCounters | Verifies if the GreenT counters are incremented. | - | failure | GreenT counters are not incremented |
|
||||
| s1-spine1 | Hardware | VerifyAdverseDrops | Verifies there are no adverse drops on DCS-7280 and DCS-7500 family switches. | - | skipped | VerifyAdverseDrops test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyEnvironmentCooling | Verifies the status of power supply fans and all fan trays. | - | skipped | VerifyEnvironmentCooling test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyEnvironmentPower | Verifies the power supplies status. | - | skipped | VerifyEnvironmentPower test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyEnvironmentSystemCooling | Verifies the device's system cooling status. | - | skipped | VerifyEnvironmentSystemCooling test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyTemperature | Verifies if the device temperature is within acceptable limits. | - | skipped | VerifyTemperature test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyTransceiversManufacturers | Verifies if all the transceivers come from approved manufacturers. | - | skipped | VerifyTransceiversManufacturers test is not supported on cEOSLab |
|
||||
| s1-spine1 | Hardware | VerifyTransceiversTemperature | Verifies if all the transceivers are operating at an acceptable temperature. | - | skipped | VerifyTransceiversTemperature test is not supported on cEOSLab |
|
||||
| s1-spine1 | Interfaces | VerifyIPProxyARP | Verifies if Proxy ARP is enabled. | - | failure | Interface: Ethernet1 - Proxy-ARP disabled<br>Interface: Ethernet2 - Proxy-ARP disabled |
|
||||
| s1-spine1 | Interfaces | VerifyIllegalLACP | Verifies there are no illegal LACP packets in all port channels. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceErrDisabled | Verifies there are no interfaces in the errdisabled state. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceErrors | Verifies that the interfaces error counters are equal to zero. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceIPv4 | Verifies the interface IPv4 addresses. | - | failure | Interface: Ethernet2 - IP address mismatch - Expected: 172.30.11.1/31 Actual: 10.100.0.11/31<br>Interface: Ethernet2 - Secondary IP address is not configured |
|
||||
| s1-spine1 | Interfaces | VerifyInterfaceUtilization | Verifies that the utilization of interfaces is below a certain threshold. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyInterfacesSpeed | Verifies the speed, lanes, auto-negotiation status, and mode as full duplex for interfaces. | - | failure | Interface: Ethernet2 - Bandwidth mismatch - Expected: 10.0Gbps Actual: 1Gbps<br>Interface: Ethernet3 - Bandwidth mismatch - Expected: 100.0Gbps Actual: 1Gbps<br>Interface: Ethernet3 - Auto-negotiation mismatch - Expected: success Actual: unknown<br>Interface: Ethernet3 - Data lanes count mismatch - Expected: 1 Actual: 0<br>Interface: Ethernet2 - Bandwidth mismatch - Expected: 2.5Gbps Actual: 1Gbps |
|
||||
| s1-spine1 | Interfaces | VerifyInterfacesStatus | Verifies the operational states of specified interfaces to ensure they match expected configurations. | interface | failure | Port-Channel100 - Not configured<br>Ethernet49/1 - Not configured |
|
||||
| s1-spine1 | Interfaces | VerifyIpVirtualRouterMac | Verifies the IP virtual router MAC address. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyL2MTU | Verifies the global L2 MTU of all L2 interfaces. | - | failure | Interface: Ethernet3 - Incorrect MTU configured - Expected: 1500 Actual: 9214<br>Interface: Port-Channel5 - Incorrect MTU configured - Expected: 1500 Actual: 9214 |
|
||||
| s1-spine1 | Interfaces | VerifyL3MTU | Verifies the global L3 MTU of all L3 interfaces. | - | failure | Interface: Ethernet2 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Ethernet1 - Incorrect MTU - Expected: 2500 Actual: 9214<br>Interface: Loopback0 - Incorrect MTU - Expected: 1500 Actual: 65535<br>Interface: Loopback1 - Incorrect MTU - Expected: 1500 Actual: 65535<br>Interface: Vlan1006 - Incorrect MTU - Expected: 1500 Actual: 9164<br>Interface: Vlan1199 - Incorrect MTU - Expected: 1500 Actual: 9164<br>Interface: Vlan4093 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan4094 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan3019 - Incorrect MTU - Expected: 1500 Actual: 9214<br>Interface: Vlan3009 - Incorrect MTU - Expected: 1500 Actual: 9214 |
|
||||
| s1-spine1 | Interfaces | VerifyLACPInterfacesStatus | Verifies the Link Aggregation Control Protocol (LACP) status of the interface. | - | failure | Interface: Ethernet1 Port-Channel: Port-Channel100 - Not configured |
|
||||
| s1-spine1 | Interfaces | VerifyLoopbackCount | Verifies the number of loopback interfaces and their status. | - | failure | Loopback interface(s) count mismatch: Expected 3 Actual: 2 |
|
||||
| s1-spine1 | Interfaces | VerifyPortChannels | Verifies there are no inactive ports in all port channels. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifySVI | Verifies the status of all SVIs. | - | success | - |
|
||||
| s1-spine1 | Interfaces | VerifyStormControlDrops | Verifies there are no interface storm-control drop counters. | - | skipped | VerifyStormControlDrops test is not supported on cEOSLab |
|
||||
| s1-spine1 | ISIS | VerifyISISGracefulRestart | Verifies the IS-IS graceful restart feature. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS | VerifyISISInterfaceMode | Verifies IS-IS interfaces are running in the correct mode. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS | VerifyISISNeighborCount | Verifies the number of IS-IS neighbors per interface and level. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS | VerifyISISNeighborState | Verifies the health of IS-IS neighbors. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS, Segment-Routing | VerifyISISSegmentRoutingAdjacencySegments | Verifies IS-IS segment routing adjacency segments. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS, Segment-Routing | VerifyISISSegmentRoutingDataplane | Verifies IS-IS segment routing data-plane configuration. | - | skipped | IS-IS not configured |
|
||||
| s1-spine1 | ISIS, Segment-Routing | VerifyISISSegmentRoutingTunnels | Verify ISIS-SR tunnels computed by device. | - | skipped | IS-IS-SR not configured |
|
||||
| s1-spine1 | LANZ | VerifyLANZ | Verifies if LANZ is enabled. | - | skipped | VerifyLANZ test is not supported on cEOSLab |
|
||||
| s1-spine1 | Logging | VerifyLoggingAccounting | Verifies if AAA accounting logs are generated. | - | success | - |
|
||||
| s1-spine1 | Logging | VerifyLoggingEntries | Verifies that the expected log string is present in the last specified log messages. | - | failure | Pattern: `.*ACCOUNTING-5-EXEC: cvpadmin ssh.*` - Not found in last 30 alerts log entries<br>Pattern: `.*SPANTREE-6-INTERFACE_ADD:.*` - Not found in last 10 critical log entries |
|
||||
| s1-spine1 | Logging | VerifyLoggingErrors | Verifies there are no syslog messages with a severity of ERRORS or higher. | - | failure | Device has reported syslog messages with a severity of ERRORS or higher:<br>Apr 29 08:01:27 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: sent to neighbor 10.100.4.5 (VRF data AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> Apr 29 08:01:27 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: sent to neighbor 10.100.4.5 (VRF guest AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> Apr 29 08:01:29 leaf1-dc1 Bgp: %BGP-3-NOTIFICATION: received from neighbor 10.100.4.5 (VRF guest AS 65102) 6/7 (Cease/connection collision resolution) 0 bytes <br> <br> |
|
||||
| s1-spine1 | Logging | VerifyLoggingHostname | Verifies if logs are generated with the device FQDN. | - | failure | Logs are not generated with the device FQDN |
|
||||
| s1-spine1 | Logging | VerifyLoggingHosts | Verifies logging hosts (syslog servers) for a specified VRF. | - | failure | Syslog servers 1.1.1.1, 2.2.2.2 are not configured in VRF default |
|
||||
| s1-spine1 | Logging | VerifyLoggingLogsGeneration | Verifies if logs are generated. | - | success | - |
|
||||
| s1-spine1 | Logging | VerifyLoggingPersistent | Verifies if logging persistent is enabled and logs are saved in flash. | - | failure | Persistent logging is disabled |
|
||||
| s1-spine1 | Logging | VerifyLoggingSourceIntf | Verifies logging source-interface for a specified VRF. | - | failure | Source-interface: Management0 VRF: default - Not configured |
|
||||
| s1-spine1 | Logging | VerifyLoggingTimestamp | Verifies if logs are generated with the appropriate timestamp. | - | failure | Logs are not generated with the appropriate timestamp format |
|
||||
| s1-spine1 | Logging | VerifySyslogLogging | Verifies if syslog logging is enabled. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagConfigSanity | Verifies there are no MLAG config-sanity inconsistencies. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagDualPrimary | Verifies the MLAG dual-primary detection parameters. | - | failure | Dual-primary detection is disabled |
|
||||
| s1-spine1 | MLAG | VerifyMlagInterfaces | Verifies there are no inactive or active-partial MLAG ports. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagPrimaryPriority | Verifies the configuration of the MLAG primary priority. | - | failure | MLAG primary priority mismatch - Expected: 3276 Actual: 32767 |
|
||||
| s1-spine1 | MLAG | VerifyMlagReloadDelay | Verifies the reload-delay parameters of the MLAG configuration. | - | success | - |
|
||||
| s1-spine1 | MLAG | VerifyMlagStatus | Verifies the health status of the MLAG configuration. | - | success | - |
|
||||
| s1-spine1 | Multicast | VerifyIGMPSnoopingGlobal | Verifies the IGMP snooping global status. | - | success | - |
|
||||
| s1-spine1 | Multicast | VerifyIGMPSnoopingVlans | Verifies the IGMP snooping status for the provided VLANs. | - | failure | VLAN10 - Incorrect IGMP state - Expected: disabled Actual: enabled<br>Supplied vlan 12 is not present on the device |
|
||||
| s1-spine1 | OSPF | VerifyOSPFMaxLSA | Verifies all OSPF instances did not cross the maximum LSA threshold. | - | skipped | OSPF not configured |
|
||||
| s1-spine1 | OSPF | VerifyOSPFNeighborCount | Verifies the number of OSPF neighbors in FULL state is the one we expect. | - | skipped | OSPF not configured |
|
||||
| s1-spine1 | OSPF | VerifyOSPFNeighborState | Verifies all OSPF neighbors are in FULL state. | - | skipped | OSPF not configured |
|
||||
| s1-spine1 | Path-Selection | VerifyPathsHealth | Verifies the path and telemetry state of all paths under router path-selection. | - | skipped | VerifyPathsHealth test is not supported on cEOSLab |
|
||||
| s1-spine1 | Path-Selection | VerifySpecificPath | Verifies the DPS path and telemetry state of an IPv4 peer. | - | skipped | VerifySpecificPath test is not supported on cEOSLab |
|
||||
| s1-spine1 | Profiles | VerifyTcamProfile | Verifies the device TCAM profile. | - | skipped | VerifyTcamProfile test is not supported on cEOSLab |
|
||||
| s1-spine1 | Profiles | VerifyUnifiedForwardingTableMode | Verifies the device is using the expected UFT mode. | - | skipped | VerifyUnifiedForwardingTableMode test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpGMStatus | Verifies that the device is locked to a valid PTP Grandmaster. | - | skipped | VerifyPtpGMStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpLockStatus | Verifies that the device was locked to the upstream PTP GM in the last minute. | - | skipped | VerifyPtpLockStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpModeStatus | Verifies that the device is configured as a PTP Boundary Clock. | - | skipped | VerifyPtpModeStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpOffset | Verifies that the PTP timing offset is within +/- 1000ns from the master clock. | - | skipped | VerifyPtpOffset test is not supported on cEOSLab |
|
||||
| s1-spine1 | PTP | VerifyPtpPortModeStatus | Verifies the PTP interfaces state. | - | skipped | VerifyPtpPortModeStatus test is not supported on cEOSLab |
|
||||
| s1-spine1 | Routing | VerifyIPv4RouteNextHops | Verifies the next-hops of the IPv4 prefixes. | - | success | - |
|
||||
| s1-spine1 | Routing | VerifyIPv4RouteType | Verifies the route-type of the IPv4 prefixes. | - | failure | Prefix: 10.100.0.12/31 VRF: default - Route not found<br>Prefix: 10.100.1.5/32 VRF: default - Incorrect route type - Expected: iBGP Actual: connected |
|
||||
| s1-spine1 | Routing | VerifyRoutingProtocolModel | Verifies the configured routing protocol model. | - | success | - |
|
||||
| s1-spine1 | Routing | VerifyRoutingStatus | Verifies the routing status for IPv4/IPv6 unicast, multicast, and IPv6 interfaces (RFC5549). | - | failure | IPv6 unicast routing enabled status mismatch - Expected: True Actual: False |
|
||||
| s1-spine1 | Routing | VerifyRoutingTableEntry | Verifies that the provided routes are present in the routing table of a specified VRF. | - | failure | The following route(s) are missing from the routing table of VRF default: 10.1.0.1, 10.1.0.2 |
|
||||
| s1-spine1 | Routing | VerifyRoutingTableSize | Verifies the size of the IP routing table of the default VRF. | - | failure | Routing table routes are outside the routes range - Expected: 2 <= to >= 20 Actual: 35 |
|
||||
| s1-spine1 | Security | VerifyAPIHttpStatus | Verifies if eAPI HTTP server is disabled globally. | - | success | - |
|
||||
| s1-spine1 | Security | VerifyAPIHttpsSSL | Verifies if the eAPI has a valid SSL profile. | - | failure | eAPI HTTPS server SSL profile default is not configured |
|
||||
| s1-spine1 | Security | VerifyAPIIPv4Acl | Verifies if eAPI has the right number IPv4 ACL(s) configured for a specified VRF. | - | failure | VRF: default - eAPI IPv4 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifyAPIIPv6Acl | Verifies if eAPI has the right number IPv6 ACL(s) configured for a specified VRF. | - | failure | VRF: default - eAPI IPv6 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifyAPISSLCertificate | Verifies the eAPI SSL certificate expiry, common subject name, encryption algorithm and key size. | - | success | - |
|
||||
| s1-spine1 | Security | VerifyBannerLogin | Verifies the login banner of a device. | - | failure | Login banner is not configured |
|
||||
| s1-spine1 | Security | VerifyBannerMotd | Verifies the motd banner of a device. | - | failure | MOTD banner is not configured |
|
||||
| s1-spine1 | Security | VerifyHardwareEntropy | Verifies hardware entropy generation is enabled on device. | - | failure | Hardware entropy generation is disabled |
|
||||
| s1-spine1 | Security | VerifyIPSecConnHealth | Verifies all IPv4 security connections. | - | failure | No IPv4 security connection configured |
|
||||
| s1-spine1 | Security | VerifyIPv4ACL | Verifies the configuration of IPv4 ACLs. | - | failure | ACL name: LabTest - Not configured |
|
||||
| s1-spine1 | Security | VerifySSHIPv4Acl | Verifies if the SSHD agent has IPv4 ACL(s) configured. | - | failure | VRF: default - SSH IPv4 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifySSHIPv6Acl | Verifies if the SSHD agent has IPv6 ACL(s) configured. | - | failure | VRF: default - SSH IPv6 ACL(s) count mismatch - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | Security | VerifySSHStatus | Verifies if the SSHD agent is disabled in the default VRF. | - | failure | SSHD status for Default VRF is enabled |
|
||||
| s1-spine1 | Security | VerifySpecificIPSecConn | Verifies the IPv4 security connections. | - | failure | Peer: 10.255.0.1 VRF: default - Not configured<br>Peer: 10.255.0.2 VRF: default - Not configured |
|
||||
| s1-spine1 | Security | VerifyTelnetStatus | Verifies if Telnet is disabled in the default VRF. | - | success | - |
|
||||
| s1-spine1 | Services | VerifyDNSLookup | Verifies the DNS name to IP address resolution. | - | success | - |
|
||||
| s1-spine1 | Services | VerifyDNSServers | Verifies if the DNS (Domain Name Service) servers are correctly configured. | - | failure | Server 10.14.0.1 VRF: default Priority: 1 - Not configured<br>Server 10.14.0.11 VRF: MGMT Priority: 0 - Not configured |
|
||||
| s1-spine1 | Services | VerifyErrdisableRecovery | Verifies the error disable recovery functionality. | - | failure | Reason: acl Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300<br>Reason: bpduguard Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300 |
|
||||
| s1-spine1 | Services | VerifyHostname | Verifies the hostname of a device. | - | failure | Incorrect Hostname - Expected: s1-spine1 Actual: leaf1-dc1 |
|
||||
| s1-spine1 | SNMP | VerifySnmpContact | Verifies the SNMP contact of a device. | - | failure | SNMP contact is not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpErrorCounters | Verifies the SNMP error counters. | - | failure | SNMP counters not found |
|
||||
| s1-spine1 | SNMP | VerifySnmpGroup | Verifies the SNMP group configurations for specified version(s). | - | failure | Group: Group1 Version: v1 - Not configured<br>Group: Group2 Version: v3 - Not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpHostLogging | Verifies SNMP logging configurations. | - | failure | SNMP logging is disabled |
|
||||
| s1-spine1 | SNMP | VerifySnmpIPv4Acl | Verifies if the SNMP agent has IPv4 ACL(s) configured. | - | failure | VRF: default - Incorrect SNMP IPv4 ACL(s) - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | SNMP | VerifySnmpIPv6Acl | Verifies if the SNMP agent has IPv6 ACL(s) configured. | - | failure | VRF: default - Incorrect SNMP IPv6 ACL(s) - Expected: 3 Actual: 0 |
|
||||
| s1-spine1 | SNMP | VerifySnmpLocation | Verifies the SNMP location of a device. | - | failure | SNMP location is not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpNotificationHost | Verifies the SNMP notification host(s) (SNMP manager) configurations. | - | failure | No SNMP host is configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpPDUCounters | Verifies the SNMP PDU counters. | - | failure | SNMP counters not found |
|
||||
| s1-spine1 | SNMP | VerifySnmpSourceInterface | Verifies SNMP source interfaces. | - | failure | SNMP source interface(s) not configured |
|
||||
| s1-spine1 | SNMP | VerifySnmpStatus | Verifies if the SNMP agent is enabled. | - | failure | VRF: default - SNMP agent disabled |
|
||||
| s1-spine1 | SNMP | VerifySnmpUser | Verifies the SNMP user configurations. | - | failure | User: test Group: test_group Version: v3 - Not found |
|
||||
| s1-spine1 | Software | VerifyEOSExtensions | Verifies that all EOS extensions installed on the device are enabled for boot persistence. | - | success | - |
|
||||
| s1-spine1 | Software | VerifyEOSVersion | Verifies the EOS version of the device. | - | failure | EOS version mismatch - Actual: 4.31.0F-33804048.4310F (engineering build) not in Expected: 4.25.4M, 4.26.1F |
|
||||
| s1-spine1 | Software | VerifyTerminAttrVersion | Verifies the TerminAttr version of the device. | - | failure | TerminAttr version mismatch - Actual: v1.29.0 not in Expected: v1.13.6, v1.8.0 |
|
||||
| s1-spine1 | STP | VerifySTPBlockedPorts | Verifies there is no STP blocked ports. | - | success | - |
|
||||
| s1-spine1 | STP | VerifySTPCounters | Verifies there is no errors in STP BPDU packets. | - | success | - |
|
||||
| s1-spine1 | STP | VerifySTPDisabledVlans | Verifies the STP disabled VLAN(s). | - | failure | VLAN: 6 - Not configured |
|
||||
| s1-spine1 | STP | VerifySTPForwardingPorts | Verifies that all interfaces are forwarding for a provided list of VLAN(s). | - | success | - |
|
||||
| s1-spine1 | STP | VerifySTPMode | Verifies the configured STP mode for a provided list of VLAN(s). | - | failure | VLAN 10 - Incorrect STP mode - Expected: rapidPvst Actual: mstp<br>VLAN 20 - Incorrect STP mode - Expected: rapidPvst Actual: mstp |
|
||||
| s1-spine1 | STP | VerifySTPRootPriority | Verifies the STP root priority for a provided list of VLAN or MST instance ID(s). | - | failure | Instance: MST10 - Not configured<br>Instance: MST20 - Not configured |
|
||||
| s1-spine1 | STP | VerifyStpTopologyChanges | Verifies the number of changes across all interfaces in the Spanning Tree Protocol (STP) topology is below a threshold. | - | success | - |
|
||||
| s1-spine1 | STUN | VerifyStunClient | (Deprecated) Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found |
|
||||
| s1-spine1 | STUN | VerifyStunClientTranslation | Verifies the translation for a source address on a STUN client. | - | failure | Client 172.18.3.2 Port: 4500 - STUN client translation not found<br>Client 100.64.3.2 Port: 4500 - STUN client translation not found |
|
||||
| s1-spine1 | STUN | VerifyStunServer | Verifies the STUN server status is enabled and running. | - | failure | STUN server status is disabled and not running |
|
||||
| s1-spine1 | System | VerifyAgentLogs | Verifies there are no agent crash reports. | - | success | - |
|
||||
| s1-spine1 | System | VerifyCPUUtilization | Verifies whether the CPU utilization is below 75%. | - | success | - |
|
||||
| s1-spine1 | System | VerifyCoredump | Verifies there are no core dump files. | - | success | - |
|
||||
| s1-spine1 | System | VerifyFileSystemUtilization | Verifies that no partition is utilizing more than 75% of its disk space. | - | success | - |
|
||||
| s1-spine1 | System | VerifyMaintenance | Verifies that the device is not currently under or entering maintenance. | - | success | - |
|
||||
| s1-spine1 | System | VerifyNTP | Verifies if NTP is synchronised. | - | success | - |
|
||||
| s1-spine1 | System | VerifyReloadCause | Verifies the last reload cause of the device. | reload-cause | success | - |
|
||||
| s1-spine1 | System | VerifyUptime | Verifies the device uptime. | - | success | - |
|
||||
| s1-spine1 | VLAN | VerifyDynamicVlanSource | Verifies dynamic VLAN allocation for specified VLAN sources. | - | failure | Dynamic VLAN source(s) exist but have no VLANs allocated: mlagsync |
|
||||
| s1-spine1 | VLAN | VerifyVlanInternalPolicy | Verifies the VLAN internal allocation policy and the range of VLANs. | - | failure | VLAN internal allocation policy: ascending - Incorrect end VLAN id configured - Expected: 4094 Actual: 1199 |
|
||||
| s1-spine1 | VLAN | VerifyVlanStatus | Verifies the administrative status of specified VLANs. | - | failure | VLAN: Vlan10 - Incorrect administrative status - Expected: suspended Actual: active |
|
||||
| s1-spine1 | VXLAN | VerifyVxlan1ConnSettings | Verifies Vxlan1 source interface and UDP port. | - | success | - |
|
||||
| s1-spine1 | VXLAN | VerifyVxlan1Interface | Verifies the Vxlan1 interface status. | - | success | - |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanConfigSanity | Verifies there are no VXLAN config-sanity inconsistencies. | - | success | - |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanVniBinding | Verifies the VNI-VLAN, VNI-VRF bindings of the Vxlan1 interface. | - | failure | Interface: Vxlan1 VNI: 500 - Binding not found |
|
||||
| s1-spine1 | VXLAN | VerifyVxlanVtep | Verifies Vxlan1 VTEP peers. | - | failure | The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.5, 10.1.1.6<br>Unexpected VTEP peer(s) on Vxlan1 interface: 10.100.2.3 |
|
|
@ -3,30 +3,77 @@
|
|||
# that can be found in the LICENSE file.
|
||||
"""Tests for anta.tests module."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import asyncio
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any, Literal, TypedDict
|
||||
|
||||
from anta.device import AntaDevice
|
||||
from anta.models import AntaTest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from anta.device import AntaDevice
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
|
||||
if sys.version_info >= (3, 11):
|
||||
from typing import NotRequired
|
||||
else:
|
||||
from typing_extensions import NotRequired
|
||||
|
||||
|
||||
def test(device: AntaDevice, data: dict[str, Any]) -> None:
|
||||
class UnitTestResult(TypedDict):
|
||||
"""Expected result of a unit test of an AntaTest subclass.
|
||||
|
||||
For our AntaTest unit tests we expect only success, failure or skipped.
|
||||
Never unset nor error.
|
||||
"""
|
||||
|
||||
result: Literal[AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.SKIPPED]
|
||||
messages: NotRequired[list[str]]
|
||||
|
||||
|
||||
class AntaUnitTest(TypedDict):
|
||||
"""The parameters required for a unit test of an AntaTest subclass."""
|
||||
|
||||
inputs: NotRequired[dict[str, Any]]
|
||||
eos_data: list[dict[str, Any] | str]
|
||||
expected: UnitTestResult
|
||||
|
||||
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
TypeAlias = type
|
||||
|
||||
|
||||
AntaUnitTestDataDict: TypeAlias = dict[tuple[type[AntaTest], str], AntaUnitTest]
|
||||
|
||||
|
||||
def test(device: AntaDevice, data: tuple[tuple[type[AntaTest], str], AntaUnitTest]) -> None:
|
||||
"""Generic test function for AntaTest subclass.
|
||||
|
||||
Generate unit tests for each AntaTest subclass.
|
||||
|
||||
See `tests/units/anta_tests/README.md` for more information on how to use it.
|
||||
"""
|
||||
# Extract the test class, name and test data from a nested tuple structure:
|
||||
# `val: Tuple[Tuple[Type[AntaTest], str], AntaUnitTest]`
|
||||
(anta_test, name), test_data = data
|
||||
|
||||
# Instantiate the AntaTest subclass
|
||||
test_instance = data["test"](device, inputs=data["inputs"], eos_data=data["eos_data"])
|
||||
test_instance = anta_test(device, inputs=test_data.get("inputs"), eos_data=test_data["eos_data"])
|
||||
# Run the test() method
|
||||
asyncio.run(test_instance.test())
|
||||
|
||||
# Assert expected result
|
||||
assert test_instance.result.result == data["expected"]["result"], f"Expected '{data['expected']['result']}' result, got '{test_instance.result.result}'"
|
||||
if "messages" in data["expected"]:
|
||||
assert test_instance.result.result == test_data["expected"]["result"], (
|
||||
f"Expected '{test_data['expected']['result']}' result, got '{test_instance.result.result}'"
|
||||
)
|
||||
if "messages" in test_data["expected"]:
|
||||
# We expect messages in test result
|
||||
assert len(test_instance.result.messages) == len(data["expected"]["messages"])
|
||||
assert len(test_instance.result.messages) == len(test_data["expected"]["messages"])
|
||||
# Test will pass if the expected message is included in the test result message
|
||||
for message, expected in zip(test_instance.result.messages, data["expected"]["messages"]): # NOTE: zip(strict=True) has been added in Python 3.10
|
||||
for message, expected in zip(test_instance.result.messages, test_data["expected"]["messages"]): # NOTE: zip(strict=True) has been added in Python 3.10
|
||||
assert expected in message
|
||||
else:
|
||||
# Test result should not have messages
|
||||
|
|
|
@ -7,17 +7,27 @@ from typing import Any
|
|||
|
||||
import pytest
|
||||
|
||||
from anta.models import AntaTest
|
||||
from tests.units.anta_tests import AntaUnitTest
|
||||
|
||||
def build_test_id(val: dict[str, Any]) -> str:
|
||||
|
||||
def build_test_id(val: tuple[tuple[type[AntaTest], str], AntaUnitTest]) -> str:
|
||||
"""Build id for a unit test of an AntaTest subclass.
|
||||
|
||||
{
|
||||
"name": "meaniful test name",
|
||||
"test": <AntaTest instance>,
|
||||
(<AntaTest instance>, "meaniful test name"):
|
||||
{
|
||||
"eos_data": [{}],
|
||||
....
|
||||
}
|
||||
...
|
||||
}
|
||||
"""
|
||||
return f"{val['test'].__module__}.{val['test'].__name__}-{val['name']}"
|
||||
# Extract the test class and its name from a nested tuple structure:
|
||||
# `val: Tuple[Tuple[Type[AntaTest], str], AntaUnitTest]`
|
||||
(anta_test, test_name) = val[0]
|
||||
|
||||
return f"{anta_test.__module__}.{anta_test.__name__}-{test_name}"
|
||||
|
||||
|
||||
def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
|
||||
|
@ -32,4 +42,4 @@ def pytest_generate_tests(metafunc: pytest.Metafunc) -> None:
|
|||
"""
|
||||
if "tests.units.anta_tests" in metafunc.module.__package__ and metafunc.function.__name__ == "test":
|
||||
# This is a unit test for an AntaTest subclass
|
||||
metafunc.parametrize("data", metafunc.module.DATA, ids=build_test_id)
|
||||
metafunc.parametrize("data", metafunc.module.DATA.items(), ids=build_test_id)
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -6,73 +6,53 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from typing import Any
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from anta.tests.routing.generic import VerifyIPv4RouteNextHops, VerifyIPv4RouteType, VerifyRoutingProtocolModel, VerifyRoutingTableEntry, VerifyRoutingTableSize
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.routing.generic import (
|
||||
VerifyIPv4RouteNextHops,
|
||||
VerifyIPv4RouteType,
|
||||
VerifyRoutingProtocolModel,
|
||||
VerifyRoutingStatus,
|
||||
VerifyRoutingTableEntry,
|
||||
VerifyRoutingTableSize,
|
||||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRoutingProtocolModel,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyRoutingProtocolModel, "success"): {
|
||||
"eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "multi-agent", "operatingProtoModel": "multi-agent"}}],
|
||||
"inputs": {"model": "multi-agent"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-configured-model",
|
||||
"test": VerifyRoutingProtocolModel,
|
||||
(VerifyRoutingProtocolModel, "failure-wrong-configured-model"): {
|
||||
"eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "ribd", "operatingProtoModel": "ribd"}}],
|
||||
"inputs": {"model": "multi-agent"},
|
||||
"expected": {"result": "failure", "messages": ["Routing model is misconfigured - Expected: multi-agent Actual: ribd"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Routing model is misconfigured - Expected: multi-agent Actual: ribd"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-mismatch-operating-model",
|
||||
"test": VerifyRoutingProtocolModel,
|
||||
(VerifyRoutingProtocolModel, "failure-mismatch-operating-model"): {
|
||||
"eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "multi-agent", "operatingProtoModel": "ribd"}}],
|
||||
"inputs": {"model": "multi-agent"},
|
||||
"expected": {"result": "failure", "messages": ["Routing model is misconfigured - Expected: multi-agent Actual: ribd"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Routing model is misconfigured - Expected: multi-agent Actual: ribd"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRoutingTableSize,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
# Output truncated
|
||||
"maskLen": {"8": 2},
|
||||
"totalRoutes": 123,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
(VerifyRoutingTableSize, "success"): {
|
||||
"eos_data": [{"vrfs": {"default": {"maskLen": {"8": 2}, "totalRoutes": 123}}}],
|
||||
"inputs": {"minimum": 42, "maximum": 666},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyRoutingTableSize,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
# Output truncated
|
||||
"maskLen": {"8": 2},
|
||||
"totalRoutes": 1000,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
(VerifyRoutingTableSize, "failure"): {
|
||||
"eos_data": [{"vrfs": {"default": {"maskLen": {"8": 2}, "totalRoutes": 1000}}}],
|
||||
"inputs": {"minimum": 42, "maximum": 666},
|
||||
"expected": {"result": "failure", "messages": ["Routing table routes are outside the routes range - Expected: 42 <= to >= 666 Actual: 1000"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Routing table routes are outside the routes range - Expected: 42 <= to >= 666 Actual: 1000"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
(VerifyRoutingTableEntry, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -92,10 +72,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.4", "interface": "Ethernet1"}],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -115,18 +95,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.6", "interface": "Ethernet2"}],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"inputs": {"vrf": "default", "routes": ["10.1.0.1", "10.1.0.2"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-collect-all",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
(VerifyRoutingTableEntry, "success-collect-all"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -159,16 +137,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"vias": [{"nexthopAddr": "10.1.255.6", "interface": "Ethernet2"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"vrf": "default", "routes": ["10.1.0.1", "10.1.0.2"], "collect": "all"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-route",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
(VerifyRoutingTableEntry, "failure-missing-route"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -178,8 +154,8 @@ DATA: list[dict[str, Any]] = [
|
|||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -199,10 +175,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.6", "interface": "Ethernet2"}],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -212,16 +188,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"inputs": {"vrf": "default", "routes": ["10.1.0.1", "10.1.0.2", "10.1.0.3"]},
|
||||
"expected": {"result": "failure", "messages": ["The following route(s) are missing from the routing table of VRF default: 10.1.0.1, 10.1.0.3"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following route(s) are missing from the routing table of VRF default: 10.1.0.1, 10.1.0.3"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-route",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
(VerifyRoutingTableEntry, "failure-wrong-route"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -241,10 +215,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.4", "interface": "Ethernet1"}],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -264,18 +238,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.6", "interface": "Ethernet2"}],
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
],
|
||||
"inputs": {"vrf": "default", "routes": ["10.1.0.1", "10.1.0.2"]},
|
||||
"expected": {"result": "failure", "messages": ["The following route(s) are missing from the routing table of VRF default: 10.1.0.2"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following route(s) are missing from the routing table of VRF default: 10.1.0.2"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-route-collect-all",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
(VerifyRoutingTableEntry, "failure-wrong-route-collect-all"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -308,16 +280,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"vias": [{"nexthopAddr": "10.1.255.6", "interface": "Ethernet2"}],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"vrf": "default", "routes": ["10.1.0.1", "10.1.0.2"], "collect": "all"},
|
||||
"expected": {"result": "failure", "messages": ["The following route(s) are missing from the routing table of VRF default: 10.1.0.2"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following route(s) are missing from the routing table of VRF default: 10.1.0.2"]},
|
||||
},
|
||||
{
|
||||
"name": "success-valid-route-type",
|
||||
"test": VerifyIPv4RouteType,
|
||||
(VerifyIPv4RouteType, "success-valid-route-type"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -333,42 +303,31 @@ DATA: list[dict[str, Any]] = [
|
|||
{"vrf": "MGMT", "prefix": "10.100.1.5/32", "route_type": "iBGP"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-route-not-found",
|
||||
"test": VerifyIPv4RouteType,
|
||||
(VerifyIPv4RouteType, "failure-route-not-found"): {
|
||||
"eos_data": [{"vrfs": {"default": {"routes": {}}}}],
|
||||
"inputs": {"routes_entries": [{"vrf": "default", "prefix": "10.10.0.1/32", "route_type": "eBGP"}]},
|
||||
"expected": {"result": "failure", "messages": ["Prefix: 10.10.0.1/32 VRF: default - Route not found"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Prefix: 10.10.0.1/32 VRF: default - Route not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-route-type",
|
||||
"test": VerifyIPv4RouteType,
|
||||
(VerifyIPv4RouteType, "failure-invalid-route-type"): {
|
||||
"eos_data": [{"vrfs": {"default": {"routes": {"10.10.0.1/32": {"routeType": "eBGP"}}}}}],
|
||||
"inputs": {"routes_entries": [{"vrf": "default", "prefix": "10.10.0.1/32", "route_type": "iBGP"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Prefix: 10.10.0.1/32 VRF: default - Incorrect route type - Expected: iBGP Actual: eBGP"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Prefix: 10.10.0.1/32 VRF: default - Incorrect route type - Expected: iBGP Actual: eBGP"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vrf-not-configured",
|
||||
"test": VerifyIPv4RouteType,
|
||||
(VerifyIPv4RouteType, "failure-vrf-not-configured"): {
|
||||
"eos_data": [{"vrfs": {}}],
|
||||
"inputs": {"routes_entries": [{"vrf": "default", "prefix": "10.10.0.1/32", "route_type": "eBGP"}]},
|
||||
"expected": {"result": "failure", "messages": ["Prefix: 10.10.0.1/32 VRF: default - VRF not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Prefix: 10.10.0.1/32 VRF: default - VRF not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyIPv4RouteNextHops,
|
||||
(VerifyIPv4RouteNextHops, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routes": {
|
||||
"10.10.0.1/32": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -379,12 +338,12 @@ DATA: list[dict[str, Any]] = [
|
|||
{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"},
|
||||
{"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"},
|
||||
{"nexthopAddr": "10.100.0.101", "interface": "Ethernet4"},
|
||||
],
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"route_entries": [
|
||||
|
@ -392,30 +351,28 @@ DATA: list[dict[str, Any]] = [
|
|||
{"prefix": "10.100.0.128/31", "vrf": "MGMT", "nexthops": ["10.100.0.8", "10.100.0.10"]},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-strict-true",
|
||||
"test": VerifyIPv4RouteNextHops,
|
||||
(VerifyIPv4RouteNextHops, "success-strict-true"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routes": {
|
||||
"10.10.0.1/32": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"routes": {
|
||||
"10.100.0.128/31": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"route_entries": [
|
||||
|
@ -423,14 +380,10 @@ DATA: list[dict[str, Any]] = [
|
|||
{"prefix": "10.100.0.128/31", "vrf": "MGMT", "strict": True, "nexthops": ["10.100.0.8", "10.100.0.10"]},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyIPv4RouteNextHops,
|
||||
"eos_data": [
|
||||
{"vrfs": {"default": {"routes": {}}, "MGMT": {"routes": {}}}},
|
||||
],
|
||||
(VerifyIPv4RouteNextHops, "failure-not-configured"): {
|
||||
"eos_data": [{"vrfs": {"default": {"routes": {}}, "MGMT": {"routes": {}}}}],
|
||||
"inputs": {
|
||||
"route_entries": [
|
||||
{"prefix": "10.10.0.1/32", "vrf": "default", "strict": True, "nexthops": ["10.100.0.8", "10.100.0.10"]},
|
||||
|
@ -438,32 +391,30 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Prefix: 10.10.0.1/32 VRF: default - prefix not found", "Prefix: 10.100.0.128/31 VRF: MGMT - prefix not found"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-strict-failed",
|
||||
"test": VerifyIPv4RouteNextHops,
|
||||
(VerifyIPv4RouteNextHops, "failure-strict-failed"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routes": {
|
||||
"10.10.0.1/32": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"routes": {
|
||||
"10.100.0.128/31": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.11", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.11", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"route_entries": [
|
||||
|
@ -472,36 +423,34 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Prefix: 10.10.0.1/32 VRF: default - List of next-hops not matching - Expected: 10.100.0.10, 10.100.0.11, 10.100.0.8 "
|
||||
"Actual: 10.100.0.10, 10.100.0.8",
|
||||
"Prefix: 10.10.0.1/32 VRF: default - List of next-hops not matching - "
|
||||
"Expected: 10.100.0.10, 10.100.0.11, 10.100.0.8 Actual: 10.100.0.10, 10.100.0.8",
|
||||
"Prefix: 10.100.0.128/31 VRF: MGMT - List of next-hops not matching - Expected: 10.100.0.10, 10.100.0.8 Actual: 10.100.0.11, 10.100.0.8",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyIPv4RouteNextHops,
|
||||
(VerifyIPv4RouteNextHops, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routes": {
|
||||
"10.10.0.1/32": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"routes": {
|
||||
"10.100.0.128/31": {
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}],
|
||||
"vias": [{"nexthopAddr": "10.100.0.8", "interface": "Ethernet1"}, {"nexthopAddr": "10.100.0.10", "interface": "Ethernet2"}]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"route_entries": [
|
||||
|
@ -510,14 +459,93 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Prefix: 10.10.0.1/32 VRF: default Nexthop: 10.100.0.11 - Route not found",
|
||||
"Prefix: 10.100.0.128/31 VRF: MGMT Nexthop: 10.100.0.11 - Route not found",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
(VerifyRoutingStatus, "success-routing-enablement"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"v4RoutingEnabled": True,
|
||||
"v6RoutingEnabled": True,
|
||||
"vrrpIntfs": 0,
|
||||
"v6IntfForwarding": True,
|
||||
"multicastRouting": {"ipMulticastEnabled": False, "ip6MulticastEnabled": False},
|
||||
"v6EcmpInfo": {"v6EcmpRouteSupport": True},
|
||||
}
|
||||
],
|
||||
"inputs": {"ipv4_unicast": True, "ipv6_unicast": True, "ipv6_interfaces": True},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyRoutingStatus, "success-routing-disable-all"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"v4RoutingEnabled": False,
|
||||
"v6RoutingEnabled": False,
|
||||
"vrrpIntfs": 0,
|
||||
"multicastRouting": {"ipMulticastEnabled": False, "ip6MulticastEnabled": False},
|
||||
"v6EcmpInfo": {"v6EcmpRouteSupport": False},
|
||||
}
|
||||
],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyRoutingStatus, "failure-ip-multicastrouting-enablement"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"v4RoutingEnabled": False,
|
||||
"v6RoutingEnabled": False,
|
||||
"vrrpIntfs": 0,
|
||||
"multicastRouting": {"ipMulticastEnabled": False, "ip6MulticastEnabled": False},
|
||||
"v6EcmpInfo": {"v6EcmpRouteSupport": True},
|
||||
}
|
||||
],
|
||||
"inputs": {"ipv4_multicast": True, "ipv6_multicast": True},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"IPv4 multicast routing enabled status mismatch - Expected: True Actual: False",
|
||||
"IPv6 multicast routing enabled status mismatch - Expected: True Actual: False",
|
||||
],
|
||||
},
|
||||
},
|
||||
(VerifyRoutingStatus, "failure-ip-routing-enablement"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"v4RoutingEnabled": False,
|
||||
"v6RoutingEnabled": False,
|
||||
"vrrpIntfs": 0,
|
||||
"multicastRouting": {"ipMulticastEnabled": True, "ip6MulticastEnabled": True},
|
||||
"v6EcmpInfo": {"v6EcmpRouteSupport": True},
|
||||
}
|
||||
],
|
||||
"inputs": {"ipv4_unicast": True, "ipv6_unicast": True},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"IPv4 unicast routing enabled status mismatch - Expected: True Actual: False",
|
||||
"IPv6 unicast routing enabled status mismatch - Expected: True Actual: False",
|
||||
"IPv4 multicast routing enabled status mismatch - Expected: False Actual: True",
|
||||
"IPv6 multicast routing enabled status mismatch - Expected: False Actual: True",
|
||||
],
|
||||
},
|
||||
},
|
||||
(VerifyRoutingStatus, "failure-ipv6-interface-routing-enablement"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"v4RoutingEnabled": True,
|
||||
"v6RoutingEnabled": True,
|
||||
"vrrpIntfs": 0,
|
||||
"multicastRouting": {"ipMulticastEnabled": False, "ip6MulticastEnabled": False},
|
||||
"v6EcmpInfo": {"v6EcmpRouteSupport": True},
|
||||
}
|
||||
],
|
||||
"inputs": {"ipv4_unicast": True, "ipv6_unicast": True, "ipv6_interfaces": True},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["IPv6 interfaces routing enabled status mismatch - Expected: True Actual: False"]},
|
||||
},
|
||||
}
|
||||
|
||||
|
||||
class TestVerifyRoutingTableSizeInputs:
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,15 +5,24 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.routing.ospf import VerifyOSPFMaxLSA, VerifyOSPFNeighborCount, VerifyOSPFNeighborState
|
||||
from tests.units.anta_tests import test
|
||||
from tests.units.anta_tests import AntaUnitTest, test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
TypeAlias = type
|
||||
|
||||
|
||||
AntaUnitTestDataDict: TypeAlias = dict[tuple[type[AntaTest], str], AntaUnitTest]
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyOSPFNeighborState, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -39,9 +48,9 @@ DATA: list[dict[str, Any]] = [
|
|||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
|
@ -55,20 +64,17 @@ DATA: list[dict[str, Any]] = [
|
|||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
(VerifyOSPFNeighborState, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -94,9 +100,9 @@ DATA: list[dict[str, Any]] = [
|
|||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
|
@ -110,63 +116,31 @@ DATA: list[dict[str, Any]] = [
|
|||
"adjacencyState": "down",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Instance: 666 VRF: default Interface: 7.7.7.7 - Incorrect adjacency state - Expected: Full Actual: 2-way",
|
||||
"Instance: 777 VRF: BLAH Interface: 8.8.8.8 - Incorrect adjacency state - Expected: Full Actual: down",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped-ospf-not-configured",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {},
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["OSPF not configured"]},
|
||||
(VerifyOSPFNeighborState, "skipped-ospf-not-configured"): {
|
||||
"eos_data": [{"vrfs": {}}],
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["OSPF not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-neighbor-not-found",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
"777": {
|
||||
"ospfNeighborEntries": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["No OSPF neighbor detected"]},
|
||||
(VerifyOSPFNeighborState, "skipped-neighbor-not-found"): {
|
||||
"eos_data": [{"vrfs": {"default": {"instList": {"666": {"ospfNeighborEntries": []}}}, "BLAH": {"instList": {"777": {"ospfNeighborEntries": []}}}}}],
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["No OSPF neighbor detected"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
(VerifyOSPFNeighborCount, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -192,9 +166,9 @@ DATA: list[dict[str, Any]] = [
|
|||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
|
@ -208,20 +182,18 @@ DATA: list[dict[str, Any]] = [
|
|||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-good-number-wrong-state",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
(VerifyOSPFNeighborCount, "failure-good-number-wrong-state"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -247,9 +219,9 @@ DATA: list[dict[str, Any]] = [
|
|||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
|
@ -263,65 +235,28 @@ DATA: list[dict[str, Any]] = [
|
|||
"adjacencyState": "down",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Neighbor count mismatch - Expected: 3 Actual: 1"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Neighbor count mismatch - Expected: 3 Actual: 1"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-ospf-not-configured",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {},
|
||||
},
|
||||
],
|
||||
(VerifyOSPFNeighborCount, "skipped-ospf-not-configured"): {
|
||||
"eos_data": [{"vrfs": {}}],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {"result": "skipped", "messages": ["OSPF not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["OSPF not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-no-neighbor-detected",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
"777": {
|
||||
"ospfNeighborEntries": [],
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
(VerifyOSPFNeighborCount, "skipped-no-neighbor-detected"): {
|
||||
"eos_data": [{"vrfs": {"default": {"instList": {"666": {"ospfNeighborEntries": []}}}, "BLAH": {"instList": {"777": {"ospfNeighborEntries": []}}}}}],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {
|
||||
"result": "skipped",
|
||||
"messages": [
|
||||
"No OSPF neighbor detected",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["No OSPF neighbor detected"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyOSPFMaxLSA,
|
||||
(VerifyOSPFMaxLSA, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -329,10 +264,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"instList": {
|
||||
"1": {
|
||||
"instanceId": 1,
|
||||
"maxLsaInformation": {
|
||||
"maxLsa": 12000,
|
||||
"maxLsaThreshold": 75,
|
||||
},
|
||||
"maxLsaInformation": {"maxLsa": 12000, "maxLsaThreshold": 75},
|
||||
"routerId": "1.1.1.1",
|
||||
"lsaInformation": {
|
||||
"lsaArrivalInterval": 1000,
|
||||
|
@ -341,17 +273,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"lsaMaxWaitInterval": 5000,
|
||||
"numLsa": 9,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"TEST": {
|
||||
"instList": {
|
||||
"10": {
|
||||
"instanceId": 10,
|
||||
"maxLsaInformation": {
|
||||
"maxLsa": 1000,
|
||||
"maxLsaThreshold": 75,
|
||||
},
|
||||
"maxLsaInformation": {"maxLsa": 1000, "maxLsaThreshold": 75},
|
||||
"routerId": "20.20.20.20",
|
||||
"lsaInformation": {
|
||||
"lsaArrivalInterval": 1000,
|
||||
|
@ -360,18 +289,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"lsaMaxWaitInterval": 5000,
|
||||
"numLsa": 5,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyOSPFMaxLSA,
|
||||
(VerifyOSPFMaxLSA, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -379,10 +305,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"instList": {
|
||||
"1": {
|
||||
"instanceId": 1,
|
||||
"maxLsaInformation": {
|
||||
"maxLsa": 12000,
|
||||
"maxLsaThreshold": 75,
|
||||
},
|
||||
"maxLsaInformation": {"maxLsa": 12000, "maxLsaThreshold": 75},
|
||||
"routerId": "1.1.1.1",
|
||||
"lsaInformation": {
|
||||
"lsaArrivalInterval": 1000,
|
||||
|
@ -391,17 +314,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"lsaMaxWaitInterval": 5000,
|
||||
"numLsa": 11500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
"TEST": {
|
||||
"instList": {
|
||||
"10": {
|
||||
"instanceId": 10,
|
||||
"maxLsaInformation": {
|
||||
"maxLsa": 1000,
|
||||
"maxLsaThreshold": 75,
|
||||
},
|
||||
"maxLsaInformation": {"maxLsa": 1000, "maxLsaThreshold": 75},
|
||||
"routerId": "20.20.20.20",
|
||||
"lsaInformation": {
|
||||
"lsaArrivalInterval": 1000,
|
||||
|
@ -410,30 +330,19 @@ DATA: list[dict[str, Any]] = [
|
|||
"lsaMaxWaitInterval": 5000,
|
||||
"numLsa": 1500,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Instance: 1 - Crossed the maximum LSA threshold - Expected: < 9000 Actual: 11500",
|
||||
"Instance: 10 - Crossed the maximum LSA threshold - Expected: < 750 Actual: 1500",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyOSPFMaxLSA,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {},
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["OSPF not configured"]},
|
||||
},
|
||||
]
|
||||
(VerifyOSPFMaxLSA, "skipped"): {"eos_data": [{"vrfs": {}}], "expected": {"result": AntaTestStatus.SKIPPED, "messages": ["OSPF not configured"]}},
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.aaa import (
|
||||
VerifyAcctConsoleMethods,
|
||||
VerifyAcctDefaultMethods,
|
||||
|
@ -18,510 +21,326 @@ from anta.tests.aaa import (
|
|||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyTacacsSourceIntf, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"intf": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [],
|
||||
"groups": {},
|
||||
"srcIntf": {},
|
||||
},
|
||||
],
|
||||
(VerifyTacacsSourceIntf, "failure-not-configured"): {
|
||||
"eos_data": [{"tacacsServers": [], "groups": {}, "srcIntf": {}}],
|
||||
"inputs": {"intf": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT Source Interface: Management0 - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT Source Interface: Management0 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-intf",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
(VerifyTacacsSourceIntf, "failure-wrong-intf"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management1"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"intf": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT - Source interface mismatch - Expected: Management0 Actual: Management1"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT - Source interface mismatch - Expected: Management0 Actual: Management1"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
(VerifyTacacsSourceIntf, "failure-wrong-vrf"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"PROD": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"intf": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT Source Interface: Management0 - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT Source Interface: Management0 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTacacsServers,
|
||||
(VerifyTacacsServers, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"servers": ["10.22.10.91"], "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-servers",
|
||||
"test": VerifyTacacsServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [],
|
||||
"groups": {},
|
||||
"srcIntf": {},
|
||||
},
|
||||
],
|
||||
(VerifyTacacsServers, "failure-no-servers"): {
|
||||
"eos_data": [{"tacacsServers": [], "groups": {}, "srcIntf": {}}],
|
||||
"inputs": {"servers": ["10.22.10.91"], "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["No TACACS servers are configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No TACACS servers are configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyTacacsServers,
|
||||
(VerifyTacacsServers, "failure-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"servers": ["10.22.10.91", "10.22.10.92"], "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["TACACS servers 10.22.10.92 are not configured in VRF MGMT"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["TACACS servers 10.22.10.92 are not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifyTacacsServers,
|
||||
(VerifyTacacsServers, "failure-wrong-vrf"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "PROD"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "PROD"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"servers": ["10.22.10.91"], "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["TACACS servers 10.22.10.91 are not configured in VRF MGMT"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["TACACS servers 10.22.10.91 are not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTacacsServerGroups,
|
||||
(VerifyTacacsServerGroups, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP1": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"groups": ["GROUP1"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-server-groups",
|
||||
"test": VerifyTacacsServerGroups,
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [],
|
||||
"groups": {},
|
||||
"srcIntf": {},
|
||||
},
|
||||
],
|
||||
(VerifyTacacsServerGroups, "failure-no-server-groups"): {
|
||||
"eos_data": [{"tacacsServers": [], "groups": {}, "srcIntf": {}}],
|
||||
"inputs": {"groups": ["GROUP1"]},
|
||||
"expected": {"result": "failure", "messages": ["No TACACS server group(s) are configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No TACACS server group(s) are configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyTacacsServerGroups,
|
||||
(VerifyTacacsServerGroups, "failure-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [
|
||||
{
|
||||
"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"},
|
||||
},
|
||||
],
|
||||
"tacacsServers": [{"serverInfo": {"hostname": "10.22.10.91", "authport": 49, "vrf": "MGMT"}}],
|
||||
"groups": {"GROUP2": {"serverGroup": "TACACS+", "members": [{"hostname": "SERVER1", "authport": 49, "vrf": "MGMT"}]}},
|
||||
"srcIntf": {"MGMT": "Management0"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"groups": ["GROUP1"]},
|
||||
"expected": {"result": "failure", "messages": ["TACACS server group(s) GROUP1 are not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["TACACS server group(s) GROUP1 are not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success-login-enable",
|
||||
"test": VerifyAuthenMethods,
|
||||
(VerifyAuthenMethods, "success-login-enable"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"loginAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}, "login": {"methods": ["group tacacs+", "local"]}},
|
||||
"enableAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}},
|
||||
"dot1xAuthenMethods": {"default": {"methods": ["group radius"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["login", "enable"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-dot1x",
|
||||
"test": VerifyAuthenMethods,
|
||||
(VerifyAuthenMethods, "success-dot1x"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"loginAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}, "login": {"methods": ["group tacacs+", "local"]}},
|
||||
"enableAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}},
|
||||
"dot1xAuthenMethods": {"default": {"methods": ["group radius"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["radius"], "types": ["dot1x"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-login-console",
|
||||
"test": VerifyAuthenMethods,
|
||||
(VerifyAuthenMethods, "failure-no-login-console"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"loginAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}},
|
||||
"enableAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}},
|
||||
"dot1xAuthenMethods": {"default": {"methods": ["group radius"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["login", "enable"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA authentication methods are not configured for login console"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA authentication methods are not configured for login console"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-login-console",
|
||||
"test": VerifyAuthenMethods,
|
||||
(VerifyAuthenMethods, "failure-login-console"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"loginAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}, "login": {"methods": ["group radius", "local"]}},
|
||||
"enableAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}},
|
||||
"dot1xAuthenMethods": {"default": {"methods": ["group radius"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["login", "enable"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA authentication methods group tacacs+, local are not matching for login console"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA authentication methods group tacacs+, local are not matching for login console"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-login-default",
|
||||
"test": VerifyAuthenMethods,
|
||||
(VerifyAuthenMethods, "failure-login-default"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"loginAuthenMethods": {"default": {"methods": ["group radius", "local"]}, "login": {"methods": ["group tacacs+", "local"]}},
|
||||
"enableAuthenMethods": {"default": {"methods": ["group tacacs+", "local"]}},
|
||||
"dot1xAuthenMethods": {"default": {"methods": ["group radius"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["login", "enable"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA authentication methods group tacacs+, local are not matching for login"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA authentication methods group tacacs+, local are not matching for login"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAuthzMethods,
|
||||
(VerifyAuthzMethods, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAuthzMethods": {"privilege0-15": {"methods": ["group tacacs+", "local"]}},
|
||||
"execAuthzMethods": {"exec": {"methods": ["group tacacs+", "local"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["commands", "exec"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-skipping-exec",
|
||||
"test": VerifyAuthzMethods,
|
||||
(VerifyAuthzMethods, "success-skipping-exec"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAuthzMethods": {"privilege0-15": {"methods": ["group tacacs+", "local"]}},
|
||||
"execAuthzMethods": {"exec": {"methods": ["group tacacs+", "local"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["commands"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-commands",
|
||||
"test": VerifyAuthzMethods,
|
||||
(VerifyAuthzMethods, "failure-commands"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAuthzMethods": {"privilege0-15": {"methods": ["group radius", "local"]}},
|
||||
"execAuthzMethods": {"exec": {"methods": ["group tacacs+", "local"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["commands", "exec"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA authorization methods group tacacs+, local are not matching for commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA authorization methods group tacacs+, local are not matching for commands"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-exec",
|
||||
"test": VerifyAuthzMethods,
|
||||
(VerifyAuthzMethods, "failure-exec"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAuthzMethods": {"privilege0-15": {"methods": ["group tacacs+", "local"]}},
|
||||
"execAuthzMethods": {"exec": {"methods": ["group radius", "local"]}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "local"], "types": ["commands", "exec"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA authorization methods group tacacs+, local are not matching for exec"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA authorization methods group tacacs+, local are not matching for exec"]},
|
||||
},
|
||||
{
|
||||
"name": "success-commands-exec-system",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
(VerifyAcctDefaultMethods, "success-commands-exec-system"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"systemAcctMethods": {"system": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-dot1x",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
(VerifyAcctDefaultMethods, "success-dot1x"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"systemAcctMethods": {"system": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultAction": "startStop", "defaultMethods": ["group radius", "logging"], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["radius", "logging"], "types": ["dot1x"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
(VerifyAcctDefaultMethods, "failure-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"systemAcctMethods": {"system": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA default accounting is not configured for commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA default accounting is not configured for commands"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured-empty",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
(VerifyAcctDefaultMethods, "failure-not-configured-empty"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"systemAcctMethods": {"system": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA default accounting is not configured for system, exec, commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA default accounting is not configured for system, exec, commands"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-matching",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
(VerifyAcctDefaultMethods, "failure-not-matching"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultAction": "startStop", "defaultMethods": ["group radius", "logging"], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"systemAcctMethods": {"system": {"defaultAction": "startStop", "defaultMethods": ["group tacacs+", "logging"], "consoleMethods": []}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA accounting default methods group tacacs+, logging are not matching for commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA accounting default methods group tacacs+, logging are not matching for commands"]},
|
||||
},
|
||||
{
|
||||
"name": "success-commands-exec-system",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
(VerifyAcctConsoleMethods, "success-commands-exec-system"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {
|
||||
"privilege0-15": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"execAcctMethods": {
|
||||
"exec": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"systemAcctMethods": {
|
||||
"system": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"execAcctMethods": {"exec": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"systemAcctMethods": {"system": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-dot1x",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
(VerifyAcctConsoleMethods, "success-dot1x"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {
|
||||
"privilege0-15": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"execAcctMethods": {
|
||||
"exec": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"systemAcctMethods": {
|
||||
"system": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"dot1xAcctMethods": {
|
||||
"dot1x": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
},
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"execAcctMethods": {"exec": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"systemAcctMethods": {"system": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["dot1x"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
(VerifyAcctConsoleMethods, "failure-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {
|
||||
"privilege0-15": {
|
||||
"defaultMethods": [],
|
||||
"consoleMethods": [],
|
||||
},
|
||||
},
|
||||
"execAcctMethods": {
|
||||
"exec": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"systemAcctMethods": {
|
||||
"system": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"systemAcctMethods": {"system": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA console accounting is not configured for commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA console accounting is not configured for commands"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured-empty",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
(VerifyAcctConsoleMethods, "failure-not-configured-empty"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"systemAcctMethods": {"system": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"execAcctMethods": {"exec": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleMethods": []}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA console accounting is not configured for system, exec, commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA console accounting is not configured for system, exec, commands"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-matching",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
(VerifyAcctConsoleMethods, "failure-not-matching"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"commandsAcctMethods": {
|
||||
"privilege0-15": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group radius", "logging"],
|
||||
},
|
||||
},
|
||||
"execAcctMethods": {
|
||||
"exec": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"systemAcctMethods": {
|
||||
"system": {
|
||||
"defaultMethods": [],
|
||||
"consoleAction": "startStop",
|
||||
"consoleMethods": ["group tacacs+", "logging"],
|
||||
},
|
||||
},
|
||||
"commandsAcctMethods": {"privilege0-15": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group radius", "logging"]}},
|
||||
"execAcctMethods": {"exec": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"systemAcctMethods": {"system": {"defaultMethods": [], "consoleAction": "startStop", "consoleMethods": ["group tacacs+", "logging"]}},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA accounting console methods group tacacs+, logging are not matching for commands"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA accounting console methods group tacacs+, logging are not matching for commands"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,15 +5,19 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.avt import VerifyAVTPathHealth, VerifyAVTRole, VerifyAVTSpecificPath
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAVTPathHealth,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyAVTPathHealth, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -21,18 +25,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"DATA-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -41,12 +37,8 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"GUEST-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -55,28 +47,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"CONTROL-PLANE-PROFILE": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
},
|
||||
"DEFAULT-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -85,21 +65,14 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-avt-not-configured",
|
||||
"test": VerifyAVTPathHealth,
|
||||
(VerifyAVTPathHealth, "failure-avt-not-configured"): {
|
||||
"eos_data": [{"vrfs": {}}],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Adaptive virtual topology paths are not configured"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Adaptive virtual topology paths are not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-active-path",
|
||||
"test": VerifyAVTPathHealth,
|
||||
(VerifyAVTPathHealth, "failure-not-active-path"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -107,18 +80,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"DATA-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -127,12 +92,8 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"GUEST-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": False},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": False}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -141,28 +102,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"CONTROL-PLANE-PROFILE": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": False},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": False}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
},
|
||||
"DEFAULT-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": False},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": False}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -172,7 +121,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"VRF: guest Profile: GUEST-AVT-POLICY-DEFAULT AVT path: direct:10 - Not active",
|
||||
"VRF: default Profile: CONTROL-PLANE-PROFILE AVT path: direct:1 - Not active",
|
||||
|
@ -180,9 +129,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-path",
|
||||
"test": VerifyAVTPathHealth,
|
||||
(VerifyAVTPathHealth, "failure-invalid-path"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -190,18 +137,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"DATA-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": False, "active": True},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": False, "active": True}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -210,12 +149,8 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"GUEST-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": False, "active": True},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": False, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -224,28 +159,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"CONTROL-PLANE-PROFILE": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": False, "active": True},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": False, "active": True}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
},
|
||||
"DEFAULT-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": False, "active": True},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": False, "active": True}},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -255,7 +178,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"VRF: data Profile: DATA-AVT-POLICY-DEFAULT AVT path: direct:10 - Invalid",
|
||||
"VRF: guest Profile: GUEST-AVT-POLICY-DEFAULT AVT path: direct:8 - Invalid",
|
||||
|
@ -264,9 +187,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-active-and-invalid",
|
||||
"test": VerifyAVTPathHealth,
|
||||
(VerifyAVTPathHealth, "failure-not-active-and-invalid"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -274,18 +195,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"DATA-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": False, "active": False},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": False},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": False, "active": False}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": False}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -294,12 +207,8 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"GUEST-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": False, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": False, "active": False},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": False, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": False, "active": False}},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -308,28 +217,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"avts": {
|
||||
"CONTROL-PLANE-PROFILE": {
|
||||
"avtPaths": {
|
||||
"direct:9": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": False, "active": False},
|
||||
},
|
||||
"direct:1": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": True, "active": True},
|
||||
},
|
||||
"direct:9": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": False, "active": False}},
|
||||
"direct:1": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": True, "active": True}},
|
||||
}
|
||||
},
|
||||
"DEFAULT-AVT-POLICY-DEFAULT": {
|
||||
"avtPaths": {
|
||||
"direct:10": {
|
||||
"flags": {"directPath": True, "valid": True, "active": False},
|
||||
},
|
||||
"direct:8": {
|
||||
"flags": {"directPath": True, "valid": False, "active": False},
|
||||
},
|
||||
"direct:10": {"flags": {"directPath": True, "valid": True, "active": False}},
|
||||
"direct:8": {"flags": {"directPath": True, "valid": False, "active": False}},
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -339,7 +236,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"VRF: data Profile: DATA-AVT-POLICY-DEFAULT AVT path: direct:10 - Invalid and not active",
|
||||
"VRF: data Profile: DATA-AVT-POLICY-DEFAULT AVT path: direct:1 - Not active",
|
||||
|
@ -351,9 +248,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAVTSpecificPath,
|
||||
(VerifyAVTSpecificPath, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -383,7 +278,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"avts": {
|
||||
|
@ -415,11 +310,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"destination": "10.101.255.1",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"avt_paths": [
|
||||
|
@ -428,14 +323,10 @@ DATA: list[dict[str, Any]] = [
|
|||
{"avt_name": "DATA-AVT-POLICY-CONTROL-PLANE", "vrf": "data", "destination": "10.101.255.1", "next_hop": "10.101.255.2"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyAVTSpecificPath,
|
||||
"eos_data": [
|
||||
{"vrfs": {}},
|
||||
],
|
||||
(VerifyAVTSpecificPath, "failure-no-peer"): {
|
||||
"eos_data": [{"vrfs": {}}],
|
||||
"inputs": {
|
||||
"avt_paths": [
|
||||
{"avt_name": "MGMT-AVT-POLICY-DEFAULT", "vrf": "default", "destination": "10.101.255.2", "next_hop": "10.101.255.1", "path_type": "multihop"},
|
||||
|
@ -443,13 +334,11 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["AVT: MGMT-AVT-POLICY-DEFAULT VRF: default Destination: 10.101.255.2 Next-hop: 10.101.255.1 - No AVT path configured"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-path_type_check_true",
|
||||
"test": VerifyAVTSpecificPath,
|
||||
(VerifyAVTSpecificPath, "failure-path_type_check_true"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -469,7 +358,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"avts": {
|
||||
|
@ -486,11 +375,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"destination": "10.101.255.3",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"avt_paths": [
|
||||
|
@ -505,16 +394,14 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"AVT: DEFAULT-AVT-POLICY-CONTROL-PLANE VRF: default Destination: 10.101.255.2 Next-hop: 10.101.255.11 Path Type: multihop - Path not found",
|
||||
"AVT: DATA-AVT-POLICY-CONTROL-PLANE VRF: data Destination: 10.101.255.1 Next-hop: 10.101.255.21 Path Type: direct - Path not found",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-path_type_check_false",
|
||||
"test": VerifyAVTSpecificPath,
|
||||
(VerifyAVTSpecificPath, "failure-path_type_check_false"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -534,7 +421,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"avts": {
|
||||
|
@ -551,34 +438,27 @@ DATA: list[dict[str, Any]] = [
|
|||
"destination": "10.101.255.3",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"avt_paths": [
|
||||
{
|
||||
"avt_name": "DEFAULT-AVT-POLICY-CONTROL-PLANE",
|
||||
"vrf": "default",
|
||||
"destination": "10.101.255.2",
|
||||
"next_hop": "10.101.255.11",
|
||||
},
|
||||
{"avt_name": "DEFAULT-AVT-POLICY-CONTROL-PLANE", "vrf": "default", "destination": "10.101.255.2", "next_hop": "10.101.255.11"},
|
||||
{"avt_name": "DATA-AVT-POLICY-CONTROL-PLANE", "vrf": "data", "destination": "10.101.255.1", "next_hop": "10.101.255.21"},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"AVT: DEFAULT-AVT-POLICY-CONTROL-PLANE VRF: default Destination: 10.101.255.2 Next-hop: 10.101.255.11 - Path not found",
|
||||
"AVT: DATA-AVT-POLICY-CONTROL-PLANE VRF: data Destination: 10.101.255.1 Next-hop: 10.101.255.21 - Path not found",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-path",
|
||||
"test": VerifyAVTSpecificPath,
|
||||
(VerifyAVTSpecificPath, "failure-incorrect-path"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -590,10 +470,10 @@ DATA: list[dict[str, Any]] = [
|
|||
"flags": {"directPath": False, "valid": False, "active": True},
|
||||
"nexthopAddr": "10.101.255.1",
|
||||
"destination": "10.101.255.2",
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
"data": {
|
||||
"avts": {
|
||||
|
@ -625,11 +505,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"destination": "10.101.255.1",
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"avt_paths": [
|
||||
|
@ -644,29 +524,21 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"AVT: DEFAULT-AVT-POLICY-CONTROL-PLANE VRF: default Destination: 10.101.255.2 Next-hop: 10.101.255.1 - "
|
||||
"Incorrect path multihop:3 - Valid: False Active: True",
|
||||
"AVT: DATA-AVT-POLICY-CONTROL-PLANE VRF: data Destination: 10.101.255.1 Next-hop: 10.101.255.1 - "
|
||||
"Incorrect path direct:10 - Valid: False Active: True",
|
||||
"AVT: DATA-AVT-POLICY-CONTROL-PLANE VRF: data Destination: 10.101.255.1 Next-hop: 10.101.255.1 - "
|
||||
"Incorrect path direct:9 - Valid: True Active: False",
|
||||
"AVT: DEFAULT-AVT-POLICY-CONTROL-PLANE VRF: default Destination: 10.101.255.2 Next-hop: 10.101.255.1 - Incorrect path multihop:3 - "
|
||||
"Valid: False Active: True",
|
||||
"AVT: DATA-AVT-POLICY-CONTROL-PLANE VRF: data Destination: 10.101.255.1 Next-hop: 10.101.255.1 - Incorrect path direct:10 - "
|
||||
"Valid: False Active: True",
|
||||
"AVT: DATA-AVT-POLICY-CONTROL-PLANE VRF: data Destination: 10.101.255.1 Next-hop: 10.101.255.1 - Incorrect path direct:9 - "
|
||||
"Valid: True Active: False",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAVTRole,
|
||||
"eos_data": [{"role": "edge"}],
|
||||
"inputs": {"role": "edge"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-role",
|
||||
"test": VerifyAVTRole,
|
||||
(VerifyAVTRole, "success"): {"eos_data": [{"role": "edge"}], "inputs": {"role": "edge"}, "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyAVTRole, "failure-incorrect-role"): {
|
||||
"eos_data": [{"role": "transit"}],
|
||||
"inputs": {"role": "edge"},
|
||||
"expected": {"result": "failure", "messages": ["AVT role mismatch - Expected: edge Actual: transit"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AVT role mismatch - Expected: edge Actual: transit"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -6,15 +6,19 @@
|
|||
# pylint: disable=C0302
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.bfd import VerifyBFDPeersHealth, VerifyBFDPeersIntervals, VerifyBFDPeersRegProtocols, VerifyBFDSpecificPeers
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyBFDPeersIntervals, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -22,14 +26,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
"detectTime": 3600000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1200000, "operRxInterval": 1200000, "detectMult": 3, "detectTime": 3600000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -38,14 +35,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
"detectTime": 3600000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1200000, "operRxInterval": 1200000, "detectMult": 3, "detectTime": 3600000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -59,11 +49,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-detection-time",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
(VerifyBFDPeersIntervals, "success-detection-time"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -71,14 +59,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
"detectTime": 3600000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1200000, "operRxInterval": 1200000, "detectMult": 3, "detectTime": 3600000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -87,14 +68,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
"detectTime": 3600000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1200000, "operRxInterval": 1200000, "detectMult": 3, "detectTime": 3600000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -108,11 +82,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3, "detection_time": 3600},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
(VerifyBFDPeersIntervals, "failure-no-peer"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -120,14 +92,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
"detectTime": 3600000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1200000, "operRxInterval": 1200000, "detectMult": 3, "detectTime": 3600000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -136,14 +101,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
"detectTime": 3600000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1200000, "operRxInterval": 1200000, "detectMult": 3, "detectTime": 3600000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -157,17 +115,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3, "detection_time": 3600},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: CS - Not found",
|
||||
"Peer: 192.0.255.70 VRF: MGMT - Not found",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Peer: 192.0.255.7 VRF: CS - Not found", "Peer: 192.0.255.70 VRF: MGMT - Not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-timers",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
(VerifyBFDPeersIntervals, "failure-incorrect-timers"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -175,14 +125,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1300000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 4,
|
||||
"detectTime": 4000000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1300000, "operRxInterval": 1200000, "detectMult": 4, "detectTime": 4000000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -190,16 +133,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 120000,
|
||||
"operRxInterval": 120000,
|
||||
"detectMult": 5,
|
||||
"detectTime": 4000000,
|
||||
}
|
||||
}
|
||||
}
|
||||
"peerStats": {"": {"peerStatsDetail": {"operTxInterval": 120000, "operRxInterval": 120000, "detectMult": 5, "detectTime": 4000000}}}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -213,7 +147,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Incorrect Transmit interval - Expected: 1200 Actual: 1300",
|
||||
"Peer: 192.0.255.7 VRF: default - Incorrect Multiplier - Expected: 3 Actual: 4",
|
||||
|
@ -223,9 +157,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-timers-with-detection-time",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
(VerifyBFDPeersIntervals, "failure-incorrect-timers-with-detection-time"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
|
@ -233,14 +165,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1300000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 4,
|
||||
"detectTime": 4000000,
|
||||
}
|
||||
}
|
||||
"": {"peerStatsDetail": {"operTxInterval": 1300000, "operRxInterval": 1200000, "detectMult": 4, "detectTime": 4000000}}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -248,16 +173,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 120000,
|
||||
"operRxInterval": 120000,
|
||||
"detectMult": 5,
|
||||
"detectTime": 4000000,
|
||||
}
|
||||
}
|
||||
}
|
||||
"peerStats": {"": {"peerStatsDetail": {"operTxInterval": 120000, "operRxInterval": 120000, "detectMult": 5, "detectTime": 4000000}}}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
@ -271,7 +187,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Incorrect Transmit interval - Expected: 1200 Actual: 1300",
|
||||
"Peer: 192.0.255.7 VRF: default - Incorrect Multiplier - Expected: 3 Actual: 4",
|
||||
|
@ -283,354 +199,149 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDSpecificPeers,
|
||||
(VerifyBFDSpecificPeers, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 108328132,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 108328132,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {"ipv4Neighbors": {"192.0.255.7": {"peerStats": {"": {"status": "up", "remoteDisc": 108328132}}}}},
|
||||
"MGMT": {"ipv4Neighbors": {"192.0.255.70": {"peerStats": {"": {"status": "up", "remoteDisc": 108328132}}}}},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bfd_peers": [{"peer_address": "192.0.255.7", "vrf": "default"}, {"peer_address": "192.0.255.70", "vrf": "MGMT"}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyBFDSpecificPeers,
|
||||
(VerifyBFDSpecificPeers, "failure-no-peer"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 108328132,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 108328132,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {"ipv4Neighbors": {"192.0.255.7": {"peerStats": {"": {"status": "up", "remoteDisc": 108328132}}}}},
|
||||
"MGMT": {"ipv4Neighbors": {"192.0.255.71": {"peerStats": {"": {"status": "up", "remoteDisc": 108328132}}}}},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bfd_peers": [{"peer_address": "192.0.255.7", "vrf": "CS"}, {"peer_address": "192.0.255.70", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: CS - Not found",
|
||||
"Peer: 192.0.255.70 VRF: MGMT - Not found",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Peer: 192.0.255.7 VRF: CS - Not found", "Peer: 192.0.255.70 VRF: MGMT - Not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-session-down",
|
||||
"test": VerifyBFDSpecificPeers,
|
||||
(VerifyBFDSpecificPeers, "failure-session-down"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "down",
|
||||
"remoteDisc": 108328132,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "down",
|
||||
"remoteDisc": 0,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {"ipv4Neighbors": {"192.0.255.7": {"peerStats": {"": {"status": "down", "remoteDisc": 108328132}}}}},
|
||||
"MGMT": {"ipv4Neighbors": {"192.0.255.70": {"peerStats": {"": {"status": "down", "remoteDisc": 0}}}}},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bfd_peers": [{"peer_address": "192.0.255.7", "vrf": "default"}, {"peer_address": "192.0.255.70", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Session not properly established - State: down Remote Discriminator: 108328132",
|
||||
"Peer: 192.0.255.70 VRF: MGMT - Session not properly established - State: down Remote Discriminator: 0",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
(VerifyBFDPeersHealth, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 3940685114,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.7": {"peerStats": {"": {"status": "up", "remoteDisc": 3940685114, "lastDown": 1703657258.652725, "l3intf": ""}}}
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 3940685114,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.71": {"peerStats": {"": {"status": "up", "remoteDisc": 3940685114, "lastDown": 1703657258.652725, "l3intf": ""}}}
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703667348.111288,
|
||||
},
|
||||
{"utcTime": 1703667348.111288},
|
||||
],
|
||||
"inputs": {"down_threshold": 2},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
(VerifyBFDPeersHealth, "failure-no-peer"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"MGMT": {
|
||||
"ipv6Neighbors": {},
|
||||
"ipv4Neighbors": {},
|
||||
},
|
||||
"default": {
|
||||
"ipv6Neighbors": {},
|
||||
"ipv4Neighbors": {},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703658481.8778424,
|
||||
},
|
||||
{"vrfs": {"MGMT": {"ipv6Neighbors": {}, "ipv4Neighbors": {}}, "default": {"ipv6Neighbors": {}, "ipv4Neighbors": {}}}},
|
||||
{"utcTime": 1703658481.8778424},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["No IPv4 BFD peers are configured for any VRF"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No IPv4 BFD peers are configured for any VRF"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-session-down",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
(VerifyBFDPeersHealth, "failure-session-down"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "down",
|
||||
"remoteDisc": 0,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 3940685114,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.7": {"peerStats": {"": {"status": "down", "remoteDisc": 0, "lastDown": 1703657258.652725, "l3intf": ""}}},
|
||||
"192.0.255.70": {"peerStats": {"": {"status": "up", "remoteDisc": 3940685114, "lastDown": 1703657258.652725, "l3intf": ""}}},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "down",
|
||||
"remoteDisc": 0,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"ipv4Neighbors": {"192.0.255.71": {"peerStats": {"": {"status": "down", "remoteDisc": 0, "lastDown": 1703657258.652725, "l3intf": ""}}}},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703658481.8778424,
|
||||
},
|
||||
{"utcTime": 1703658481.8778424},
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Session not properly established - State: down Remote Discriminator: 0",
|
||||
"Peer: 192.0.255.71 VRF: MGMT - Session not properly established - State: down Remote Discriminator: 0",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-session-up-disc",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
(VerifyBFDPeersHealth, "failure-session-up-disc"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 0,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "Ethernet2",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 0,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "Ethernet2",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.7": {"peerStats": {"": {"status": "up", "remoteDisc": 0, "lastDown": 1703657258.652725, "l3intf": "Ethernet2"}}},
|
||||
"192.0.255.71": {"peerStats": {"": {"status": "up", "remoteDisc": 0, "lastDown": 1703657258.652725, "l3intf": "Ethernet2"}}},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703658481.8778424,
|
||||
},
|
||||
{"utcTime": 1703658481.8778424},
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Session not properly established - State: up Remote Discriminator: 0",
|
||||
"Peer: 192.0.255.71 VRF: default - Session not properly established - State: up Remote Discriminator: 0",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-last-down",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
(VerifyBFDPeersHealth, "failure-last-down"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 3940685114,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 3940685114,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.17": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 3940685114,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
"192.0.255.7": {"peerStats": {"": {"status": "up", "remoteDisc": 3940685114, "lastDown": 1703657258.652725, "l3intf": ""}}},
|
||||
"192.0.255.71": {"peerStats": {"": {"status": "up", "remoteDisc": 3940685114, "lastDown": 1703657258.652725, "l3intf": ""}}},
|
||||
"192.0.255.17": {"peerStats": {"": {"status": "up", "remoteDisc": 3940685114, "lastDown": 1703657258.652725, "l3intf": ""}}},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703667348.111288,
|
||||
},
|
||||
{"utcTime": 1703667348.111288},
|
||||
],
|
||||
"inputs": {"down_threshold": 4},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Session failure detected within the expected uptime threshold (3 hours ago)",
|
||||
"Peer: 192.0.255.71 VRF: default - Session failure detected within the expected uptime threshold (3 hours ago)",
|
||||
|
@ -638,42 +349,18 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDPeersRegProtocols,
|
||||
(VerifyBFDPeersRegProtocols, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 108328132,
|
||||
"peerStatsDetail": {
|
||||
"role": "active",
|
||||
"apps": ["ospf"],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
"192.0.255.7": {"peerStats": {"": {"status": "up", "remoteDisc": 108328132, "peerStatsDetail": {"role": "active", "apps": ["ospf"]}}}}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 108328132,
|
||||
"peerStatsDetail": {
|
||||
"role": "active",
|
||||
"apps": ["bgp"],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
"192.0.255.70": {"peerStats": {"": {"status": "up", "remoteDisc": 108328132, "peerStatsDetail": {"role": "active", "apps": ["bgp"]}}}}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -685,43 +372,16 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "protocols": ["bgp"]},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyBFDPeersRegProtocols,
|
||||
(VerifyBFDPeersRegProtocols, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"peerStatsDetail": {
|
||||
"role": "active",
|
||||
"apps": ["ospf"],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"default": {"ipv4Neighbors": {"192.0.255.7": {"peerStats": {"": {"status": "up", "peerStatsDetail": {"role": "active", "apps": ["ospf"]}}}}}},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "up",
|
||||
"remoteDisc": 0,
|
||||
"peerStatsDetail": {
|
||||
"role": "active",
|
||||
"apps": ["bgp"],
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
"192.0.255.70": {"peerStats": {"": {"status": "up", "remoteDisc": 0, "peerStatsDetail": {"role": "active", "apps": ["bgp"]}}}}
|
||||
}
|
||||
},
|
||||
}
|
||||
|
@ -734,36 +394,21 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - `isis` routing protocol(s) not configured",
|
||||
"Peer: 192.0.255.70 VRF: MGMT - `isis`, `ospf` routing protocol(s) not configured",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-found",
|
||||
"test": VerifyBFDPeersRegProtocols,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {},
|
||||
"MGMT": {},
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifyBFDPeersRegProtocols, "failure-not-found"): {
|
||||
"eos_data": [{"vrfs": {"default": {}, "MGMT": {}}}],
|
||||
"inputs": {
|
||||
"bfd_peers": [
|
||||
{"peer_address": "192.0.255.7", "vrf": "default", "protocols": ["isis"]},
|
||||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "protocols": ["isis"]},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Peer: 192.0.255.7 VRF: default - Not found",
|
||||
"Peer: 192.0.255.70 VRF: MGMT - Not found",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Peer: 192.0.255.7 VRF: default - Not found", "Peer: 192.0.255.70 VRF: MGMT - Not found"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,59 +5,34 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.configuration import VerifyRunningConfigDiffs, VerifyRunningConfigLines, VerifyZeroTouch
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyZeroTouch,
|
||||
"eos_data": [{"mode": "disabled"}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyZeroTouch,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyZeroTouch, "success"): {"eos_data": [{"mode": "disabled"}], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyZeroTouch, "failure"): {
|
||||
"eos_data": [{"mode": "enabled"}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["ZTP is NOT disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["ZTP is NOT disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRunningConfigDiffs,
|
||||
"eos_data": [""],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyRunningConfigDiffs,
|
||||
"eos_data": ["blah blah"],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["blah blah"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRunningConfigLines,
|
||||
"eos_data": ["blah blah"],
|
||||
"inputs": {"regex_patterns": ["blah"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRunningConfigLines,
|
||||
(VerifyRunningConfigDiffs, "success"): {"eos_data": [""], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyRunningConfigDiffs, "failure"): {"eos_data": ["blah blah"], "expected": {"result": AntaTestStatus.FAILURE, "messages": ["blah blah"]}},
|
||||
(VerifyRunningConfigLines, "success"): {"eos_data": ["blah blah"], "inputs": {"regex_patterns": ["blah"]}, "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyRunningConfigLines, "success-patterns"): {
|
||||
"eos_data": ["enable password something\nsome other line"],
|
||||
"inputs": {"regex_patterns": ["^enable password .*$", "^.*other line$"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyRunningConfigLines,
|
||||
(VerifyRunningConfigLines, "failure"): {
|
||||
"eos_data": ["enable password something\nsome other line"],
|
||||
"inputs": {"regex_patterns": ["bla", "bleh"]},
|
||||
"expected": {"result": "failure", "messages": ["Following patterns were not found: 'bla', 'bleh'"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Following patterns were not found: 'bla', 'bleh"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,313 +5,244 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.connectivity import VerifyLLDPNeighbors, VerifyReachability
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success-ip",
|
||||
"test": VerifyReachability,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyReachability, "success-ip"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "10.0.0.5"}, {"destination": "10.0.0.2", "source": "10.0.0.5"}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
"PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.1 ping statistics ---\n"
|
||||
" 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.2 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
"PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.2 ping statistics ---\n"
|
||||
" 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-expected-unreachable",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-expected-unreachable"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
2 packets transmitted, 0 received, 100% packet loss, time 10ms
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.\n\n --- 10.0.0.1 ping statistics ---\n"
|
||||
" 2 packets transmitted, 0 received, 100% packet loss, time 10ms\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "10.0.0.5", "reachable": False}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-ipv6",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-ipv6"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING fd12:3456:789a:1::2(fd12:3456:789a:1::2) from fd12:3456:789a:1::1 : 52 data bytes
|
||||
60 bytes from fd12:3456:789a:1::2: icmp_seq=1 ttl=64 time=0.097 ms
|
||||
60 bytes from fd12:3456:789a:1::2: icmp_seq=2 ttl=64 time=0.033 ms
|
||||
|
||||
--- fd12:3456:789a:1::2 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.033/0.065/0.097/0.032 ms, ipg/ewma 0.148/0.089 ms
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING fd12:3456:789a:1::2(fd12:3456:789a:1::2) from fd12:3456:789a:1::1 : 52 data bytes\n 60 bytes from fd12:3456:789a:1::2:"
|
||||
" icmp_seq=1 ttl=64 time=0.097 ms\n 60 bytes from fd12:3456:789a:1::2: icmp_seq=2 ttl=64 time=0.033 ms\n\n"
|
||||
" --- fd12:3456:789a:1::2 ping statistics ---\n 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n"
|
||||
" rtt min/avg/max/mdev = 0.033/0.065/0.097/0.032 ms, ipg/ewma 0.148/0.089 ms\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"hosts": [{"destination": "fd12:3456:789a:1::2", "source": "fd12:3456:789a:1::1"}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-ipv6-vlan",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-ipv6-vlan"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING fd12:3456:789a:1::2(fd12:3456:789a:1::2) 52 data bytes
|
||||
60 bytes from fd12:3456:789a:1::2: icmp_seq=1 ttl=64 time=0.094 ms
|
||||
60 bytes from fd12:3456:789a:1::2: icmp_seq=2 ttl=64 time=0.027 ms
|
||||
|
||||
--- fd12:3456:789a:1::2 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.027/0.060/0.094/0.033 ms, ipg/ewma 0.152/0.085 ms
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING fd12:3456:789a:1::2(fd12:3456:789a:1::2) 52 data bytes\n 60 bytes from fd12:3456:789a:1::2: "
|
||||
"icmp_seq=1 ttl=64 time=0.094 ms\n 60 bytes from fd12:3456:789a:1::2: icmp_seq=2 ttl=64 time=0.027 ms\n\n"
|
||||
" --- fd12:3456:789a:1::2 ping statistics ---\n 2 packets transmitted, 2 received, 0% packet loss,"
|
||||
" time 0ms\n rtt min/avg/max/mdev = 0.027/0.060/0.094/0.033 ms, ipg/ewma 0.152/0.085 ms\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"hosts": [{"destination": "fd12:3456:789a:1::2", "source": "vl110"}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-interface",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-interface"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "Management0"}, {"destination": "10.0.0.2", "source": "Management0"}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
"PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.1 ping statistics ---\n"
|
||||
" 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.2 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
"PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.2 ping statistics ---\n"
|
||||
" 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-repeat",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-repeat"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "Management0", "repeat": 1}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
1 packets transmitted, 1 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms\n\n"
|
||||
" --- 10.0.0.1 ping statistics ---\n 1 packets transmitted, 1 received, 0% packet loss, time 0ms\n"
|
||||
" rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-df-bit-size",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-df-bit-size"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "Management0", "repeat": 5, "size": 1500, "df_bit": True}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 172.20.20.6 : 1472(1500) bytes of data.
|
||||
1480 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.085 ms
|
||||
1480 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.020 ms
|
||||
1480 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.019 ms
|
||||
1480 bytes from 10.0.0.1: icmp_seq=4 ttl=64 time=0.018 ms
|
||||
1480 bytes from 10.0.0.1: icmp_seq=5 ttl=64 time=0.017 ms
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
5 packets transmitted, 5 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.017/0.031/0.085/0.026 ms, ipg/ewma 0.061/0.057 ms""",
|
||||
],
|
||||
},
|
||||
"PING 10.0.0.1 (10.0.0.1) from 172.20.20.6 : 1472(1500) bytes of data.\n 1480 bytes from 10.0.0.1: "
|
||||
"icmp_seq=1 ttl=64 time=0.085 ms\n 1480 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.020 ms\n"
|
||||
" 1480 bytes from 10.0.0.1: icmp_seq=3 ttl=64 time=0.019 ms\n 1480 bytes from 10.0.0.1:"
|
||||
" icmp_seq=4 ttl=64 time=0.018 ms\n 1480 bytes from 10.0.0.1:"
|
||||
" icmp_seq=5 ttl=64 time=0.017 ms\n\n --- 10.0.0.1 ping statistics ---\n 5 packets transmitted,"
|
||||
" 5 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.017/0.031/0.085/0.026 ms, ipg/ewma 0.061/0.057 ms"
|
||||
]
|
||||
}
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-ip",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "success-without-source"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "repeat": 1}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"PING 10.0.0.1 (10.0.0.1) : 72(100) bytes of data.\n 80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms\n\n"
|
||||
" --- 10.0.0.1 ping statistics ---\n 1 packets transmitted, 1 received, 0% packet loss, time 0ms\n"
|
||||
" rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyReachability, "failure-ip"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.11", "source": "10.0.0.5"}, {"destination": "10.0.0.2", "source": "10.0.0.5"}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""ping: sendmsg: Network is unreachable
|
||||
ping: sendmsg: Network is unreachable
|
||||
PING 10.0.0.11 (10.0.0.11) from 10.0.0.5 : 72(100) bytes of data.
|
||||
|
||||
--- 10.0.0.11 ping statistics ---
|
||||
2 packets transmitted, 0 received, 100% packet loss, time 10ms
|
||||
|
||||
|
||||
""",
|
||||
],
|
||||
"ping: sendmsg: Network is unreachable\n ping: sendmsg: Network is unreachable\n "
|
||||
"PING 10.0.0.11 (10.0.0.11) from 10.0.0.5 : 72(100) bytes of data.\n\n --- 10.0.0.11 ping statistics ---\n"
|
||||
" 2 packets transmitted, 0 received, 100% packet loss, time 10ms\n\n\n "
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.2 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
"PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.2 ping statistics ---\n "
|
||||
"2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["Host: 10.0.0.11 Source: 10.0.0.5 VRF: default - Unreachable"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Host: 10.0.0.11 Source: 10.0.0.5 VRF: default - Unreachable"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-ipv6",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "failure-ipv6"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING fd12:3456:789a:1::2(fd12:3456:789a:1::2) from fd12:3456:789a:1::1 : 52 data bytes
|
||||
|
||||
--- fd12:3456:789a:1::3 ping statistics ---
|
||||
2 packets transmitted, 0 received, 100% packet loss, time 10ms
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING fd12:3456:789a:1::2(fd12:3456:789a:1::2) from fd12:3456:789a:1::1 : 52 data bytes\n\n --- fd12:3456:789a:1::3 "
|
||||
"ping statistics ---\n 2 packets transmitted, 0 received, 100% packet loss, time 10ms\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"hosts": [{"destination": "fd12:3456:789a:1::2", "source": "fd12:3456:789a:1::1"}]},
|
||||
"expected": {"result": "failure", "messages": ["Host: fd12:3456:789a:1::2 Source: fd12:3456:789a:1::1 VRF: default - Unreachable"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Host: fd12:3456:789a:1::2 Source: fd12:3456:789a:1::1 VRF: default - Unreachable"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-interface",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "failure-interface"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.11", "source": "Management0"}, {"destination": "10.0.0.2", "source": "Management0"}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""ping: sendmsg: Network is unreachable
|
||||
ping: sendmsg: Network is unreachable
|
||||
PING 10.0.0.11 (10.0.0.11) from 10.0.0.5 : 72(100) bytes of data.
|
||||
|
||||
--- 10.0.0.11 ping statistics ---
|
||||
2 packets transmitted, 0 received, 100% packet loss, time 10ms
|
||||
|
||||
|
||||
""",
|
||||
],
|
||||
"ping: sendmsg: Network is unreachable\n ping: sendmsg: Network is unreachable\n "
|
||||
"PING 10.0.0.11 (10.0.0.11) from 10.0.0.5 : 72(100) bytes of data.\n\n --- 10.0.0.11 ping statistics ---\n"
|
||||
" 2 packets transmitted, 0 received, 100% packet loss, time 10ms\n\n\n "
|
||||
]
|
||||
},
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.2 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
"PING 10.0.0.2 (10.0.0.2) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.2: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.2: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.2 ping statistics ---\n"
|
||||
" 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["Host: 10.0.0.11 Source: Management0 VRF: default - Unreachable"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Host: 10.0.0.11 Source: Management0 VRF: default - Unreachable"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-size",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "failure-size"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "Management0", "repeat": 5, "size": 1501, "df_bit": True}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 172.20.20.6 : 1473(1501) bytes of data.
|
||||
ping: local error: message too long, mtu=1500
|
||||
ping: local error: message too long, mtu=1500
|
||||
ping: local error: message too long, mtu=1500
|
||||
ping: local error: message too long, mtu=1500
|
||||
ping: local error: message too long, mtu=1500
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
5 packets transmitted, 0 received, +5 errors, 100% packet loss, time 40ms
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING 10.0.0.1 (10.0.0.1) from 172.20.20.6 : 1473(1501) bytes of data.\n ping: local error: message too long, mtu=1500\n"
|
||||
" ping: local error: message too long, mtu=1500\n"
|
||||
" ping: local error: message too long, mtu=1500\n ping: local error: message too long, mtu=1500\n"
|
||||
" ping: local error: message too long, mtu=1500\n\n --- 10.0.0.1 ping statistics ---\n"
|
||||
" 5 packets transmitted, 0 received, +5 errors, 100% packet loss, time 40ms\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["Host: 10.0.0.1 Source: Management0 VRF: default - Unreachable"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Host: 10.0.0.1 Source: Management0 VRF: default - Unreachable"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-expected-unreachable",
|
||||
"test": VerifyReachability,
|
||||
(VerifyReachability, "failure-expected-unreachable"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"""PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.
|
||||
80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms
|
||||
80 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.072 ms
|
||||
|
||||
--- 10.0.0.1 ping statistics ---
|
||||
2 packets transmitted, 2 received, 0% packet loss, time 0ms
|
||||
rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms, ipg/ewma 0.370/0.225 ms
|
||||
|
||||
""",
|
||||
],
|
||||
},
|
||||
"PING 10.0.0.1 (10.0.0.1) from 10.0.0.5 : 72(100) bytes of data.\n 80 bytes from 10.0.0.1: icmp_seq=1 ttl=64 time=0.247 ms\n"
|
||||
" 80 bytes from 10.0.0.1: icmp_seq=2 ttl=64 time=0.072 ms\n\n --- 10.0.0.1 ping statistics ---\n"
|
||||
" 2 packets transmitted, 2 received, 0% packet loss, time 0ms\n rtt min/avg/max/mdev = 0.072/0.159/0.247/0.088 ms,"
|
||||
" ipg/ewma 0.370/0.225 ms\n\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "source": "10.0.0.5", "reachable": False}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Host: 10.0.0.1 Source: 10.0.0.5 VRF: default - Destination is expected to be unreachable but found reachable"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyReachability, "failure-without-source"): {
|
||||
"inputs": {"hosts": [{"destination": "10.0.0.1", "repeat": 1}]},
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"ping: sendmsg: Network is unreachable\n PING 10.0.0.1 (10.0.0.1) : 72(100) bytes of data.\n\n"
|
||||
" --- 10.0.0.11 ping statistics ---\n "
|
||||
"2 packets transmitted, 0 received, 100% packet loss, time 10ms\n\n "
|
||||
]
|
||||
}
|
||||
],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Host: 10.0.0.1 VRF: default - Unreachable"]},
|
||||
},
|
||||
(VerifyLLDPNeighbors, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -323,12 +254,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {
|
||||
"lldpNeighborInfo": [
|
||||
|
@ -338,27 +269,25 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE2",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet2",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-multiple-neighbors",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyLLDPNeighbors, "success-multiple-neighbors"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -370,7 +299,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
|
@ -381,26 +310,20 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE2",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet2",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"inputs": {"neighbors": [{"port": "Ethernet1", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"}]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-port-not-configured",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyLLDPNeighbors, "failure-port-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -412,27 +335,25 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
]
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - Port not found"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - Port not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-neighbor",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyLLDPNeighbors, "failure-no-neighbor"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -444,28 +365,26 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {"lldpNeighborInfo": []},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
]
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - No LLDP neighbors"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - No LLDP neighbors"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-neighbor",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyLLDPNeighbors, "failure-wrong-neighbor"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -477,12 +396,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {
|
||||
"lldpNeighborInfo": [
|
||||
|
@ -492,30 +411,28 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE2",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet2"',
|
||||
"interfaceId": "Ethernet2",
|
||||
"interfaceId_v2": "Ethernet2",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet2",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: DC1-SPINE2/Ethernet2"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-multiple",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyLLDPNeighbors, "failure-multiple"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -527,26 +444,26 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet2"',
|
||||
"interfaceId": "Ethernet2",
|
||||
"interfaceId_v2": "Ethernet2",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {"lldpNeighborInfo": []},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet3", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Port: Ethernet1 Neighbor: DC1-SPINE1 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: DC1-SPINE1/Ethernet2",
|
||||
"Port: Ethernet2 Neighbor: DC1-SPINE2 Neighbor Port: Ethernet1 - No LLDP neighbors",
|
||||
|
@ -554,9 +471,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-multiple-neighbors",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
(VerifyLLDPNeighbors, "failure-multiple-neighbors"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
|
@ -568,7 +483,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
|
@ -579,24 +494,20 @@ DATA: list[dict[str, Any]] = [
|
|||
"systemName": "DC1-SPINE2",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId": "Ethernet1",
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet2",
|
||||
},
|
||||
},
|
||||
],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"},
|
||||
],
|
||||
},
|
||||
"inputs": {"neighbors": [{"port": "Ethernet1", "neighbor_device": "DC1-SPINE3", "neighbor_port": "Ethernet1"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Port: Ethernet1 Neighbor: DC1-SPINE3 Neighbor Port: Ethernet1 - Wrong LLDP neighbors: DC1-SPINE1/Ethernet1, DC1-SPINE2/Ethernet1"],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,182 +5,127 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.cvx import VerifyActiveCVXConnections, VerifyCVXClusterStatus, VerifyManagementCVX, VerifyMcsClientMounts, VerifyMcsServerMounts
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMcsClientMounts,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyMcsClientMounts, "success"): {
|
||||
"eos_data": [{"mountStates": [{"path": "mcs/v1/toSwitch/28-99-3a-8f-93-7b", "type": "Mcs::DeviceConfigV1", "state": "mountStateMountComplete"}]}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-haclient",
|
||||
"test": VerifyMcsClientMounts,
|
||||
(VerifyMcsClientMounts, "success-haclient"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"mountStates": [
|
||||
{"path": "mcs/v1/apiCfgRedState", "type": "Mcs::ApiConfigRedundancyState", "state": "mountStateMountComplete"},
|
||||
{"path": "mcs/v1/toSwitch/00-1c-73-74-c0-8b", "type": "Mcs::DeviceConfigV1", "state": "mountStateMountComplete"},
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-partial-non-mcs",
|
||||
"test": VerifyMcsClientMounts,
|
||||
(VerifyMcsClientMounts, "success-partial-non-mcs"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"mountStates": [
|
||||
{"path": "blah/blah/blah", "type": "blah::blah", "state": "mountStatePreservedUnmounted"},
|
||||
{"path": "mcs/v1/toSwitch/00-1c-73-74-c0-8b", "type": "Mcs::DeviceConfigV1", "state": "mountStateMountComplete"},
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-nomounts",
|
||||
"test": VerifyMcsClientMounts,
|
||||
"eos_data": [
|
||||
{"mountStates": []},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["MCS Client mount states are not present"]},
|
||||
(VerifyMcsClientMounts, "failure-nomounts"): {
|
||||
"eos_data": [{"mountStates": []}],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MCS Client mount states are not present"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-mountStatePreservedUnmounted",
|
||||
"test": VerifyMcsClientMounts,
|
||||
(VerifyMcsClientMounts, "failure-mountStatePreservedUnmounted"): {
|
||||
"eos_data": [{"mountStates": [{"path": "mcs/v1/toSwitch/28-99-3a-8f-93-7b", "type": "Mcs::DeviceConfigV1", "state": "mountStatePreservedUnmounted"}]}],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["MCS Client mount states are not valid - Expected: mountStateMountComplete Actual: mountStatePreservedUnmounted"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-partial-haclient",
|
||||
"test": VerifyMcsClientMounts,
|
||||
(VerifyMcsClientMounts, "failure-partial-haclient"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"mountStates": [
|
||||
{"path": "mcs/v1/apiCfgRedState", "type": "Mcs::ApiConfigRedundancyState", "state": "mountStateMountComplete"},
|
||||
{"path": "mcs/v1/toSwitch/00-1c-73-74-c0-8b", "type": "Mcs::DeviceConfigV1", "state": "mountStatePreservedUnmounted"},
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["MCS Client mount states are not valid - Expected: mountStateMountComplete Actual: mountStatePreservedUnmounted"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-full-haclient",
|
||||
"test": VerifyMcsClientMounts,
|
||||
(VerifyMcsClientMounts, "failure-full-haclient"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"mountStates": [
|
||||
{"path": "blah/blah/blah", "type": "blah::blahState", "state": "mountStatePreservedUnmounted"},
|
||||
{"path": "mcs/v1/toSwitch/00-1c-73-74-c0-8b", "type": "Mcs::DeviceConfigV1", "state": "mountStatePreservedUnmounted"},
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["MCS Client mount states are not valid - Expected: mountStateMountComplete Actual: mountStatePreservedUnmounted"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-non-mcs-client",
|
||||
"test": VerifyMcsClientMounts,
|
||||
"eos_data": [
|
||||
{"mountStates": [{"path": "blah/blah/blah", "type": "blah::blahState", "state": "mountStatePreservedUnmounted"}]},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["MCS Client mount states are not present"]},
|
||||
(VerifyMcsClientMounts, "failure-non-mcs-client"): {
|
||||
"eos_data": [{"mountStates": [{"path": "blah/blah/blah", "type": "blah::blahState", "state": "mountStatePreservedUnmounted"}]}],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MCS Client mount states are not present"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-partial-mcs-client",
|
||||
"test": VerifyMcsClientMounts,
|
||||
(VerifyMcsClientMounts, "failure-partial-mcs-client"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"mountStates": [
|
||||
{"path": "blah/blah/blah", "type": "blah::blahState", "state": "mountStatePreservedUnmounted"},
|
||||
{"path": "blah/blah/blah", "type": "Mcs::DeviceConfigV1", "state": "mountStatePreservedUnmounted"},
|
||||
]
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["MCS Client mount states are not valid - Expected: mountStateMountComplete Actual: mountStatePreservedUnmounted"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success-enabled",
|
||||
"test": VerifyManagementCVX,
|
||||
"eos_data": [
|
||||
{
|
||||
"clusterStatus": {
|
||||
"enabled": True,
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifyManagementCVX, "success-enabled"): {
|
||||
"eos_data": [{"clusterStatus": {"enabled": True}}],
|
||||
"inputs": {"enabled": True},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-disabled",
|
||||
"test": VerifyManagementCVX,
|
||||
"eos_data": [
|
||||
{
|
||||
"clusterStatus": {
|
||||
"enabled": False,
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifyManagementCVX, "success-disabled"): {
|
||||
"eos_data": [{"clusterStatus": {"enabled": False}}],
|
||||
"inputs": {"enabled": False},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-state",
|
||||
"test": VerifyManagementCVX,
|
||||
"eos_data": [
|
||||
{
|
||||
"clusterStatus": {
|
||||
"enabled": False,
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifyManagementCVX, "failure-invalid-state"): {
|
||||
"eos_data": [{"clusterStatus": {"enabled": False}}],
|
||||
"inputs": {"enabled": True},
|
||||
"expected": {"result": "failure", "messages": ["Management CVX status is not valid: Expected: enabled Actual: disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Management CVX status is not valid: Expected: enabled Actual: disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-enabled state",
|
||||
"test": VerifyManagementCVX,
|
||||
(VerifyManagementCVX, "failure-no-enabled state"): {
|
||||
"eos_data": [{"clusterStatus": {}}],
|
||||
"inputs": {"enabled": False},
|
||||
"expected": {"result": "failure", "messages": ["Management CVX status - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Management CVX status - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure - no clusterStatus",
|
||||
"test": VerifyManagementCVX,
|
||||
(VerifyManagementCVX, "failure - no clusterStatus"): {
|
||||
"eos_data": [{}],
|
||||
"inputs": {"enabled": False},
|
||||
"expected": {"result": "failure", "messages": ["Management CVX status - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Management CVX status - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
|
@ -205,21 +150,17 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-mounts",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "failure-no-mounts"): {
|
||||
"eos_data": [{"connections": [{"hostname": "media-leaf-1", "mounts": []}]}],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Host: media-leaf-1 - No mount status found", "Incorrect CVX successful connections count - Expected: 1 Actual: 0"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-unexpected-number-paths",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "failure-unexpected-number-paths"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
|
@ -244,17 +185,15 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Host: media-leaf-1 - Incorrect number of mount path states - Expected: 3 Actual: 2",
|
||||
"Host: media-leaf-1 - Unexpected MCS path type - Expected: Mcs::ApiConfigRedundancyStatus, Mcs::ActiveFlows, "
|
||||
"Mcs::Client::Status Actual: Mcs::ApiStatus",
|
||||
"Host: media-leaf-1 - Unexpected MCS path type - Expected: Mcs::ApiConfigRedundancyStatus, "
|
||||
"Mcs::ActiveFlows, Mcs::Client::Status Actual: Mcs::ApiStatus",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-unexpected-path-type",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "failure-unexpected-path-type"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
|
@ -280,16 +219,14 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Host: media-leaf-1 - Unexpected MCS path type - Expected: Mcs::ApiConfigRedundancyStatus, Mcs::ActiveFlows, Mcs::Client::Status"
|
||||
" Actual: Mcs::ApiStatus"
|
||||
"Host: media-leaf-1 - Unexpected MCS path type - Expected: Mcs::ApiConfigRedundancyStatus, Mcs::ActiveFlows, "
|
||||
"Mcs::Client::Status Actual: Mcs::ApiStatus"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-mount-state",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "failure-invalid-mount-state"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
|
@ -315,16 +252,14 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Host: media-leaf-1 Path Type: Mcs::ApiConfigRedundancyStatus - MCS server mount state is not valid - Expected: mountStateMountComplete"
|
||||
" Actual:mountStateMountFailed"
|
||||
"Host: media-leaf-1 Path Type: Mcs::ApiConfigRedundancyStatus - MCS server mount state is not valid - "
|
||||
"Expected: mountStateMountComplete Actual:mountStateMountFailed"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-mcs-mount",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "failure-no-mcs-mount"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
|
@ -341,69 +276,46 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {"result": "failure", "messages": ["MCS mount state not detected", "Incorrect CVX successful connections count - Expected: 1 Actual: 0"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["MCS mount state not detected", "Incorrect CVX successful connections count - Expected: 1 Actual: 0"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-connections",
|
||||
"test": VerifyMcsServerMounts,
|
||||
(VerifyMcsServerMounts, "failure-connections"): {
|
||||
"eos_data": [{}],
|
||||
"inputs": {"connections_count": 1},
|
||||
"expected": {"result": "failure", "messages": ["CVX connections are not available"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["CVX connections are not available"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyActiveCVXConnections,
|
||||
(VerifyActiveCVXConnections, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
{
|
||||
"switchId": "fc:bd:67:c3:16:55",
|
||||
"hostname": "lyv563",
|
||||
"oobConnectionActive": True,
|
||||
},
|
||||
{
|
||||
"switchId": "00:1c:73:3c:e3:9e",
|
||||
"hostname": "tg264",
|
||||
"oobConnectionActive": True,
|
||||
},
|
||||
{"switchId": "fc:bd:67:c3:16:55", "hostname": "lyv563", "oobConnectionActive": True},
|
||||
{"switchId": "00:1c:73:3c:e3:9e", "hostname": "tg264", "oobConnectionActive": True},
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"connections_count": 2},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyActiveCVXConnections,
|
||||
(VerifyActiveCVXConnections, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"connections": [
|
||||
{
|
||||
"switchId": "fc:bd:67:c3:16:55",
|
||||
"hostname": "lyv563",
|
||||
"oobConnectionActive": False,
|
||||
},
|
||||
{
|
||||
"switchId": "00:1c:73:3c:e3:9e",
|
||||
"hostname": "tg264",
|
||||
"oobConnectionActive": True,
|
||||
},
|
||||
{"switchId": "fc:bd:67:c3:16:55", "hostname": "lyv563", "oobConnectionActive": False},
|
||||
{"switchId": "00:1c:73:3c:e3:9e", "hostname": "tg264", "oobConnectionActive": True},
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {"connections_count": 2},
|
||||
"expected": {"result": "failure", "messages": ["CVX active connections count - Expected: 2 Actual: 1"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["CVX active connections count - Expected: 2 Actual: 1"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-connections",
|
||||
"test": VerifyActiveCVXConnections,
|
||||
(VerifyActiveCVXConnections, "failure-no-connections"): {
|
||||
"eos_data": [{}],
|
||||
"inputs": {"connections_count": 2},
|
||||
"expected": {"result": "failure", "messages": ["CVX connections are not available"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["CVX connections are not available"]},
|
||||
},
|
||||
{
|
||||
"name": "success-all",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
(VerifyCVXClusterStatus, "success-all"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
|
@ -424,11 +336,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_name": "cvx-red-3", "registrationState": "Registration complete"},
|
||||
],
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-role",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
(VerifyCVXClusterStatus, "failure-invalid-role"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
|
@ -449,56 +359,24 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_name": "cvx-red-3", "registrationState": "Registration complete"},
|
||||
],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["CVX Role is not valid: Expected: Master Actual: Standby"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["CVX Role is not valid: Expected: Master Actual: Standby"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-cvx-enabled",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": False,
|
||||
"clusterMode": True,
|
||||
"clusterStatus": {
|
||||
"role": "Master",
|
||||
"peerStatus": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"role": "Master",
|
||||
"peer_status": [],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["CVX Server status is not enabled"]},
|
||||
(VerifyCVXClusterStatus, "failure-cvx-enabled"): {
|
||||
"eos_data": [{"enabled": False, "clusterMode": True, "clusterStatus": {"role": "Master", "peerStatus": {}}}],
|
||||
"inputs": {"role": "Master", "peer_status": []},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["CVX Server status is not enabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-cluster-enabled",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"clusterMode": False,
|
||||
"clusterStatus": {},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"role": "Master",
|
||||
"peer_status": [],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["CVX Server is not a cluster"]},
|
||||
(VerifyCVXClusterStatus, "failure-cluster-enabled"): {
|
||||
"eos_data": [{"enabled": True, "clusterMode": False, "clusterStatus": {}}],
|
||||
"inputs": {"role": "Master", "peer_status": []},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["CVX Server is not a cluster"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-peers",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
(VerifyCVXClusterStatus, "failure-missing-peers"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"clusterMode": True,
|
||||
"clusterStatus": {
|
||||
"role": "Master",
|
||||
"peerStatus": {
|
||||
"cvx-red-2": {"peerName": "cvx-red-2", "registrationState": "Registration complete"},
|
||||
},
|
||||
},
|
||||
"clusterStatus": {"role": "Master", "peerStatus": {"cvx-red-2": {"peerName": "cvx-red-2", "registrationState": "Registration complete"}}},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
|
@ -508,21 +386,10 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_name": "cvx-red-3", "registrationState": "Registration complete"},
|
||||
],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["Unexpected number of peers - Expected: 2 Actual: 1", "cvx-red-3 - Not present"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Unexpected number of peers - Expected: 2 Actual: 1", "cvx-red-3 - Not present"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-peers",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"clusterMode": True,
|
||||
"clusterStatus": {
|
||||
"role": "Master",
|
||||
"peerStatus": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
(VerifyCVXClusterStatus, "failure-invalid-peers"): {
|
||||
"eos_data": [{"enabled": True, "clusterMode": True, "clusterStatus": {"role": "Master", "peerStatus": {}}}],
|
||||
"inputs": {
|
||||
"role": "Master",
|
||||
"peer_status": [
|
||||
|
@ -530,11 +397,12 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_name": "cvx-red-3", "registrationState": "Registration complete"},
|
||||
],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["Unexpected number of peers - Expected: 2 Actual: 0", "cvx-red-2 - Not present", "cvx-red-3 - Not present"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Unexpected number of peers - Expected: 2 Actual: 0", "cvx-red-2 - Not present", "cvx-red-3 - Not present"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-registration-error",
|
||||
"test": VerifyCVXClusterStatus,
|
||||
(VerifyCVXClusterStatus, "failure-registration-error"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
|
@ -555,6 +423,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer_name": "cvx-red-3", "registrationState": "Registration complete"},
|
||||
],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["cvx-red-2 - Invalid registration state - Expected: Registration complete Actual: Registration error"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["cvx-red-2 - Invalid registration state - Expected: Registration complete Actual: Registration error"],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
449
tests/units/anta_tests/test_evpn.py
Normal file
449
tests/units/anta_tests/test_evpn.py
Normal file
|
@ -0,0 +1,449 @@
|
|||
# Copyright (c) 2023-2025 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Tests for anta.tests.evpn.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.evpn import VerifyEVPNType5Routes
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyEVPNType5Routes, "success-all"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [{"nextHop": "10.100.2.3", "routeType": {"active": True, "valid": True}}],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [{"nextHop": "10.100.2.3", "routeType": {"active": True, "valid": True}}],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [
|
||||
{"address": "10.100.0.128/31", "vni": 10},
|
||||
{"address": "10.100.0.128/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local"}]},
|
||||
{"address": "10.100.4.0/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3"}]}]},
|
||||
{
|
||||
"address": "10.100.4.1/31",
|
||||
"vni": 10,
|
||||
"routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3", "route_targets": ["10:10"]}]}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "success-ipv6"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.1.0.21",
|
||||
"asn": 65120,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.1.0.21:500 ip-prefix fd00:dc:5::1/128": {
|
||||
"totalPaths": 1,
|
||||
"routeKeyDetail": {"ipGenPrefix": "fd00:dc:5::1/128", "domain": "local", "rd": "10.1.0.21:500", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "",
|
||||
"asPathEntry": {"asPathType": "Local", "asPath": "i"},
|
||||
"reasonNotBestpath": "noReason",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
}
|
||||
],
|
||||
},
|
||||
"RD: 10.1.0.21:500 ip-prefix fd00:dc:5::1/128 remote": {
|
||||
"totalPaths": 1,
|
||||
"routeKeyDetail": {"ipGenPrefix": "fd00:dc:5::1/128", "domain": "remote", "rd": "10.1.0.21:500", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "",
|
||||
"asPathEntry": {"asPathType": "Local", "asPath": "i"},
|
||||
"reasonNotBestpath": "noReason",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"prefixes": [{"address": "fd00:dc:5::1/128", "vni": 500}]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "success-across-all-rds"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [{"nextHop": "10.100.2.3", "routeType": {"active": True, "valid": True}}],
|
||||
},
|
||||
"RD: 10.100.1.4:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.4:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [{"nextHop": "10.100.2.3", "routeType": {"active": False, "valid": False}}],
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"prefixes": [{"address": "10.100.0.128/31", "vni": 10}]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "success-specific-rd"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{"nextHop": "10.100.2.3", "routeType": {"active": False, "valid": False}},
|
||||
{"nextHop": "10.100.2.4", "routeType": {"active": True, "valid": True}},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"prefixes": [{"address": "10.100.0.128/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local"}]}]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "success-specific-nexthop"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
},
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": False, "valid": False},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [{"address": "10.100.4.0/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3"}]}]}]
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "success-RTs"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [
|
||||
{
|
||||
"address": "10.100.4.1/31",
|
||||
"vni": 10,
|
||||
"routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3", "route_targets": ["10:10"]}]}],
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "failure-all"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [{"nextHop": "10.100.2.3", "routeType": {"active": False, "valid": True}}],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [{"nextHop": "10.100.2.3", "routeType": {"active": False, "valid": True}}],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": True, "valid": False},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": False, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [
|
||||
{"address": "10.100.0.128/31", "vni": 10},
|
||||
{"address": "10.100.0.128/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local"}]},
|
||||
{"address": "10.100.4.0/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3"}]}]},
|
||||
{
|
||||
"address": "10.100.4.1/31",
|
||||
"vni": 10,
|
||||
"routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3", "route_targets": ["10:10"]}]}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Prefix: 10.100.0.128/31 VNI: 10 - No active and valid path found across all RDs",
|
||||
"Prefix: 10.100.0.128/31 VNI: 10 RD: 10.100.1.3:10 - No active and valid path found",
|
||||
"Prefix: 10.100.4.0/31 VNI: 10 RD: 10.100.1.3:10 Nexthop: 10.100.2.3 - No active and valid path found",
|
||||
"Prefix: 10.100.4.1/31 VNI: 10 RD: 10.100.1.3:10 Nexthop: 10.100.2.3 RTs: 10:10 - No active and valid path found",
|
||||
],
|
||||
},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "failure-not-configured"): {
|
||||
"eos_data": [
|
||||
{"vrf": "default", "routerId": "10.100.1.5", "asn": 65102, "evpnRoutes": {}},
|
||||
{"vrf": "default", "routerId": "10.100.1.5", "asn": 65102, "evpnRoutes": {}},
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [
|
||||
{"address": "10.100.0.128/31", "vni": 10},
|
||||
{
|
||||
"address": "10.100.4.1/31",
|
||||
"vni": 10,
|
||||
"routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3", "route_targets": ["10:10"]}]}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Prefix: 10.100.0.128/31 VNI: 10 - No EVPN Type-5 routes found", "Prefix: 10.100.4.1/31 VNI: 10 - No EVPN Type-5 routes found"],
|
||||
},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "failure-route-not-found-with-specified-rd-domain"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.0.128/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.0.128/31", "domain": "remote", "rd": "10.100.1.4:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{"nextHop": "10.100.2.3", "routeType": {"active": False, "valid": False}},
|
||||
{"nextHop": "10.100.2.4", "routeType": {"active": True, "valid": True}},
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"prefixes": [{"address": "10.100.0.128/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "remote"}]}]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Prefix: 10.100.0.128/31 VNI: 10 RD: 10.100.1.3:10 Domain: remote - Route not found"]},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "failiure-specific-nexthop-path-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.4",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:10:10", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [{"address": "10.100.4.0/31", "vni": 10, "routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3"}]}]}]
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Prefix: 10.100.4.0/31 VNI: 10 RD: 10.100.1.3:10 Nexthop: 10.100.2.3 - Path not found"]},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "failiure-specific-nexthop-RTs-path-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.100.1.5",
|
||||
"asn": 65102,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.100.1.3:10 ip-prefix 10.100.4.0/31": {
|
||||
"routeKeyDetail": {"ipGenPrefix": "10.100.4.0/31", "domain": "local", "rd": "10.100.1.3:10", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "10.100.2.3",
|
||||
"routeType": {"active": True, "valid": True},
|
||||
"routeDetail": {"extCommunities": ["Route-Target-AS:20:20", "TunnelEncap:tunnelTypeVxlan", "EvpnRouterMac:02:1c:73:71:73:45"]},
|
||||
}
|
||||
],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"prefixes": [
|
||||
{
|
||||
"address": "10.100.4.1/31",
|
||||
"vni": 10,
|
||||
"routes": [{"rd": "10.100.1.3:10", "domain": "local", "paths": [{"nexthop": "10.100.2.3", "route_targets": ["10:10"]}]}],
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Prefix: 10.100.4.1/31 VNI: 10 RD: 10.100.1.3:10 Nexthop: 10.100.2.3 RTs: 10:10 - Path not found"],
|
||||
},
|
||||
},
|
||||
(VerifyEVPNType5Routes, "failure-ipv6"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vrf": "default",
|
||||
"routerId": "10.1.0.21",
|
||||
"asn": 65120,
|
||||
"evpnRoutes": {
|
||||
"RD: 10.1.0.21:500 ip-prefix fd00:dc:5::1/128": {
|
||||
"totalPaths": 1,
|
||||
"routeKeyDetail": {"ipGenPrefix": "fd00:dc:5::1/128", "domain": "local", "rd": "10.1.0.21:500", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "",
|
||||
"asPathEntry": {"asPathType": "Local", "asPath": "i"},
|
||||
"reasonNotBestpath": "noReason",
|
||||
"routeType": {"active": True, "valid": False},
|
||||
}
|
||||
],
|
||||
},
|
||||
"RD: 10.1.0.21:500 ip-prefix fd00:dc:5::1/128 remote": {
|
||||
"totalPaths": 1,
|
||||
"routeKeyDetail": {"ipGenPrefix": "fd00:dc:5::1/128", "domain": "remote", "rd": "10.1.0.21:500", "nlriType": "ip-prefix"},
|
||||
"evpnRoutePaths": [
|
||||
{
|
||||
"nextHop": "",
|
||||
"asPathEntry": {"asPathType": "Local", "asPath": "i"},
|
||||
"reasonNotBestpath": "noReason",
|
||||
"routeType": {"active": False, "valid": True},
|
||||
}
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"prefixes": [{"address": "fd00:dc:5::1/128", "vni": 500}]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Prefix: fd00:dc:5::1/128 VNI: 500 - No active and valid path found across all RDs"]},
|
||||
},
|
||||
}
|
|
@ -5,15 +5,19 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.field_notices import VerifyFieldNotice44Resolution, VerifyFieldNotice72Resolution
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyFieldNotice44Resolution, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
|
@ -23,343 +27,200 @@ DATA: list[dict[str, Any]] = [
|
|||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}, {"name": "NotAboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-4.0",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
(VerifyFieldNotice44Resolution, "failure-4.0"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-4.0.1-3255441"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "Aboot", "version": "Aboot-veos-4.0.1-3255441"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Device is running incorrect version of aboot 4.0.1"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device is running incorrect version of aboot 4.0.1"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-4.1",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
(VerifyFieldNotice44Resolution, "failure-4.1"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-4.1.0-3255441"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "Aboot", "version": "Aboot-veos-4.1.0-3255441"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Device is running incorrect version of aboot 4.1.0"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device is running incorrect version of aboot 4.1.0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-6.0",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
(VerifyFieldNotice44Resolution, "failure-6.0"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-6.0.1-3255441"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "Aboot", "version": "Aboot-veos-6.0.1-3255441"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Device is running incorrect version of aboot 6.0.1"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device is running incorrect version of aboot 6.0.1"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-6.1",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
(VerifyFieldNotice44Resolution, "failure-6.1"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-6.1.1-3255441"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "Aboot", "version": "Aboot-veos-6.1.1-3255441"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Device is running incorrect version of aboot 6.1.1"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device is running incorrect version of aboot 6.1.1"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-model",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
(VerifyFieldNotice44Resolution, "skipped-model"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "vEOS-lab",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "skipped",
|
||||
"messages": ["Device is not impacted by FN044"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Device is not impacted by FN044"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-aboot-component",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
(VerifyFieldNotice44Resolution, "failure-no-aboot-component"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "NotAboot", "version": "Aboot-veos-4.0.1-3255441"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "NotAboot", "version": "Aboot-veos-4.0.1-3255441"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Aboot component not found"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Aboot component not found"]},
|
||||
},
|
||||
{
|
||||
"name": "success-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "success-JPE"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JPE2130000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "7"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS, "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "success-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "success-JAS"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "7"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS, "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "success-K-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "success-K-JPE"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JPE2133000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "7"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS, "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "success-K-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "success-K-JAS"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "7"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS, "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-Serial",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "skipped-Serial"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "BAN2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "7"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-Platform",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "skipped-Platform"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7150-52-CL",
|
||||
"serialNumber": "JAS0040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
{"modelName": "DCS-7150-52-CL", "serialNumber": "JAS0040000", "details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]}}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "skipped",
|
||||
"messages": ["Platform is not impacted by FN072"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Platform is not impacted by FN072"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-range-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "skipped-range-JPE"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JPE2131000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-range-K-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "skipped-range-K-JPE"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JPE2134000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-range-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "skipped-range-JAS"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2041000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-range-K-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "skipped-range-K-JAS"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JAS2041000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "failed-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "failed-JPE"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JPE2133000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device is exposed to FN72"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device is exposed to FN72"]},
|
||||
},
|
||||
{
|
||||
"name": "failed-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "failed-JAS"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm1", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device is exposed to FN72"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device is exposed to FN72"]},
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
(VerifyFieldNotice72Resolution, "error"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm2", "version": "5"}],
|
||||
},
|
||||
},
|
||||
"details": {"deviations": [], "components": [{"name": "FixedSystemvrm2", "version": "5"}]},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Error in running test - Component FixedSystemvrm1 not found in 'show version'"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Error in running test - Component FixedSystemvrm1 not found in 'show version"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,15 +5,19 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.flow_tracking import VerifyHardwareFlowTrackerStatus
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyHardwareFlowTrackerStatus, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -31,14 +35,12 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"running": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"trackers": [{"name": "FLOW-TRACKER"}, {"name": "HARDWARE-TRACKER"}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-with-optional-field",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "success-with-optional-field"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -56,7 +58,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"running": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"trackers": [
|
||||
|
@ -72,21 +74,14 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-flow-tracking-not-running",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "failure-flow-tracking-not-running"): {
|
||||
"eos_data": [{"trackers": {}, "running": False}],
|
||||
"inputs": {"trackers": [{"name": "FLOW-TRACKER"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Hardware flow tracking is not running."],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Hardware flow tracking is not running"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-tracker-not-configured",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "failure-tracker-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -101,14 +96,9 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {"trackers": [{"name": "FLOW-Sample"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Flow Tracker: FLOW-Sample - Not found"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Flow Tracker: FLOW-Sample - Not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-tracker-not-active",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "failure-tracker-not-active"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -126,7 +116,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"running": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"trackers": [
|
||||
|
@ -142,14 +132,9 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Flow Tracker: FLOW-TRACKER - Disabled", "Flow Tracker: HARDWARE-TRACKER - Disabled"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Flow Tracker: FLOW-TRACKER - Disabled", "Flow Tracker: HARDWARE-TRACKER - Disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-record-export",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "failure-incorrect-record-export"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -167,22 +152,16 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"running": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"trackers": [
|
||||
{
|
||||
"name": "FLOW-TRACKER",
|
||||
"record_export": {"on_inactive_timeout": 6000, "on_interval": 30000},
|
||||
},
|
||||
{
|
||||
"name": "HARDWARE-TRACKER",
|
||||
"record_export": {"on_inactive_timeout": 60000, "on_interval": 300000},
|
||||
},
|
||||
{"name": "FLOW-TRACKER", "record_export": {"on_inactive_timeout": 6000, "on_interval": 30000}},
|
||||
{"name": "HARDWARE-TRACKER", "record_export": {"on_inactive_timeout": 60000, "on_interval": 300000}},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Flow Tracker: FLOW-TRACKER Inactive Timeout: 6000 Active Interval: 30000 - Incorrect timers - Inactive Timeout: 60000 OnActive Interval: 300000",
|
||||
"Flow Tracker: HARDWARE-TRACKER Inactive Timeout: 60000 Active Interval: 300000 - Incorrect timers - "
|
||||
|
@ -190,9 +169,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-exporters",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "failure-incorrect-exporters"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -216,7 +193,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"running": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"trackers": [
|
||||
|
@ -237,7 +214,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Flow Tracker: FLOW-TRACKER Exporter: CVP-FLOW - Incorrect local interface - Expected: Loopback10 Actual: Loopback0",
|
||||
"Flow Tracker: FLOW-TRACKER Exporter: CVP-FLOW - Incorrect template interval - Expected: 3500000 Actual: 3600000",
|
||||
|
@ -247,9 +224,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-type",
|
||||
"test": VerifyHardwareFlowTrackerStatus,
|
||||
(VerifyHardwareFlowTrackerStatus, "failure-all-type"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"trackers": {
|
||||
|
@ -291,7 +266,7 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"running": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"trackers": [
|
||||
|
@ -301,10 +276,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"record_export": {"on_inactive_timeout": 60000, "on_interval": 300000},
|
||||
"exporters": [{"name": "CV-TELEMETRY", "local_interface": "Loopback0", "template_interval": 3600000}],
|
||||
},
|
||||
{
|
||||
"name": "HARDWARE-FLOW",
|
||||
"record_export": {"on_inactive_timeout": 60000, "on_interval": 300000},
|
||||
},
|
||||
{"name": "HARDWARE-FLOW", "record_export": {"on_inactive_timeout": 60000, "on_interval": 300000}},
|
||||
{
|
||||
"name": "FLOW-TRACKER2",
|
||||
"exporters": [
|
||||
|
@ -322,7 +294,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Flow Tracker: FLOW-Sample - Not found",
|
||||
"Flow Tracker: FLOW-TRIGGER - Disabled",
|
||||
|
@ -335,4 +307,4 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,51 +5,45 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.greent import VerifyGreenT, VerifyGreenTCounters
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyGreenTCounters,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyGreenTCounters, "success"): {
|
||||
"eos_data": [{"sampleRcvd": 0, "sampleDiscarded": 0, "multiDstSampleRcvd": 0, "grePktSent": 1, "sampleSent": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyGreenTCounters,
|
||||
(VerifyGreenTCounters, "failure"): {
|
||||
"eos_data": [{"sampleRcvd": 0, "sampleDiscarded": 0, "multiDstSampleRcvd": 0, "grePktSent": 0, "sampleSent": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["GreenT counters are not incremented"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["GreenT counters are not incremented"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyGreenT,
|
||||
(VerifyGreenT, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"profiles": {
|
||||
"default": {"interfaces": [], "appliedInterfaces": [], "samplePolicy": "default", "failures": {}, "appliedInterfaces6": [], "failures6": {}},
|
||||
"testProfile": {"interfaces": [], "appliedInterfaces": [], "samplePolicy": "default", "failures": {}, "appliedInterfaces6": [], "failures6": {}},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyGreenT,
|
||||
(VerifyGreenT, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"profiles": {
|
||||
"default": {"interfaces": [], "appliedInterfaces": [], "samplePolicy": "default", "failures": {}, "appliedInterfaces6": [], "failures6": {}},
|
||||
},
|
||||
},
|
||||
"default": {"interfaces": [], "appliedInterfaces": [], "samplePolicy": "default", "failures": {}, "appliedInterfaces6": [], "failures6": {}}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["No GreenT policy is created"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No GreenT policy is created"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.hardware import (
|
||||
VerifyAdverseDrops,
|
||||
VerifyEnvironmentCooling,
|
||||
|
@ -18,44 +21,41 @@ from anta.tests.hardware import (
|
|||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTransceiversManufacturers,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyTransceiversManufacturers, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"xcvrSlots": {
|
||||
"1": {"mfgName": "Arista Networks", "modelName": "QSFP-100G-DR", "serialNum": "XKT203501340", "hardwareRev": "21"},
|
||||
"2": {"mfgName": "Arista Networks", "modelName": "QSFP-100G-DR", "serialNum": "XKT203501337", "hardwareRev": "21"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"manufacturers": ["Arista Networks"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTransceiversManufacturers,
|
||||
(VerifyTransceiversManufacturers, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"xcvrSlots": {
|
||||
"1": {"mfgName": "Arista Networks", "modelName": "QSFP-100G-DR", "serialNum": "XKT203501340", "hardwareRev": "21"},
|
||||
"2": {"mfgName": "Arista Networks", "modelName": "QSFP-100G-DR", "serialNum": "XKT203501337", "hardwareRev": "21"},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"manufacturers": ["Arista"]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Interface: 1 - Transceiver is from unapproved manufacturers - Expected: Arista Actual: Arista Networks",
|
||||
"Interface: 2 - Transceiver is from unapproved manufacturers - Expected: Arista Actual: Arista Networks",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTemperature,
|
||||
(VerifyTemperature, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"powercycleOnOverheat": "False",
|
||||
|
@ -64,14 +64,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"shutdownOnOverheat": "True",
|
||||
"systemStatus": "temperatureOk",
|
||||
"recoveryModeOnOverheat": "recoveryModeNA",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTemperature,
|
||||
(VerifyTemperature, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"powercycleOnOverheat": "False",
|
||||
|
@ -80,14 +77,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"shutdownOnOverheat": "True",
|
||||
"systemStatus": "temperatureCritical",
|
||||
"recoveryModeOnOverheat": "recoveryModeNA",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device temperature exceeds acceptable limits - Expected: temperatureOk Actual: temperatureCritical"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Device temperature exceeds acceptable limits - Expected: temperatureOk Actual: temperatureCritical"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTransceiversTemperature,
|
||||
(VerifyTransceiversTemperature, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tempSensors": [
|
||||
|
@ -107,17 +104,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"pidDriverCount": 0,
|
||||
"isPidDriver": False,
|
||||
"name": "DomTemperatureSensor54",
|
||||
},
|
||||
}
|
||||
],
|
||||
"cardSlots": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-hwStatus",
|
||||
"test": VerifyTransceiversTemperature,
|
||||
(VerifyTransceiversTemperature, "failure-hwStatus"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tempSensors": [
|
||||
|
@ -137,20 +131,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"pidDriverCount": 0,
|
||||
"isPidDriver": False,
|
||||
"name": "DomTemperatureSensor54",
|
||||
},
|
||||
}
|
||||
],
|
||||
"cardSlots": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Sensor: DomTemperatureSensor54 - Invalid hardware state - Expected: ok Actual: ko"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Sensor: DomTemperatureSensor54 - Invalid hardware state - Expected: ok Actual: ko"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-alertCount",
|
||||
"test": VerifyTransceiversTemperature,
|
||||
(VerifyTransceiversTemperature, "failure-alertCount"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"tempSensors": [
|
||||
|
@ -170,20 +158,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"pidDriverCount": 0,
|
||||
"isPidDriver": False,
|
||||
"name": "DomTemperatureSensor54",
|
||||
},
|
||||
}
|
||||
],
|
||||
"cardSlots": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Sensor: DomTemperatureSensor54 - Incorrect alert counter - Expected: 0 Actual: 1"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Sensor: DomTemperatureSensor54 - Incorrect alert counter - Expected: 0 Actual: 1"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEnvironmentSystemCooling,
|
||||
(VerifyEnvironmentSystemCooling, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
|
@ -199,14 +181,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingOk",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEnvironmentSystemCooling,
|
||||
(VerifyEnvironmentSystemCooling, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
|
@ -222,14 +201,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingKo",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device system cooling status invalid - Expected: coolingOk Actual: coolingKo"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device system cooling status invalid - Expected: coolingOk Actual: coolingKo"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
(VerifyEnvironmentCooling, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
|
@ -253,7 +229,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
|
@ -271,7 +247,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
|
@ -291,7 +267,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
|
@ -309,7 +285,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
|
@ -327,7 +303,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
|
@ -345,7 +321,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
|
@ -355,14 +331,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingOk",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-additional-states",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
(VerifyEnvironmentCooling, "success-additional-states"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
|
@ -386,7 +360,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
|
@ -395,7 +369,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "Not Inserted",
|
||||
"status": "powerLoss",
|
||||
"uptime": 1682498935.9121106,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499092.4665174,
|
||||
|
@ -404,7 +378,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
|
@ -424,7 +398,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
|
@ -442,7 +416,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
|
@ -460,7 +434,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
|
@ -478,7 +452,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
|
@ -488,14 +462,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingOk",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"expected": {"result": "success"},
|
||||
"inputs": {"states": ["ok", "powerLoss"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-fan-tray",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
(VerifyEnvironmentCooling, "failure-fan-tray"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
|
@ -519,7 +491,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
|
@ -537,7 +509,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
|
@ -548,7 +520,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "down",
|
||||
"status": "unknownHwStatus",
|
||||
"uptime": 1682498923.9303148,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0139885,
|
||||
|
@ -557,7 +529,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
|
@ -575,7 +547,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
|
@ -584,7 +556,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "Not Inserted",
|
||||
"status": "powerLoss",
|
||||
"uptime": 1682498923.9383528,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140095,
|
||||
|
@ -593,7 +565,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
|
@ -611,7 +583,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
|
@ -621,14 +593,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "CoolingKo",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"expected": {"result": "failure", "messages": ["Fan Tray: 1 Fan: 1/1 - Invalid state - Expected: ok, Not Inserted Actual: down"]},
|
||||
"inputs": {"states": ["ok", "powerLoss"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Fan Tray: 1 Fan: 1/1 - Invalid state - Expected: ok, powerLoss Actual: unknownHwStatus"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-power-supply",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
(VerifyEnvironmentCooling, "failure-power-supply"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
|
@ -643,7 +613,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "down",
|
||||
"status": "unknownHwStatus",
|
||||
"uptime": 1682498937.0240965,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499033.0403435,
|
||||
|
@ -652,7 +622,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
|
@ -670,7 +640,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
|
@ -690,7 +660,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
|
@ -708,7 +678,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
|
@ -717,7 +687,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "Not Inserted",
|
||||
"status": "powerLoss",
|
||||
"uptime": 1682498923.9383528,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140095,
|
||||
|
@ -726,7 +696,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
|
@ -744,7 +714,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
},
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
|
@ -754,19 +724,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "CoolingKo",
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"inputs": {"states": ["ok", "powerLoss"]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Power Slot: PowerSupply1 Fan: PowerSupply1/1 - Invalid state - Expected: ok, Not Inserted Actual: down",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Power Slot: PowerSupply1 Fan: PowerSupply1/1 - Invalid state - Expected: ok, powerLoss Actual: unknownHwStatus"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEnvironmentPower,
|
||||
(VerifyEnvironmentPower, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"powerSupplies": {
|
||||
|
@ -805,62 +771,13 @@ DATA: list[dict[str, Any]] = [
|
|||
"outputCurrent": 9.828125,
|
||||
"managed": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-additional-states",
|
||||
"test": VerifyEnvironmentPower,
|
||||
"eos_data": [
|
||||
{
|
||||
"powerSupplies": {
|
||||
"1": {
|
||||
"outputPower": 0.0,
|
||||
"modelName": "PWR-500AC-F",
|
||||
"capacity": 500.0,
|
||||
"tempSensors": {
|
||||
"TempSensorP1/2": {"status": "ok", "temperature": 0.0},
|
||||
"TempSensorP1/3": {"status": "ok", "temperature": 0.0},
|
||||
"TempSensorP1/1": {"status": "ok", "temperature": 0.0},
|
||||
},
|
||||
"fans": {"FanP1/1": {"status": "ok", "speed": 33}},
|
||||
"state": "Not Inserted",
|
||||
"inputCurrent": 0.0,
|
||||
"dominant": False,
|
||||
"inputVoltage": 0.0,
|
||||
"outputCurrent": 0.0,
|
||||
"managed": True,
|
||||
},
|
||||
"2": {
|
||||
"outputPower": 117.375,
|
||||
"uptime": 1682498935.9121966,
|
||||
"modelName": "PWR-500AC-F",
|
||||
"capacity": 500.0,
|
||||
"tempSensors": {
|
||||
"TempSensorP2/1": {"status": "ok", "temperature": 39.0},
|
||||
"TempSensorP2/3": {"status": "ok", "temperature": 43.0},
|
||||
"TempSensorP2/2": {"status": "ok", "temperature": 31.0},
|
||||
},
|
||||
"fans": {"FanP2/1": {"status": "ok", "speed": 33}},
|
||||
"state": "ok",
|
||||
"inputCurrent": 0.572265625,
|
||||
"dominant": False,
|
||||
"inputVoltage": 232.5,
|
||||
"outputCurrent": 9.828125,
|
||||
"managed": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEnvironmentPower,
|
||||
(VerifyEnvironmentPower, "success-additional-states"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"powerSupplies": {
|
||||
|
@ -899,24 +816,60 @@ DATA: list[dict[str, Any]] = [
|
|||
"outputCurrent": 9.828125,
|
||||
"managed": True,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "powerLoss"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyEnvironmentPower, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"powerSupplies": {
|
||||
"1": {
|
||||
"outputPower": 0.0,
|
||||
"modelName": "PWR-500AC-F",
|
||||
"capacity": 500.0,
|
||||
"tempSensors": {
|
||||
"TempSensorP1/2": {"status": "ok", "temperature": 0.0},
|
||||
"TempSensorP1/3": {"status": "ok", "temperature": 0.0},
|
||||
"TempSensorP1/1": {"status": "ok", "temperature": 0.0},
|
||||
},
|
||||
"fans": {"FanP1/1": {"status": "ok", "speed": 33}},
|
||||
"state": "powerLoss",
|
||||
"inputCurrent": 0.0,
|
||||
"dominant": False,
|
||||
"inputVoltage": 0.0,
|
||||
"outputCurrent": 0.0,
|
||||
"managed": True,
|
||||
},
|
||||
"2": {
|
||||
"outputPower": 117.375,
|
||||
"uptime": 1682498935.9121966,
|
||||
"modelName": "PWR-500AC-F",
|
||||
"capacity": 500.0,
|
||||
"tempSensors": {
|
||||
"TempSensorP2/1": {"status": "ok", "temperature": 39.0},
|
||||
"TempSensorP2/3": {"status": "ok", "temperature": 43.0},
|
||||
"TempSensorP2/2": {"status": "ok", "temperature": 31.0},
|
||||
},
|
||||
"fans": {"FanP2/1": {"status": "ok", "speed": 33}},
|
||||
"state": "ok",
|
||||
"inputCurrent": 0.572265625,
|
||||
"dominant": False,
|
||||
"inputVoltage": 232.5,
|
||||
"outputCurrent": 9.828125,
|
||||
"managed": True,
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok"]},
|
||||
"expected": {"result": "failure", "messages": ["Power Slot: 1 - Invalid power supplies state - Expected: ok Actual: powerLoss"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Power Slot: 1 - Invalid power supplies state - Expected: ok Actual: powerLoss"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAdverseDrops,
|
||||
"eos_data": [{"totalAdverseDrops": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyAdverseDrops,
|
||||
(VerifyAdverseDrops, "success"): {"eos_data": [{"totalAdverseDrops": 0}], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyAdverseDrops, "failure"): {
|
||||
"eos_data": [{"totalAdverseDrops": 10}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Incorrect total adverse drops counter - Expected: 0 Actual: 10"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Incorrect total adverse drops counter - Expected: 0 Actual: 10"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,24 +5,21 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.lanz import VerifyLANZ
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLANZ,
|
||||
"eos_data": [{"lanzEnabled": True}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLANZ,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyLANZ, "success"): {"eos_data": [{"lanzEnabled": True}], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyLANZ, "failure"): {
|
||||
"eos_data": [{"lanzEnabled": False}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["LANZ is not enabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["LANZ is not enabled"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.logging import (
|
||||
VerifyLoggingAccounting,
|
||||
VerifyLoggingEntries,
|
||||
|
@ -21,312 +24,199 @@ from anta.tests.logging import (
|
|||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingPersistent,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyLoggingPersistent, "success"): {
|
||||
"eos_data": [
|
||||
"Persistent logging: level debugging\n",
|
||||
"""Directory of flash:/persist/messages
|
||||
|
||||
-rw- 9948 May 10 13:54 messages
|
||||
|
||||
33214693376 bytes total (10081136640 bytes free)
|
||||
|
||||
""",
|
||||
"Directory of flash:/persist/messages\n\n -rw- 9948 May 10 13:54 messages\n\n"
|
||||
" 33214693376 bytes total (10081136640 bytes free)\n\n ",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifyLoggingPersistent,
|
||||
(VerifyLoggingPersistent, "failure-disabled"): {
|
||||
"eos_data": [
|
||||
"Persistent logging: disabled\n",
|
||||
"""Directory of flash:/persist/messages
|
||||
|
||||
-rw- 0 Apr 13 16:29 messages
|
||||
|
||||
33214693376 bytes total (10082168832 bytes free)
|
||||
|
||||
""",
|
||||
"Directory of flash:/persist/messages\n\n -rw- 0 Apr 13 16:29 messages\n\n"
|
||||
" 33214693376 bytes total (10082168832 bytes free)\n\n ",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Persistent logging is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Persistent logging is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-saved",
|
||||
"test": VerifyLoggingPersistent,
|
||||
(VerifyLoggingPersistent, "failure-not-saved"): {
|
||||
"eos_data": [
|
||||
"Persistent logging: level debugging\n",
|
||||
"""Directory of flash:/persist/messages
|
||||
|
||||
-rw- 0 Apr 13 16:29 messages
|
||||
|
||||
33214693376 bytes total (10082168832 bytes free)
|
||||
|
||||
""",
|
||||
"Directory of flash:/persist/messages\n\n -rw- 0 Apr 13 16:29 messages\n\n"
|
||||
" 33214693376 bytes total (10082168832 bytes free)\n\n ",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["No persistent logs are saved in flash"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No persistent logs are saved in flash"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingSourceIntf,
|
||||
(VerifyLoggingSourceIntf, "success"): {
|
||||
"eos_data": [
|
||||
"""Trap logging: level informational
|
||||
Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF MGMT
|
||||
Logging to '10.22.10.92' port 514 in VRF MGMT via udp
|
||||
Logging to '10.22.10.93' port 514 in VRF MGMT via tcp
|
||||
Logging to '10.22.10.94' port 911 in VRF MGMT via udp
|
||||
|
||||
""",
|
||||
"Trap logging: level informational\n Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF MGMT\n"
|
||||
" Logging to '10.22.10.92' port 514 in VRF MGMT via udp\n Logging to '10.22.10.93' port 514 in VRF MGMT via tcp\n"
|
||||
" Logging to '10.22.10.94' port 911 in VRF MGMT via udp\n\n "
|
||||
],
|
||||
"inputs": {"interface": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-intf",
|
||||
"test": VerifyLoggingSourceIntf,
|
||||
(VerifyLoggingSourceIntf, "failure-intf"): {
|
||||
"eos_data": [
|
||||
"""Trap logging: level informational
|
||||
Logging source-interface 'Management1', IP Address 172.20.20.12 in VRF MGMT
|
||||
Logging to '10.22.10.92' port 514 in VRF MGMT via udp
|
||||
Logging to '10.22.10.93' port 514 in VRF MGMT via tcp
|
||||
Logging to '10.22.10.94' port 911 in VRF MGMT via udp
|
||||
|
||||
""",
|
||||
"Trap logging: level informational\n Logging source-interface 'Management1', IP Address 172.20.20.12 in VRF MGMT\n"
|
||||
" Logging to '10.22.10.92' port 514 in VRF MGMT via udp\n Logging to '10.22.10.93' port 514 in VRF MGMT via tcp\n"
|
||||
" Logging to '10.22.10.94' port 911 in VRF MGMT via udp\n\n "
|
||||
],
|
||||
"inputs": {"interface": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Source-interface: Management0 VRF: MGMT - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Source-interface: Management0 VRF: MGMT - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vrf",
|
||||
"test": VerifyLoggingSourceIntf,
|
||||
(VerifyLoggingSourceIntf, "failure-vrf"): {
|
||||
"eos_data": [
|
||||
"""Trap logging: level informational
|
||||
Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF default
|
||||
Logging to '10.22.10.92' port 514 in VRF MGMT via udp
|
||||
Logging to '10.22.10.93' port 514 in VRF MGMT via tcp
|
||||
Logging to '10.22.10.94' port 911 in VRF MGMT via udp
|
||||
|
||||
""",
|
||||
"Trap logging: level informational\n Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF default\n"
|
||||
" Logging to '10.22.10.92' port 514 in VRF MGMT via udp\n Logging to '10.22.10.93' port 514 in VRF MGMT via tcp\n"
|
||||
" Logging to '10.22.10.94' port 911 in VRF MGMT via udp\n\n "
|
||||
],
|
||||
"inputs": {"interface": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Source-interface: Management0 VRF: MGMT - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Source-interface: Management0 VRF: MGMT - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingHosts,
|
||||
(VerifyLoggingHosts, "success"): {
|
||||
"eos_data": [
|
||||
"""Trap logging: level informational
|
||||
Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF MGMT
|
||||
Logging to '10.22.10.92' port 514 in VRF MGMT via udp
|
||||
Logging to '10.22.10.93' port 514 in VRF MGMT via tcp
|
||||
Logging to '10.22.10.94' port 911 in VRF MGMT via udp
|
||||
|
||||
""",
|
||||
"Trap logging: level informational\n Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF MGMT\n"
|
||||
" Logging to '10.22.10.92' port 514 in VRF MGMT via udp\n Logging to '10.22.10.93' port 514 in VRF MGMT via tcp\n"
|
||||
" Logging to '10.22.10.94' port 911 in VRF MGMT via udp\n\n "
|
||||
],
|
||||
"inputs": {"hosts": ["10.22.10.92", "10.22.10.93", "10.22.10.94"], "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-hosts",
|
||||
"test": VerifyLoggingHosts,
|
||||
(VerifyLoggingHosts, "failure-hosts"): {
|
||||
"eos_data": [
|
||||
"""Trap logging: level informational
|
||||
Logging source-interface 'Management1', IP Address 172.20.20.12 in VRF MGMT
|
||||
Logging to '10.22.10.92' port 514 in VRF MGMT via udp
|
||||
Logging to '10.22.10.103' port 514 in VRF MGMT via tcp
|
||||
Logging to '10.22.10.104' port 911 in VRF MGMT via udp
|
||||
|
||||
""",
|
||||
"Trap logging: level informational\n Logging source-interface 'Management1', IP Address 172.20.20.12 in VRF MGMT\n"
|
||||
" Logging to '10.22.10.92' port 514 in VRF MGMT via udp\n Logging to '10.22.10.103' port 514 in VRF MGMT via tcp\n"
|
||||
" Logging to '10.22.10.104' port 911 in VRF MGMT via udp\n\n "
|
||||
],
|
||||
"inputs": {"hosts": ["10.22.10.92", "10.22.10.93", "10.22.10.94"], "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Syslog servers 10.22.10.93, 10.22.10.94 are not configured in VRF MGMT"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Syslog servers 10.22.10.93, 10.22.10.94 are not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vrf",
|
||||
"test": VerifyLoggingHosts,
|
||||
(VerifyLoggingHosts, "failure-vrf"): {
|
||||
"eos_data": [
|
||||
"""Trap logging: level informational
|
||||
Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF MGMT
|
||||
Logging to '10.22.10.92' port 514 in VRF MGMT via udp
|
||||
Logging to '10.22.10.93' port 514 in VRF default via tcp
|
||||
Logging to '10.22.10.94' port 911 in VRF default via udp
|
||||
|
||||
""",
|
||||
"Trap logging: level informational\n Logging source-interface 'Management0', IP Address 172.20.20.12 in VRF MGMT\n"
|
||||
" Logging to '10.22.10.92' port 514 in VRF MGMT via udp\n Logging to '10.22.10.93' port 514 in VRF default via tcp\n"
|
||||
" Logging to '10.22.10.94' port 911 in VRF default via udp\n\n "
|
||||
],
|
||||
"inputs": {"hosts": ["10.22.10.92", "10.22.10.93", "10.22.10.94"], "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Syslog servers 10.22.10.93, 10.22.10.94 are not configured in VRF MGMT"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Syslog servers 10.22.10.93, 10.22.10.94 are not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingLogsGeneration,
|
||||
(VerifyLoggingLogsGeneration, "success"): {
|
||||
"eos_data": [
|
||||
"",
|
||||
"2023-05-10T13:54:21.463497-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingLogsGeneration validation\n",
|
||||
"2023-05-10T13:54:21.463497-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: Message from arista on command-api (10.22.1.107):"
|
||||
" ANTA VerifyLoggingLogsGeneration validation\n",
|
||||
],
|
||||
"inputs": {"severity_level": "informational"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingLogsGeneration,
|
||||
(VerifyLoggingLogsGeneration, "failure"): {
|
||||
"eos_data": ["", "Log Buffer:\n"],
|
||||
"inputs": {"severity_level": "notifications"},
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Logs are not generated"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingHostname,
|
||||
(VerifyLoggingHostname, "success"): {
|
||||
"eos_data": [
|
||||
{"hostname": "NW-CORE", "fqdn": "NW-CORE.example.org"},
|
||||
"",
|
||||
"2023-05-10T15:41:44.701810-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingHostname validation\n",
|
||||
"2023-05-10T15:41:44.701810-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: Message from arista on command-api (10.22.1.107):"
|
||||
" ANTA VerifyLoggingHostname validation\n",
|
||||
],
|
||||
"inputs": {"severity_level": "informational"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingHostname,
|
||||
(VerifyLoggingHostname, "failure"): {
|
||||
"eos_data": [
|
||||
{"hostname": "NW-CORE", "fqdn": "NW-CORE.example.org"},
|
||||
"",
|
||||
"2023-05-10T13:54:21.463497-05:00 NW-CORE ConfigAgent: %SYS-6-LOGMSG_NOTICE: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingLogsHostname validation\n",
|
||||
"2023-05-10T13:54:21.463497-05:00 NW-CORE ConfigAgent: %SYS-6-LOGMSG_NOTICE: Message from arista on command-api (10.22.1.107):"
|
||||
" ANTA VerifyLoggingLogsHostname validation\n",
|
||||
],
|
||||
"inputs": {"severity_level": "notifications"},
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated with the device FQDN"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Logs are not generated with the device FQDN"]},
|
||||
},
|
||||
{
|
||||
"name": "success-negative-offset",
|
||||
"test": VerifyLoggingTimestamp,
|
||||
(VerifyLoggingTimestamp, "success-negative-offset"): {
|
||||
"eos_data": [
|
||||
"",
|
||||
"2023-05-10T15:41:44.680813-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingTimestamp validation\n"
|
||||
"2023-05-10T15:42:44.680813-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Other log\n",
|
||||
"2023-05-10T15:41:44.680813-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: Message from arista on command-api (10.22.1.107):"
|
||||
" ANTA VerifyLoggingTimestamp validation\n2023-05-10T15:42:44.680813-05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: Other log\n",
|
||||
],
|
||||
"inputs": {"severity_level": "informational"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-positive-offset",
|
||||
"test": VerifyLoggingTimestamp,
|
||||
(VerifyLoggingTimestamp, "success-positive-offset"): {
|
||||
"eos_data": [
|
||||
"",
|
||||
"2023-05-10T15:41:44.680813+05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingTimestamp validation\n"
|
||||
"2023-05-10T15:42:44.680813+05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Other log\n",
|
||||
"2023-05-10T15:41:44.680813+05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: Message from arista on command-api (10.22.1.107):"
|
||||
" ANTA VerifyLoggingTimestamp validation\n2023-05-10T15:42:44.680813+05:00 NW-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: Other log\n",
|
||||
],
|
||||
"inputs": {"severity_level": "informational"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingTimestamp,
|
||||
(VerifyLoggingTimestamp, "failure"): {
|
||||
"eos_data": [
|
||||
"",
|
||||
"May 10 13:54:22 NE-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_ALERT: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingTimestamp validation\n",
|
||||
"May 10 13:54:22 NE-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_ALERT: Message from arista on command-api (10.22.1.107):"
|
||||
" ANTA VerifyLoggingTimestamp validation\n",
|
||||
],
|
||||
"inputs": {"severity_level": "alerts"},
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated with the appropriate timestamp format"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Logs are not generated with the appropriate timestamp format"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-matching-log",
|
||||
"test": VerifyLoggingTimestamp,
|
||||
"eos_data": [
|
||||
"",
|
||||
"May 10 13:54:22 NE-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_NOTICE: Message from arista on command-api (10.22.1.107): BLAH\n",
|
||||
],
|
||||
(VerifyLoggingTimestamp, "failure-no-matching-log"): {
|
||||
"eos_data": ["", "May 10 13:54:22 NE-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_NOTICE: Message from arista on command-api (10.22.1.107): BLAH\n"],
|
||||
"inputs": {"severity_level": "notifications"},
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated with the appropriate timestamp format"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Logs are not generated with the appropriate timestamp format"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingAccounting,
|
||||
(VerifyLoggingAccounting, "success"): {
|
||||
"eos_data": ["2023 May 10 15:50:31 arista command-api 10.22.1.107 stop service=shell priv-lvl=15 cmd=show aaa accounting logs | tail\n"],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingAccounting,
|
||||
(VerifyLoggingAccounting, "failure"): {
|
||||
"eos_data": ["2023 May 10 15:52:26 arista vty14 10.22.1.107 stop service=shell priv-lvl=15 cmd=show bgp summary\n"],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["AAA accounting logs are not generated"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["AAA accounting logs are not generated"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingErrors,
|
||||
"eos_data": [""],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingErrors,
|
||||
(VerifyLoggingErrors, "success"): {"eos_data": [""], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyLoggingErrors, "failure"): {
|
||||
"eos_data": [
|
||||
"Aug 2 19:57:42 DC1-LEAF1A Mlag: %FWK-3-SOCKET_CLOSE_REMOTE: Connection to Mlag (pid:27200) at tbt://192.168.0.1:4432/+n closed by peer (EOF)",
|
||||
"Aug 2 19:57:42 DC1-LEAF1A Mlag: %FWK-3-SOCKET_CLOSE_REMOTE: Connection to Mlag (pid:27200) at tbt://192.168.0.1:4432/+n closed by peer (EOF)"
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device has reported syslog messages with a severity of ERRORS or higher"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Device has reported syslog messages with a severity of ERRORS or higher:\nAug 2 19:57:42 DC1-LEAF1A Mlag:"
|
||||
" %FWK-3-SOCKET_CLOSE_REMOTE: Connection to Mlag (pid:27200) at tbt://192.168.0.1:4432/+n closed by peer (EOF)"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySyslogLogging,
|
||||
(VerifySyslogLogging, "success"): {
|
||||
"eos_data": [
|
||||
"""Syslog logging: enabled
|
||||
Buffer logging: level debugging
|
||||
|
||||
External configuration:
|
||||
active:
|
||||
inactive:
|
||||
|
||||
Facility Severity Effective Severity
|
||||
-------------------- ------------- ------------------
|
||||
aaa debugging debugging
|
||||
accounting debugging debugging""",
|
||||
"Syslog logging: enabled\n Buffer logging: level debugging\n\n External configuration:\n active:\n"
|
||||
" inactive:\n\n Facility Severity Effective Severity\n"
|
||||
" -------------------- ------------- ------------------\n aaa debugging"
|
||||
" debugging\n accounting debugging debugging"
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySyslogLogging,
|
||||
(VerifySyslogLogging, "failure"): {
|
||||
"eos_data": [
|
||||
"""Syslog logging: disabled
|
||||
Buffer logging: level debugging
|
||||
Console logging: level errors
|
||||
Persistent logging: disabled
|
||||
Monitor logging: level errors
|
||||
|
||||
External configuration:
|
||||
active:
|
||||
inactive:
|
||||
|
||||
Facility Severity Effective Severity
|
||||
-------------------- ------------- ------------------
|
||||
aaa debugging debugging
|
||||
accounting debugging debugging""",
|
||||
"Syslog logging: disabled\n Buffer logging: level debugging\n Console logging: level errors\n"
|
||||
" Persistent logging: disabled\n Monitor logging: level errors\n\n External configuration:\n"
|
||||
" active:\n inactive:\n\n Facility Severity Effective Severity\n"
|
||||
" -------------------- ------------- ------------------\n aaa debugging"
|
||||
" debugging\n accounting debugging debugging"
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Syslog logging is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Syslog logging is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingEntries,
|
||||
(VerifyLoggingEntries, "success"): {
|
||||
"eos_data": [
|
||||
"""Mar 13 04:10:45 s1-leaf1 ProcMgr: %PROCMGR-6-TERMINATE_RUNNING_PROCESS: Terminating deconfigured/reconfigured process 'SystemInitMonitor' (PID=859)
|
||||
Mar 13 04:10:45 s1-leaf1 ProcMgr: %PROCMGR-6-PROCESS_TERMINATED: 'SystemInitMonitor' (PID=859, status=9) has terminated.""",
|
||||
"""Mar 13 04:10:45 s1-leaf1 ProcMgr: %PROCMGR-7-WORKER_WARMSTART_DONE: ProcMgr worker warm start done. (PID=547)""",
|
||||
"Mar 13 04:10:45 s1-leaf1 ProcMgr: %PROCMGR-6-TERMINATE_RUNNING_PROCESS: Terminating deconfigured/reconfigured process 'SystemInitMonitor'"
|
||||
" (PID=859)\n Mar 13 04:10:45 s1-leaf1 ProcMgr: %PROCMGR-6-PROCESS_TERMINATED: 'SystemInitMonitor' (PID=859, status=9) has terminated.",
|
||||
"Mar 13 04:10:45 s1-leaf1 ProcMgr: %PROCMGR-7-WORKER_WARMSTART_DONE: ProcMgr worker warm start done. (PID=547)",
|
||||
],
|
||||
"inputs": {
|
||||
"logging_entries": [
|
||||
|
@ -334,17 +224,15 @@ DATA: list[dict[str, Any]] = [
|
|||
{"regex_match": ".*ProcMgr worker warm start.*", "last_number_messages": 2, "severity_level": "debugging"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-log-str-not-found",
|
||||
"test": VerifyLoggingEntries,
|
||||
(VerifyLoggingEntries, "failure-log-str-not-found"): {
|
||||
"eos_data": [
|
||||
"""Mar 12 04:34:01 s1-leaf1 ProcMgr: %PROCMGR-7-WORKER_WARMSTART_DONE: ProcMgr worker warm start done. (PID=559)
|
||||
Mar 12 04:34:01 s1-leaf1 ProcMgr: %PROCMGR-6-PROCESS_TERMINATED: 'SystemInitMonitor' (PID=867, status=9) has terminated.""",
|
||||
"""Mar 13 03:58:12 s1-leaf1 ConfigAgent: %SYS-5-CONFIG_SESSION_ABORTED: User cvpsystem aborted
|
||||
configuration session capiVerify-612-612b34a2ffbf11ef96ba3a348d538ba0 on TerminAttr (localhost)
|
||||
Mar 13 04:10:45 s1-leaf1 SystemInitMonitor: %SYS-5-SYSTEM_INITIALIZED: System is initialized""",
|
||||
"Mar 12 04:34:01 s1-leaf1 ProcMgr: %PROCMGR-7-WORKER_WARMSTART_DONE: ProcMgr worker warm start done. (PID=559)\nMar 12 04:34:01 "
|
||||
"s1-leaf1 ProcMgr: %PROCMGR-6-PROCESS_TERMINATED: 'SystemInitMonitor' (PID=867, status=9) has terminated.",
|
||||
"Mar 13 03:58:12 s1-leaf1 ConfigAgent: %SYS-5-CONFIG_SESSION_ABORTED: User cvpsystem aborted\n "
|
||||
"configuration session capiVerify-612-612b34a2ffbf11ef96ba3a348d538ba0 on TerminAttr (localhost)\n "
|
||||
"Mar 13 04:10:45 s1-leaf1 SystemInitMonitor: %SYS-5-SYSTEM_INITIALIZED: System is initialized",
|
||||
],
|
||||
"inputs": {
|
||||
"logging_entries": [
|
||||
|
@ -353,11 +241,11 @@ Mar 12 04:34:01 s1-leaf1 ProcMgr: %PROCMGR-6-PROCESS_TERMINATED: 'SystemInitMoni
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Pattern: .ACCOUNTING-5-EXEC: cvpadmin ssh. - Not found in last 3 informational log entries",
|
||||
"Pattern: .*ProcMgr worker warm start.* - Not found in last 10 debugging log entries",
|
||||
"Pattern: `.ACCOUNTING-5-EXEC: cvpadmin ssh.` - Not found in last 3 informational log entries",
|
||||
"Pattern: `.*ProcMgr worker warm start.*` - Not found in last 10 debugging log entries",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,196 +5,103 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.mlag import VerifyMlagConfigSanity, VerifyMlagDualPrimary, VerifyMlagInterfaces, VerifyMlagPrimaryPriority, VerifyMlagReloadDelay, VerifyMlagStatus
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagStatus,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyMlagStatus, "success"): {
|
||||
"eos_data": [{"state": "active", "negStatus": "connected", "peerLinkStatus": "up", "localIntfStatus": "up"}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyMlagStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
(VerifyMlagStatus, "skipped"): {
|
||||
"eos_data": [{"state": "disabled"}],
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-negotiation-status",
|
||||
"test": VerifyMlagStatus,
|
||||
(VerifyMlagStatus, "failure-negotiation-status"): {
|
||||
"eos_data": [{"state": "active", "negStatus": "connecting", "peerLinkStatus": "up", "localIntfStatus": "up"}],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["MLAG negotiation status mismatch - Expected: connected Actual: connecting"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MLAG negotiation status mismatch - Expected: connected Actual: connecting"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-local-interface",
|
||||
"test": VerifyMlagStatus,
|
||||
(VerifyMlagStatus, "failure-local-interface"): {
|
||||
"eos_data": [{"state": "active", "negStatus": "connected", "peerLinkStatus": "up", "localIntfStatus": "down"}],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Operational state of the MLAG local interface is not correct - Expected: up Actual: down"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Operational state of the MLAG local interface is not correct - Expected: up Actual: down"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-peer-link",
|
||||
"test": VerifyMlagStatus,
|
||||
(VerifyMlagStatus, "failure-peer-link"): {
|
||||
"eos_data": [{"state": "active", "negStatus": "connected", "peerLinkStatus": "down", "localIntfStatus": "up"}],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Operational state of the MLAG peer link is not correct - Expected: up Actual: down"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Operational state of the MLAG peer link is not correct - Expected: up Actual: down"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagInterfaces,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"mlagPorts": {"Disabled": 0, "Configured": 0, "Inactive": 0, "Active-partial": 0, "Active-full": 1},
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
(VerifyMlagInterfaces, "success"): {
|
||||
"eos_data": [{"state": "active", "mlagPorts": {"Disabled": 0, "Configured": 0, "Inactive": 0, "Active-partial": 0, "Active-full": 1}}],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyMlagInterfaces,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
(VerifyMlagInterfaces, "skipped"): {
|
||||
"eos_data": [{"state": "disabled"}],
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-active-partial",
|
||||
"test": VerifyMlagInterfaces,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"mlagPorts": {"Disabled": 0, "Configured": 0, "Inactive": 0, "Active-partial": 1, "Active-full": 1},
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["MLAG status is not ok - Inactive Ports: 0 Partial Active Ports: 1"],
|
||||
},
|
||||
(VerifyMlagInterfaces, "failure-active-partial"): {
|
||||
"eos_data": [{"state": "active", "mlagPorts": {"Disabled": 0, "Configured": 0, "Inactive": 0, "Active-partial": 1, "Active-full": 1}}],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MLAG status is not ok - Inactive Ports: 0 Partial Active Ports: 1"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-inactive",
|
||||
"test": VerifyMlagInterfaces,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"mlagPorts": {"Disabled": 0, "Configured": 0, "Inactive": 1, "Active-partial": 1, "Active-full": 1},
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["MLAG status is not ok - Inactive Ports: 1 Partial Active Ports: 1"],
|
||||
},
|
||||
(VerifyMlagInterfaces, "failure-inactive"): {
|
||||
"eos_data": [{"state": "active", "mlagPorts": {"Disabled": 0, "Configured": 0, "Inactive": 1, "Active-partial": 1, "Active-full": 1}}],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MLAG status is not ok - Inactive Ports: 1 Partial Active Ports: 1"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
(VerifyMlagConfigSanity, "success"): {
|
||||
"eos_data": [{"globalConfiguration": {}, "interfaceConfiguration": {}, "mlagActive": True, "mlagConnected": True}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
"eos_data": [
|
||||
{
|
||||
"mlagActive": False,
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
(VerifyMlagConfigSanity, "skipped"): {
|
||||
"eos_data": [{"mlagActive": False}],
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-global",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
(VerifyMlagConfigSanity, "failure-global"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"globalConfiguration": {"mlag": {"globalParameters": {"dual-primary-detection-delay": {"localValue": "0", "peerValue": "200"}}}},
|
||||
"interfaceConfiguration": {},
|
||||
"mlagActive": True,
|
||||
"mlagConnected": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["MLAG config-sanity found in global configuration"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MLAG config-sanity found in global configuration"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-interface",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
(VerifyMlagConfigSanity, "failure-interface"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"globalConfiguration": {},
|
||||
"interfaceConfiguration": {"trunk-native-vlan mlag30": {"interface": {"Port-Channel30": {"localValue": "123", "peerValue": "3700"}}}},
|
||||
"mlagActive": True,
|
||||
"mlagConnected": True,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["MLAG config-sanity found in interface configuration"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["MLAG config-sanity found in interface configuration"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagReloadDelay,
|
||||
(VerifyMlagReloadDelay, "success"): {
|
||||
"eos_data": [{"state": "active", "reloadDelay": 300, "reloadDelayNonMlag": 330}],
|
||||
"inputs": {"reload_delay": 300, "reload_delay_non_mlag": 330},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped-disabled",
|
||||
"test": VerifyMlagReloadDelay,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
},
|
||||
],
|
||||
(VerifyMlagReloadDelay, "skipped-disabled"): {
|
||||
"eos_data": [{"state": "disabled"}],
|
||||
"inputs": {"reload_delay": 300, "reload_delay_non_mlag": 330},
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyMlagReloadDelay,
|
||||
(VerifyMlagReloadDelay, "failure"): {
|
||||
"eos_data": [{"state": "active", "reloadDelay": 400, "reloadDelayNonMlag": 430}],
|
||||
"inputs": {"reload_delay": 300, "reload_delay_non_mlag": 330},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["MLAG reload-delay mismatch - Expected: 300s Actual: 400s", "Delay for non-MLAG ports mismatch - Expected: 330s Actual: 430s"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
(VerifyMlagDualPrimary, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
|
@ -203,38 +110,22 @@ DATA: list[dict[str, Any]] = [
|
|||
"dualPrimaryMlagRecoveryDelay": 60,
|
||||
"dualPrimaryNonMlagRecoveryDelay": 0,
|
||||
"detail": {"dualPrimaryDetectionDelay": 200, "dualPrimaryAction": "none"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"detection_delay": 200, "errdisabled": False, "recovery_delay": 60, "recovery_delay_non_mlag": 0},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped-disabled",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
},
|
||||
],
|
||||
(VerifyMlagDualPrimary, "skipped-disabled"): {
|
||||
"eos_data": [{"state": "disabled"}],
|
||||
"inputs": {"detection_delay": 200, "errdisabled": False, "recovery_delay": 60, "recovery_delay_non_mlag": 0},
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"dualPrimaryDetectionState": "disabled",
|
||||
"dualPrimaryPortsErrdisabled": False,
|
||||
},
|
||||
],
|
||||
(VerifyMlagDualPrimary, "failure-disabled"): {
|
||||
"eos_data": [{"state": "active", "dualPrimaryDetectionState": "disabled", "dualPrimaryPortsErrdisabled": False}],
|
||||
"inputs": {"detection_delay": 200, "errdisabled": False, "recovery_delay": 60, "recovery_delay_non_mlag": 0},
|
||||
"expected": {"result": "failure", "messages": ["Dual-primary detection is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Dual-primary detection is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-timers",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
(VerifyMlagDualPrimary, "failure-wrong-timers"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
|
@ -243,20 +134,18 @@ DATA: list[dict[str, Any]] = [
|
|||
"dualPrimaryMlagRecoveryDelay": 160,
|
||||
"dualPrimaryNonMlagRecoveryDelay": 0,
|
||||
"detail": {"dualPrimaryDetectionDelay": 300, "dualPrimaryAction": "none"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"detection_delay": 200, "errdisabled": False, "recovery_delay": 60, "recovery_delay_non_mlag": 0},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Dual-primary detection delay mismatch - Expected: 200 Actual: 300",
|
||||
"Dual-primary MLAG recovery delay mismatch - Expected: 60 Actual: 160",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-action",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
(VerifyMlagDualPrimary, "failure-wrong-action"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
|
@ -265,17 +154,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"dualPrimaryMlagRecoveryDelay": 60,
|
||||
"dualPrimaryNonMlagRecoveryDelay": 0,
|
||||
"detail": {"dualPrimaryDetectionDelay": 200, "dualPrimaryAction": "none"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"detection_delay": 200, "errdisabled": True, "recovery_delay": 60, "recovery_delay_non_mlag": 0},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Dual-primary action mismatch - Expected: errdisableAllInterfaces Actual: none"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Dual-primary action mismatch - Expected: errdisableAllInterfaces Actual: none"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-non-mlag-delay",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
(VerifyMlagDualPrimary, "failure-wrong-non-mlag-delay"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
|
@ -284,67 +168,32 @@ DATA: list[dict[str, Any]] = [
|
|||
"dualPrimaryMlagRecoveryDelay": 60,
|
||||
"dualPrimaryNonMlagRecoveryDelay": 120,
|
||||
"detail": {"dualPrimaryDetectionDelay": 200, "dualPrimaryAction": "errdisableAllInterfaces"},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"detection_delay": 200, "errdisabled": True, "recovery_delay": 60, "recovery_delay_non_mlag": 60},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Dual-primary non MLAG recovery delay mismatch - Expected: 60 Actual: 120"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Dual-primary non MLAG recovery delay mismatch - Expected: 60 Actual: 120"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagPrimaryPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"detail": {"mlagState": "primary", "primaryPriority": 32767},
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"primary_priority": 32767,
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "skipped-disabled",
|
||||
"test": VerifyMlagPrimaryPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
}
|
||||
],
|
||||
(VerifyMlagPrimaryPriority, "success"): {
|
||||
"eos_data": [{"state": "active", "detail": {"mlagState": "primary", "primaryPriority": 32767}}],
|
||||
"inputs": {"primary_priority": 32767},
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-primary",
|
||||
"test": VerifyMlagPrimaryPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"detail": {"mlagState": "secondary", "primaryPriority": 32767},
|
||||
}
|
||||
],
|
||||
(VerifyMlagPrimaryPriority, "skipped-disabled"): {
|
||||
"eos_data": [{"state": "disabled"}],
|
||||
"inputs": {"primary_priority": 32767},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["The device is not set as MLAG primary"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-priority",
|
||||
"test": VerifyMlagPrimaryPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"detail": {"mlagState": "secondary", "primaryPriority": 32767},
|
||||
}
|
||||
],
|
||||
(VerifyMlagPrimaryPriority, "failure-not-primary"): {
|
||||
"eos_data": [{"state": "active", "detail": {"mlagState": "secondary", "primaryPriority": 32767}}],
|
||||
"inputs": {"primary_priority": 32767},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The device is not set as MLAG primary"]},
|
||||
},
|
||||
(VerifyMlagPrimaryPriority, "failure-incorrect-priority"): {
|
||||
"eos_data": [{"state": "active", "detail": {"mlagState": "secondary", "primaryPriority": 32767}}],
|
||||
"inputs": {"primary_priority": 1},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["The device is not set as MLAG primary", "MLAG primary priority mismatch - Expected: 1 Actual: 32767"],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,15 +5,19 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.multicast import VerifyIGMPSnoopingGlobal, VerifyIGMPSnoopingVlans
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success-enabled",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyIGMPSnoopingVlans, "success-enabled"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
|
@ -45,14 +49,12 @@ DATA: list[dict[str, Any]] = [
|
|||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {1: True, 42: True}},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-disabled",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
(VerifyIGMPSnoopingVlans, "success-disabled"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
|
@ -68,19 +70,17 @@ DATA: list[dict[str, Any]] = [
|
|||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {42: False}},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-vlan",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
(VerifyIGMPSnoopingVlans, "failure-missing-vlan"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
|
@ -96,22 +96,20 @@ DATA: list[dict[str, Any]] = [
|
|||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {1: False, 42: False}},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["VLAN1 - Incorrect IGMP state - Expected: disabled Actual: enabled", "Supplied vlan 42 is not present on the device"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-state",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
(VerifyIGMPSnoopingVlans, "failure-wrong-state"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
|
@ -127,53 +125,29 @@ DATA: list[dict[str, Any]] = [
|
|||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
}
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {1: True}},
|
||||
"expected": {"result": "failure", "messages": ["VLAN1 - Incorrect IGMP state - Expected: enabled Actual: disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VLAN1 - Incorrect IGMP state - Expected: enabled Actual: disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success-enabled",
|
||||
"test": VerifyIGMPSnoopingGlobal,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
},
|
||||
],
|
||||
(VerifyIGMPSnoopingGlobal, "success-enabled"): {
|
||||
"eos_data": [{"reportFlooding": "disabled", "igmpSnoopingState": "enabled", "robustness": 2, "immediateLeave": "enabled", "reportFloodingSwitchPorts": []}],
|
||||
"inputs": {"enabled": True},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-disabled",
|
||||
"test": VerifyIGMPSnoopingGlobal,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "disabled",
|
||||
},
|
||||
],
|
||||
(VerifyIGMPSnoopingGlobal, "success-disabled"): {
|
||||
"eos_data": [{"reportFlooding": "disabled", "igmpSnoopingState": "disabled"}],
|
||||
"inputs": {"enabled": False},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-state",
|
||||
"test": VerifyIGMPSnoopingGlobal,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "disabled",
|
||||
},
|
||||
],
|
||||
(VerifyIGMPSnoopingGlobal, "failure-wrong-state"): {
|
||||
"eos_data": [{"reportFlooding": "disabled", "igmpSnoopingState": "disabled"}],
|
||||
"inputs": {"enabled": True},
|
||||
"expected": {"result": "failure", "messages": ["IGMP state is not valid - Expected: enabled Actual: disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["IGMP state is not valid - Expected: enabled Actual: disabled"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,101 +5,67 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.path_selection import VerifyPathsHealth, VerifySpecificPath
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPathsHealth,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyPathsHealth, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
"10.255.0.1": {
|
||||
"dpsGroups": {
|
||||
"internet": {
|
||||
"dpsPaths": {
|
||||
"path3": {"state": "routeResolved", "dpsSessions": {"0": {"active": True}}},
|
||||
},
|
||||
},
|
||||
"mpls": {
|
||||
"dpsPaths": {
|
||||
"path4": {"state": "ipsecEstablished", "dpsSessions": {"0": {"active": True}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"internet": {"dpsPaths": {"path3": {"state": "routeResolved", "dpsSessions": {"0": {"active": True}}}}},
|
||||
"mpls": {"dpsPaths": {"path4": {"state": "ipsecEstablished", "dpsSessions": {"0": {"active": True}}}}},
|
||||
}
|
||||
},
|
||||
"10.255.0.2": {
|
||||
"dpsGroups": {
|
||||
"internet": {
|
||||
"dpsPaths": {
|
||||
"path1": {"state": "ipsecEstablished", "dpsSessions": {"0": {"active": True}}},
|
||||
},
|
||||
},
|
||||
"mpls": {
|
||||
"dpsPaths": {
|
||||
"path2": {"state": "routeResolved", "dpsSessions": {"0": {"active": True}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"internet": {"dpsPaths": {"path1": {"state": "ipsecEstablished", "dpsSessions": {"0": {"active": True}}}}},
|
||||
"mpls": {"dpsPaths": {"path2": {"state": "routeResolved", "dpsSessions": {"0": {"active": True}}}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyPathsHealth,
|
||||
"eos_data": [
|
||||
{"dpsPeers": {}},
|
||||
],
|
||||
(VerifyPathsHealth, "failure-no-peer"): {
|
||||
"eos_data": [{"dpsPeers": {}}],
|
||||
"inputs": {},
|
||||
"expected": {"result": "failure", "messages": ["No path configured for router path-selection"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No path configured for router path-selection"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-established",
|
||||
"test": VerifyPathsHealth,
|
||||
(VerifyPathsHealth, "failure-not-established"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
"10.255.0.1": {
|
||||
"dpsGroups": {
|
||||
"internet": {
|
||||
"dpsPaths": {
|
||||
"path3": {"state": "ipsecPending", "dpsSessions": {"0": {"active": False}}},
|
||||
},
|
||||
},
|
||||
"mpls": {
|
||||
"dpsPaths": {
|
||||
"path4": {"state": "ipsecPending", "dpsSessions": {"0": {"active": False}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"internet": {"dpsPaths": {"path3": {"state": "ipsecPending", "dpsSessions": {"0": {"active": False}}}}},
|
||||
"mpls": {"dpsPaths": {"path4": {"state": "ipsecPending", "dpsSessions": {"0": {"active": False}}}}},
|
||||
}
|
||||
},
|
||||
"10.255.0.2": {
|
||||
"dpsGroups": {
|
||||
"internet": {
|
||||
"dpsPaths": {
|
||||
"path1": {"state": "ipsecEstablished", "dpsSessions": {"0": {"active": True}}},
|
||||
},
|
||||
},
|
||||
"mpls": {
|
||||
"dpsPaths": {
|
||||
"path2": {"state": "ipsecPending", "dpsSessions": {"0": {"active": False}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"internet": {"dpsPaths": {"path1": {"state": "ipsecEstablished", "dpsSessions": {"0": {"active": True}}}}},
|
||||
"mpls": {"dpsPaths": {"path2": {"state": "ipsecPending", "dpsSessions": {"0": {"active": False}}}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 10.255.0.1 Path Group: internet - Invalid path state - Expected: ipsecEstablished, routeResolved Actual: ipsecPending",
|
||||
"Peer: 10.255.0.1 Path Group: mpls - Invalid path state - Expected: ipsecEstablished, routeResolved Actual: ipsecPending",
|
||||
|
@ -107,46 +73,28 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-inactive",
|
||||
"test": VerifyPathsHealth,
|
||||
(VerifyPathsHealth, "failure-inactive"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
"10.255.0.1": {
|
||||
"dpsGroups": {
|
||||
"internet": {
|
||||
"dpsPaths": {
|
||||
"path3": {"state": "routeResolved", "dpsSessions": {"0": {"active": False}}},
|
||||
},
|
||||
},
|
||||
"mpls": {
|
||||
"dpsPaths": {
|
||||
"path4": {"state": "routeResolved", "dpsSessions": {"0": {"active": False}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"internet": {"dpsPaths": {"path3": {"state": "routeResolved", "dpsSessions": {"0": {"active": False}}}}},
|
||||
"mpls": {"dpsPaths": {"path4": {"state": "routeResolved", "dpsSessions": {"0": {"active": False}}}}},
|
||||
}
|
||||
},
|
||||
"10.255.0.2": {
|
||||
"dpsGroups": {
|
||||
"internet": {
|
||||
"dpsPaths": {
|
||||
"path1": {"state": "routeResolved", "dpsSessions": {"0": {"active": True}}},
|
||||
},
|
||||
},
|
||||
"mpls": {
|
||||
"dpsPaths": {
|
||||
"path2": {"state": "routeResolved", "dpsSessions": {"0": {"active": False}}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"internet": {"dpsPaths": {"path1": {"state": "routeResolved", "dpsSessions": {"0": {"active": True}}}}},
|
||||
"mpls": {"dpsPaths": {"path2": {"state": "routeResolved", "dpsSessions": {"0": {"active": False}}}}},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 10.255.0.1 Path Group internet - Telemetry state inactive",
|
||||
"Peer: 10.255.0.1 Path Group mpls - Telemetry state inactive",
|
||||
|
@ -154,9 +102,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySpecificPath,
|
||||
(VerifySpecificPath, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
|
@ -200,21 +146,10 @@ DATA: list[dict[str, Any]] = [
|
|||
{"peer": "10.255.0.2", "path_group": "mpls", "source_address": "172.18.13.2", "destination_address": "172.18.15.2"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-expected-path-group-not-found",
|
||||
"test": VerifySpecificPath,
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
"10.255.0.2": {
|
||||
"dpsGroups": {"internet": {}},
|
||||
},
|
||||
"10.255.0.1": {"peerName": "", "dpsGroups": {"mpls": {}}},
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifySpecificPath, "failure-expected-path-group-not-found"): {
|
||||
"eos_data": [{"dpsPeers": {"10.255.0.2": {"dpsGroups": {"internet": {}}}, "10.255.0.1": {"peerName": "", "dpsGroups": {"mpls": {}}}}}],
|
||||
"inputs": {
|
||||
"paths": [
|
||||
{"peer": "10.255.0.1", "path_group": "internet", "source_address": "100.64.3.2", "destination_address": "100.64.1.2"},
|
||||
|
@ -222,30 +157,27 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 10.255.0.1 PathGroup: internet Source: 100.64.3.2 Destination: 100.64.1.2 - No DPS path found for this peer and path group",
|
||||
"Peer: 10.255.0.2 PathGroup: mpls Source: 172.18.13.2 Destination: 172.18.15.2 - No DPS path found for this peer and path group",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-router-path-configured",
|
||||
"test": VerifySpecificPath,
|
||||
(VerifySpecificPath, "failure-no-router-path-configured"): {
|
||||
"eos_data": [{"dpsPeers": {}}],
|
||||
"inputs": {"paths": [{"peer": "10.255.0.1", "path_group": "internet", "source_address": "100.64.3.2", "destination_address": "100.64.1.2"}]},
|
||||
"expected": {"result": "failure", "messages": ["Router path-selection not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Router path-selection not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-specific-peer-configured",
|
||||
"test": VerifySpecificPath,
|
||||
(VerifySpecificPath, "failure-no-specific-peer-configured"): {
|
||||
"eos_data": [{"dpsPeers": {"10.255.0.2": {}}}],
|
||||
"inputs": {"paths": [{"peer": "10.255.0.1", "path_group": "internet", "source_address": "172.18.3.2", "destination_address": "172.18.5.2"}]},
|
||||
"expected": {"result": "failure", "messages": ["Peer: 10.255.0.1 PathGroup: internet Source: 172.18.3.2 Destination: 172.18.5.2 - Peer not found"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Peer: 10.255.0.1 PathGroup: internet Source: 172.18.3.2 Destination: 172.18.5.2 - Peer not found"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-established",
|
||||
"test": VerifySpecificPath,
|
||||
(VerifySpecificPath, "failure-not-established"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
|
@ -285,18 +217,16 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 10.255.0.1 PathGroup: internet Source: 172.18.3.2 Destination: 172.18.5.2 - Invalid state path - Expected: ipsecEstablished, routeResolved "
|
||||
"Actual: ipsecPending",
|
||||
"Peer: 10.255.0.2 PathGroup: mpls Source: 172.18.13.2 Destination: 172.18.15.2 - Invalid state path - Expected: ipsecEstablished, routeResolved "
|
||||
"Actual: ipsecPending",
|
||||
"Peer: 10.255.0.1 PathGroup: internet Source: 172.18.3.2 Destination: 172.18.5.2 - Invalid state path - "
|
||||
"Expected: ipsecEstablished, routeResolved Actual: ipsecPending",
|
||||
"Peer: 10.255.0.2 PathGroup: mpls Source: 172.18.13.2 Destination: 172.18.15.2 - Invalid state path - "
|
||||
"Expected: ipsecEstablished, routeResolved Actual: ipsecPending",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-inactive",
|
||||
"test": VerifySpecificPath,
|
||||
(VerifySpecificPath, "failure-inactive"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
|
@ -333,16 +263,14 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 10.255.0.1 PathGroup: internet Source: 172.18.3.2 Destination: 172.18.5.2 - Telemetry state inactive for this path",
|
||||
"Peer: 10.255.0.2 PathGroup: mpls Source: 172.18.13.2 Destination: 172.18.15.2 - Telemetry state inactive for this path",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-source-destination-not-configured",
|
||||
"test": VerifySpecificPath,
|
||||
(VerifySpecificPath, "failure-source-destination-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"dpsPeers": {
|
||||
|
@ -374,11 +302,11 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Peer: 10.255.0.1 PathGroup: internet Source: 172.18.3.2 Destination: 172.18.5.2 - No path matching the source and destination found",
|
||||
"Peer: 10.255.0.2 PathGroup: mpls Source: 172.18.13.2 Destination: 172.18.15.2 - No path matching the source and destination found",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,42 +5,40 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.profiles import VerifyTcamProfile, VerifyUnifiedForwardingTableMode
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyUnifiedForwardingTableMode,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyUnifiedForwardingTableMode, "success"): {
|
||||
"eos_data": [{"uftMode": "2", "urpfEnabled": False, "chipModel": "bcm56870", "l2TableSize": 163840, "l3TableSize": 147456, "lpmTableSize": 32768}],
|
||||
"inputs": {"mode": 2},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyUnifiedForwardingTableMode,
|
||||
(VerifyUnifiedForwardingTableMode, "failure"): {
|
||||
"eos_data": [{"uftMode": "2", "urpfEnabled": False, "chipModel": "bcm56870", "l2TableSize": 163840, "l3TableSize": 147456, "lpmTableSize": 32768}],
|
||||
"inputs": {"mode": 3},
|
||||
"expected": {"result": "failure", "messages": ["Not running the correct UFT mode - Expected: 3 Actual: 2"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Not running the correct UFT mode - Expected: 3 Actual: 2"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTcamProfile,
|
||||
(VerifyTcamProfile, "success"): {
|
||||
"eos_data": [
|
||||
{"pmfProfiles": {"FixedSystem": {"config": "test", "configType": "System Profile", "status": "test", "mode": "tcam"}}, "lastProgrammingStatus": {}},
|
||||
{"pmfProfiles": {"FixedSystem": {"config": "test", "configType": "System Profile", "status": "test", "mode": "tcam"}}, "lastProgrammingStatus": {}}
|
||||
],
|
||||
"inputs": {"profile": "test"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTcamProfile,
|
||||
(VerifyTcamProfile, "failure"): {
|
||||
"eos_data": [
|
||||
{"pmfProfiles": {"FixedSystem": {"config": "test", "configType": "System Profile", "status": "default", "mode": "tcam"}}, "lastProgrammingStatus": {}},
|
||||
{"pmfProfiles": {"FixedSystem": {"config": "test", "configType": "System Profile", "status": "default", "mode": "tcam"}}, "lastProgrammingStatus": {}}
|
||||
],
|
||||
"inputs": {"profile": "test"},
|
||||
"expected": {"result": "failure", "messages": ["Incorrect profile running on device: default"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Incorrect profile running on device: default"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,15 +5,19 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.ptp import VerifyPtpGMStatus, VerifyPtpLockStatus, VerifyPtpModeStatus, VerifyPtpOffset, VerifyPtpPortModeStatus
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPtpModeStatus,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyPtpModeStatus, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -31,26 +35,17 @@ DATA: list[dict[str, Any]] = [
|
|||
"ptpIntfSummaries": {},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyPtpModeStatus,
|
||||
(VerifyPtpModeStatus, "failure"): {
|
||||
"eos_data": [{"ptpMode": "ptpDisabled", "ptpIntfSummaries": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Not configured as a PTP Boundary Clock - Actual: ptpDisabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Not configured as a PTP Boundary Clock - Actual: ptpDisabled"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyPtpModeStatus,
|
||||
(VerifyPtpModeStatus, "skipped"): {
|
||||
"eos_data": [{"ptpIntfSummaries": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["PTP is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["PTP is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPtpGMStatus,
|
||||
(VerifyPtpGMStatus, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -72,11 +67,9 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {"gmid": "0xec:46:70:ff:fe:00:ff:a8"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyPtpGMStatus,
|
||||
(VerifyPtpGMStatus, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -97,22 +90,16 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {"gmid": "0xec:46:70:ff:fe:00:ff:a8"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"The device is locked to the incorrect Grandmaster - Expected: 0xec:46:70:ff:fe:00:ff:a8 Actual: 0x00:1c:73:ff:ff:0a:00:01",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["The device is locked to the incorrect Grandmaster - Expected: 0xec:46:70:ff:fe:00:ff:a8 Actual: 0x00:1c:73:ff:ff:0a:00:01"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyPtpGMStatus,
|
||||
(VerifyPtpGMStatus, "skipped"): {
|
||||
"eos_data": [{"ptpIntfSummaries": {}}],
|
||||
"inputs": {"gmid": "0xec:46:70:ff:fe:00:ff:a8"},
|
||||
"expected": {"result": "skipped", "messages": ["PTP is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["PTP is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPtpLockStatus,
|
||||
(VerifyPtpLockStatus, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -133,12 +120,9 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyPtpLockStatus,
|
||||
(VerifyPtpLockStatus, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -157,24 +141,13 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Lock is more than 60s old - Actual: 157s"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Lock is more than 60s old - Actual: 157s"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyPtpLockStatus,
|
||||
(VerifyPtpLockStatus, "skipped"): {
|
||||
"eos_data": [{"ptpIntfSummaries": {}}],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "skipped",
|
||||
"messages": [
|
||||
"PTP is not configured",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["PTP is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPtpOffset,
|
||||
(VerifyPtpOffset, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"monitorEnabled": True,
|
||||
|
@ -201,12 +174,9 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyPtpOffset,
|
||||
(VerifyPtpOffset, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"monitorEnabled": True,
|
||||
|
@ -233,29 +203,16 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Interface: Ethernet27/1 - Timing offset from master is greater than +/- 1000ns: Actual: 1200, -1300",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Interface: Ethernet27/1 - Timing offset from master is greater than +/- 1000ns: Actual: 1200, -1300"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyPtpOffset,
|
||||
"eos_data": [
|
||||
{
|
||||
"monitorEnabled": True,
|
||||
"ptpMonitorData": [],
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["PTP is not configured"]},
|
||||
(VerifyPtpOffset, "skipped"): {
|
||||
"eos_data": [{"monitorEnabled": True, "ptpMonitorData": []}],
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["PTP is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPtpPortModeStatus,
|
||||
(VerifyPtpPortModeStatus, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -293,19 +250,13 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-interfaces",
|
||||
"test": VerifyPtpPortModeStatus,
|
||||
(VerifyPtpPortModeStatus, "failure-no-interfaces"): {
|
||||
"eos_data": [{"ptpIntfSummaries": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["No interfaces are PTP enabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No interfaces are PTP enabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-invalid-state",
|
||||
"test": VerifyPtpPortModeStatus,
|
||||
(VerifyPtpPortModeStatus, "failure-invalid-state"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
|
@ -336,7 +287,6 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["The following interface(s) are not in a valid PTP state: Ethernet53, Ethernet1"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following interface(s) are not in a valid PTP state: Ethernet53, Ethernet1"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -5,65 +5,58 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.services import VerifyDNSLookup, VerifyDNSServers, VerifyErrdisableRecovery, VerifyHostname
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyHostname,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyHostname, "success"): {
|
||||
"eos_data": [{"hostname": "s1-spine1", "fqdn": "s1-spine1.fun.aristanetworks.com"}],
|
||||
"inputs": {"hostname": "s1-spine1"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-hostname",
|
||||
"test": VerifyHostname,
|
||||
(VerifyHostname, "failure-incorrect-hostname"): {
|
||||
"eos_data": [{"hostname": "s1-spine2", "fqdn": "s1-spine1.fun.aristanetworks.com"}],
|
||||
"inputs": {"hostname": "s1-spine1"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Incorrect Hostname - Expected: s1-spine1 Actual: s1-spine2"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Incorrect Hostname - Expected: s1-spine1 Actual: s1-spine2"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyDNSLookup,
|
||||
(VerifyDNSLookup, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"messages": [
|
||||
"Server:\t\t127.0.0.1\nAddress:\t127.0.0.1#53\n\nNon-authoritative answer:\nName:\tarista.com\nAddress: 151.101.130.132\nName:\tarista.com\n"
|
||||
"Address: 151.101.2.132\nName:\tarista.com\nAddress: 151.101.194.132\nName:\tarista.com\nAddress: 151.101.66.132\n\n"
|
||||
"Server:\t\t127.0.0.1\nAddress:\t127.0.0.1#53\n\nNon-authoritative answer:\nName:\tarista.com\nAddress: 151.101.130.132\n"
|
||||
"Name:\tarista.com\nAddress: 151.101.2.132\nName:\tarista.com\nAddress: 151.101.194.132\nName:\tarista.com\nAddress: 151.101.66.132\n\n"
|
||||
]
|
||||
},
|
||||
{"messages": ["Server:\t\t127.0.0.1\nAddress:\t127.0.0.1#53\n\nNon-authoritative answer:\nName:\twww.google.com\nAddress: 172.217.12.100\n\n"]},
|
||||
],
|
||||
"inputs": {"domain_names": ["arista.com", "www.google.com"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyDNSLookup,
|
||||
(VerifyDNSLookup, "failure"): {
|
||||
"eos_data": [
|
||||
{"messages": ["Server:\t\t127.0.0.1\nAddress:\t127.0.0.1#53\n\nNon-authoritative answer:\n*** Can't find arista.ca: No answer\n\n"]},
|
||||
{"messages": ["Server:\t\t127.0.0.1\nAddress:\t127.0.0.1#53\n\nNon-authoritative answer:\nName:\twww.google.com\nAddress: 172.217.12.100\n\n"]},
|
||||
{"messages": ["Server:\t\t127.0.0.1\nAddress:\t127.0.0.1#53\n\nNon-authoritative answer:\n*** Can't find google.ca: No answer\n\n"]},
|
||||
],
|
||||
"inputs": {"domain_names": ["arista.ca", "www.google.com", "google.ca"]},
|
||||
"expected": {"result": "failure", "messages": ["The following domain(s) are not resolved to an IP address: arista.ca, google.ca"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following domain(s) are not resolved to an IP address: arista.ca, google.ca"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyDNSServers,
|
||||
(VerifyDNSServers, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"nameServerConfigs": [
|
||||
{"ipAddr": "10.14.0.1", "vrf": "default", "priority": 0},
|
||||
{"ipAddr": "10.14.0.11", "vrf": "MGMT", "priority": 1},
|
||||
{"ipAddr": "fd12:3456:789a::1", "vrf": "default", "priority": 0},
|
||||
],
|
||||
]
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
|
@ -73,32 +66,20 @@ DATA: list[dict[str, Any]] = [
|
|||
{"server_address": "fd12:3456:789a::1", "vrf": "default", "priority": 0},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-dns-found",
|
||||
"test": VerifyDNSServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"nameServerConfigs": [],
|
||||
}
|
||||
],
|
||||
(VerifyDNSServers, "failure-no-dns-found"): {
|
||||
"eos_data": [{"nameServerConfigs": []}],
|
||||
"inputs": {
|
||||
"dns_servers": [{"server_address": "10.14.0.10", "vrf": "default", "priority": 0}, {"server_address": "10.14.0.21", "vrf": "MGMT", "priority": 1}]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Server 10.14.0.10 VRF: default Priority: 0 - Not configured", "Server 10.14.0.21 VRF: MGMT Priority: 1 - Not configured"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-dns-details",
|
||||
"test": VerifyDNSServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"nameServerConfigs": [{"ipAddr": "10.14.0.1", "vrf": "CS", "priority": 1}, {"ipAddr": "10.14.0.11", "vrf": "MGMT", "priority": 1}],
|
||||
}
|
||||
],
|
||||
(VerifyDNSServers, "failure-incorrect-dns-details"): {
|
||||
"eos_data": [{"nameServerConfigs": [{"ipAddr": "10.14.0.1", "vrf": "CS", "priority": 1}, {"ipAddr": "10.14.0.11", "vrf": "MGMT", "priority": 1}]}],
|
||||
"inputs": {
|
||||
"dns_servers": [
|
||||
{"server_address": "10.14.0.1", "vrf": "CS", "priority": 0},
|
||||
|
@ -107,7 +88,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Server 10.14.0.1 VRF: CS Priority: 0 - Incorrect priority - Priority: 1",
|
||||
"Server 10.14.0.11 VRF: default Priority: 0 - Not configured",
|
||||
|
@ -115,94 +96,62 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
(VerifyErrdisableRecovery, "success"): {
|
||||
"eos_data": [
|
||||
# Adding empty line on purpose to verify they are skipped
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Enabled 300
|
||||
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
"\n Errdisable Reason Timer Status Timer Interval\n ------------------------------"
|
||||
" ----------------- --------------\n acl Enabled 300\n\n "
|
||||
" bpduguard Enabled 300\n arp-inspection "
|
||||
" Enabled 30\n "
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 300}, {"reason": "bpduguard", "interval": 300}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-reason-missing",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
(VerifyErrdisableRecovery, "failure-reason-missing"): {
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Enabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
"\n Errdisable Reason Timer Status Timer Interval\n ------------------------------"
|
||||
" ----------------- --------------\n acl Enabled 300\n "
|
||||
" bpduguard Enabled 300\n arp-inspection Enabled"
|
||||
" 30\n "
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 300}, {"reason": "arp-inspection", "interval": 30}, {"reason": "tapagg", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Reason: tapagg Status: Enabled Interval: 30 - Not found"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Reason: tapagg Status: Enabled Interval: 30 - Not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-reason-disabled",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
(VerifyErrdisableRecovery, "failure-reason-disabled"): {
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Disabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
"\n Errdisable Reason Timer Status Timer Interval\n ------------------------------ "
|
||||
"----------------- --------------\n acl Disabled 300\n "
|
||||
"bpduguard Enabled 300\n arp-inspection Enabled"
|
||||
" 30\n "
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 300}, {"reason": "arp-inspection", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Reason: acl Status: Enabled Interval: 300 - Incorrect configuration - Status: Disabled Interval: 300"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-interval-not-ok",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
(VerifyErrdisableRecovery, "failure-interval-not-ok"): {
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Enabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
"\n Errdisable Reason Timer Status Timer Interval\n ------------------------------ "
|
||||
"----------------- --------------\n acl Enabled 300\n "
|
||||
"bpduguard Enabled 300\n arp-inspection Enabled "
|
||||
" 30\n "
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 30}, {"reason": "arp-inspection", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Reason: acl Status: Enabled Interval: 30 - Incorrect configuration - Status: Enabled Interval: 300",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Reason: acl Status: Enabled Interval: 30 - Incorrect configuration - Status: Enabled Interval: 300"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-type",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
(VerifyErrdisableRecovery, "failure-all-type"): {
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Disabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
"\n Errdisable Reason Timer Status Timer Interval\n ------------------------------ "
|
||||
"----------------- --------------\n acl Disabled 300\n "
|
||||
"bpduguard Enabled 300\n arp-inspection Enabled "
|
||||
" 30\n "
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 30}, {"reason": "arp-inspection", "interval": 300}, {"reason": "tapagg", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Reason: acl Status: Enabled Interval: 30 - Incorrect configuration - Status: Disabled Interval: 300",
|
||||
"Reason: arp-inspection Status: Enabled Interval: 300 - Incorrect configuration - Status: Enabled Interval: 30",
|
||||
|
@ -210,4 +159,4 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.snmp import (
|
||||
VerifySnmpContact,
|
||||
VerifySnmpErrorCounters,
|
||||
|
@ -23,234 +26,117 @@ from anta.tests.snmp import (
|
|||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpStatus,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifySnmpStatus, "success"): {
|
||||
"eos_data": [{"vrfs": {"snmpVrfs": ["MGMT", "default"]}, "enabled": True}],
|
||||
"inputs": {"vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySnmpStatus,
|
||||
(VerifySnmpStatus, "failure-wrong-vrf"): {
|
||||
"eos_data": [{"vrfs": {"snmpVrfs": ["default"]}, "enabled": True}],
|
||||
"inputs": {"vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT - SNMP agent disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT - SNMP agent disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifySnmpStatus,
|
||||
(VerifySnmpStatus, "failure-disabled"): {
|
||||
"eos_data": [{"vrfs": {"snmpVrfs": ["default"]}, "enabled": False}],
|
||||
"inputs": {"vrf": "default"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: default - SNMP agent disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: default - SNMP agent disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpIPv4Acl,
|
||||
(VerifySnmpIPv4Acl, "success"): {
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_SNMP", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifySnmpIPv4Acl,
|
||||
(VerifySnmpIPv4Acl, "failure-wrong-number"): {
|
||||
"eos_data": [{"ipAclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT - Incorrect SNMP IPv4 ACL(s) - Expected: 1 Actual: 0"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT - Incorrect SNMP IPv4 ACL(s) - Expected: 1 Actual: 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySnmpIPv4Acl,
|
||||
(VerifySnmpIPv4Acl, "failure-wrong-vrf"): {
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_SNMP", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT - Following SNMP IPv4 ACL(s) not configured or active: ACL_IPV4_SNMP"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT - Following SNMP IPv4 ACL(s) not configured or active: ACL_IPV4_SNMP"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpIPv6Acl,
|
||||
(VerifySnmpIPv6Acl, "success"): {
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_SNMP", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifySnmpIPv6Acl,
|
||||
(VerifySnmpIPv6Acl, "failure-wrong-number"): {
|
||||
"eos_data": [{"ipv6AclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT - Incorrect SNMP IPv6 ACL(s) - Expected: 1 Actual: 0"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT - Incorrect SNMP IPv6 ACL(s) - Expected: 1 Actual: 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySnmpIPv6Acl,
|
||||
(VerifySnmpIPv6Acl, "failure-wrong-vrf"): {
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_SNMP", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["VRF: MGMT - Following SNMP IPv6 ACL(s) not configured or active: ACL_IPV6_SNMP"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VRF: MGMT - Following SNMP IPv6 ACL(s) not configured or active: ACL_IPV6_SNMP"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpLocation,
|
||||
"eos_data": [
|
||||
{
|
||||
"location": {"location": "New York"},
|
||||
}
|
||||
],
|
||||
(VerifySnmpLocation, "success"): {
|
||||
"eos_data": [{"location": {"location": "New York"}}],
|
||||
"inputs": {"location": "New York"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-location",
|
||||
"test": VerifySnmpLocation,
|
||||
"eos_data": [
|
||||
{
|
||||
"location": {"location": "Europe"},
|
||||
}
|
||||
],
|
||||
(VerifySnmpLocation, "failure-incorrect-location"): {
|
||||
"eos_data": [{"location": {"location": "Europe"}}],
|
||||
"inputs": {"location": "New York"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Incorrect SNMP location - Expected: New York Actual: Europe"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Incorrect SNMP location - Expected: New York Actual: Europe"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-details-not-configured",
|
||||
"test": VerifySnmpLocation,
|
||||
"eos_data": [
|
||||
{
|
||||
"location": {"location": ""},
|
||||
}
|
||||
],
|
||||
(VerifySnmpLocation, "failure-details-not-configured"): {
|
||||
"eos_data": [{"location": {"location": ""}}],
|
||||
"inputs": {"location": "New York"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["SNMP location is not configured"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["SNMP location is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpContact,
|
||||
"eos_data": [
|
||||
{
|
||||
"contact": {"contact": "Jon@example.com"},
|
||||
}
|
||||
],
|
||||
(VerifySnmpContact, "success"): {
|
||||
"eos_data": [{"contact": {"contact": "Jon@example.com"}}],
|
||||
"inputs": {"contact": "Jon@example.com"},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-contact",
|
||||
"test": VerifySnmpContact,
|
||||
"eos_data": [
|
||||
{
|
||||
"contact": {"contact": "Jon@example.com"},
|
||||
}
|
||||
],
|
||||
(VerifySnmpContact, "failure-incorrect-contact"): {
|
||||
"eos_data": [{"contact": {"contact": "Jon@example.com"}}],
|
||||
"inputs": {"contact": "Bob@example.com"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Incorrect SNMP contact - Expected: Bob@example.com Actual: Jon@example.com"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Incorrect SNMP contact - Expected: Bob@example.com Actual: Jon@example.com"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-details-not-configured",
|
||||
"test": VerifySnmpContact,
|
||||
"eos_data": [
|
||||
{
|
||||
"contact": {"contact": ""},
|
||||
}
|
||||
],
|
||||
(VerifySnmpContact, "failure-details-not-configured"): {
|
||||
"eos_data": [{"contact": {"contact": ""}}],
|
||||
"inputs": {"contact": "Bob@example.com"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["SNMP contact is not configured"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["SNMP contact is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpPDUCounters,
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {
|
||||
"inGetPdus": 3,
|
||||
"inGetNextPdus": 2,
|
||||
"inSetPdus": 3,
|
||||
"outGetResponsePdus": 3,
|
||||
"outTrapPdus": 9,
|
||||
},
|
||||
}
|
||||
],
|
||||
(VerifySnmpPDUCounters, "success"): {
|
||||
"eos_data": [{"counters": {"inGetPdus": 3, "inGetNextPdus": 2, "inSetPdus": 3, "outGetResponsePdus": 3, "outTrapPdus": 9}}],
|
||||
"inputs": {},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-specific-pdus",
|
||||
"test": VerifySnmpPDUCounters,
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {
|
||||
"inGetPdus": 3,
|
||||
"inGetNextPdus": 0,
|
||||
"inSetPdus": 0,
|
||||
"outGetResponsePdus": 0,
|
||||
"outTrapPdus": 9,
|
||||
},
|
||||
}
|
||||
],
|
||||
(VerifySnmpPDUCounters, "success-specific-pdus"): {
|
||||
"eos_data": [{"counters": {"inGetPdus": 3, "inGetNextPdus": 0, "inSetPdus": 0, "outGetResponsePdus": 0, "outTrapPdus": 9}}],
|
||||
"inputs": {"pdus": ["inGetPdus", "outTrapPdus"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-counters-not-found",
|
||||
"test": VerifySnmpPDUCounters,
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {},
|
||||
}
|
||||
],
|
||||
(VerifySnmpPDUCounters, "failure-counters-not-found"): {
|
||||
"eos_data": [{"counters": {}}],
|
||||
"inputs": {},
|
||||
"expected": {"result": "failure", "messages": ["SNMP counters not found"]},
|
||||
"expected": {"result": AntaTestStatus.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,
|
||||
},
|
||||
}
|
||||
],
|
||||
(VerifySnmpPDUCounters, "failure-incorrect-counters"): {
|
||||
"eos_data": [{"counters": {"inGetPdus": 0, "inGetNextPdus": 2, "inSetPdus": 0, "outGetResponsePdus": 3, "outTrapPdus": 9}}],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["The following SNMP PDU counters are not found or have zero PDU counters: inGetPdus, inSetPdus"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-pdu-not-found",
|
||||
"test": VerifySnmpPDUCounters,
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {
|
||||
"inGetNextPdus": 0,
|
||||
"inSetPdus": 0,
|
||||
"outGetResponsePdus": 0,
|
||||
},
|
||||
}
|
||||
],
|
||||
(VerifySnmpPDUCounters, "failure-pdu-not-found"): {
|
||||
"eos_data": [{"counters": {"inGetNextPdus": 0, "inSetPdus": 0, "outGetResponsePdus": 0}}],
|
||||
"inputs": {"pdus": ["inGetPdus", "outTrapPdus"]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["The following SNMP PDU counters are not found or have zero PDU counters: inGetPdus, outTrapPdus"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpErrorCounters,
|
||||
(VerifySnmpErrorCounters, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {
|
||||
|
@ -262,15 +148,13 @@ DATA: list[dict[str, Any]] = [
|
|||
"outNoSuchNameErrs": 0,
|
||||
"outBadValueErrs": 0,
|
||||
"outGeneralErrs": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-specific-counters",
|
||||
"test": VerifySnmpErrorCounters,
|
||||
(VerifySnmpErrorCounters, "success-specific-counters"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {
|
||||
|
@ -282,26 +166,18 @@ DATA: list[dict[str, Any]] = [
|
|||
"outNoSuchNameErrs": 0,
|
||||
"outBadValueErrs": 10,
|
||||
"outGeneralErrs": 1,
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"error_counters": ["inVersionErrs", "inParseErrs"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-counters-not-found",
|
||||
"test": VerifySnmpErrorCounters,
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {},
|
||||
}
|
||||
],
|
||||
(VerifySnmpErrorCounters, "failure-counters-not-found"): {
|
||||
"eos_data": [{"counters": {}}],
|
||||
"inputs": {},
|
||||
"expected": {"result": "failure", "messages": ["SNMP counters not found"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["SNMP counters not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-counters",
|
||||
"test": VerifySnmpErrorCounters,
|
||||
(VerifySnmpErrorCounters, "failure-incorrect-counters"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"counters": {
|
||||
|
@ -313,18 +189,16 @@ DATA: list[dict[str, Any]] = [
|
|||
"outNoSuchNameErrs": 0,
|
||||
"outBadValueErrs": 2,
|
||||
"outGeneralErrs": 0,
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["The following SNMP error counters are not found or have non-zero error counters: inParseErrs, inVersionErrs, outBadValueErrs"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpHostLogging,
|
||||
(VerifySnmpHostLogging, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"logging": {
|
||||
|
@ -344,61 +218,38 @@ DATA: list[dict[str, Any]] = [
|
|||
{"hostname": "snmp-server-01", "vrf": "default"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-logging-disabled",
|
||||
"test": VerifySnmpHostLogging,
|
||||
(VerifySnmpHostLogging, "failure-logging-disabled"): {
|
||||
"eos_data": [{"logging": {"loggingEnabled": False}}],
|
||||
"inputs": {"hosts": [{"hostname": "192.168.1.100", "vrf": "default"}, {"hostname": "192.168.1.101", "vrf": "MGMT"}]},
|
||||
"expected": {"result": "failure", "messages": ["SNMP logging is disabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["SNMP logging is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-mismatch-vrf",
|
||||
"test": VerifySnmpHostLogging,
|
||||
(VerifySnmpHostLogging, "failure-mismatch-vrf"): {
|
||||
"eos_data": [{"logging": {"loggingEnabled": True, "hosts": {"192.168.1.100": {"port": 162, "vrf": "MGMT"}, "192.168.1.101": {"port": 162, "vrf": "Test"}}}}],
|
||||
"inputs": {"hosts": [{"hostname": "192.168.1.100", "vrf": "default"}, {"hostname": "192.168.1.101", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Host: 192.168.1.100 VRF: default - Incorrect VRF - Actual: MGMT", "Host: 192.168.1.101 VRF: MGMT - Incorrect VRF - Actual: Test"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-host-not-configured",
|
||||
"test": VerifySnmpHostLogging,
|
||||
(VerifySnmpHostLogging, "failure-host-not-configured"): {
|
||||
"eos_data": [{"logging": {"loggingEnabled": True, "hosts": {"192.168.1.100": {"port": 162, "vrf": "MGMT"}, "192.168.1.103": {"port": 162, "vrf": "Test"}}}}],
|
||||
"inputs": {"hosts": [{"hostname": "192.168.1.101", "vrf": "default"}, {"hostname": "192.168.1.102", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Host: 192.168.1.101 VRF: default - Not configured", "Host: 192.168.1.102 VRF: MGMT - Not configured"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpUser,
|
||||
(VerifySnmpUser, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"usersByVersion": {
|
||||
"v1": {
|
||||
"users": {
|
||||
"Test1": {
|
||||
"groupName": "TestGroup1",
|
||||
},
|
||||
}
|
||||
},
|
||||
"v2c": {
|
||||
"users": {
|
||||
"Test2": {
|
||||
"groupName": "TestGroup2",
|
||||
},
|
||||
}
|
||||
},
|
||||
"v1": {"users": {"Test1": {"groupName": "TestGroup1"}}},
|
||||
"v2c": {"users": {"Test2": {"groupName": "TestGroup2"}}},
|
||||
"v3": {
|
||||
"users": {
|
||||
"Test3": {
|
||||
"groupName": "TestGroup3",
|
||||
"v3Params": {"authType": "SHA-384", "privType": "AES-128"},
|
||||
},
|
||||
"Test3": {"groupName": "TestGroup3", "v3Params": {"authType": "SHA-384", "privType": "AES-128"}},
|
||||
"Test4": {"groupName": "TestGroup3", "v3Params": {"authType": "SHA-512", "privType": "AES-192"}},
|
||||
}
|
||||
},
|
||||
|
@ -413,25 +264,10 @@ DATA: list[dict[str, Any]] = [
|
|||
{"username": "Test4", "group_name": "TestGroup3", "version": "v3", "auth_type": "SHA-512", "priv_type": "AES-192"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifySnmpUser,
|
||||
"eos_data": [
|
||||
{
|
||||
"usersByVersion": {
|
||||
"v3": {
|
||||
"users": {
|
||||
"Test3": {
|
||||
"groupName": "TestGroup3",
|
||||
"v3Params": {"authType": "SHA-384", "privType": "AES-128"},
|
||||
},
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifySnmpUser, "failure-not-configured"): {
|
||||
"eos_data": [{"usersByVersion": {"v3": {"users": {"Test3": {"groupName": "TestGroup3", "v3Params": {"authType": "SHA-384", "privType": "AES-128"}}}}}}],
|
||||
"inputs": {
|
||||
"snmp_users": [
|
||||
{"username": "Test1", "group_name": "TestGroup1", "version": "v1"},
|
||||
|
@ -441,7 +277,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"User: Test1 Group: TestGroup1 Version: v1 - Not found",
|
||||
"User: Test2 Group: TestGroup2 Version: v2c - Not found",
|
||||
|
@ -449,70 +285,30 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-group",
|
||||
"test": VerifySnmpUser,
|
||||
(VerifySnmpUser, "failure-incorrect-group"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"usersByVersion": {
|
||||
"v1": {
|
||||
"users": {
|
||||
"Test1": {
|
||||
"groupName": "TestGroup2",
|
||||
},
|
||||
}
|
||||
},
|
||||
"v2c": {
|
||||
"users": {
|
||||
"Test2": {
|
||||
"groupName": "TestGroup1",
|
||||
},
|
||||
}
|
||||
},
|
||||
"v3": {},
|
||||
}
|
||||
}
|
||||
{"usersByVersion": {"v1": {"users": {"Test1": {"groupName": "TestGroup2"}}}, "v2c": {"users": {"Test2": {"groupName": "TestGroup1"}}}, "v3": {}}}
|
||||
],
|
||||
"inputs": {
|
||||
"snmp_users": [
|
||||
{"username": "Test1", "group_name": "TestGroup1", "version": "v1"},
|
||||
{"username": "Test2", "group_name": "TestGroup2", "version": "v2c"},
|
||||
]
|
||||
"snmp_users": [{"username": "Test1", "group_name": "TestGroup1", "version": "v1"}, {"username": "Test2", "group_name": "TestGroup2", "version": "v2c"}]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"User: Test1 Group: TestGroup1 Version: v1 - Incorrect user group - Actual: TestGroup2",
|
||||
"User: Test2 Group: TestGroup2 Version: v2c - Incorrect user group - Actual: TestGroup1",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-auth-encryption",
|
||||
"test": VerifySnmpUser,
|
||||
(VerifySnmpUser, "failure-incorrect-auth-encryption"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"usersByVersion": {
|
||||
"v1": {
|
||||
"users": {
|
||||
"Test1": {
|
||||
"groupName": "TestGroup1",
|
||||
},
|
||||
}
|
||||
},
|
||||
"v2c": {
|
||||
"users": {
|
||||
"Test2": {
|
||||
"groupName": "TestGroup2",
|
||||
},
|
||||
}
|
||||
},
|
||||
"v1": {"users": {"Test1": {"groupName": "TestGroup1"}}},
|
||||
"v2c": {"users": {"Test2": {"groupName": "TestGroup2"}}},
|
||||
"v3": {
|
||||
"users": {
|
||||
"Test3": {
|
||||
"groupName": "TestGroup3",
|
||||
"v3Params": {"authType": "SHA-512", "privType": "AES-192"},
|
||||
},
|
||||
"Test3": {"groupName": "TestGroup3", "v3Params": {"authType": "SHA-512", "privType": "AES-192"}},
|
||||
"Test4": {"groupName": "TestGroup4", "v3Params": {"authType": "SHA-384", "privType": "AES-128"}},
|
||||
}
|
||||
},
|
||||
|
@ -528,7 +324,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"User: Test3 Group: TestGroup3 Version: v3 - Incorrect authentication type - Expected: SHA-384 Actual: SHA-512",
|
||||
"User: Test3 Group: TestGroup3 Version: v3 - Incorrect privacy type - Expected: AES-128 Actual: AES-192",
|
||||
|
@ -537,9 +333,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"hosts": [
|
||||
|
@ -568,11 +362,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"hostname": "192.168.1.101", "vrf": "MGMT", "notification_type": "trap", "version": "v2c", "udp_port": 162, "community_string": "public"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "failure-not-configured"): {
|
||||
"eos_data": [{"hosts": []}],
|
||||
"inputs": {
|
||||
"notification_hosts": [
|
||||
|
@ -580,11 +372,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"hostname": "192.168.1.101", "vrf": "default", "notification_type": "trap", "version": "v2c", "udp_port": 162, "community_string": "public"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["No SNMP host is configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No SNMP host is configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-details-host-not-found",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "failure-details-host-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"hosts": [
|
||||
|
@ -595,7 +385,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"notificationType": "trap",
|
||||
"protocolVersion": "v3",
|
||||
"v3Params": {"user": "public", "securityLevel": "authNoPriv"},
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
],
|
||||
|
@ -605,11 +395,9 @@ DATA: list[dict[str, Any]] = [
|
|||
{"hostname": "192.168.1.101", "vrf": "default", "notification_type": "trap", "version": "v2c", "udp_port": 162, "community_string": "public"},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["Host: 192.168.1.101 VRF: default Version: v2c - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Host: 192.168.1.101 VRF: default Version: v2c - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-notification-type",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "failure-incorrect-notification-type"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"hosts": [
|
||||
|
@ -639,16 +427,14 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Host: 192.168.1.100 VRF: default - Incorrect notification type - Expected: inform Actual: trap",
|
||||
"Host: 192.168.1.101 VRF: default - Incorrect notification type - Expected: trap Actual: inform",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-udp-port",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "failure-incorrect-udp-port"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"hosts": [
|
||||
|
@ -678,16 +464,14 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Host: 192.168.1.100 VRF: default - Incorrect UDP port - Expected: 162 Actual: 163",
|
||||
"Host: 192.168.1.101 VRF: default - Incorrect UDP port - Expected: 162 Actual: 164",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-community-string-version-v1-v2c",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "failure-incorrect-community-string-version-v1-v2c"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"hosts": [
|
||||
|
@ -717,16 +501,14 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Host: 192.168.1.100 VRF: default Version: v1 - Incorrect community string - Expected: public Actual: private",
|
||||
"Host: 192.168.1.101 VRF: default Version: v2c - Incorrect community string - Expected: public Actual: private",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-user-for-version-v3",
|
||||
"test": VerifySnmpNotificationHost,
|
||||
(VerifySnmpNotificationHost, "failure-incorrect-user-for-version-v3"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"hosts": [
|
||||
|
@ -742,58 +524,35 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {
|
||||
"notification_hosts": [
|
||||
{"hostname": "192.168.1.100", "vrf": "default", "notification_type": "trap", "version": "v3", "udp_port": 162, "user": "public"},
|
||||
]
|
||||
"notification_hosts": [{"hostname": "192.168.1.100", "vrf": "default", "notification_type": "trap", "version": "v3", "udp_port": 162, "user": "public"}]
|
||||
},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Host: 192.168.1.100 VRF: default Version: v3 - Incorrect user - Expected: public Actual: private"],
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["Host: 192.168.1.100 VRF: default Version: v3 - Incorrect user - Expected: public Actual: private"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpSourceInterface,
|
||||
"eos_data": [
|
||||
{
|
||||
"srcIntf": {"sourceInterfaces": {"default": "Ethernet1", "MGMT": "Management0"}},
|
||||
}
|
||||
],
|
||||
(VerifySnmpSourceInterface, "success"): {
|
||||
"eos_data": [{"srcIntf": {"sourceInterfaces": {"default": "Ethernet1", "MGMT": "Management0"}}}],
|
||||
"inputs": {"interfaces": [{"interface": "Ethernet1", "vrf": "default"}, {"interface": "Management0", "vrf": "MGMT"}]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifySnmpSourceInterface,
|
||||
"eos_data": [
|
||||
{
|
||||
"srcIntf": {},
|
||||
}
|
||||
],
|
||||
(VerifySnmpSourceInterface, "failure-not-configured"): {
|
||||
"eos_data": [{"srcIntf": {}}],
|
||||
"inputs": {"interfaces": [{"interface": "Ethernet1", "vrf": "default"}, {"interface": "Management0", "vrf": "MGMT"}]},
|
||||
"expected": {"result": "failure", "messages": ["SNMP source interface(s) not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["SNMP source interface(s) not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-interfaces",
|
||||
"test": VerifySnmpSourceInterface,
|
||||
"eos_data": [
|
||||
{
|
||||
"srcIntf": {
|
||||
"sourceInterfaces": {
|
||||
"default": "Management0",
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
(VerifySnmpSourceInterface, "failure-incorrect-interfaces"): {
|
||||
"eos_data": [{"srcIntf": {"sourceInterfaces": {"default": "Management0"}}}],
|
||||
"inputs": {"interfaces": [{"interface": "Ethernet1", "vrf": "default"}, {"interface": "Management0", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Source Interface: Ethernet1 VRF: default - Incorrect source interface - Actual: Management0",
|
||||
"Source Interface: Management0 VRF: MGMT - Not configured",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpGroup,
|
||||
(VerifySnmpGroup, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"groups": {
|
||||
|
@ -853,11 +612,9 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-view",
|
||||
"test": VerifySnmpGroup,
|
||||
(VerifySnmpGroup, "failure-incorrect-view"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"groups": {
|
||||
|
@ -918,7 +675,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Group: Group1 Version: v1 - Incorrect Read view - Expected: group_read_1 Actual: group_read",
|
||||
"Group: Group1 Version: v1 - Incorrect Write view - Expected: group_write_1 Actual: group_write",
|
||||
|
@ -931,9 +688,7 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-view-config-not-found",
|
||||
"test": VerifySnmpGroup,
|
||||
(VerifySnmpGroup, "failure-view-config-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"groups": {
|
||||
|
@ -983,17 +738,11 @@ DATA: list[dict[str, Any]] = [
|
|||
"snmp_groups": [
|
||||
{"group_name": "Group1", "version": "v1", "read_view": "group_read", "write_view": "group_write", "notify_view": "group_notify"},
|
||||
{"group_name": "Group2", "version": "v2c", "read_view": "group_read", "write_view": "group_write", "notify_view": "group_notify"},
|
||||
{
|
||||
"group_name": "Group3",
|
||||
"version": "v3",
|
||||
"write_view": "group_write",
|
||||
"notify_view": "group_notify",
|
||||
"authentication": "priv",
|
||||
},
|
||||
{"group_name": "Group3", "version": "v3", "write_view": "group_write", "notify_view": "group_notify", "authentication": "priv"},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Group: Group1 Version: v1 Read View: group_read - Not configured",
|
||||
"Group: Group1 Version: v1 Write View: group_write - Not configured",
|
||||
|
@ -1006,18 +755,8 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-group-version-not-configured",
|
||||
"test": VerifySnmpGroup,
|
||||
"eos_data": [
|
||||
{
|
||||
"groups": {
|
||||
"Group1": {"versions": {"v1": {}}},
|
||||
"Group2": {"versions": {"v2c": {}}},
|
||||
"Group3": {"versions": {"v3": {}}},
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifySnmpGroup, "failure-group-version-not-configured"): {
|
||||
"eos_data": [{"groups": {"Group1": {"versions": {"v1": {}}}, "Group2": {"versions": {"v2c": {}}}, "Group3": {"versions": {"v3": {}}}}}],
|
||||
"inputs": {
|
||||
"snmp_groups": [
|
||||
{"group_name": "Group1", "version": "v1", "read_view": "group_read_1", "write_view": "group_write_1"},
|
||||
|
@ -1033,17 +772,11 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Group: Group1 Version: v1 - Not configured",
|
||||
"Group: Group2 Version: v2c - Not configured",
|
||||
"Group: Group3 Version: v3 - Not configured",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Group: Group1 Version: v1 - Not configured", "Group: Group2 Version: v2c - Not configured", "Group: Group3 Version: v3 - Not configured"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-v3-auth-model",
|
||||
"test": VerifySnmpGroup,
|
||||
(VerifySnmpGroup, "failure-incorrect-v3-auth-model"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"groups": {
|
||||
|
@ -1059,7 +792,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"notifyViewConfig": True,
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -1072,42 +805,20 @@ DATA: list[dict[str, Any]] = [
|
|||
"write_view": "group_write",
|
||||
"notify_view": "group_notify",
|
||||
"authentication": "priv",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Group: Group3 Version: v3 - Incorrect security model - Expected: v3Priv Actual: v3Auth",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Group: Group3 Version: v3 - Incorrect security model - Expected: v3Priv Actual: v3Auth"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-view-not-configured",
|
||||
"test": VerifySnmpGroup,
|
||||
(VerifySnmpGroup, "failure-view-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"groups": {
|
||||
"Group3": {"versions": {"v3": {"secModel": "v3NoAuth", "readView": "group_read", "readViewConfig": True, "writeView": "", "notifyView": ""}}},
|
||||
"Group3": {"versions": {"v3": {"secModel": "v3NoAuth", "readView": "group_read", "readViewConfig": True, "writeView": "", "notifyView": ""}}}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"snmp_groups": [
|
||||
{
|
||||
"group_name": "Group3",
|
||||
"version": "v3",
|
||||
"read_view": "group_read",
|
||||
"write_view": "group_write",
|
||||
"authentication": "noauth",
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Group: Group3 Version: v3 View: write - Not configured",
|
||||
],
|
||||
},
|
||||
"inputs": {"snmp_groups": [{"group_name": "Group3", "version": "v3", "read_view": "group_read", "write_view": "group_write", "authentication": "noauth"}]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Group: Group3 Version: v3 View: write - Not configured"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,41 +5,29 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.software import VerifyEOSExtensions, VerifyEOSVersion, VerifyTerminAttrVersion
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEOSVersion,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "vEOS-lab",
|
||||
"internalVersion": "4.27.0F-24305004.4270F",
|
||||
"version": "4.27.0F",
|
||||
},
|
||||
],
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyEOSVersion, "success"): {
|
||||
"eos_data": [{"modelName": "vEOS-lab", "internalVersion": "4.27.0F-24305004.4270F", "version": "4.27.0F"}],
|
||||
"inputs": {"versions": ["4.27.0F", "4.28.0F"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEOSVersion,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "vEOS-lab",
|
||||
"internalVersion": "4.27.0F-24305004.4270F",
|
||||
"version": "4.27.0F",
|
||||
},
|
||||
],
|
||||
(VerifyEOSVersion, "failure"): {
|
||||
"eos_data": [{"modelName": "vEOS-lab", "internalVersion": "4.27.0F-24305004.4270F", "version": "4.27.0F"}],
|
||||
"inputs": {"versions": ["4.27.1F"]},
|
||||
"expected": {"result": "failure", "messages": ["EOS version mismatch - Actual: 4.27.0F not in Expected: 4.27.1F"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["EOS version mismatch - Actual: 4.27.0F not in Expected: 4.27.1F"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTerminAttrVersion,
|
||||
(VerifyTerminAttrVersion, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
|
@ -49,18 +37,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
"switchType": "fixedSystem",
|
||||
"packages": {
|
||||
"TerminAttr-core": {"release": "1", "version": "v1.17.0"},
|
||||
},
|
||||
"packages": {"TerminAttr-core": {"release": "1", "version": "v1.17.0"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"versions": ["v1.17.0", "v1.18.1"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTerminAttrVersion,
|
||||
(VerifyTerminAttrVersion, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
|
@ -70,28 +54,18 @@ DATA: list[dict[str, Any]] = [
|
|||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
"switchType": "fixedSystem",
|
||||
"packages": {
|
||||
"TerminAttr-core": {"release": "1", "version": "v1.17.0"},
|
||||
},
|
||||
"packages": {"TerminAttr-core": {"release": "1", "version": "v1.17.0"}},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"versions": ["v1.17.1", "v1.18.1"]},
|
||||
"expected": {"result": "failure", "messages": ["TerminAttr version mismatch - Actual: v1.17.0 not in Expected: v1.17.1, v1.18.1"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["TerminAttr version mismatch - Actual: v1.17.0 not in Expected: v1.17.1, v1.18.1"]},
|
||||
},
|
||||
{
|
||||
"name": "success-no-extensions",
|
||||
"test": VerifyEOSExtensions,
|
||||
"eos_data": [
|
||||
{"extensions": {}, "extensionStoredDir": "flash:", "warnings": ["No extensions are available"]},
|
||||
{"extensions": []},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
(VerifyEOSExtensions, "success-no-extensions"): {
|
||||
"eos_data": [{"extensions": {}, "extensionStoredDir": "flash:", "warnings": ["No extensions are available"]}, {"extensions": []}],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-extensions",
|
||||
"test": VerifyEOSExtensions,
|
||||
(VerifyEOSExtensions, "success-extensions"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"extensions": {
|
||||
|
@ -110,17 +84,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"description": "An extension for Arista Cloud Connect gateway",
|
||||
"affectedAgents": [],
|
||||
"agentsToRestart": [],
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{"extensions": ["AristaCloudGateway-1.0.1-1.swix"]},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEOSExtensions,
|
||||
(VerifyEOSExtensions, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"extensions": {
|
||||
|
@ -139,17 +110,14 @@ DATA: list[dict[str, Any]] = [
|
|||
"description": "An extension for Arista Cloud Connect gateway",
|
||||
"affectedAgents": [],
|
||||
"agentsToRestart": [],
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{"extensions": []},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix Configured: Not found"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix Configured: Not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-multiple-extensions",
|
||||
"test": VerifyEOSExtensions,
|
||||
(VerifyEOSExtensions, "failure-multiple-extensions"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"extensions": {
|
||||
|
@ -190,12 +158,11 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
{"extensions": ["AristaCloudGateway-1.0.1-1.swix", "EOS-4.33.0F-NDRSensor.swix"]},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"EOS extensions mismatch - Installed: AristaCloudGateway-1.0.1-1.swix Configured: AristaCloudGateway-1.0.1-1.swix, EOS-4.33.0F-NDRSensor.swix"
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.stp import (
|
||||
VerifySTPBlockedPorts,
|
||||
VerifySTPCounters,
|
||||
|
@ -18,117 +21,89 @@ from anta.tests.stp import (
|
|||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPMode,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifySTPMode, "success"): {
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {"10": {"spanningTreeVlanInstance": {"protocol": "rstp"}}}},
|
||||
{"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "rstp"}}}},
|
||||
],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-instances",
|
||||
"test": VerifySTPMode,
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {}},
|
||||
{"spanningTreeVlanInstances": {}},
|
||||
],
|
||||
(VerifySTPMode, "failure-no-instances"): {
|
||||
"eos_data": [{"spanningTreeVlanInstances": {}}, {"spanningTreeVlanInstances": {}}],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["VLAN 10 STP mode: rstp - Not configured", "VLAN 20 STP mode: rstp - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VLAN 10 STP mode: rstp - Not configured", "VLAN 20 STP mode: rstp - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-mode",
|
||||
"test": VerifySTPMode,
|
||||
(VerifySTPMode, "failure-wrong-mode"): {
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {"10": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}},
|
||||
{"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}},
|
||||
],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["VLAN 10 - Incorrect STP mode - Expected: rstp Actual: mstp", "VLAN 20 - Incorrect STP mode - Expected: rstp Actual: mstp"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-both",
|
||||
"test": VerifySTPMode,
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {}},
|
||||
{"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}},
|
||||
],
|
||||
(VerifySTPMode, "failure-both"): {
|
||||
"eos_data": [{"spanningTreeVlanInstances": {}}, {"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}}],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["VLAN 10 STP mode: rstp - Not configured", "VLAN 20 - Incorrect STP mode - Expected: rstp Actual: mstp"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPBlockedPorts,
|
||||
"eos_data": [{"spanningTreeInstances": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySTPBlockedPorts,
|
||||
(VerifySTPBlockedPorts, "success"): {"eos_data": [{"spanningTreeInstances": {}}], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifySTPBlockedPorts, "failure"): {
|
||||
"eos_data": [{"spanningTreeInstances": {"MST0": {"spanningTreeBlockedPorts": ["Ethernet10"]}, "MST10": {"spanningTreeBlockedPorts": ["Ethernet10"]}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["STP Instance: MST0 - Blocked ports - Ethernet10", "STP Instance: MST10 - Blocked ports - Ethernet10"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["STP Instance: MST0 - Blocked ports - Ethernet10", "STP Instance: MST10 - Blocked ports - Ethernet10"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPCounters,
|
||||
(VerifySTPCounters, "success"): {
|
||||
"eos_data": [{"interfaces": {"Ethernet10": {"bpduSent": 99, "bpduReceived": 0, "bpduTaggedError": 0, "bpduOtherError": 0, "bpduRateLimitCount": 0}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-bpdu-tagged-error-mismatch",
|
||||
"test": VerifySTPCounters,
|
||||
(VerifySTPCounters, "failure-bpdu-tagged-error-mismatch"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"interfaces": {
|
||||
"Ethernet10": {"bpduSent": 201, "bpduReceived": 0, "bpduTaggedError": 3, "bpduOtherError": 0, "bpduRateLimitCount": 0},
|
||||
"Ethernet11": {"bpduSent": 99, "bpduReceived": 0, "bpduTaggedError": 3, "bpduOtherError": 0, "bpduRateLimitCount": 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Interface Ethernet10 - STP BPDU packet tagged errors count mismatch - Expected: 0 Actual: 3",
|
||||
"Interface Ethernet11 - STP BPDU packet tagged errors count mismatch - Expected: 0 Actual: 3",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-bpdu-other-error-mismatch",
|
||||
"test": VerifySTPCounters,
|
||||
(VerifySTPCounters, "failure-bpdu-other-error-mismatch"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"interfaces": {
|
||||
"Ethernet10": {"bpduSent": 201, "bpduReceived": 0, "bpduTaggedError": 0, "bpduOtherError": 3, "bpduRateLimitCount": 0},
|
||||
"Ethernet11": {"bpduSent": 99, "bpduReceived": 0, "bpduTaggedError": 0, "bpduOtherError": 6, "bpduRateLimitCount": 0},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Interface Ethernet10 - STP BPDU packet other errors count mismatch - Expected: 0 Actual: 3",
|
||||
"Interface Ethernet11 - STP BPDU packet other errors count mismatch - Expected: 0 Actual: 6",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPForwardingPorts,
|
||||
(VerifySTPForwardingPorts, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -140,11 +115,9 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-vlan-not-in-topology", # Should it succeed really ? TODO - this output should be impossible
|
||||
"test": VerifySTPForwardingPorts,
|
||||
(VerifySTPForwardingPorts, "success-vlan-not-in-topology"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -156,18 +129,14 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-instances",
|
||||
"test": VerifySTPForwardingPorts,
|
||||
(VerifySTPForwardingPorts, "failure-no-instances"): {
|
||||
"eos_data": [{"unmappedVlans": [], "topologies": {}}, {"unmappedVlans": [], "topologies": {}}],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["VLAN 10 - STP instance is not configured", "VLAN 20 - STP instance is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VLAN 10 - STP instance is not configured", "VLAN 20 - STP instance is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySTPForwardingPorts,
|
||||
(VerifySTPForwardingPorts, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -180,16 +149,14 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"VLAN 10 Interface: Ethernet10 - Invalid state - Expected: forwarding Actual: discarding",
|
||||
"VLAN 20 Interface: Ethernet10 - Invalid state - Expected: forwarding Actual: discarding",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success-specific-instances",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "success-specific-instances"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -201,7 +168,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
"VL20": {
|
||||
"rootBridge": {
|
||||
|
@ -211,7 +178,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
"VL30": {
|
||||
"rootBridge": {
|
||||
|
@ -221,17 +188,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-all-instances",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "success-all-instances"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -243,7 +208,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
"VL20": {
|
||||
"rootBridge": {
|
||||
|
@ -253,7 +218,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
"VL30": {
|
||||
"rootBridge": {
|
||||
|
@ -263,17 +228,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-MST",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "success-MST"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -285,17 +248,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 16384, "instances": [0]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-input-instance-none",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "success-input-instance-none"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -307,17 +268,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 16384},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-instances",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "failure-no-instances"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -329,24 +288,20 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [0]},
|
||||
"expected": {"result": "failure", "messages": ["STP Instance: WRONG0 - Unsupported STP instance type"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["STP Instance: WRONG0 - Unsupported STP instance type"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-instance-type",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "failure-wrong-instance-type"): {
|
||||
"eos_data": [{"instances": {}}],
|
||||
"inputs": {"priority": 32768, "instances": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["No STP instances configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No STP instances configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-instance-not-found",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "failure-instance-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -358,17 +313,15 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [11, 20]},
|
||||
"expected": {"result": "failure", "messages": ["Instance: VL11 - Not configured", "Instance: VL20 - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Instance: VL11 - Not configured", "Instance: VL20 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-priority",
|
||||
"test": VerifySTPRootPriority,
|
||||
(VerifySTPRootPriority, "failure-wrong-priority"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
|
@ -380,7 +333,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
"VL20": {
|
||||
"rootBridge": {
|
||||
|
@ -390,7 +343,7 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
"VL30": {
|
||||
"rootBridge": {
|
||||
|
@ -400,23 +353,21 @@ DATA: list[dict[str, Any]] = [
|
|||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [10, 20, 30]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"STP Instance: VL20 - Incorrect root priority - Expected: 32768 Actual: 8196",
|
||||
"STP Instance: VL30 - Incorrect root priority - Expected: 32768 Actual: 8196",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success-mstp",
|
||||
"test": VerifyStpTopologyChanges,
|
||||
(VerifyStpTopologyChanges, "success-mstp"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -434,14 +385,12 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"threshold": 10},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-rstp",
|
||||
"test": VerifyStpTopologyChanges,
|
||||
(VerifyStpTopologyChanges, "success-rstp"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -459,23 +408,19 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"threshold": 10},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-rapid-pvst",
|
||||
"test": VerifyStpTopologyChanges,
|
||||
(VerifyStpTopologyChanges, "success-rapid-pvst"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {
|
||||
"NoStp": {
|
||||
"vlans": [4094, 4093, 1006],
|
||||
"interfaces": {
|
||||
"PeerEthernet2": {"state": "forwarding", "numChanges": 1, "lastChange": 1727151356.1330667},
|
||||
},
|
||||
"interfaces": {"PeerEthernet2": {"state": "forwarding", "numChanges": 1, "lastChange": 1727151356.1330667}},
|
||||
},
|
||||
"Vl1": {"vlans": [1], "interfaces": {"Port-Channel5": {"state": "forwarding", "numChanges": 1, "lastChange": 1727326710.0615358}}},
|
||||
"Vl10": {
|
||||
|
@ -527,14 +472,12 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"threshold": 10},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-unstable-topology",
|
||||
"test": VerifyStpTopologyChanges,
|
||||
(VerifyStpTopologyChanges, "failure-unstable-topology"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -544,22 +487,20 @@ DATA: list[dict[str, Any]] = [
|
|||
"Cpu": {"state": "forwarding", "numChanges": 15, "lastChange": 1723990624.735365},
|
||||
"Port-Channel5": {"state": "forwarding", "numChanges": 15, "lastChange": 1723990624.7353542},
|
||||
}
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"threshold": 10},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Topology: Cist Interface: Cpu - Number of changes not within the threshold - Expected: 10 Actual: 15",
|
||||
"Topology: Cist Interface: Port-Channel5 - Number of changes not within the threshold - Expected: 10 Actual: 15",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-topologies-not-configured",
|
||||
"test": VerifyStpTopologyChanges,
|
||||
(VerifyStpTopologyChanges, "failure-topologies-not-configured"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
|
@ -571,28 +512,22 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"threshold": 10},
|
||||
"expected": {"result": "failure", "messages": ["STP is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["STP is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPDisabledVlans,
|
||||
(VerifySTPDisabledVlans, "success"): {
|
||||
"eos_data": [{"spanningTreeVlanInstances": {"1": {"spanningTreeVlanInstance": {"protocol": "mstp", "bridge": {"priority": 32768}}}, "6": {}, "4094": {}}}],
|
||||
"inputs": {"vlans": ["6", "4094"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-stp-not-configured",
|
||||
"test": VerifySTPDisabledVlans,
|
||||
(VerifySTPDisabledVlans, "failure-stp-not-configured"): {
|
||||
"eos_data": [{"spanningTreeVlanInstances": {}}],
|
||||
"inputs": {"vlans": ["6", "4094"]},
|
||||
"expected": {"result": "failure", "messages": ["STP is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["STP is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vlans-not-found",
|
||||
"test": VerifySTPDisabledVlans,
|
||||
(VerifySTPDisabledVlans, "failure-vlans-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"spanningTreeVlanInstances": {
|
||||
|
@ -603,11 +538,9 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {"vlans": ["16", "4093"]},
|
||||
"expected": {"result": "failure", "messages": ["VLAN: 16 - Not configured", "VLAN: 4093 - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VLAN: 16 - Not configured", "VLAN: 4093 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vlans-enabled",
|
||||
"test": VerifySTPDisabledVlans,
|
||||
(VerifySTPDisabledVlans, "failure-vlans-enabled"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"spanningTreeVlanInstances": {
|
||||
|
@ -618,6 +551,6 @@ DATA: list[dict[str, Any]] = [
|
|||
}
|
||||
],
|
||||
"inputs": {"vlans": ["6", "4094"]},
|
||||
"expected": {"result": "failure", "messages": ["VLAN: 6 - STP is enabled", "VLAN: 4094 - STP is enabled"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VLAN: 6 - STP is enabled", "VLAN: 4094 - STP is enabled"]},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,48 +5,24 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.stun import VerifyStunClientTranslation, VerifyStunServer
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyStunClientTranslation,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyStunClientTranslation, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"bindings": {
|
||||
"000000010a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "100.64.3.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.64.3.2", "port": 6006},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"bindings": {
|
||||
"000000040a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "172.18.3.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.18.3.2", "port": 6006},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"bindings": {
|
||||
"000000040a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "172.18.4.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.18.4.2", "port": 6006},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"bindings": {
|
||||
"000000040a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "172.18.6.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.18.6.2", "port": 6006},
|
||||
}
|
||||
}
|
||||
},
|
||||
{"bindings": {"000000010a64ff0100000000": {"sourceAddress": {"ip": "100.64.3.2", "port": 4500}, "publicAddress": {"ip": "192.64.3.2", "port": 6006}}}},
|
||||
{"bindings": {"000000040a64ff0100000000": {"sourceAddress": {"ip": "172.18.3.2", "port": 4500}, "publicAddress": {"ip": "192.18.3.2", "port": 6006}}}},
|
||||
{"bindings": {"000000040a64ff0100000000": {"sourceAddress": {"ip": "172.18.4.2", "port": 4500}, "publicAddress": {"ip": "192.18.4.2", "port": 6006}}}},
|
||||
{"bindings": {"000000040a64ff0100000000": {"sourceAddress": {"ip": "172.18.6.2", "port": 4500}, "publicAddress": {"ip": "192.18.6.2", "port": 6006}}}},
|
||||
],
|
||||
"inputs": {
|
||||
"stun_clients": [
|
||||
|
@ -56,28 +32,12 @@ DATA: list[dict[str, Any]] = [
|
|||
{"source_address": "172.18.6.2", "source_port": 4500, "public_port": 6006},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-public-ip",
|
||||
"test": VerifyStunClientTranslation,
|
||||
(VerifyStunClientTranslation, "failure-incorrect-public-ip"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"bindings": {
|
||||
"000000010a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "100.64.3.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.64.3.2", "port": 6006},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"bindings": {
|
||||
"000000040a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "172.18.3.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.18.3.2", "port": 6006},
|
||||
}
|
||||
}
|
||||
},
|
||||
{"bindings": {"000000010a64ff0100000000": {"sourceAddress": {"ip": "100.64.3.2", "port": 4500}, "publicAddress": {"ip": "192.64.3.2", "port": 6006}}}},
|
||||
{"bindings": {"000000040a64ff0100000000": {"sourceAddress": {"ip": "172.18.3.2", "port": 4500}, "publicAddress": {"ip": "192.18.3.2", "port": 6006}}}},
|
||||
],
|
||||
"inputs": {
|
||||
"stun_clients": [
|
||||
|
@ -86,20 +46,15 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Client 100.64.3.2 Port: 4500 - Incorrect public-facing address - Expected: 192.164.3.2 Actual: 192.64.3.2",
|
||||
"Client 172.18.3.2 Port: 4500 - Incorrect public-facing address - Expected: 192.118.3.2 Actual: 192.18.3.2",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-client",
|
||||
"test": VerifyStunClientTranslation,
|
||||
"eos_data": [
|
||||
{"bindings": {}},
|
||||
{"bindings": {}},
|
||||
],
|
||||
(VerifyStunClientTranslation, "failure-no-client"): {
|
||||
"eos_data": [{"bindings": {}}, {"bindings": {}}],
|
||||
"inputs": {
|
||||
"stun_clients": [
|
||||
{"source_address": "100.64.3.2", "public_address": "192.164.3.2", "source_port": 4500, "public_port": 6006},
|
||||
|
@ -107,23 +62,14 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Client 100.64.3.2 Port: 4500 - STUN client translation not found", "Client 172.18.3.2 Port: 4500 - STUN client translation not found"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-public-port",
|
||||
"test": VerifyStunClientTranslation,
|
||||
(VerifyStunClientTranslation, "failure-incorrect-public-port"): {
|
||||
"eos_data": [
|
||||
{"bindings": {}},
|
||||
{
|
||||
"bindings": {
|
||||
"000000040a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "172.18.3.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.18.3.2", "port": 4800},
|
||||
}
|
||||
}
|
||||
},
|
||||
{"bindings": {"000000040a64ff0100000000": {"sourceAddress": {"ip": "172.18.3.2", "port": 4500}, "publicAddress": {"ip": "192.18.3.2", "port": 4800}}}},
|
||||
],
|
||||
"inputs": {
|
||||
"stun_clients": [
|
||||
|
@ -132,7 +78,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Client 100.64.3.2 Port: 4500 - STUN client translation not found",
|
||||
"Client 172.18.3.2 Port: 4500 - Incorrect public-facing address - Expected: 192.118.3.2 Actual: 192.18.3.2",
|
||||
|
@ -140,19 +86,10 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-type",
|
||||
"test": VerifyStunClientTranslation,
|
||||
(VerifyStunClientTranslation, "failure-all-type"): {
|
||||
"eos_data": [
|
||||
{"bindings": {}},
|
||||
{
|
||||
"bindings": {
|
||||
"000000040a64ff0100000000": {
|
||||
"sourceAddress": {"ip": "172.18.3.2", "port": 4500},
|
||||
"publicAddress": {"ip": "192.18.3.2", "port": 4800},
|
||||
}
|
||||
}
|
||||
},
|
||||
{"bindings": {"000000040a64ff0100000000": {"sourceAddress": {"ip": "172.18.3.2", "port": 4500}, "publicAddress": {"ip": "192.18.3.2", "port": 4800}}}},
|
||||
],
|
||||
"inputs": {
|
||||
"stun_clients": [
|
||||
|
@ -161,7 +98,7 @@ DATA: list[dict[str, Any]] = [
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Client 100.64.3.2 Port: 4500 - STUN client translation not found",
|
||||
"Client 172.18.4.2 Port: 4800 - Incorrect public-facing address - Expected: 192.118.3.2 Actual: 192.18.3.2",
|
||||
|
@ -169,61 +106,20 @@ DATA: list[dict[str, Any]] = [
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyStunServer,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"pid": 1895,
|
||||
}
|
||||
],
|
||||
(VerifyStunServer, "success"): {"eos_data": [{"enabled": True, "pid": 1895}], "inputs": {}, "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyStunServer, "failure-disabled"): {
|
||||
"eos_data": [{"enabled": False, "pid": 1895}],
|
||||
"inputs": {},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["STUN server status is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifyStunServer,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": False,
|
||||
"pid": 1895,
|
||||
}
|
||||
],
|
||||
(VerifyStunServer, "failure-not-running"): {
|
||||
"eos_data": [{"enabled": True, "pid": 0}],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["STUN server status is disabled"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["STUN server is not running"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-running",
|
||||
"test": VerifyStunServer,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"pid": 0,
|
||||
}
|
||||
],
|
||||
(VerifyStunServer, "failure-not-running-disabled"): {
|
||||
"eos_data": [{"enabled": False, "pid": 0}],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["STUN server is not running"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["STUN server status is disabled and not running"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-running-disabled",
|
||||
"test": VerifyStunServer,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": False,
|
||||
"pid": 0,
|
||||
}
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["STUN server status is disabled and not running"],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,8 +5,11 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.system import (
|
||||
VerifyAgentLogs,
|
||||
VerifyCoredump,
|
||||
|
@ -21,127 +24,137 @@ from anta.tests.system import (
|
|||
)
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyUptime,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyUptime, "success"): {
|
||||
"eos_data": [{"upTime": 1186689.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
|
||||
"inputs": {"minimum": 666},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyUptime,
|
||||
(VerifyUptime, "failure"): {
|
||||
"eos_data": [{"upTime": 665.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
|
||||
"inputs": {"minimum": 666},
|
||||
"expected": {"result": "failure", "messages": ["Device uptime is incorrect - Expected: 666s Actual: 665.15s"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device uptime is incorrect - Expected: 666s Actual: 665.15s"]},
|
||||
},
|
||||
{
|
||||
"name": "success-no-reload",
|
||||
"test": VerifyReloadCause,
|
||||
(VerifyReloadCause, "success-no-reload"): {
|
||||
"eos_data": [{"kernelCrashData": [], "resetCauses": [], "full": False}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-valid-cause",
|
||||
"test": VerifyReloadCause,
|
||||
(VerifyReloadCause, "success-valid-cause-user"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"resetCauses": [
|
||||
{"recommendedAction": "No action necessary.", "description": "Reload requested by the user.", "timestamp": 1683186892.0, "debugInfoIsDir": False}
|
||||
],
|
||||
"full": False,
|
||||
}
|
||||
],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyReloadCause, "success-valid-reload-cause-ztp"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"resetCauses": [
|
||||
{
|
||||
"description": "System reloaded due to Zero Touch Provisioning",
|
||||
"timestamp": 1729856740.0,
|
||||
"recommendedAction": "No action necessary.",
|
||||
"description": "Reload requested by the user.",
|
||||
"timestamp": 1683186892.0,
|
||||
"debugInfoIsDir": False,
|
||||
},
|
||||
}
|
||||
],
|
||||
"full": False,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"inputs": {"allowed_causes": ["ZTP"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyReloadCause,
|
||||
# The failure cause is made up
|
||||
(VerifyReloadCause, "success-valid-reload-cause-fpga"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"resetCauses": [
|
||||
{"recommendedAction": "No action necessary.", "description": "Reload after crash.", "timestamp": 1683186892.0, "debugInfoIsDir": False},
|
||||
{
|
||||
"description": "Reload requested after FPGA upgrade",
|
||||
"timestamp": 1729856740.0,
|
||||
"recommendedAction": "No action necessary.",
|
||||
"debugInfoIsDir": False,
|
||||
}
|
||||
],
|
||||
"full": False,
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Reload cause is: Reload after crash."]},
|
||||
"inputs": {"allowed_causes": ["fpga"]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-without-minidump",
|
||||
"test": VerifyCoredump,
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": []}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-with-minidump",
|
||||
"test": VerifyCoredump,
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": ["minidump"]}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-without-minidump",
|
||||
"test": VerifyCoredump,
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": ["core.2344.1584483862.Mlag.gz", "core.23101.1584483867.Mlag.gz"]}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Core dump(s) have been found: core.2344.1584483862.Mlag.gz, core.23101.1584483867.Mlag.gz"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-with-minidump",
|
||||
"test": VerifyCoredump,
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": ["minidump", "core.2344.1584483862.Mlag.gz", "core.23101.1584483867.Mlag.gz"]}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Core dump(s) have been found: core.2344.1584483862.Mlag.gz, core.23101.1584483867.Mlag.gz"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAgentLogs,
|
||||
"eos_data": [""],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyAgentLogs,
|
||||
(VerifyReloadCause, "failure-invalid-reload-cause"): {
|
||||
"eos_data": [
|
||||
"""===> /var/log/agents/Test-666 Thu May 4 09:57:02 2023 <===
|
||||
CLI Exception: Exception
|
||||
CLI Exception: Backtrace
|
||||
===> /var/log/agents/Aaa-855 Fri Jul 7 15:07:00 2023 <===
|
||||
===== Output from /usr/bin/Aaa [] (PID=855) started Jul 7 15:06:11.606414 ===
|
||||
EntityManager::doBackoff waiting for remote sysdb version ....ok
|
||||
|
||||
===> /var/log/agents/Acl-830 Fri Jul 7 15:07:00 2023 <===
|
||||
===== Output from /usr/bin/Acl [] (PID=830) started Jul 7 15:06:10.871700 ===
|
||||
EntityManager::doBackoff waiting for remote sysdb version ...................ok
|
||||
""",
|
||||
{
|
||||
"resetCauses": [
|
||||
{
|
||||
"description": "Reload requested after FPGA upgrade",
|
||||
"timestamp": 1729856740.0,
|
||||
"recommendedAction": "No action necessary.",
|
||||
"debugInfoIsDir": False,
|
||||
}
|
||||
],
|
||||
"full": False,
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"inputs": {"allowed_causes": ["ZTP"]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Invalid reload cause - Expected: 'System reloaded due to Zero Touch Provisioning' Actual: 'Reload requested after FPGA upgrade'"],
|
||||
},
|
||||
},
|
||||
(VerifyReloadCause, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"resetCauses": [
|
||||
{"recommendedAction": "No action necessary.", "description": "Reload after crash.", "timestamp": 1683186892.0, "debugInfoIsDir": False}
|
||||
],
|
||||
"full": False,
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Invalid reload cause - Expected: 'Reload requested by the user.', 'Reload requested after FPGA upgrade' Actual: 'Reload after crash.'"],
|
||||
},
|
||||
},
|
||||
(VerifyCoredump, "success-without-minidump"): {
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": []}],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyCoredump, "success-with-minidump"): {
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": ["minidump"]}],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyCoredump, "failure-without-minidump"): {
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": ["core.2344.1584483862.Mlag.gz", "core.23101.1584483867.Mlag.gz"]}],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Core dump(s) have been found: core.2344.1584483862.Mlag.gz, core.23101.1584483867.Mlag.gz"]},
|
||||
},
|
||||
(VerifyCoredump, "failure-with-minidump"): {
|
||||
"eos_data": [{"mode": "compressedDeferred", "coreFiles": ["minidump", "core.2344.1584483862.Mlag.gz", "core.23101.1584483867.Mlag.gz"]}],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Core dump(s) have been found: core.2344.1584483862.Mlag.gz, core.23101.1584483867.Mlag.gz"]},
|
||||
},
|
||||
(VerifyAgentLogs, "success"): {"eos_data": [""], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyAgentLogs, "failure"): {
|
||||
"eos_data": [
|
||||
"===> /var/log/agents/Test-666 Thu May 4 09:57:02 2023 <===\nCLI Exception: Exception\nCLI Exception: Backtrace\n===> /var/log/agents/Aaa-855"
|
||||
" Fri Jul 7 15:07:00 2023 <===\n===== Output from /usr/bin/Aaa [] (PID=855) started Jul 7 15:06:11.606414 ===\n"
|
||||
"EntityManager::doBackoff waiting for remote sysdb version ....ok\n\n===> /var/log/agents/Acl-830"
|
||||
" Fri Jul 7 15:07:00 2023 <===\n===== Output from /usr/bin/Acl [] (PID=830) started Jul 7 15:06:10.871700 ===\n"
|
||||
"EntityManager::doBackoff waiting for remote sysdb version ...................ok\n"
|
||||
],
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Device has reported agent crashes:\n"
|
||||
" * /var/log/agents/Test-666 Thu May 4 09:57:02 2023\n"
|
||||
" * /var/log/agents/Aaa-855 Fri Jul 7 15:07:00 2023\n"
|
||||
" * /var/log/agents/Acl-830 Fri Jul 7 15:07:00 2023",
|
||||
"Device has reported agent crashes:\n * /var/log/agents/Test-666 Thu May 4 09:57:02 2023\n"
|
||||
" * /var/log/agents/Aaa-855 Fri Jul 7 15:07:00 2023\n * /var/log/agents/Acl-830 Fri Jul 7 15:07:00 2023"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyCPUUtilization,
|
||||
(VerifyCPUUtilization, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"cpuInfo": {"%Cpu(s)": {"idle": 88.2, "stolen": 0.0, "user": 5.9, "swIrq": 0.0, "ioWait": 0.0, "system": 0.0, "hwIrq": 5.9, "nice": 0.0}},
|
||||
|
@ -159,16 +172,13 @@ EntityManager::doBackoff waiting for remote sysdb version ...................ok
|
|||
"activeTime": 360,
|
||||
"virtMem": "6644",
|
||||
"sharedMem": "3996",
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyCPUUtilization,
|
||||
(VerifyCPUUtilization, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"cpuInfo": {"%Cpu(s)": {"idle": 24.8, "stolen": 0.0, "user": 5.9, "swIrq": 0.0, "ioWait": 0.0, "system": 0.0, "hwIrq": 5.9, "nice": 0.0}},
|
||||
|
@ -186,122 +196,56 @@ EntityManager::doBackoff waiting for remote sysdb version ...................ok
|
|||
"activeTime": 360,
|
||||
"virtMem": "6644",
|
||||
"sharedMem": "3996",
|
||||
},
|
||||
}
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device has reported a high CPU utilization - Expected: < 75% Actual: 75.2%"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device has reported a high CPU utilization - Expected: < 75% Actual: 75.2%"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMemoryUtilization,
|
||||
(VerifyMemoryUtilization, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"uptime": 1994.67,
|
||||
"modelName": "vEOS-lab",
|
||||
"internalVersion": "4.27.3F-26379303.4273F",
|
||||
"memTotal": 2004568,
|
||||
"memFree": 879004,
|
||||
"version": "4.27.3F",
|
||||
},
|
||||
{"uptime": 1994.67, "modelName": "vEOS-lab", "internalVersion": "4.27.3F-26379303.4273F", "memTotal": 2004568, "memFree": 879004, "version": "4.27.3F"}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyMemoryUtilization,
|
||||
(VerifyMemoryUtilization, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"uptime": 1994.67,
|
||||
"modelName": "vEOS-lab",
|
||||
"internalVersion": "4.27.3F-26379303.4273F",
|
||||
"memTotal": 2004568,
|
||||
"memFree": 89004,
|
||||
"version": "4.27.3F",
|
||||
},
|
||||
{"uptime": 1994.67, "modelName": "vEOS-lab", "internalVersion": "4.27.3F-26379303.4273F", "memTotal": 2004568, "memFree": 89004, "version": "4.27.3F"}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device has reported a high memory usage - Expected: < 75% Actual: 95.56%"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Device has reported a high memory usage - Expected: < 75% Actual: 95.56%"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyFileSystemUtilization,
|
||||
(VerifyFileSystemUtilization, "success"): {
|
||||
"eos_data": [
|
||||
"""Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/sda2 3.9G 988M 2.9G 26% /mnt/flash
|
||||
none 294M 78M 217M 27% /
|
||||
none 294M 78M 217M 27% /.overlay
|
||||
/dev/loop0 461M 461M 0 100% /rootfs-i386
|
||||
""",
|
||||
"Filesystem Size Used Avail Use% Mounted on\n/dev/sda2 3.9G 988M 2.9G 26% /mnt/flash\nnone 294M 78M 217M 27% /\n"
|
||||
"none 294M 78M 217M 27% /.overlay\n/dev/loop0 461M 461M 0 100% /rootfs-i386\n"
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyFileSystemUtilization,
|
||||
(VerifyFileSystemUtilization, "failure"): {
|
||||
"eos_data": [
|
||||
"""Filesystem Size Used Avail Use% Mounted on
|
||||
/dev/sda2 3.9G 988M 2.9G 84% /mnt/flash
|
||||
none 294M 78M 217M 27% /
|
||||
none 294M 78M 217M 84% /.overlay
|
||||
/dev/loop0 461M 461M 0 100% /rootfs-i386
|
||||
""",
|
||||
"Filesystem Size Used Avail Use% Mounted on\n/dev/sda2 3.9G 988M 2.9G 84% /mnt/flash\nnone 294M 78M 217M 27% /\n"
|
||||
"none 294M 78M 217M 84% /.overlay\n/dev/loop0 461M 461M 0 100% /rootfs-i386\n"
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Mount point: /dev/sda2 3.9G 988M 2.9G 84% /mnt/flash - Higher disk space utilization - Expected: 75% Actual: 84%",
|
||||
"Mount point: none 294M 78M 217M 84% /.overlay - Higher disk space utilization - Expected: 75% Actual: 84%",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyNTP,
|
||||
"eos_data": [
|
||||
"""synchronised
|
||||
poll interval unknown
|
||||
""",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
(VerifyNTP, "success"): {"eos_data": ["synchronised\npoll interval unknown\n"], "expected": {"result": AntaTestStatus.SUCCESS}},
|
||||
(VerifyNTP, "failure"): {
|
||||
"eos_data": ["unsynchronised\npoll interval unknown\n"],
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["NTP status mismatch - Expected: synchronised Actual: unsynchronised"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyNTP,
|
||||
"eos_data": [
|
||||
"""unsynchronised
|
||||
poll interval unknown
|
||||
""",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["NTP status mismatch - Expected: synchronised Actual: unsynchronised"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.1.1.1": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"2.2.2.2": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"3.3.3.3": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"1.1.1.1": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"2.2.2.2": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"3.3.3.3": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -312,29 +256,15 @@ poll interval unknown
|
|||
{"server_address": "3.3.3.3", "stratum": 2},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-pool-name",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "success-pool-name"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.ntp.networks.com": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"2.ntp.networks.com": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"3.ntp.networks.com": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"1.ntp.networks.com": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"2.ntp.networks.com": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"3.ntp.networks.com": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -345,56 +275,28 @@ poll interval unknown
|
|||
{"server_address": "3.ntp.networks.com", "stratum": 2},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-ntp-pool-as-input",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "success-ntp-pool-as-input"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.1.1.1": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"2.2.2.2": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"3.3.3.3": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"1.1.1.1": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"2.2.2.2": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"3.3.3.3": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"ntp_pool": {"server_addresses": ["1.1.1.1", "2.2.2.2", "3.3.3.3"], "preferred_stratum_range": [1, 2]}},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-ntp-pool-hostname",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "success-ntp-pool-hostname"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"itsys-ntp010p.aristanetworks.com": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"itsys-ntp011p.aristanetworks.com": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"itsys-ntp012p.aristanetworks.com": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"itsys-ntp010p.aristanetworks.com": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"itsys-ntp011p.aristanetworks.com": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"itsys-ntp012p.aristanetworks.com": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -404,29 +306,15 @@ poll interval unknown
|
|||
"preferred_stratum_range": [1, 2],
|
||||
}
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-ip-dns",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "success-ip-dns"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.1.1.1 (1.ntp.networks.com)": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"2.2.2.2 (2.ntp.networks.com)": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"3.3.3.3 (3.ntp.networks.com)": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"1.1.1.1 (1.ntp.networks.com)": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"2.2.2.2 (2.ntp.networks.com)": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"3.3.3.3 (3.ntp.networks.com)": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -437,29 +325,15 @@ poll interval unknown
|
|||
{"server_address": "3.3.3.3", "stratum": 2},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-ntp-server",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "failure-ntp-server"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.1.1.1": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"2.2.2.2": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"3.3.3.3": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 3,
|
||||
},
|
||||
"1.1.1.1": {"condition": "candidate", "peerIpAddr": "1.1.1.1", "stratumLevel": 2},
|
||||
"2.2.2.2": {"condition": "sys.peer", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"3.3.3.3": {"condition": "sys.peer", "peerIpAddr": "3.3.3.3", "stratumLevel": 3},
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -471,7 +345,7 @@ poll interval unknown
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"NTP Server: 1.1.1.1 Preferred: True Stratum: 1 - Incorrect condition - Expected: sys.peer Actual: candidate",
|
||||
"NTP Server: 1.1.1.1 Preferred: True Stratum: 1 - Incorrect stratum level - Expected: 1 Actual: 2",
|
||||
|
@ -481,9 +355,7 @@ poll interval unknown
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peers",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "failure-no-peers"): {
|
||||
"eos_data": [{"peers": {}}],
|
||||
"inputs": {
|
||||
"ntp_servers": [
|
||||
|
@ -492,27 +364,14 @@ poll interval unknown
|
|||
{"server_address": "3.3.3.3", "stratum": 1},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["No NTP peers configured"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["No NTP peers configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-one-peer-not-found",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "failure-one-peer-not-found"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.1.1.1": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"2.2.2.2": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"1.1.1.1": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"2.2.2.2": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 1},
|
||||
}
|
||||
}
|
||||
],
|
||||
|
@ -523,25 +382,10 @@ poll interval unknown
|
|||
{"server_address": "3.3.3.3", "stratum": 1},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["NTP Server: 3.3.3.3 Preferred: False Stratum: 1 - Not configured"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["NTP Server: 3.3.3.3 Preferred: False Stratum: 1 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-with-two-peers-not-found",
|
||||
"test": VerifyNTPAssociations,
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"1.1.1.1": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
(VerifyNTPAssociations, "failure-with-two-peers-not-found"): {
|
||||
"eos_data": [{"peers": {"1.1.1.1": {"condition": "candidate", "peerIpAddr": "1.1.1.1", "stratumLevel": 1}}}],
|
||||
"inputs": {
|
||||
"ntp_servers": [
|
||||
{"server_address": "1.1.1.1", "preferred": True, "stratum": 1},
|
||||
|
@ -550,7 +394,7 @@ poll interval unknown
|
|||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"NTP Server: 1.1.1.1 Preferred: True Stratum: 1 - Incorrect condition - Expected: sys.peer Actual: candidate",
|
||||
"NTP Server: 2.2.2.2 Preferred: False Stratum: 1 - Not configured",
|
||||
|
@ -558,96 +402,51 @@ poll interval unknown
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-ntp-pool-as-input",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "failure-ntp-pool-as-input"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"ntp1.pool": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"ntp2.pool": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"ntp3.pool": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"ntp1.pool": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"ntp2.pool": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"ntp3.pool": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"ntp_pool": {"server_addresses": ["1.1.1.1", "2.2.2.2"], "preferred_stratum_range": [1, 2]}},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["NTP Server: 3.3.3.3 Hostname: ntp3.pool - Associated but not part of the provided NTP pool"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["NTP Server: 3.3.3.3 Hostname: ntp3.pool - Associated but not part of the provided NTP pool"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-ntp-pool-as-input-bad-association",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "failure-ntp-pool-as-input-bad-association"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"ntp1.pool": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 1,
|
||||
},
|
||||
"ntp2.pool": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"ntp3.pool": {
|
||||
"condition": "reject",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 3,
|
||||
},
|
||||
"ntp1.pool": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 1},
|
||||
"ntp2.pool": {"condition": "candidate", "peerIpAddr": "2.2.2.2", "stratumLevel": 2},
|
||||
"ntp3.pool": {"condition": "reject", "peerIpAddr": "3.3.3.3", "stratumLevel": 3},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"ntp_pool": {"server_addresses": ["1.1.1.1", "2.2.2.2", "3.3.3.3"], "preferred_stratum_range": [1, 2]}},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"NTP Server: 3.3.3.3 Hostname: ntp3.pool - Incorrect condition - Expected: sys.peer, candidate Actual: reject",
|
||||
"NTP Server: 3.3.3.3 Hostname: ntp3.pool - Incorrect stratum level - Expected Stratum Range: 1 to 2 Actual: 3",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-ntp-pool-hostname",
|
||||
"test": VerifyNTPAssociations,
|
||||
(VerifyNTPAssociations, "failure-ntp-pool-hostname"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"peers": {
|
||||
"itsys-ntp010p.aristanetworks.com": {
|
||||
"condition": "sys.peer",
|
||||
"peerIpAddr": "1.1.1.1",
|
||||
"stratumLevel": 5,
|
||||
},
|
||||
"itsys-ntp011p.aristanetworks.com": {
|
||||
"condition": "reject",
|
||||
"peerIpAddr": "2.2.2.2",
|
||||
"stratumLevel": 4,
|
||||
},
|
||||
"itsys-ntp012p.aristanetworks.com": {
|
||||
"condition": "candidate",
|
||||
"peerIpAddr": "3.3.3.3",
|
||||
"stratumLevel": 2,
|
||||
},
|
||||
"itsys-ntp010p.aristanetworks.com": {"condition": "sys.peer", "peerIpAddr": "1.1.1.1", "stratumLevel": 5},
|
||||
"itsys-ntp011p.aristanetworks.com": {"condition": "reject", "peerIpAddr": "2.2.2.2", "stratumLevel": 4},
|
||||
"itsys-ntp012p.aristanetworks.com": {"condition": "candidate", "peerIpAddr": "3.3.3.3", "stratumLevel": 2},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"ntp_pool": {"server_addresses": ["itsys-ntp010p.aristanetworks.com", "itsys-ntp011p.aristanetworks.com"], "preferred_stratum_range": [1, 2]}},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"NTP Server: 1.1.1.1 Hostname: itsys-ntp010p.aristanetworks.com - Incorrect stratum level - Expected Stratum Range: 1 to 2 Actual: 5",
|
||||
"NTP Server: 2.2.2.2 Hostname: itsys-ntp011p.aristanetworks.com - Incorrect condition - Expected: sys.peer, candidate Actual: reject",
|
||||
|
@ -656,23 +455,11 @@ poll interval unknown
|
|||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success-no-maintenance-configured",
|
||||
"test": VerifyMaintenance,
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
"warnings": ["Maintenance Mode is disabled."],
|
||||
},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
(VerifyMaintenance, "success-no-maintenance-configured"): {
|
||||
"eos_data": [{"units": {}, "interfaces": {}, "vrfs": {}, "warnings": ["Maintenance Mode is disabled."]}],
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-maintenance-configured-but-not-enabled",
|
||||
"test": VerifyMaintenance,
|
||||
(VerifyMaintenance, "success-maintenance-configured-but-not-enabled"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {
|
||||
|
@ -688,14 +475,11 @@ poll interval unknown
|
|||
},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "success-multiple-units-but-not-enabled",
|
||||
"test": VerifyMaintenance,
|
||||
(VerifyMaintenance, "success-multiple-units-but-not-enabled"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {
|
||||
|
@ -720,14 +504,11 @@ poll interval unknown
|
|||
},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-maintenance-enabled",
|
||||
"test": VerifyMaintenance,
|
||||
(VerifyMaintenance, "failure-maintenance-enabled"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {
|
||||
|
@ -752,20 +533,11 @@ poll interval unknown
|
|||
},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Units under maintenance: 'mlag'.",
|
||||
"Possible causes: 'Quiesce is configured'.",
|
||||
],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Units under maintenance: 'mlag'", "Possible causes: 'Quiesce is configured'"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-multiple-reasons",
|
||||
"test": VerifyMaintenance,
|
||||
(VerifyMaintenance, "failure-multiple-reasons"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {
|
||||
|
@ -790,21 +562,14 @@ poll interval unknown
|
|||
},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Units under maintenance: 'mlag'.",
|
||||
"Units entering maintenance: 'System'.",
|
||||
"Possible causes: 'Quiesce is configured'.",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Units under maintenance: 'mlag'", "Units entering maintenance: 'System'", "Possible causes: 'Quiesce is configured'"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-onboot-maintenance",
|
||||
"test": VerifyMaintenance,
|
||||
(VerifyMaintenance, "failure-onboot-maintenance"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {
|
||||
|
@ -820,20 +585,14 @@ poll interval unknown
|
|||
},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Units under maintenance: 'System'.",
|
||||
"Possible causes: 'On-boot maintenance is configured, Quiesce is configured'.",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Units under maintenance: 'System'", "Possible causes: 'On-boot maintenance is configured, Quiesce is configured'"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-entering-maintenance-interface-violation",
|
||||
"test": VerifyMaintenance,
|
||||
(VerifyMaintenance, "failure-entering-maintenance-interface-violation"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"units": {
|
||||
|
@ -849,15 +608,11 @@ poll interval unknown
|
|||
},
|
||||
"interfaces": {},
|
||||
"vrfs": {},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Units entering maintenance: 'System'.",
|
||||
"Possible causes: 'Interface traffic threshold violation, Quiesce is configured'.",
|
||||
],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Units entering maintenance: 'System'", "Possible causes: 'Interface traffic threshold violation, Quiesce is configured'"],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -5,88 +5,109 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.tests.vlan import VerifyDynamicVlanSource, VerifyVlanInternalPolicy
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.vlan import VerifyDynamicVlanSource, VerifyVlanInternalPolicy, VerifyVlanStatus
|
||||
from tests.units.anta_tests import test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVlanInternalPolicy,
|
||||
if TYPE_CHECKING:
|
||||
from tests.units.anta_tests import AntaUnitTestDataDict
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyVlanInternalPolicy, "success"): {
|
||||
"eos_data": [{"policy": "ascending", "startVlanId": 1006, "endVlanId": 4094}],
|
||||
"inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-policy",
|
||||
"test": VerifyVlanInternalPolicy,
|
||||
(VerifyVlanInternalPolicy, "failure-incorrect-policy"): {
|
||||
"eos_data": [{"policy": "descending", "startVlanId": 4094, "endVlanId": 1006}],
|
||||
"inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Incorrect VLAN internal allocation policy configured - Expected: ascending Actual: descending"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-start-end-id",
|
||||
"test": VerifyVlanInternalPolicy,
|
||||
(VerifyVlanInternalPolicy, "failure-incorrect-start-end-id"): {
|
||||
"eos_data": [{"policy": "ascending", "startVlanId": 4094, "endVlanId": 1006}],
|
||||
"inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"VLAN internal allocation policy: ascending - Incorrect start VLAN id configured - Expected: 1006 Actual: 4094",
|
||||
"VLAN internal allocation policy: ascending - Incorrect end VLAN id configured - Expected: 4094 Actual: 1006",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyDynamicVlanSource,
|
||||
(VerifyDynamicVlanSource, "success"): {
|
||||
"eos_data": [{"dynamicVlans": {"evpn": {"vlanIds": [1199]}, "mlagsync": {"vlanIds": [1401]}, "vccbfd": {"vlanIds": [1501]}}}],
|
||||
"inputs": {"sources": ["evpn", "mlagsync"], "strict": False},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-dynamic-vlan-sources",
|
||||
"test": VerifyDynamicVlanSource,
|
||||
(VerifyDynamicVlanSource, "failure-no-dynamic-vlan-sources"): {
|
||||
"eos_data": [{"dynamicVlans": {}}],
|
||||
"inputs": {"sources": ["evpn", "mlagsync"], "strict": False},
|
||||
"expected": {"result": "failure", "messages": ["Dynamic VLAN source(s) not found in configuration: evpn, mlagsync"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Dynamic VLAN source(s) not found in configuration: evpn, mlagsync"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-dynamic-vlan-sources-mismatch",
|
||||
"test": VerifyDynamicVlanSource,
|
||||
(VerifyDynamicVlanSource, "failure-dynamic-vlan-sources-mismatch"): {
|
||||
"eos_data": [{"dynamicVlans": {"vccbfd": {"vlanIds": [1500]}, "mlagsync": {"vlanIds": [1501]}}}],
|
||||
"inputs": {"sources": ["evpn", "mlagsync"], "strict": False},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Dynamic VLAN source(s) not found in configuration: evpn"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Dynamic VLAN source(s) not found in configuration: evpn"]},
|
||||
},
|
||||
{
|
||||
"name": "success-strict-mode",
|
||||
"test": VerifyDynamicVlanSource,
|
||||
(VerifyDynamicVlanSource, "success-strict-mode"): {
|
||||
"eos_data": [{"dynamicVlans": {"evpn": {"vlanIds": [1199]}, "mlagsync": {"vlanIds": [1502], "vccbfd": {"vlanIds": []}}}}],
|
||||
"inputs": {"sources": ["evpn", "mlagsync"], "strict": True},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-sources-exact-match-additional-source-found",
|
||||
"test": VerifyDynamicVlanSource,
|
||||
(VerifyDynamicVlanSource, "failure-all-sources-exact-match-additional-source-found"): {
|
||||
"eos_data": [{"dynamicVlans": {"evpn": {"vlanIds": [1199]}, "mlagsync": {"vlanIds": [1500]}, "vccbfd": {"vlanIds": [1500]}}}],
|
||||
"inputs": {"sources": ["evpn", "mlagsync"], "strict": True},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Strict mode enabled: Unexpected sources have VLANs allocated: vccbfd"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Strict mode enabled: Unexpected sources have VLANs allocated: vccbfd"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-sources-exact-match-expected-source-not-found",
|
||||
"test": VerifyDynamicVlanSource,
|
||||
(VerifyDynamicVlanSource, "failure-all-sources-exact-match-expected-source-not-found"): {
|
||||
"eos_data": [{"dynamicVlans": {"evpn": {"vlanIds": [1199]}, "mlagsync": {"vlanIds": []}}}],
|
||||
"inputs": {"sources": ["evpn", "mlagsync"], "strict": True},
|
||||
"expected": {"result": "failure", "messages": ["Dynamic VLAN source(s) exist but have no VLANs allocated: mlagsync"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Dynamic VLAN source(s) exist but have no VLANs allocated: mlagsync"]},
|
||||
},
|
||||
]
|
||||
(VerifyVlanStatus, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vlans": {
|
||||
"1": {"name": "default", "dynamic": False, "status": "active", "interfaces": {}},
|
||||
"4092": {"name": "VLAN4092", "dynamic": True, "status": "active", "interfaces": {}},
|
||||
"4094": {"name": "VLAN4094", "dynamic": True, "status": "active", "interfaces": {}},
|
||||
},
|
||||
"sourceDetail": "",
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": [{"vlan_id": 4092, "status": "active"}, {"vlan_id": 4094, "status": "active"}]},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
(VerifyVlanStatus, "failure-vlan-not-conifgured"): {
|
||||
"eos_data": [{"vlans": {"1": {"name": "default", "dynamic": False, "status": "active", "interfaces": {}}}, "sourceDetail": ""}],
|
||||
"inputs": {"vlans": [{"vlan_id": 4092, "status": "active"}, {"vlan_id": 4094, "status": "active"}]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["VLAN: Vlan4092 - Not configured", "VLAN: Vlan4094 - Not configured"]},
|
||||
},
|
||||
(VerifyVlanStatus, "failure-incorrect-status"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vlans": {
|
||||
"1": {"name": "default", "dynamic": False, "status": "active", "interfaces": {}},
|
||||
"4092": {"name": "VLAN4092", "dynamic": True, "status": "suspended", "interfaces": {}},
|
||||
"4094": {"name": "VLAN4094", "dynamic": True, "status": "active", "interfaces": {}},
|
||||
},
|
||||
"sourceDetail": "",
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": [{"vlan_id": 4092, "status": "active"}, {"vlan_id": 4094, "status": "suspended"}]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"VLAN: Vlan4092 - Incorrect administrative status - Expected: active Actual: suspended",
|
||||
"VLAN: Vlan4094 - Incorrect administrative status - Expected: suspended Actual: active",
|
||||
],
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
@ -5,50 +5,47 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
import sys
|
||||
from typing import TYPE_CHECKING, Any
|
||||
|
||||
from anta.models import AntaTest
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tests.vxlan import VerifyVxlan1ConnSettings, VerifyVxlan1Interface, VerifyVxlanConfigSanity, VerifyVxlanVniBinding, VerifyVxlanVtep
|
||||
from tests.units.anta_tests import test
|
||||
from tests.units.anta_tests import AntaUnitTest, test
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlan1Interface,
|
||||
if sys.version_info >= (3, 10):
|
||||
from typing import TypeAlias
|
||||
else:
|
||||
TypeAlias = type
|
||||
|
||||
|
||||
AntaUnitTestDataDict: TypeAlias = dict[tuple[type[AntaTest], str], AntaUnitTest]
|
||||
|
||||
DATA: AntaUnitTestDataDict = {
|
||||
(VerifyVxlan1Interface, "success"): {
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "up", "interfaceStatus": "up"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlan1Interface,
|
||||
(VerifyVxlan1Interface, "skipped"): {
|
||||
"eos_data": [{"interfaceDescriptions": {"Loopback0": {"lineProtocolStatus": "up", "interfaceStatus": "up"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Interface: Vxlan1 - Not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Interface: Vxlan1 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-down-up",
|
||||
"test": VerifyVxlan1Interface,
|
||||
(VerifyVxlan1Interface, "failure-down-up"): {
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "down", "interfaceStatus": "up"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Interface: Vxlan1 - Incorrect Line protocol status/Status - Expected: up/up Actual: down/up"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Interface: Vxlan1 - Incorrect Line protocol status/Status - Expected: up/up Actual: down/up"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-up-down",
|
||||
"test": VerifyVxlan1Interface,
|
||||
(VerifyVxlan1Interface, "failure-up-down"): {
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "up", "interfaceStatus": "down"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Interface: Vxlan1 - Incorrect Line protocol status/Status - Expected: up/up Actual: up/down"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Interface: Vxlan1 - Incorrect Line protocol status/Status - Expected: up/up Actual: up/down"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-down-down",
|
||||
"test": VerifyVxlan1Interface,
|
||||
(VerifyVxlan1Interface, "failure-down-down"): {
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "down", "interfaceStatus": "down"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Interface: Vxlan1 - Incorrect Line protocol status/Status - Expected: up/up Actual: down/down"]},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Interface: Vxlan1 - Incorrect Line protocol status/Status - Expected: up/up Actual: down/down"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlanConfigSanity,
|
||||
(VerifyVxlanConfigSanity, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"categories": {
|
||||
|
@ -106,14 +103,11 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"warnings": [],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyVxlanConfigSanity,
|
||||
(VerifyVxlanConfigSanity, "failure"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"categories": {
|
||||
|
@ -171,186 +165,181 @@ DATA: list[dict[str, Any]] = [
|
|||
},
|
||||
},
|
||||
"warnings": ["Your configuration contains warnings. This does not mean misconfigurations. But you may wish to re-check your configurations."],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Vxlan Category: localVtep - Config sanity check is not passing"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Vxlan Category: localVtep - Config sanity check is not passing"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlanConfigSanity,
|
||||
(VerifyVxlanConfigSanity, "skipped"): {
|
||||
"eos_data": [{"categories": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["VXLAN is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["VXLAN is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
(VerifyVxlanVniBinding, "success"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 20, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}},
|
||||
"10020": {"vlan": 20, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}}
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "PROD", "vlan": 1199, "source": "evpn"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "TEST", "vlan": 1199, "source": "evpn"}, "600": {"vrfName": "PROD", "vlan": 1198, "source": "evpn"}},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bindings": {10020: 20, 500: 1199}},
|
||||
"expected": {"result": "success"},
|
||||
"inputs": {"bindings": {10020: 20, 500: 1199, 600: "PROD"}},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-binding",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
(VerifyVxlanVniBinding, "failure-no-binding"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 20, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}},
|
||||
"10020": {"vlan": 20, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}}
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "PROD", "vlan": 1199, "source": "evpn"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bindings": {10010: 10, 10020: 20, 500: 1199}},
|
||||
"expected": {"result": "failure", "messages": ["Interface: Vxlan1 VNI: 10010 - Binding not found"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Interface: Vxlan1 VNI: 10010 - Binding not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-binding",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
(VerifyVxlanVniBinding, "failure-vrf-wrong-binding"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 30, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}},
|
||||
"10020": {"vlan": 20, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}}
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "PROD", "vlan": 1199, "source": "evpn"}, "600": {"vrfName": "TEST", "vlan": 1199, "source": "evpn"}},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bindings": {10020: 20, 500: 1199, 600: "PROD"}},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Interface: Vxlan1 VNI: 600 - Wrong VRF binding - Expected: PROD Actual: TEST"]},
|
||||
},
|
||||
(VerifyVxlanVniBinding, "failure-wrong-binding"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 30, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}}
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "PROD", "vlan": 1199, "source": "evpn"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bindings": {10020: 20, 500: 1199}},
|
||||
"expected": {"result": "failure", "messages": ["Interface: Vxlan1 VNI: 10020 VLAN: 20 - Wrong VLAN binding - Actual: 30"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Interface: Vxlan1 VNI: 10020 - Wrong VLAN binding - Expected: 20 Actual: 30"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-and-wrong-binding",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
(VerifyVxlanVniBinding, "failure-no-and-wrong-binding"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 30, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}},
|
||||
"10020": {"vlan": 30, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}}
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "PROD", "vlan": 1199, "source": "evpn"}},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bindings": {10010: 10, 10020: 20, 500: 1199}},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Interface: Vxlan1 VNI: 10010 - Binding not found", "Interface: Vxlan1 VNI: 10020 VLAN: 20 - Wrong VLAN binding - Actual: 30"],
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Interface: Vxlan1 VNI: 10010 - Binding not found", "Interface: Vxlan1 VNI: 10020 - Wrong VLAN binding - Expected: 20 Actual: 30"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
(VerifyVxlanVniBinding, "failure-wrong-vni-vrf-binding"): {
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 30, "dynamicVlan": False, "source": "static", "interfaces": {"Ethernet31": {"dot1q": 0}, "Vxlan1": {"dot1q": 20}}}
|
||||
},
|
||||
"vniBindingsToVrf": {"500": {"vrfName": "PROD", "vlan": 1199, "source": "evpn"}},
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bindings": {10020: "PROD", 500: 30}},
|
||||
"expected": {
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": ["Interface: Vxlan1 VNI: 10020 - Binding not found", "Interface: Vxlan1 VNI: 500 - Wrong VLAN binding - Expected: 30 Actual: 1199"],
|
||||
},
|
||||
},
|
||||
(VerifyVxlanVniBinding, "skipped"): {
|
||||
"eos_data": [{"vxlanIntfs": {}}],
|
||||
"inputs": {"bindings": {10020: 20, 500: 1199}},
|
||||
"expected": {"result": "skipped", "messages": ["Vxlan1 interface is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Interface: Vxlan1 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlanVtep,
|
||||
(VerifyVxlanVtep, "success"): {
|
||||
"eos_data": [{"vteps": {}, "interfaces": {"Vxlan1": {"vteps": ["10.1.1.5", "10.1.1.6"]}}}],
|
||||
"inputs": {"vteps": ["10.1.1.5", "10.1.1.6"]},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-vtep",
|
||||
"test": VerifyVxlanVtep,
|
||||
(VerifyVxlanVtep, "failure-missing-vtep"): {
|
||||
"eos_data": [{"vteps": {}, "interfaces": {"Vxlan1": {"vteps": ["10.1.1.5", "10.1.1.6"]}}}],
|
||||
"inputs": {"vteps": ["10.1.1.5", "10.1.1.6", "10.1.1.7"]},
|
||||
"expected": {"result": "failure", "messages": ["The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.7"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.7"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-vtep",
|
||||
"test": VerifyVxlanVtep,
|
||||
(VerifyVxlanVtep, "failure-no-vtep"): {
|
||||
"eos_data": [{"vteps": {}, "interfaces": {"Vxlan1": {"vteps": []}}}],
|
||||
"inputs": {"vteps": ["10.1.1.5", "10.1.1.6"]},
|
||||
"expected": {"result": "failure", "messages": ["The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.5, 10.1.1.6"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.5, 10.1.1.6"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-input-vtep",
|
||||
"test": VerifyVxlanVtep,
|
||||
(VerifyVxlanVtep, "failure-no-input-vtep"): {
|
||||
"eos_data": [{"vteps": {}, "interfaces": {"Vxlan1": {"vteps": ["10.1.1.5"]}}}],
|
||||
"inputs": {"vteps": []},
|
||||
"expected": {"result": "failure", "messages": ["Unexpected VTEP peer(s) on Vxlan1 interface: 10.1.1.5"]},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Unexpected VTEP peer(s) on Vxlan1 interface: 10.1.1.5"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-missmatch",
|
||||
"test": VerifyVxlanVtep,
|
||||
(VerifyVxlanVtep, "failure-missmatch"): {
|
||||
"eos_data": [{"vteps": {}, "interfaces": {"Vxlan1": {"vteps": ["10.1.1.6", "10.1.1.7", "10.1.1.8"]}}}],
|
||||
"inputs": {"vteps": ["10.1.1.5", "10.1.1.6"]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"The following VTEP peer(s) are missing from the Vxlan1 interface: 10.1.1.5",
|
||||
"Unexpected VTEP peer(s) on Vxlan1 interface: 10.1.1.7, 10.1.1.8",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlanVtep,
|
||||
(VerifyVxlanVtep, "skipped"): {
|
||||
"eos_data": [{"vteps": {}, "interfaces": {}}],
|
||||
"inputs": {"vteps": ["10.1.1.5", "10.1.1.6", "10.1.1.7"]},
|
||||
"expected": {"result": "skipped", "messages": ["Vxlan1 interface is not configured"]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Interface: Vxlan1 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
(VerifyVxlan1ConnSettings, "success"): {
|
||||
"eos_data": [{"interfaces": {"Vxlan1": {"srcIpIntf": "Loopback1", "udpPort": 4789}}}],
|
||||
"inputs": {"source_interface": "Loopback1", "udp_port": 4789},
|
||||
"expected": {"result": "success"},
|
||||
"expected": {"result": AntaTestStatus.SUCCESS},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
(VerifyVxlan1ConnSettings, "skipped"): {
|
||||
"eos_data": [{"interfaces": {}}],
|
||||
"inputs": {"source_interface": "Loopback1", "udp_port": 4789},
|
||||
"expected": {"result": "skipped", "messages": ["Vxlan1 interface is not configured."]},
|
||||
"expected": {"result": AntaTestStatus.SKIPPED, "messages": ["Interface: Vxlan1 - Not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-interface",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
(VerifyVxlan1ConnSettings, "failure-wrong-interface"): {
|
||||
"eos_data": [{"interfaces": {"Vxlan1": {"srcIpIntf": "Loopback10", "udpPort": 4789}}}],
|
||||
"inputs": {"source_interface": "lo1", "udp_port": 4789},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Interface: Vxlan1 - Incorrect Source interface - Expected: Loopback1 Actual: Loopback10"],
|
||||
},
|
||||
"expected": {"result": AntaTestStatus.FAILURE, "messages": ["Interface: Vxlan1 - Incorrect Source interface - Expected: Loopback1 Actual: Loopback10"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-port",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
(VerifyVxlan1ConnSettings, "failure-wrong-port"): {
|
||||
"eos_data": [{"interfaces": {"Vxlan1": {"srcIpIntf": "Loopback10", "udpPort": 4789}}}],
|
||||
"inputs": {"source_interface": "Lo1", "udp_port": 4780},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"result": AntaTestStatus.FAILURE,
|
||||
"messages": [
|
||||
"Interface: Vxlan1 - Incorrect Source interface - Expected: Loopback1 Actual: Loopback10",
|
||||
"Interface: Vxlan1 - Incorrect UDP port - Expected: 4780 Actual: 4789",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
|
|
@ -123,7 +123,7 @@ def click_runner(capsys: pytest.CaptureFixture[str], anta_env: dict[str, str]) -
|
|||
|
||||
# Patch asynceapi methods used by AsyncEOSDevice. See tests/units/test_device.py
|
||||
with (
|
||||
patch("asynceapi.device.Device.check_connection", return_value=True),
|
||||
patch("asynceapi.device.Device.check_api_endpoint", return_value=True),
|
||||
patch("asynceapi.device.Device.cli", side_effect=cli),
|
||||
patch("asyncssh.connect"),
|
||||
patch(
|
||||
|
|
|
@ -368,7 +368,7 @@ def test_from_ansible_overwrite(
|
|||
None,
|
||||
True,
|
||||
False,
|
||||
"`anta get tests --module <module>` does not support relative imports",
|
||||
"`--module <module>` option does not support relative imports",
|
||||
ExitCode.USAGE_ERROR,
|
||||
id="Use relative module name",
|
||||
),
|
||||
|
@ -454,3 +454,185 @@ def test_get_tests_local_module(click_runner: CliRunner) -> None:
|
|||
if cwd != local_module_parent_path:
|
||||
assert "injecting CWD in PYTHONPATH and retrying..." in result.output
|
||||
assert "No test found in 'local_module'" in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("module", "test_name", "catalog", "expected_output", "expected_exit_code"),
|
||||
[
|
||||
pytest.param(
|
||||
None,
|
||||
None,
|
||||
None,
|
||||
"VerifyAcctConsoleMethods",
|
||||
ExitCode.OK,
|
||||
id="Get all commands",
|
||||
),
|
||||
pytest.param(
|
||||
"anta.tests.aaa",
|
||||
None,
|
||||
None,
|
||||
"VerifyAcctConsoleMethods",
|
||||
ExitCode.OK,
|
||||
id="Get commands, filter on module",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
"VerifyNTPAssociations",
|
||||
None,
|
||||
"VerifyNTPAssociations",
|
||||
ExitCode.OK,
|
||||
id="Get commands, filter on exact test name",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
"VerifyNTP",
|
||||
None,
|
||||
"anta.tests.system",
|
||||
ExitCode.OK,
|
||||
id="Get commands, filter on included test name",
|
||||
),
|
||||
pytest.param(
|
||||
"unknown_module",
|
||||
None,
|
||||
None,
|
||||
"Module `unknown_module` was not found!",
|
||||
ExitCode.USAGE_ERROR,
|
||||
id="Get commands wrong module",
|
||||
),
|
||||
pytest.param(
|
||||
"unknown_module.unknown",
|
||||
None,
|
||||
None,
|
||||
"Module `unknown_module.unknown` was not found!",
|
||||
ExitCode.USAGE_ERROR,
|
||||
id="Get commands wrong submodule",
|
||||
),
|
||||
pytest.param(
|
||||
".unknown_module",
|
||||
None,
|
||||
None,
|
||||
"`--module <module>` option does not support relative imports",
|
||||
ExitCode.USAGE_ERROR,
|
||||
id="Use relative module name",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
"VerifySomething",
|
||||
None,
|
||||
"No test 'VerifySomething' found in 'anta.tests'",
|
||||
ExitCode.OK,
|
||||
id="Get commands wrong test name",
|
||||
),
|
||||
pytest.param(
|
||||
"anta.tests.aaa",
|
||||
"VerifyNTP",
|
||||
None,
|
||||
"No test 'VerifyNTP' found in 'anta.tests.aaa'",
|
||||
ExitCode.OK,
|
||||
id="Get commands test exists but not in module",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
None,
|
||||
DATA_DIR / "test_catalog.yml",
|
||||
"VerifyEOSVersion",
|
||||
ExitCode.OK,
|
||||
id="Get all commands from catalog",
|
||||
),
|
||||
pytest.param(
|
||||
"anta.tests.aaa",
|
||||
None,
|
||||
DATA_DIR / "test_catalog.yml",
|
||||
"No test found in 'anta.tests.aaa' for catalog '", # partial match as no test from aaa in the catalog
|
||||
ExitCode.OK,
|
||||
id="Get all commands from module in catalog",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
None,
|
||||
DATA_DIR / "non_existing_catalog.yml",
|
||||
"Invalid value for '--catalog'",
|
||||
ExitCode.USAGE_ERROR,
|
||||
id="Catalog does not exist",
|
||||
),
|
||||
# TODO: catalog format JSON
|
||||
],
|
||||
)
|
||||
def test_get_commands(
|
||||
click_runner: CliRunner, module: str | None, test_name: str | None, catalog: str | None, expected_output: str, expected_exit_code: str
|
||||
) -> None:
|
||||
"""Test `anta get commands`."""
|
||||
cli_args = [
|
||||
"get",
|
||||
"commands",
|
||||
]
|
||||
if module is not None:
|
||||
cli_args.extend(["--module", module])
|
||||
|
||||
if test_name is not None:
|
||||
cli_args.extend(["--test", test_name])
|
||||
|
||||
if catalog is not None:
|
||||
cli_args.extend(["--catalog", catalog])
|
||||
|
||||
# Make sure to disable any ANTA_CATALOG env that could be set and pollute the test
|
||||
result = click_runner.invoke(anta, cli_args, env={"ANTA_CATALOG": None})
|
||||
|
||||
assert result.exit_code == expected_exit_code
|
||||
assert expected_output in result.output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("module", "test_name", "catalog", "expected_count"),
|
||||
[
|
||||
pytest.param(
|
||||
"anta.tests.aaa",
|
||||
None,
|
||||
None,
|
||||
4,
|
||||
id="Get unique commands, filter on module",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
"VerifyNTPAssociations",
|
||||
None,
|
||||
1,
|
||||
id="Get unique commands, filter on exact test name",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
"VerifyNTP",
|
||||
None,
|
||||
2,
|
||||
id="Get unique commands, filter on included test name",
|
||||
),
|
||||
pytest.param(
|
||||
None,
|
||||
None,
|
||||
DATA_DIR / "test_catalog.yml",
|
||||
1,
|
||||
id="Get all unique commands from catalog",
|
||||
),
|
||||
],
|
||||
)
|
||||
def test_get_commands_unique(click_runner: CliRunner, module: str | None, test_name: str | None, catalog: str | None, expected_count: int) -> None:
|
||||
"""Test `anta get commands`."""
|
||||
cli_args = [
|
||||
"get",
|
||||
"commands",
|
||||
]
|
||||
if module is not None:
|
||||
cli_args.extend(["--module", module])
|
||||
|
||||
if test_name is not None:
|
||||
cli_args.extend(["--test", test_name])
|
||||
|
||||
if catalog is not None:
|
||||
cli_args.extend(["--catalog", catalog])
|
||||
|
||||
cli_args.extend(["--unique"])
|
||||
|
||||
# Make sure to disable any ANTA_CATALOG env that could be set and pollute the test
|
||||
result = click_runner.invoke(anta, cli_args, env={"ANTA_CATALOG": None})
|
||||
|
||||
assert expected_count == len(result.output.splitlines())
|
||||
|
|
|
@ -13,7 +13,7 @@ from unittest.mock import MagicMock, patch
|
|||
import pytest
|
||||
import requests
|
||||
|
||||
from anta.cli.get.utils import create_inventory_from_ansible, create_inventory_from_cvp, extract_examples, find_tests_examples, get_cv_token, print_test
|
||||
from anta.cli.get.utils import create_inventory_from_ansible, create_inventory_from_cvp, extract_examples, find_tests_in_module, get_cv_token, print_test
|
||||
from anta.inventory import AntaInventory
|
||||
from anta.models import AntaCommand, AntaTemplate, AntaTest
|
||||
|
||||
|
@ -219,14 +219,14 @@ class TypoExampleTest(AntaTest):
|
|||
self.result.is_success()
|
||||
|
||||
|
||||
def test_find_tests_examples() -> None:
|
||||
def test_find_tests_in_module() -> None:
|
||||
"""Test find_tests_examples.
|
||||
|
||||
Only testing the failure scenarii not tested through test_commands.
|
||||
TODO: expand
|
||||
"""
|
||||
with pytest.raises(ValueError, match="Error when importing"):
|
||||
find_tests_examples("blah", "UnusedTestName")
|
||||
find_tests_in_module("blah", "UnusedTestName")
|
||||
|
||||
|
||||
def test_print_test() -> None:
|
||||
|
|
|
@ -178,7 +178,7 @@ def test_anta_nrfu_md_report(click_runner: CliRunner, tmp_path: Path) -> None:
|
|||
def test_anta_nrfu_md_report_failure(click_runner: CliRunner, tmp_path: Path) -> None:
|
||||
"""Test anta nrfu md-report failure."""
|
||||
md_output = tmp_path / "test.md"
|
||||
with patch("anta.reporter.md_reporter.MDReportGenerator.generate", side_effect=OSError()):
|
||||
with patch("anta.reporter.md_reporter.MDReportGenerator.generate_sections", side_effect=OSError()):
|
||||
result = click_runner.invoke(anta, ["nrfu", "md-report", "--md-output", str(md_output)])
|
||||
|
||||
assert result.exit_code == ExitCode.USAGE_ERROR
|
||||
|
@ -206,5 +206,17 @@ def test_anta_nrfu_md_report_with_hide(click_runner: CliRunner, tmp_path: Path)
|
|||
total_tests = int(match.group(1))
|
||||
total_tests_success = int(match.group(2))
|
||||
|
||||
assert total_tests == 0
|
||||
assert total_tests_success == 0
|
||||
assert total_tests == 3
|
||||
assert total_tests_success == 3
|
||||
|
||||
# Collecting the rows inside the Test Results section
|
||||
row_count = 0
|
||||
lines = content.splitlines()
|
||||
|
||||
idx = lines.index("## Test Results")
|
||||
|
||||
for line in lines[idx + 1 :]:
|
||||
if line.startswith("|") and "---" not in line:
|
||||
row_count += 1
|
||||
# Reducing the row count by 1, as above conditions counts the TABLE_HEADING
|
||||
assert (row_count - 1) == 0
|
||||
|
|
|
@ -6,35 +6,21 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import sys
|
||||
from importlib import reload
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from typing import Any
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
import anta.cli
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from types import ModuleType
|
||||
|
||||
builtins_import = __import__
|
||||
|
||||
|
||||
# Tried to achieve this with mock
|
||||
# http://materials-scientist.com/blog/2021/02/11/mocking-failing-module-import-python/
|
||||
def import_mock(name: str, *args: Any) -> ModuleType: # noqa: ANN401
|
||||
"""Mock."""
|
||||
if name == "click":
|
||||
msg = "No module named 'click'"
|
||||
raise ModuleNotFoundError(msg)
|
||||
return builtins_import(name, *args)
|
||||
|
||||
|
||||
def test_cli_error_missing(capsys: pytest.CaptureFixture[Any]) -> None:
|
||||
# https://github.com/python/cpython/issues/88852
|
||||
@pytest.mark.skipif(sys.version_info <= (3, 11), reason="Unreliable behavior patching sys.modules before 3.11")
|
||||
def test_cli_error_missing_click(capsys: pytest.CaptureFixture[Any]) -> None:
|
||||
"""Test ANTA errors out when anta[cli] was not installed."""
|
||||
with patch.dict(sys.modules) as sys_modules, patch("builtins.__import__", import_mock):
|
||||
del sys_modules["anta.cli._main"]
|
||||
reload(anta.cli)
|
||||
with patch.dict(sys.modules, {"click": None}) as sys_modules:
|
||||
for k in list(sys_modules.keys()):
|
||||
if k.startswith("anta."):
|
||||
del sys_modules[k]
|
||||
import anta.cli
|
||||
|
||||
with pytest.raises(SystemExit) as e_info:
|
||||
anta.cli.cli()
|
||||
|
@ -53,3 +39,18 @@ def test_cli_error_missing(capsys: pytest.CaptureFixture[Any]) -> None:
|
|||
assert "Make sure you've installed everything with: pip install 'anta[cli]'" in captured.out
|
||||
assert "The caught exception was:" in captured.out
|
||||
assert e_info.value.code == 1
|
||||
|
||||
|
||||
# https://github.com/python/cpython/issues/88852
|
||||
@pytest.mark.skipif(sys.version_info <= (3, 11), reason="Unreliable behavior patching sys.modules before 3.11")
|
||||
def test_cli_error_missing_other() -> None:
|
||||
"""Test ANTA errors out when anta[cli] was not installed."""
|
||||
with patch.dict(sys.modules, {"httpx": None}) as sys_modules:
|
||||
# Need to clean up from previous runs a path that will trigger reimporting httpx
|
||||
for k in list(sys_modules.keys()):
|
||||
if k.startswith("anta."):
|
||||
del sys_modules[k]
|
||||
import anta.cli
|
||||
|
||||
with pytest.raises(ImportError, match="httpx"):
|
||||
anta.cli.cli()
|
||||
|
|
|
@ -5,8 +5,10 @@
|
|||
|
||||
from __future__ import annotations
|
||||
|
||||
import os
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, Any
|
||||
from unittest import mock
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
@ -15,7 +17,7 @@ import yaml
|
|||
from anta.device import AntaDevice, AsyncEOSDevice
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Iterator
|
||||
from collections.abc import Generator, Iterator
|
||||
|
||||
from anta.models import AntaCommand
|
||||
|
||||
|
@ -83,3 +85,10 @@ def yaml_file(request: pytest.FixtureRequest, tmp_path: Path) -> Path:
|
|||
content: dict[str, Any] = request.param
|
||||
file.write_text(yaml.dump(content, allow_unicode=True))
|
||||
return file
|
||||
|
||||
|
||||
@pytest.fixture
|
||||
def setenvvar(monkeypatch: pytest.MonkeyPatch) -> Generator[pytest.MonkeyPatch, None, None]:
|
||||
"""Fixture to set environment variables for testing."""
|
||||
with mock.patch.dict(os.environ, clear=True):
|
||||
yield monkeypatch
|
||||
|
|
|
@ -28,7 +28,9 @@ from anta.tests.routing.bgp import (
|
|||
)
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from anta.custom_types import Afi, RedistributedAfiSafi, RedistributedProtocol, Safi
|
||||
from ipaddress import IPv4Address, IPv6Address
|
||||
|
||||
from anta.custom_types import Afi, Interface, RedistributedAfiSafi, RedistributedProtocol, Safi
|
||||
|
||||
|
||||
class TestBgpAddressFamily:
|
||||
|
@ -60,6 +62,33 @@ class TestBgpAddressFamily:
|
|||
BgpAddressFamily(afi=afi, safi=safi, vrf=vrf)
|
||||
|
||||
|
||||
class TestBgpPeer:
|
||||
"""Test anta.input_models.routing.bgp.BgpPeer."""
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("peer_address", "interface"),
|
||||
[
|
||||
pytest.param("10.1.1.0", None, id="peer"),
|
||||
pytest.param(None, "Et1", id="interface"),
|
||||
],
|
||||
)
|
||||
def test_valid(self, peer_address: IPv4Address | IPv6Address, interface: Interface) -> None:
|
||||
"""Test BgpPeer valid inputs."""
|
||||
BgpPeer(peer_address=peer_address, interface=interface)
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("peer_address", "interface"),
|
||||
[
|
||||
pytest.param("10.1.1.0", "Et1", id="both"),
|
||||
pytest.param(None, "None", id="both-None"),
|
||||
],
|
||||
)
|
||||
def test_invalid(self, peer_address: IPv4Address | IPv6Address, interface: Interface) -> None:
|
||||
"""Test BgpPeer invalid inputs."""
|
||||
with pytest.raises(ValidationError):
|
||||
BgpPeer(peer_address=peer_address, interface=interface)
|
||||
|
||||
|
||||
class TestVerifyBGPPeerCountInput:
|
||||
"""Test anta.tests.routing.bgp.VerifyBGPPeerCount.Input."""
|
||||
|
||||
|
|
|
@ -19,6 +19,9 @@ if TYPE_CHECKING:
|
|||
|
||||
from _pytest.mark.structures import ParameterSet
|
||||
|
||||
from anta.device import AntaDevice, AsyncEOSDevice
|
||||
|
||||
|
||||
INIT_VALID_PARAMS: list[ParameterSet] = [
|
||||
pytest.param(
|
||||
{"anta_inventory": {"hosts": [{"host": "192.168.0.17"}, {"host": "192.168.0.2"}, {"host": "my.awesome.host.com"}]}},
|
||||
|
@ -87,3 +90,22 @@ class TestAntaInventory:
|
|||
with pytest.raises(OSError, match="No such file or directory"):
|
||||
_ = AntaInventory.parse(filename="dummy.yml", username="arista", password="arista123")
|
||||
assert "Unable to parse ANTA Device Inventory file" in caplog.records[0].message
|
||||
|
||||
@pytest.mark.parametrize(("inventory"), [{"count": 3}], indirect=True)
|
||||
def test_max_potential_connections(self, inventory: AntaInventory) -> None:
|
||||
"""Test max_potential_connections property with regular AsyncEOSDevice objects in the inventory."""
|
||||
# Each AsyncEOSDevice has a max_connections of 100
|
||||
assert inventory.max_potential_connections == 300
|
||||
|
||||
@pytest.mark.parametrize(("device"), [{"name": "anta_device"}], indirect=True)
|
||||
def test_get_potential_connections_custom_anta_device(self, caplog: pytest.LogCaptureFixture, async_device: AsyncEOSDevice, device: AntaDevice) -> None:
|
||||
"""Test max_potential_connections property with an AntaDevice with no max_connections in the inventory."""
|
||||
caplog.set_level(logging.DEBUG)
|
||||
|
||||
inventory = AntaInventory()
|
||||
inventory.add_device(async_device)
|
||||
inventory.add_device(device)
|
||||
|
||||
assert len(inventory) == 2
|
||||
assert inventory.max_potential_connections is None
|
||||
assert "Device anta_device 'max_connections' is not available" in caplog.messages
|
||||
|
|
|
@ -7,15 +7,48 @@ from __future__ import annotations
|
|||
|
||||
from io import StringIO
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING, ClassVar
|
||||
|
||||
import pytest
|
||||
|
||||
from anta.reporter.md_reporter import MDReportBase, MDReportGenerator
|
||||
from anta.result_manager import ResultManager
|
||||
from anta.result_manager.models import AntaTestStatus
|
||||
from anta.tools import convert_categories
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from collections.abc import Generator
|
||||
|
||||
DATA_DIR: Path = Path(__file__).parent.parent.parent.resolve() / "data"
|
||||
|
||||
|
||||
class FailedTestResultsSummary(MDReportBase):
|
||||
"""Test-only class used for simulating behavior in unit tests.
|
||||
|
||||
Generates the `## Failed Test Results Summary` section of the markdown report.
|
||||
"""
|
||||
|
||||
TABLE_HEADING: ClassVar[list[str]] = [
|
||||
"| Device Under Test | Categories | Test | Description | Custom Field | Result | Messages |",
|
||||
"| ----------------- | ---------- | ---- | ----------- | ------------ | ------ | -------- |",
|
||||
]
|
||||
|
||||
def generate_rows(self) -> Generator[str, None, None]:
|
||||
"""Generate the rows of the all test results table."""
|
||||
for result in self.results.results:
|
||||
messages = self.safe_markdown(result.messages[0]) if len(result.messages) == 1 else self.safe_markdown("<br>".join(result.messages))
|
||||
categories = ", ".join(sorted(convert_categories(result.categories)))
|
||||
yield (
|
||||
f"| {result.name or '-'} | {categories or '-'} | {result.test or '-'} "
|
||||
f"| {result.description or '-'} | {self.safe_markdown(result.custom_field) or '-'} | {result.result or '-'} | {messages or '-'} |\n"
|
||||
)
|
||||
|
||||
def generate_section(self) -> None:
|
||||
"""Generate the `## Failed Test Results Summary` section of the markdown report."""
|
||||
self.write_heading(heading_level=2)
|
||||
self.write_table(table_heading=self.TABLE_HEADING)
|
||||
|
||||
|
||||
def test_md_report_generate(tmp_path: Path, result_manager: ResultManager) -> None:
|
||||
"""Test the MDReportGenerator class."""
|
||||
md_filename = tmp_path / "test.md"
|
||||
|
@ -35,6 +68,31 @@ def test_md_report_generate(tmp_path: Path, result_manager: ResultManager) -> No
|
|||
assert content == expected_content
|
||||
|
||||
|
||||
def test_md_report_generate_sections(tmp_path: Path, result_manager: ResultManager) -> None:
|
||||
"""Test the MDReportGenerator class."""
|
||||
md_filename = tmp_path / "test.md"
|
||||
expected_report = "test_md_report_custom_sections.md"
|
||||
rm = result_manager.sort(sort_by=["name", "categories", "test"])
|
||||
|
||||
sections = [(section, rm) for section in MDReportGenerator.DEFAULT_SECTIONS]
|
||||
# Adding custom section
|
||||
failed_section = (FailedTestResultsSummary, rm.filter({AntaTestStatus.SUCCESS, AntaTestStatus.ERROR, AntaTestStatus.SKIPPED, AntaTestStatus.UNSET}))
|
||||
sections.insert(-1, failed_section)
|
||||
|
||||
# Generate the Markdown report
|
||||
MDReportGenerator.generate_sections(sections, md_filename)
|
||||
assert md_filename.exists()
|
||||
|
||||
# Load the existing Markdown report to compare with the generated one
|
||||
with (DATA_DIR / expected_report).open("r", encoding="utf-8") as f:
|
||||
expected_content = f.read()
|
||||
|
||||
# Check the content of the Markdown file
|
||||
content = md_filename.read_text(encoding="utf-8")
|
||||
|
||||
assert content == expected_content
|
||||
|
||||
|
||||
def test_md_report_base() -> None:
|
||||
"""Test the MDReportBase class."""
|
||||
|
||||
|
@ -52,3 +110,17 @@ def test_md_report_base() -> None:
|
|||
|
||||
with pytest.raises(NotImplementedError, match="Subclasses should implement this method"):
|
||||
report.generate_rows()
|
||||
|
||||
|
||||
def test_md_report_error(result_manager: ResultManager) -> None:
|
||||
"""Test the MDReportGenerator class to OSError to be raised."""
|
||||
md_filename = Path("non_existent_directory/non_existent_file.md")
|
||||
rm = result_manager.sort(sort_by=["name", "categories", "test"])
|
||||
|
||||
sections = [(section, rm) for section in MDReportGenerator.DEFAULT_SECTIONS]
|
||||
|
||||
with pytest.raises(OSError, match="No such file or directory"):
|
||||
MDReportGenerator.generate_sections(sections, md_filename)
|
||||
|
||||
with pytest.raises(OSError, match="No such file or directory"):
|
||||
MDReportGenerator.generate(result_manager, md_filename)
|
||||
|
|
|
@ -172,11 +172,11 @@ class TestResultManager:
|
|||
assert "results_by_status" not in result_manager.__dict__
|
||||
|
||||
# Access the cache
|
||||
assert result_manager.get_total_results() == 30
|
||||
assert result_manager.get_total_results() == 181
|
||||
|
||||
# Check the cache is filled with the correct results count
|
||||
assert "results_by_status" in result_manager.__dict__
|
||||
assert sum(len(v) for v in result_manager.__dict__["results_by_status"].values()) == 30
|
||||
assert sum(len(v) for v in result_manager.__dict__["results_by_status"].values()) == 181
|
||||
|
||||
# Add a new test
|
||||
result_manager.add(result=test_result_factory())
|
||||
|
@ -185,46 +185,51 @@ class TestResultManager:
|
|||
assert "results_by_status" not in result_manager.__dict__
|
||||
|
||||
# Access the cache again
|
||||
assert result_manager.get_total_results() == 31
|
||||
assert result_manager.get_total_results() == 182
|
||||
|
||||
# Check the cache is filled again with the correct results count
|
||||
assert "results_by_status" in result_manager.__dict__
|
||||
assert sum(len(v) for v in result_manager.__dict__["results_by_status"].values()) == 31
|
||||
assert sum(len(v) for v in result_manager.__dict__["results_by_status"].values()) == 182
|
||||
|
||||
def test_get_results(self, result_manager: ResultManager) -> None:
|
||||
"""Test ResultManager.get_results."""
|
||||
# Check for single status
|
||||
success_results = result_manager.get_results(status={AntaTestStatus.SUCCESS})
|
||||
assert len(success_results) == 4
|
||||
assert len(success_results) == 43
|
||||
assert all(r.result == "success" for r in success_results)
|
||||
|
||||
# Check for multiple statuses
|
||||
failure_results = result_manager.get_results(status={AntaTestStatus.FAILURE, AntaTestStatus.ERROR})
|
||||
assert len(failure_results) == 17
|
||||
assert len(failure_results) == 104
|
||||
assert all(r.result in {"failure", "error"} for r in failure_results)
|
||||
|
||||
# Check all results
|
||||
all_results = result_manager.get_results()
|
||||
assert len(all_results) == 30
|
||||
assert len(all_results) == 181
|
||||
|
||||
def test_get_results_sort_by(self, result_manager: ResultManager) -> None:
|
||||
"""Test ResultManager.get_results with sort_by."""
|
||||
# Check all results with sort_by result
|
||||
all_results = result_manager.get_results(sort_by=["result"])
|
||||
assert len(all_results) == 30
|
||||
assert [r.result for r in all_results] == ["error"] * 2 + ["failure"] * 15 + ["skipped"] * 9 + ["success"] * 4
|
||||
assert len(all_results) == 181
|
||||
assert [r.result for r in all_results] == ["error"] * 1 + ["failure"] * 103 + ["skipped"] * 34 + ["success"] * 43
|
||||
|
||||
# Check all results with sort_by device (name)
|
||||
all_results = result_manager.get_results(sort_by=["name"])
|
||||
assert len(all_results) == 30
|
||||
assert len(all_results) == 181
|
||||
assert all_results[0].name == "s1-spine1"
|
||||
|
||||
# Check multiple statuses with sort_by categories
|
||||
success_skipped_results = result_manager.get_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.SKIPPED}, sort_by=["categories"])
|
||||
assert len(success_skipped_results) == 13
|
||||
assert len(success_skipped_results) == 77
|
||||
assert success_skipped_results[0].categories == ["avt"]
|
||||
assert success_skipped_results[-1].categories == ["vxlan"]
|
||||
|
||||
# Check multiple statuses with sort_by custom_field
|
||||
success_skipped_results = result_manager.get_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.SKIPPED}, sort_by=["custom_field"])
|
||||
assert len(success_skipped_results) == 77
|
||||
assert success_skipped_results[-1].test == "VerifyReloadCause"
|
||||
|
||||
# Check all results with bad sort_by
|
||||
with pytest.raises(
|
||||
ValueError,
|
||||
|
@ -237,18 +242,18 @@ class TestResultManager:
|
|||
def test_get_total_results(self, result_manager: ResultManager) -> None:
|
||||
"""Test ResultManager.get_total_results."""
|
||||
# Test all results
|
||||
assert result_manager.get_total_results() == 30
|
||||
assert result_manager.get_total_results() == 181
|
||||
|
||||
# Test single status
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS}) == 4
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.FAILURE}) == 15
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.ERROR}) == 2
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SKIPPED}) == 9
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS}) == 43
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.FAILURE}) == 103
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.ERROR}) == 1
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SKIPPED}) == 34
|
||||
|
||||
# Test multiple statuses
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE}) == 19
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR}) == 21
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR, AntaTestStatus.SKIPPED}) == 30
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE}) == 146
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR}) == 147
|
||||
assert result_manager.get_total_results(status={AntaTestStatus.SUCCESS, AntaTestStatus.FAILURE, AntaTestStatus.ERROR, AntaTestStatus.SKIPPED}) == 181
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("status", "error_status", "ignore_error", "expected_status"),
|
||||
|
@ -546,6 +551,32 @@ class TestResultManager:
|
|||
assert results[2].result == "failure"
|
||||
assert results[2].test == "Test2"
|
||||
|
||||
def test_sort_fields_as_none(self, test_result_factory: Callable[[], TestResult]) -> None:
|
||||
"""Test sorting by multiple fields."""
|
||||
result_manager = ResultManager()
|
||||
test1 = test_result_factory()
|
||||
test1.result = AntaTestStatus.ERROR
|
||||
test1.test = "Test3"
|
||||
test1.custom_field = "custom"
|
||||
test2 = test_result_factory()
|
||||
test2.result = AntaTestStatus.ERROR
|
||||
test2.test = "Test1"
|
||||
test3 = test_result_factory()
|
||||
test3.result = AntaTestStatus.FAILURE
|
||||
test3.test = "Test2"
|
||||
|
||||
result_manager.results = [test1, test2, test3]
|
||||
sorted_manager = result_manager.sort(["custom_field"])
|
||||
results = sorted_manager.results
|
||||
|
||||
assert results[0].result == "error"
|
||||
assert results[0].test == "Test1"
|
||||
assert results[1].result == "failure"
|
||||
assert results[1].test == "Test2"
|
||||
assert results[2].result == "error"
|
||||
assert results[2].test == "Test3"
|
||||
assert results[2].custom_field == "custom"
|
||||
|
||||
def test_sort_invalid_field(self) -> None:
|
||||
"""Test that sort method raises ValueError for invalid sort_by fields."""
|
||||
result_manager = ResultManager()
|
||||
|
@ -561,3 +592,34 @@ class TestResultManager:
|
|||
"""Test that the sort method is chainable."""
|
||||
result_manager = ResultManager()
|
||||
assert isinstance(result_manager.sort(["name"]), ResultManager)
|
||||
|
||||
def test_merge_result_manager(self) -> None:
|
||||
"""Test the merge_results function."""
|
||||
result = ResultManager()
|
||||
final_merged_results = ResultManager.merge_results([result])
|
||||
assert isinstance(final_merged_results, ResultManager)
|
||||
|
||||
def test_merge_two_result_managers(self, test_result_factory: Callable[[], TestResult]) -> None:
|
||||
"""Test merging two non-empty ResultManager instances."""
|
||||
rm1 = ResultManager()
|
||||
test1_rm1 = test_result_factory()
|
||||
test1_rm1.name = "device1"
|
||||
rm1.add(test1_rm1)
|
||||
test2_rm1 = test_result_factory()
|
||||
test2_rm1.name = "device2"
|
||||
rm1.add(test2_rm1)
|
||||
|
||||
rm2 = ResultManager()
|
||||
test1_rm2 = test_result_factory()
|
||||
test1_rm2.name = "device3"
|
||||
rm2.add(test1_rm2)
|
||||
|
||||
merged_rm = ResultManager.merge_results([rm1, rm2])
|
||||
assert len(merged_rm) == 3
|
||||
assert {r.name for r in merged_rm.results} == {"device1", "device2", "device3"}
|
||||
|
||||
def test_merge_empty_list(self) -> None:
|
||||
"""Test merging an empty list of ResultManager instances."""
|
||||
merged_rm = ResultManager.merge_results([])
|
||||
assert isinstance(merged_rm, ResultManager)
|
||||
assert len(merged_rm) == 0
|
||||
|
|
File diff suppressed because it is too large
Load diff
414
tests/units/test__runner.py
Normal file
414
tests/units/test__runner.py
Normal file
|
@ -0,0 +1,414 @@
|
|||
# Copyright (c) 2023-2025 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Test anta._runner.py."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
from collections import defaultdict
|
||||
from pathlib import Path
|
||||
from typing import ClassVar
|
||||
|
||||
import pytest
|
||||
import respx
|
||||
from pydantic import ValidationError
|
||||
|
||||
from anta._runner import AntaRunContext, AntaRunFilters, AntaRunner
|
||||
from anta.catalog import AntaCatalog, AntaTestDefinition
|
||||
from anta.inventory import AntaInventory
|
||||
from anta.models import AntaCommand, AntaTemplate, AntaTest
|
||||
from anta.result_manager import ResultManager
|
||||
from anta.result_manager.models import TestResult as AntaTestResult
|
||||
from anta.settings import DEFAULT_MAX_CONCURRENCY, DEFAULT_NOFILE, AntaRunnerSettings
|
||||
from anta.tests.routing.generic import VerifyRoutingTableEntry
|
||||
|
||||
DATA_DIR: Path = Path(__file__).parent.parent.resolve() / "data"
|
||||
|
||||
|
||||
class TestAntaRunner:
|
||||
"""Test AntaRunner class."""
|
||||
|
||||
def test_init_with_default_settings(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test initialization with default settings."""
|
||||
caplog.set_level(logging.DEBUG)
|
||||
default_settings = {"nofile": DEFAULT_NOFILE, "max_concurrency": DEFAULT_MAX_CONCURRENCY}
|
||||
|
||||
runner = AntaRunner()
|
||||
|
||||
assert f"AntaRunner initialized with settings: {default_settings}" in caplog.messages
|
||||
assert runner._settings
|
||||
|
||||
def test_init_with_custom_env_settings(self, caplog: pytest.LogCaptureFixture, setenvvar: pytest.MonkeyPatch) -> None:
|
||||
"""Test initialization with custom env settings."""
|
||||
caplog.set_level(logging.DEBUG)
|
||||
desired_settings = {"nofile": 1048576, "max_concurrency": 10000}
|
||||
setenvvar.setenv("ANTA_NOFILE", str(desired_settings["nofile"]))
|
||||
setenvvar.setenv("ANTA_MAX_CONCURRENCY", str(desired_settings["max_concurrency"]))
|
||||
|
||||
runner = AntaRunner()
|
||||
|
||||
assert f"AntaRunner initialized with settings: {desired_settings}" in caplog.messages
|
||||
assert runner._settings
|
||||
|
||||
def test_init_with_provided_settings(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test initialization with provided settings."""
|
||||
caplog.set_level(logging.DEBUG)
|
||||
desired_settings = AntaRunnerSettings(nofile=1048576, max_concurrency=10000)
|
||||
|
||||
runner = AntaRunner(settings=desired_settings)
|
||||
|
||||
assert f"AntaRunner initialized with settings: {desired_settings.model_dump()}" in caplog.messages
|
||||
assert runner._settings
|
||||
|
||||
async def test_dry_run(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner.run() in dry-run."""
|
||||
caplog.set_level(logging.INFO)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner = AntaRunner()
|
||||
ctx = await runner.run(inventory, catalog, dry_run=True)
|
||||
|
||||
# Validate the final context attributes
|
||||
assert ctx.selected_inventory == ctx.inventory == inventory
|
||||
assert len(ctx.manager) > 0
|
||||
assert ctx.manager.status == "unset"
|
||||
assert ctx.total_tests_scheduled > 0
|
||||
assert ctx.total_devices_filtered_by_tags == 0
|
||||
assert ctx.total_devices_unreachable == 0
|
||||
assert ctx.total_devices_selected_for_testing == ctx.total_devices_in_inventory == len(inventory)
|
||||
assert ctx.duration is not None
|
||||
|
||||
assert "Dry-run mode, exiting before running the tests." in caplog.messages
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("filters", "expected_devices", "expected_tests"),
|
||||
[
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests=None, tags=None),
|
||||
3,
|
||||
27,
|
||||
id="all-tests",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests=None, tags={"leaf"}),
|
||||
2,
|
||||
6,
|
||||
id="1-tag",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests=None, tags={"leaf", "spine"}),
|
||||
3,
|
||||
9,
|
||||
id="2-tags",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests={"VerifyMlagStatus", "VerifyUptime"}, tags=None),
|
||||
3,
|
||||
5,
|
||||
id="filtered-tests",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests={"VerifyMlagStatus", "VerifyUptime"}, tags={"leaf"}),
|
||||
2,
|
||||
4,
|
||||
id="1-tag-filtered-tests",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices={"leaf1"}, tests=None, tags=None),
|
||||
1,
|
||||
9,
|
||||
id="filtered-devices",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests=None, tags={"invalid"}),
|
||||
0,
|
||||
0,
|
||||
id="invalid-tag",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices={"invalid"}, tests=None, tags=None),
|
||||
0,
|
||||
0,
|
||||
id="invalid-device",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests={"invalid"}, tags=None),
|
||||
3,
|
||||
0,
|
||||
id="invalid-test",
|
||||
),
|
||||
pytest.param(
|
||||
AntaRunFilters(devices=None, tests=None, tags={"dc1"}),
|
||||
1,
|
||||
0,
|
||||
id="device-tag-no-tests",
|
||||
),
|
||||
],
|
||||
)
|
||||
async def test_run_filters(self, caplog: pytest.LogCaptureFixture, filters: AntaRunFilters, expected_devices: int, expected_tests: int) -> None:
|
||||
"""Test AntaRunner.run() with different filters."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner = AntaRunner()
|
||||
ctx = await runner.run(inventory, catalog, filters=filters, dry_run=True)
|
||||
|
||||
# Gather the warning message
|
||||
warning_msg = None
|
||||
if expected_devices == 0:
|
||||
msg = "The inventory is empty after filtering by tags/devices. "
|
||||
if filters.devices:
|
||||
msg += f"Devices filter: {', '.join(sorted(filters.devices))}. "
|
||||
if filters.tags:
|
||||
msg += f"Tags filter: {', '.join(sorted(filters.tags))}. "
|
||||
msg += "Exiting ..."
|
||||
elif expected_tests == 0:
|
||||
msg = "No tests scheduled to run after filtering by tags/tests. "
|
||||
if filters.tests:
|
||||
msg += f"Tests filter: {', '.join(sorted(filters.tests))}. "
|
||||
if filters.tags:
|
||||
msg += f"Tags filter: {', '.join(sorted(filters.tags))}. "
|
||||
msg += "Exiting ..."
|
||||
|
||||
if warning_msg is not None:
|
||||
assert msg in ctx.warnings_at_setup
|
||||
assert msg in caplog.messages
|
||||
|
||||
assert ctx.total_tests_scheduled == expected_tests
|
||||
assert ctx.total_devices_selected_for_testing == expected_devices
|
||||
|
||||
async def test_run_invalid_filters(self) -> None:
|
||||
"""Test AntaRunner.run() with invalid filters."""
|
||||
inventory = AntaInventory()
|
||||
catalog = AntaCatalog()
|
||||
runner = AntaRunner()
|
||||
|
||||
with pytest.raises(ValidationError, match="1 validation error for AntaRunFilters"):
|
||||
await runner.run(inventory, catalog, filters=AntaRunFilters(devices="invalid"), dry_run=True) # type: ignore[arg-type]
|
||||
|
||||
async def test_run_provided_manager(self) -> None:
|
||||
"""Test AntaRunner.run() with a provided ResultManager instance."""
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
manager = ResultManager()
|
||||
runner = AntaRunner()
|
||||
|
||||
ctx = await runner.run(inventory, catalog, manager, dry_run=True)
|
||||
assert isinstance(ctx.manager, ResultManager)
|
||||
assert ctx.manager is manager
|
||||
assert len(manager) == 27
|
||||
|
||||
async def test_run_provided_manager_not_empty(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner.run() with a provided non-empty ResultManager instance."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
manager = ResultManager()
|
||||
test = AntaTestResult(name="DC1-LEAF1A", test="VerifyNTP", categories=["system"], description="NTP Test")
|
||||
runner = AntaRunner()
|
||||
manager.add(test)
|
||||
|
||||
ctx = await runner.run(inventory, catalog, manager, dry_run=True)
|
||||
assert isinstance(ctx.manager, ResultManager)
|
||||
assert ctx.manager is manager
|
||||
assert len(manager) == 28
|
||||
assert len(manager.device_stats) == ctx.total_devices_selected_for_testing + 1
|
||||
|
||||
warning_msg = (
|
||||
"Appending new results to the provided ResultManager which already holds 1 results. Statistics in this run context are for the current execution only."
|
||||
)
|
||||
assert warning_msg in ctx.warnings_at_setup
|
||||
assert warning_msg in caplog.messages
|
||||
|
||||
async def test_run_empty_catalog(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner.run() with an empty AntaCatalog."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog()
|
||||
runner = AntaRunner()
|
||||
|
||||
ctx = await runner.run(inventory, catalog)
|
||||
|
||||
warning_msg = "The list of tests is empty. Exiting ..."
|
||||
assert warning_msg in ctx.warnings_at_setup
|
||||
assert warning_msg in caplog.messages
|
||||
|
||||
async def test_run_empty_inventory(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner.run() with an empty AntaInventory."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
inventory = AntaInventory()
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner = AntaRunner()
|
||||
|
||||
ctx = await runner.run(inventory, catalog)
|
||||
|
||||
warning_msg = "The initial inventory is empty. Exiting ..."
|
||||
assert warning_msg in ctx.warnings_at_setup
|
||||
assert warning_msg in caplog.messages
|
||||
|
||||
@pytest.mark.parametrize("inventory", [{"reachable": False}], indirect=True)
|
||||
async def test_run_no_reachable_devices(self, caplog: pytest.LogCaptureFixture, inventory: AntaInventory) -> None:
|
||||
"""Test AntaRunner.run() with an empty AntaInventory."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner = AntaRunner()
|
||||
|
||||
ctx = await runner.run(inventory, catalog)
|
||||
assert ctx.total_devices_unreachable == ctx.total_devices_in_inventory
|
||||
assert "device-0" in ctx.devices_unreachable_at_setup
|
||||
|
||||
warning_msg = "No reachable devices found for testing after connectivity checks. Exiting ..."
|
||||
assert warning_msg in ctx.warnings_at_setup
|
||||
assert warning_msg in caplog.messages
|
||||
|
||||
async def test_run_invalid_anta_test(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner.run() with a provided non-empty ResultManager instance."""
|
||||
caplog.set_level(logging.CRITICAL)
|
||||
|
||||
class InvalidTest(AntaTest):
|
||||
"""ANTA test that raises an exception when test is called."""
|
||||
|
||||
categories: ClassVar[list[str]] = []
|
||||
commands: ClassVar[list[AntaCommand | AntaTemplate]] = []
|
||||
|
||||
def test(self) -> None: # type: ignore[override]
|
||||
"""Test function."""
|
||||
msg = "Test not implemented"
|
||||
raise NotImplementedError(msg)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
test_definition = AntaTestDefinition(test=InvalidTest, inputs=None)
|
||||
catalog = AntaCatalog(tests=[test_definition])
|
||||
runner = AntaRunner()
|
||||
|
||||
ctx = await runner.run(inventory, catalog, dry_run=True)
|
||||
assert len(ctx.manager) == 0
|
||||
|
||||
error_msg = (
|
||||
f"There is an error when creating test {__name__}.InvalidTest.\n"
|
||||
"If this is not a custom test implementation: "
|
||||
"Please reach out to the maintainer team or open an issue on Github: https://github.com/aristanetworks/anta.\n"
|
||||
"NotImplementedError: Test not implemented"
|
||||
)
|
||||
assert error_msg in caplog.messages
|
||||
|
||||
async def test_log_run_information_default(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner._log_run_information with default settings."""
|
||||
caplog.set_level(logging.INFO)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner = AntaRunner()
|
||||
await runner.run(inventory, catalog, dry_run=True)
|
||||
|
||||
expected_output = [
|
||||
"ANTA NRFU Dry Run Information",
|
||||
"Devices:",
|
||||
" Total in initial inventory: 3",
|
||||
" Selected for testing: 3",
|
||||
"Total number of selected tests: 27",
|
||||
]
|
||||
for line in expected_output:
|
||||
assert line in caplog.text
|
||||
|
||||
async def test_log_run_information_concurrency_limit(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner._log_run_information with higher tests count than concurrency limit."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner_settings = AntaRunnerSettings(max_concurrency=20)
|
||||
runner = AntaRunner(settings=runner_settings)
|
||||
|
||||
ctx = await runner.run(inventory, catalog, dry_run=True)
|
||||
|
||||
warning_msg = "Tests count (27) exceeds concurrent limit (20). Tests will be throttled. Please consult the ANTA FAQ."
|
||||
assert warning_msg in ctx.warnings_at_setup
|
||||
assert warning_msg in caplog.messages
|
||||
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Very unlikely to happen on non-POSIX systems due to sys.maxsize")
|
||||
async def test_log_run_information_file_descriptor_limit(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test AntaRunner._log_run_information with higher connections count than file descriptor limit."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
|
||||
inventory = AntaInventory.parse(filename=DATA_DIR / "test_inventory_with_tags.yml", username="anta", password="anta")
|
||||
catalog = AntaCatalog.parse(filename=DATA_DIR / "test_catalog_with_tags.yml")
|
||||
runner_settings = AntaRunnerSettings(nofile=128)
|
||||
runner = AntaRunner(settings=runner_settings)
|
||||
|
||||
ctx = await runner.run(inventory, catalog, dry_run=True)
|
||||
|
||||
warning_msg = "Potential connections (300) exceeds file descriptor limit (128). Connection errors may occur. Please consult the ANTA FAQ."
|
||||
assert warning_msg in ctx.warnings_at_setup
|
||||
assert warning_msg in caplog.messages
|
||||
|
||||
@pytest.mark.parametrize(("inventory"), [{"count": 3}], indirect=True)
|
||||
@respx.mock
|
||||
async def test_run(self, inventory: AntaInventory) -> None:
|
||||
"""Test AntaRunner.run()."""
|
||||
# Mock the eAPI requests
|
||||
respx.post(path="/command-api", headers={"Content-Type": "application/json-rpc"}, json__params__cmds__0__cmd="show ip route vrf default").respond(
|
||||
json={"result": [{"vrfs": {"default": {"routes": {}}}}]}
|
||||
)
|
||||
tests = [AntaTestDefinition(test=VerifyRoutingTableEntry, inputs={"routes": [f"10.1.0.{i}"], "collect": "all"}) for i in range(5)]
|
||||
catalog = AntaCatalog(tests=tests)
|
||||
runner = AntaRunner()
|
||||
|
||||
ctx = await runner.run(inventory, catalog)
|
||||
|
||||
assert ctx.total_devices_selected_for_testing == 3
|
||||
assert ctx.total_tests_scheduled == 15
|
||||
assert len(ctx.warnings_at_setup) == 0
|
||||
assert len(ctx.manager) == 15
|
||||
for result in ctx.manager.results:
|
||||
assert result.result == "failure"
|
||||
|
||||
|
||||
# pylint: disable=too-few-public-methods
|
||||
class TestAntaRunContext:
|
||||
"""Test AntaRunContext class."""
|
||||
|
||||
def test_init(self) -> None:
|
||||
"""Test initialization."""
|
||||
inventory = AntaInventory()
|
||||
catalog = AntaCatalog()
|
||||
manager = ResultManager()
|
||||
filters = AntaRunFilters()
|
||||
|
||||
ctx = AntaRunContext(inventory, catalog, manager, filters)
|
||||
|
||||
# Test initialized attributes
|
||||
assert ctx.inventory is inventory
|
||||
assert ctx.catalog is catalog
|
||||
assert ctx.manager is manager
|
||||
assert ctx.filters is filters
|
||||
assert not ctx.dry_run
|
||||
|
||||
assert isinstance(ctx.selected_inventory, AntaInventory)
|
||||
assert len(ctx.selected_inventory) == 0
|
||||
assert isinstance(ctx.selected_tests, defaultdict)
|
||||
assert len(ctx.selected_tests) == 0
|
||||
assert isinstance(ctx.devices_filtered_at_setup, list)
|
||||
assert len(ctx.devices_filtered_at_setup) == 0
|
||||
assert isinstance(ctx.devices_unreachable_at_setup, list)
|
||||
assert len(ctx.devices_unreachable_at_setup) == 0
|
||||
assert isinstance(ctx.warnings_at_setup, list)
|
||||
assert len(ctx.warnings_at_setup) == 0
|
||||
assert ctx.start_time is None
|
||||
assert ctx.end_time is None
|
||||
|
||||
# Test properties
|
||||
assert ctx.total_devices_in_inventory == 0
|
||||
assert ctx.total_devices_filtered_by_tags == 0
|
||||
assert ctx.total_devices_unreachable == 0
|
||||
assert ctx.total_devices_selected_for_testing == 0
|
||||
assert ctx.total_tests_scheduled == 0
|
||||
assert ctx.duration is None
|
|
@ -23,6 +23,7 @@ from anta.custom_types import (
|
|||
REGEXP_TYPE_VXLAN_SRC_INTERFACE,
|
||||
aaa_group_prefix,
|
||||
bgp_multiprotocol_capabilities_abbreviations,
|
||||
convert_reload_cause,
|
||||
interface_autocomplete,
|
||||
interface_case_sensitivity,
|
||||
snmp_v3_prefix,
|
||||
|
@ -267,3 +268,28 @@ def test_snmp_v3_prefix_valid_input() -> None:
|
|||
assert snmp_v3_prefix("auth") == "v3Auth"
|
||||
assert snmp_v3_prefix("noauth") == "v3NoAuth"
|
||||
assert snmp_v3_prefix("priv") == "v3Priv"
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("str_input", "expected_output"),
|
||||
[
|
||||
pytest.param("Ztp", "System reloaded due to Zero Touch Provisioning", id="valid"),
|
||||
pytest.param("USER", "Reload requested by the user.", id="valid"),
|
||||
pytest.param("fpga", "Reload requested after FPGA upgrade", id="valid"),
|
||||
],
|
||||
)
|
||||
def test_convert_reload_cause(str_input: str, expected_output: str) -> None:
|
||||
"""Test convert_reload_cause."""
|
||||
assert convert_reload_cause(str_input) == expected_output
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("str_input"),
|
||||
[
|
||||
pytest.param("ztp2", id="invalid"),
|
||||
],
|
||||
)
|
||||
def test_invalid_convert_reload_cause(str_input: str) -> None:
|
||||
"""Test invalid convert_reload_cause."""
|
||||
with pytest.raises(ValueError, match=r"Invalid reload cause: 'ztp2' - expected causes are \['ZTP', 'USER', 'FPGA'\]"):
|
||||
convert_reload_cause(str_input)
|
||||
|
|
|
@ -429,29 +429,8 @@ REFRESH_PARAMS: list[ParameterSet] = [
|
|||
pytest.param(
|
||||
{},
|
||||
(
|
||||
{"return_value": False},
|
||||
{
|
||||
"return_value": {
|
||||
"mfgName": "Arista",
|
||||
"modelName": "DCS-7280CR3-32P4-F",
|
||||
"hardwareRevision": "11.00",
|
||||
"serialNumber": "JPE19500066",
|
||||
"systemMacAddress": "fc:bd:67:3d:13:c5",
|
||||
"hwMacAddress": "fc:bd:67:3d:13:c5",
|
||||
"configMacAddress": "00:00:00:00:00:00",
|
||||
"version": "4.31.1F-34361447.fraserrel (engineering build)",
|
||||
"architecture": "x86_64",
|
||||
"internalVersion": "4.31.1F-34361447.fraserrel",
|
||||
"internalBuildId": "4940d112-a2fc-4970-8b5a-a16cd03fd08c",
|
||||
"imageFormatVersion": "3.0",
|
||||
"imageOptimization": "Default",
|
||||
"bootupTimestamp": 1700729434.5892005,
|
||||
"uptime": 20666.78,
|
||||
"memTotal": 8099732,
|
||||
"memFree": 4989568,
|
||||
"isIntlVersion": False,
|
||||
}
|
||||
},
|
||||
{"side_effect": HTTPError(message="Unauthorized")},
|
||||
{},
|
||||
),
|
||||
{"is_online": False, "established": False, "hw_model": None},
|
||||
id="is not online",
|
||||
|
@ -613,6 +592,10 @@ class TestAntaDevice:
|
|||
"""
|
||||
assert device.cache_statistics == expected
|
||||
|
||||
def test_max_connections(self, device: AntaDevice) -> None:
|
||||
"""Test max_connections property."""
|
||||
assert device.max_connections is None
|
||||
|
||||
|
||||
class TestAsyncEOSDevice:
|
||||
"""Test for anta.device.AsyncEOSDevice."""
|
||||
|
@ -646,6 +629,16 @@ class TestAsyncEOSDevice:
|
|||
else:
|
||||
assert dev1 != dev2
|
||||
|
||||
def test_max_connections(self, async_device: AsyncEOSDevice) -> None:
|
||||
"""Test max_connections property."""
|
||||
# HTTPX uses a max_connections of 100 by default
|
||||
assert async_device.max_connections == 100
|
||||
|
||||
def test_max_connections_none(self, async_device: AsyncEOSDevice) -> None:
|
||||
"""Test max_connections property when not available in the session object."""
|
||||
with patch.object(async_device, "_session", None):
|
||||
assert async_device.max_connections is None
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("async_device", "patch_kwargs", "expected"),
|
||||
REFRESH_PARAMS,
|
||||
|
@ -653,9 +646,9 @@ class TestAsyncEOSDevice:
|
|||
)
|
||||
async def test_refresh(self, async_device: AsyncEOSDevice, patch_kwargs: list[dict[str, Any]], expected: dict[str, Any]) -> None:
|
||||
"""Test AsyncEOSDevice.refresh()."""
|
||||
with patch.object(async_device._session, "check_connection", **patch_kwargs[0]), patch.object(async_device._session, "cli", **patch_kwargs[1]):
|
||||
with patch.object(async_device._session, "check_api_endpoint", **patch_kwargs[0]), patch.object(async_device._session, "cli", **patch_kwargs[1]):
|
||||
await async_device.refresh()
|
||||
async_device._session.check_connection.assert_called_once() # type: ignore[attr-defined] # asynceapi.Device.check_connection is patched
|
||||
async_device._session.check_api_endpoint.assert_called_once() # type: ignore[attr-defined] # asynceapi.Device.check_api_endpoint is patched
|
||||
if expected["is_online"]:
|
||||
async_device._session.cli.assert_called_once() # type: ignore[attr-defined] # asynceapi.Device.cli is patched
|
||||
assert async_device.is_online == expected["is_online"]
|
||||
|
|
|
@ -298,82 +298,30 @@ class FakeTestWithMissingTest(AntaTest):
|
|||
commands: ClassVar[list[AntaCommand | AntaTemplate]] = []
|
||||
|
||||
|
||||
ANTATEST_DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "no input",
|
||||
"test": FakeTest,
|
||||
"inputs": None,
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "success"}},
|
||||
},
|
||||
{
|
||||
"name": "extra input",
|
||||
"test": FakeTest,
|
||||
ANTATEST_DATA: dict[tuple[type[AntaTest], str], Any] = {
|
||||
(FakeTest, "no input"): {"inputs": None, "expected": {"__init__": {"result": "unset"}, "test": {"result": "success"}}},
|
||||
(FakeTest, "extra input"): {
|
||||
"inputs": {"string": "culpa! veniam quas quas veniam molestias, esse"},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
"result": "error",
|
||||
"messages": ["Extra inputs are not permitted"],
|
||||
},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "error", "messages": ["Extra inputs are not permitted"]}, "test": {"result": "error"}},
|
||||
},
|
||||
{
|
||||
"name": "no input",
|
||||
"test": FakeTestWithInput,
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "error", "messages": ["Field required"]},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "wrong input type",
|
||||
"test": FakeTestWithInput,
|
||||
(FakeTestWithInput, "no input"): {"inputs": None, "expected": {"__init__": {"result": "error", "messages": ["Field required"]}, "test": {"result": "error"}}},
|
||||
(FakeTestWithInput, "wrong input type"): {
|
||||
"inputs": {"string": 1},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
"result": "error",
|
||||
"messages": ["Input should be a valid string"],
|
||||
},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "error", "messages": ["Input should be a valid string"]}, "test": {"result": "error"}},
|
||||
},
|
||||
{
|
||||
"name": "good input",
|
||||
"test": FakeTestWithInput,
|
||||
(FakeTestWithInput, "good input"): {
|
||||
"inputs": {"string": "culpa! veniam quas quas veniam molestias, esse"},
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {
|
||||
"result": "success",
|
||||
"messages": ["culpa! veniam quas quas veniam molestias, esse"],
|
||||
},
|
||||
},
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "success", "messages": ["culpa! veniam quas quas veniam molestias, esse"]}},
|
||||
},
|
||||
{
|
||||
"name": "good input",
|
||||
"test": FakeTestWithTemplate,
|
||||
(FakeTestWithTemplate, "good input"): {
|
||||
"inputs": {"interface": "Ethernet1"},
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {"result": "success", "messages": ["show interface Ethernet1"]},
|
||||
},
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "success", "messages": ["show interface Ethernet1"]}},
|
||||
},
|
||||
{
|
||||
"name": "wrong input type",
|
||||
"test": FakeTestWithTemplate,
|
||||
(FakeTestWithTemplate, "wrong input type"): {
|
||||
"inputs": {"interface": 1},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
"result": "error",
|
||||
"messages": ["Input should be a valid string"],
|
||||
},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "error", "messages": ["Input should be a valid string"]}, "test": {"result": "error"}},
|
||||
},
|
||||
{
|
||||
"name": "wrong render definition",
|
||||
"test": FakeTestWithTemplateNoRender,
|
||||
(FakeTestWithTemplateNoRender, "wrong render definition"): {
|
||||
"inputs": {"interface": "Ethernet1"},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
|
@ -383,9 +331,7 @@ ANTATEST_DATA: list[dict[str, Any]] = [
|
|||
"test": {"result": "error"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "AntaTemplateRenderError",
|
||||
"test": FakeTestWithTemplateBadRender1,
|
||||
(FakeTestWithTemplateBadRender1, "AntaTemplateRenderError"): {
|
||||
"inputs": {"interface": "Ethernet1"},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
|
@ -395,125 +341,57 @@ ANTATEST_DATA: list[dict[str, Any]] = [
|
|||
"test": {"result": "error"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "RuntimeError in render()",
|
||||
"test": FakeTestWithTemplateBadRender2,
|
||||
(FakeTestWithTemplateBadRender2, "RuntimeError in render()"): {
|
||||
"inputs": {"interface": "Ethernet1"},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
"result": "error",
|
||||
"messages": ["Exception in tests.units.test_models.FakeTestWithTemplateBadRender2.render(): RuntimeError"],
|
||||
},
|
||||
"__init__": {"result": "error", "messages": ["Exception in tests.units.test_models.FakeTestWithTemplateBadRender2.render(): RuntimeError"]},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "Extra template parameters in render()",
|
||||
"test": FakeTestWithTemplateBadRender3,
|
||||
(FakeTestWithTemplateBadRender3, "Extra template parameters in render()"): {
|
||||
"inputs": {"interface": "Ethernet1"},
|
||||
"expected": {
|
||||
"__init__": {
|
||||
"result": "error",
|
||||
"messages": [
|
||||
"Exception in tests.units.test_models.FakeTestWithTemplateBadRender3.render(): ValidationError: 1 validation error for AntaParams\n"
|
||||
"extra\n"
|
||||
"Exception in tests.units.test_models.FakeTestWithTemplateBadRender3.render(): ValidationError: 1 validation error for AntaParams\nextra\n"
|
||||
" Extra inputs are not permitted [type=extra_forbidden, input_value='blah', input_type=str]\n"
|
||||
],
|
||||
},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "Access undefined template param in test()",
|
||||
"test": FakeTestWithTemplateBadTest,
|
||||
(FakeTestWithTemplateBadTest, "Access undefined template param in test()"): {
|
||||
"inputs": {"interface": "Ethernet1"},
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {"result": "error", "messages": ["AttributeError: 'AntaParams' object has no attribute 'wrong_template_param'"]},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "unskip on platforms",
|
||||
"test": UnSkipOnPlatformTest,
|
||||
(UnSkipOnPlatformTest, "unskip on platforms"): {"inputs": None, "expected": {"__init__": {"result": "unset"}, "test": {"result": "success"}}},
|
||||
(SkipOnPlatformTest, "skip on platforms, unset"): {"inputs": None, "expected": {"__init__": {"result": "unset"}, "test": {"result": "skipped"}}},
|
||||
(SkipOnPlatformTestWithInput, "skip on platforms, not unset"): {
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {"result": "success"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "error", "messages": ["Field required"]}, "test": {"result": "error"}},
|
||||
},
|
||||
{
|
||||
"name": "skip on platforms, unset",
|
||||
"test": SkipOnPlatformTest,
|
||||
(DeprecatedTestWithoutNewTest, "deprecate test without new test"): {
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {"result": "skipped"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "success"}},
|
||||
},
|
||||
{
|
||||
"name": "skip on platforms, not unset",
|
||||
"test": SkipOnPlatformTestWithInput,
|
||||
(DeprecatedTestWithNewTest, "deprecate test with new test"): {"inputs": None, "expected": {"__init__": {"result": "unset"}, "test": {"result": "success"}}},
|
||||
(FakeTestWithFailedCommand, "failed command"): {
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "error", "messages": ["Field required"]},
|
||||
"test": {"result": "error"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "error", "messages": ["show version has failed: failed command"]}},
|
||||
},
|
||||
{
|
||||
"name": "deprecate test without new test",
|
||||
"test": DeprecatedTestWithoutNewTest,
|
||||
(FakeTestWithUnsupportedCommand, "unsupported command"): {
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {"result": "success"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "skipped", "messages": ["'show hardware counter drop' is not supported on pytest"]}},
|
||||
},
|
||||
{
|
||||
"name": "deprecate test with new test",
|
||||
"test": DeprecatedTestWithNewTest,
|
||||
(FakeTestWithKnownEOSError, "known EOS error command"): {
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {"result": "success"},
|
||||
},
|
||||
"expected": {"__init__": {"result": "unset"}, "test": {"result": "failure", "messages": ["BGP inactive"]}},
|
||||
},
|
||||
{
|
||||
"name": "failed command",
|
||||
"test": FakeTestWithFailedCommand,
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {
|
||||
"result": "error",
|
||||
"messages": ["show version has failed: failed command"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "unsupported command",
|
||||
"test": FakeTestWithUnsupportedCommand,
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {
|
||||
"result": "skipped",
|
||||
"messages": ["'show hardware counter drop' is not supported on pytest"],
|
||||
},
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "known EOS error command",
|
||||
"test": FakeTestWithKnownEOSError,
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"__init__": {"result": "unset"},
|
||||
"test": {
|
||||
"result": "failure",
|
||||
"messages": ["BGP inactive"],
|
||||
},
|
||||
},
|
||||
},
|
||||
]
|
||||
}
|
||||
|
||||
BLACKLIST_COMMANDS_PARAMS = ["reload", "reload now", "reload --force", "write", "wr mem", "write memory", "conf t", "configure terminal", "configure session"]
|
||||
|
||||
|
@ -597,18 +475,20 @@ class TestAntaTest:
|
|||
for result_msg, expected_msg in zip(test.result.messages, expected["messages"]): # NOTE: zip(strict=True) has been added in Python 3.10
|
||||
assert expected_msg in result_msg
|
||||
|
||||
@pytest.mark.parametrize("data", ANTATEST_DATA, ids=build_test_id)
|
||||
def test__init__(self, device: AntaDevice, data: dict[str, Any]) -> None:
|
||||
@pytest.mark.parametrize("data", ANTATEST_DATA.items(), ids=build_test_id)
|
||||
def test__init__(self, device: AntaDevice, data: tuple[tuple[type[AntaTest], str], Any]) -> None:
|
||||
"""Test the AntaTest constructor."""
|
||||
expected = data["expected"]["__init__"]
|
||||
test = data["test"](device, inputs=data["inputs"])
|
||||
(anta_test, test_data) = data
|
||||
expected = test_data["expected"]["__init__"]
|
||||
test = anta_test[0](device, inputs=test_data["inputs"])
|
||||
self._assert_test(test, expected)
|
||||
|
||||
@pytest.mark.parametrize("data", ANTATEST_DATA, ids=build_test_id)
|
||||
def test_test(self, device: AntaDevice, data: dict[str, Any]) -> None:
|
||||
@pytest.mark.parametrize("data", ANTATEST_DATA.items(), ids=build_test_id)
|
||||
def test_test(self, device: AntaDevice, data: tuple[tuple[type[AntaTest], str], Any]) -> None:
|
||||
"""Test the AntaTest.test method."""
|
||||
expected = data["expected"]["test"]
|
||||
test = data["test"](device, inputs=data["inputs"])
|
||||
(anta_test, test_data) = data
|
||||
expected = test_data["expected"]["test"]
|
||||
test = anta_test[0](device, inputs=test_data["inputs"])
|
||||
asyncio.run(test.test())
|
||||
self._assert_test(test, expected)
|
||||
|
||||
|
|
|
@ -7,18 +7,19 @@ from __future__ import annotations
|
|||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from pathlib import Path
|
||||
from typing import TYPE_CHECKING
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
|
||||
from anta.catalog import AntaCatalog
|
||||
from anta.inventory import AntaInventory
|
||||
from anta.result_manager import ResultManager
|
||||
from anta.runner import main, prepare_tests
|
||||
from anta.runner import prepare_tests
|
||||
|
||||
from .test_models import FakeTest, FakeTestWithMissingTest
|
||||
from .test_models import FakeTest
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from anta.inventory import AntaInventory
|
||||
|
||||
if os.name == "posix":
|
||||
# The function is not defined on non-POSIX system
|
||||
|
@ -30,47 +31,8 @@ DATA_DIR: Path = Path(__file__).parent.parent.resolve() / "data"
|
|||
FAKE_CATALOG: AntaCatalog = AntaCatalog.from_list([(FakeTest, None)])
|
||||
|
||||
|
||||
async def test_empty_tests(caplog: pytest.LogCaptureFixture, inventory: AntaInventory) -> None:
|
||||
"""Test that when the list of tests is empty, a log is raised."""
|
||||
caplog.set_level(logging.INFO)
|
||||
manager = ResultManager()
|
||||
await main(manager, inventory, AntaCatalog())
|
||||
|
||||
assert len(caplog.record_tuples) == 1
|
||||
assert "The list of tests is empty, exiting" in caplog.records[0].message
|
||||
|
||||
|
||||
async def test_empty_inventory(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test that when the Inventory is empty, a log is raised."""
|
||||
caplog.set_level(logging.INFO)
|
||||
manager = ResultManager()
|
||||
await main(manager, AntaInventory(), FAKE_CATALOG)
|
||||
assert len(caplog.record_tuples) == 3
|
||||
assert "The inventory is empty, exiting" in caplog.records[1].message
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
("inventory", "tags", "devices"),
|
||||
[
|
||||
pytest.param({"count": 1, "reachable": False}, None, None, id="not-reachable"),
|
||||
pytest.param({"filename": "test_inventory_with_tags.yml", "reachable": False}, {"leaf"}, None, id="not-reachable-with-tag"),
|
||||
pytest.param({"count": 1, "reachable": True}, {"invalid-tag"}, None, id="reachable-with-invalid-tag"),
|
||||
pytest.param({"filename": "test_inventory_with_tags.yml", "reachable": True}, None, {"invalid-device"}, id="reachable-with-invalid-device"),
|
||||
pytest.param({"filename": "test_inventory_with_tags.yml", "reachable": False}, None, {"leaf1"}, id="not-reachable-with-device"),
|
||||
pytest.param({"filename": "test_inventory_with_tags.yml", "reachable": False}, {"leaf"}, {"leaf1"}, id="not-reachable-with-device-and-tag"),
|
||||
pytest.param({"filename": "test_inventory_with_tags.yml", "reachable": False}, {"invalid"}, {"invalid-device"}, id="reachable-with-invalid-tag-and-device"),
|
||||
],
|
||||
indirect=["inventory"],
|
||||
)
|
||||
async def test_no_selected_device(caplog: pytest.LogCaptureFixture, inventory: AntaInventory, tags: set[str], devices: set[str]) -> None:
|
||||
"""Test that when the list of established devices is empty a log is raised."""
|
||||
caplog.set_level(logging.WARNING)
|
||||
manager = ResultManager()
|
||||
await main(manager, inventory, FAKE_CATALOG, tags=tags, devices=devices)
|
||||
msg = f"No reachable device {f'matching the tags {tags} ' if tags else ''}was found.{f' Selected devices: {devices} ' if devices is not None else ''}"
|
||||
assert msg in caplog.messages
|
||||
|
||||
|
||||
# TODO: Remove this in ANTA v2.0.0
|
||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Cannot run this test on Windows")
|
||||
def test_adjust_rlimit_nofile_valid_env(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test adjust_rlimit_nofile with valid environment variables."""
|
||||
|
@ -104,9 +66,11 @@ def test_adjust_rlimit_nofile_valid_env(caplog: pytest.LogCaptureFixture) -> Non
|
|||
setrlimit_mock.assert_called_once_with(resource.RLIMIT_NOFILE, (20480, 1048576))
|
||||
|
||||
|
||||
# TODO: Remove this in ANTA v2.0.0
|
||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Cannot run this test on Windows")
|
||||
def test_adjust_rlimit_nofile_invalid_env(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test adjust_rlimit_nofile with valid environment variables."""
|
||||
"""Test adjust_rlimit_nofile with invalid environment variables."""
|
||||
with (
|
||||
caplog.at_level(logging.DEBUG),
|
||||
patch.dict("os.environ", {"ANTA_NOFILE": "invalid"}),
|
||||
|
@ -138,31 +102,42 @@ def test_adjust_rlimit_nofile_invalid_env(caplog: pytest.LogCaptureFixture) -> N
|
|||
setrlimit_mock.assert_called_once_with(resource.RLIMIT_NOFILE, (16384, 1048576))
|
||||
|
||||
|
||||
@pytest.mark.skipif(os.name == "posix", reason="Run this test on Windows only")
|
||||
async def test_check_runner_log_for_windows(caplog: pytest.LogCaptureFixture, inventory: AntaInventory) -> None:
|
||||
"""Test log output for Windows host regarding rlimit."""
|
||||
caplog.set_level(logging.INFO)
|
||||
manager = ResultManager()
|
||||
# Using dry-run to shorten the test
|
||||
await main(manager, inventory, FAKE_CATALOG, dry_run=True)
|
||||
assert "Running on a non-POSIX system, cannot adjust the maximum number of file descriptors." in caplog.records[-3].message
|
||||
|
||||
|
||||
# We could instead merge multiple coverage report together but that requires more work than just this.
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Fake non-posix for coverage")
|
||||
async def test_check_runner_log_for_windows_fake(caplog: pytest.LogCaptureFixture, inventory: AntaInventory) -> None:
|
||||
"""Test log output for Windows host regarding rlimit."""
|
||||
with patch("os.name", new="win32"):
|
||||
del sys.modules["anta.runner"]
|
||||
from anta.runner import main # pylint: disable=W0621
|
||||
|
||||
caplog.set_level(logging.INFO)
|
||||
manager = ResultManager()
|
||||
# Using dry-run to shorten the test
|
||||
await main(manager, inventory, FAKE_CATALOG, dry_run=True)
|
||||
assert "Running on a non-POSIX system, cannot adjust the maximum number of file descriptors." in caplog.records[-3].message
|
||||
# TODO: Remove this in ANTA v2.0.0
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Cannot run this test on Windows")
|
||||
def test_adjust_rlimit_nofile_value_error(caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test adjust_rlimit_nofile with invalid environment variables."""
|
||||
with (
|
||||
caplog.at_level(logging.DEBUG),
|
||||
patch.dict("os.environ", {"ANTA_NOFILE": "666"}),
|
||||
patch("anta.runner.resource.getrlimit") as getrlimit_mock,
|
||||
patch("anta.runner.resource.setrlimit") as setrlimit_mock,
|
||||
):
|
||||
# Simulate the default system limits
|
||||
system_limits = (8192, 1048576)
|
||||
|
||||
# Setup getrlimit mock return value
|
||||
getrlimit_mock.return_value = system_limits
|
||||
|
||||
# Simulate setrlimit behavior raising ValueError
|
||||
def side_effect_setrlimit(_resource_id: int, _limits: tuple[int, int]) -> None:
|
||||
msg = "not allowed to raise maximum limit"
|
||||
raise ValueError(msg)
|
||||
|
||||
setrlimit_mock.side_effect = side_effect_setrlimit
|
||||
|
||||
result = adjust_rlimit_nofile()
|
||||
|
||||
# Assert the limits were *NOT* updated as expected
|
||||
assert result == system_limits
|
||||
assert "Initial limit numbers for open file descriptors for the current ANTA process: Soft Limit: 8192 | Hard Limit: 1048576" in caplog.text
|
||||
assert caplog.records[-1].levelname == "WARNING"
|
||||
assert "Failed to set soft limit for open file descriptors for the current ANTA process" in caplog.records[-1].getMessage()
|
||||
|
||||
setrlimit_mock.assert_called_once_with(resource.RLIMIT_NOFILE, (666, 1048576))
|
||||
|
||||
|
||||
# TODO: Remove this in ANTA v2.0.0
|
||||
@pytest.mark.filterwarnings("ignore::DeprecationWarning")
|
||||
@pytest.mark.parametrize(
|
||||
("inventory", "tags", "tests", "devices_count", "tests_count"),
|
||||
[
|
||||
|
@ -190,29 +165,3 @@ async def test_prepare_tests(
|
|||
assert selected_tests is not None
|
||||
assert len(selected_tests) == devices_count
|
||||
assert sum(len(tests) for tests in selected_tests.values()) == tests_count
|
||||
|
||||
|
||||
async def test_dry_run(caplog: pytest.LogCaptureFixture, inventory: AntaInventory) -> None:
|
||||
"""Test that when dry_run is True, no tests are run."""
|
||||
caplog.set_level(logging.INFO)
|
||||
manager = ResultManager()
|
||||
await main(manager, inventory, FAKE_CATALOG, dry_run=True)
|
||||
assert "Dry-run mode, exiting before running the tests." in caplog.records[-1].message
|
||||
|
||||
|
||||
async def test_cannot_create_test(caplog: pytest.LogCaptureFixture, inventory: AntaInventory) -> None:
|
||||
"""Test that when an Exception is raised during test instantiation, it is caught and a log is raised."""
|
||||
caplog.set_level(logging.CRITICAL)
|
||||
manager = ResultManager()
|
||||
catalog = AntaCatalog.from_list([(FakeTestWithMissingTest, None)]) # type: ignore[type-abstract]
|
||||
await main(manager, inventory, catalog)
|
||||
msg = (
|
||||
"There is an error when creating test tests.units.test_models.FakeTestWithMissingTest.\nIf this is not a custom test implementation: "
|
||||
"Please reach out to the maintainer team or open an issue on Github: https://github.com/aristanetworks/anta.\nTypeError: "
|
||||
)
|
||||
msg += (
|
||||
"Can't instantiate abstract class FakeTestWithMissingTest without an implementation for abstract method 'test'"
|
||||
if sys.version_info >= (3, 12)
|
||||
else "Can't instantiate abstract class FakeTestWithMissingTest with abstract method test"
|
||||
)
|
||||
assert msg in caplog.messages
|
||||
|
|
126
tests/units/test_settings.py
Normal file
126
tests/units/test_settings.py
Normal file
|
@ -0,0 +1,126 @@
|
|||
# Copyright (c) 2023-2025 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Unit tests for the anta.settings module."""
|
||||
|
||||
from __future__ import annotations
|
||||
|
||||
import logging
|
||||
import os
|
||||
import sys
|
||||
from unittest.mock import patch
|
||||
|
||||
import pytest
|
||||
from pydantic import ValidationError
|
||||
|
||||
from anta.settings import DEFAULT_MAX_CONCURRENCY, DEFAULT_NOFILE, AntaRunnerSettings
|
||||
|
||||
if os.name == "posix":
|
||||
# The function is not defined on non-POSIX system
|
||||
import resource
|
||||
|
||||
|
||||
class TestAntaRunnerSettings:
|
||||
"""Tests for the AntaRunnerSettings class."""
|
||||
|
||||
def test_defaults(self, setenvvar: pytest.MonkeyPatch) -> None:
|
||||
"""Test defaults for ANTA runner settings."""
|
||||
settings = AntaRunnerSettings()
|
||||
assert settings.nofile == DEFAULT_NOFILE
|
||||
assert settings.max_concurrency == DEFAULT_MAX_CONCURRENCY
|
||||
|
||||
def test_env_var(self, setenvvar: pytest.MonkeyPatch) -> None:
|
||||
"""Test setting different ANTA runner settings."""
|
||||
setenvvar.setenv("ANTA_NOFILE", "20480")
|
||||
settings = AntaRunnerSettings()
|
||||
assert settings.nofile == 20480
|
||||
assert settings.max_concurrency == DEFAULT_MAX_CONCURRENCY
|
||||
|
||||
def test_validation(self, setenvvar: pytest.MonkeyPatch) -> None:
|
||||
"""Test validation of ANTA runner settings."""
|
||||
setenvvar.setenv("ANTA_NOFILE", "-1")
|
||||
with pytest.raises(ValidationError):
|
||||
AntaRunnerSettings()
|
||||
|
||||
setenvvar.setenv("ANTA_MAX_CONCURRENCY", "0")
|
||||
with pytest.raises(ValidationError):
|
||||
AntaRunnerSettings()
|
||||
|
||||
@pytest.mark.skipif(os.name == "posix", reason="Run this test on Windows only")
|
||||
def test_file_descriptor_limit_windows(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test file_descriptor_limit on Windows."""
|
||||
caplog.set_level(logging.INFO)
|
||||
settings = AntaRunnerSettings()
|
||||
assert settings.file_descriptor_limit == sys.maxsize
|
||||
assert "Running on a non-POSIX system, cannot adjust the maximum number of file descriptors." in caplog.text
|
||||
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Fake non-posix for coverage")
|
||||
async def test_file_descriptor_limit_fake_windows(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test file_descriptor_limit on fake Windows."""
|
||||
caplog.set_level(logging.INFO)
|
||||
with patch("os.name", new="win32"):
|
||||
settings = AntaRunnerSettings()
|
||||
assert settings.file_descriptor_limit == sys.maxsize
|
||||
assert "Running on a non-POSIX system, cannot adjust the maximum number of file descriptors." in caplog.records[0].message
|
||||
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Cannot run this test on Windows")
|
||||
def test_file_descriptor_limit_posix(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test file_descriptor_limit on POSIX systems."""
|
||||
with (
|
||||
caplog.at_level(logging.DEBUG),
|
||||
patch.dict("os.environ", {"ANTA_NOFILE": "20480"}),
|
||||
patch("resource.getrlimit") as getrlimit_mock,
|
||||
patch("resource.setrlimit") as setrlimit_mock,
|
||||
):
|
||||
# Simulate the default system limits
|
||||
system_limits = (8192, 1048576)
|
||||
|
||||
# Setup getrlimit mock return value
|
||||
getrlimit_mock.return_value = system_limits
|
||||
|
||||
# Simulate setrlimit behavior
|
||||
def side_effect_setrlimit(_resource_id: int, limits: tuple[int, int]) -> None:
|
||||
getrlimit_mock.return_value = (limits[0], limits[1])
|
||||
|
||||
setrlimit_mock.side_effect = side_effect_setrlimit
|
||||
|
||||
settings = AntaRunnerSettings()
|
||||
|
||||
# Assert the limits were updated as expected
|
||||
assert settings.file_descriptor_limit == 20480
|
||||
assert "Initial file descriptor limits for the current ANTA process: Soft Limit: 8192 | Hard Limit: 1048576" in caplog.text
|
||||
assert "Setting file descriptor soft limit to 20480" in caplog.text
|
||||
|
||||
setrlimit_mock.assert_called_once_with(resource.RLIMIT_NOFILE, (20480, 1048576)) # pylint: disable=possibly-used-before-assignment
|
||||
|
||||
@pytest.mark.skipif(os.name != "posix", reason="Cannot run this test on Windows")
|
||||
def test_file_descriptor_limit_value_error(self, caplog: pytest.LogCaptureFixture) -> None:
|
||||
"""Test file_descriptor_limit with invalid environment variables."""
|
||||
with (
|
||||
caplog.at_level(logging.DEBUG),
|
||||
patch.dict("os.environ", {"ANTA_NOFILE": "666"}),
|
||||
patch("resource.getrlimit") as getrlimit_mock,
|
||||
patch("resource.setrlimit") as setrlimit_mock,
|
||||
):
|
||||
# Simulate the default system limits
|
||||
system_limits = (32768, 131072)
|
||||
|
||||
# Setup getrlimit mock return value
|
||||
getrlimit_mock.return_value = system_limits
|
||||
|
||||
# Simulate setrlimit behavior raising ValueError
|
||||
def side_effect_setrlimit(_resource_id: int, _limits: tuple[int, int]) -> None:
|
||||
msg = "not allowed to raise maximum limit"
|
||||
raise ValueError(msg)
|
||||
|
||||
setrlimit_mock.side_effect = side_effect_setrlimit
|
||||
|
||||
settings = AntaRunnerSettings()
|
||||
|
||||
# Assert the limits were *NOT* updated as expected
|
||||
assert settings.file_descriptor_limit == 32768
|
||||
assert "Initial file descriptor limits for the current ANTA process: Soft Limit: 32768 | Hard Limit: 131072" in caplog.text
|
||||
assert caplog.records[-1].levelname == "WARNING"
|
||||
assert "Failed to set file descriptor soft limit for the current ANTA process" in caplog.records[-1].getMessage()
|
||||
|
||||
setrlimit_mock.assert_called_once_with(resource.RLIMIT_NOFILE, (666, 131072))
|
Loading…
Add table
Add a link
Reference in a new issue