Adding upstream version 0.13.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
c0ae77e0f6
commit
ecf5ca3300
272 changed files with 33172 additions and 0 deletions
7
tests/units/anta_tests/README.md
Normal file
7
tests/units/anta_tests/README.md
Normal file
|
@ -0,0 +1,7 @@
|
|||
<!--
|
||||
~ Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
~ Use of this source code is governed by the Apache License 2.0
|
||||
~ that can be found in the LICENSE file.
|
||||
-->
|
||||
|
||||
A guide explaining how to write the unit test can be found in the [contribution guide](../../../docs/contribution.md#unit-tests)
|
3
tests/units/anta_tests/__init__.py
Normal file
3
tests/units/anta_tests/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
3
tests/units/anta_tests/routing/__init__.py
Normal file
3
tests/units/anta_tests/routing/__init__.py
Normal file
|
@ -0,0 +1,3 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
3385
tests/units/anta_tests/routing/test_bgp.py
Normal file
3385
tests/units/anta_tests/routing/test_bgp.py
Normal file
File diff suppressed because it is too large
Load diff
230
tests/units/anta_tests/routing/test_generic.py
Normal file
230
tests/units/anta_tests/routing/test_generic.py
Normal file
|
@ -0,0 +1,230 @@
|
|||
# Copyright (c) 2023-2024 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.routing.generic.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.routing.generic import VerifyRoutingProtocolModel, VerifyRoutingTableEntry, VerifyRoutingTableSize
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRoutingProtocolModel,
|
||||
"eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "multi-agent", "operatingProtoModel": "multi-agent"}}],
|
||||
"inputs": {"model": "multi-agent"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-configured-model",
|
||||
"test": VerifyRoutingProtocolModel,
|
||||
"eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "ribd", "operatingProtoModel": "ribd"}}],
|
||||
"inputs": {"model": "multi-agent"},
|
||||
"expected": {"result": "failure", "messages": ["routing model is misconfigured: configured: ribd - operating: ribd - expected: multi-agent"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-mismatch-operating-model",
|
||||
"test": VerifyRoutingProtocolModel,
|
||||
"eos_data": [{"vrfs": {"default": {}}, "protoModelStatus": {"configuredProtoModel": "multi-agent", "operatingProtoModel": "ribd"}}],
|
||||
"inputs": {"model": "multi-agent"},
|
||||
"expected": {"result": "failure", "messages": ["routing model is misconfigured: configured: multi-agent - operating: ribd - expected: multi-agent"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRoutingTableSize,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
# Output truncated
|
||||
"maskLen": {"8": 2},
|
||||
"totalRoutes": 123,
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"minimum": 42, "maximum": 666},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyRoutingTableSize,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
# Output truncated
|
||||
"maskLen": {"8": 2},
|
||||
"totalRoutes": 1000,
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"minimum": 42, "maximum": 666},
|
||||
"expected": {"result": "failure", "messages": ["routing-table has 1000 routes and not between min (42) and maximum (666)"]},
|
||||
},
|
||||
{
|
||||
"name": "error-max-smaller-than-min",
|
||||
"test": VerifyRoutingTableSize,
|
||||
"eos_data": [{}],
|
||||
"inputs": {"minimum": 666, "maximum": 42},
|
||||
"expected": {
|
||||
"result": "error",
|
||||
"messages": ["Minimum 666 is greater than maximum 42"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routingDisabled": False,
|
||||
"allRoutesProgrammedHardware": True,
|
||||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {
|
||||
"10.1.0.1/32": {
|
||||
"hardwareProgrammed": True,
|
||||
"routeType": "eBGP",
|
||||
"routeLeaked": False,
|
||||
"kernelProgrammed": True,
|
||||
"routeAction": "forward",
|
||||
"directlyConnected": False,
|
||||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.4", "interface": "Ethernet1"}],
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routingDisabled": False,
|
||||
"allRoutesProgrammedHardware": True,
|
||||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {
|
||||
"10.1.0.2/32": {
|
||||
"hardwareProgrammed": True,
|
||||
"routeType": "eBGP",
|
||||
"routeLeaked": False,
|
||||
"kernelProgrammed": True,
|
||||
"routeAction": "forward",
|
||||
"directlyConnected": False,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-route",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routingDisabled": False,
|
||||
"allRoutesProgrammedHardware": True,
|
||||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routingDisabled": False,
|
||||
"allRoutesProgrammedHardware": True,
|
||||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {
|
||||
"10.1.0.2/32": {
|
||||
"hardwareProgrammed": True,
|
||||
"routeType": "eBGP",
|
||||
"routeLeaked": False,
|
||||
"kernelProgrammed": True,
|
||||
"routeAction": "forward",
|
||||
"directlyConnected": False,
|
||||
"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.1']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-route",
|
||||
"test": VerifyRoutingTableEntry,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routingDisabled": False,
|
||||
"allRoutesProgrammedHardware": True,
|
||||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {
|
||||
"10.1.0.1/32": {
|
||||
"hardwareProgrammed": True,
|
||||
"routeType": "eBGP",
|
||||
"routeLeaked": False,
|
||||
"kernelProgrammed": True,
|
||||
"routeAction": "forward",
|
||||
"directlyConnected": False,
|
||||
"preference": 20,
|
||||
"metric": 0,
|
||||
"vias": [{"nexthopAddr": "10.1.255.4", "interface": "Ethernet1"}],
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"routingDisabled": False,
|
||||
"allRoutesProgrammedHardware": True,
|
||||
"allRoutesProgrammedKernel": True,
|
||||
"defaultRouteState": "notSet",
|
||||
"routes": {
|
||||
"10.1.0.55/32": {
|
||||
"hardwareProgrammed": True,
|
||||
"routeType": "eBGP",
|
||||
"routeLeaked": False,
|
||||
"kernelProgrammed": True,
|
||||
"routeAction": "forward",
|
||||
"directlyConnected": False,
|
||||
"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']"]},
|
||||
},
|
||||
]
|
298
tests/units/anta_tests/routing/test_ospf.py
Normal file
298
tests/units/anta_tests/routing/test_ospf.py
Normal file
|
@ -0,0 +1,298 @@
|
|||
# Copyright (c) 2023-2024 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.routing.ospf.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.routing.ospf import VerifyOSPFNeighborCount, VerifyOSPFNeighborState
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "7.7.7.7",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
{
|
||||
"routerId": "9.9.9.9",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
"777": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "8.8.8.8",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "7.7.7.7",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "2-way",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
{
|
||||
"routerId": "9.9.9.9",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
"777": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "8.8.8.8",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "down",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Some neighbors are not correctly configured: [{'vrf': 'default', 'instance': '666', 'neighbor': '7.7.7.7', 'state': '2-way'},"
|
||||
" {'vrf': 'BLAH', 'instance': '777', 'neighbor': '8.8.8.8', 'state': 'down'}]."
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyOSPFNeighborState,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["no OSPF neighbor found"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "7.7.7.7",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
{
|
||||
"routerId": "9.9.9.9",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
"777": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "8.8.8.8",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "7.7.7.7",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {"result": "failure", "messages": ["device has 1 neighbors (expected 3)"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-good-number-wrong-state",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"instList": {
|
||||
"666": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "7.7.7.7",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "2-way",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
{
|
||||
"routerId": "9.9.9.9",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "full",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
},
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
"BLAH": {
|
||||
"instList": {
|
||||
"777": {
|
||||
"ospfNeighborEntries": [
|
||||
{
|
||||
"routerId": "8.8.8.8",
|
||||
"priority": 1,
|
||||
"drState": "DR",
|
||||
"interfaceName": "Ethernet1",
|
||||
"adjacencyState": "down",
|
||||
"inactivity": 1683298014.844345,
|
||||
"interfaceAddress": "10.3.0.1",
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Some neighbors are not correctly configured: [{'vrf': 'default', 'instance': '666', 'neighbor': '7.7.7.7', 'state': '2-way'},"
|
||||
" {'vrf': 'BLAH', 'instance': '777', 'neighbor': '8.8.8.8', 'state': 'down'}]."
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyOSPFNeighborCount,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {},
|
||||
}
|
||||
],
|
||||
"inputs": {"number": 3},
|
||||
"expected": {"result": "skipped", "messages": ["no OSPF neighbor found"]},
|
||||
},
|
||||
]
|
516
tests/units/anta_tests/test_aaa.py
Normal file
516
tests/units/anta_tests/test_aaa.py
Normal file
|
@ -0,0 +1,516 @@
|
|||
# Copyright (c) 2023-2024 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.aaa.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.aaa import (
|
||||
VerifyAcctConsoleMethods,
|
||||
VerifyAcctDefaultMethods,
|
||||
VerifyAuthenMethods,
|
||||
VerifyAuthzMethods,
|
||||
VerifyTacacsServerGroups,
|
||||
VerifyTacacsServers,
|
||||
VerifyTacacsSourceIntf,
|
||||
)
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=unused-import
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [],
|
||||
"groups": {},
|
||||
"srcIntf": {},
|
||||
}
|
||||
],
|
||||
"inputs": {"intf": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Source-interface Management0 is not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-intf",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
"eos_data": [
|
||||
{
|
||||
"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": ["Wrong source-interface configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifyTacacsSourceIntf,
|
||||
"eos_data": [
|
||||
{
|
||||
"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": ["Source-interface Management0 is not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTacacsServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-servers",
|
||||
"test": VerifyTacacsServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [],
|
||||
"groups": {},
|
||||
"srcIntf": {},
|
||||
}
|
||||
],
|
||||
"inputs": {"servers": ["10.22.10.91"], "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["No TACACS servers are configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyTacacsServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifyTacacsServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTacacsServerGroups,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-server-groups",
|
||||
"test": VerifyTacacsServerGroups,
|
||||
"eos_data": [
|
||||
{
|
||||
"tacacsServers": [],
|
||||
"groups": {},
|
||||
"srcIntf": {},
|
||||
}
|
||||
],
|
||||
"inputs": {"groups": ["GROUP1"]},
|
||||
"expected": {"result": "failure", "messages": ["No TACACS server group(s) are configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyTacacsServerGroups,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "success-login-enable",
|
||||
"test": VerifyAuthenMethods,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "success-dot1x",
|
||||
"test": VerifyAuthenMethods,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-login-console",
|
||||
"test": VerifyAuthenMethods,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-login-console",
|
||||
"test": VerifyAuthenMethods,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-login-default",
|
||||
"test": VerifyAuthenMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAuthzMethods,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-commands",
|
||||
"test": VerifyAuthzMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-exec",
|
||||
"test": VerifyAuthzMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "success-commands-exec-system",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "success-dot1x",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured-empty",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-matching",
|
||||
"test": VerifyAcctDefaultMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "success-commands-exec-system",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
"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": [], "consoleMethods": []}},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-dot1x",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
"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"],
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["dot1x"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
"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"],
|
||||
}
|
||||
},
|
||||
"dot1xAcctMethods": {"dot1x": {"defaultMethods": [], "consoleMethods": []}},
|
||||
}
|
||||
],
|
||||
"inputs": {"methods": ["tacacs+", "logging"], "types": ["commands", "exec", "system"]},
|
||||
"expected": {"result": "failure", "messages": ["AAA console accounting is not configured for ['commands']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured-empty",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-matching",
|
||||
"test": VerifyAcctConsoleMethods,
|
||||
"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"],
|
||||
}
|
||||
},
|
||||
"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']"]},
|
||||
},
|
||||
]
|
523
tests/units/anta_tests/test_bfd.py
Normal file
523
tests/units/anta_tests/test_bfd.py
Normal file
|
@ -0,0 +1,523 @@
|
|||
# Copyright (c) 2023-2024 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.bfd.py
|
||||
"""
|
||||
# pylint: disable=C0302
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
# pylint: disable=C0413
|
||||
# because of the patch above
|
||||
from anta.tests.bfd import VerifyBFDPeersHealth, VerifyBFDPeersIntervals, VerifyBFDSpecificPeers # noqa: E402
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"bfd_peers": [
|
||||
{"peer_address": "192.0.255.7", "vrf": "default", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1200000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 3,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"bfd_peers": [
|
||||
{"peer_address": "192.0.255.7", "vrf": "CS", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Following BFD peers are not configured or timers are not correct:\n"
|
||||
"{'192.0.255.7': {'CS': 'Not Configured'}, '192.0.255.70': {'MGMT': 'Not Configured'}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-timers",
|
||||
"test": VerifyBFDPeersIntervals,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.7": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 1300000,
|
||||
"operRxInterval": 1200000,
|
||||
"detectMult": 4,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.70": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"peerStatsDetail": {
|
||||
"operTxInterval": 120000,
|
||||
"operRxInterval": 120000,
|
||||
"detectMult": 5,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"bfd_peers": [
|
||||
{"peer_address": "192.0.255.7", "vrf": "default", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
{"peer_address": "192.0.255.70", "vrf": "MGMT", "tx_interval": 1200, "rx_interval": 1200, "multiplier": 3},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Following BFD peers are not configured or timers are not correct:\n"
|
||||
"{'192.0.255.7': {'default': {'tx_interval': 1300000, 'rx_interval': 1200000, 'multiplier': 4}}, "
|
||||
"'192.0.255.70': {'MGMT': {'tx_interval': 120000, 'rx_interval': 120000, 'multiplier': 5}}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDSpecificPeers,
|
||||
"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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bfd_peers": [{"peer_address": "192.0.255.7", "vrf": "default"}, {"peer_address": "192.0.255.70", "vrf": "MGMT"}]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyBFDSpecificPeers,
|
||||
"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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bfd_peers": [{"peer_address": "192.0.255.7", "vrf": "CS"}, {"peer_address": "192.0.255.70", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Following BFD peers are not configured, status is not up or remote disc is zero:\n"
|
||||
"{'192.0.255.7': {'CS': 'Not Configured'}, '192.0.255.70': {'MGMT': 'Not Configured'}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-session-down",
|
||||
"test": VerifyBFDSpecificPeers,
|
||||
"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,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"bfd_peers": [{"peer_address": "192.0.255.7", "vrf": "default"}, {"peer_address": "192.0.255.70", "vrf": "MGMT"}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Following BFD peers are not configured, status is not up or remote disc is zero:\n"
|
||||
"{'192.0.255.7': {'default': {'status': 'Down', 'remote_disc': 108328132}}, "
|
||||
"'192.0.255.70': {'MGMT': {'status': 'Down', 'remote_disc': 0}}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
"eos_data": [
|
||||
{
|
||||
"vrfs": {
|
||||
"default": {
|
||||
"ipv4Neighbors": {
|
||||
"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": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703667348.111288,
|
||||
},
|
||||
],
|
||||
"inputs": {"down_threshold": 2},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-peer",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
"eos_data": [
|
||||
{
|
||||
"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."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-session-down",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
"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": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
"MGMT": {
|
||||
"ipv4Neighbors": {
|
||||
"192.0.255.71": {
|
||||
"peerStats": {
|
||||
"": {
|
||||
"status": "down",
|
||||
"remoteDisc": 0,
|
||||
"lastDown": 1703657258.652725,
|
||||
"l3intf": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703658481.8778424,
|
||||
},
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Following BFD peers are not up:\n192.0.255.7 is down in default VRF with remote disc 0.\n192.0.255.71 is down in MGMT VRF with remote disc 0."
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-session-up-disc",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
"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",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703658481.8778424,
|
||||
},
|
||||
],
|
||||
"inputs": {},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Following BFD peers were down:\n192.0.255.7 in default VRF has remote disc 0.\n192.0.255.71 in default VRF has remote disc 0."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-last-down",
|
||||
"test": VerifyBFDPeersHealth,
|
||||
"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": "",
|
||||
}
|
||||
}
|
||||
},
|
||||
},
|
||||
"ipv6Neighbors": {},
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1703667348.111288,
|
||||
},
|
||||
],
|
||||
"inputs": {"down_threshold": 4},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Following BFD peers were down:\n192.0.255.7 in default VRF was down 3 hours ago.\n"
|
||||
"192.0.255.71 in default VRF was down 3 hours ago.\n192.0.255.17 in default VRF was down 3 hours ago."
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
35
tests/units/anta_tests/test_configuration.py
Normal file
35
tests/units/anta_tests/test_configuration.py
Normal file
|
@ -0,0 +1,35 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Data for testing anta.tests.configuration"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.configuration import VerifyRunningConfigDiffs, VerifyZeroTouch
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyZeroTouch,
|
||||
"eos_data": [{"mode": "disabled"}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyZeroTouch,
|
||||
"eos_data": [{"mode": "enabled"}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "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"]}},
|
||||
]
|
369
tests/units/anta_tests/test_connectivity.py
Normal file
369
tests/units/anta_tests/test_connectivity.py
Normal file
|
@ -0,0 +1,369 @@
|
|||
# Copyright (c) 2023-2024 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.connectivity.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.connectivity import VerifyLLDPNeighbors, VerifyReachability
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success-ip",
|
||||
"test": VerifyReachability,
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-interface",
|
||||
"test": VerifyReachability,
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-repeat",
|
||||
"test": VerifyReachability,
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-ip",
|
||||
"test": VerifyReachability,
|
||||
"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
|
||||
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["Connectivity test failed for the following source-destination pairs: [('10.0.0.5', '10.0.0.11')]"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-interface",
|
||||
"test": VerifyReachability,
|
||||
"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
|
||||
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
{
|
||||
"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
|
||||
|
||||
"""
|
||||
]
|
||||
},
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["Connectivity test failed for the following source-destination pairs: [('Management0', '10.0.0.11')]"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
]
|
||||
},
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
"Ethernet1": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73a0.fc18",
|
||||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73f7.d138",
|
||||
"systemName": "DC1-SPINE2",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet2",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-port-not-configured",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
]
|
||||
},
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
"Ethernet1": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73a0.fc18",
|
||||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["The following port(s) have issues: {'port_not_configured': ['Ethernet2']}"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-neighbor",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
]
|
||||
},
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
"Ethernet1": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73a0.fc18",
|
||||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {"lldpNeighborInfo": []},
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["The following port(s) have issues: {'no_lldp_neighbor': ['Ethernet2']}"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-neighbor",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
"inputs": {
|
||||
"neighbors": [
|
||||
{"port": "Ethernet1", "neighbor_device": "DC1-SPINE1", "neighbor_port": "Ethernet1"},
|
||||
{"port": "Ethernet2", "neighbor_device": "DC1-SPINE2", "neighbor_port": "Ethernet1"},
|
||||
]
|
||||
},
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
"Ethernet1": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73a0.fc18",
|
||||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet1"',
|
||||
"interfaceId_v2": "Ethernet1",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73f7.d138",
|
||||
"systemName": "DC1-SPINE2",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet2"',
|
||||
"interfaceId_v2": "Ethernet2",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet2",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {"result": "failure", "messages": ["The following port(s) have issues: {'wrong_lldp_neighbor': ['Ethernet2']}"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-multiple",
|
||||
"test": VerifyLLDPNeighbors,
|
||||
"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"},
|
||||
]
|
||||
},
|
||||
"eos_data": [
|
||||
{
|
||||
"lldpNeighbors": {
|
||||
"Ethernet1": {
|
||||
"lldpNeighborInfo": [
|
||||
{
|
||||
"chassisIdType": "macAddress",
|
||||
"chassisId": "001c.73a0.fc18",
|
||||
"systemName": "DC1-SPINE1",
|
||||
"neighborInterfaceInfo": {
|
||||
"interfaceIdType": "interfaceName",
|
||||
"interfaceId": '"Ethernet2"',
|
||||
"interfaceId_v2": "Ethernet2",
|
||||
"interfaceDescription": "P2P_LINK_TO_DC1-LEAF1A_Ethernet1",
|
||||
},
|
||||
}
|
||||
]
|
||||
},
|
||||
"Ethernet2": {"lldpNeighborInfo": []},
|
||||
}
|
||||
}
|
||||
],
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"The following port(s) have issues: {'wrong_lldp_neighbor': ['Ethernet1'], 'no_lldp_neighbor': ['Ethernet2'], 'port_not_configured': ['Ethernet3']}"
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
291
tests/units/anta_tests/test_field_notices.py
Normal file
291
tests/units/anta_tests/test_field_notices.py
Normal file
|
@ -0,0 +1,291 @@
|
|||
# Copyright (c) 2023-2024 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 inputs for anta.tests.field_notices"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.field_notices import VerifyFieldNotice44Resolution, VerifyFieldNotice72Resolution
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-4.0",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"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)"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-4.1",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"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)"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-6.0",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"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)"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-6.1",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "DCS-7280QRA-C36S",
|
||||
"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)"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-model",
|
||||
"test": VerifyFieldNotice44Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1109144.35,
|
||||
"modelName": "vEOS-lab",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["device is not impacted by FN044"]},
|
||||
},
|
||||
{
|
||||
"name": "success-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JPE2130000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "success-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "success-K-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JPE2133000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "success-K-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["FN72 is mitigated"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-Serial",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "BAN2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "7"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-Platform",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-range-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JPE2131000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "skipped-range-K-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JAS2041000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Device not exposed"]},
|
||||
},
|
||||
{
|
||||
"name": "failed-JPE",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3K-48YC8",
|
||||
"serialNumber": "JPE2133000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device is exposed to FN72"]},
|
||||
},
|
||||
{
|
||||
"name": "failed-JAS",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm1", "version": "5"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device is exposed to FN72"]},
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"test": VerifyFieldNotice72Resolution,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "DCS-7280SR3-48YC8",
|
||||
"serialNumber": "JAS2040000",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "FixedSystemvrm2", "version": "5"}],
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "error", "messages": ["Error in running test - FixedSystemvrm1 not found"]},
|
||||
},
|
||||
]
|
47
tests/units/anta_tests/test_greent.py
Normal file
47
tests/units/anta_tests/test_greent.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Data for testing anta.tests.configuration"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.greent import VerifyGreenT, VerifyGreenTCounters
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyGreenTCounters,
|
||||
"eos_data": [{"sampleRcvd": 0, "sampleDiscarded": 0, "multiDstSampleRcvd": 0, "grePktSent": 1, "sampleSent": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyGreenTCounters,
|
||||
"eos_data": [{"sampleRcvd": 0, "sampleDiscarded": 0, "multiDstSampleRcvd": 0, "grePktSent": 0, "sampleSent": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure"},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyGreenT,
|
||||
"eos_data": [{"sampleRcvd": 0, "sampleDiscarded": 0, "multiDstSampleRcvd": 0, "grePktSent": 1, "sampleSent": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyGreenT,
|
||||
"eos_data": [
|
||||
{
|
||||
"profiles": {
|
||||
"default": {"interfaces": [], "appliedInterfaces": [], "samplePolicy": "default", "failures": {}, "appliedInterfaces6": [], "failures6": {}},
|
||||
"testProfile": {"interfaces": [], "appliedInterfaces": [], "samplePolicy": "default", "failures": {}, "appliedInterfaces6": [], "failures6": {}},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure"},
|
||||
},
|
||||
]
|
918
tests/units/anta_tests/test_hardware.py
Normal file
918
tests/units/anta_tests/test_hardware.py
Normal file
|
@ -0,0 +1,918 @@
|
|||
# Copyright (c) 2023-2024 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 inputs for anta.tests.hardware"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.hardware import (
|
||||
VerifyAdverseDrops,
|
||||
VerifyEnvironmentCooling,
|
||||
VerifyEnvironmentPower,
|
||||
VerifyEnvironmentSystemCooling,
|
||||
VerifyTemperature,
|
||||
VerifyTransceiversManufacturers,
|
||||
VerifyTransceiversTemperature,
|
||||
)
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTransceiversManufacturers,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTransceiversManufacturers,
|
||||
"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", "messages": ["Some transceivers are from unapproved manufacturers: {'1': 'Arista Networks', '2': 'Arista Networks'}"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTemperature,
|
||||
"eos_data": [
|
||||
{
|
||||
"powercycleOnOverheat": "False",
|
||||
"ambientThreshold": 45,
|
||||
"cardSlots": [],
|
||||
"shutdownOnOverheat": "True",
|
||||
"systemStatus": "temperatureOk",
|
||||
"recoveryModeOnOverheat": "recoveryModeNA",
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTemperature,
|
||||
"eos_data": [
|
||||
{
|
||||
"powercycleOnOverheat": "False",
|
||||
"ambientThreshold": 45,
|
||||
"cardSlots": [],
|
||||
"shutdownOnOverheat": "True",
|
||||
"systemStatus": "temperatureKO",
|
||||
"recoveryModeOnOverheat": "recoveryModeNA",
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device temperature exceeds acceptable limits. Current system status: 'temperatureKO'"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTransceiversTemperature,
|
||||
"eos_data": [
|
||||
{
|
||||
"tempSensors": [
|
||||
{
|
||||
"maxTemperature": 25.03125,
|
||||
"maxTemperatureLastChange": 1682509618.2227979,
|
||||
"hwStatus": "ok",
|
||||
"alertCount": 0,
|
||||
"description": "Xcvr54 temp sensor",
|
||||
"overheatThreshold": 70.0,
|
||||
"criticalThreshold": 70.0,
|
||||
"inAlertState": False,
|
||||
"targetTemperature": 62.0,
|
||||
"relPos": "54",
|
||||
"currentTemperature": 24.171875,
|
||||
"setPointTemperature": 61.8,
|
||||
"pidDriverCount": 0,
|
||||
"isPidDriver": False,
|
||||
"name": "DomTemperatureSensor54",
|
||||
}
|
||||
],
|
||||
"cardSlots": [],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-hwStatus",
|
||||
"test": VerifyTransceiversTemperature,
|
||||
"eos_data": [
|
||||
{
|
||||
"tempSensors": [
|
||||
{
|
||||
"maxTemperature": 25.03125,
|
||||
"maxTemperatureLastChange": 1682509618.2227979,
|
||||
"hwStatus": "ko",
|
||||
"alertCount": 0,
|
||||
"description": "Xcvr54 temp sensor",
|
||||
"overheatThreshold": 70.0,
|
||||
"criticalThreshold": 70.0,
|
||||
"inAlertState": False,
|
||||
"targetTemperature": 62.0,
|
||||
"relPos": "54",
|
||||
"currentTemperature": 24.171875,
|
||||
"setPointTemperature": 61.8,
|
||||
"pidDriverCount": 0,
|
||||
"isPidDriver": False,
|
||||
"name": "DomTemperatureSensor54",
|
||||
}
|
||||
],
|
||||
"cardSlots": [],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"The following sensors are operating outside the acceptable temperature range or have raised alerts: "
|
||||
"{'DomTemperatureSensor54': "
|
||||
"{'hwStatus': 'ko', 'alertCount': 0}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-alertCount",
|
||||
"test": VerifyTransceiversTemperature,
|
||||
"eos_data": [
|
||||
{
|
||||
"tempSensors": [
|
||||
{
|
||||
"maxTemperature": 25.03125,
|
||||
"maxTemperatureLastChange": 1682509618.2227979,
|
||||
"hwStatus": "ok",
|
||||
"alertCount": 1,
|
||||
"description": "Xcvr54 temp sensor",
|
||||
"overheatThreshold": 70.0,
|
||||
"criticalThreshold": 70.0,
|
||||
"inAlertState": False,
|
||||
"targetTemperature": 62.0,
|
||||
"relPos": "54",
|
||||
"currentTemperature": 24.171875,
|
||||
"setPointTemperature": 61.8,
|
||||
"pidDriverCount": 0,
|
||||
"isPidDriver": False,
|
||||
"name": "DomTemperatureSensor54",
|
||||
}
|
||||
],
|
||||
"cardSlots": [],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"The following sensors are operating outside the acceptable temperature range or have raised alerts: "
|
||||
"{'DomTemperatureSensor54': "
|
||||
"{'hwStatus': 'ok', 'alertCount': 1}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEnvironmentSystemCooling,
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
"numCoolingZones": [],
|
||||
"coolingMode": "automatic",
|
||||
"ambientTemperature": 24.5,
|
||||
"shutdownOnInsufficientFans": True,
|
||||
"airflowDirection": "frontToBackAirflow",
|
||||
"overrideFanSpeed": 0,
|
||||
"powerSupplySlots": [],
|
||||
"fanTraySlots": [],
|
||||
"minFanSpeed": 0,
|
||||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingOk",
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEnvironmentSystemCooling,
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
"numCoolingZones": [],
|
||||
"coolingMode": "automatic",
|
||||
"ambientTemperature": 24.5,
|
||||
"shutdownOnInsufficientFans": True,
|
||||
"airflowDirection": "frontToBackAirflow",
|
||||
"overrideFanSpeed": 0,
|
||||
"powerSupplySlots": [],
|
||||
"fanTraySlots": [],
|
||||
"minFanSpeed": 0,
|
||||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingKo",
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device system cooling is not OK: 'coolingKo'"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
"numCoolingZones": [],
|
||||
"coolingMode": "automatic",
|
||||
"ambientTemperature": 24.5,
|
||||
"shutdownOnInsufficientFans": True,
|
||||
"airflowDirection": "frontToBackAirflow",
|
||||
"overrideFanSpeed": 0,
|
||||
"powerSupplySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498937.0240965,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499033.0403435,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498935.9121106,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499092.4665174,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
},
|
||||
],
|
||||
"fanTraySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303148,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0139885,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 29,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9304729,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498939.9329433,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9383528,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140095,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303904,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140295,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
},
|
||||
],
|
||||
"minFanSpeed": 0,
|
||||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingOk",
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-additional-states",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
"numCoolingZones": [],
|
||||
"coolingMode": "automatic",
|
||||
"ambientTemperature": 24.5,
|
||||
"shutdownOnInsufficientFans": True,
|
||||
"airflowDirection": "frontToBackAirflow",
|
||||
"overrideFanSpeed": 0,
|
||||
"powerSupplySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498937.0240965,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499033.0403435,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "Not Inserted",
|
||||
"uptime": 1682498935.9121106,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499092.4665174,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
},
|
||||
],
|
||||
"fanTraySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303148,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0139885,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 29,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9304729,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498939.9329433,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9383528,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140095,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303904,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140295,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
},
|
||||
],
|
||||
"minFanSpeed": 0,
|
||||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "coolingOk",
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-fan-tray",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
"numCoolingZones": [],
|
||||
"coolingMode": "automatic",
|
||||
"ambientTemperature": 24.5,
|
||||
"shutdownOnInsufficientFans": True,
|
||||
"airflowDirection": "frontToBackAirflow",
|
||||
"overrideFanSpeed": 0,
|
||||
"powerSupplySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498937.0240965,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499033.0403435,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498935.9121106,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499092.4665174,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
},
|
||||
],
|
||||
"fanTraySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "down",
|
||||
"uptime": 1682498923.9303148,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0139885,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 29,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9304729,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498939.9329433,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "Not Inserted",
|
||||
"uptime": 1682498923.9383528,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140095,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303904,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140295,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
},
|
||||
],
|
||||
"minFanSpeed": 0,
|
||||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "CoolingKo",
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"expected": {"result": "failure", "messages": ["Fan 1/1 on Fan Tray 1 is: 'down'"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-power-supply",
|
||||
"test": VerifyEnvironmentCooling,
|
||||
"eos_data": [
|
||||
{
|
||||
"defaultZones": False,
|
||||
"numCoolingZones": [],
|
||||
"coolingMode": "automatic",
|
||||
"ambientTemperature": 24.5,
|
||||
"shutdownOnInsufficientFans": True,
|
||||
"airflowDirection": "frontToBackAirflow",
|
||||
"overrideFanSpeed": 0,
|
||||
"powerSupplySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "down",
|
||||
"uptime": 1682498937.0240965,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499033.0403435,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498935.9121106,
|
||||
"maxSpeed": 23000,
|
||||
"lastSpeedStableChangeTime": 1682499092.4665174,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 33,
|
||||
"speedHwOverride": True,
|
||||
"speedStable": True,
|
||||
"label": "PowerSupply2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "PowerSupply2",
|
||||
},
|
||||
],
|
||||
"fanTraySlots": [
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303148,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0139885,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 29,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "1/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "1",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9304729,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498939.9329433,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "2/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "2",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "Not Inserted",
|
||||
"uptime": 1682498923.9383528,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140095,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "3/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "3",
|
||||
},
|
||||
{
|
||||
"status": "ok",
|
||||
"fans": [
|
||||
{
|
||||
"status": "ok",
|
||||
"uptime": 1682498923.9303904,
|
||||
"maxSpeed": 17500,
|
||||
"lastSpeedStableChangeTime": 1682498975.0140295,
|
||||
"configuredSpeed": 30,
|
||||
"actualSpeed": 30,
|
||||
"speedHwOverride": False,
|
||||
"speedStable": True,
|
||||
"label": "4/1",
|
||||
}
|
||||
],
|
||||
"speed": 30,
|
||||
"label": "4",
|
||||
},
|
||||
],
|
||||
"minFanSpeed": 0,
|
||||
"currentZones": 1,
|
||||
"configuredZones": 0,
|
||||
"systemStatus": "CoolingKo",
|
||||
}
|
||||
],
|
||||
"inputs": {"states": ["ok", "Not Inserted"]},
|
||||
"expected": {"result": "failure", "messages": ["Fan PowerSupply1/1 on PowerSupply PowerSupply1 is: 'down'"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"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": "ok",
|
||||
"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": "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,
|
||||
"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": ["The following power supplies status are not in the accepted states list: {'1': {'state': 'powerLoss'}}"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAdverseDrops,
|
||||
"eos_data": [{"totalAdverseDrops": 0}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyAdverseDrops,
|
||||
"eos_data": [{"totalAdverseDrops": 10}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device totalAdverseDrops counter is: '10'"]},
|
||||
},
|
||||
]
|
1411
tests/units/anta_tests/test_interfaces.py
Normal file
1411
tests/units/anta_tests/test_interfaces.py
Normal file
File diff suppressed because it is too large
Load diff
27
tests/units/anta_tests/test_lanz.py
Normal file
27
tests/units/anta_tests/test_lanz.py
Normal file
|
@ -0,0 +1,27 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Data for testing anta.tests.configuration"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.lanz import VerifyLANZ
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLANZ,
|
||||
"eos_data": [{"lanzEnabled": True}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success", "messages": ["LANZ is enabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLANZ,
|
||||
"eos_data": [{"lanzEnabled": False}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["LANZ is not enabled"]},
|
||||
},
|
||||
]
|
254
tests/units/anta_tests/test_logging.py
Normal file
254
tests/units/anta_tests/test_logging.py
Normal file
|
@ -0,0 +1,254 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Data for testing anta.tests.logging"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.logging import (
|
||||
VerifyLoggingAccounting,
|
||||
VerifyLoggingErrors,
|
||||
VerifyLoggingHostname,
|
||||
VerifyLoggingHosts,
|
||||
VerifyLoggingLogsGeneration,
|
||||
VerifyLoggingPersistent,
|
||||
VerifyLoggingSourceIntf,
|
||||
VerifyLoggingTimestamp,
|
||||
)
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingPersistent,
|
||||
"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)
|
||||
|
||||
""",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifyLoggingPersistent,
|
||||
"eos_data": [
|
||||
"Persistent logging: disabled\n",
|
||||
"""Directory of flash:/persist/messages
|
||||
|
||||
-rw- 0 Apr 13 16:29 messages
|
||||
|
||||
33214693376 bytes total (10082168832 bytes free)
|
||||
|
||||
""",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Persistent logging is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-saved",
|
||||
"test": VerifyLoggingPersistent,
|
||||
"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)
|
||||
|
||||
""",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["No persistent logs are saved in flash"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingSourceIntf,
|
||||
"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
|
||||
|
||||
"""
|
||||
],
|
||||
"inputs": {"interface": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-intf",
|
||||
"test": VerifyLoggingSourceIntf,
|
||||
"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
|
||||
|
||||
"""
|
||||
],
|
||||
"inputs": {"interface": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Source-interface 'Management0' is not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vrf",
|
||||
"test": VerifyLoggingSourceIntf,
|
||||
"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
|
||||
|
||||
"""
|
||||
],
|
||||
"inputs": {"interface": "Management0", "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Source-interface 'Management0' is not configured in VRF MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingHosts,
|
||||
"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
|
||||
|
||||
"""
|
||||
],
|
||||
"inputs": {"hosts": ["10.22.10.92", "10.22.10.93", "10.22.10.94"], "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-hosts",
|
||||
"test": VerifyLoggingHosts,
|
||||
"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
|
||||
|
||||
"""
|
||||
],
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-vrf",
|
||||
"test": VerifyLoggingHosts,
|
||||
"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
|
||||
|
||||
"""
|
||||
],
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingLogsGeneration,
|
||||
"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",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingLogsGeneration,
|
||||
"eos_data": ["", "Log Buffer:\n"],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingHostname,
|
||||
"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",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingHostname,
|
||||
"eos_data": [
|
||||
{"hostname": "NW-CORE", "fqdn": "NW-CORE.example.org"},
|
||||
"",
|
||||
"2023-05-10T13:54:21.463497-05:00 NW-CORE ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingLogsHostname validation\n",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated with the device FQDN"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingTimestamp,
|
||||
"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",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingTimestamp,
|
||||
"eos_data": [
|
||||
"",
|
||||
"May 10 13:54:22 NE-CORE.example.org ConfigAgent: %SYS-6-LOGMSG_INFO: "
|
||||
"Message from arista on command-api (10.22.1.107): ANTA VerifyLoggingTimestamp validation\n",
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Logs are not generated with the appropriate timestamp format"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingAccounting,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingAccounting,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyLoggingErrors,
|
||||
"eos_data": [""],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyLoggingErrors,
|
||||
"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)"
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device has reported syslog messages with a severity of ERRORS or higher"]},
|
||||
},
|
||||
]
|
343
tests/units/anta_tests/test_mlag.py
Normal file
343
tests/units/anta_tests/test_mlag.py
Normal file
|
@ -0,0 +1,343 @@
|
|||
# Copyright (c) 2023-2024 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.mlag.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.mlag import VerifyMlagConfigSanity, VerifyMlagDualPrimary, VerifyMlagInterfaces, VerifyMlagPrimaryPriority, VerifyMlagReloadDelay, VerifyMlagStatus
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagStatus,
|
||||
"eos_data": [{"state": "active", "negStatus": "connected", "peerLinkStatus": "up", "localIntfStatus": "up"}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyMlagStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyMlagStatus,
|
||||
"eos_data": [{"state": "active", "negStatus": "connected", "peerLinkStatus": "down", "localIntfStatus": "up"}],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["MLAG status is not OK: {'state': 'active', 'negStatus': 'connected', 'localIntfStatus': 'up', 'peerLinkStatus': '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"},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyMlagInterfaces,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "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: {'Disabled': 0, 'Configured': 0, 'Inactive': 0, 'Active-partial': 1, 'Active-full': 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: {'Disabled': 0, 'Configured': 0, 'Inactive': 1, 'Active-partial': 1, 'Active-full': 1}"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
"eos_data": [{"globalConfiguration": {}, "interfaceConfiguration": {}, "mlagActive": True, "mlagConnected": True}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
"eos_data": [
|
||||
{
|
||||
"mlagActive": False,
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
"eos_data": [
|
||||
{
|
||||
"dummy": False,
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "error", "messages": ["Incorrect JSON response - 'mlagActive' state was not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-global",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
"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 returned inconsistencies: "
|
||||
"{'globalConfiguration': {'mlag': {'globalParameters': "
|
||||
"{'dual-primary-detection-delay': {'localValue': '0', 'peerValue': '200'}}}}, "
|
||||
"'interfaceConfiguration': {}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-interface",
|
||||
"test": VerifyMlagConfigSanity,
|
||||
"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 returned inconsistencies: "
|
||||
"{'globalConfiguration': {}, "
|
||||
"'interfaceConfiguration': {'trunk-native-vlan mlag30': "
|
||||
"{'interface': {'Port-Channel30': {'localValue': '123', 'peerValue': '3700'}}}}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagReloadDelay,
|
||||
"eos_data": [{"state": "active", "reloadDelay": 300, "reloadDelayNonMlag": 330}],
|
||||
"inputs": {"reload_delay": 300, "reload_delay_non_mlag": 330},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "skipped-disabled",
|
||||
"test": VerifyMlagReloadDelay,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "disabled",
|
||||
}
|
||||
],
|
||||
"inputs": {"reload_delay": 300, "reload_delay_non_mlag": 330},
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyMlagReloadDelay,
|
||||
"eos_data": [{"state": "active", "reloadDelay": 400, "reloadDelayNonMlag": 430}],
|
||||
"inputs": {"reload_delay": 300, "reload_delay_non_mlag": 330},
|
||||
"expected": {"result": "failure", "messages": ["The reload-delay parameters are not configured properly: {'reloadDelay': 400, 'reloadDelayNonMlag': 430}"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"dualPrimaryDetectionState": "configured",
|
||||
"dualPrimaryPortsErrdisabled": False,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "skipped-disabled",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-timers",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"dualPrimaryDetectionState": "configured",
|
||||
"dualPrimaryPortsErrdisabled": False,
|
||||
"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",
|
||||
"messages": [
|
||||
(
|
||||
"The dual-primary parameters are not configured properly: "
|
||||
"{'detail.dualPrimaryDetectionDelay': 300, "
|
||||
"'detail.dualPrimaryAction': 'none', "
|
||||
"'dualPrimaryMlagRecoveryDelay': 160, "
|
||||
"'dualPrimaryNonMlagRecoveryDelay': 0}"
|
||||
)
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-action",
|
||||
"test": VerifyMlagDualPrimary,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"dualPrimaryDetectionState": "configured",
|
||||
"dualPrimaryPortsErrdisabled": False,
|
||||
"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": [
|
||||
(
|
||||
"The dual-primary parameters are not configured properly: "
|
||||
"{'detail.dualPrimaryDetectionDelay': 200, "
|
||||
"'detail.dualPrimaryAction': 'none', "
|
||||
"'dualPrimaryMlagRecoveryDelay': 60, "
|
||||
"'dualPrimaryNonMlagRecoveryDelay': 0}"
|
||||
)
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"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",
|
||||
}
|
||||
],
|
||||
"inputs": {"primary_priority": 32767},
|
||||
"expected": {"result": "skipped", "messages": ["MLAG is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-primary",
|
||||
"test": VerifyMlagPrimaryPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"detail": {"mlagState": "secondary", "primaryPriority": 32767},
|
||||
}
|
||||
],
|
||||
"inputs": {"primary_priority": 32767},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["The device is not set as MLAG primary."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-priority",
|
||||
"test": VerifyMlagPrimaryPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"state": "active",
|
||||
"detail": {"mlagState": "secondary", "primaryPriority": 32767},
|
||||
}
|
||||
],
|
||||
"inputs": {"primary_priority": 1},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["The device is not set as MLAG primary.", "The primary priority does not match expected. Expected `1`, but found `32767` instead."],
|
||||
},
|
||||
},
|
||||
]
|
175
tests/units/anta_tests/test_multicast.py
Normal file
175
tests/units/anta_tests/test_multicast.py
Normal file
|
@ -0,0 +1,175 @@
|
|||
# Copyright (c) 2023-2024 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 inputs for anta.tests.multicast"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.multicast import VerifyIGMPSnoopingGlobal, VerifyIGMPSnoopingVlans
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=unused-import
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success-enabled",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"vlans": {
|
||||
"1": {
|
||||
"reportFlooding": "disabled",
|
||||
"proxyActive": False,
|
||||
"groupsOverrun": False,
|
||||
"multicastRouterLearningMode": "pim-dvmrp",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"pruningActive": False,
|
||||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
"42": {
|
||||
"reportFlooding": "disabled",
|
||||
"proxyActive": False,
|
||||
"groupsOverrun": False,
|
||||
"multicastRouterLearningMode": "pim-dvmrp",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"pruningActive": False,
|
||||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {1: True, 42: True}},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-disabled",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"vlans": {
|
||||
"42": {
|
||||
"reportFlooding": "disabled",
|
||||
"proxyActive": False,
|
||||
"groupsOverrun": False,
|
||||
"multicastRouterLearningMode": "pim-dvmrp",
|
||||
"igmpSnoopingState": "disabled",
|
||||
"pruningActive": False,
|
||||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
}
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {42: False}},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-vlan",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"vlans": {
|
||||
"1": {
|
||||
"reportFlooding": "disabled",
|
||||
"proxyActive": False,
|
||||
"groupsOverrun": False,
|
||||
"multicastRouterLearningMode": "pim-dvmrp",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"pruningActive": False,
|
||||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {1: False, 42: False}},
|
||||
"expected": {"result": "failure", "messages": ["IGMP state for vlan 1 is enabled", "Supplied vlan 42 is not present on the device."]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-state",
|
||||
"test": VerifyIGMPSnoopingVlans,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"vlans": {
|
||||
"1": {
|
||||
"reportFlooding": "disabled",
|
||||
"proxyActive": False,
|
||||
"groupsOverrun": False,
|
||||
"multicastRouterLearningMode": "pim-dvmrp",
|
||||
"igmpSnoopingState": "disabled",
|
||||
"pruningActive": False,
|
||||
"maxGroups": 65534,
|
||||
"immediateLeave": "default",
|
||||
"floodingTraffic": True,
|
||||
},
|
||||
},
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
}
|
||||
],
|
||||
"inputs": {"vlans": {1: True}},
|
||||
"expected": {"result": "failure", "messages": ["IGMP state for vlan 1 is disabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success-enabled",
|
||||
"test": VerifyIGMPSnoopingGlobal,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "enabled",
|
||||
"robustness": 2,
|
||||
"immediateLeave": "enabled",
|
||||
"reportFloodingSwitchPorts": [],
|
||||
}
|
||||
],
|
||||
"inputs": {"enabled": True},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-disabled",
|
||||
"test": VerifyIGMPSnoopingGlobal,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "disabled",
|
||||
}
|
||||
],
|
||||
"inputs": {"enabled": False},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-state",
|
||||
"test": VerifyIGMPSnoopingGlobal,
|
||||
"eos_data": [
|
||||
{
|
||||
"reportFlooding": "disabled",
|
||||
"igmpSnoopingState": "disabled",
|
||||
}
|
||||
],
|
||||
"inputs": {"enabled": True},
|
||||
"expected": {"result": "failure", "messages": ["IGMP state is not valid: disabled"]},
|
||||
},
|
||||
]
|
47
tests/units/anta_tests/test_profiles.py
Normal file
47
tests/units/anta_tests/test_profiles.py
Normal file
|
@ -0,0 +1,47 @@
|
|||
# Copyright (c) 2023-2024 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.profiles.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.profiles import VerifyTcamProfile, VerifyUnifiedForwardingTableMode
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyUnifiedForwardingTableMode,
|
||||
"eos_data": [{"uftMode": "2", "urpfEnabled": False, "chipModel": "bcm56870", "l2TableSize": 163840, "l3TableSize": 147456, "lpmTableSize": 32768}],
|
||||
"inputs": {"mode": 2},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyUnifiedForwardingTableMode,
|
||||
"eos_data": [{"uftMode": "2", "urpfEnabled": False, "chipModel": "bcm56870", "l2TableSize": 163840, "l3TableSize": 147456, "lpmTableSize": 32768}],
|
||||
"inputs": {"mode": 3},
|
||||
"expected": {"result": "failure", "messages": ["Device is not running correct UFT mode (expected: 3 / running: 2)"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTcamProfile,
|
||||
"eos_data": [
|
||||
{"pmfProfiles": {"FixedSystem": {"config": "test", "configType": "System Profile", "status": "test", "mode": "tcam"}}, "lastProgrammingStatus": {}}
|
||||
],
|
||||
"inputs": {"profile": "test"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTcamProfile,
|
||||
"eos_data": [
|
||||
{"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"]},
|
||||
},
|
||||
]
|
42
tests/units/anta_tests/test_ptp.py
Normal file
42
tests/units/anta_tests/test_ptp.py
Normal file
|
@ -0,0 +1,42 @@
|
|||
# Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
# Use of this source code is governed by the Apache License 2.0
|
||||
# that can be found in the LICENSE file.
|
||||
"""Data for testing anta.tests.configuration"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.ptp import VerifyPtpStatus
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyPtpStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"ptpMode": "ptpBoundaryClock",
|
||||
"ptpProfile": "ptpDefaultProfile",
|
||||
"ptpClockSummary": {
|
||||
"clockIdentity": "0xcc:1a:a3:ff:ff:c3:bf:eb",
|
||||
"gmClockIdentity": "0x00:00:00:00:00:00:00:00",
|
||||
"numberOfSlavePorts": 0,
|
||||
"numberOfMasterPorts": 0,
|
||||
"offsetFromMaster": 0,
|
||||
"meanPathDelay": 0,
|
||||
"stepsRemoved": 0,
|
||||
"skew": 1.0,
|
||||
},
|
||||
"ptpIntfSummaries": {},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyPtpStatus,
|
||||
"eos_data": [{"ptpIntfSummaries": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure"},
|
||||
},
|
||||
]
|
900
tests/units/anta_tests/test_security.py
Normal file
900
tests/units/anta_tests/test_security.py
Normal file
|
@ -0,0 +1,900 @@
|
|||
# Copyright (c) 2023-2024 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.security.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.security import (
|
||||
VerifyAPIHttpsSSL,
|
||||
VerifyAPIHttpStatus,
|
||||
VerifyAPIIPv4Acl,
|
||||
VerifyAPIIPv6Acl,
|
||||
VerifyAPISSLCertificate,
|
||||
VerifyBannerLogin,
|
||||
VerifyBannerMotd,
|
||||
VerifyIPv4ACL,
|
||||
VerifySSHIPv4Acl,
|
||||
VerifySSHIPv6Acl,
|
||||
VerifySSHStatus,
|
||||
VerifyTelnetStatus,
|
||||
)
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySSHStatus,
|
||||
"eos_data": ["SSHD status for Default VRF is disabled\nSSH connection limit is 50\nSSH per host connection limit is 20\nFIPS status: disabled\n\n"],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySSHStatus,
|
||||
"eos_data": ["SSHD status for Default VRF is enabled\nSSH connection limit is 50\nSSH per host connection limit is 20\nFIPS status: disabled\n\n"],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["SSHD status for Default VRF is enabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySSHIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_SSH", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifySSHIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Expected 1 SSH IPv4 ACL(s) in vrf MGMT but got 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySSHIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_SSH", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["SSH IPv4 ACL(s) not configured or active in vrf MGMT: ['ACL_IPV4_SSH']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySSHIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_SSH", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifySSHIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Expected 1 SSH IPv6 ACL(s) in vrf MGMT but got 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySSHIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_SSH", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["SSH IPv6 ACL(s) not configured or active in vrf MGMT: ['ACL_IPV6_SSH']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTelnetStatus,
|
||||
"eos_data": [{"serverState": "disabled", "vrfName": "default", "maxTelnetSessions": 20, "maxTelnetSessionsPerHost": 20}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTelnetStatus,
|
||||
"eos_data": [{"serverState": "enabled", "vrfName": "default", "maxTelnetSessions": 20, "maxTelnetSessionsPerHost": 20}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Telnet status for Default VRF is enabled"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAPIHttpStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"httpServer": {"configured": False, "running": False, "port": 80},
|
||||
"localHttpServer": {"configured": False, "running": False, "port": 8080},
|
||||
"httpsServer": {"configured": True, "running": True, "port": 443},
|
||||
"unixSocketServer": {"configured": False, "running": False},
|
||||
"sslProfile": {"name": "API_SSL_Profile", "configured": True, "state": "valid"},
|
||||
"tlsProtocol": ["1.2"],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyAPIHttpStatus,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"httpServer": {"configured": True, "running": True, "port": 80},
|
||||
"localHttpServer": {"configured": False, "running": False, "port": 8080},
|
||||
"httpsServer": {"configured": True, "running": True, "port": 443},
|
||||
"unixSocketServer": {"configured": False, "running": False},
|
||||
"sslProfile": {"name": "API_SSL_Profile", "configured": True, "state": "valid"},
|
||||
"tlsProtocol": ["1.2"],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["eAPI HTTP server is enabled globally"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAPIHttpsSSL,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"httpServer": {"configured": False, "running": False, "port": 80},
|
||||
"localHttpServer": {"configured": False, "running": False, "port": 8080},
|
||||
"httpsServer": {"configured": True, "running": True, "port": 443},
|
||||
"unixSocketServer": {"configured": False, "running": False},
|
||||
"sslProfile": {"name": "API_SSL_Profile", "configured": True, "state": "valid"},
|
||||
"tlsProtocol": ["1.2"],
|
||||
}
|
||||
],
|
||||
"inputs": {"profile": "API_SSL_Profile"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-not-configured",
|
||||
"test": VerifyAPIHttpsSSL,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"httpServer": {"configured": True, "running": True, "port": 80},
|
||||
"localHttpServer": {"configured": False, "running": False, "port": 8080},
|
||||
"httpsServer": {"configured": True, "running": True, "port": 443},
|
||||
"unixSocketServer": {"configured": False, "running": False},
|
||||
"tlsProtocol": ["1.2"],
|
||||
}
|
||||
],
|
||||
"inputs": {"profile": "API_SSL_Profile"},
|
||||
"expected": {"result": "failure", "messages": ["eAPI HTTPS server SSL profile (API_SSL_Profile) is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-misconfigured-invalid",
|
||||
"test": VerifyAPIHttpsSSL,
|
||||
"eos_data": [
|
||||
{
|
||||
"enabled": True,
|
||||
"httpServer": {"configured": True, "running": True, "port": 80},
|
||||
"localHttpServer": {"configured": False, "running": False, "port": 8080},
|
||||
"httpsServer": {"configured": True, "running": True, "port": 443},
|
||||
"unixSocketServer": {"configured": False, "running": False},
|
||||
"sslProfile": {"name": "Wrong_SSL_Profile", "configured": True, "state": "valid"},
|
||||
"tlsProtocol": ["1.2"],
|
||||
}
|
||||
],
|
||||
"inputs": {"profile": "API_SSL_Profile"},
|
||||
"expected": {"result": "failure", "messages": ["eAPI HTTPS server SSL profile (API_SSL_Profile) is misconfigured or invalid"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAPIIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_API", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifyAPIIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Expected 1 eAPI IPv4 ACL(s) in vrf MGMT but got 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifyAPIIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_API", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["eAPI IPv4 ACL(s) not configured or active in vrf MGMT: ['ACL_IPV4_API']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAPIIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_API", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifyAPIIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Expected 1 eAPI IPv6 ACL(s) in vrf MGMT but got 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifyAPIIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_API", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["eAPI IPv6 ACL(s) not configured or active in vrf MGMT: ['ACL_IPV6_API']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_ROOT_CA.crt": {
|
||||
"subject": {"commonName": "Arista Networks Internal IT Root Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "RSA",
|
||||
"size": 4096,
|
||||
},
|
||||
},
|
||||
"ARISTA_SIGNING_CA.crt": {
|
||||
"subject": {"commonName": "AristaIT-ICA ECDSA Issuing Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "ECDSA",
|
||||
"size": 256,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702288467.6736515,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-certificate-not-configured",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_SIGNING_CA.crt": {
|
||||
"subject": {"commonName": "AristaIT-ICA ECDSA Issuing Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "ECDSA",
|
||||
"size": 256,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702288467.6736515,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["SSL certificate 'ARISTA_ROOT_CA.crt', is not configured.\n"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-certificate-expired",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_ROOT_CA.crt": {
|
||||
"subject": {"commonName": "Arista Networks Internal IT Root Cert Authority"},
|
||||
"notAfter": 1702533518,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "RSA",
|
||||
"size": 4096,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702622372.2240553,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["SSL certificate 'ARISTA_SIGNING_CA.crt', is not configured.\n", "SSL certificate `ARISTA_ROOT_CA.crt` is expired.\n"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-certificate-about-to-expire",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_ROOT_CA.crt": {
|
||||
"subject": {"commonName": "Arista Networks Internal IT Root Cert Authority"},
|
||||
"notAfter": 1704782709,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "RSA",
|
||||
"size": 4096,
|
||||
},
|
||||
},
|
||||
"ARISTA_SIGNING_CA.crt": {
|
||||
"subject": {"commonName": "AristaIT-ICA ECDSA Issuing Cert Authority"},
|
||||
"notAfter": 1702533518,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "ECDSA",
|
||||
"size": 256,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702622372.2240553,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["SSL certificate `ARISTA_SIGNING_CA.crt` is expired.\n", "SSL certificate `ARISTA_ROOT_CA.crt` is about to expire in 25 days."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-subject-name",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_ROOT_CA.crt": {
|
||||
"subject": {"commonName": "AristaIT-ICA Networks Internal IT Root Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "RSA",
|
||||
"size": 4096,
|
||||
},
|
||||
},
|
||||
"ARISTA_SIGNING_CA.crt": {
|
||||
"subject": {"commonName": "Arista ECDSA Issuing Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "ECDSA",
|
||||
"size": 256,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702288467.6736515,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"SSL certificate `ARISTA_SIGNING_CA.crt` is not configured properly:\n"
|
||||
"Expected `AristaIT-ICA ECDSA Issuing Cert Authority` as the subject.commonName, but found "
|
||||
"`Arista ECDSA Issuing Cert Authority` instead.\n",
|
||||
"SSL certificate `ARISTA_ROOT_CA.crt` is not configured properly:\n"
|
||||
"Expected `Arista Networks Internal IT Root Cert Authority` as the subject.commonName, "
|
||||
"but found `AristaIT-ICA Networks Internal IT Root Cert Authority` instead.\n",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-encryption-type-and-size",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_ROOT_CA.crt": {
|
||||
"subject": {"commonName": "Arista Networks Internal IT Root Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "ECDSA",
|
||||
"size": 256,
|
||||
},
|
||||
},
|
||||
"ARISTA_SIGNING_CA.crt": {
|
||||
"subject": {"commonName": "AristaIT-ICA ECDSA Issuing Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
"publicKey": {
|
||||
"encryptionAlgorithm": "RSA",
|
||||
"size": 4096,
|
||||
},
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702288467.6736515,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"SSL certificate `ARISTA_SIGNING_CA.crt` is not configured properly:\n"
|
||||
"Expected `ECDSA` as the publicKey.encryptionAlgorithm, but found `RSA` instead.\n"
|
||||
"Expected `256` as the publicKey.size, but found `4096` instead.\n",
|
||||
"SSL certificate `ARISTA_ROOT_CA.crt` is not configured properly:\n"
|
||||
"Expected `RSA` as the publicKey.encryptionAlgorithm, but found `ECDSA` instead.\n"
|
||||
"Expected `4096` as the publicKey.size, but found `256` instead.\n",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-actual-output",
|
||||
"test": VerifyAPISSLCertificate,
|
||||
"eos_data": [
|
||||
{
|
||||
"certificates": {
|
||||
"ARISTA_ROOT_CA.crt": {
|
||||
"subject": {"commonName": "Arista Networks Internal IT Root Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
},
|
||||
"ARISTA_SIGNING_CA.crt": {
|
||||
"subject": {"commonName": "AristaIT-ICA ECDSA Issuing Cert Authority"},
|
||||
"notAfter": 2127420899,
|
||||
},
|
||||
}
|
||||
},
|
||||
{
|
||||
"utcTime": 1702288467.6736515,
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"certificates": [
|
||||
{
|
||||
"certificate_name": "ARISTA_SIGNING_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "AristaIT-ICA ECDSA Issuing Cert Authority",
|
||||
"encryption_algorithm": "ECDSA",
|
||||
"key_size": 256,
|
||||
},
|
||||
{
|
||||
"certificate_name": "ARISTA_ROOT_CA.crt",
|
||||
"expiry_threshold": 30,
|
||||
"common_name": "Arista Networks Internal IT Root Cert Authority",
|
||||
"encryption_algorithm": "RSA",
|
||||
"key_size": 4096,
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"SSL certificate `ARISTA_SIGNING_CA.crt` is not configured properly:\n"
|
||||
"Expected `ECDSA` as the publicKey.encryptionAlgorithm, but it was not found in the actual output.\n"
|
||||
"Expected `256` as the publicKey.size, but it was not found in the actual output.\n",
|
||||
"SSL certificate `ARISTA_ROOT_CA.crt` is not configured properly:\n"
|
||||
"Expected `RSA` as the publicKey.encryptionAlgorithm, but it was not found in the actual output.\n"
|
||||
"Expected `4096` as the publicKey.size, but it was not found in the actual output.\n",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBannerLogin,
|
||||
"eos_data": [
|
||||
{
|
||||
"loginBanner": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"login_banner": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-multiline",
|
||||
"test": VerifyBannerLogin,
|
||||
"eos_data": [
|
||||
{
|
||||
"loginBanner": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"login_banner": """Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
Use of this source code is governed by the Apache License 2.0
|
||||
that can be found in the LICENSE file."""
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-login-banner",
|
||||
"test": VerifyBannerLogin,
|
||||
"eos_data": [
|
||||
{
|
||||
"loginBanner": "Copyright (c) 2023 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"login_banner": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Expected `Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file.` as the login banner, but found `Copyright (c) 2023 Arista Networks, Inc.\nUse of this source code is "
|
||||
"governed by the Apache License 2.0\nthat can be found in the LICENSE file.` instead."
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyBannerMotd,
|
||||
"eos_data": [
|
||||
{
|
||||
"motd": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"motd_banner": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-multiline",
|
||||
"test": VerifyBannerMotd,
|
||||
"eos_data": [
|
||||
{
|
||||
"motd": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"motd_banner": """Copyright (c) 2023-2024 Arista Networks, Inc.
|
||||
Use of this source code is governed by the Apache License 2.0
|
||||
that can be found in the LICENSE file."""
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-motd-banner",
|
||||
"test": VerifyBannerMotd,
|
||||
"eos_data": [
|
||||
{
|
||||
"motd": "Copyright (c) 2023 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"motd_banner": "Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file."
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Expected `Copyright (c) 2023-2024 Arista Networks, Inc.\nUse of this source code is governed by the Apache License 2.0\n"
|
||||
"that can be found in the LICENSE file.` as the motd banner, but found `Copyright (c) 2023 Arista Networks, Inc.\nUse of this source code is "
|
||||
"governed by the Apache License 2.0\nthat can be found in the LICENSE file.` instead."
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyIPv4ACL,
|
||||
"eos_data": [
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit ip any any tracked", "sequenceNumber": 20},
|
||||
{"text": "permit udp any any eq bfd ttl eq 255", "sequenceNumber": 30},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit tcp any any range 5900 5910", "sequenceNumber": 20},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"ipv4_access_lists": [
|
||||
{
|
||||
"name": "default-control-plane-acl",
|
||||
"entries": [
|
||||
{"sequence": 10, "action": "permit icmp any any"},
|
||||
{"sequence": 20, "action": "permit ip any any tracked"},
|
||||
{"sequence": 30, "action": "permit udp any any eq bfd ttl eq 255"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LabTest",
|
||||
"entries": [{"sequence": 10, "action": "permit icmp any any"}, {"sequence": 20, "action": "permit tcp any any range 5900 5910"}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-acl-not-found",
|
||||
"test": VerifyIPv4ACL,
|
||||
"eos_data": [
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit ip any any tracked", "sequenceNumber": 20},
|
||||
{"text": "permit udp any any eq bfd ttl eq 255", "sequenceNumber": 30},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{"aclList": []},
|
||||
],
|
||||
"inputs": {
|
||||
"ipv4_access_lists": [
|
||||
{
|
||||
"name": "default-control-plane-acl",
|
||||
"entries": [
|
||||
{"sequence": 10, "action": "permit icmp any any"},
|
||||
{"sequence": 20, "action": "permit ip any any tracked"},
|
||||
{"sequence": 30, "action": "permit udp any any eq bfd ttl eq 255"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LabTest",
|
||||
"entries": [{"sequence": 10, "action": "permit icmp any any"}, {"sequence": 20, "action": "permit tcp any any range 5900 5910"}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {"result": "failure", "messages": ["LabTest: Not found"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-sequence-not-found",
|
||||
"test": VerifyIPv4ACL,
|
||||
"eos_data": [
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit ip any any tracked", "sequenceNumber": 20},
|
||||
{"text": "permit udp any any eq bfd ttl eq 255", "sequenceNumber": 40},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit tcp any any range 5900 5910", "sequenceNumber": 30},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"ipv4_access_lists": [
|
||||
{
|
||||
"name": "default-control-plane-acl",
|
||||
"entries": [
|
||||
{"sequence": 10, "action": "permit icmp any any"},
|
||||
{"sequence": 20, "action": "permit ip any any tracked"},
|
||||
{"sequence": 30, "action": "permit udp any any eq bfd ttl eq 255"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LabTest",
|
||||
"entries": [{"sequence": 10, "action": "permit icmp any any"}, {"sequence": 20, "action": "permit tcp any any range 5900 5910"}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["default-control-plane-acl:\nSequence number `30` is not found.\n", "LabTest:\nSequence number `20` is not found.\n"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-action-not-match",
|
||||
"test": VerifyIPv4ACL,
|
||||
"eos_data": [
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit ip any any tracked", "sequenceNumber": 20},
|
||||
{"text": "permit tcp any any range 5900 5910", "sequenceNumber": 30},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit udp any any eq bfd ttl eq 255", "sequenceNumber": 20},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
],
|
||||
"inputs": {
|
||||
"ipv4_access_lists": [
|
||||
{
|
||||
"name": "default-control-plane-acl",
|
||||
"entries": [
|
||||
{"sequence": 10, "action": "permit icmp any any"},
|
||||
{"sequence": 20, "action": "permit ip any any tracked"},
|
||||
{"sequence": 30, "action": "permit udp any any eq bfd ttl eq 255"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LabTest",
|
||||
"entries": [{"sequence": 10, "action": "permit icmp any any"}, {"sequence": 20, "action": "permit tcp any any range 5900 5910"}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"default-control-plane-acl:\n"
|
||||
"Expected `permit udp any any eq bfd ttl eq 255` as sequence number 30 action but found `permit tcp any any range 5900 5910` instead.\n",
|
||||
"LabTest:\nExpected `permit tcp any any range 5900 5910` as sequence number 20 action but found `permit udp any any eq bfd ttl eq 255` instead.\n",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-type",
|
||||
"test": VerifyIPv4ACL,
|
||||
"eos_data": [
|
||||
{
|
||||
"aclList": [
|
||||
{
|
||||
"sequence": [
|
||||
{"text": "permit icmp any any", "sequenceNumber": 10},
|
||||
{"text": "permit ip any any tracked", "sequenceNumber": 40},
|
||||
{"text": "permit tcp any any range 5900 5910", "sequenceNumber": 30},
|
||||
],
|
||||
}
|
||||
]
|
||||
},
|
||||
{"aclList": []},
|
||||
],
|
||||
"inputs": {
|
||||
"ipv4_access_lists": [
|
||||
{
|
||||
"name": "default-control-plane-acl",
|
||||
"entries": [
|
||||
{"sequence": 10, "action": "permit icmp any any"},
|
||||
{"sequence": 20, "action": "permit ip any any tracked"},
|
||||
{"sequence": 30, "action": "permit udp any any eq bfd ttl eq 255"},
|
||||
],
|
||||
},
|
||||
{
|
||||
"name": "LabTest",
|
||||
"entries": [{"sequence": 10, "action": "permit icmp any any"}, {"sequence": 20, "action": "permit tcp any any range 5900 5910"}],
|
||||
},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"default-control-plane-acl:\nSequence number `20` is not found.\n"
|
||||
"Expected `permit udp any any eq bfd ttl eq 255` as sequence number 30 action but found `permit tcp any any range 5900 5910` instead.\n",
|
||||
"LabTest: Not found",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
218
tests/units/anta_tests/test_services.py
Normal file
218
tests/units/anta_tests/test_services.py
Normal file
|
@ -0,0 +1,218 @@
|
|||
# Copyright (c) 2023-2024 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.services.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.services import VerifyDNSLookup, VerifyDNSServers, VerifyErrdisableRecovery, VerifyHostname
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyHostname,
|
||||
"eos_data": [{"hostname": "s1-spine1", "fqdn": "s1-spine1.fun.aristanetworks.com"}],
|
||||
"inputs": {"hostname": "s1-spine1"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-hostname",
|
||||
"test": VerifyHostname,
|
||||
"eos_data": [{"hostname": "s1-spine2", "fqdn": "s1-spine1.fun.aristanetworks.com"}],
|
||||
"inputs": {"hostname": "s1-spine1"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Expected `s1-spine1` as the hostname, but found `s1-spine2` instead."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyDNSLookup,
|
||||
"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"
|
||||
]
|
||||
},
|
||||
{"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyDNSLookup,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyDNSServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"nameServerConfigs": [{"ipAddr": "10.14.0.1", "vrf": "default", "priority": 0}, {"ipAddr": "10.14.0.11", "vrf": "MGMT", "priority": 1}],
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"dns_servers": [{"server_address": "10.14.0.1", "vrf": "default", "priority": 0}, {"server_address": "10.14.0.11", "vrf": "MGMT", "priority": 1}]
|
||||
},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-dns-missing",
|
||||
"test": VerifyDNSServers,
|
||||
"eos_data": [
|
||||
{
|
||||
"nameServerConfigs": [{"ipAddr": "10.14.0.1", "vrf": "default", "priority": 0}, {"ipAddr": "10.14.0.11", "vrf": "MGMT", "priority": 1}],
|
||||
}
|
||||
],
|
||||
"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",
|
||||
"messages": ["DNS server `10.14.0.10` is not configured with any VRF.", "DNS server `10.14.0.21` is not configured with any VRF."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-dns-found",
|
||||
"test": VerifyDNSServers,
|
||||
"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",
|
||||
"messages": ["DNS server `10.14.0.10` is not configured with any VRF.", "DNS server `10.14.0.21` is not configured with any VRF."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"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}],
|
||||
}
|
||||
],
|
||||
"inputs": {
|
||||
"dns_servers": [
|
||||
{"server_address": "10.14.0.1", "vrf": "CS", "priority": 0},
|
||||
{"server_address": "10.14.0.11", "vrf": "default", "priority": 0},
|
||||
{"server_address": "10.14.0.110", "vrf": "MGMT", "priority": 0},
|
||||
]
|
||||
},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"For DNS server `10.14.0.1`, the expected priority is `0`, but `1` was found instead.",
|
||||
"DNS server `10.14.0.11` is not configured with VRF `default`.",
|
||||
"DNS server `10.14.0.110` is not configured with any VRF.",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Enabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 300}, {"reason": "bpduguard", "interval": 300}]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-reason-missing",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Enabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 300}, {"reason": "arp-inspection", "interval": 30}, {"reason": "tapagg", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["`tapagg`: Not found."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-reason-disabled",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Disabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 300}, {"reason": "arp-inspection", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["`acl`:\nExpected `Enabled` as the status, but found `Disabled` instead."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-interval-not-ok",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Enabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 30}, {"reason": "arp-inspection", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["`acl`:\nExpected `30` as the interval, but found `300` instead."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-all-type",
|
||||
"test": VerifyErrdisableRecovery,
|
||||
"eos_data": [
|
||||
"""
|
||||
Errdisable Reason Timer Status Timer Interval
|
||||
------------------------------ ----------------- --------------
|
||||
acl Disabled 300
|
||||
bpduguard Enabled 300
|
||||
arp-inspection Enabled 30
|
||||
"""
|
||||
],
|
||||
"inputs": {"reasons": [{"reason": "acl", "interval": 30}, {"reason": "arp-inspection", "interval": 300}, {"reason": "tapagg", "interval": 30}]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"`acl`:\nExpected `30` as the interval, but found `300` instead.\nExpected `Enabled` as the status, but found `Disabled` instead.",
|
||||
"`arp-inspection`:\nExpected `300` as the interval, but found `30` instead.",
|
||||
"`tapagg`: Not found.",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
128
tests/units/anta_tests/test_snmp.py
Normal file
128
tests/units/anta_tests/test_snmp.py
Normal file
|
@ -0,0 +1,128 @@
|
|||
# Copyright (c) 2023-2024 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.snmp.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.snmp import VerifySnmpContact, VerifySnmpIPv4Acl, VerifySnmpIPv6Acl, VerifySnmpLocation, VerifySnmpStatus
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpStatus,
|
||||
"eos_data": [{"vrfs": {"snmpVrfs": ["MGMT", "default"]}, "enabled": True}],
|
||||
"inputs": {"vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySnmpStatus,
|
||||
"eos_data": [{"vrfs": {"snmpVrfs": ["default"]}, "enabled": True}],
|
||||
"inputs": {"vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["SNMP agent disabled in vrf MGMT"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-disabled",
|
||||
"test": VerifySnmpStatus,
|
||||
"eos_data": [{"vrfs": {"snmpVrfs": ["default"]}, "enabled": False}],
|
||||
"inputs": {"vrf": "default"},
|
||||
"expected": {"result": "failure", "messages": ["SNMP agent disabled in vrf default"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_SNMP", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifySnmpIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Expected 1 SNMP IPv4 ACL(s) in vrf MGMT but got 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySnmpIPv4Acl,
|
||||
"eos_data": [{"ipAclList": {"aclList": [{"type": "Ip4Acl", "name": "ACL_IPV4_SNMP", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["SNMP IPv4 ACL(s) not configured or active in vrf MGMT: ['ACL_IPV4_SNMP']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_SNMP", "configuredVrfs": ["MGMT"], "activeVrfs": ["MGMT"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-number",
|
||||
"test": VerifySnmpIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": []}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["Expected 1 SNMP IPv6 ACL(s) in vrf MGMT but got 0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-vrf",
|
||||
"test": VerifySnmpIPv6Acl,
|
||||
"eos_data": [{"ipv6AclList": {"aclList": [{"type": "Ip6Acl", "name": "ACL_IPV6_SNMP", "configuredVrfs": ["default"], "activeVrfs": ["default"]}]}}],
|
||||
"inputs": {"number": 1, "vrf": "MGMT"},
|
||||
"expected": {"result": "failure", "messages": ["SNMP IPv6 ACL(s) not configured or active in vrf MGMT: ['ACL_IPV6_SNMP']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpLocation,
|
||||
"eos_data": [
|
||||
{
|
||||
"location": {"location": "New York"},
|
||||
}
|
||||
],
|
||||
"inputs": {"location": "New York"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-location",
|
||||
"test": VerifySnmpLocation,
|
||||
"eos_data": [
|
||||
{
|
||||
"location": {"location": "Europe"},
|
||||
}
|
||||
],
|
||||
"inputs": {"location": "New York"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Expected `New York` as the location, but found `Europe` instead."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySnmpContact,
|
||||
"eos_data": [
|
||||
{
|
||||
"contact": {"contact": "Jon@example.com"},
|
||||
}
|
||||
],
|
||||
"inputs": {"contact": "Jon@example.com"},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-contact",
|
||||
"test": VerifySnmpContact,
|
||||
"eos_data": [
|
||||
{
|
||||
"contact": {"contact": "Jon@example.com"},
|
||||
}
|
||||
],
|
||||
"inputs": {"contact": "Bob@example.com"},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Expected `Bob@example.com` as the contact, but found `Jon@example.com` instead."],
|
||||
},
|
||||
},
|
||||
]
|
101
tests/units/anta_tests/test_software.py
Normal file
101
tests/units/anta_tests/test_software.py
Normal file
|
@ -0,0 +1,101 @@
|
|||
# Copyright (c) 2023-2024 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 inputs for anta.tests.hardware"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.software import VerifyEOSExtensions, VerifyEOSVersion, VerifyTerminAttrVersion
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyEOSVersion,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEOSVersion,
|
||||
"eos_data": [
|
||||
{
|
||||
"modelName": "vEOS-lab",
|
||||
"internalVersion": "4.27.0F-24305004.4270F",
|
||||
"version": "4.27.0F",
|
||||
}
|
||||
],
|
||||
"inputs": {"versions": ["4.27.1F"]},
|
||||
"expected": {"result": "failure", "messages": ["device is running version \"4.27.0F\" not in expected versions: ['4.27.1F']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyTerminAttrVersion,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1107543.52,
|
||||
"modelName": "vEOS-lab",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
"switchType": "fixedSystem",
|
||||
"packages": {
|
||||
"TerminAttr-core": {"release": "1", "version": "v1.17.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"versions": ["v1.17.0", "v1.18.1"]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyTerminAttrVersion,
|
||||
"eos_data": [
|
||||
{
|
||||
"imageFormatVersion": "1.0",
|
||||
"uptime": 1107543.52,
|
||||
"modelName": "vEOS-lab",
|
||||
"details": {
|
||||
"deviations": [],
|
||||
"components": [{"name": "Aboot", "version": "Aboot-veos-8.0.0-3255441"}],
|
||||
"switchType": "fixedSystem",
|
||||
"packages": {
|
||||
"TerminAttr-core": {"release": "1", "version": "v1.17.0"},
|
||||
},
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": {"versions": ["v1.17.1", "v1.18.1"]},
|
||||
"expected": {"result": "failure", "messages": ["device is running TerminAttr version v1.17.0 and is not in the allowed list: ['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"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyEOSExtensions,
|
||||
"eos_data": [
|
||||
{"extensions": {}, "extensionStoredDir": "flash:", "warnings": ["No extensions are available"]},
|
||||
{"extensions": ["dummy"]},
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Missing EOS extensions: installed [] / configured: ['dummy']"]},
|
||||
},
|
||||
]
|
328
tests/units/anta_tests/test_stp.py
Normal file
328
tests/units/anta_tests/test_stp.py
Normal file
|
@ -0,0 +1,328 @@
|
|||
# Copyright (c) 2023-2024 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.stp.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.stp import VerifySTPBlockedPorts, VerifySTPCounters, VerifySTPForwardingPorts, VerifySTPMode, VerifySTPRootPriority
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPMode,
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {"10": {"spanningTreeVlanInstance": {"protocol": "rstp"}}}},
|
||||
{"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "rstp"}}}},
|
||||
],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-instances",
|
||||
"test": VerifySTPMode,
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {}},
|
||||
{"spanningTreeVlanInstances": {}},
|
||||
],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["STP mode 'rstp' not configured for the following VLAN(s): [10, 20]"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-mode",
|
||||
"test": VerifySTPMode,
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {"10": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}},
|
||||
{"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}},
|
||||
],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["Wrong STP mode configured for the following VLAN(s): [10, 20]"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-both",
|
||||
"test": VerifySTPMode,
|
||||
"eos_data": [
|
||||
{"spanningTreeVlanInstances": {}},
|
||||
{"spanningTreeVlanInstances": {"20": {"spanningTreeVlanInstance": {"protocol": "mstp"}}}},
|
||||
],
|
||||
"inputs": {"mode": "rstp", "vlans": [10, 20]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["STP mode 'rstp' not configured for the following VLAN(s): [10]", "Wrong STP mode configured for the following VLAN(s): [20]"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPBlockedPorts,
|
||||
"eos_data": [{"spanningTreeInstances": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySTPBlockedPorts,
|
||||
"eos_data": [{"spanningTreeInstances": {"MST0": {"spanningTreeBlockedPorts": ["Ethernet10"]}, "MST10": {"spanningTreeBlockedPorts": ["Ethernet10"]}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["The following ports are blocked by STP: {'MST0': ['Ethernet10'], 'MST10': ['Ethernet10']}"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPCounters,
|
||||
"eos_data": [{"interfaces": {"Ethernet10": {"bpduSent": 99, "bpduReceived": 0, "bpduTaggedError": 0, "bpduOtherError": 0, "bpduRateLimitCount": 0}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySTPCounters,
|
||||
"eos_data": [
|
||||
{
|
||||
"interfaces": {
|
||||
"Ethernet10": {"bpduSent": 201, "bpduReceived": 0, "bpduTaggedError": 3, "bpduOtherError": 0, "bpduRateLimitCount": 0},
|
||||
"Ethernet11": {"bpduSent": 99, "bpduReceived": 0, "bpduTaggedError": 0, "bpduOtherError": 6, "bpduRateLimitCount": 0},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["The following interfaces have STP BPDU packet errors: ['Ethernet10', 'Ethernet11']"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifySTPForwardingPorts,
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {"Mst10": {"vlans": [10], "interfaces": {"Ethernet10": {"state": "forwarding"}, "MplsTrunk1": {"state": "forwarding"}}}},
|
||||
},
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {"Mst20": {"vlans": [20], "interfaces": {"Ethernet10": {"state": "forwarding"}, "MplsTrunk1": {"state": "forwarding"}}}},
|
||||
},
|
||||
],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-vlan-not-in-topology", # Should it succeed really ? TODO - this output should be impossible
|
||||
"test": VerifySTPForwardingPorts,
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {"Mst10": {"vlans": [10], "interfaces": {"Ethernet10": {"state": "forwarding"}, "MplsTrunk1": {"state": "forwarding"}}}},
|
||||
},
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {"Mst10": {"vlans": [10], "interfaces": {"Ethernet10": {"state": "forwarding"}, "MplsTrunk1": {"state": "forwarding"}}}},
|
||||
},
|
||||
],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-instances",
|
||||
"test": VerifySTPForwardingPorts,
|
||||
"eos_data": [{"unmappedVlans": [], "topologies": {}}, {"unmappedVlans": [], "topologies": {}}],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["STP instance is not configured for the following VLAN(s): [10, 20]"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifySTPForwardingPorts,
|
||||
"eos_data": [
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {"Vl10": {"vlans": [10], "interfaces": {"Ethernet10": {"state": "discarding"}, "MplsTrunk1": {"state": "forwarding"}}}},
|
||||
},
|
||||
{
|
||||
"unmappedVlans": [],
|
||||
"topologies": {"Vl20": {"vlans": [20], "interfaces": {"Ethernet10": {"state": "discarding"}, "MplsTrunk1": {"state": "forwarding"}}}},
|
||||
},
|
||||
],
|
||||
"inputs": {"vlans": [10, 20]},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["The following VLAN(s) have interface(s) that are not in a fowarding state: [{'VLAN 10': ['Ethernet10']}, {'VLAN 20': ['Ethernet10']}]"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success-specific-instances",
|
||||
"test": VerifySTPRootPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
"VL10": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 10,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
"VL20": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 20,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
"VL30": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 30,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [10, 20]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-all-instances",
|
||||
"test": VerifySTPRootPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
"VL10": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 10,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
"VL20": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 20,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
"VL30": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 30,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-MST",
|
||||
"test": VerifySTPRootPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
"MST0": {
|
||||
"rootBridge": {
|
||||
"priority": 16384,
|
||||
"systemIdExtension": 0,
|
||||
"macAddress": "02:1c:73:8b:93:ac",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 16384, "instances": [0]},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-instances",
|
||||
"test": VerifySTPRootPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
"WRONG0": {
|
||||
"rootBridge": {
|
||||
"priority": 16384,
|
||||
"systemIdExtension": 0,
|
||||
"macAddress": "02:1c:73:8b:93:ac",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [0]},
|
||||
"expected": {"result": "failure", "messages": ["Unsupported STP instance type: WRONG0"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-instance-type",
|
||||
"test": VerifySTPRootPriority,
|
||||
"eos_data": [{"instances": {}}],
|
||||
"inputs": {"priority": 32768, "instances": [10, 20]},
|
||||
"expected": {"result": "failure", "messages": ["No STP instances configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-priority",
|
||||
"test": VerifySTPRootPriority,
|
||||
"eos_data": [
|
||||
{
|
||||
"instances": {
|
||||
"VL10": {
|
||||
"rootBridge": {
|
||||
"priority": 32768,
|
||||
"systemIdExtension": 10,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
"VL20": {
|
||||
"rootBridge": {
|
||||
"priority": 8196,
|
||||
"systemIdExtension": 20,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
"VL30": {
|
||||
"rootBridge": {
|
||||
"priority": 8196,
|
||||
"systemIdExtension": 30,
|
||||
"macAddress": "00:1c:73:27:95:a2",
|
||||
"helloTime": 2.0,
|
||||
"maxAge": 20,
|
||||
"forwardDelay": 15,
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
],
|
||||
"inputs": {"priority": 32768, "instances": [10, 20, 30]},
|
||||
"expected": {"result": "failure", "messages": ["The following instance(s) have the wrong STP root priority configured: ['VL20', 'VL30']"]},
|
||||
},
|
||||
]
|
283
tests/units/anta_tests/test_system.py
Normal file
283
tests/units/anta_tests/test_system.py
Normal file
|
@ -0,0 +1,283 @@
|
|||
# Copyright (c) 2023-2024 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 inputs for anta.tests.system"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.system import (
|
||||
VerifyAgentLogs,
|
||||
VerifyCoredump,
|
||||
VerifyCPUUtilization,
|
||||
VerifyFileSystemUtilization,
|
||||
VerifyMemoryUtilization,
|
||||
VerifyNTP,
|
||||
VerifyReloadCause,
|
||||
VerifyUptime,
|
||||
)
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyUptime,
|
||||
"eos_data": [{"upTime": 1186689.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
|
||||
"inputs": {"minimum": 666},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyUptime,
|
||||
"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 665.15 seconds"]},
|
||||
},
|
||||
{
|
||||
"name": "success-no-reload",
|
||||
"test": VerifyReloadCause,
|
||||
"eos_data": [{"kernelCrashData": [], "resetCauses": [], "full": False}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "success-valid-cause",
|
||||
"test": VerifyReloadCause,
|
||||
"eos_data": [
|
||||
{
|
||||
"resetCauses": [
|
||||
{"recommendedAction": "No action necessary.", "description": "Reload requested by the user.", "timestamp": 1683186892.0, "debugInfoIsDir": False}
|
||||
],
|
||||
"full": False,
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyReloadCause,
|
||||
# The failure cause is made up
|
||||
"eos_data": [
|
||||
{
|
||||
"resetCauses": [
|
||||
{"recommendedAction": "No action necessary.", "description": "Reload after crash.", "timestamp": 1683186892.0, "debugInfoIsDir": False}
|
||||
],
|
||||
"full": False,
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Reload cause is: 'Reload after crash.'"]},
|
||||
},
|
||||
{
|
||||
"name": "error",
|
||||
"test": VerifyReloadCause,
|
||||
"eos_data": [{}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "error", "messages": ["No reload causes available"]},
|
||||
},
|
||||
{
|
||||
"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,
|
||||
"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
|
||||
"""
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "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",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyCPUUtilization,
|
||||
"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}},
|
||||
"processes": {
|
||||
"1": {
|
||||
"userName": "root",
|
||||
"status": "S",
|
||||
"memPct": 0.3,
|
||||
"niceValue": 0,
|
||||
"cpuPct": 0.0,
|
||||
"cpuPctType": "{:.1f}",
|
||||
"cmd": "systemd",
|
||||
"residentMem": "5096",
|
||||
"priority": "20",
|
||||
"activeTime": 360,
|
||||
"virtMem": "6644",
|
||||
"sharedMem": "3996",
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyCPUUtilization,
|
||||
"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}},
|
||||
"processes": {
|
||||
"1": {
|
||||
"userName": "root",
|
||||
"status": "S",
|
||||
"memPct": 0.3,
|
||||
"niceValue": 0,
|
||||
"cpuPct": 0.0,
|
||||
"cpuPctType": "{:.1f}",
|
||||
"cmd": "systemd",
|
||||
"residentMem": "5096",
|
||||
"priority": "20",
|
||||
"activeTime": 360,
|
||||
"virtMem": "6644",
|
||||
"sharedMem": "3996",
|
||||
}
|
||||
},
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Device has reported a high CPU utilization: 75.2%"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyMemoryUtilization,
|
||||
"eos_data": [
|
||||
{
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyMemoryUtilization,
|
||||
"eos_data": [
|
||||
{
|
||||
"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: 95.56%"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyFileSystemUtilization,
|
||||
"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
|
||||
"""
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyFileSystemUtilization,
|
||||
"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
|
||||
"""
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Mount point /dev/sda2 3.9G 988M 2.9G 84% /mnt/flash is higher than 75%: reported 84%",
|
||||
"Mount point none 294M 78M 217M 84% /.overlay is higher than 75%: reported 84%",
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyNTP,
|
||||
"eos_data": [
|
||||
"""synchronised
|
||||
poll interval unknown
|
||||
"""
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyNTP,
|
||||
"eos_data": [
|
||||
"""unsynchronised
|
||||
poll interval unknown
|
||||
"""
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["The device is not synchronized with the configured NTP server(s): 'unsynchronised'"]},
|
||||
},
|
||||
]
|
37
tests/units/anta_tests/test_vlan.py
Normal file
37
tests/units/anta_tests/test_vlan.py
Normal file
|
@ -0,0 +1,37 @@
|
|||
# Copyright (c) 2023-2024 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.vlan.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.vlan import VerifyVlanInternalPolicy
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVlanInternalPolicy,
|
||||
"eos_data": [{"policy": "ascending", "startVlanId": 1006, "endVlanId": 4094}],
|
||||
"inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-incorrect-policy",
|
||||
"test": VerifyVlanInternalPolicy,
|
||||
"eos_data": [{"policy": "descending", "startVlanId": 4094, "endVlanId": 1006}],
|
||||
"inputs": {"policy": "ascending", "start_vlan_id": 1006, "end_vlan_id": 4094},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"The VLAN internal allocation policy is not configured properly:\n"
|
||||
"Expected `ascending` as the policy, but found `descending` instead.\n"
|
||||
"Expected `1006` as the startVlanId, but found `4094` instead.\n"
|
||||
"Expected `4094` as the endVlanId, but found `1006` instead."
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
365
tests/units/anta_tests/test_vxlan.py
Normal file
365
tests/units/anta_tests/test_vxlan.py
Normal file
|
@ -0,0 +1,365 @@
|
|||
# Copyright (c) 2023-2024 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.vxlan.py
|
||||
"""
|
||||
from __future__ import annotations
|
||||
|
||||
from typing import Any
|
||||
|
||||
from anta.tests.vxlan import VerifyVxlan1ConnSettings, VerifyVxlan1Interface, VerifyVxlanConfigSanity, VerifyVxlanVniBinding, VerifyVxlanVtep
|
||||
from tests.lib.anta import test # noqa: F401; pylint: disable=W0611
|
||||
|
||||
DATA: list[dict[str, Any]] = [
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlan1Interface,
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "up", "interfaceStatus": "up"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlan1Interface,
|
||||
"eos_data": [{"interfaceDescriptions": {"Loopback0": {"lineProtocolStatus": "up", "interfaceStatus": "up"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["Vxlan1 interface is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyVxlan1Interface,
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "down", "interfaceStatus": "up"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Vxlan1 interface is down/up"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyVxlan1Interface,
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "up", "interfaceStatus": "down"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Vxlan1 interface is up/down"]},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyVxlan1Interface,
|
||||
"eos_data": [{"interfaceDescriptions": {"Vxlan1": {"lineProtocolStatus": "down", "interfaceStatus": "down"}}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "failure", "messages": ["Vxlan1 interface is down/down"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlanConfigSanity,
|
||||
"eos_data": [
|
||||
{
|
||||
"categories": {
|
||||
"localVtep": {
|
||||
"description": "Local VTEP Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [
|
||||
{"name": "Loopback IP Address", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VLAN-VNI Map", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Flood List", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Routing", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VNI VRF ACL", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VRF-VNI Dynamic VLAN", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Decap VRF-VNI Map", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
],
|
||||
},
|
||||
"remoteVtep": {
|
||||
"description": "Remote VTEP Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [{"name": "Remote VTEP", "checkPass": True, "hasWarning": False, "detail": ""}],
|
||||
},
|
||||
"pd": {
|
||||
"description": "Platform Dependent Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [
|
||||
{"name": "VXLAN Bridging", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VXLAN Routing", "checkPass": True, "hasWarning": False, "detail": "VXLAN Routing not enabled"},
|
||||
],
|
||||
},
|
||||
"cvx": {
|
||||
"description": "CVX Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [{"name": "CVX Server", "checkPass": True, "hasWarning": False, "detail": "Not in controller client mode"}],
|
||||
},
|
||||
"mlag": {
|
||||
"description": "MLAG Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "Run 'show mlag config-sanity' to verify MLAG config",
|
||||
"hasWarning": False,
|
||||
"items": [
|
||||
{"name": "Peer VTEP IP", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "MLAG VTEP IP", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Virtual VTEP IP", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Peer VLAN-VNI", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "MLAG Inactive State", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
],
|
||||
},
|
||||
},
|
||||
"warnings": [],
|
||||
}
|
||||
],
|
||||
"inputs": None,
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure",
|
||||
"test": VerifyVxlanConfigSanity,
|
||||
"eos_data": [
|
||||
{
|
||||
"categories": {
|
||||
"localVtep": {
|
||||
"description": "Local VTEP Configuration Check",
|
||||
"allCheckPass": False,
|
||||
"detail": "",
|
||||
"hasWarning": True,
|
||||
"items": [
|
||||
{"name": "Loopback IP Address", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VLAN-VNI Map", "checkPass": False, "hasWarning": False, "detail": "No VLAN-VNI mapping in Vxlan1"},
|
||||
{"name": "Flood List", "checkPass": False, "hasWarning": True, "detail": "No VXLAN VLANs in Vxlan1"},
|
||||
{"name": "Routing", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VNI VRF ACL", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VRF-VNI Dynamic VLAN", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Decap VRF-VNI Map", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
],
|
||||
},
|
||||
"remoteVtep": {
|
||||
"description": "Remote VTEP Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [{"name": "Remote VTEP", "checkPass": True, "hasWarning": False, "detail": ""}],
|
||||
},
|
||||
"pd": {
|
||||
"description": "Platform Dependent Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [
|
||||
{"name": "VXLAN Bridging", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "VXLAN Routing", "checkPass": True, "hasWarning": False, "detail": "VXLAN Routing not enabled"},
|
||||
],
|
||||
},
|
||||
"cvx": {
|
||||
"description": "CVX Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "",
|
||||
"hasWarning": False,
|
||||
"items": [{"name": "CVX Server", "checkPass": True, "hasWarning": False, "detail": "Not in controller client mode"}],
|
||||
},
|
||||
"mlag": {
|
||||
"description": "MLAG Configuration Check",
|
||||
"allCheckPass": True,
|
||||
"detail": "Run 'show mlag config-sanity' to verify MLAG config",
|
||||
"hasWarning": False,
|
||||
"items": [
|
||||
{"name": "Peer VTEP IP", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "MLAG VTEP IP", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Virtual VTEP IP", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "Peer VLAN-VNI", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
{"name": "MLAG Inactive State", "checkPass": True, "hasWarning": False, "detail": ""},
|
||||
],
|
||||
},
|
||||
},
|
||||
"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 config sanity check is not passing: {'localVtep': {'description': 'Local VTEP Configuration Check', "
|
||||
"'allCheckPass': False, 'detail': '', 'hasWarning': True, 'items': [{'name': 'Loopback IP Address', 'checkPass': True, "
|
||||
"'hasWarning': False, 'detail': ''}, {'name': 'VLAN-VNI Map', 'checkPass': False, 'hasWarning': False, 'detail': "
|
||||
"'No VLAN-VNI mapping in Vxlan1'}, {'name': 'Flood List', 'checkPass': False, 'hasWarning': True, 'detail': "
|
||||
"'No VXLAN VLANs in Vxlan1'}, {'name': 'Routing', 'checkPass': True, 'hasWarning': False, 'detail': ''}, {'name': "
|
||||
"'VNI VRF ACL', 'checkPass': True, 'hasWarning': False, 'detail': ''}, {'name': 'VRF-VNI Dynamic VLAN', 'checkPass': True, "
|
||||
"'hasWarning': False, 'detail': ''}, {'name': 'Decap VRF-VNI Map', 'checkPass': True, 'hasWarning': False, 'detail': ''}]}}"
|
||||
],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlanConfigSanity,
|
||||
"eos_data": [{"categories": {}}],
|
||||
"inputs": None,
|
||||
"expected": {"result": "skipped", "messages": ["VXLAN is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"10020": {"vlan": 20, "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": "success"},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-binding",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
"eos_data": [
|
||||
{
|
||||
"vxlanIntfs": {
|
||||
"Vxlan1": {
|
||||
"vniBindings": {
|
||||
"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": ["The following VNI(s) have no binding: ['10010']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-binding",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
"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": ["The following VNI(s) have the wrong VLAN binding: [{'10020': 30}]"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-and-wrong-binding",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
"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": {10010: 10, 10020: 20, 500: 1199}},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["The following VNI(s) have no binding: ['10010']", "The following VNI(s) have the wrong VLAN binding: [{'10020': 30}]"],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlanVniBinding,
|
||||
"eos_data": [{"vxlanIntfs": {}}],
|
||||
"inputs": {"bindings": {10020: 20, 500: 1199}},
|
||||
"expected": {"result": "skipped", "messages": ["Vxlan1 interface is not configured"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlanVtep,
|
||||
"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"},
|
||||
},
|
||||
{
|
||||
"name": "failure-missing-vtep",
|
||||
"test": VerifyVxlanVtep,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-vtep",
|
||||
"test": VerifyVxlanVtep,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-no-input-vtep",
|
||||
"test": VerifyVxlanVtep,
|
||||
"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']"]},
|
||||
},
|
||||
{
|
||||
"name": "failure-missmatch",
|
||||
"test": VerifyVxlanVtep,
|
||||
"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",
|
||||
"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,
|
||||
"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"]},
|
||||
},
|
||||
{
|
||||
"name": "success",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
"eos_data": [{"interfaces": {"Vxlan1": {"srcIpIntf": "Loopback1", "udpPort": 4789}}}],
|
||||
"inputs": {"source_interface": "Loopback1", "udp_port": 4789},
|
||||
"expected": {"result": "success"},
|
||||
},
|
||||
{
|
||||
"name": "skipped",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
"eos_data": [{"interfaces": {}}],
|
||||
"inputs": {"source_interface": "Loopback1", "udp_port": 4789},
|
||||
"expected": {"result": "skipped", "messages": ["Vxlan1 interface is not configured."]},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-interface",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
"eos_data": [{"interfaces": {"Vxlan1": {"srcIpIntf": "Loopback10", "udpPort": 4789}}}],
|
||||
"inputs": {"source_interface": "lo1", "udp_port": 4789},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": ["Source interface is not correct. Expected `Loopback1` as source interface but found `Loopback10` instead."],
|
||||
},
|
||||
},
|
||||
{
|
||||
"name": "failure-wrong-port",
|
||||
"test": VerifyVxlan1ConnSettings,
|
||||
"eos_data": [{"interfaces": {"Vxlan1": {"srcIpIntf": "Loopback10", "udpPort": 4789}}}],
|
||||
"inputs": {"source_interface": "Lo1", "udp_port": 4780},
|
||||
"expected": {
|
||||
"result": "failure",
|
||||
"messages": [
|
||||
"Source interface is not correct. Expected `Loopback1` as source interface but found `Loopback10` instead.",
|
||||
"UDP port is not correct. Expected `4780` as UDP port but found `4789` instead.",
|
||||
],
|
||||
},
|
||||
},
|
||||
]
|
Loading…
Add table
Add a link
Reference in a new issue