summaryrefslogtreecommitdiffstats
path: root/docs
diff options
context:
space:
mode:
Diffstat (limited to 'docs')
-rwxr-xr-xdocs/README.md14
-rw-r--r--docs/advanced_usages/as-python-lib.md14
-rw-r--r--docs/advanced_usages/caching.md6
-rw-r--r--docs/advanced_usages/custom-tests.md52
-rw-r--r--docs/api/tests.aaa.md11
-rw-r--r--docs/api/tests.bfd.md11
-rw-r--r--docs/api/tests.configuration.md11
-rw-r--r--docs/api/tests.connectivity.md11
-rw-r--r--docs/api/tests.field_notices.md11
-rw-r--r--docs/api/tests.greent.md20
-rw-r--r--docs/api/tests.hardware.md11
-rw-r--r--docs/api/tests.interfaces.md11
-rw-r--r--docs/api/tests.lanz.md20
-rw-r--r--docs/api/tests.logging.md11
-rw-r--r--docs/api/tests.md15
-rw-r--r--docs/api/tests.mlag.md11
-rw-r--r--docs/api/tests.multicast.md11
-rw-r--r--docs/api/tests.profiles.md11
-rw-r--r--docs/api/tests.ptp.md20
-rw-r--r--docs/api/tests.routing.bgp.md11
-rw-r--r--docs/api/tests.routing.generic.md11
-rw-r--r--docs/api/tests.routing.ospf.md11
-rw-r--r--docs/api/tests.security.md11
-rw-r--r--docs/api/tests.services.md11
-rw-r--r--docs/api/tests.snmp.md11
-rw-r--r--docs/api/tests.software.md11
-rw-r--r--docs/api/tests.stp.md11
-rw-r--r--docs/api/tests.stun.md20
-rw-r--r--docs/api/tests.system.md11
-rw-r--r--docs/api/tests.vlan.md11
-rw-r--r--docs/api/tests.vxlan.md11
-rw-r--r--docs/cli/debug.md39
-rw-r--r--docs/cli/exec.md54
-rw-r--r--docs/cli/get-inventory-information.md31
-rw-r--r--docs/cli/inv-from-ansible.md2
-rw-r--r--docs/cli/nrfu.md83
-rw-r--r--docs/cli/overview.md8
-rw-r--r--docs/contribution.md10
-rw-r--r--docs/faq.md122
-rw-r--r--docs/getting-started.md49
-rw-r--r--docs/imgs/animated-svg.md8
-rw-r--r--docs/imgs/anta-nrfu.svg2
-rw-r--r--docs/overrides/partials/content.html18
-rw-r--r--docs/overrides/partials/toc-item.html21
-rw-r--r--docs/requirements-and-installation.md10
-rw-r--r--docs/scripts/__init__.py4
-rw-r--r--docs/scripts/generate_svg.py20
-rw-r--r--docs/snippets/anta_help.txt12
-rw-r--r--docs/snippets/anta_nrfu_help.txt51
-rw-r--r--docs/templates/python/material/anta_test.html163
-rw-r--r--docs/templates/python/material/attributes_table.html70
-rw-r--r--docs/templates/python/material/class.html35
-rw-r--r--docs/templates/python/material/docstring.html36
-rw-r--r--docs/templates/python/material/docstring/examples.html14
-rw-r--r--docs/troubleshooting.md79
-rw-r--r--docs/usage-inventory-catalog.md8
56 files changed, 1044 insertions, 328 deletions
diff --git a/docs/README.md b/docs/README.md
index d47d3fe..1fe8734 100755
--- a/docs/README.md
+++ b/docs/README.md
@@ -4,16 +4,14 @@
~ 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
+| **Code** | [![Ruff](https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json)](https://github.com/astral-sh/ruff) [![Numpy](https://img.shields.io/badge/Docstring_format-numpy-blue)](https://numpydoc.readthedocs.io/en/latest/format.html) |
+| :------------: | :-------|
+| **License** | [![License](https://img.shields.io/badge/license-Apache%202.0-brightgreen.svg)](https://github.com/arista-netdevops-community/anta/blob/main/LICENSE) |
+| **GitHub** | [![CI](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) ![Coverage](https://raw.githubusercontent.com/arista-netdevops-community/anta/coverage-badge/latest-release-coverage.svg) ![Commit](https://img.shields.io/github/last-commit/arista-netdevops-community/anta) ![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/) [![Contributors](https://img.shields.io/github/contributors/arista-netdevops-community/anta)](https://github.com/arista-netdevops-community/anta/graphs/contributors) |
+| **PyPi** | ![PyPi Version](https://img.shields.io/pypi/v/anta) ![Python Versions](https://img.shields.io/pypi/pyversions/anta) ![Python format](https://img.shields.io/pypi/format/anta) ![PyPI - Downloads](https://img.shields.io/pypi/dm/anta) |
+
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
diff --git a/docs/advanced_usages/as-python-lib.md b/docs/advanced_usages/as-python-lib.md
index b4ce654..f8d6734 100644
--- a/docs/advanced_usages/as-python-lib.md
+++ b/docs/advanced_usages/as-python-lib.md
@@ -72,7 +72,6 @@ if __name__ == "__main__":
filename="inv.yml",
username="arista",
password="@rista123",
- timeout=15,
)
# Run the main coroutine
@@ -129,7 +128,6 @@ if __name__ == "__main__":
filename="inv.yml",
username="arista",
password="@rista123",
- timeout=15,
)
# Create a list of commands with json output
@@ -228,7 +226,7 @@ class VerifyTransceiversManufacturers(AntaTest):
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:
+The test itself does not return any value, but the result is directly available 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.
@@ -256,7 +254,7 @@ To make it easier to get data, ANTA defines 2 different classes to manage comman
Represent a command with following information:
- Command to run
-- Ouput format expected
+- Output format expected
- eAPI version
- Output of the command
@@ -272,13 +270,13 @@ 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__ 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__ values 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.
+ * By default, eAPI returns the first revision of each model to ensure that when upgrading, integrations with existing tools are 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.
+ By default, ANTA uses `version="latest"` in AntaCommand, but when developing tests, the revision MUST be provided when the outformat of the command is `json`. As explained earlier, this is to ensure that the eAPI always returns the same output model and that the test remains always valid from the day it was created. For some commands, you may also want to run them with a different revision or version.
- For instance the `VerifyRoutingTableSize` test leverages the first revision of `show bfd peers`:
+ For instance, the `VerifyBFDPeersHealth` test leverages the first revision of `show bfd peers`:
```
# revision 1 as later revision introduce additional nesting for type
diff --git a/docs/advanced_usages/caching.md b/docs/advanced_usages/caching.md
index cec2467..ce4a787 100644
--- a/docs/advanced_usages/caching.md
+++ b/docs/advanced_usages/caching.md
@@ -47,7 +47,7 @@ There might be scenarios where caching is not wanted. You can disable caching in
```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:
+2. Caching can be disabled per device, network or range by setting the `disable_cache` key to `True` when defining the ANTA [Inventory](../usage-inventory-catalog.md#create-an-inventory-file) file:
```yaml
anta_inventory:
hosts:
@@ -71,7 +71,7 @@ There might be scenarios where caching is not wanted. You can disable caching in
```
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.
+3. For tests developers, 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`
@@ -82,6 +82,6 @@ class AnsibleEOSDevice(AntaDevice):
"""
Implementation of an AntaDevice using Ansible HttpApi plugin for EOS.
"""
- def __init__(self, name: str, connection: ConnectionBase, tags: list = None) -> None:
+ def __init__(self, name: str, connection: ConnectionBase, tags: set = None) -> None:
super().__init__(name, tags, disable_cache=True)
```
diff --git a/docs/advanced_usages/custom-tests.md b/docs/advanced_usages/custom-tests.md
index 87402c1..df17c1c 100644
--- a/docs/advanced_usages/custom-tests.md
+++ b/docs/advanced_usages/custom-tests.md
@@ -21,24 +21,32 @@ 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.
+ """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.
+
+ Examples
+ --------
+ ```yaml
+ anta.tests.hardware:
+ - VerifyTemperature:
+ ```
"""
name = "VerifyTemperature"
- description = "Verifies if the device temperature is within the acceptable range."
- categories = ["hardware"]
- commands = [AntaCommand(command="show system environment temperature", ofmt="json")]
+ description = "Verifies the device temperature."
+ categories: ClassVar[list[str]] = ["hardware"]
+ commands: ClassVar[list[AntaCommand | AntaTemplate]] = [AntaCommand(command="show system environment temperature", revision=1)]
- @skip_on_platforms(["cEOSLab", "vEOS-lab"])
+ @skip_on_platforms(["cEOSLab", "vEOS-lab", "cEOSCloudLab"])
@AntaTest.anta_test
def test(self) -> None:
+ """Main test function for VerifyTemperature."""
command_output = self.instance_commands[0].json_output
- temperature_status = command_output["systemStatus"] if "systemStatus" in command_output.keys() else ""
+ temperature_status = command_output.get("systemStatus", "")
if temperature_status == "temperatureOk":
self.result.is_success()
else:
@@ -54,7 +62,7 @@ class VerifyTemperature(AntaTest):
- `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.
+- `commands` (`[list[AntaCommand | AntaTemplate]]`): 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.
@@ -127,7 +135,7 @@ The base definition of [AntaTest.Input](../api/models.md#anta.models.AntaTest.In
### 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.
+- [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) occurrence 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
@@ -191,8 +199,24 @@ If the user needs to provide inputs for your test, you need to define a [pydanti
```python
class <YourTestName>(AntaTest):
+ """Verifies ...
+
+ Expected Results
+ ----------------
+ * Success: The test will pass if ...
+ * Failure: The test will fail if ...
+
+ Examples
+ --------
+ ```yaml
+ your.module.path:
+ - YourTestName:
+ field_name: example_field_value
+ ```
+ """
...
- class Input(AntaTest.Input): # pylint: disable=missing-class-docstring
+ class Input(AntaTest.Input):
+ """Inputs for my awesome test."""
<input field name>: <input field type>
"""<input field docstring>"""
```
diff --git a/docs/api/tests.aaa.md b/docs/api/tests.aaa.md
index bdbe7ec..e5c4b91 100644
--- a/docs/api/tests.aaa.md
+++ b/docs/api/tests.aaa.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for AAA tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.bfd.md b/docs/api/tests.bfd.md
index d28521f..719466e 100644
--- a/docs/api/tests.bfd.md
+++ b/docs/api/tests.bfd.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for BFD tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ show_labels: true
+ anta_hide_test_module_description: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.configuration.md b/docs/api/tests.configuration.md
index aaee1f4..9b24ea7 100644
--- a/docs/api/tests.configuration.md
+++ b/docs/api/tests.configuration.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for device configuration tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.connectivity.md b/docs/api/tests.connectivity.md
index 8a1b8a2..0dd5d44 100644
--- a/docs/api/tests.connectivity.md
+++ b/docs/api/tests.connectivity.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for connectivity tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.field_notices.md b/docs/api/tests.field_notices.md
index ed0e837..fe95bf5 100644
--- a/docs/api/tests.field_notices.md
+++ b/docs/api/tests.field_notices.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for Field Notices tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.greent.md b/docs/api/tests.greent.md
new file mode 100644
index 0000000..01900a9
--- /dev/null
+++ b/docs/api/tests.greent.md
@@ -0,0 +1,20 @@
+---
+anta_title: ANTA catalog for GreenT tests
+---
+<!--
+ ~ 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.greent
+ options:
+ show_root_heading: false
+ show_root_toc_entry: false
+ show_bases: false
+ merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.hardware.md b/docs/api/tests.hardware.md
index 6e84196..ad06a50 100644
--- a/docs/api/tests.hardware.md
+++ b/docs/api/tests.hardware.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for hardware tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.interfaces.md b/docs/api/tests.interfaces.md
index b21da40..95630f5 100644
--- a/docs/api/tests.interfaces.md
+++ b/docs/api/tests.interfaces.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for interfaces tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.lanz.md b/docs/api/tests.lanz.md
new file mode 100644
index 0000000..0685717
--- /dev/null
+++ b/docs/api/tests.lanz.md
@@ -0,0 +1,20 @@
+---
+anta_title: ANTA catalog for LANZ tests
+---
+<!--
+ ~ 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.lanz
+ options:
+ show_root_heading: false
+ show_root_toc_entry: false
+ show_bases: false
+ merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.logging.md b/docs/api/tests.logging.md
index e9acc20..2c4dec0 100644
--- a/docs/api/tests.logging.md
+++ b/docs/api/tests.logging.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for logging tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.md b/docs/api/tests.md
index 40c7d8a..1db3a8b 100644
--- a/docs/api/tests.md
+++ b/docs/api/tests.md
@@ -4,22 +4,28 @@
~ that can be found in the LICENSE file.
-->
-# ANTA Tests landing page
+# ANTA Tests Landing Page
-This section describes all the available tests provided by ANTA package.
+This section describes all the available tests provided by the ANTA package.
+## Available Tests
+
+Here are the tests that we currently provide:
- [AAA](tests.aaa.md)
- [BFD](tests.bfd.md)
- [Configuration](tests.configuration.md)
- [Connectivity](tests.connectivity.md)
- [Field Notice](tests.field_notices.md)
+- [GreenT](tests.greent.md)
- [Hardware](tests.hardware.md)
- [Interfaces](tests.interfaces.md)
+- [LANZ](tests.lanz.md)
- [Logging](tests.logging.md)
- [MLAG](tests.mlag.md)
- [Multicast](tests.multicast.md)
- [Profiles](tests.profiles.md)
+- [PTP](tests.ptp.md)
- [Routing Generic](tests.routing.generic.md)
- [Routing BGP](tests.routing.bgp.md)
- [Routing OSPF](tests.routing.ospf.md)
@@ -28,10 +34,11 @@ This section describes all the available tests provided by ANTA package.
- [SNMP](tests.snmp.md)
- [Software](tests.software.md)
- [STP](tests.stp.md)
+- [STUN](tests.stun.md)
- [System](tests.system.md)
- [VLAN](tests.vlan.md)
- [VXLAN](tests.vxlan.md)
+## Using the Tests
-
-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)
+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).
diff --git a/docs/api/tests.mlag.md b/docs/api/tests.mlag.md
index 6ce419b..5470bcd 100644
--- a/docs/api/tests.mlag.md
+++ b/docs/api/tests.mlag.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for MLAG tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.multicast.md b/docs/api/tests.multicast.md
index 2b03420..7072796 100644
--- a/docs/api/tests.multicast.md
+++ b/docs/api/tests.multicast.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for multicast and IGMP tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.profiles.md b/docs/api/tests.profiles.md
index c6d06e7..a022c6a 100644
--- a/docs/api/tests.profiles.md
+++ b/docs/api/tests.profiles.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for profiles tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.ptp.md b/docs/api/tests.ptp.md
new file mode 100644
index 0000000..3b03ac0
--- /dev/null
+++ b/docs/api/tests.ptp.md
@@ -0,0 +1,20 @@
+---
+anta_title: ANTA catalog for PTP tests
+---
+<!--
+ ~ 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.ptp
+ options:
+ show_root_heading: false
+ show_root_toc_entry: false
+ show_bases: false
+ merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.routing.bgp.md b/docs/api/tests.routing.bgp.md
index 2346866..5c54678 100644
--- a/docs/api/tests.routing.bgp.md
+++ b/docs/api/tests.routing.bgp.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for BGP tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.routing.generic.md b/docs/api/tests.routing.generic.md
index 3853fb0..1c4c39d 100644
--- a/docs/api/tests.routing.generic.md
+++ b/docs/api/tests.routing.generic.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for generic routing tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.routing.ospf.md b/docs/api/tests.routing.ospf.md
index c4e6fed..a01eb50 100644
--- a/docs/api/tests.routing.ospf.md
+++ b/docs/api/tests.routing.ospf.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for OSPF tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.security.md b/docs/api/tests.security.md
index 1186b31..fe008ba 100644
--- a/docs/api/tests.security.md
+++ b/docs/api/tests.security.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for security tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.services.md b/docs/api/tests.services.md
index 82a7b38..63d9234 100644
--- a/docs/api/tests.services.md
+++ b/docs/api/tests.services.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for services tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.snmp.md b/docs/api/tests.snmp.md
index a015d04..be2da48 100644
--- a/docs/api/tests.snmp.md
+++ b/docs/api/tests.snmp.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for SNMP tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.software.md b/docs/api/tests.software.md
index 7a2f0ec..7600476 100644
--- a/docs/api/tests.software.md
+++ b/docs/api/tests.software.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for Software tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.stp.md b/docs/api/tests.stp.md
index f86dac4..50a004b 100644
--- a/docs/api/tests.stp.md
+++ b/docs/api/tests.stp.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for STP tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.stun.md b/docs/api/tests.stun.md
new file mode 100644
index 0000000..b4274e9
--- /dev/null
+++ b/docs/api/tests.stun.md
@@ -0,0 +1,20 @@
+---
+anta_title: ANTA catalog for STUN tests
+---
+<!--
+ ~ 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.stun
+ options:
+ show_root_heading: false
+ show_root_toc_entry: false
+ show_bases: false
+ merge_init_into_class: false
+ anta_hide_test_module_description: true
+ show_labels: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.system.md b/docs/api/tests.system.md
index 621c17b..5dcfbc0 100644
--- a/docs/api/tests.system.md
+++ b/docs/api/tests.system.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for System tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ show_labels: true
+ anta_hide_test_module_description: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.vlan.md b/docs/api/tests.vlan.md
index 0e1aa15..74cb003 100644
--- a/docs/api/tests.vlan.md
+++ b/docs/api/tests.vlan.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for VLAN tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ show_labels: true
+ anta_hide_test_module_description: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/api/tests.vxlan.md b/docs/api/tests.vxlan.md
index a4dcff3..4c3859a 100644
--- a/docs/api/tests.vxlan.md
+++ b/docs/api/tests.vxlan.md
@@ -1,13 +1,20 @@
+---
+anta_title: ANTA catalog for VXLAN tests
+---
<!--
~ 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
+ show_bases: false
merge_init_into_class: false
+ show_labels: true
+ anta_hide_test_module_description: true
+ filters:
+ - "!test"
+ - "!render"
diff --git a/docs/cli/debug.md b/docs/cli/debug.md
index 1743c7a..db5f496 100644
--- a/docs/cli/debug.md
+++ b/docs/cli/debug.md
@@ -23,10 +23,9 @@ You can use the `run-cmd` entrypoint to run a command, which includes the follow
### Command overview
```bash
-$ anta debug run-cmd --help
Usage: anta debug run-cmd [OPTIONS]
- Run arbitrary command to an ANTA device
+ Run arbitrary command to an ANTA device.
Options:
-u, --username TEXT Username to connect to EOS [env var:
@@ -44,16 +43,17 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used for
+ all devices. [env var: ANTA_TIMEOUT; default:
+ 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --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
@@ -90,15 +90,15 @@ The `run-template` entrypoint allows the user to provide an [`f-string`](https:/
### 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:
+ used as template parameters.
- anta debug run-template -d leaf1a -t 'show vlan {vlan_id}' vlan_id 1
+ 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:
@@ -116,16 +116,17 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used for
+ all devices. [env var: ANTA_TIMEOUT; default:
+ 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --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
diff --git a/docs/cli/exec.md b/docs/cli/exec.md
index fe39c12..061a19e 100644
--- a/docs/cli/exec.md
+++ b/docs/cli/exec.md
@@ -31,10 +31,9 @@ This command clears interface counters on EOS devices specified in your inventor
### Command overview
```bash
-anta exec clear-counters --help
Usage: anta exec clear-counters [OPTIONS]
- Clear counter statistics on EOS devices
+ Clear counter statistics on EOS devices.
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
@@ -50,16 +49,16 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used for all
+ devices. [env var: ANTA_TIMEOUT; default: 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --tags TEXT List of tags using comma as separator:
+ tag1,tag2,tag3. [env var: ANTA_TAGS]
--help Show this message and exit.
```
@@ -84,10 +83,9 @@ This command collects all the commands specified in a commands-list file, which
### Command overview
```bash
-anta exec snapshot --help
Usage: anta exec snapshot [OPTIONS]
- Collect commands output from devices in inventory
+ Collect commands output from devices in inventory.
Options:
-u, --username TEXT Username to connect to EOS [env var:
@@ -105,21 +103,22 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used for
+ all devices. [env var: ANTA_TIMEOUT; default:
+ 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --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]
+ anta_snapshot_2024-04-09_15_56_19]
--help Show this message and exit.
```
@@ -203,10 +202,9 @@ For Network Readiness for Use (NRFU) tests and to keep a comprehensive report of
### Command overview
```bash
-anta exec collect-tech-support --help
Usage: anta exec collect-tech-support [OPTIONS]
- Collect scheduled tech-support from EOS devices
+ Collect scheduled tech-support from EOS devices.
Options:
-u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME;
@@ -222,16 +220,16 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used for all
+ devices. [env var: ANTA_TIMEOUT; default: 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --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
diff --git a/docs/cli/get-inventory-information.md b/docs/cli/get-inventory-information.md
index 70100fe..1831484 100644
--- a/docs/cli/get-inventory-information.md
+++ b/docs/cli/get-inventory-information.md
@@ -72,7 +72,6 @@ As most of ANTA's commands accommodate tag filtering, this particular command is
### Command overview
```bash
-anta get tags --help
Usage: anta get tags [OPTIONS]
Get list of configured tags in user inventory.
@@ -91,16 +90,16 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used for all
+ devices. [env var: ANTA_TIMEOUT; default: 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --tags TEXT List of tags using comma as separator:
+ tag1,tag2,tag3. [env var: ANTA_TAGS]
--help Show this message and exit.
```
@@ -132,7 +131,6 @@ This command will list all devices available in the inventory. Using the `--tags
### Command overview
```bash
-anta get inventory --help
Usage: anta get inventory [OPTIONS]
Show inventory loaded in ANTA.
@@ -153,16 +151,17 @@ Options:
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:
+ --timeout FLOAT Global API timeout. This value will be used
+ for all devices. [env var: ANTA_TIMEOUT;
+ default: 30.0]
+ --insecure Disable SSH Host Key validation. [env var:
ANTA_INSECURE]
- --disable-cache Disable cache globally [env var:
+ --disable-cache Disable cache globally. [env var:
ANTA_DISABLE_CACHE]
- -i, --inventory FILE Path to the inventory YAML file [env var:
+ -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]
+ --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.
diff --git a/docs/cli/inv-from-ansible.md b/docs/cli/inv-from-ansible.md
index bb944d4..ebe7da3 100644
--- a/docs/cli/inv-from-ansible.md
+++ b/docs/cli/inv-from-ansible.md
@@ -39,7 +39,7 @@ anta_inventory:
```
!!! 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.
+ The current implementation only considers devices directly attached to a specific Ansible group and does not support inheritance 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
diff --git a/docs/cli/nrfu.md b/docs/cli/nrfu.md
index 6dcc393..7427f62 100644
--- a/docs/cli/nrfu.md
+++ b/docs/cli/nrfu.md
@@ -13,51 +13,10 @@ ANTA provides a set of commands for performing NRFU tests on devices. These comm
- [JSON view](#performing-nrfu-with-json-rendering)
- [Custom template view](#performing-nrfu-with-custom-reports)
-### NRFU Command overview
+## 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
+--8<-- "anta_nrfu_help.txt"
```
> `username`, `password`, `enable-password`, `enable`, `timeout` and `insecure` values are the same for all devices
@@ -67,7 +26,7 @@ All commands under the `anta nrfu` namespace require a catalog yaml file specifi
!!! info
Issuing the command `anta nrfu` will run `anta nrfu table` without any option.
-## Tag management
+### 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:
@@ -80,6 +39,14 @@ The `--tags` option can be used to target specific devices in your inventory and
!!! info
[More examples](tag-management.md) available on this dedicated page.
+### Device and test filtering
+
+Options `--device` and `--test` can be used to target one or multiple devices and/or tests to run in your environment. The options can be repeated. Example: `anta nrfu --device leaf1a --device leaf1b --test VerifyUptime --test VerifyReloadCause`.
+
+### Hide results
+
+Option `--hide` can be used to hide test results in the output based on their status. The option can be repeated. Example: `anta nrfu --hide error --hide skipped`.
+
## Performing NRFU with text rendering
The `text` subcommand provides a straightforward text report for each test executed on all devices in your inventory.
@@ -87,25 +54,18 @@ The `text` subcommand provides a straightforward text report for each test execu
### Command overview
```bash
-anta nrfu text --help
Usage: anta nrfu text [OPTIONS]
- ANTA command to check network states with text result
+ 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.
+ --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 --device DC1-LEAF1A text
```
[![anta nrfu text results](../imgs/anta-nrfu-text-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-text-output.png)
@@ -116,20 +76,15 @@ The `table` command under the `anta nrfu` namespace offers a clear and organized
### Command overview
```bash
-anta nrfu table --help
Usage: anta nrfu table [OPTIONS]
- ANTA command to check network states with table result
+ 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
+ --group-by [device|test] Group result by test or device.
--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
@@ -154,12 +109,12 @@ anta nrfu table --group-by test
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 --device spine1 table
```
[![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 --test VerifyZeroTouch table
```
[![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)
@@ -173,7 +128,7 @@ The JSON rendering command in NRFU testing is useful in generating a JSON output
anta nrfu json --help
Usage: anta nrfu json [OPTIONS]
- ANTA command to check network state with JSON result
+ ANTA command to check network state with JSON result.
Options:
-o, --output FILE Path to save report as a file [env var:
diff --git a/docs/cli/overview.md b/docs/cli/overview.md
index 90e70a5..5e95ff5 100644
--- a/docs/cli/overview.md
+++ b/docs/cli/overview.md
@@ -22,7 +22,7 @@ $ anta --help
--8<-- "anta_help.txt"
```
-## ANTA environement variables
+## ANTA environment variables
Certain parameters are required and can be either passed to the ANTA CLI or set as an environment variable (ENV VAR).
@@ -48,10 +48,10 @@ anta nrfu
```
!!! note
- All environement variables may not be needed for every commands.
- Refer to `<command> --help` for the comprehensive environment varibles names.
+ All environment variables may not be needed for every commands.
+ Refer to `<command> --help` for the comprehensive environment variables names.
-Below are the environement variables usable with the `anta nrfu` command:
+Below are the environment variables usable with the `anta nrfu` command:
| Variable Name | Purpose | Required |
| ------------- | ------- |----------|
diff --git a/docs/contribution.md b/docs/contribution.md
index 49df256..5c6ae8e 100644
--- a/docs/contribution.md
+++ b/docs/contribution.md
@@ -10,9 +10,9 @@ Contribution model is based on a fork-model. Don't push to arista-netdevops-comm
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
+## Create a development environment
-Run the following commands to create an ANTA development environement:
+Run the following commands to create an ANTA development environment:
```bash
# Clone repository
@@ -26,10 +26,10 @@ $ pip install -e .[dev]
$ pip list -e
Package Version Editable project location
------- ------- -------------------------
-anta 0.13.0 /mnt/lab/projects/anta
+anta 0.14.0 /mnt/lab/projects/anta
```
-Then, [`tox`](https://tox.wiki/) is configued with few environments to run CI locally:
+Then, [`tox`](https://tox.wiki/) is configured with few environments to run CI locally:
```bash
$ tox list -d
@@ -219,7 +219,7 @@ Image will be generated under `docs/imgs/uml/` and can be inserted in your docum
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
+muffet -c 2 --color=always http://127.0.0.1:8000 -e fonts.gstatic.com -b 8192
```
## Continuous Integration
diff --git a/docs/faq.md b/docs/faq.md
index 7c995ac..1cce990 100644
--- a/docs/faq.md
+++ b/docs/faq.md
@@ -1,67 +1,129 @@
+---
+toc_depth: 4
+---
<!--
~ 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.
-->
+<style>
+ h4 {
+ visibility: hidden;
+ font-size: 0em;
+ height: 0em;
+ line-height: 0;
+ padding: 0;
+ margin: 0;
+ }
+ .md-typeset details {
+ margin-top: 0em;
+ margin-bottom: 0.8em;
+ }
+</style>
# Frequently Asked Questions (FAQ)
-## Why am I seeing an `ImportError` related to `urllib3` when running ANTA?
+## A local OS error occurred while connecting to a device
+???+ faq "A local OS error occurred while connecting to a device"
-When running the `anta --help` command, some users might encounter the following error:
+ When running ANTA, you can receive `A local OS error occurred while connecting to <device>` errors. The underlying [`OSError`](https://docs.python.org/3/library/exceptions.html#OSError) exception can have various reasons: `[Errno 24] Too many open files` or `[Errno 16] Device or resource busy`.
-```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 usually means that the operating system refused to open a new file descriptor (or socket) for the ANTA process. This might be due to the hard limit for open file descriptors currently set for the ANTA process.
-This error arises due to a compatibility issue between `urllib3` v2.0 and older versions of OpenSSL.
+ At startup, ANTA sets the soft limit of its process to the hard limit up to 16384. This is because the soft limit is usually 1024 and the hard limit is usually higher (depends on the system). If the hard limit of the ANTA process is still lower than the number of selected tests in ANTA, the ANTA process may request to the operating system too many file descriptors and get an error, a WARNING is displayed at startup if this is the case.
-#### How can I resolve this error?
+ ### Solution
-1. _Workaround_: Downgrade `urllib3`
+ One solution could be to raise the hard limit for the user starting the ANTA process.
+ You can get the current hard limit for a user using the command `ulimit -n -H` while logged in.
+ Create the file `/etc/security/limits.d/10-anta.conf` with the following content:
+ ```
+ <user> hard nofile <value>
+ ```
+ The `user` is the one with which the ANTA process is started.
+ The `value` is the new hard limit. The maximum value depends on the system. A hard limit of 16384 should be sufficient for ANTA to run in most high scale scenarios. After creating this file, log out the current session and log in again.
+
+
+## `Timeout` error in the logs
+???+ faq "`Timeout` error in the logs"
+
+ When running ANTA, you can receive `<Foo>Timeout` errors in the logs (could be ReadTimeout, WriteTimeout, ConnectTimeout or PoolTimeout). More details on the timeouts of the underlying library are available here: https://www.python-httpx.org/advanced/timeouts.
+
+ This might be due to the time the host on which ANTA is run takes to reach the target devices (for instance if going through firewalls, NATs, ...) or when a lot of tests are being run at the same time on a device (eAPI has a queue mechanism to avoid exhausting EOS resources because of a high number of simultaneous eAPI requests).
- If you need a quick fix, you can temporarily downgrade the `urllib3` package:
+ ### Solution
+
+ Use the `timeout` option. As an example for the `nrfu` command:
```bash
- pip3 uninstall urllib3
+ anta nrfu --enable --username username --password arista --inventory inventory.yml -c nrfu.yml --timeout 50 text
+ ```
+
+ The previous command set a couple of options for ANTA NRFU, one them being the `timeout` command, by default, when running ANTA from CLI, it is set to 30s.
+ The timeout is increased to 50s to allow ANTA to wait for API calls a little longer.
+
+## `ImportError` related to `urllib3`
+???+ faq "`ImportError` related to `urllib3` when running ANTA"
+
+
+ When running the `anta --help` command, some users might encounter the following error:
- pip3 install urllib3==1.26.15
+ ```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
```
-2. _Recommended_: Upgrade System or Libraries:
+ This error arises due to a compatibility issue between `urllib3` v2.0 and older versions of OpenSSL.
+
+ ### Solution
+
+ 1. _Workaround_: Downgrade `urllib3`
- 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.
+ If you need a quick fix, you can temporarily downgrade the `urllib3` package:
-## Why am I seeing `AttributeError: module 'lib' has no attribute 'OpenSSL_add_all_algorithms'` when running ANTA
+ ```bash
+ pip3 uninstall urllib3
-When running the `anta` commands after installation, some users might encounter the following error:
+ pip3 install urllib3==1.26.15
+ ```
-```bash
-AttributeError: module 'lib' has no attribute 'OpenSSL_add_all_algorithms'
-```
+ 2. _Recommended_: Upgrade System or Libraries:
-The error is a result of incompatibility between `cryptography` and `pyopenssl` when installing `asyncssh` which is a requirement of ANTA.
+ 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.
-#### How can I resolve this error?
+##`AttributeError: module 'lib' has no attribute 'OpenSSL_add_all_algorithms'`
+???+ faq "`AttributeError: module 'lib' has no attribute 'OpenSSL_add_all_algorithms'` when running ANTA"
-1. Upgrade `pyopenssl`
+
+ When running the `anta` commands after installation, some users might encounter the following error:
```bash
- pip install -U pyopenssl>22.0
+ 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.
+
+ ### Solution
+
+ 1. Upgrade `pyopenssl`
+
+ ```bash
+ pip install -U pyopenssl>22.0
+ ```
+
## `__NSCFConstantString initialize` error on OSX
+???+ faq "`__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?
+ 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
-1. Set the following environment variable
+ ### Solution
- ```bash
- export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
- ```
+ 1. Set the following environment variable
+
+ ```bash
+ export OBJC_DISABLE_INITIALIZE_FORK_SAFETY=YES
+ ```
-## Still facing issues?
+# 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).
+If you've tried the above solutions and continue to experience problems, please follow the [troubleshooting](troubleshooting.md) instructions and report the issue in our [GitHub repository](https://github.com/arista-netdevops-community/anta).
diff --git a/docs/getting-started.md b/docs/getting-started.md
index fd147e7..4386485 100644
--- a/docs/getting-started.md
+++ b/docs/getting-started.md
@@ -10,13 +10,13 @@ This section shows how to use ANTA with basic configuration. All examples are ba
## Installation
-The easiest way to intall ANTA package is to run Python (`>=3.8`) and its pip package to install:
+The easiest way to install ANTA package is to run Python (`>=3.9`) 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.
+For more details about how to install package, please see the [requirements and installation](./requirements-and-installation.md) section.
## Configure Arista EOS devices
@@ -126,54 +126,11 @@ ANTA comes with a generic CLI entrypoint to run tests in your network. It requir
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
+--8<-- "anta_nrfu_help.txt"
```
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
diff --git a/docs/imgs/animated-svg.md b/docs/imgs/animated-svg.md
deleted file mode 100644
index 6a27a50..0000000
--- a/docs/imgs/animated-svg.md
+++ /dev/null
@@ -1,8 +0,0 @@
-<!--
- ~ 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`
diff --git a/docs/imgs/anta-nrfu.svg b/docs/imgs/anta-nrfu.svg
index c01eabb..c9ed61b 100644
--- a/docs/imgs/anta-nrfu.svg
+++ b/docs/imgs/anta-nrfu.svg
@@ -1 +1 @@
-<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1250" height="277.1"><rect width="1250" height="277.1" rx="5" ry="5" class="a"/><svg y="0%" x="0%"><circle cx="20" cy="20" r="6" fill="#ff5f58"/><circle cx="40" cy="20" r="6" fill="#ffbd2e"/><circle cx="60" cy="20" r="6" fill="#18c132"/></svg><svg height="217.1" viewBox="0 0 121 21.71" width="1210" x="15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="50"><style>@keyframes q{0%{transform:translateX(0)}2.2%{transform:translateX(-121px)}11.3%{transform:translateX(-242px)}13.7%{transform:translateX(-363px)}15.8%{transform:translateX(-484px)}17.9%{transform:translateX(-605px)}19.9%{transform:translateX(-726px)}22.2%{transform:translateX(-847px)}23.9%{transform:translateX(-968px)}26.1%{transform:translateX(-1089px)}28.3%{transform:translateX(-1210px)}29.4%{transform:translateX(-1331px)}32.1%{transform:translateX(-1452px)}34%{transform:translateX(-1573px)}36.6%{transform:translateX(-1694px)}38.3%{transform:translateX(-1815px)}40%{transform:translateX(-1936px)}45%{transform:translateX(-2057px)}48.5%{transform:translateX(-2299px)}49.1%{transform:translateX(-2541px)}49.9%{transform:translateX(-2662px)}51.1%{transform:translateX(-2783px)}52.4%{transform:translateX(-2904px)}53.6%{transform:translateX(-3025px)}54.9%{transform:translateX(-3146px)}56.1%{transform:translateX(-3267px)}57.4%{transform:translateX(-3388px)}59%{transform:translateX(-3509px)}60.3%{transform:translateX(-3630px)}61.5%{transform:translateX(-3751px)}62.8%{transform:translateX(-3872px)}64%{transform:translateX(-3993px)}65.2%{transform:translateX(-4114px)}66.5%{transform:translateX(-4235px)}67.7%{transform:translateX(-4356px)}68.9%{transform:translateX(-4477px)}70.2%{transform:translateX(-4598px)}71.4%{transform:translateX(-4719px)}72.6%{transform:translateX(-4840px)}73.9%{transform:translateX(-4961px)}75.1%{transform:translateX(-5082px)}76.3%{transform:translateX(-5203px)}77.6%{transform:translateX(-5324px)}78.8%{transform:translateX(-5445px)}80%{transform:translateX(-5566px)}81.3%{transform:translateX(-5687px)}82.5%{transform:translateX(-5808px)}83.7%{transform:translateX(-5929px)}85%{transform:translateX(-6050px)}86.2%{transform:translateX(-6171px)}87.4%{transform:translateX(-6292px)}88.7%{transform:translateX(-6413px)}89.9%{transform:translateX(-6534px)}91.1%{transform:translateX(-6655px)}92.3%{transform:translateX(-6776px)}93.6%{transform:translateX(-6897px)}94.8%{transform:translateX(-7018px)}96%{transform:translateX(-7139px)}97.3%{transform:translateX(-7260px)}98.5%{transform:translateX(-7381px)}99.1%{transform:translateX(-7502px)}to{transform:translateX(-7623px)}}.a{fill:#282d35}.f{fill:#b9c0cb;white-space:pre}.g,.h,.i,.j,.k,.m{fill:#66c2cd;white-space:pre}.h,.i,.j,.k,.m{fill:#a8cc8c}.i,.j,.k,.m{fill:#d290e4}.j,.k,.m{fill:#3a3a3a}.k,.m{fill:#dbab79}.m{fill:#ff005f}</style><g font-family="Monaco,Consolas,Menlo,'Bitstream Vera Sans Mono','Powerline Symbols',monospace" font-size="1.67"><defs><symbol id="1"><text y="1.67" class="f">❯</text></symbol><symbol id="2"><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text></symbol><symbol id="3"><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text></symbol><symbol id="4"><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">table</text></symbol><symbol id="5"><text y="1.67" class="g">╭──────────────────────</text><text x="24.048" y="1.67" class="h">Settings</text><text x="33.066" y="1.67" class="g">──────────────────────╮</text></symbol><symbol id="6"><text y="1.67" class="g">│</text><text x="2.004" y="1.67" class="g">Running</text><text x="10.02" y="1.67" class="g">ANTA</text><text x="15.03" y="1.67" class="g">tests:</text><text x="55.11" y="1.67" class="g">│</text></symbol><symbol id="7"><text y="1.67" class="g">│</text><text x="2.004" y="1.67" class="g">-</text><text x="4.008" y="1.67" class="g">ANTA</text><text x="9.018" y="1.67" class="g">Inventory</text><text x="19.038" y="1.67" class="g">contains</text><text x="28.056" y="1.67" class="g">6</text><text x="30.06" y="1.67" class="g">devices</text><text x="38.076" y="1.67" class="g">(AsyncEOSDevice)</text><text x="55.11" y="1.67" class="g">│</text></symbol><symbol id="8"><text y="1.67" class="g">│</text><text x="2.004" y="1.67" class="g">-</text><text x="4.008" y="1.67" class="g">Tests</text><text x="10.02" y="1.67" class="g">catalog</text><text x="18.036" y="1.67" class="g">contains</text><text x="27.054" y="1.67" class="g">89</text><text x="30.06" y="1.67" class="g">tests</text><text x="55.11" y="1.67" class="g">│</text></symbol><symbol id="9"><text y="1.67" class="g">╰──────────────────────────────────────────────────────╯</text></symbol><symbol id="10"><text y="1.67" class="h">(</text><text x="6.012" y="1.67" class="h">🐜)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="35.07" y="1.67" class="i">0%</text><text x="38.076" y="1.67" class="j">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="96.192" y="1.67" class="h">0/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:00</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">-:--:--</text></symbol><symbol id="11"><text y="1.67" class="g">[11:29:47]</text><text x="11.022" y="1.67" style="white-space:pre" fill="#71bef2">INFO</text><text x="20.04" y="1.67" class="f">Running</text><text x="28.056" y="1.67" class="f">ANTA</text><text x="33.066" y="1.67" class="f">tests</text><text x="38.076" y="1.67" class="k">...</text><text x="109.218" y="1.67" class="f">runner.py:71</text></symbol><symbol id="12"><text y="1.67" class="h">(</text><text x="5.01" y="1.67" class="h">🐜</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">15%</text><text x="38.076" y="1.67" class="m">━━━━━━━━</text><text x="46.092" y="1.67" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="1.67" class="h">78/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:00</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="13"><text y="1.67" class="h">(</text><text x="3.006" y="1.67" class="h">🐜</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">15%</text><text x="38.076" y="1.67" class="m">━━━━━━━━</text><text x="46.092" y="1.67" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="1.67" class="h">78/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:00</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="14"><text y="1.67" class="h">(</text><text x="2.004" y="1.67" class="h">🐌</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:02</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="15"><text y="1.67" class="h">(</text><text x="4.008" y="1.67" class="h">🐌</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:03</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="16"><text y="1.67" class="h">(</text><text x="6.012" y="1.67" class="h">🐌)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:03</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="17"><text y="1.67" class="h">(</text><text x="5.01" y="1.67" class="h">🐜</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:03</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="18"><text x="2.004" y="1.67" class="f">•</text><text x="4.008" y="1.67" class="f">Running</text><text x="12.024" y="1.67" class="f">NRFU</text><text x="17.034" y="1.67" class="f">Tests...</text><text x="25.05" y="1.67" class="i">100%</text><text x="30.06" y="1.67" style="white-space:pre" fill="#5faf00">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="1.67" class="h">534/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:04</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:00</text></symbol><symbol id="a"><path fill="transparent" d="M0 0h121v11H0z"/></symbol><symbol id="b"><path fill="#6f7683" d="M0 0h1.102v2.171H0z"/></symbol></defs><path class="a" d="M0 0h121v21.71H0z"/><g style="animation-duration:8.22014s;animation-iteration-count:infinite;animation-name:q;animation-timing-function:steps(1,end)"><svg width="7744"><svg><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="121"><use xlink:href="#a"/><use xlink:href="#b" x="1.996"/><use xlink:href="#1"/></svg><svg x="242"><use xlink:href="#a"/><use xlink:href="#b" x="2.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">a</text></svg><svg x="363"><use xlink:href="#a"/><use xlink:href="#b" x="3.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">an</text></svg><svg x="484"><use xlink:href="#a"/><use xlink:href="#b" x="4.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">ant</text></svg><svg x="605"><use xlink:href="#a"/><use xlink:href="#b" x="5.996"/><use xlink:href="#2"/></svg><svg x="726"><use xlink:href="#a"/><use xlink:href="#b" x="6.996"/><use xlink:href="#2"/></svg><svg x="847"><use xlink:href="#a"/><use xlink:href="#b" x="7.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">n</text></svg><svg x="968"><use xlink:href="#a"/><use xlink:href="#b" x="8.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nr</text></svg><svg x="1089"><use xlink:href="#a"/><use xlink:href="#b" x="9.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrf</text></svg><svg x="1210"><use xlink:href="#a"/><use xlink:href="#b" x="10.996"/><use xlink:href="#3"/></svg><svg x="1331"><use xlink:href="#a"/><use xlink:href="#b" x="11.996"/><use xlink:href="#3"/></svg><svg x="1452"><use xlink:href="#a"/><use xlink:href="#b" x="12.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">t</text></svg><svg x="1573"><use xlink:href="#a"/><use xlink:href="#b" x="13.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">ta</text></svg><svg x="1694"><use xlink:href="#a"/><use xlink:href="#b" x="14.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">tab</text></svg><svg x="1815"><use xlink:href="#a"/><use xlink:href="#b" x="15.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">tabl</text></svg><svg x="1936"><use xlink:href="#a"/><use xlink:href="#b" x="16.996"/><use xlink:href="#4"/></svg><svg x="2057"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="2.146"/><use xlink:href="#4"/></svg><svg x="2178"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="13.001"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/></svg><svg x="2299"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/></svg><svg x="2420"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#10" y="13.026"/></svg><svg x="2541"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#10" y="15.197"/></svg><svg x="2662"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="2783"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#12" y="15.197"/></svg><svg x="2904"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#12" y="15.197"/></svg><svg x="3025"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3146"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#13" y="15.197"/></svg><svg x="3267"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#13" y="15.197"/></svg><svg x="3388"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3509"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3630"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">18%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━</text><text x="48.096" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">98/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:05</text></svg><svg x="3751"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">35%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━</text><text x="57.114" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">189/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:02</text></svg><svg x="3872"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">55%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="68.136" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">293/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3993"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">58%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="70.14" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">311/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4114"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">63%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="73.146" y="16.867" class="j">━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">335/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4235"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">67%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="75.15" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">360/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4356"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">71%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="77.154" y="16.867" class="j">━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">378/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4477"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">72%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="77.154" y="16.867" class="j">╺━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">383/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4598"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐌)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">72%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="78.156" y="16.867" class="j">━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">385/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4719"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">76%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="80.16" y="16.867" class="j">━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">407/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4840"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">81%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="83.166" y="16.867" class="j">━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">433/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4961"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">84%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="84.168" y="16.867" class="j">╺━━━━━━━━</text><text x="94.188" y="16.867" class="h">447/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5082"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">85%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="85.17" y="16.867" class="j">━━━━━━━━</text><text x="94.188" y="16.867" class="h">456/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5203"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">87%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="86.172" y="16.867" class="j">╺━━━━━━</text><text x="94.188" y="16.867" class="h">467/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5324"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">89%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="87.174" y="16.867" class="j">╺━━━━━</text><text x="94.188" y="16.867" class="h">476/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5445"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">91%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="88.176" y="16.867" class="j">╺━━━━</text><text x="94.188" y="16.867" class="h">486/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5566"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">95%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="90.18" y="16.867" class="j">╺━━</text><text x="94.188" y="16.867" class="h">505/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5687"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">98%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="92.184" y="16.867" class="j">━</text><text x="94.188" y="16.867" class="h">521/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5808"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="92.184" y="16.867" class="j">╺</text><text x="94.188" y="16.867" class="h">528/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5929"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#14" y="15.197"/></svg><svg x="6050"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#14" y="15.197"/></svg><svg x="6171"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="6292"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#15" y="15.197"/></svg><svg x="6413"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#15" y="15.197"/></svg><svg x="6534"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="6655"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#16" y="15.197"/></svg><svg x="6776"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#16" y="15.197"/></svg><svg x="6897"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="7018"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#17" y="15.197"/></svg><svg x="7139"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#17" y="15.197"/></svg><svg x="7260"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="7381"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="33.066" y="16.867" class="i">100%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">533/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:04</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="7502"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="17.343"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#18" y="15.197"/></svg><svg x="7623"><use xlink:href="#a"/><use xlink:href="#b" x="1.996" y="17.343"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#18" y="15.197"/><use xlink:href="#1" y="17.368"/></svg></svg></g></g></svg></svg>
+<svg xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" width="1250" height="277.1"><rect width="1250" height="277.1" rx="5" ry="5" class="a"/><svg y="0%" x="0%"><circle cx="20" cy="20" r="6" fill="#ff5f58"/><circle cx="40" cy="20" r="6" fill="#ffbd2e"/><circle cx="60" cy="20" r="6" fill="#18c132"/></svg><svg height="217.1" viewBox="0 0 121 21.71" width="1210" x="15" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" y="50"><style>@keyframes q{0%{transform:translateX(0)}2.2%{transform:translateX(-121px)}11.3%{transform:translateX(-242px)}13.7%{transform:translateX(-363px)}15.8%{transform:translateX(-484px)}17.9%{transform:translateX(-605px)}19.9%{transform:translateX(-726px)}22.2%{transform:translateX(-847px)}23.9%{transform:translateX(-968px)}26.1%{transform:translateX(-1089px)}28.3%{transform:translateX(-1210px)}29.4%{transform:translateX(-1331px)}32.1%{transform:translateX(-1452px)}34%{transform:translateX(-1573px)}36.6%{transform:translateX(-1694px)}38.3%{transform:translateX(-1815px)}40%{transform:translateX(-1936px)}45%{transform:translateX(-2057px)}48.5%{transform:translateX(-2299px)}49.1%{transform:translateX(-2541px)}49.9%{transform:translateX(-2662px)}51.1%{transform:translateX(-2783px)}52.4%{transform:translateX(-2904px)}53.6%{transform:translateX(-3025px)}54.9%{transform:translateX(-3146px)}56.1%{transform:translateX(-3267px)}57.4%{transform:translateX(-3388px)}59%{transform:translateX(-3509px)}60.3%{transform:translateX(-3630px)}61.5%{transform:translateX(-3751px)}62.8%{transform:translateX(-3872px)}64%{transform:translateX(-3993px)}65.2%{transform:translateX(-4114px)}66.5%{transform:translateX(-4235px)}67.7%{transform:translateX(-4356px)}68.9%{transform:translateX(-4477px)}70.2%{transform:translateX(-4598px)}71.4%{transform:translateX(-4719px)}72.6%{transform:translateX(-4840px)}73.9%{transform:translateX(-4961px)}75.1%{transform:translateX(-5082px)}76.3%{transform:translateX(-5203px)}77.6%{transform:translateX(-5324px)}78.8%{transform:translateX(-5445px)}80%{transform:translateX(-5566px)}81.3%{transform:translateX(-5687px)}82.5%{transform:translateX(-5808px)}83.7%{transform:translateX(-5929px)}85%{transform:translateX(-6050px)}86.2%{transform:translateX(-6171px)}87.4%{transform:translateX(-6292px)}88.7%{transform:translateX(-6413px)}89.9%{transform:translateX(-6534px)}91.1%{transform:translateX(-6655px)}92.3%{transform:translateX(-6776px)}93.6%{transform:translateX(-6897px)}94.8%{transform:translateX(-7018px)}96%{transform:translateX(-7139px)}97.3%{transform:translateX(-7260px)}98.5%{transform:translateX(-7381px)}99.1%{transform:translateX(-7502px)}to{transform:translateX(-7623px)}}.a{fill:#282d35}.f{fill:#b9c0cb;white-space:pre}.g,.h,.i,.j,.k,.m{fill:#66c2cd;white-space:pre}.h,.i,.j,.k,.m{fill:#a8cc8c}.i,.j,.k,.m{fill:#d290e4}.j,.k,.m{fill:#3a3a3a}.k,.m{fill:#dbab79}.m{fill:#ff005f}</style><g font-family="Monaco,Consolas,Menlo,'Bitstream Vera Sans Mono','Powerline Symbols',monospace" font-size="1.67"><defs><symbol id="1"><text y="1.67" class="f">❯</text></symbol><symbol id="2"><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text></symbol><symbol id="3"><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text></symbol><symbol id="4"><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">table</text></symbol><symbol id="5"><text y="1.67" class="g">╭──────────────────────</text><text x="24.048" y="1.67" class="h">Settings</text><text x="33.066" y="1.67" class="g">──────────────────────╮</text></symbol><symbol id="6"><text y="1.67" class="g">│</text><text x="2.004" y="1.67" class="g">Running</text><text x="10.02" y="1.67" class="g">ANTA</text><text x="15.03" y="1.67" class="g">tests:</text><text x="55.11" y="1.67" class="g">│</text></symbol><symbol id="7"><text y="1.67" class="g">│</text><text x="2.004" y="1.67" class="g">-</text><text x="4.008" y="1.67" class="g">ANTA</text><text x="9.018" y="1.67" class="g">Inventory</text><text x="19.038" y="1.67" class="g">contains</text><text x="28.056" y="1.67" class="g">6</text><text x="30.06" y="1.67" class="g">devices</text><text x="38.076" y="1.67" class="g">(AsyncEOSDevice)</text><text x="55.11" y="1.67" class="g">│</text></symbol><symbol id="8"><text y="1.67" class="g">│</text><text x="2.004" y="1.67" class="g">-</text><text x="4.008" y="1.67" class="g">Tests</text><text x="10.02" y="1.67" class="g">catalog</text><text x="18.036" y="1.67" class="g">contains</text><text x="27.054" y="1.67" class="g">89</text><text x="30.06" y="1.67" class="g">tests</text><text x="55.11" y="1.67" class="g">│</text></symbol><symbol id="9"><text y="1.67" class="g">╰──────────────────────────────────────────────────────╯</text></symbol><symbol id="10"><text y="1.67" class="h">(</text><text x="6.012" y="1.67" class="h">🐜)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="35.07" y="1.67" class="i">0%</text><text x="38.076" y="1.67" class="j">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="96.192" y="1.67" class="h">0/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:00</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">-:--:--</text></symbol><symbol id="11"><text y="1.67" class="g">[11:29:47]</text><text x="11.022" y="1.67" style="white-space:pre" fill="#71bef2">INFO</text><text x="20.04" y="1.67" class="f">Running</text><text x="28.056" y="1.67" class="f">ANTA</text><text x="33.066" y="1.67" class="f">tests</text><text x="38.076" y="1.67" class="k">...</text><text x="109.218" y="1.67" class="f">runner.py:71</text></symbol><symbol id="12"><text y="1.67" class="h">(</text><text x="5.01" y="1.67" class="h">🐜</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">15%</text><text x="38.076" y="1.67" class="m">━━━━━━━━</text><text x="46.092" y="1.67" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="1.67" class="h">78/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:00</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="13"><text y="1.67" class="h">(</text><text x="3.006" y="1.67" class="h">🐜</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">15%</text><text x="38.076" y="1.67" class="m">━━━━━━━━</text><text x="46.092" y="1.67" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="1.67" class="h">78/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:00</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="14"><text y="1.67" class="h">(</text><text x="2.004" y="1.67" class="h">🐌</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:02</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="15"><text y="1.67" class="h">(</text><text x="4.008" y="1.67" class="h">🐌</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:03</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="16"><text y="1.67" class="h">(</text><text x="6.012" y="1.67" class="h">🐌)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:03</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="17"><text y="1.67" class="h">(</text><text x="5.01" y="1.67" class="h">🐜</text><text x="8.016" y="1.67" class="h">)</text><text x="10.02" y="1.67" class="f">•</text><text x="12.024" y="1.67" class="f">Running</text><text x="20.04" y="1.67" class="f">NRFU</text><text x="25.05" y="1.67" class="f">Tests...</text><text x="34.068" y="1.67" class="i">99%</text><text x="38.076" y="1.67" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="1.67" class="h">531/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:03</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:01</text></symbol><symbol id="18"><text x="2.004" y="1.67" class="f">•</text><text x="4.008" y="1.67" class="f">Running</text><text x="12.024" y="1.67" class="f">NRFU</text><text x="17.034" y="1.67" class="f">Tests...</text><text x="25.05" y="1.67" class="i">100%</text><text x="30.06" y="1.67" style="white-space:pre" fill="#5faf00">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="1.67" class="h">534/534</text><text x="102.204" y="1.67" class="f">•</text><text x="104.208" y="1.67" class="k">0:00:04</text><text x="112.224" y="1.67" class="f">•</text><text x="114.228" y="1.67" class="g">0:00:00</text></symbol><symbol id="a"><path fill="transparent" d="M0 0h121v11H0z"/></symbol><symbol id="b"><path fill="#6f7683" d="M0 0h1.102v2.171H0z"/></symbol></defs><path class="a" d="M0 0h121v21.71H0z"/><g style="animation-duration:8.22014s;animation-iteration-count:infinite;animation-name:q;animation-timing-function:steps(1,end)"><svg width="7744"><svg><use xlink:href="#a"/><use xlink:href="#b" x="-.004"/></svg><svg x="121"><use xlink:href="#a"/><use xlink:href="#b" x="1.996"/><use xlink:href="#1"/></svg><svg x="242"><use xlink:href="#a"/><use xlink:href="#b" x="2.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">a</text></svg><svg x="363"><use xlink:href="#a"/><use xlink:href="#b" x="3.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">an</text></svg><svg x="484"><use xlink:href="#a"/><use xlink:href="#b" x="4.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">ant</text></svg><svg x="605"><use xlink:href="#a"/><use xlink:href="#b" x="5.996"/><use xlink:href="#2"/></svg><svg x="726"><use xlink:href="#a"/><use xlink:href="#b" x="6.996"/><use xlink:href="#2"/></svg><svg x="847"><use xlink:href="#a"/><use xlink:href="#b" x="7.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">n</text></svg><svg x="968"><use xlink:href="#a"/><use xlink:href="#b" x="8.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nr</text></svg><svg x="1089"><use xlink:href="#a"/><use xlink:href="#b" x="9.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrf</text></svg><svg x="1210"><use xlink:href="#a"/><use xlink:href="#b" x="10.996"/><use xlink:href="#3"/></svg><svg x="1331"><use xlink:href="#a"/><use xlink:href="#b" x="11.996"/><use xlink:href="#3"/></svg><svg x="1452"><use xlink:href="#a"/><use xlink:href="#b" x="12.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">t</text></svg><svg x="1573"><use xlink:href="#a"/><use xlink:href="#b" x="13.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">ta</text></svg><svg x="1694"><use xlink:href="#a"/><use xlink:href="#b" x="14.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">tab</text></svg><svg x="1815"><use xlink:href="#a"/><use xlink:href="#b" x="15.996"/><text y="1.67" class="f">❯</text><text x="2.004" y="1.67" class="f">anta</text><text x="7.014" y="1.67" class="f">nrfu</text><text x="12.024" y="1.67" class="f">table</text></svg><svg x="1936"><use xlink:href="#a"/><use xlink:href="#b" x="16.996"/><use xlink:href="#4"/></svg><svg x="2057"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="2.146"/><use xlink:href="#4"/></svg><svg x="2178"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="13.001"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/></svg><svg x="2299"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/></svg><svg x="2420"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#10" y="13.026"/></svg><svg x="2541"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#10" y="15.197"/></svg><svg x="2662"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="2783"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#12" y="15.197"/></svg><svg x="2904"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#12" y="15.197"/></svg><svg x="3025"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3146"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#13" y="15.197"/></svg><svg x="3267"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#13" y="15.197"/></svg><svg x="3388"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3509"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">15%</text><text x="38.076" y="16.867" class="m">━━━━━━━━</text><text x="46.092" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">78/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3630"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">18%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━</text><text x="48.096" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="95.19" y="16.867" class="h">98/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:00</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:05</text></svg><svg x="3751"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">35%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━</text><text x="57.114" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">189/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:02</text></svg><svg x="3872"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">55%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="68.136" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">293/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="3993"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">58%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="70.14" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">311/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4114"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">63%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="73.146" y="16.867" class="j">━━━━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">335/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4235"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">67%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="75.15" y="16.867" class="j">╺━━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">360/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4356"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">71%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="77.154" y="16.867" class="j">━━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">378/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4477"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">72%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="77.154" y="16.867" class="j">╺━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">383/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4598"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐌)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">72%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="78.156" y="16.867" class="j">━━━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">385/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4719"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">76%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="80.16" y="16.867" class="j">━━━━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">407/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4840"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">81%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="83.166" y="16.867" class="j">━━━━━━━━━━</text><text x="94.188" y="16.867" class="h">433/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:01</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="4961"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">84%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="84.168" y="16.867" class="j">╺━━━━━━━━</text><text x="94.188" y="16.867" class="h">447/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5082"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">85%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="85.17" y="16.867" class="j">━━━━━━━━</text><text x="94.188" y="16.867" class="h">456/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5203"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">87%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="86.172" y="16.867" class="j">╺━━━━━━</text><text x="94.188" y="16.867" class="h">467/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5324"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">89%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="87.174" y="16.867" class="j">╺━━━━━</text><text x="94.188" y="16.867" class="h">476/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5445"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">91%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="88.176" y="16.867" class="j">╺━━━━</text><text x="94.188" y="16.867" class="h">486/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5566"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="2.004" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">95%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="90.18" y="16.867" class="j">╺━━</text><text x="94.188" y="16.867" class="h">505/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5687"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">98%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="92.184" y="16.867" class="j">━</text><text x="94.188" y="16.867" class="h">521/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5808"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━</text><text x="92.184" y="16.867" class="j">╺</text><text x="94.188" y="16.867" class="h">528/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:02</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="5929"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#14" y="15.197"/></svg><svg x="6050"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#14" y="15.197"/></svg><svg x="6171"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="6292"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#15" y="15.197"/></svg><svg x="6413"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#15" y="15.197"/></svg><svg x="6534"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="5.01" y="16.867" class="h">🐌</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="6655"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#16" y="15.197"/></svg><svg x="6776"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#16" y="15.197"/></svg><svg x="6897"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="6.012" y="16.867" class="h">🐜)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="7018"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#17" y="15.197"/></svg><svg x="7139"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#17" y="15.197"/></svg><svg x="7260"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="4.008" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="34.068" y="16.867" class="i">99%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">531/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:03</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="7381"><use xlink:href="#a"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><text y="16.867" class="h">(</text><text x="3.006" y="16.867" class="h">🐜</text><text x="8.016" y="16.867" class="h">)</text><text x="10.02" y="16.867" class="f">•</text><text x="12.024" y="16.867" class="f">Running</text><text x="20.04" y="16.867" class="f">NRFU</text><text x="25.05" y="16.867" class="f">Tests...</text><text x="33.066" y="16.867" class="i">100%</text><text x="38.076" y="16.867" class="m">━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━╸</text><text x="94.188" y="16.867" class="h">533/534</text><text x="102.204" y="16.867" class="f">•</text><text x="104.208" y="16.867" class="k">0:00:04</text><text x="112.224" y="16.867" class="f">•</text><text x="114.228" y="16.867" class="g">0:00:01</text></svg><svg x="7502"><use xlink:href="#a"/><use xlink:href="#b" x="-.004" y="17.343"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#18" y="15.197"/></svg><svg x="7623"><use xlink:href="#a"/><use xlink:href="#b" x="1.996" y="17.343"/><use xlink:href="#4"/><use xlink:href="#5" y="2.171"/><use xlink:href="#6" y="4.342"/><use xlink:href="#7" y="6.513"/><use xlink:href="#8" y="8.684"/><use xlink:href="#9" y="10.855"/><use xlink:href="#11" y="13.026"/><use xlink:href="#18" y="15.197"/><use xlink:href="#1" y="17.368"/></svg></svg></g></g></svg></svg>
diff --git a/docs/overrides/partials/content.html b/docs/overrides/partials/content.html
new file mode 100644
index 0000000..1bda13b
--- /dev/null
+++ b/docs/overrides/partials/content.html
@@ -0,0 +1,18 @@
+{#-
+ This file was automatically generated - do not edit
+-#}
+{% if "material/tags" in config.plugins and tags %}
+ {% include "partials/tags.html" %}
+{% endif %}
+{% include "partials/actions.html" %}
+{% if "\x3ch1" not in page.content %}
+ {% if page.meta and page.meta.anta_title %}
+ <h1>{{ page.meta.anta_title | d(config.site_name, true)}}</h1>
+ {% else %}
+ <h1>{{ page.title | d(config.site_name, true)}}</h1>
+ {% endif %}
+{% endif %}
+{{ page.content }}
+{% include "partials/source-file.html" %}
+{% include "partials/feedback.html" %}
+{% include "partials/comments.html" %}
diff --git a/docs/overrides/partials/toc-item.html b/docs/overrides/partials/toc-item.html
new file mode 100644
index 0000000..b5cd840
--- /dev/null
+++ b/docs/overrides/partials/toc-item.html
@@ -0,0 +1,21 @@
+<!-- Courtesy of https://github.com/squidfunk/mkdocs-material/issues/4827#issuecomment-1869812019 -->
+<li class="md-nav__item">
+ <a href="{{ toc_item.url }}" class="md-nav__link">
+ <span class="md-ellipsis">
+ {{ toc_item.title }}
+ </span>
+ </a>
+
+ <!-- Table of contents list -->
+ {% if toc_item.children %}
+ <nav class="md-nav" aria-label="{{ toc_item.title | striptags }}">
+ <ul class="md-nav__list">
+ {% for toc_item in toc_item.children %}
+ {% if not page.meta.toc_depth or toc_item.level <= page.meta.toc_depth %}
+ {% include "partials/toc-item.html" %}
+ {% endif %}
+ {% endfor %}
+ </ul>
+ </nav>
+ {% endif %}
+ </li>
diff --git a/docs/requirements-and-installation.md b/docs/requirements-and-installation.md
index 9885cbe..b3107a6 100644
--- a/docs/requirements-and-installation.md
+++ b/docs/requirements-and-installation.md
@@ -8,11 +8,11 @@
## Python version
-Python 3 (`>=3.8`) is required:
+Python 3 (`>=3.9`) is required:
```bash
python --version
-Python 3.9.9
+Python 3.11.8
```
## Install ANTA package
@@ -61,12 +61,12 @@ which anta
```bash
# Check ANTA version
anta --version
-anta, version v0.13.0
+anta, version v0.14.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):
+To get ANTA working, the targeted Arista EOS devices must have the following configuration (assuming you connect to the device using Management interface in MGMT VRF):
```eos
configure
@@ -95,7 +95,7 @@ management api http-commands
end
```
-Now the swicth accepts on port 443 in the MGMT VRF HTTPS requests containing a list of CLI commands.
+Now the switch accepts on port 443 in the MGMT VRF HTTPS requests containing a list of CLI commands.
Run these EOS commands to verify:
diff --git a/docs/scripts/__init__.py b/docs/scripts/__init__.py
new file mode 100644
index 0000000..c6adabb
--- /dev/null
+++ b/docs/scripts/__init__.py
@@ -0,0 +1,4 @@
+# Copyright (c) 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.
+"""Scripts for ANTA documentation."""
diff --git a/docs/scripts/generate_svg.py b/docs/scripts/generate_svg.py
index 19177db..426a785 100644
--- a/docs/scripts/generate_svg.py
+++ b/docs/scripts/generate_svg.py
@@ -1,13 +1,16 @@
# 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
+"""A script to generate svg files from anta command.
usage:
python generate_svg.py anta ...
"""
+# This script is not a package
+# ruff: noqa: INP001
+# This script contains print statements
+# ruff: noqa: T201
import io
import os
@@ -27,8 +30,7 @@ OUTPUT_DIR = pathlib.Path(__file__).parent.parent / "imgs"
def custom_progress_bar() -> None:
- """
- Set the console of progress_bar to main anta console
+ """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
@@ -76,17 +78,15 @@ if __name__ == "__main__":
# 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()
+ # redirect potential progress bar output to console by patching
+ with redirect_stdout(io.StringIO()) as f, patch("anta.cli.nrfu.commands.anta_progress_bar", custom_progress_bar), 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"{'_'.join(x.replace('/', '_').replace('-', '_').replace('.', '_') for x in args)}.svg"
filename = f"{OUTPUT_DIR}/{filename}"
print(f"File saved at {filename}")
new_console.save_svg(filename, title=" ".join(args))
diff --git a/docs/snippets/anta_help.txt b/docs/snippets/anta_help.txt
index 0c3302a..7bc37ad 100644
--- a/docs/snippets/anta_help.txt
+++ b/docs/snippets/anta_help.txt
@@ -1,6 +1,6 @@
Usage: anta [OPTIONS] COMMAND [ARGS]...
- Arista Network Test Automation (ANTA) CLI
+ Arista Network Test Automation (ANTA) CLI.
Options:
--version Show the version and exit.
@@ -13,8 +13,8 @@ Options:
--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
+ 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 selected inventory devices.
diff --git a/docs/snippets/anta_nrfu_help.txt b/docs/snippets/anta_nrfu_help.txt
new file mode 100644
index 0000000..87e5195
--- /dev/null
+++ b/docs/snippets/anta_nrfu_help.txt
@@ -0,0 +1,51 @@
+Usage: anta nrfu [OPTIONS] COMMAND [ARGS]...
+
+ Run ANTA tests on selected 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 FLOAT Global API timeout. This value will be used
+ for all devices. [env var: ANTA_TIMEOUT;
+ default: 30.0]
+ --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]
+ --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]
+ -d, --device TEXT Run tests on a specific device. Can be
+ provided multiple times.
+ -t, --test TEXT Run a specific test. Can be provided
+ multiple times.
+ --ignore-status Exit code will always be 0. [env var:
+ ANTA_NRFU_IGNORE_STATUS]
+ --ignore-error Exit code will be 0 if all tests succeeded
+ or 1 if any test failed. [env var:
+ ANTA_NRFU_IGNORE_ERROR]
+ --hide [success|failure|error|skipped]
+ Group result by test or device.
+ --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.
diff --git a/docs/templates/python/material/anta_test.html b/docs/templates/python/material/anta_test.html
new file mode 100644
index 0000000..ade0ba6
--- /dev/null
+++ b/docs/templates/python/material/anta_test.html
@@ -0,0 +1,163 @@
+{% if obj.members %}
+ {{ log.debug("Rendering children of " + obj.path) }}
+
+ <div class="doc doc-children">
+
+ {% if root_members %}
+ {% set members_list = config.members %}
+ {% else %}
+ {% set members_list = none %}
+ {% endif %}
+
+ {% if config.group_by_category %}
+
+ {% with %}
+
+ {% if config.show_category_heading %}
+ {% set extra_level = 1 %}
+ {% else %}
+ {% set extra_level = 0 %}
+ {% endif %}
+
+ {% with attributes = obj.attributes|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if attributes %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-attributes") %}Attributes{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for attribute in attributes|order_members(config.members_order, members_list) %}
+ {% if members_list is not none or attribute.is_public(check_name=False) %}
+ {% include attribute|get_template with context %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+
+ {% with classes = obj.classes|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if classes %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-classes") %}Classes{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for class in classes|order_members(config.members_order, members_list) %}
+ {% if class.name == "Input" %}
+ {% filter heading(heading_level, id=html_id ~ "-attributes") %}Inputs{% endfilter %}
+ {% set root = False %}
+ {% set heading_level = heading_level + 1 %}
+ {% set old_obj = obj %}
+ {% set obj = class %}
+ {% include "attributes_table.html" with context %}
+ {% set obj = old_obj %}
+ {% else %}
+ {% if members_list is not none or class.is_public(check_name=False) %}
+ {% include class|get_template with context %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+
+ {% with functions = obj.functions|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if functions %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-functions") %}Functions{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for function in functions|order_members(config.members_order, members_list) %}
+ {% if not (obj.kind.value == "class" and function.name == "__init__" and config.merge_init_into_class) %}
+ {% if members_list is not none or function.is_public(check_name=False) %}
+ {% include function|get_template with context %}
+ {% endif %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+
+ {% if config.show_submodules %}
+ {% with modules = obj.modules|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% if modules %}
+ {% if config.show_category_heading %}
+ {% filter heading(heading_level, id=html_id ~ "-modules") %}Modules{% endfilter %}
+ {% endif %}
+ {% with heading_level = heading_level + extra_level %}
+ {% for module in modules|order_members(config.members_order.alphabetical, members_list) %}
+ {% if members_list is not none or module.is_public(check_name=False) %}
+ {% include module|get_template with context %}
+ {% endif %}
+ {% endfor %}
+ {% endwith %}
+ {% endif %}
+ {% endwith %}
+ {% endif %}
+
+ {% endwith %}
+
+ {% else %}
+
+ {% for child in obj.all_members
+ |filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=config.inherited_members,
+ keep_no_docstrings=config.show_if_no_docstring,
+ )
+ |order_members(config.members_order, members_list)
+ %}
+
+ {% if not (obj.is_class and child.name == "__init__" and config.merge_init_into_class) %}
+
+ {% if members_list is not none or child.is_public(check_name=False) %}
+ {% if child.is_attribute %}
+ {% with attribute = child %}
+ {% include attribute|get_template with context %}
+ {% endwith %}
+
+ {% elif child.is_class %}
+ {% with class = child %}
+ {% include class|get_template with context %}
+ {% endwith %}
+
+ {% elif child.is_function %}
+ {% with function = child %}
+ {% include function|get_template with context %}
+ {% endwith %}
+
+ {% elif child.is_module and config.show_submodules %}
+ {% with module = child %}
+ {% include module|get_template with context %}
+ {% endwith %}
+
+ {% endif %}
+ {% endif %}
+
+ {% endif %}
+
+ {% endfor %}
+
+ {% endif %}
+
+ </div>
+{% endif %}
diff --git a/docs/templates/python/material/attributes_table.html b/docs/templates/python/material/attributes_table.html
new file mode 100644
index 0000000..4997145
--- /dev/null
+++ b/docs/templates/python/material/attributes_table.html
@@ -0,0 +1,70 @@
+{% if obj.members %}
+ {{ log.debug("Rendering children of " + obj.path) }}
+
+ <div class="doc doc-children">
+ {# Notice inherited members false #}
+ {% with attributes = obj.attributes|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=false,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ <table>
+ <thead>
+ <tr>
+ <th>Name</th>
+ <th>Type</th>
+ <th>Description</th>
+ <th>Default</th>
+ </tr>
+ </thead>
+ <tbody>
+ {% for attribute in attributes %}
+ <tr>
+ <td><code>{{ attribute.name }}</code></td>
+ <td>
+ {% if attribute.annotation %}
+ {% with expression = attribute.annotation %}
+ <code>{% include "expression.html" with context %}</code>
+ {% endwith %}
+ {% endif %}
+ </td>
+ <td>
+ <div class="doc-md-description">
+ {{ attribute.docstring.value }}
+ </div>
+ </td>
+ <td>
+ {% if attribute.value %}
+ {% with expression = attribute.value %}
+ <code>{% include "expression.html" with context %}</code>
+ {% endwith %}
+ {% else %}
+ <em>-</em>
+ {% endif %}
+ </td>
+ </tr>
+ {% endfor %}
+ </tbody>
+ </table>
+ {%endwith %}
+ {% with classes = obj.classes|filter_objects(
+ filters=config.filters,
+ members_list=members_list,
+ inherited_members=false,
+ keep_no_docstrings=config.show_if_no_docstring,
+ ) %}
+ {% for class in classes %}
+ {% filter heading(heading_level, id=html_id ~ "-attributes") %}{{class.name}}{% endfilter %}
+ <div class="doc doc-children doc-contents">
+ {% set root = False %}
+ {% set heading_level = heading_level + 1 %}
+ {% set old_obj = obj %}
+ {% set obj = class %}
+ {% include "attributes_table.html" with context %}
+ {% set obj = old_obj %}
+ </div>
+ {% endfor %}
+ {%endwith %}
+ </div>
+{% endif %}
diff --git a/docs/templates/python/material/class.html b/docs/templates/python/material/class.html
new file mode 100644
index 0000000..940103b
--- /dev/null
+++ b/docs/templates/python/material/class.html
@@ -0,0 +1,35 @@
+{% extends "_base/class.html" %}
+{% set anta_test = namespace(found=false) %}
+{% for base in class.bases %}
+{% set basestr = base | string %}
+{% if "AntaTest" == basestr %}
+{% set anta_test.found = True %}
+{% endif %}
+{% endfor %}
+{% block children %}
+{% if anta_test.found %}
+ {% set root = False %}
+ {% set heading_level = heading_level + 1 %}
+ {% include "anta_test.html" with context %}
+ {# render source after children - TODO make add flag to respect disabling it.. though do we want to disable?#}
+ <details class="quote">
+ <summary>Source code in <code>
+ {%- if class.relative_filepath.is_absolute() -%}
+ {{ class.relative_package_filepath }}
+ {%- else -%}
+ {{ class.relative_filepath }}
+ {%- endif -%}
+ </code></summary>
+ {{ class.source|highlight(language="python", linestart=class.lineno, linenums=True) }}
+ </details>
+{% else %}
+ {{ super() }}
+{% endif %}
+{% endblock children %}
+
+{# Do not render source before children for AntaTest #}
+{% block source %}
+{% if not anta_test.found %}
+ {{ super() }}
+{% endif %}
+{% endblock source %}
diff --git a/docs/templates/python/material/docstring.html b/docs/templates/python/material/docstring.html
new file mode 100644
index 0000000..b12ae7e
--- /dev/null
+++ b/docs/templates/python/material/docstring.html
@@ -0,0 +1,36 @@
+{% if docstring_sections %}
+ {{ log.debug("Rendering docstring") }}
+ {% for section in docstring_sections %}
+ {% if config.show_docstring_description and section.kind.value == "text" %}
+ {% if not (config.anta_hide_test_module_description and module == obj) %}
+ {{ section.value|convert_markdown(heading_level, html_id) }}
+ {% endif %}
+ {% elif config.show_docstring_attributes and section.kind.value == "attributes" %}
+ {% include "docstring/attributes.html" with context %}
+ {% elif config.show_docstring_functions and section.kind.value == "functions" %}
+ {% include "docstring/functions.html" with context %}
+ {% elif config.show_docstring_classes and section.kind.value == "classes" %}
+ {% include "docstring/classes.html" with context %}
+ {% elif config.show_docstring_modules and section.kind.value == "modules" %}
+ {% include "docstring/modules.html" with context %}
+ {% elif config.show_docstring_parameters and section.kind.value == "parameters" %}
+ {% include "docstring/parameters.html" with context %}
+ {% elif config.show_docstring_other_parameters and section.kind.value == "other parameters" %}
+ {% include "docstring/other_parameters.html" with context %}
+ {% elif config.show_docstring_raises and section.kind.value == "raises" %}
+ {% include "docstring/raises.html" with context %}
+ {% elif config.show_docstring_warns and section.kind.value == "warns" %}
+ {% include "docstring/warns.html" with context %}
+ {% elif config.show_docstring_yields and section.kind.value == "yields" %}
+ {% include "docstring/yields.html" with context %}
+ {% elif config.show_docstring_receives and section.kind.value == "receives" %}
+ {% include "docstring/receives.html" with context %}
+ {% elif config.show_docstring_returns and section.kind.value == "returns" %}
+ {% include "docstring/returns.html" with context %}
+ {% elif config.show_docstring_examples and section.kind.value == "examples" %}
+ {% include "docstring/examples.html" with context %}
+ {% elif config.show_docstring_description and section.kind.value == "admonition" %}
+ {% include "docstring/admonition.html" with context %}
+ {% endif %}
+ {% endfor %}
+{% endif %}
diff --git a/docs/templates/python/material/docstring/examples.html b/docs/templates/python/material/docstring/examples.html
new file mode 100644
index 0000000..d8709c9
--- /dev/null
+++ b/docs/templates/python/material/docstring/examples.html
@@ -0,0 +1,14 @@
+{{ log.debug("Rendering examples section") }}
+
+{% import "language.html" as lang with context %}
+
+<details class="example" open>
+ <summary>{{ "Examples" | convert_markdown(heading_level +1, html_id, strip_paragraph=True) }}</summary>
+ {% for section_type, sub_section in section.value %}
+ {% if section_type.value == "text" %}
+ {{ sub_section|convert_markdown(heading_level, html_id) }}
+ {% elif section_type.value == "examples" %}
+ {{ sub_section|highlight(language="pycon", linenums=False) }}
+ {% endif %}
+ {% endfor %}
+</details>
diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md
new file mode 100644
index 0000000..596aad6
--- /dev/null
+++ b/docs/troubleshooting.md
@@ -0,0 +1,79 @@
+<!--
+ ~ Copyright (c) 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.
+ -->
+
+# Troubleshooting ANTA
+
+A couple of things to check when hitting an issue with ANTA:
+
+```mermaid
+flowchart LR
+ A>Hitting an issue with ANTA] --> B{Is my issue <br >listed in the FAQ?}
+ B -- Yes --> C{Does the FAQ solution<<br />works for me?}
+ C -- Yes --> V(((Victory)))
+ B -->|No| E{Is my problem<br />mentioned in one<<br />of the open issues?}
+ C -->|No| E
+ E -- Yes --> F{Has the issue been<br />fixed in a newer<br />release or in main?}
+ F -- Yes --> U[Upgrade]
+ E -- No ---> H((Follow the steps below<br />and open a Github issue))
+ U --> I{Did it fix<br /> your problem}
+ I -- Yes --> V
+ I -- No --> H
+ F -- No ----> G((Add a comment on the <br />issue indicating you<br >are hitting this and<br />describing your setup<br /> and adding your logs.))
+
+ click B "../faq" "FAQ"
+ click E "https://github.com/arista-netdevops-community/anta/issues"
+ click H "https://github.com/arista-netdevops-community/anta/issues"
+ style A stroke:#f00,stroke-width:2px
+```
+
+## Capturing logs
+
+To help document the issue in Github, it is important to capture some logs so the developers can understand what is affecting your system. No logs mean that the first question asked on the issue will probably be _"Can you share some logs please?"_.
+
+ANTA provides very verbose logs when using the `DEBUG` level. When using DEBUG log level with a log file, the DEBUG logging level is not sent to stdout, but only to the file.
+
+!!! danger
+
+ On real deployments, do not use DEBUG logging level without setting a log file at the same time.
+
+To save the logs to a file called `anta.log`, use the following flags:
+
+```bash
+# Where ANTA_COMMAND is one of nrfu, debug, get, exec, check
+anta -l DEBUG –log-file anta.log <ANTA_COMMAND>
+```
+
+See `anta --help` for more information. These have to precede the `nrfu` cmd.
+
+!!! tip
+
+ Remember that in ANTA, each level of command has its own options and they can only be set at this level.
+ so the `-l` and `--log-file` MUST be between `anta` and the `ANTA_COMMAND`.
+ similarly, all the `nrfu` options MUST be set between the `nrfu` and the `ANTA_NRFU_SUBCOMMAND` (`json`, `text`, `table` or `tpl-report`).
+
+
+As an example, for the `nrfu` command, it would look like:
+
+```bash
+anta -l DEBUG --log-file anta.log nrfu --enable --username username --password arista --inventory inventory.yml -c nrfu.yml text
+```
+
+
+### `ANTA_DEBUG` environment variable
+
+??? warning
+
+ Do not use this if you do not know why. This produces a lot of logs and can create confusion if you do not know what to look for.
+
+The environment variable `ANTA_DEBUG=true` enable ANTA Debug Mode.
+
+This flag is used by various functions in ANTA: when set to true, the function will display or log more information. In particular, when an Exception occurs in the code and this variable is set, the logging function used by ANTA is different to also produce the Python traceback for debugging. This typically needs to be done when opening a GitHub issue and an Exception is seen at runtime.
+
+Example:
+
+```bash
+ANTA_DEBUG=true anta -l DEBUG --log-file anta.log nrfu --enable --username username --password arista --inventory inventory.yml -c nrfu.yml text
+```
diff --git a/docs/usage-inventory-catalog.md b/docs/usage-inventory-catalog.md
index 39734f3..370f573 100644
--- a/docs/usage-inventory-catalog.md
+++ b/docs/usage-inventory-catalog.md
@@ -12,7 +12,7 @@ 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.
+A device inventory is an instance of the [AntaInventory](./api/inventory.md#anta.inventory.AntaInventory) class.
### Device Inventory File
@@ -41,8 +41,8 @@ anta_inventory:
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
+- `networks`: scan a network for devices accessible via eAPI
+- `ranges`: scan a range for devices accessible via eAPI
A full description of the inventory model is available in [API documentation](api/inventory.models.input.md)
@@ -72,7 +72,7 @@ anta_inventory:
## Test Catalog
-A test catalog is an instance of the [AntaCatalog](../api/catalog.md#anta.catalog.AntaCatalog) class.
+A test catalog is an instance of the [AntaCatalog](./api/catalog.md#anta.catalog.AntaCatalog) class.
### Test Catalog File