Adding upstream version 0.13.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 11:32:35 +01:00
parent c0ae77e0f6
commit ecf5ca3300
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
272 changed files with 33172 additions and 0 deletions

70
docs/README.md Executable file
View file

@ -0,0 +1,70 @@
<!--
~ 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.
-->
[![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](https://github.com/arista-netdevops-community/anta/blob/main/LICENSE)
[![Linting and Testing Anta](https://github.com/arista-netdevops-community/anta/actions/workflows/code-testing.yml/badge.svg)](https://github.com/arista-netdevops-community/anta/actions/workflows/code-testing.yml)
[![Code style: black](https://img.shields.io/badge/code%20style-black-000000.svg)](https://github.com/psf/black)
![GitHub commit activity (branch)](https://img.shields.io/github/commit-activity/m/arista-netdevops-community/anta)
[![github release](https://img.shields.io/github/release/arista-netdevops-community/anta.svg)](https://github.com/arista-netdevops-community/anta/releases/)
![PyPI - Downloads](https://img.shields.io/pypi/dm/anta)
![coverage](https://raw.githubusercontent.com/arista-netdevops-community/anta/coverage-badge/latest-release-coverage.svg)
# Arista Network Test Automation (ANTA) Framework
ANTA is Python framework that automates tests for Arista devices.
- ANTA provides a [set of tests](api/tests.md) to validate the state of your network
- ANTA can be used to:
- Automate NRFU (Network Ready For Use) test on a preproduction network
- Automate tests on a live network (periodically or on demand)
- ANTA can be used with:
- The [ANTA CLI](cli/overview.md)
- As a [Python library](advanced_usages/as-python-lib.md) in your own application
![anta nrfu](https://raw.githubusercontent.com/arista-netdevops-community/anta/main/docs/imgs/anta-nrfu.svg)
```bash
# Install ANTA CLI
$ pip install anta
# Run ANTA CLI
$ anta --help
Usage: anta [OPTIONS] COMMAND [ARGS]...
Arista Network Test Automation (ANTA) CLI
Options:
--version Show the version and exit.
--log-file FILE Send the logs to a file. If logging level is
DEBUG, only INFO or higher will be sent to
stdout. [env var: ANTA_LOG_FILE]
-l, --log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]
ANTA logging level [env var:
ANTA_LOG_LEVEL; default: INFO]
--help Show this message and exit.
Commands:
check Commands to validate configuration files
debug Commands to execute EOS commands on remote devices
exec Commands to execute various scripts on EOS devices
get Commands to get information from or generate inventories
nrfu Run ANTA tests on devices
```
> [!WARNING]
> The ANTA CLI options have changed after version 0.11 and have moved away from the top level `anta` and are now required at their respective commands (e.g. `anta nrfu`). This breaking change occurs after users feedback on making the CLI more intuitive. This change should not affect user experience when using environment variables.
## Documentation
The documentation is published on [ANTA package website](https://www.anta.ninja). Also, a [demo repository](https://github.com/titom73/atd-anta-demo) is available to facilitate your journey with ANTA.
## Contribution guide
Contributions are welcome. Please refer to the [contribution guide](contribution.md)
## Credits
Thank you to [Angélique Phillipps](https://github.com/aphillipps), [Colin MacGiollaEáin](https://github.com/colinmacgiolla), [Khelil Sator](https://github.com/ksator), [Matthieu Tache](https://github.com/mtache), [Onur Gashi](https://github.com/onurgashi), [Paul Lavelle](https://github.com/paullavelle), [Guillaume Mulocher](https://github.com/gmuloc) and [Thomas Grimonet](https://github.com/titom73) for their contributions and guidances.

View file

@ -0,0 +1,315 @@
<!--
~ 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.
-->
ANTA is a Python library that can be used in user applications. This section describes how you can leverage ANTA Python modules to help you create your own NRFU solution.
!!! tip
If you are unfamiliar with asyncio, refer to the Python documentation relevant to your Python version - https://docs.python.org/3/library/asyncio.html
## [AntaDevice](../api/device.md#anta.device.AntaDevice) Abstract Class
A device is represented in ANTA as a instance of a subclass of the [AntaDevice](../api/device.md### ::: anta.device.AntaDevice) abstract class.
There are few abstract methods that needs to be implemented by child classes:
- The [collect()](../api/device.md#anta.device.AntaDevice.collect) coroutine is in charge of collecting outputs of [AntaCommand](../api/models.md#anta.models.AntaCommand) instances.
- The [refresh()](../api/device.md#anta.device.AntaDevice.refresh) coroutine is in charge of updating attributes of the [AntaDevice](../api/device.md### ::: anta.device.AntaDevice) instance. These attributes are used by [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) to filter out unreachable devices or by [AntaTest](../api/models.md#anta.models.AntaTest) to skip devices based on their hardware models.
The [copy()](../api/device.md#anta.device.AntaDevice.copy) coroutine is used to copy files to and from the device. It does not need to be implemented if tests are not using it.
### [AsyncEOSDevice](../api/device.md#anta.device.AsyncEOSDevice) Class
The [AsyncEOSDevice](../api/device.md#anta.device.AsyncEOSDevice) class is an implementation of [AntaDevice](../api/device.md#anta.device.AntaDevice) for Arista EOS.
It uses the [aio-eapi](https://github.com/jeremyschulman/aio-eapi) eAPI client and the [AsyncSSH](https://github.com/ronf/asyncssh) library.
- The [collect()](../api/device.md#anta.device.AsyncEOSDevice.collect) coroutine collects [AntaCommand](../api/models.md#anta.models.AntaCommand) outputs using eAPI.
- The [refresh()](../api/device.md#anta.device.AsyncEOSDevice.refresh) coroutine tries to open a TCP connection on the eAPI port and update the `is_online` attribute accordingly. If the TCP connection succeeds, it sends a `show version` command to gather the hardware model of the device and updates the `established` and `hw_model` attributes.
- The [copy()](../api/device.md#anta.device.AsyncEOSDevice.copy) coroutine copies files to and from the device using the SCP protocol.
## [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) Class
The [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) class is a subclass of the standard Python type [dict](https://docs.python.org/3/library/stdtypes.html#dict). The keys of this dictionary are the device names, the values are [AntaDevice](../api/device.md#anta.device.AntaDevice) instances.
[AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) provides methods to interact with the ANTA inventory:
- The [add_device()](../api/inventory.md#anta.inventory.AntaInventory.add_device) method adds an [AntaDevice](../api/device.md### ::: anta.device.AntaDevice) instance to the inventory. Adding an entry to [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) with a key different from the device name is not allowed.
- The [get_inventory()](../api/inventory.md#anta.inventory.AntaInventory.get_inventory) returns a new [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) instance with filtered out devices based on the method inputs.
- The [connect_inventory()](../api/inventory.md#anta.inventory.AntaInventory.connect_inventory) coroutine will execute the [refresh()](../api/device.md#anta.device.AntaDevice.refresh) coroutines of all the devices in the inventory.
- The [parse()](../api/inventory.md#anta.inventory.AntaInventory.parse) static method creates an [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) instance from a YAML file and returns it. The devices are [AsyncEOSDevice](../api/device.md#anta.device.AsyncEOSDevice) instances.
To parse a YAML inventory file and print the devices connection status:
```python
"""
Example
"""
import asyncio
from anta.inventory import AntaInventory
async def main(inv: AntaInventory) -> None:
"""
Take an AntaInventory and:
1. try to connect to every device in the inventory
2. print a message for every device connection status
"""
await inv.connect_inventory()
for device in inv.values():
if device.established:
print(f"Device {device.name} is online")
else:
print(f"Could not connect to device {device.name}")
if __name__ == "__main__":
# Create the AntaInventory instance
inventory = AntaInventory.parse(
filename="inv.yml",
username="arista",
password="@rista123",
timeout=15,
)
# Run the main coroutine
res = asyncio.run(main(inventory))
```
??? note "How to create your inventory file"
Please visit this [dedicated section](../usage-inventory-catalog.md) for how to use inventory and catalog files.
To run an EOS commands list on the reachable devices from the inventory:
```python
"""
Example
"""
# This is needed to run the script for python < 3.10 for typing annotations
from __future__ import annotations
import asyncio
from pprint import pprint
from anta.inventory import AntaInventory
from anta.models import AntaCommand
async def main(inv: AntaInventory, commands: list[str]) -> dict[str, list[AntaCommand]]:
"""
Take an AntaInventory and a list of commands as string and:
1. try to connect to every device in the inventory
2. collect the results of the commands from each device
Returns:
a dictionary where key is the device name and the value is the list of AntaCommand ran towards the device
"""
await inv.connect_inventory()
# Make a list of coroutine to run commands towards each connected device
coros = []
# dict to keep track of the commands per device
result_dict = {}
for name, device in inv.get_inventory(established_only=True).items():
anta_commands = [AntaCommand(command=command, ofmt="json") for command in commands]
result_dict[name] = anta_commands
coros.append(device.collect_commands(anta_commands))
# Run the coroutines
await asyncio.gather(*coros)
return result_dict
if __name__ == "__main__":
# Create the AntaInventory instance
inventory = AntaInventory.parse(
filename="inv.yml",
username="arista",
password="@rista123",
timeout=15,
)
# Create a list of commands with json output
commands = ["show version", "show ip bgp summary"]
# Run the main asyncio entry point
res = asyncio.run(main(inventory, commands))
pprint(res)
```
## Use tests from ANTA
All the test classes inherit from the same abstract Base Class AntaTest. The Class definition indicates which commands are required for the test and the user should focus only on writing the `test` function with optional keywords argument. The instance of the class upon creation instantiates a TestResult object that can be accessed later on to check the status of the test ([unset, skipped, success, failure, error]).
### Test structure
All tests are built on a class named `AntaTest` which provides a complete toolset for a test:
- Object creation
- Test definition
- TestResult definition
- Abstracted method to collect data
This approach means each time you create a test it will be based on this `AntaTest` class. Besides that, you will have to provide some elements:
- `name`: Name of the test
- `description`: A human readable description of your test
- `categories`: a list of categories to sort test.
- `commands`: a list of command to run. This list _must_ be a list of `AntaCommand` which is described in the next part of this document.
Here is an example of a hardware test related to device temperature:
```python
from __future__ import annotations
import logging
from typing import Any, Dict, List, Optional, cast
from anta.models import AntaTest, AntaCommand
class VerifyTemperature(AntaTest):
"""
Verifies device temparture is currently OK.
"""
# The test name
name = "VerifyTemperature"
# A small description of the test, usually the first line of the class docstring
description = "Verifies device temparture is currently OK"
# The category of the test, usually the module name
categories = ["hardware"]
# The command(s) used for the test. Could be a template instead
commands = [AntaCommand(command="show system environment temperature", ofmt="json")]
# Decorator
@AntaTest.anta_test
# abstract method that must be defined by the child Test class
def test(self) -> None:
"""Run VerifyTemperature validation"""
command_output = cast(Dict[str, Dict[Any, Any]], self.instance_commands[0].output)
temperature_status = command_output["systemStatus"] if "systemStatus" in command_output.keys() else ""
if temperature_status == "temperatureOk":
self.result.is_success()
else:
self.result.is_failure(f"Device temperature is not OK, systemStatus: {temperature_status }")
```
When you run the test, object will automatically call its `anta.models.AntaTest.collect()` method to get device output for each command if no pre-collected data was given to the test. This method does a loop to call `anta.inventory.models.InventoryDevice.collect()` methods which is in charge of managing device connection and how to get data.
??? info "run test offline"
You can also pass eos data directly to your test if you want to validate data collected in a different workflow. An example is provided below just for information:
```python
test = VerifyTemperature(device, eos_data=test_data["eos_data"])
asyncio.run(test.test())
```
The `test` function is always the same and __must__ be defined with the `@AntaTest.anta_test` decorator. This function takes at least one argument which is a `anta.inventory.models.InventoryDevice` object.
In some cases a test would rely on some additional inputs from the user, for instance the number of expected peers or some expected numbers. All parameters __must__ come with a default value and the test function __should__ validate the parameters values (at this stage this is the only place where validation can be done but there are future plans to make this better).
```python
class VerifyTemperature(AntaTest):
...
@AntaTest.anta_test
def test(self) -> None:
pass
class VerifyTransceiversManufacturers(AntaTest):
...
@AntaTest.anta_test
def test(self, manufacturers: Optional[List[str]] = None) -> None:
# validate the manufactures parameter
pass
```
The test itself does not return any value, but the result is directly availble from your AntaTest object and exposes a `anta.result_manager.models.TestResult` object with result, name of the test and optional messages:
- `name` (str): Device name where the test has run.
- `test` (str): Test name runs on the device.
- `categories` (List[str]): List of categories the TestResult belongs to, by default the AntaTest categories.
- `description` (str): TestResult description, by default the AntaTest description.
- `results` (str): Result of the test. Can be one of ["unset", "success", "failure", "error", "skipped"].
- `message` (str, optional): Message to report after the test if any.
- `custom_field` (str, optional): Custom field to store a string for flexibility in integrating with ANTA
```python
from anta.tests.hardware import VerifyTemperature
test = VerifyTemperature(device, eos_data=test_data["eos_data"])
asyncio.run(test.test())
assert test.result.result == "success"
```
### Classes for commands
To make it easier to get data, ANTA defines 2 different classes to manage commands to send to devices:
#### [AntaCommand](../api/models.md#anta.models.AntaCommand) Class
Represent a command with following information:
- Command to run
- Ouput format expected
- eAPI version
- Output of the command
Usage example:
```python
from anta.models import AntaCommand
cmd1 = AntaCommand(command="show zerotouch")
cmd2 = AntaCommand(command="show running-config diffs", ofmt="text")
```
!!! tip "Command revision and version"
* Most of EOS commands return a JSON structure according to a model (some commands may not be modeled hence the necessity to use `text` outformat sometimes.
* The model can change across time (adding feature, ... ) and when the model is changed in a non backward-compatible way, the __revision__ number is bumped. The initial model starts with __revision__ 1.
* A __revision__ applies to a particular CLI command whereas a __version__ is global to an eAPI call. The __version__ is internally translated to a specific __revision__ for each CLI command in the RPC call. The currently supported __version__ vaues are `1` and `latest`.
* A __revision takes precedence over a version__ (e.g. if a command is run with version="latest" and revision=1, the first revision of the model is returned)
* By default eAPI returns the first revision of each model to ensure that when upgrading, intergation with existing tools is not broken. This is done by using by default `version=1` in eAPI calls.
ANTA uses by default `version="latest"` in AntaCommand. For some commands, you may want to run them with a different revision or version.
For instance the `VerifyRoutingTableSize` test leverages the first revision of `show bfd peers`:
```
# revision 1 as later revision introduce additional nesting for type
commands = [AntaCommand(command="show bfd peers", revision=1)]
```
#### [AntaTemplate](../api/models.md#anta.models.AntaTemplate) Class
Because some command can require more dynamic than just a command with no parameter provided by user, ANTA supports command template: you define a template in your test class and user provide parameters when creating test object.
```python
class RunArbitraryTemplateCommand(AntaTest):
"""
Run an EOS command and return result
Based on AntaTest to build relevant output for pytest
"""
name = "Run aributrary EOS command"
description = "To be used only with anta debug commands"
template = AntaTemplate(template="show interfaces {ifd}")
categories = ["debug"]
@AntaTest.anta_test
def test(self) -> None:
errdisabled_interfaces = [interface for interface, value in response["interfaceStatuses"].items() if value["linkStatus"] == "errdisabled"]
...
params = [{"ifd": "Ethernet2"}, {"ifd": "Ethernet49/1"}]
run_command1 = RunArbitraryTemplateCommand(device_anta, params)
```
In this example, test waits for interfaces to check from user setup and will only check for interfaces in `params`

View file

@ -0,0 +1,87 @@
<!--
~ 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.
-->
ANTA is a streamlined Python framework designed for efficient interaction with network devices. This section outlines how ANTA incorporates caching mechanisms to collect command outputs from network devices.
## Configuration
By default, ANTA utilizes [aiocache](https://github.com/aio-libs/aiocache)'s memory cache backend, also called [`SimpleMemoryCache`](https://aiocache.aio-libs.org/en/v0.12.2/caches.html#simplememorycache). This library aims for simplicity and supports asynchronous operations to go along with Python `asyncio` used in ANTA.
The `_init_cache()` method of the [AntaDevice](../advanced_usages/as-python-lib.md#antadevice-abstract-class) abstract class initializes the cache. Child classes can override this method to tweak the cache configuration:
```python
def _init_cache(self) -> None:
"""
Initialize cache for the device, can be overridden by subclasses to manipulate how it works
"""
self.cache = Cache(cache_class=Cache.MEMORY, ttl=60, namespace=self.name, plugins=[HitMissRatioPlugin()])
self.cache_locks = defaultdict(asyncio.Lock)
```
The cache is also configured with `aiocache`'s [`HitMissRatioPlugin`](https://aiocache.aio-libs.org/en/v0.12.2/plugins.html#hitmissratioplugin) plugin to calculate the ratio of hits the cache has and give useful statistics for logging purposes in ANTA.
## Cache key design
The cache is initialized per `AntaDevice` and uses the following cache key design:
`<device_name>:<uid>`
The `uid` is an attribute of [AntaCommand](../advanced_usages/as-python-lib.md#antacommand-class), which is a unique identifier generated from the command, version, revision and output format.
Each UID has its own asyncio lock. This design allows coroutines that need to access the cache for different UIDs to do so concurrently. The locks are managed by the `self.cache_locks` dictionary.
## Mechanisms
By default, once the cache is initialized, it is used in the `collect()` method of `AntaDevice`. The `collect()` method prioritizes retrieving the output of the command from the cache. If the output is not in the cache, the private `_collect()` method will retrieve and then store it for future access.
## How to disable caching
Caching is enabled by default in ANTA following the previous configuration and mechanisms.
There might be scenarios where caching is not wanted. You can disable caching in multiple ways in ANTA:
1. Caching can be disabled globally, for **ALL** commands on **ALL** devices, using the `--disable-cache` global flag when invoking anta at the [CLI](../cli/overview.md#invoking-anta-cli):
```bash
anta --disable-cache --username arista --password arista nrfu table
```
2. Caching can be disabled per device, network or range by setting the `disable_cache` key to `True` when definining the ANTA [Inventory](../usage-inventory-catalog.md#create-an-inventory-file) file:
```yaml
anta_inventory:
hosts:
- host: 172.20.20.101
name: DC1-SPINE1
tags: ["SPINE", "DC1"]
disable_cache: True # Set this key to True
- host: 172.20.20.102
name: DC1-SPINE2
tags: ["SPINE", "DC1"]
disable_cache: False # Optional since it's the default
networks:
- network: "172.21.21.0/24"
disable_cache: True
ranges:
- start: 172.22.22.10
end: 172.22.22.19
disable_cache: True
```
This approach effectively disables caching for **ALL** commands sent to devices targeted by the `disable_cache` key.
3. For tests developpers, caching can be disabled for a specific [`AntaCommand`](../advanced_usages/as-python-lib.md#antacommand-class) or [`AntaTemplate`](../advanced_usages/as-python-lib.md#antatemplate-class) by setting the `use_cache` attribute to `False`. That means the command output will always be collected on the device and therefore, never use caching.
### Disable caching in a child class of `AntaDevice`
Since caching is implemented at the `AntaDevice` abstract class level, all subclasses will inherit that default behavior. As a result, if you need to disable caching in any custom implementation of `AntaDevice` outside of the ANTA framework, you must initialize `AntaDevice` with `disable_cache` set to `True`:
```python
class AnsibleEOSDevice(AntaDevice):
"""
Implementation of an AntaDevice using Ansible HttpApi plugin for EOS.
"""
def __init__(self, name: str, connection: ConnectionBase, tags: list = None) -> None:
super().__init__(name, tags, disable_cache=True)
```

View file

@ -0,0 +1,324 @@
<!--
~ 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.
-->
!!! info ""
This documentation applies for both creating tests in ANTA or creating your own test package.
ANTA is not only a Python library with a CLI and a collection of built-in tests, it is also a framework you can extend by building your own tests.
## Generic approach
A test is a Python class where a test function is defined and will be run by the framework.
ANTA provides an abstract class [AntaTest](../api/models.md#anta.models.AntaTest). This class does the heavy lifting and provide the logic to define, collect and test data. The code below is an example of a simple test in ANTA, which is an [AntaTest](../api/models.md#anta.models.AntaTest) subclass:
```python
from anta.models import AntaTest, AntaCommand
from anta.decorators import skip_on_platforms
class VerifyTemperature(AntaTest):
"""
This test verifies if the device temperature is within acceptable limits.
Expected Results:
* success: The test will pass if the device temperature is currently OK: 'temperatureOk'.
* failure: The test will fail if the device temperature is NOT OK.
"""
name = "VerifyTemperature"
description = "Verifies if the device temperature is within the acceptable range."
categories = ["hardware"]
commands = [AntaCommand(command="show system environment temperature", ofmt="json")]
@skip_on_platforms(["cEOSLab", "vEOS-lab"])
@AntaTest.anta_test
def test(self) -> None:
command_output = self.instance_commands[0].json_output
temperature_status = command_output["systemStatus"] if "systemStatus" in command_output.keys() else ""
if temperature_status == "temperatureOk":
self.result.is_success()
else:
self.result.is_failure(f"Device temperature exceeds acceptable limits. Current system status: '{temperature_status}'")
```
[AntaTest](../api/models.md#anta.models.AntaTest) also provide more advanced capabilities like [AntaCommand](../api/models.md#anta.models.AntaCommand) templating using the [AntaTemplate](../api/models.md#anta.models.AntaTemplate) class or test inputs definition and validation using [AntaTest.Input](../api/models.md#anta.models.AntaTest.Input) [pydantic](https://docs.pydantic.dev/latest/) model. This will be discussed in the sections below.
## [AntaTest](../api/models.md#anta.models.AntaTest) structure
### Class Attributes
- `name` (`str`): Name of the test. Used during reporting.
- `description` (`str`): A human readable description of your test.
- `categories` (`list[str]`): A list of categories in which the test belongs.
- `commands` (`list[Union[AntaTemplate, AntaCommand]]`): A list of command to collect from devices. This list __must__ be a list of [AntaCommand](../api/models.md#anta.models.AntaCommand) or [AntaTemplate](../api/models.md#anta.models.AntaTemplate) instances. Rendering [AntaTemplate](../api/models.md#anta.models.AntaTemplate) instances will be discussed later.
!!! info
All these class attributes are mandatory. If any attribute is missing, a `NotImplementedError` exception will be raised during class instantiation.
### Instance Attributes
!!! info
You can access an instance attribute in your code using the `self` reference. E.g. you can access the test input values using `self.inputs`.
::: anta.models.AntaTest
options:
show_docstring_attributes: true
show_root_heading: false
show_bases: false
show_docstring_description: false
show_docstring_examples: false
show_docstring_parameters: false
members: false
show_source: false
show_root_toc_entry: false
heading_level: 10
!!! note "Logger object"
ANTA already provides comprehensive logging at every steps of a test execution. The [AntaTest](../api/models.md#anta.models.AntaTest) class also provides a `logger` attribute that is a Python logger specific to the test instance. See [Python documentation](https://docs.python.org/3/library/logging.html) for more information.
!!! note "AntaDevice object"
Even if `device` is not a private attribute, you should not need to access this object in your code.
### Test Inputs
[AntaTest.Input](../api/models.md#anta.models.AntaTest.Input) is a [pydantic model](https://docs.pydantic.dev/latest/usage/models/) that allow test developers to define their test inputs. [pydantic](https://docs.pydantic.dev/latest/) provides out of the box [error handling](https://docs.pydantic.dev/latest/usage/models/#error-handling) for test input validation based on the type hints defined by the test developer.
The base definition of [AntaTest.Input](../api/models.md#anta.models.AntaTest.Input) provides common test inputs for all [AntaTest](../api/models.md#anta.models.AntaTest) instances:
#### [Input](../api/models.md#anta.models.AntaTest.Input) model
::: anta.models.AntaTest.Input
options:
show_docstring_attributes: true
show_root_heading: false
show_category_heading: false
show_bases: false
show_docstring_description: false
show_docstring_examples: false
show_docstring_parameters: false
show_source: false
members: false
show_root_toc_entry: false
heading_level: 10
#### [ResultOverwrite](../api/models.md#anta.models.AntaTest.Input.ResultOverwrite) model
::: anta.models.AntaTest.Input.ResultOverwrite
options:
show_docstring_attributes: true
show_root_heading: false
show_category_heading: false
show_bases: false
show_docstring_description: false
show_docstring_examples: false
show_docstring_parameters: false
show_source: false
show_root_toc_entry: false
heading_level: 10
!!! note
The pydantic model is configured using the [`extra=forbid`](https://docs.pydantic.dev/latest/usage/model_config/#extra-attributes) that will fail input validation if extra fields are provided.
### Methods
- [test(self) -> None](../api/models.md#anta.models.AntaTest.test): This is an abstract method that __must__ be implemented. It contains the test logic that can access the collected command outputs using the `instance_commands` instance attribute, access the test inputs using the `inputs` instance attribute and __must__ set the `result` instance attribute accordingly. It must be implemented using the `AntaTest.anta_test` decorator that provides logging and will collect commands before executing the `test()` method.
- [render(self, template: AntaTemplate) -> list[AntaCommand]](../api/models.md#anta.models.AntaTest.render): This method only needs to be implemented if [AntaTemplate](../api/models.md#anta.models.AntaTemplate) instances are present in the `commands` class attribute. It will be called for every [AntaTemplate](../api/models.md#anta.models.AntaTemplate) occurence and __must__ return a list of [AntaCommand](../api/models.md#anta.models.AntaCommand) using the [AntaTemplate.render()](../api/models.md#anta.models.AntaTemplate.render) method. It can access test inputs using the `inputs` instance attribute.
## Test execution
Below is a high level description of the test execution flow in ANTA:
1. ANTA will parse the test catalog to get the list of [AntaTest](../api/models.md#anta.models.AntaTest) subclasses to instantiate and their associated input values. We consider a single [AntaTest](../api/models.md#anta.models.AntaTest) subclass in the following steps.
2. ANTA will instantiate the [AntaTest](../api/models.md#anta.models.AntaTest) subclass and a single device will be provided to the test instance. The `Input` model defined in the class will also be instantiated at this moment. If any [ValidationError](https://docs.pydantic.dev/latest/errors/errors/) is raised, the test execution will be stopped.
3. If there is any [AntaTemplate](../api/models.md#anta.models.AntaTemplate) instance in the `commands` class attribute, [render()](../api/models.md#anta.models.AntaTest.render) will be called for every occurrence. At this moment, the `instance_commands` attribute has been initialized. If any rendering error occurs, the test execution will be stopped.
4. The `AntaTest.anta_test` decorator will collect the commands from the device and update the `instance_commands` attribute with the outputs. If any collection error occurs, the test execution will be stopped.
5. The [test()](../api/models.md#anta.models.AntaTest.test) method is executed.
## Writing an AntaTest subclass
In this section, we will go into all the details of writing an [AntaTest](../api/models.md#anta.models.AntaTest) subclass.
### Class definition
Import [anta.models.AntaTest](../api/models.md#anta.models.AntaTest) and define your own class.
Define the mandatory class attributes using [anta.models.AntaCommand](../api/models.md#anta.models.AntaCommand), [anta.models.AntaTemplate](../api/models.md#anta.models.AntaTemplate) or both.
!!! info
Caching can be disabled per `AntaCommand` or `AntaTemplate` by setting the `use_cache` argument to `False`. For more details about how caching is implemented in ANTA, please refer to [Caching in ANTA](../advanced_usages/caching.md).
```python
from anta.models import AntaTest, AntaCommand, AntaTemplate
class <YourTestName>(AntaTest):
"""
<a docstring description of your test>
"""
name = "YourTestName" # should be your class name
description = "<test description in human reading format>"
categories = ["<arbitrary category>", "<another arbitrary category>"]
commands = [
AntaCommand(
command="<EOS command to run>",
ofmt="<command format output>",
version="<eAPI version to use>",
revision="<revision to use for the command>", # revision has precedence over version
use_cache="<Use cache for the command>",
),
AntaTemplate(
template="<Python f-string to render an EOS command>",
ofmt="<command format output>",
version="<eAPI version to use>",
revision="<revision to use for the command>", # revision has precedence over version
use_cache="<Use cache for the command>",
)
]
```
### Inputs definition
If the user needs to provide inputs for your test, you need to define a [pydantic model](https://docs.pydantic.dev/latest/usage/models/) that defines the schema of the test inputs:
```python
class <YourTestName>(AntaTest):
...
class Input(AntaTest.Input): # pylint: disable=missing-class-docstring
<input field name>: <input field type>
"""<input field docstring>"""
```
To define an input field type, refer to the [pydantic documentation](https://docs.pydantic.dev/latest/usage/types/types/) about types.
You can also leverage [anta.custom_types](../api/types.md) that provides reusable types defined in ANTA tests.
Regarding required, optional and nullable fields, refer to this [documentation](https://docs.pydantic.dev/latest/migration/#required-optional-and-nullable-fields) on how to define them.
!!! note
All the `pydantic` features are supported. For instance you can define [validators](https://docs.pydantic.dev/latest/usage/validators/) for complex input validation.
### Template rendering
Define the `render()` method if you have [AntaTemplate](../api/models.md#anta.models.AntaTemplate) instances in your `commands` class attribute:
```python
class <YourTestName>(AntaTest):
...
def render(self, template: AntaTemplate) -> list[AntaCommand]:
return [template.render(<template param>=input_value) for input_value in self.inputs.<input_field>]
```
You can access test inputs and render as many [AntaCommand](../api/models.md#anta.models.AntaCommand) as desired.
### Test definition
Implement the `test()` method with your test logic:
```python
class <YourTestName>(AntaTest):
...
@AntaTest.anta_test
def test(self) -> None:
pass
```
The logic usually includes the following different stages:
1. Parse the command outputs using the `self.instance_commands` instance attribute.
2. If needed, access the test inputs using the `self.inputs` instance attribute and write your conditional logic.
3. Set the `result` instance attribute to reflect the test result by either calling `self.result.is_success()` or `self.result.is_failure("<FAILURE REASON>")`. Sometimes, setting the test result to `skipped` using `self.result.is_skipped("<SKIPPED REASON>")` can make sense (e.g. testing the OSPF neighbor states but no neighbor was found). However, you should not need to catch any exception and set the test result to `error` since the error handling is done by the framework, see below.
The example below is based on the [VerifyTemperature](../api/tests.hardware.md#anta.tests.hardware.VerifyTemperature) test.
```python
class VerifyTemperature(AntaTest):
...
@AntaTest.anta_test
def test(self) -> None:
# Grab output of the collected command
command_output = self.instance_commands[0].json_output
# Do your test: In this example we check a specific field of the JSON output from EOS
temperature_status = command_output["systemStatus"] if "systemStatus" in command_output.keys() else ""
if temperature_status == "temperatureOk":
self.result.is_success()
else:
self.result.is_failure(f"Device temperature exceeds acceptable limits. Current system status: '{temperature_status}'")
```
As you can see there is no error handling to do in your code. Everything is packaged in the `AntaTest.anta_tests` decorator and below is a simple example of error captured when trying to access a dictionary with an incorrect key:
```python
class VerifyTemperature(AntaTest):
...
@AntaTest.anta_test
def test(self) -> None:
# Grab output of the collected command
command_output = self.instance_commands[0].json_output
# Access the dictionary with an incorrect key
command_output['incorrectKey']
```
```bash
ERROR Exception raised for test VerifyTemperature (on device 192.168.0.10) - KeyError ('incorrectKey')
```
!!! info "Get stack trace for debugging"
If you want to access to the full exception stack, you can run ANTA in debug mode by setting the `ANTA_DEBUG` environment variable to `true`. Example:
```bash
$ ANTA_DEBUG=true anta nrfu --catalog test_custom.yml text
```
### Test decorators
In addition to the required `AntaTest.anta_tests` decorator, ANTA offers a set of optional decorators for further test customization:
- `anta.decorators.deprecated_test`: Use this to log a message of WARNING severity when a test is deprecated.
- `anta.decorators.skip_on_platforms`: Use this to skip tests for functionalities that are not supported on specific platforms.
```python
from anta.decorators import skip_on_platforms
class VerifyTemperature(AntaTest):
...
@skip_on_platforms(["cEOSLab", "vEOS-lab"])
@AntaTest.anta_test
def test(self) -> None:
pass
```
## Access your custom tests in the test catalog
!!! warning ""
This section is required only if you are not merging your development into ANTA. Otherwise, just follow [contribution guide](../contribution.md).
For that, you need to create your own Python package as described in this [hitchhiker's guide](https://the-hitchhikers-guide-to-packaging.readthedocs.io/en/latest/) to package Python code. We assume it is well known and we won't focus on this aspect. Thus, your package must be impartable by ANTA hence available in the module search path `sys.path` (you can use `PYTHONPATH` for example).
It is very similar to what is documented in [catalog section](../usage-inventory-catalog.md) but you have to use your own package name.2
Let say the custom Python package is `anta_titom73` and the test is defined in `anta_titom73.dc_project` Python module, the test catalog would look like:
```yaml
anta_titom73.dc_project:
- VerifyFeatureX:
minimum: 1
```
And now you can run your NRFU tests with the CLI:
```bash
anta nrfu text --catalog test_custom.yml
spine01 :: verify_dynamic_vlan :: FAILURE (Device has 0 configured, we expect at least 1)
spine02 :: verify_dynamic_vlan :: FAILURE (Device has 0 configured, we expect at least 1)
leaf01 :: verify_dynamic_vlan :: SUCCESS
leaf02 :: verify_dynamic_vlan :: SUCCESS
leaf03 :: verify_dynamic_vlan :: SUCCESS
leaf04 :: verify_dynamic_vlan :: SUCCESS
```

13
docs/api/catalog.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
### ::: anta.catalog.AntaCatalog
options:
filters: ["!^_[^_]", "!__str__"]
### ::: anta.catalog.AntaTestDefinition
### ::: anta.catalog.AntaCatalogFile

25
docs/api/device.md Normal file
View file

@ -0,0 +1,25 @@
<!--
~ 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.
-->
# AntaDevice base class
## UML representation
![](../imgs/uml/anta.device.AntaDevice.jpeg)
### ::: anta.device.AntaDevice
options:
filters: ["!^_[^_]", "!__(eq|rich_repr)__"]
# Async EOS device class
## UML representation
![](../imgs/uml/anta.device.AsyncEOSDevice.jpeg)
### ::: anta.device.AsyncEOSDevice
options:
filters: ["!^_[^_]", "!__(eq|rich_repr)__"]

11
docs/api/inventory.md Normal file
View file

@ -0,0 +1,11 @@
<!--
~ 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.
-->
### ::: anta.inventory.AntaInventory
options:
filters: ["!^_[^_]", "!__str__"]
### ::: anta.inventory.exceptions

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
### ::: anta.inventory.models.AntaInventoryInput
### ::: anta.inventory.models.AntaInventoryHost
### ::: anta.inventory.models.AntaInventoryNetwork
### ::: anta.inventory.models.AntaInventoryRange

37
docs/api/models.md Normal file
View 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.
-->
# Test definition
## UML Diagram
![](../imgs/uml/anta.models.AntaTest.jpeg)
### ::: anta.models.AntaTest
options:
filters: ["!^_[^_]", "!__init_subclass__", "!update_progress"]
# Command definition
## UML Diagram
![](../imgs/uml/anta.models.AntaCommand.jpeg)
### ::: anta.models.AntaCommand
!!! warning
CLI commands are protected to avoid execution of critical commands such as `reload` or `write erase`.
- Reload command: `^reload\s*\w*`
- Configure mode: `^conf\w*\s*(terminal|session)*`
- Write: `^wr\w*\s*\w+`
# Template definition
## UML Diagram
![](../imgs/uml/anta.models.AntaTemplate.jpeg)
### ::: anta.models.AntaTemplate

View 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.
-->
### ::: anta.reporter.ReportTable

View file

@ -0,0 +1,15 @@
<!--
~ 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.
-->
# Result Manager definition
## UML Diagram
![](../imgs/uml/anta.result_manager.ResultManager.jpeg)
### ::: anta.result_manager.ResultManager
options:
filters: ["!^_[^_]", "!^__len__"]

View file

@ -0,0 +1,15 @@
<!--
~ 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 Result model
## UML Diagram
![](../imgs/uml/anta.result_manager.models.TestResult.jpeg)
### ::: anta.result_manager.models.TestResult
options:
filters: ["!^_[^_]", "!__str__"]

13
docs/api/tests.aaa.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for interfaces tests
::: anta.tests.aaa
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.bfd.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for bfd tests
::: anta.tests.bfd
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for configuration tests
::: anta.tests.configuration
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for connectivity tests
::: anta.tests.connectivity
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for Field Notices tests
::: anta.tests.field_notices
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for hardware tests
::: anta.tests.hardware
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for interfaces tests
::: anta.tests.interfaces
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.logging.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for logging tests
::: anta.tests.logging
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

37
docs/api/tests.md Normal file
View 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.
-->
# ANTA Tests landing page
This section describes all the available tests provided by ANTA package.
- [AAA](tests.aaa.md)
- [BFD](tests.bfd.md)
- [Configuration](tests.configuration.md)
- [Connectivity](tests.connectivity.md)
- [Field Notice](tests.field_notices.md)
- [Hardware](tests.hardware.md)
- [Interfaces](tests.interfaces.md)
- [Logging](tests.logging.md)
- [MLAG](tests.mlag.md)
- [Multicast](tests.multicast.md)
- [Profiles](tests.profiles.md)
- [Routing Generic](tests.routing.generic.md)
- [Routing BGP](tests.routing.bgp.md)
- [Routing OSPF](tests.routing.ospf.md)
- [Security](tests.security.md)
- [Services](tests.services.md)
- [SNMP](tests.snmp.md)
- [Software](tests.software.md)
- [STP](tests.stp.md)
- [System](tests.system.md)
- [VLAN](tests.vlan.md)
- [VXLAN](tests.vxlan.md)
All these tests can be imported in a [catalog](../usage-inventory-catalog.md) to be used by [the anta cli](../cli/nrfu.md) or in your [own framework](../advanced_usages/as-python-lib.md)

13
docs/api/tests.mlag.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for mlag tests
::: anta.tests.mlag
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for multicast tests
::: anta.tests.multicast
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for profiles tests
::: anta.tests.profiles
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for BGP tests
::: anta.tests.routing.bgp
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for routing-generic tests
::: anta.tests.routing.generic
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for routing-ospf tests
::: anta.tests.routing.ospf
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for security tests
::: anta.tests.security
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for services tests
::: anta.tests.services
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.snmp.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for SNMP tests
::: anta.tests.snmp
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for software tests
::: anta.tests.software
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.stp.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for STP tests
::: anta.tests.stp
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.system.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for system tests
::: anta.tests.system
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.vlan.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for vlan tests
::: anta.tests.vlan
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

13
docs/api/tests.vxlan.md Normal file
View file

@ -0,0 +1,13 @@
<!--
~ 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.
-->
# ANTA catalog for VXLAN tests
::: anta.tests.vxlan
options:
show_root_heading: false
show_root_toc_entry: false
merge_init_into_class: false

10
docs/api/types.md Normal file
View file

@ -0,0 +1,10 @@
<!--
~ 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.
-->
### ::: anta.custom_types
options:
show_if_no_docstring: true
show_root_full_path: true

36
docs/cli/check.md Normal file
View file

@ -0,0 +1,36 @@
<!--
~ 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.
-->
# ANTA check commands
The ANTA check command allow to execute some checks on the ANTA input files.
Only checking the catalog is currently supported.
```bash
anta check --help
Usage: anta check [OPTIONS] COMMAND [ARGS]...
Check commands for building ANTA
Options:
--help Show this message and exit.
Commands:
catalog Check that the catalog is valid
```
## Checking the catalog
```bash
Usage: anta check catalog [OPTIONS]
Check that the catalog is valid
Options:
-c, --catalog FILE Path to the test catalog YAML file [env var:
ANTA_CATALOG; required]
--help Show this message and exit.
```

175
docs/cli/debug.md Normal file
View 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.
-->
# ANTA debug commands
The ANTA CLI includes a set of debugging tools, making it easier to build and test ANTA content. This functionality is accessed via the `debug` subcommand and offers the following options:
- Executing a command on a device from your inventory and retrieving the result.
- Running a templated command on a device from your inventory and retrieving the result.
These tools are especially helpful in building the tests, as they give a visual access to the output received from the eAPI. They also facilitate the extraction of output content for use in unit tests, as described in our [contribution guide](../contribution.md).
!!! warning
The `debug` tools require a device from your inventory. Thus, you MUST use a valid [ANTA Inventory](../usage-inventory-catalog.md#create-an-inventory-file).
## Executing an EOS command
You can use the `run-cmd` entrypoint to run a command, which includes the following options:
### Command overview
```bash
$ anta debug run-cmd --help
Usage: anta debug run-cmd [OPTIONS]
Run arbitrary command to an ANTA device
Options:
-u, --username TEXT Username to connect to EOS [env var:
ANTA_USERNAME; required]
-p, --password TEXT Password to connect to EOS that must be provided.
It can be prompted using '--prompt' option. [env
var: ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It
can be prompted using '--prompt' option. Requires
'--enable' option. [env var:
ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC
mode. This option tries to access this mode before
sending a command to the device. [env var:
ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided.
[env var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
--ofmt [json|text] EOS eAPI format to use. can be text or json
-v, --version [1|latest] EOS eAPI version
-r, --revision INTEGER eAPI command revision
-d, --device TEXT Device from inventory to use [required]
-c, --command TEXT Command to run [required]
--help Show this message and exit.
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
### Example
This example illustrates how to run the `show interfaces description` command with a `JSON` format (default):
```bash
anta debug run-cmd --command "show interfaces description" --device DC1-SPINE1
Run command show interfaces description on DC1-SPINE1
{
'interfaceDescriptions': {
'Ethernet1': {'lineProtocolStatus': 'up', 'description': 'P2P_LINK_TO_DC1-LEAF1A_Ethernet1', 'interfaceStatus': 'up'},
'Ethernet2': {'lineProtocolStatus': 'up', 'description': 'P2P_LINK_TO_DC1-LEAF1B_Ethernet1', 'interfaceStatus': 'up'},
'Ethernet3': {'lineProtocolStatus': 'up', 'description': 'P2P_LINK_TO_DC1-BL1_Ethernet1', 'interfaceStatus': 'up'},
'Ethernet4': {'lineProtocolStatus': 'up', 'description': 'P2P_LINK_TO_DC1-BL2_Ethernet1', 'interfaceStatus': 'up'},
'Loopback0': {'lineProtocolStatus': 'up', 'description': 'EVPN_Overlay_Peering', 'interfaceStatus': 'up'},
'Management0': {'lineProtocolStatus': 'up', 'description': 'oob_management', 'interfaceStatus': 'up'}
}
}
```
## Executing an EOS command using templates
The `run-template` entrypoint allows the user to provide an [`f-string`](https://realpython.com/python-f-strings/#f-strings-a-new-and-improved-way-to-format-strings-in-python) templated command. It is followed by a list of arguments (key-value pairs) that build a dictionary used as template parameters.
### Command overview
```bash
$ anta debug run-template --help
Usage: anta debug run-template [OPTIONS] PARAMS...
Run arbitrary templated command to an ANTA device.
Takes a list of arguments (keys followed by a value) to build a dictionary
used as template parameters. Example:
anta debug run-template -d leaf1a -t 'show vlan {vlan_id}' vlan_id 1
Options:
-u, --username TEXT Username to connect to EOS [env var:
ANTA_USERNAME; required]
-p, --password TEXT Password to connect to EOS that must be provided.
It can be prompted using '--prompt' option. [env
var: ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It
can be prompted using '--prompt' option. Requires
'--enable' option. [env var:
ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC
mode. This option tries to access this mode before
sending a command to the device. [env var:
ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided.
[env var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
--ofmt [json|text] EOS eAPI format to use. can be text or json
-v, --version [1|latest] EOS eAPI version
-r, --revision INTEGER eAPI command revision
-d, --device TEXT Device from inventory to use [required]
-t, --template TEXT Command template to run. E.g. 'show vlan
{vlan_id}' [required]
--help Show this message and exit.
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
### Example
This example uses the `show vlan {vlan_id}` command in a `JSON` format:
```bash
anta debug run-template --template "show vlan {vlan_id}" vlan_id 10 --device DC1-LEAF1A
Run templated command 'show vlan {vlan_id}' with {'vlan_id': '10'} on DC1-LEAF1A
{
'vlans': {
'10': {
'name': 'VRFPROD_VLAN10',
'dynamic': False,
'status': 'active',
'interfaces': {
'Cpu': {'privatePromoted': False, 'blocked': None},
'Port-Channel11': {'privatePromoted': False, 'blocked': None},
'Vxlan1': {'privatePromoted': False, 'blocked': None}
}
}
},
'sourceDetail': ''
}
```
!!! warning
If multiple arguments of the same key are provided, only the last argument value will be kept in the template parameters.
### Example of multiple arguments
```bash
anta -log DEBUG debug run-template --template "ping {dst} source {src}" dst "8.8.8.8" src Loopback0 --device DC1-SPINE1    
> {'dst': '8.8.8.8', 'src': 'Loopback0'}
anta -log DEBUG debug run-template --template "ping {dst} source {src}" dst "8.8.8.8" src Loopback0 dst "1.1.1.1" src Loopback1 --device DC1-SPINE1          
> {'dst': '1.1.1.1', 'src': 'Loopback1'}
# Notice how `src` and `dst` keep only the latest value
```

298
docs/cli/exec.md Normal file
View 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.
-->
# Executing Commands on Devices
ANTA CLI provides a set of entrypoints to facilitate remote command execution on EOS devices.
### EXEC Command overview
```bash
anta exec --help
Usage: anta exec [OPTIONS] COMMAND [ARGS]...
Execute commands to inventory devices
Options:
--help Show this message and exit.
Commands:
clear-counters Clear counter statistics on EOS devices
collect-tech-support Collect scheduled tech-support from EOS devices
snapshot Collect commands output from devices in inventory
```
## Clear interfaces counters
This command clears interface counters on EOS devices specified in your inventory.
### Command overview
```bash
anta exec clear-counters --help
Usage: anta exec clear-counters [OPTIONS]
Clear counter statistics on EOS devices
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
required]
-p, --password TEXT Password to connect to EOS that must be provided. It
can be prompted using '--prompt' option. [env var:
ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It can
be prompted using '--prompt' option. Requires '--
enable' option. [env var: ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC mode.
This option tries to access this mode before sending
a command to the device. [env var: ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided. [env
var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
--help Show this message and exit.
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
### Example
```bash
anta exec clear-counters --tags SPINE
[20:19:13] INFO Connecting to devices... utils.py:43
INFO Clearing counters on remote devices... utils.py:46
INFO Cleared counters on DC1-SPINE2 (cEOSLab) utils.py:41
INFO Cleared counters on DC2-SPINE1 (cEOSLab) utils.py:41
INFO Cleared counters on DC1-SPINE1 (cEOSLab) utils.py:41
INFO Cleared counters on DC2-SPINE2 (cEOSLab)
```
## Collect a set of commands
This command collects all the commands specified in a commands-list file, which can be in either `json` or `text` format.
### Command overview
```bash
anta exec snapshot --help
Usage: anta exec snapshot [OPTIONS]
Collect commands output from devices in inventory
Options:
-u, --username TEXT Username to connect to EOS [env var:
ANTA_USERNAME; required]
-p, --password TEXT Password to connect to EOS that must be provided.
It can be prompted using '--prompt' option. [env
var: ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It
can be prompted using '--prompt' option. Requires
'--enable' option. [env var:
ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC
mode. This option tries to access this mode before
sending a command to the device. [env var:
ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided.
[env var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
-c, --commands-list FILE File with list of commands to collect [env var:
ANTA_EXEC_SNAPSHOT_COMMANDS_LIST; required]
-o, --output DIRECTORY Directory to save commands output. [env var:
ANTA_EXEC_SNAPSHOT_OUTPUT; default:
anta_snapshot_2023-12-06_09_22_11]
--help Show this message and exit.
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
The commands-list file should follow this structure:
```yaml
---
json_format:
- show version
text_format:
- show bfd peers
```
### Example
```bash
anta exec snapshot --tags SPINE --commands-list ./commands.yaml --output ./
[20:25:15] INFO Connecting to devices... utils.py:78
INFO Collecting commands from remote devices utils.py:81
INFO Collected command 'show version' from device DC2-SPINE1 (cEOSLab) utils.py:76
INFO Collected command 'show version' from device DC2-SPINE2 (cEOSLab) utils.py:76
INFO Collected command 'show version' from device DC1-SPINE1 (cEOSLab) utils.py:76
INFO Collected command 'show version' from device DC1-SPINE2 (cEOSLab) utils.py:76
[20:25:16] INFO Collected command 'show bfd peers' from device DC2-SPINE2 (cEOSLab) utils.py:76
INFO Collected command 'show bfd peers' from device DC2-SPINE1 (cEOSLab) utils.py:76
INFO Collected command 'show bfd peers' from device DC1-SPINE1 (cEOSLab) utils.py:76
INFO Collected command 'show bfd peers' from device DC1-SPINE2 (cEOSLab)
```
The results of the executed commands will be stored in the output directory specified during command execution:
```bash
tree _2023-07-14_20_25_15
_2023-07-14_20_25_15
├── DC1-SPINE1
│   ├── json
│   │   └── show version.json
│   └── text
│   └── show bfd peers.log
├── DC1-SPINE2
│   ├── json
│   │   └── show version.json
│   └── text
│   └── show bfd peers.log
├── DC2-SPINE1
│   ├── json
│   │   └── show version.json
│   └── text
│   └── show bfd peers.log
└── DC2-SPINE2
├── json
│   └── show version.json
└── text
└── show bfd peers.log
12 directories, 8 files
```
## Get Scheduled tech-support
EOS offers a feature that automatically creates a tech-support archive every hour by default. These archives are stored under `/mnt/flash/schedule/tech-support`.
```eos
leaf1#show schedule summary
Maximum concurrent jobs 1
Prepend host name to logfile: Yes
Name At Time Last Interval Timeout Max Max Logfile Location Status
Time (mins) (mins) Log Logs
Files Size
----------------- ------------- ----------- -------------- ------------- ----------- ---------- --------------------------------- ------
tech-support now 08:37 60 30 100 - flash:schedule/tech-support/ Success
leaf1#bash ls /mnt/flash/schedule/tech-support
leaf1_tech-support_2023-03-09.1337.log.gz leaf1_tech-support_2023-03-10.0837.log.gz leaf1_tech-support_2023-03-11.0337.log.gz
```
For Network Readiness for Use (NRFU) tests and to keep a comprehensive report of the system state before going live, ANTA provides a command-line interface that efficiently retrieves these files.
### Command overview
```bash
anta exec collect-tech-support --help
Usage: anta exec collect-tech-support [OPTIONS]
Collect scheduled tech-support from EOS devices
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
required]
-p, --password TEXT Password to connect to EOS that must be provided. It
can be prompted using '--prompt' option. [env var:
ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It can
be prompted using '--prompt' option. Requires '--
enable' option. [env var: ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC mode.
This option tries to access this mode before sending
a command to the device. [env var: ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided. [env
var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
-o, --output PATH Path for test catalog [default: ./tech-support]
--latest INTEGER Number of scheduled show-tech to retrieve
--configure Ensure devices have 'aaa authorization exec default
local' configured (required for SCP on EOS). THIS
WILL CHANGE THE CONFIGURATION OF YOUR NETWORK.
--help Show this message and exit.
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
When executed, this command fetches tech-support files and downloads them locally into a device-specific subfolder within the designated folder. You can specify the output folder with the `--output` option.
ANTA uses SCP to download files from devices and will not trust unknown SSH hosts by default. Add the SSH public keys of your devices to your `known_hosts` file or use the `anta --insecure` option to ignore SSH host keys validation.
The configuration `aaa authorization exec default` must be present on devices to be able to use SCP.
ANTA can automatically configure `aaa authorization exec default local` using the `anta exec collect-tech-support --configure` option.
If you require specific AAA configuration for `aaa authorization exec default`, like `aaa authorization exec default none` or `aaa authorization exec default group tacacs+`, you will need to configure it manually.
The `--latest` option allows retrieval of a specific number of the most recent tech-support files.
!!! warning
By default **all** the tech-support files present on the devices are retrieved.
### Example
```bash
anta --insecure exec collect-tech-support
[15:27:19] INFO Connecting to devices...
INFO Copying '/mnt/flash/schedule/tech-support/spine1_tech-support_2023-06-09.1315.log.gz' from device spine1 to 'tech-support/spine1' locally
INFO Copying '/mnt/flash/schedule/tech-support/leaf3_tech-support_2023-06-09.1315.log.gz' from device leaf3 to 'tech-support/leaf3' locally
INFO Copying '/mnt/flash/schedule/tech-support/leaf1_tech-support_2023-06-09.1315.log.gz' from device leaf1 to 'tech-support/leaf1' locally
INFO Copying '/mnt/flash/schedule/tech-support/leaf2_tech-support_2023-06-09.1315.log.gz' from device leaf2 to 'tech-support/leaf2' locally
INFO Copying '/mnt/flash/schedule/tech-support/spine2_tech-support_2023-06-09.1315.log.gz' from device spine2 to 'tech-support/spine2' locally
INFO Copying '/mnt/flash/schedule/tech-support/leaf4_tech-support_2023-06-09.1315.log.gz' from device leaf4 to 'tech-support/leaf4' locally
INFO Collected 1 scheduled tech-support from leaf2
INFO Collected 1 scheduled tech-support from spine2
INFO Collected 1 scheduled tech-support from leaf3
INFO Collected 1 scheduled tech-support from spine1
INFO Collected 1 scheduled tech-support from leaf1
INFO Collected 1 scheduled tech-support from leaf4
```
The output folder structure is as follows:
```bash
tree tech-support/
tech-support/
├── leaf1
│   └── leaf1_tech-support_2023-06-09.1315.log.gz
├── leaf2
│   └── leaf2_tech-support_2023-06-09.1315.log.gz
├── leaf3
│   └── leaf3_tech-support_2023-06-09.1315.log.gz
├── leaf4
│   └── leaf4_tech-support_2023-06-09.1315.log.gz
├── spine1
│   └── spine1_tech-support_2023-06-09.1315.log.gz
└── spine2
└── spine2_tech-support_2023-06-09.1315.log.gz
6 directories, 6 files
```
Each device has its own subdirectory containing the collected tech-support files.

View file

@ -0,0 +1,237 @@
<!--
~ 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.
-->
# Retrieving Inventory Information
The ANTA CLI offers multiple entrypoints to access data from your local inventory.
## Inventory used of examples
Let's consider the following inventory:
```yaml
---
anta_inventory:
hosts:
- host: 172.20.20.101
name: DC1-SPINE1
tags: ["SPINE", "DC1"]
- host: 172.20.20.102
name: DC1-SPINE2
tags: ["SPINE", "DC1"]
- host: 172.20.20.111
name: DC1-LEAF1A
tags: ["LEAF", "DC1"]
- host: 172.20.20.112
name: DC1-LEAF1B
tags: ["LEAF", "DC1"]
- host: 172.20.20.121
name: DC1-BL1
tags: ["BL", "DC1"]
- host: 172.20.20.122
name: DC1-BL2
tags: ["BL", "DC1"]
- host: 172.20.20.201
name: DC2-SPINE1
tags: ["SPINE", "DC2"]
- host: 172.20.20.202
name: DC2-SPINE2
tags: ["SPINE", "DC2"]
- host: 172.20.20.211
name: DC2-LEAF1A
tags: ["LEAF", "DC2"]
- host: 172.20.20.212
name: DC2-LEAF1B
tags: ["LEAF", "DC2"]
- host: 172.20.20.221
name: DC2-BL1
tags: ["BL", "DC2"]
- host: 172.20.20.222
name: DC2-BL2
tags: ["BL", "DC2"]
```
## Obtaining all configured tags
As most of ANTA's commands accommodate tag filtering, this particular command is useful for enumerating all tags configured in the inventory. Running the `anta get tags` command will return a list of all tags that have been configured in the inventory.
### Command overview
```bash
anta get tags --help
Usage: anta get tags [OPTIONS]
Get list of configured tags in user inventory.
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
required]
-p, --password TEXT Password to connect to EOS that must be provided. It
can be prompted using '--prompt' option. [env var:
ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It can
be prompted using '--prompt' option. Requires '--
enable' option. [env var: ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC mode.
This option tries to access this mode before sending
a command to the device. [env var: ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided. [env
var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
--help Show this message and exit.
```
### Example
To get the list of all configured tags in the inventory, run the following command:
```bash
anta get tags
Tags found:
[
"BL",
"DC1",
"DC2",
"LEAF",
"SPINE"
]
* note that tag all has been added by anta
```
!!! note
Even if you haven't explicitly configured the `all` tag in the inventory, it is automatically added. This default tag allows to execute commands on all devices in the inventory when no tag is specified.
## List devices in inventory
This command will list all devices available in the inventory. Using the `--tags` option, you can filter this list to only include devices with specific tags. The `--connected` option allows to display only the devices where a connection has been established.
### Command overview
```bash
anta get inventory --help
Usage: anta get inventory [OPTIONS]
Show inventory loaded in ANTA.
Options:
-u, --username TEXT Username to connect to EOS [env var:
ANTA_USERNAME; required]
-p, --password TEXT Password to connect to EOS that must be
provided. It can be prompted using '--prompt'
option. [env var: ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode.
It can be prompted using '--prompt' option.
Requires '--enable' option. [env var:
ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC
mode. This option tries to access this mode
before sending a command to the device. [env
var: ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not
provided. [env var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var:
ANTA_TIMEOUT; default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
--connected / --not-connected Display inventory after connection has been
created
--help Show this message and exit.
```
!!! tip
In its default mode, `anta get inventory` provides only information that doesn't rely on a device connection. If you are interested in obtaining connection-dependent details, like the hardware model, please use the `--connected` option.
### Example
To retrieve a comprehensive list of all devices along with their details, execute the following command. It will provide all the data loaded into the ANTA inventory from your [inventory file](../usage-inventory-catalog.md).
```bash
anta get inventory --tags SPINE
Current inventory content is:
{
'DC1-SPINE1': AsyncEOSDevice(
name='DC1-SPINE1',
tags=['SPINE', 'DC1'],
hw_model=None,
is_online=False,
established=False,
disable_cache=False,
host='172.20.20.101',
eapi_port=443,
username='arista',
enable=True,
enable_password='arista',
insecure=False
),
'DC1-SPINE2': AsyncEOSDevice(
name='DC1-SPINE2',
tags=['SPINE', 'DC1'],
hw_model=None,
is_online=False,
established=False,
disable_cache=False,
host='172.20.20.102',
eapi_port=443,
username='arista',
enable=True,
insecure=False
),
'DC2-SPINE1': AsyncEOSDevice(
name='DC2-SPINE1',
tags=['SPINE', 'DC2'],
hw_model=None,
is_online=False,
established=False,
disable_cache=False,
host='172.20.20.201',
eapi_port=443,
username='arista',
enable=True,
insecure=False
),
'DC2-SPINE2': AsyncEOSDevice(
name='DC2-SPINE2',
tags=['SPINE', 'DC2'],
hw_model=None,
is_online=False,
established=False,
disable_cache=False,
host='172.20.20.202',
eapi_port=443,
username='arista',
enable=True,
insecure=False
)
}
```

View file

@ -0,0 +1,72 @@
<!--
~ 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.
-->
# Create an Inventory from Ansible inventory
In large setups, it might be beneficial to construct your inventory based on your Ansible inventory. The `from-ansible` entrypoint of the `get` command enables the user to create an ANTA inventory from Ansible.
### Command overview
```bash
$ anta get from-ansible --help
Usage: anta get from-ansible [OPTIONS]
Build ANTA inventory from an ansible inventory YAML file
Options:
-g, --ansible-group TEXT Ansible group to filter
--ansible-inventory FILENAME
Path to your ansible inventory file to read
-o, --output FILENAME Path to save inventory file
-d, --inventory-directory PATH Directory to save inventory file
--help Show this message and exit.
```
The output is an inventory where the name of the container is added as a tag for each host:
```yaml
anta_inventory:
hosts:
- host: 10.73.252.41
name: srv-pod01
- host: 10.73.252.42
name: srv-pod02
- host: 10.73.252.43
name: srv-pod03
```
!!! warning
The current implementation only considers devices directly attached to a specific Ansible group and does not support inheritence when using the `--ansible-group` option.
By default, if user does not provide `--output` file, anta will save output to configured anta inventory (`anta --inventory`). If the output file has content, anta will ask user to overwrite when running in interactive console. This mechanism can be controlled by triggers in case of CI usage: `--overwrite` to force anta to overwrite file. If not set, anta will exit
### Command output
`host` value is coming from the `ansible_host` key in your inventory while `name` is the name you defined for your host. Below is an ansible inventory example used to generate previous inventory:
```yaml
---
tooling:
children:
endpoints:
hosts:
srv-pod01:
ansible_httpapi_port: 9023
ansible_port: 9023
ansible_host: 10.73.252.41
type: endpoint
srv-pod02:
ansible_httpapi_port: 9024
ansible_port: 9024
ansible_host: 10.73.252.42
type: endpoint
srv-pod03:
ansible_httpapi_port: 9025
ansible_port: 9025
ansible_host: 10.73.252.43
type: endpoint
```

72
docs/cli/inv-from-cvp.md Normal file
View file

@ -0,0 +1,72 @@
<!--
~ 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.
-->
# Create an Inventory from CloudVision
In large setups, it might be beneficial to construct your inventory based on CloudVision. The `from-cvp` entrypoint of the `get` command enables the user to create an ANTA inventory from CloudVision.
### Command overview
```bash
anta get from-cvp --help
Usage: anta get from-cvp [OPTIONS]
Build ANTA inventory from Cloudvision
Options:
-ip, --cvp-ip TEXT CVP IP Address [required]
-u, --cvp-username TEXT CVP Username [required]
-p, --cvp-password TEXT CVP Password / token [required]
-c, --cvp-container TEXT Container where devices are configured
-d, --inventory-directory PATH Path to save inventory file
--help Show this message and exit.
```
The output is an inventory where the name of the container is added as a tag for each host:
```yaml
anta_inventory:
hosts:
- host: 192.168.0.13
name: leaf2
tags:
- pod1
- host: 192.168.0.15
name: leaf4
tags:
- pod2
```
!!! warning
The current implementation only considers devices directly attached to a specific container when using the `--cvp-container` option.
### Creating an inventory from multiple containers
If you need to create an inventory from multiple containers, you can use a bash command and then manually concatenate files to create a single inventory file:
```bash
$ for container in pod01 pod02 spines; do anta get from-cvp -ip <cvp-ip> -u cvpadmin -p cvpadmin -c $container -d test-inventory; done
[12:25:35] INFO Getting auth token from cvp.as73.inetsix.net for user tom
[12:25:36] INFO Creating inventory folder /home/tom/Projects/arista/network-test-automation/test-inventory
WARNING Using the new api_token parameter. This will override usage of the cvaas_token parameter if both are provided. This is because api_token and cvaas_token parameters
are for the same use case and api_token is more generic
INFO Connected to CVP cvp.as73.inetsix.net
[12:25:37] INFO Getting auth token from cvp.as73.inetsix.net for user tom
[12:25:38] WARNING Using the new api_token parameter. This will override usage of the cvaas_token parameter if both are provided. This is because api_token and cvaas_token parameters
are for the same use case and api_token is more generic
INFO Connected to CVP cvp.as73.inetsix.net
[12:25:38] INFO Getting auth token from cvp.as73.inetsix.net for user tom
[12:25:39] WARNING Using the new api_token parameter. This will override usage of the cvaas_token parameter if both are provided. This is because api_token and cvaas_token parameters
are for the same use case and api_token is more generic
INFO Connected to CVP cvp.as73.inetsix.net
INFO Inventory file has been created in /home/tom/Projects/arista/network-test-automation/test-inventory/inventory-spines.yml
```

247
docs/cli/nrfu.md Normal file
View file

@ -0,0 +1,247 @@
<!--
~ 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.
-->
# Execute Network Readiness For Use (NRFU) Testing
ANTA provides a set of commands for performing NRFU tests on devices. These commands are under the `anta nrfu` namespace and offer multiple output format options:
- [Text view](#performing-nrfu-with-text-rendering)
- [Table view](#performing-nrfu-with-table-rendering)
- [JSON view](#performing-nrfu-with-json-rendering)
- [Custom template view](#performing-nrfu-with-custom-reports)
### NRFU Command overview
```bash
anta nrfu --help
Usage: anta nrfu [OPTIONS] COMMAND [ARGS]...
Run NRFU against inventory devices
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
required]
-p, --password TEXT Password to connect to EOS that must be provided. It
can be prompted using '--prompt' option. [env var:
ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It can
be prompted using '--prompt' option. Requires '--
enable' option. [env var: ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC mode.
This option tries to access this mode before sending
a command to the device. [env var: ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided. [env
var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
-c, --catalog FILE Path to the test catalog YAML file [env var:
ANTA_CATALOG; required]
--ignore-status Always exit with success [env var:
ANTA_NRFU_IGNORE_STATUS]
--ignore-error Only report failures and not errors [env var:
ANTA_NRFU_IGNORE_ERROR]
--help Show this message and exit.
Commands:
json ANTA command to check network state with JSON result
table ANTA command to check network states with table result
text ANTA command to check network states with text result
tpl-report ANTA command to check network state with templated report
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
All commands under the `anta nrfu` namespace require a catalog yaml file specified with the `--catalog` option and a device inventory file specified with the `--inventory` option.
!!! info
Issuing the command `anta nrfu` will run `anta nrfu table` without any option.
## Tag management
The `--tags` option can be used to target specific devices in your inventory and run only tests configured with this specific tags from your catalog. The default tag is set to `all` and is implicit. Expected behaviour is provided below:
| Command | Description |
| ------- | ----------- |
| `none` | Run all tests on all devices according `tag` definition in your inventory and test catalog. And tests with no tag are executed on all devices|
| `--tags leaf` | Run all tests marked with `leaf` tag on all devices configured with `leaf` tag.<br/> All other tags are ignored |
| `--tags leaf,spine` | Run all tests marked with `leaf` tag on all devices configured with `leaf` tag.<br/>Run all tests marked with `spine` tag on all devices configured with `spine` tag.<br/> All other tags are ignored |
!!! info
[More examples](tag-management.md) available on this dedicated page.
## Performing NRFU with text rendering
The `text` subcommand provides a straightforward text report for each test executed on all devices in your inventory.
### Command overview
```bash
anta nrfu text --help
Usage: anta nrfu text [OPTIONS]
ANTA command to check network states with text result
Options:
-s, --search TEXT Regular expression to search in both name and test
--skip-error Hide tests in errors due to connectivity issue
--help Show this message and exit.
```
The `--search` option permits filtering based on a regular expression pattern in both the hostname and the test name.
The `--skip-error` option can be used to exclude tests that failed due to connectivity issues or unsupported commands.
### Example
```bash
anta nrfu text --tags LEAF --search DC1-LEAF1A
```
[![anta nrfu text results](../imgs/anta-nrfu-text-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-text-output.png)
## Performing NRFU with table rendering
The `table` command under the `anta nrfu` namespace offers a clear and organized table view of the test results, suitable for filtering. It also has its own set of options for better control over the output.
### Command overview
```bash
anta nrfu table --help
Usage: anta nrfu table [OPTIONS]
ANTA command to check network states with table result
Options:
-d, --device TEXT Show a summary for this device
-t, --test TEXT Show a summary for this test
--group-by [device|test] Group result by test or host. default none
--help Show this message and exit.
```
The `--device` and `--test` options show a summarized view of the test results for a specific host or test case, respectively.
The `--group-by` option show a summarized view of the test results per host or per test.
### Examples
```bash
anta nrfu --tags LEAF table
```
[![anta nrfu table results](../imgs/anta-nrfu-table-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-table-output.png)
For larger setups, you can also group the results by host or test to get a summarized view:
```bash
anta nrfu table --group-by device
```
[![anta nrfu table group_by_host_output](../imgs/anta-nrfu-table-group-by-host-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-table-group-by-host-output.png)
```bash
anta nrfu table --group-by test
```
[![anta nrfu table group_by_test_output](../imgs/anta-nrfu-table-group-by-test-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-table-group-by-test-output.png)
To get more specific information, it is possible to filter on a single device or a single test:
```bash
anta nrfu table --device spine1
```
[![anta nrfu table filter_host_output](../imgs/anta-nrfu-table-filter-host-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-table-filter-host-output.png)
```bash
anta nrfu table --test VerifyZeroTouch
```
[![anta nrfu table filter_test_output](../imgs/anta-nrfu-table-filter-test-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-table-filter-test-output.png)
## Performing NRFU with JSON rendering
The JSON rendering command in NRFU testing is useful in generating a JSON output that can subsequently be passed on to another tool for reporting purposes.
### Command overview
```bash
anta nrfu json --help
Usage: anta nrfu json [OPTIONS]
ANTA command to check network state with JSON result
Options:
-o, --output FILE Path to save report as a file [env var:
ANTA_NRFU_JSON_OUTPUT]
--help Show this message and exit.
```
The `--output` option allows you to save the JSON report as a file.
### Example
```bash
anta nrfu --tags LEAF json
```
[![anta nrfu json results](../imgs/anta-nrfu-json-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-json-output.png)
## Performing NRFU with custom reports
ANTA offers a CLI option for creating custom reports. This leverages the Jinja2 template system, allowing you to tailor reports to your specific needs.
### Command overview
```bash
anta nrfu tpl-report --help
Usage: anta nrfu tpl-report [OPTIONS]
ANTA command to check network state with templated report
Options:
-tpl, --template FILE Path to the template to use for the report [env var:
ANTA_NRFU_TPL_REPORT_TEMPLATE; required]
-o, --output FILE Path to save report as a file [env var:
ANTA_NRFU_TPL_REPORT_OUTPUT]
--help Show this message and exit.
```
The `--template` option is used to specify the Jinja2 template file for generating the custom report.
The `--output` option allows you to choose the path where the final report will be saved.
### Example
```bash
anta nrfu --tags LEAF tpl-report --template ./custom_template.j2
```
[![anta nrfu json results](../imgs/anta-nrfu-tpl-report-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-tpl-report-output.png)
The template `./custom_template.j2` is a simple Jinja2 template:
```j2
{% for d in data %}
* {{ d.test }} is [green]{{ d.result | upper}}[/green] for {{ d.name }}
{% endfor %}
```
The Jinja2 template has access to all `TestResult` elements and their values, as described in this [documentation](../api/result_manager_models.md#testresult-entry).
You can also save the report result to a file using the `--output` option:
```bash
anta nrfu --tags LEAF tpl-report --template ./custom_template.j2 --output nrfu-tpl-report.txt
```
The resulting output might look like this:
```bash
cat nrfu-tpl-report.txt
* VerifyMlagStatus is [green]SUCCESS[/green] for DC1-LEAF1A
* VerifyMlagInterfaces is [green]SUCCESS[/green] for DC1-LEAF1A
* VerifyMlagConfigSanity is [green]SUCCESS[/green] for DC1-LEAF1A
* VerifyMlagReloadDelay is [green]SUCCESS[/green] for DC1-LEAF1A
```

103
docs/cli/overview.md Normal file
View file

@ -0,0 +1,103 @@
<!--
~ 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.
-->
# Overview of ANTA's Command-Line Interface (CLI)
ANTA provides a powerful Command-Line Interface (CLI) to perform a wide range of operations. This document provides a comprehensive overview of ANTA CLI usage and its commands.
ANTA can also be used as a Python library, allowing you to build your own tools based on it. Visit this [page](../advanced_usages/as-python-lib.md) for more details.
To start using the ANTA CLI, open your terminal and type `anta`.
!!! warning
The ANTA CLI options have changed after version 0.11 and have moved away from the top level `anta` and are now required at their respective commands (e.g. `anta nrfu`). This breaking change occurs after users feedback on making the CLI more intuitive. This change should not affect user experience when using environment variables.
## Invoking ANTA CLI
```bash
$ anta --help
--8<-- "anta_help.txt"
```
## ANTA environement variables
Certain parameters are required and can be either passed to the ANTA CLI or set as an environment variable (ENV VAR).
To pass the parameters via the CLI:
```bash
anta nrfu -u admin -p arista123 -i inventory.yaml -c tests.yaml
```
To set them as environment variables:
```bash
export ANTA_USERNAME=admin
export ANTA_PASSWORD=arista123
export ANTA_INVENTORY=inventory.yml
export ANTA_INVENTORY=tests.yml
```
Then, run the CLI without options:
```bash
anta nrfu
```
!!! note
All environement variables may not be needed for every commands.
Refer to `<command> --help` for the comprehensive environment varibles names.
Below are the environement variables usable with the `anta nrfu` command:
| Variable Name | Purpose | Required |
| ------------- | ------- |----------|
| ANTA_USERNAME | The username to use in the inventory to connect to devices. | Yes |
| ANTA_PASSWORD | The password to use in the inventory to connect to devices. | Yes |
| ANTA_INVENTORY | The path to the inventory file. | Yes |
| ANTA_CATALOG | The path to the catalog file. | Yes |
| ANTA_PROMPT | The value to pass to the prompt for password is password is not provided | No |
| ANTA_INSECURE | Whether or not using insecure mode when connecting to the EOS devices HTTP API. | No |
| ANTA_DISABLE_CACHE | A variable to disable caching for all ANTA tests (enabled by default). | No |
| ANTA_ENABLE | Whether it is necessary to go to enable mode on devices. | No |
| ANTA_ENABLE_PASSWORD | The optional enable password, when this variable is set, ANTA_ENABLE or `--enable` is required. | No |
!!! info
Caching can be disabled with the global parameter `--disable-cache`. For more details about how caching is implemented in ANTA, please refer to [Caching in ANTA](../advanced_usages/caching.md).
## ANTA Exit Codes
ANTA CLI utilizes the following exit codes:
- `Exit code 0` - All tests passed successfully.
- `Exit code 1` - An internal error occurred while executing ANTA.
- `Exit code 2` - A usage error was raised.
- `Exit code 3` - Tests were run, but at least one test returned an error.
- `Exit code 4` - Tests were run, but at least one test returned a failure.
To ignore the test status, use `anta nrfu --ignore-status`, and the exit code will always be 0.
To ignore errors, use `anta nrfu --ignore-error`, and the exit code will be 0 if all tests succeeded or 1 if any test failed.
## Shell Completion
You can enable shell completion for the ANTA CLI:
=== "ZSH"
If you use ZSH shell, add the following line in your `~/.zshrc`:
```bash
eval "$(_ANTA_COMPLETE=zsh_source anta)" > /dev/null
```
=== "BASH"
With bash, add the following line in your `~/.bashrc`:
```bash
eval "$(_ANTA_COMPLETE=bash_source anta)" > /dev/null
```

165
docs/cli/tag-management.md Normal file
View file

@ -0,0 +1,165 @@
<!--
~ 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.
-->
# Tag management
## Overview
Some of the ANTA commands like `anta nrfu` command come with a `--tags` option.
For `nrfu`, this allows users to specify a set of tests, marked with a given tag, to be run on devices marked with the same tag. For instance, you can run tests dedicated to leaf devices on your leaf devices only and not on other devices.
Tags are string defined by the user and can be anything considered as a string by Python. A [default one](#default-tags) is present for all tests and devices.
The next table provides a short summary of the scope of tags using CLI
| Command | Description |
| ------- | ----------- |
| `none` | Run all tests on all devices according `tag` definition in your inventory and test catalog. And tests with no tag are executed on all devices|
| `--tags leaf` | Run all tests marked with `leaf` tag on all devices configured with `leaf` tag.<br/> All other tags are ignored |
| `--tags leaf,spine` | Run all tests marked with `leaf` tag on all devices configured with `leaf` tag.<br/>Run all tests marked with `spine` tag on all devices configured with `spine` tag.<br/> All other tags are ignored |
## Inventory and Catalog for tests
All commands in this page are based on the following inventory and test catalog.
=== "Inventory"
```yaml
---
anta_inventory:
hosts:
- host: 192.168.0.10
name: spine01
tags: ['fabric', 'spine']
- host: 192.168.0.11
name: spine02
tags: ['fabric', 'spine']
- host: 192.168.0.12
name: leaf01
tags: ['fabric', 'leaf']
- host: 192.168.0.13
name: leaf02
tags: ['fabric', 'leaf']
- host: 192.168.0.14
name: leaf03
tags: ['fabric', 'leaf']
- host: 192.168.0.15
name: leaf04
tags: ['fabric', 'leaf'
```
=== "Test Catalog"
```yaml
anta.tests.system:
- VerifyUptime:
minimum: 10
filters:
tags: ['fabric']
- VerifyReloadCause:
tags: ['leaf', spine']
- VerifyCoredump:
- VerifyAgentLogs:
- VerifyCPUUtilization:
filters:
tags: ['spine', 'leaf']
- VerifyMemoryUtilization:
- VerifyFileSystemUtilization:
- VerifyNTP:
anta.tests.mlag:
- VerifyMlagStatus:
anta.tests.interfaces:
- VerifyL3MTU:
mtu: 1500
filters:
tags: ['demo']
```
## Default tags
By default, ANTA uses a default tag for both devices and tests. This default tag is `all` and it can be explicit if you want to make it visible in your inventory and also implicit since the framework injects this tag if it is not defined.
So this command will run all tests from your catalog on all devices. With a mapping for `tags` defined in your inventory and catalog. If no `tags` configured, then tests are executed against all devices.
```bash
$ anta nrfu -c .personal/catalog-class.yml table --group-by device
╭────────────────────── Settings ──────────────────────╮
│ Running ANTA tests: │
│ - ANTA Inventory contains 6 devices (AsyncEOSDevice) │
│ - Tests catalog contains 10 tests │
╰──────────────────────────────────────────────────────╯
┏━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┓
┃ Device ┃ # of success ┃ # of skipped ┃ # of failure ┃ # of errors ┃ List of failed or error test cases ┃
┡━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┩
│ spine01 │ 5 │ 1 │ 1 │ 0 │ ['VerifyCPUUtilization'] │
│ spine02 │ 5 │ 1 │ 1 │ 0 │ ['VerifyCPUUtilization'] │
│ leaf01 │ 6 │ 0 │ 1 │ 0 │ ['VerifyCPUUtilization'] │
│ leaf02 │ 6 │ 0 │ 1 │ 0 │ ['VerifyCPUUtilization'] │
│ leaf03 │ 6 │ 0 │ 1 │ 0 │ ['VerifyCPUUtilization'] │
│ leaf04 │ 6 │ 0 │ 1 │ 0 │ ['VerifyCPUUtilization'] │
└─────────┴──────────────┴──────────────┴──────────────┴─────────────┴────────────────────────────────────┘
```
## Use a single tag in CLI
The most used approach is to use a single tag in your CLI to filter tests & devices configured with this one.
In such scenario, ANTA will run tests marked with `$tag` only on devices marked with `$tag`. All other tests and devices will be ignored
```bash
$ anta nrfu -c .personal/catalog-class.yml --tags leaf text
╭────────────────────── Settings ──────────────────────╮
│ Running ANTA tests: │
│ - ANTA Inventory contains 6 devices (AsyncEOSDevice) │
│ - Tests catalog contains 10 tests │
╰──────────────────────────────────────────────────────╯
leaf01 :: VerifyUptime :: SUCCESS
leaf01 :: VerifyReloadCause :: SUCCESS
leaf01 :: VerifyCPUUtilization :: SUCCESS
leaf02 :: VerifyUptime :: SUCCESS
leaf02 :: VerifyReloadCause :: SUCCESS
leaf02 :: VerifyCPUUtilization :: SUCCESS
leaf03 :: VerifyUptime :: SUCCESS
leaf03 :: VerifyReloadCause :: SUCCESS
leaf03 :: VerifyCPUUtilization :: SUCCESS
leaf04 :: VerifyUptime :: SUCCESS
leaf04 :: VerifyReloadCause :: SUCCESS
leaf04 :: VerifyCPUUtilization :: SUCCESS
```
In this case, only `leaf` devices defined in your [inventory](#inventory-and-catalog-for-tests) are used to run tests marked with `leaf` in your [test catalog](#inventory-and-catalog-for-tests)
## Use multiple tags in CLI
A more advanced usage of the tag feature is to list multiple tags in your CLI using `--tags $tag1,$tag2` syntax.
In such scenario, all devices marked with `$tag1` will be selected and ANTA will run tests with `$tag1`, then devices with `$tag2` will be selected and will be tested with tests marked with `$tag2`
```bash
anta nrfu -c .personal/catalog-class.yml --tags leaf,fabric text
spine01 :: VerifyUptime :: SUCCESS
spine02 :: VerifyUptime :: SUCCESS
leaf01 :: VerifyUptime :: SUCCESS
leaf01 :: VerifyReloadCause :: SUCCESS
leaf01 :: VerifyCPUUtilization :: SUCCESS
leaf02 :: VerifyUptime :: SUCCESS
leaf02 :: VerifyReloadCause :: SUCCESS
leaf02 :: VerifyCPUUtilization :: SUCCESS
leaf03 :: VerifyUptime :: SUCCESS
leaf03 :: VerifyReloadCause :: SUCCESS
leaf03 :: VerifyCPUUtilization :: SUCCESS
leaf04 :: VerifyUptime :: SUCCESS
leaf04 :: VerifyReloadCause :: SUCCESS
leaf04 :: VerifyCPUUtilization :: SUCCESS
```

227
docs/contribution.md Normal file
View file

@ -0,0 +1,227 @@
<!--
~ 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.
-->
# How to contribute to ANTA
Contribution model is based on a fork-model. Don't push to arista-netdevops-community/anta directly. Always do a branch in your forked repository and create a PR.
To help development, open your PR as soon as possible even in draft mode. It helps other to know on what you are working on and avoid duplicate PRs.
## Create a development environement
Run the following commands to create an ANTA development environement:
```bash
# Clone repository
$ git clone https://github.com/arista-netdevops-community/anta.git
$ cd anta
# Install ANTA in editable mode and its development tools
$ pip install -e .[dev]
# Verify installation
$ pip list -e
Package Version Editable project location
------- ------- -------------------------
anta 0.13.0 /mnt/lab/projects/anta
```
Then, [`tox`](https://tox.wiki/) is configued with few environments to run CI locally:
```bash
$ tox list -d
default environments:
clean -> Erase previous coverage reports
lint -> Check the code style
type -> Check typing
py38 -> Run pytest with py38
py39 -> Run pytest with py39
py310 -> Run pytest with py310
py311 -> Run pytest with py311
report -> Generate coverage report
```
### Code linting
```bash
tox -e lint
[...]
lint: commands[0]> black --check --diff --color .
All done! ✨ 🍰 ✨
104 files would be left unchanged.
lint: commands[1]> isort --check --diff --color .
Skipped 7 files
lint: commands[2]> flake8 --max-line-length=165 --config=/dev/null anta
lint: commands[3]> flake8 --max-line-length=165 --config=/dev/null tests
lint: commands[4]> pylint anta
--------------------------------------------------------------------
Your code has been rated at 10.00/10 (previous run: 10.00/10, +0.00)
.pkg: _exit> python /Users/guillaumemulocher/.pyenv/versions/3.8.13/envs/anta/lib/python3.8/site-packages/pyproject_api/_backend.py True setuptools.build_meta
lint: OK (19.26=setup[5.83]+cmd[1.50,0.76,1.19,1.20,8.77] seconds)
congratulations :) (19.56 seconds)
```
### Code Typing
```bash
tox -e type
[...]
type: commands[0]> mypy --config-file=pyproject.toml anta
Success: no issues found in 52 source files
.pkg: _exit> python /Users/guillaumemulocher/.pyenv/versions/3.8.13/envs/anta/lib/python3.8/site-packages/pyproject_api/_backend.py True setuptools.build_meta
type: OK (46.66=setup[24.20]+cmd[22.46] seconds)
congratulations :) (47.01 seconds)
```
> NOTE: Typing is configured quite strictly, do not hesitate to reach out if you have any questions, struggles, nightmares.
## Unit tests
To keep high quality code, we require to provide a Pytest for every tests implemented in ANTA.
All submodule should have its own pytest section under `tests/units/anta_tests/<submodule-name>.py`.
### How to write a unit test for an AntaTest subclass
The Python modules in the `tests/units/anta_tests` folder define test parameters for AntaTest subclasses unit tests.
A generic test function is written for all unit tests in `tests.lib.anta` module.
The `pytest_generate_tests` function definition in `conftest.py` is called during test collection.
The `pytest_generate_tests` function will parametrize the generic test function based on the `DATA` data structure defined in `tests.units.anta_tests` modules.
See https://docs.pytest.org/en/7.3.x/how-to/parametrize.html#basic-pytest-generate-tests-example
The `DATA` structure is a list of dictionaries used to parametrize the test.
The list elements have the following keys:
- `name` (str): Test name as displayed by Pytest.
- `test` (AntaTest): An AntaTest subclass imported in the test module - e.g. VerifyUptime.
- `eos_data` (list[dict]): List of data mocking EOS returned data to be passed to the test.
- `inputs` (dict): Dictionary to instantiate the `test` inputs as defined in the class from `test`.
- `expected` (dict): Expected test result structure, a dictionary containing a key
`result` containing one of the allowed status (`Literal['success', 'failure', 'unset', 'skipped', 'error']`) and optionally a key `messages` which is a list(str) and each message is expected to be a substring of one of the actual messages in the TestResult object.
In order for your unit tests to be correctly collected, you need to import the generic test function even if not used in the Python module.
Test example for `anta.tests.system.VerifyUptime` AntaTest.
``` python
# Import the generic test function
from tests.lib.anta import test # noqa: F401
# Import your AntaTest
from anta.tests.system import VerifyUptime
# Define test parameters
DATA: list[dict[str, Any]] = [
{
# Arbitrary test name
"name": "success",
# Must be an AntaTest definition
"test": VerifyUptime,
# Data returned by EOS on which the AntaTest is tested
"eos_data": [{"upTime": 1186689.15, "loadAvg": [0.13, 0.12, 0.09], "users": 1, "currentTime": 1683186659.139859}],
# Dictionary to instantiate VerifyUptime.Input
"inputs": {"minimum": 666},
# Expected test result
"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},
# If the test returns messages, it needs to be expected otherwise test will fail.
# NB: expected messages only needs to be included in messages returned by the test. Exact match is not required.
"expected": {"result": "failure", "messages": ["Device uptime is 665.15 seconds"]},
},
]
```
## Git Pre-commit hook
```bash
pip install pre-commit
pre-commit install
```
When running a commit or a pre-commit check:
``` bash
echo "import foobaz" > test.py && git add test.py
pre-commit
pylint...................................................................Failed
- hook id: pylint
- exit code: 22
************* Module test
test.py:1:0: C0114: Missing module docstring (missing-module-docstring)
test.py:1:0: E0401: Unable to import 'foobaz' (import-error)
test.py:1:0: W0611: Unused import foobaz (unused-import)
```
> NOTE: It could happen that pre-commit and tox disagree on something, in that case please open an issue on Github so we can take a look.. It is most probably wrong configuration on our side.
## Configure MYPYPATH
In some cases, mypy can complain about not having `MYPYPATH` configured in your shell. It is especially the case when you update both an anta test and its unit test. So you can configure this environment variable with:
```bash
# Option 1: use local folder
export MYPYPATH=.
# Option 2: use absolute path
export MYPYPATH=/path/to/your/local/anta/repository
```
## Documentation
[`mkdocs`](https://www.mkdocs.org/) is used to generate the documentation. A PR should always update the documentation to avoid documentation debt.
### Install documentation requirements
Run pip to install the documentation requirements from the root of the repo:
```bash
pip install -e .[doc]
```
### Testing documentation
You can then check locally the documentation using the following command from the root of the repo:
```bash
mkdocs serve
```
By default, `mkdocs` listens to http://127.0.0.1:8000/, if you need to expose the documentation to another IP or port (for instance all IPs on port 8080), use the following command:
```bash
mkdocs serve --dev-addr=0.0.0.0:8080
```
### Build class diagram
To build class diagram to use in API documentation, you can use `pyreverse` part of `pylint` with [`graphviz`](https://graphviz.org/) installed for jpeg generation.
```bash
pyreverse anta --colorized -a1 -s1 -o jpeg -m true -k --output-directory docs/imgs/uml/ -c <FQDN anta class>
```
Image will be generated under `docs/imgs/uml/` and can be inserted in your documentation.
### Checking links
Writing documentation is crucial but managing links can be cumbersome. To be sure there is no dead links, you can use [`muffet`](https://github.com/raviqqe/muffet) with the following command:
```bash
muffet -c 2 --color=always http://127.0.0.1:8000 -e fonts.gstatic.com
```
## Continuous Integration
GitHub actions is used to test git pushes and pull requests. The workflows are defined in this [directory](https://github.com/arista-netdevops-community/anta/tree/main/.github/workflows). We can view the results [here](https://github.com/arista-netdevops-community/anta/actions).

67
docs/faq.md Normal file
View file

@ -0,0 +1,67 @@
<!--
~ 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.
-->
# Frequently Asked Questions (FAQ)
## Why am I seeing an `ImportError` related to `urllib3` when running ANTA?
When running the `anta --help` command, some users might encounter the following error:
```bash
ImportError: urllib3 v2.0 only supports OpenSSL 1.1.1+, currently the 'ssl' module is compiled with 'OpenSSL 1.0.2k-fips 26 Jan 2017'. See: https://github.com/urllib3/urllib3/issues/2168
```
This error arises due to a compatibility issue between `urllib3` v2.0 and older versions of OpenSSL.
#### How can I resolve this error?
1. _Workaround_: Downgrade `urllib3`
If you need a quick fix, you can temporarily downgrade the `urllib3` package:
```bash
pip3 uninstall urllib3
pip3 install urllib3==1.26.15
```
2. _Recommended_: Upgrade System or Libraries:
As per the [urllib3 v2 migration guide](https://urllib3.readthedocs.io/en/latest/v2-migration-guide.html), the root cause of this error is an incompatibility with older OpenSSL versions. For example, users on RHEL7 might consider upgrading to RHEL8, which supports the required OpenSSL version.
## Why am I seeing `AttributeError: module 'lib' has no attribute 'OpenSSL_add_all_algorithms'` when running ANTA
When running the `anta` commands after installation, some users might encounter the following error:
```bash
AttributeError: module 'lib' has no attribute 'OpenSSL_add_all_algorithms'
```
The error is a result of incompatibility between `cryptography` and `pyopenssl` when installing `asyncssh` which is a requirement of ANTA.
#### How can I resolve this error?
1. Upgrade `pyopenssl`
```bash
pip install -U pyopenssl>22.0
```
## `__NSCFConstantString initialize` error on OSX
This error occurs because of added security to restrict multithreading in macOS High Sierra and later versions of macOS. https://www.wefearchange.org/2018/11/forkmacos.rst.html
#### How can I resolve this error?
1. Set the following environment variable
```bash
export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
```
## Still facing issues?
If you've tried the above solutions and continue to experience problems, please report the issue in our [GitHub repository](https://github.com/arista-netdevops-community/anta).

301
docs/getting-started.md Normal file
View file

@ -0,0 +1,301 @@
<!--
~ 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.
-->
# Getting Started
This section shows how to use ANTA with basic configuration. All examples are based on Arista Test Drive (ATD) topology you can access by reaching out to your preferred SE.
## Installation
The easiest way to intall ANTA package is to run Python (`>=3.8`) and its pip package to install:
```bash
pip install anta
```
For more details about how to install package, please see the [requirements and intallation](./requirements-and-installation.md) section.
## Configure Arista EOS devices
For ANTA to be able to connect to your target devices, you need to configure your management interface
```eos
vrf instance MGMT
!
interface Management0
description oob_management
vrf MGMT
ip address 192.168.0.10/24
!
```
Then, configure access to eAPI:
```eos
!
management api http-commands
protocol https port 443
no shutdown
vrf MGMT
no shutdown
!
!
```
## Create your inventory
ANTA uses an inventory to list the target devices for the tests. You can create a file manually with this format:
```yaml
anta_inventory:
hosts:
- host: 192.168.0.10
name: spine01
tags: ['fabric', 'spine']
- host: 192.168.0.11
name: spine02
tags: ['fabric', 'spine']
- host: 192.168.0.12
name: leaf01
tags: ['fabric', 'leaf']
- host: 192.168.0.13
name: leaf02
tags: ['fabric', 'leaf']
- host: 192.168.0.14
name: leaf03
tags: ['fabric', 'leaf']
- host: 192.168.0.15
name: leaf04
tags: ['fabric', 'leaf']
```
> You can read more details about how to build your inventory [here](usage-inventory-catalog.md#create-an-inventory-file)
## Test Catalog
To test your network, ANTA relies on a test catalog to list all the tests to run against your inventory. A test catalog references python functions into a yaml file.
The structure to follow is like:
```yaml
<anta_tests_submodule>:
- <anta_tests_submodule function name>:
<test function option>:
<test function option value>
```
> You can read more details about how to build your catalog [here](usage-inventory-catalog.md#test-catalog)
Here is an example for basic tests:
```yaml
# Load anta.tests.software
anta.tests.software:
- VerifyEOSVersion: # Verifies the device is running one of the allowed EOS version.
versions: # List of allowed EOS versions.
- 4.25.4M
- 4.26.1F
- '4.28.3M-28837868.4283M (engineering build)'
- VerifyTerminAttrVersion:
versions:
- v1.22.1
anta.tests.system:
- VerifyUptime: # Verifies the device uptime is higher than a value.
minimum: 1
- VerifyNTP:
- VerifySyslog:
anta.tests.mlag:
- VerifyMlagStatus:
- VerifyMlagInterfaces:
- VerifyMlagConfigSanity:
anta.tests.configuration:
- VerifyZeroTouch: # Verifies ZeroTouch is disabled.
- VerifyRunningConfigDiffs:
```
## Test your network
ANTA comes with a generic CLI entrypoint to run tests in your network. It requires an inventory file as well as a test catalog.
This entrypoint has multiple options to manage test coverage and reporting.
```bash
# Generic ANTA options
$ anta
--8<-- "anta_help.txt"
```
```bash
# NRFU part of ANTA
Usage: anta nrfu [OPTIONS] COMMAND [ARGS]...
Run ANTA tests on devices
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
required]
-p, --password TEXT Password to connect to EOS that must be provided. It
can be prompted using '--prompt' option. [env var:
ANTA_PASSWORD]
--enable-password TEXT Password to access EOS Privileged EXEC mode. It can
be prompted using '--prompt' option. Requires '--
enable' option. [env var: ANTA_ENABLE_PASSWORD]
--enable Some commands may require EOS Privileged EXEC mode.
This option tries to access this mode before sending
a command to the device. [env var: ANTA_ENABLE]
-P, --prompt Prompt for passwords if they are not provided. [env
var: ANTA_PROMPT]
--timeout INTEGER Global connection timeout [env var: ANTA_TIMEOUT;
default: 30]
--insecure Disable SSH Host Key validation [env var:
ANTA_INSECURE]
--disable-cache Disable cache globally [env var:
ANTA_DISABLE_CACHE]
-i, --inventory FILE Path to the inventory YAML file [env var:
ANTA_INVENTORY; required]
-t, --tags TEXT List of tags using comma as separator:
tag1,tag2,tag3 [env var: ANTA_TAGS]
-c, --catalog FILE Path to the test catalog YAML file [env var:
ANTA_CATALOG; required]
--ignore-status Always exit with success [env var:
ANTA_NRFU_IGNORE_STATUS]
--ignore-error Only report failures and not errors [env var:
ANTA_NRFU_IGNORE_ERROR]
--help Show this message and exit.
Commands:
json ANTA command to check network state with JSON result
table ANTA command to check network states with table result
text ANTA command to check network states with text result
tpl-report ANTA command to check network state with templated report
```
To run the NRFU, you need to select an output format amongst ["json", "table", "text", "tpl-report"]. For a first usage, `table` is recommended. By default all test results for all devices are rendered but it can be changed to a report per test case or per host
### Default report using table
```bash
anta nrfu \
--username tom \
--password arista123 \
--enable \
--enable-password t \
--inventory .personal/inventory_atd.yml \
--catalog .personal/tests-bases.yml \
table --tags leaf
╭────────────────────── Settings ──────────────────────╮
│ Running ANTA tests: │
│ - ANTA Inventory contains 6 devices (AsyncEOSDevice) │
│ - Tests catalog contains 10 tests │
╰──────────────────────────────────────────────────────╯
[10:17:24] INFO Running ANTA tests... runner.py:75
• Running NRFU Tests...100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40/40 • 0:00:02 • 0:00:00
All tests results
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Device IP ┃ Test Name ┃ Test Status ┃ Message(s) ┃ Test description ┃ Test category ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ leaf01 │ VerifyEOSVersion │ success │ │ Verifies the device is running one of the allowed EOS version. │ software │
│ leaf01 │ VerifyTerminAttrVersion │ success │ │ Verifies the device is running one of the allowed TerminAttr │ software │
│ │ │ │ │ version. │ │
│ leaf01 │ VerifyUptime │ success │ │ Verifies the device uptime is higher than a value. │ system │
│ leaf01 │ VerifyNTP │ success │ │ Verifies NTP is synchronised. │ system │
│ leaf01 │ VerifySyslog │ success │ │ Verifies the device had no syslog message with a severity of warning │ system │
│ │ │ │ │ (or a more severe message) during the last 7 days. │ │
│ leaf01 │ VerifyMlagStatus │ skipped │ MLAG is disabled │ This test verifies the health status of the MLAG configuration. │ mlag │
│ leaf01 │ VerifyMlagInterfaces │ skipped │ MLAG is disabled │ This test verifies there are no inactive or active-partial MLAG │ mlag │
[...]
│ leaf04 │ VerifyMlagConfigSanity │ skipped │ MLAG is disabled │ This test verifies there are no MLAG config-sanity inconsistencies. │ mlag │
│ leaf04 │ VerifyZeroTouch │ success │ │ Verifies ZeroTouch is disabled. │ configuration │
│ leaf04 │ VerifyRunningConfigDiffs │ success │ │ │ configuration │
└───────────┴──────────────────────────┴─────────────┴──────────────────┴──────────────────────────────────────────────────────────────────────┴───────────────┘
```
### Report in text mode
```bash
$ anta nrfu \
--username tom \
--password arista123 \
--enable \
--enable-password t \
--inventory .personal/inventory_atd.yml \
--catalog .personal/tests-bases.yml \
text --tags leaf
╭────────────────────── Settings ──────────────────────╮
│ Running ANTA tests: │
│ - ANTA Inventory contains 6 devices (AsyncEOSDevice) │
│ - Tests catalog contains 10 tests │
╰──────────────────────────────────────────────────────╯
[10:20:47] INFO Running ANTA tests... runner.py:75
• Running NRFU Tests...100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40/40 • 0:00:01 • 0:00:00
leaf01 :: VerifyEOSVersion :: SUCCESS
leaf01 :: VerifyTerminAttrVersion :: SUCCESS
leaf01 :: VerifyUptime :: SUCCESS
leaf01 :: VerifyNTP :: SUCCESS
leaf01 :: VerifySyslog :: SUCCESS
leaf01 :: VerifyMlagStatus :: SKIPPED (MLAG is disabled)
leaf01 :: VerifyMlagInterfaces :: SKIPPED (MLAG is disabled)
leaf01 :: VerifyMlagConfigSanity :: SKIPPED (MLAG is disabled)
[...]
```
### Report in JSON format
```bash
$ anta nrfu \
--username tom \
--password arista123 \
--enable \
--enable-password t \
--inventory .personal/inventory_atd.yml \
--catalog .personal/tests-bases.yml \
json --tags leaf
╭────────────────────── Settings ──────────────────────╮
│ Running ANTA tests: │
│ - ANTA Inventory contains 6 devices (AsyncEOSDevice) │
│ - Tests catalog contains 10 tests │
╰──────────────────────────────────────────────────────╯
[10:21:51] INFO Running ANTA tests... runner.py:75
• Running NRFU Tests...100% ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 40/40 • 0:00:02 • 0:00:00
╭──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╮
│ JSON results of all tests │
╰──────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────────╯
[
{
"name": "leaf01",
"test": "VerifyEOSVersion",
"categories": [
"software"
],
"description": "Verifies the device is running one of the allowed EOS version.",
"result": "success",
"messages": [],
"custom_field": "None",
},
{
"name": "leaf01",
"test": "VerifyTerminAttrVersion",
"categories": [
"software"
],
"description": "Verifies the device is running one of the allowed TerminAttr version.",
"result": "success",
"messages": [],
"custom_field": "None",
},
[...]
]
```
You can find more information under the __usage__ section of the website

View file

@ -0,0 +1,8 @@
<!--
~ 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.
-->
Repository: https://github.com/marionebl/svg-term-cli
Command: `cat anta-nrfu.cast | svg-term --height 10 --window --out anta.svg`

Binary file not shown.

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 53 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 37 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 39 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 267 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 43 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 22 KiB

64
docs/imgs/anta-nrfu.cast Normal file
View file

@ -0,0 +1,64 @@
{"version": 2, "width": 121, "height": 56, "timestamp": 1689845383, "env": {"SHELL": "/bin/bash", "TERM": "xterm-256color"}}
[0.182046, "o", "\u001b[?2004h "]
[0.930909, "o", "a"]
[1.124462, "o", "n"]
[1.296703, "o", "t"]
[1.467422, "o", "a"]
[1.63869, "o", " "]
[1.822924, "o", "n"]
[1.967039, "o", "r"]
[2.147509, "o", "f"]
[2.323682, "o", "u"]
[2.419445, "o", " "]
[2.638124, "o", "t"]
[2.795029, "o", "a"]
[3.006538, "o", "b"]
[3.151247, "o", "l"]
[3.286674, "o", "e"]
[3.697852, "o", "\r\n\u001b[?2004l\r"]
[3.989809, "o", "\u001b[36m╭─\u001b[0m\u001b[36m─────────────────────\u001b[0m\u001b[36m \u001b[0m\u001b[32mSettings\u001b[0m\u001b[36m \u001b[0m\u001b[36m─────────────────────\u001b[0m\u001b[36m─╮\u001b[0m\r\n\u001b[36m│\u001b[0m\u001b[36m \u001b[0m\u001b[36mRunning ANTA tests:\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m\u001b[36m│\u001b[0m\r\n\u001b[36m│\u001b[0m\u001b[36m \u001b[0m\u001b[36m- ANTA Inventory contains 6 devices (AsyncEOSDevice)\u001b[0m\u001b[36m \u001b[0m\u001b[36m│\u001b[0m\r\n\u001b[36m│\u001b[0m\u001b[36m \u001b[0m\u001b[36m- Tests catalog contains 89 tests\u001b[0m\u001b[36m \u001b[0m\u001b[36m \u001b[0m\u001b[36m│\u001b[0m\r\n\u001b[36m╰──────────────────────────────────────────────────────╯\u001b[0m\r\n"]
[3.989919, "o", "\u001b[?25l"]
[4.033083, "o", "\r\u001b[2K\u001b[32m( 🐜)\u001b[0m • Running NRFU Tests...\u001b[35m 0%\u001b[0m \u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 0/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m-:--:--\u001b[0m"]
[4.035615, "o", "\r\u001b[2K\u001b[2;36m[11:29:47]\u001b[0m\u001b[2;36m \u001b[0m\u001b[34mINFO \u001b[0m Running ANTA tests\u001b[33m...\u001b[0m \u001b]8;id=396032;file:///mnt/lab/projects/anta/anta/runner.py\u001b\\\u001b[2mrunner.py\u001b[0m\u001b]8;;\u001b\\\u001b[2m:\u001b[0m\u001b]8;id=993683;file:///mnt/lab/projects/anta/anta/runner.py#71\u001b\\\u001b[2m71\u001b[0m\u001b]8;;\u001b\\\r\n\u001b[32m( 🐜)\u001b[0m • Running NRFU Tests...\u001b[35m 0%\u001b[0m \u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 0/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m-:--:--\u001b[0m"]
[4.100083, "o", "\r\u001b[2K\u001b[32m( 🐜)\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.20303, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.304638, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.407072, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.509771, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.612195, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.714541, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.850439, "o", "\r\u001b[2K\u001b[32m(🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 15%\u001b[0m \u001b[38;5;197m━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 78/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[4.954054, "o", "\r\u001b[2K\u001b[32m(🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 18%\u001b[0m \u001b[38;5;197m━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m 98/534\u001b[0m • \u001b[33m0:00:00\u001b[0m • \u001b[36m0:00:05\u001b[0m"]
[5.056909, "o", "\r\u001b[2K\u001b[32m(🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 35%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m189/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:02\u001b[0m"]
[5.158885, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 55%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m293/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.260648, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 58%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m311/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.361906, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 63%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m335/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.463151, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 67%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m360/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.56479, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 71%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m378/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.66611, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 72%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━\u001b[0m \u001b[32m383/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.767251, "o", "\r\u001b[2K\u001b[32m( 🐌)\u001b[0m • Running NRFU Tests...\u001b[35m 72%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━━━\u001b[0m \u001b[32m385/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.868443, "o", "\r\u001b[2K\u001b[32m( 🐜)\u001b[0m • Running NRFU Tests...\u001b[35m 76%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━━━━━━━━━━━━━\u001b[0m \u001b[32m407/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[5.969691, "o", "\r\u001b[2K\u001b[32m( 🐜)\u001b[0m • Running NRFU Tests...\u001b[35m 81%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━━━━━━━━━━\u001b[0m \u001b[32m433/534\u001b[0m • \u001b[33m0:00:01\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.072113, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 84%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━━━\u001b[0m \u001b[32m447/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.173693, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 85%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━━━━━━━━\u001b[0m \u001b[32m456/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.275903, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 87%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━━\u001b[0m \u001b[32m467/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.377199, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 89%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━━\u001b[0m \u001b[32m476/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.478317, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 91%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━━━\u001b[0m \u001b[32m486/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.579526, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 95%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m\u001b[38;5;237m━━\u001b[0m \u001b[32m505/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.680856, "o", "\r\u001b[2K\u001b[32m(🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 98%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m\u001b[38;5;237m━\u001b[0m \u001b[32m521/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.782108, "o", "\r\u001b[2K\u001b[32m(🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;237m╺\u001b[0m \u001b[32m528/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.883283, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[6.98442, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:02\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.085424, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.186472, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.287535, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.388642, "o", "\r\u001b[2K\u001b[32m( 🐌 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.489818, "o", "\r\u001b[2K\u001b[32m( 🐌)\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.590902, "o", "\r\u001b[2K\u001b[32m( 🐌)\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.692031, "o", "\r\u001b[2K\u001b[32m( 🐜)\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.793107, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.894156, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[7.995198, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m 99%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m531/534\u001b[0m • \u001b[33m0:00:03\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[8.096303, "o", "\r\u001b[2K\u001b[32m( 🐜 )\u001b[0m • Running NRFU Tests...\u001b[35m100%\u001b[0m \u001b[38;5;197m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m\u001b[38;5;197m╸\u001b[0m \u001b[32m533/534\u001b[0m • \u001b[33m0:00:04\u001b[0m • \u001b[36m0:00:01\u001b[0m"]
[8.146442, "o", "\r\u001b[2K • Running NRFU Tests...\u001b[35m100%\u001b[0m \u001b[38;5;70m━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\u001b[0m \u001b[32m534/534\u001b[0m • \u001b[33m0:00:04\u001b[0m • \u001b[36m0:00:00\u001b[0m\r\n\u001b[?25h"]
[8.22014, "o", "\u001b[?2004h "]

1
docs/imgs/anta-nrfu.svg Normal file

File diff suppressed because one or more lines are too long

After

Width:  |  Height:  |  Size: 51 KiB

BIN
docs/imgs/favicon.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.2 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 31 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 21 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 26 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 8.7 KiB

17
docs/overrides/main.html Normal file
View file

@ -0,0 +1,17 @@
{% extends "base.html" %}
{% block outdated %}
<div id="current-version"> </div>
<script>
let message = "You're not viewing the latest version."
// There is probably a nicer method retrieving the value of the
// version element but it is loaded after the outdated block
let current = window.location.pathname.split("/")[1]
if (current == "main") {
message = "This is the documentation from the 'main' branch which is not a stable release."
}
message = message + '<a href="{{ "../" ~ base_url }}"> <strong>Click here to go to latest stable release.</strong> </a>'
document.getElementById("current-version").innerHTML = message;
</script>
{{app}}
{% endblock %}

View file

@ -0,0 +1,105 @@
<!--
~ 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.
-->
# ANTA Requirements
## Python version
Python 3 (`>=3.8`) is required:
```bash
python --version
Python 3.9.9
```
## Install ANTA package
This installation will deploy tests collection, scripts and all their Python requirements.
The ANTA package and the cli require some packages that are not part of the Python standard library. They are indicated in the [pyproject.toml](https://github.com/arista-netdevops-community/anta/blob/main/pyproject.toml) file, under dependencies.
### Install from Pypi server
```bash
pip install anta
```
### Install ANTA from github
```bash
pip install git+https://github.com/arista-netdevops-community/anta.git
# You can even specify the branch, tag or commit:
pip install git+https://github.com/arista-netdevops-community/anta.git@<cool-feature-branch>
pip install git+https://github.com/arista-netdevops-community/anta.git@<cool-tag>
pip install git+https://github.com/arista-netdevops-community/anta.git@<more-or-less-cool-hash>
```
### Check installation
After installing ANTA, verify the installation with the following commands:
```bash
# Check ANTA has been installed in your python path
pip list | grep anta
# Check scripts are in your $PATH
# Path may differ but it means CLI is in your path
which anta
/home/tom/.pyenv/shims/anta
```
!!! warning
Before running the `anta --version` command, please be aware that some users have reported issues related to the `urllib3` package. If you encounter an error at this step, please refer to our [FAQ](faq.md) page for guidance on resolving it.
```bash
# Check ANTA version
anta --version
anta, version v0.13.0
```
## EOS Requirements
To get ANTA working, the targetted Arista EOS devices must have the following configuration (assuming you connect to the device using Management interface in MGMT VRF):
```eos
configure
!
vrf instance MGMT
!
interface Management1
description oob_management
vrf MGMT
ip address 10.73.1.105/24
!
end
```
Enable eAPI on the MGMT vrf:
```eos
configure
!
management api http-commands
protocol https port 443
no shutdown
vrf MGMT
no shutdown
!
end
```
Now the swicth accepts on port 443 in the MGMT VRF HTTPS requests containing a list of CLI commands.
Run these EOS commands to verify:
```eos
show management http-server
show management api http-commands
```

View file

@ -0,0 +1,92 @@
# 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 script to generate svg files from anta command
usage:
python generate_svg.py anta ...
"""
import io
import os
import pathlib
import sys
from contextlib import redirect_stdout, suppress
from importlib import import_module
from importlib.metadata import entry_points
from unittest.mock import patch
from rich.console import Console
from anta.cli.console import console
from anta.cli.nrfu.utils import anta_progress_bar
OUTPUT_DIR = pathlib.Path(__file__).parent.parent / "imgs"
def custom_progress_bar() -> None:
"""
Set the console of progress_bar to main anta console
Caveat: this capture all steps of the progress bar..
Disabling refresh to only capture beginning and end
"""
progress = anta_progress_bar()
progress.live.auto_refresh = False
progress.live.console = console
return progress
if __name__ == "__main__":
# Sane rich size
os.environ["COLUMNS"] = "165"
# stolen from https://github.com/ewels/rich-click/blob/main/src/rich_click/cli.py
args = sys.argv[1:]
script_name = args[0]
scripts = {script.name: script for script in entry_points().get("console_scripts")}
if script_name in scripts:
# A VALID SCRIPT WAS passed
script = scripts[script_name]
module_path, function_name = script.value.split(":", 1)
prog = script_name
elif ":" in script_name:
# the path to a function was passed
module_path, function_name = args[0].split(":", 1)
prog = module_path.split(".", 1)[0]
else:
print("This is supposed to be used with anta only")
print("Usage: python generate_svg.py anta <options>")
sys.exit(1)
sys.argv = [prog, *args[1:]]
module = import_module(module_path)
function = getattr(module, function_name)
# Console to captur everything
new_console = Console(record=True)
# tweaks to record and redirect to a dummy file
pipe = io.StringIO()
console.record = True
console.file = pipe
# Redirect stdout of the program towards another StringIO to capture help
# that is not part or anta rich console
with redirect_stdout(io.StringIO()) as f:
# redirect potential progress bar output to console by patching
with patch("anta.cli.nrfu.commands.anta_progress_bar", custom_progress_bar):
with suppress(SystemExit):
function()
# print to our new console the output of anta console
new_console.print(console.export_text())
# print the content of the stdout to our new_console
new_console.print(f.getvalue())
filename = f"{'_'.join(map(lambda x: x.replace('/', '_').replace('-', '_').replace('.', '_'), args))}.svg"
filename = f"{OUTPUT_DIR}/{filename}"
print(f"File saved at {filename}")
new_console.save_svg(filename, title=" ".join(args))

View file

@ -0,0 +1,20 @@
Usage: anta [OPTIONS] COMMAND [ARGS]...
Arista Network Test Automation (ANTA) CLI
Options:
--version Show the version and exit.
--log-file FILE Send the logs to a file. If logging level is
DEBUG, only INFO or higher will be sent to
stdout. [env var: ANTA_LOG_FILE]
-l, --log-level [CRITICAL|ERROR|WARNING|INFO|DEBUG]
ANTA logging level [env var:
ANTA_LOG_LEVEL; default: INFO]
--help Show this message and exit.
Commands:
check Commands to validate configuration files
debug Commands to execute EOS commands on remote devices
exec Commands to execute various scripts on EOS devices
get Commands to get information from or generate inventories
nrfu Run ANTA tests on devices

View file

@ -0,0 +1,207 @@
[data-md-color-scheme="slate"] {
--md-hue: 210;
}
:root {
/* Color schema based on Arista Color Schema */
/* Default color shades */
--md-default-fg-color: #000000;
--md-default-fg-color--light: #a1a0a0;
--md-default-fg-color--lighter: #FFFFFF;
--md-default-fg-color--lightest: #FFFFFF;
--md-default-bg-color: #FFFFFF;
--md-default-bg-color--light: #FFFFFF;
--md-default-bg-color--lighter: #FFFFFF;
--md-default-bg-color--lightest: #FFFFFF;
/* Primary color shades */
--md-primary-fg-color: #27569B;
--md-primary-fg-color--light: #FFFFFF;
--md-primary-fg-color--dark: #27569B;
--md-primary-bg-color: #FFFFFF;
--md-primary-bg-color--light: #FFFFFF;
/* Accent color shades */
--md-accent-fg-color: #27569B;
--md-accent-bg-color: #27569B;
--md-accent-bg-color--light: #27569B;
/* Link color */
--md-typeset-a-color: #27569B;
--md-typeset-a-color-fg: #FFFFFF;
--md-typeset-a-color-bg: #27569B;
/* Code block color shades */
--md-code-bg-color: #E6E6E6;
--md-code-border-color: #0000004f;
--block-code-bg-color: #e4e4e4;
/* --md-code-fg-color: ...; */
font-size: 1.1rem;
/* min-height: 100%;
position: relative;
width: 100%; */
font-feature-settings: "kern","liga";
font-family: var(--md-text-font-family,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif;
-webkit-font-smoothing: antialiased;
}
[data-md-color-scheme="slate"] {
/* Link color */
--md-typeset-a-color: #75aaf8;
--md-typeset-a-color-fg: #FFFFFF;
--md-typeset-a-color-bg: #27569B;
/* Code block color shades */
/* --md-code-bg-color: #E6E6E6; */
--md-code-border-color: #aec6db4f;
/* --block-code-bg-color: #e4e4e4; */
}
@media only screen and (min-width: 76.25em) {
.md-main__inner, .md-header__inner {
max-width: 85%;
}
.md-sidebar--primary {
left: 5%;
}
.md-sidebar--secondary {
right: 5%;
margin-left: 0;
-webkit-transform: none;
transform: none;
}
}
@media only screen {
.md-typeset a:hover {
background-color: var(--md-typeset-a-color-bg);
color: var(--md-typeset-a-color-fg);
}
.md-footer-nav {
background-color: var(--md-default-bg-color--light);
color: var(--md-accent-fg-color--transparent)
}
.md-footer {
height: 2%;
}
.md-footer-nav__direction {
position: absolute;
right: 0;
left: 0;
margin-top: -1rem;
padding: 0 1rem;
color: var(--md-default-fg-color--light);
font-size: .64rem;
}
.md-footer-nav__title {
font-size: 1.2rem;
line-height: 10rem;
color: var(--md-default-fg-color--light);
}
.md-typeset h4 h5 h6 {
font-size: 1.5rem;
margin: 1em 0;
/* font-weight: 700; */
letter-spacing: -.01em;
line-height: 3em;
}
.md-typeset table:not([class]) th {
min-width: 5rem;
padding: .6rem .8rem;
color: var(--md-default-fg-color);
vertical-align: top;
/* background-color: var(--md-accent-bg-color); */
text-align: left;
/* min-width: 100%; */
/* display: table; */
}
.md-typeset table:not([class]) td {
/* padding: .9375em 1.25em; */
border-collapse: collapse;
vertical-align: center;
text-align: left;
/* border-bottom: 1px solid var(--md-default-fg-color--light); */
}
.md-typeset code {
padding: 0 .2941176471em;
font-size: 100%;
word-break: break-word;
background-color: var(--md-code-bg-color);
border-radius: .1rem;
-webkit-box-decoration-break: clone;
box-decoration-break: clone;
}
.highlight code {
background-color: var(--md-code-bg-color);
font-size: 90%;
border-radius: 2%;
}
.md-typeset .admonition, .md-typeset details {
margin: 1.5625em 0;
padding: 0 .6rem;
overflow: hidden;
font-size: 90%;
page-break-inside: avoid;
border-left: .2rem solid var(--md-accent-bg-color);
border-left-color: var(--md-accent-bg-color);
border-radius: .1rem;
box-shadow: 0 .2rem .5rem rgba(0,0,0,.05),0 0 .05rem rgba(0,0,0,.1);
}
/* .md-typeset .note > .admonition-title, .md-typeset .note > summary {
background-color: var(--md-accent-bg-color);
color: var(--md-default-fg-color--lighter)
} */
.md-typeset__table {
min-width: 80%;
}
.md-typeset table:not([class]) {
display: table;
}
.mdx-content__footer {
margin-top: 20px;
text-align: center;
}
.mdx-content__footer a {
display: inline-block;
transition: transform 250ms cubic-bezier(0.1, 0.7, 0.1, 1), color 125ms;
}
.mdx-content__footer a:focus, .mdx-content__footer a:hover {
transform: scale(1.2);
}
.md-typeset table:not([class]) th {
min-width: 5rem;
padding: .6rem .8rem;
/* color: var(--md-primary-fg-color--light); */
bg: var(--md-footer-fg-color--lighter);
}
.md-footer-copyright {
color: var(--md-footer-fg-color--lighter);
font-size: .64rem;
margin: auto 0.6rem;
padding: 0.4rem;
width: 100%;
text-align: center;
}
.img_center {
display: block;
margin-left: auto;
margin-right: auto;
border-radius: 1%;
/* width: 50%; */
}
}
/* mkdocstrings css from official repo to indent sub-elements nicely */
/* Indentation. */
div.doc-contents {
padding-left: 25px;
border-left: .05rem solid var(--md-typeset-table-color);
}

View file

@ -0,0 +1,3 @@
document$.subscribe(() => {
hljs.highlightAll()
})

View file

@ -0,0 +1,6 @@
document$.subscribe(function() {
var tables = document.querySelectorAll("article table")
tables.forEach(function(table) {
new Tablesort(table)
})
})

View file

@ -0,0 +1,246 @@
<!--
~ 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.
-->
# Inventory and Catalog
The ANTA framework needs 2 important inputs from the user to run: a **device inventory** and a **test catalog**.
Both inputs can be defined in a file or programmatically.
## Device Inventory
A device inventory is an instance of the [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) class.
### Device Inventory File
The ANTA device inventory can easily be defined as a YAML file.
The file must comply with the following structure:
```yaml
anta_inventory:
hosts:
- host: < ip address value >
port: < TCP port for eAPI. Default is 443 (Optional)>
name: < name to display in report. Default is host:port (Optional) >
tags: < list of tags to use to filter inventory during tests >
disable_cache: < Disable cache per hosts. Default is False. >
networks:
- network: < network using CIDR notation >
tags: < list of tags to use to filter inventory during tests >
disable_cache: < Disable cache per network. Default is False. >
ranges:
- start: < first ip address value of the range >
end: < last ip address value of the range >
tags: < list of tags to use to filter inventory during tests >
disable_cache: < Disable cache per range. Default is False. >
```
The inventory file must start with the `anta_inventory` key then define one or multiple methods:
- `hosts`: define each device individually
- `networks`: scan a network for devices accesible via eAPI
- `ranges`: scan a range for devices accesible via eAPI
A full description of the inventory model is available in [API documentation](api/inventory.models.input.md)
!!! info
Caching can be disabled per device, network or range by setting the `disable_cache` key to `True` in the inventory file. For more details about how caching is implemented in ANTA, please refer to [Caching in ANTA](advanced_usages/caching.md).
### Example
```yaml
---
anta_inventory:
hosts:
- host: 192.168.0.10
name: spine01
tags: ['fabric', 'spine']
- host: 192.168.0.11
name: spine02
tags: ['fabric', 'spine']
networks:
- network: '192.168.110.0/24'
tags: ['fabric', 'leaf']
ranges:
- start: 10.0.0.9
end: 10.0.0.11
tags: ['fabric', 'l2leaf']
```
## Test Catalog
A test catalog is an instance of the [AntaCatalog](../api/catalog.md#anta.catalog.AntaCatalog) class.
### Test Catalog File
In addition to the inventory file, you also have to define a catalog of tests to execute against your devices. This catalog list all your tests, their inputs and their tags.
A valid test catalog file must have the following structure:
```yaml
---
<Python module>:
- <AntaTest subclass>:
<AntaTest.Input compliant dictionary>
```
### Example
```yaml
---
anta.tests.connectivity:
- VerifyReachability:
hosts:
- source: Management0
destination: 1.1.1.1
vrf: MGMT
- source: Management0
destination: 8.8.8.8
vrf: MGMT
filters:
tags: ['leaf']
result_overwrite:
categories:
- "Overwritten category 1"
description: "Test with overwritten description"
custom_field: "Test run by John Doe"
```
It is also possible to nest Python module definition:
```yaml
anta.tests:
connectivity:
- VerifyReachability:
hosts:
- source: Management0
destination: 1.1.1.1
vrf: MGMT
- source: Management0
destination: 8.8.8.8
vrf: MGMT
filters:
tags: ['leaf']
result_overwrite:
categories:
- "Overwritten category 1"
description: "Test with overwritten description"
custom_field: "Test run by John Doe"
```
[This test catalog example](https://github.com/arista-netdevops-community/anta/blob/main/examples/tests.yaml) is maintained with all the tests defined in the `anta.tests` Python module.
### Test tags
All tests can be defined with a list of user defined tags. These tags will be mapped with device tags: when at least one tag is defined for a test, this test will only be executed on devices with the same tag. If a test is defined in the catalog without any tags, the test will be executed on all devices.
```yaml
anta.tests.system:
- VerifyUptime:
minimum: 10
filters:
tags: ['demo', 'leaf']
- VerifyReloadCause:
- VerifyCoredump:
- VerifyAgentLogs:
- VerifyCPUUtilization:
filters:
tags: ['leaf']
```
!!! info
When using the CLI, you can filter the NRFU execution using tags. Refer to [this section](cli/tag-management.md) of the CLI documentation.
### Tests available in ANTA
All tests available as part of the ANTA framework are defined under the `anta.tests` Python module and are categorised per family (Python submodule).
The complete list of the tests and their respective inputs is available at the [tests section](api/tests.md) of this website.
To run test to verify the EOS software version, you can do:
```yaml
anta.tests.software:
- VerifyEOSVersion:
```
It will load the test `VerifyEOSVersion` located in `anta.tests.software`. But since this test has mandatory inputs, we need to provide them as a dictionary in the YAML file:
```yaml
anta.tests.software:
- VerifyEOSVersion:
# List of allowed EOS versions.
versions:
- 4.25.4M
- 4.26.1F
```
The following example is a very minimal test catalog:
```yaml
---
# Load anta.tests.software
anta.tests.software:
# Verifies the device is running one of the allowed EOS version.
- VerifyEOSVersion:
# List of allowed EOS versions.
versions:
- 4.25.4M
- 4.26.1F
# Load anta.tests.system
anta.tests.system:
# Verifies the device uptime is higher than a value.
- VerifyUptime:
minimum: 1
# Load anta.tests.configuration
anta.tests.configuration:
# Verifies ZeroTouch is disabled.
- VerifyZeroTouch:
- VerifyRunningConfigDiffs:
```
### Catalog with custom tests
In case you want to leverage your own tests collection, use your own Python package in the test catalog.
So for instance, if my custom tests are defined in the `titom73.tests.system` Python module, the test catalog will be:
```yaml
titom73.tests.system:
- VerifyPlatform:
type: ['cEOS-LAB']
```
!!! tip "How to create custom tests"
To create your custom tests, you should refer to this [documentation](advanced_usages/custom-tests.md)
### Customize test description and categories
It might be interesting to use your own categories and customized test description to build a better report for your environment. ANTA comes with a handy feature to define your own `categories` and `description` in the report.
In your test catalog, use `result_overwrite` dictionary with `categories` and `description` to just overwrite this values in your report:
```yaml
anta.tests.configuration:
- VerifyZeroTouch: # Verifies ZeroTouch is disabled.
result_overwrite:
categories: ['demo', 'pr296']
description: A custom test
- VerifyRunningConfigDiffs:
anta.tests.interfaces:
- VerifyInterfaceUtilization:
```
Once you run `anta nrfu table`, you will see following output:
```bash
┏━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━┳━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━┓
┃ Device IP ┃ Test Name ┃ Test Status ┃ Message(s) ┃ Test description ┃ Test category ┃
┡━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━╇━━━━━━━━━━━━╇━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╇━━━━━━━━━━━━━━━┩
│ spine01 │ VerifyZeroTouch │ success │ │ A custom test │ demo, pr296 │
│ spine01 │ VerifyRunningConfigDiffs │ success │ │ │ configuration │
│ spine01 │ VerifyInterfaceUtilization │ success │ │ Verifies interfaces utilization is below 75%. │ interfaces │
└───────────┴────────────────────────────┴─────────────┴────────────┴───────────────────────────────────────────────┴───────────────┘
```