diff options
Diffstat (limited to '')
-rwxr-xr-x | docs/README.md | 32 | ||||
-rw-r--r-- | docs/advanced_usages/custom-tests.md | 12 | ||||
-rw-r--r-- | docs/api/runner.md | 9 | ||||
-rw-r--r-- | docs/api/tests.avt.md | 20 | ||||
-rw-r--r-- | docs/api/tests.md | 2 | ||||
-rw-r--r-- | docs/api/tests.path_selection.md | 20 | ||||
-rw-r--r-- | docs/api/tests.routing.isis.md | 20 | ||||
-rw-r--r-- | docs/cli/inv-from-ansible.md | 25 | ||||
-rw-r--r-- | docs/cli/nrfu.md | 8 | ||||
-rw-r--r-- | docs/cli/overview.md | 3 | ||||
-rw-r--r-- | docs/contribution.md | 21 | ||||
-rw-r--r-- | docs/faq.md | 4 | ||||
-rw-r--r-- | docs/getting-started.md | 16 | ||||
-rw-r--r-- | docs/imgs/anta_nrfu___dry_run.svg | 127 | ||||
-rw-r--r-- | docs/requirements-and-installation.md | 40 | ||||
-rw-r--r-- | docs/scripts/generate_svg.py | 36 | ||||
-rw-r--r-- | docs/snippets/anta_nrfu_help.txt | 4 | ||||
-rw-r--r-- | docs/stylesheets/extra.material.css | 75 | ||||
-rw-r--r-- | docs/troubleshooting.md | 11 | ||||
-rw-r--r-- | docs/usage-inventory-catalog.md | 29 |
20 files changed, 449 insertions, 65 deletions
diff --git a/docs/README.md b/docs/README.md index 1fe8734..378867f 100755 --- a/docs/README.md +++ b/docs/README.md @@ -19,14 +19,31 @@ ANTA is Python framework that automates tests for Arista devices. - Automate NRFU (Network Ready For Use) test on a preproduction network - Automate tests on a live network (periodically or on demand) - ANTA can be used with: - - The [ANTA CLI](cli/overview.md) - As a [Python library](advanced_usages/as-python-lib.md) in your own application + - The [ANTA CLI](cli/overview.md) ![anta nrfu](https://raw.githubusercontent.com/arista-netdevops-community/anta/main/docs/imgs/anta-nrfu.svg) +## Install ANTA library + +The library will **NOT** install the necessary dependencies for the CLI. + +```bash +# Install ANTA as a library +pip install anta +``` + +## Install ANTA CLI + +If you plan to use ANTA only as a CLI tool you can use `pipx` to install it. +[`pipx`](https://pipx.pypa.io/stable/) is a tool to install and run python applications in isolated environments. Refer to `pipx` instructions to install on your system. +`pipx` installs ANTA in an isolated python environment and makes it available globally. + +**This is not recommended if you plan to contribute to ANTA** + ```bash -# Install ANTA CLI -$ pip install anta +# Install ANTA CLI with pipx +$ pipx install anta[cli] # Run ANTA CLI $ anta --help @@ -52,8 +69,11 @@ Commands: nrfu Run ANTA tests on devices ``` -> [!WARNING] -> The ANTA CLI options have changed after version 0.11 and have moved away from the top level `anta` and are now required at their respective commands (e.g. `anta nrfu`). This breaking change occurs after users feedback on making the CLI more intuitive. This change should not affect user experience when using environment variables. +You can also still choose to install it with directly with `pip`: + +```bash +$ pip install anta[cli] +``` ## Documentation @@ -65,4 +85,6 @@ Contributions are welcome. Please refer to the [contribution guide](contribution ## Credits +Thank you to [Jeremy Schulman](https://github.com/jeremyschulman) for [aio-eapi](https://github.com/jeremyschulman/aio-eapi/tree/main/aioeapi). + Thank you to [Angélique Phillipps](https://github.com/aphillipps), [Colin MacGiollaEáin](https://github.com/colinmacgiolla), [Khelil Sator](https://github.com/ksator), [Matthieu Tache](https://github.com/mtache), [Onur Gashi](https://github.com/onurgashi), [Paul Lavelle](https://github.com/paullavelle), [Guillaume Mulocher](https://github.com/gmuloc) and [Thomas Grimonet](https://github.com/titom73) for their contributions and guidances. diff --git a/docs/advanced_usages/custom-tests.md b/docs/advanced_usages/custom-tests.md index df17c1c..ba62636 100644 --- a/docs/advanced_usages/custom-tests.md +++ b/docs/advanced_usages/custom-tests.md @@ -55,7 +55,9 @@ class VerifyTemperature(AntaTest): [AntaTest](../api/models.md#anta.models.AntaTest) also provide more advanced capabilities like [AntaCommand](../api/models.md#anta.models.AntaCommand) templating using the [AntaTemplate](../api/models.md#anta.models.AntaTemplate) class or test inputs definition and validation using [AntaTest.Input](../api/models.md#anta.models.AntaTest.Input) [pydantic](https://docs.pydantic.dev/latest/) model. This will be discussed in the sections below. -## [AntaTest](../api/models.md#anta.models.AntaTest) structure +## AntaTest structure + +Full AntaTest API documentation is available in the [API documentation section](../api/models.md#anta.models.AntaTest) ### Class Attributes @@ -98,7 +100,9 @@ class VerifyTemperature(AntaTest): The base definition of [AntaTest.Input](../api/models.md#anta.models.AntaTest.Input) provides common test inputs for all [AntaTest](../api/models.md#anta.models.AntaTest) instances: -#### [Input](../api/models.md#anta.models.AntaTest.Input) model +#### Input model + +Full `Input` model documentation is available in [API documentation section](../api/models.md#anta.models.AntaTest.Input) ::: anta.models.AntaTest.Input options: @@ -114,7 +118,9 @@ The base definition of [AntaTest.Input](../api/models.md#anta.models.AntaTest.In show_root_toc_entry: false heading_level: 10 -#### [ResultOverwrite](../api/models.md#anta.models.AntaTest.Input.ResultOverwrite) model +#### ResultOverwrite model + +Full `ResultOverwrite` model documentation is available in [API documentation section](../api/models.md#anta.models.AntaTest.Input.ResultOverwrite) ::: anta.models.AntaTest.Input.ResultOverwrite options: diff --git a/docs/api/runner.md b/docs/api/runner.md new file mode 100644 index 0000000..27fbaa2 --- /dev/null +++ b/docs/api/runner.md @@ -0,0 +1,9 @@ +<!-- + ~ 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.runner + options: + filters: ["!^_[^_]", "!__str__"] diff --git a/docs/api/tests.avt.md b/docs/api/tests.avt.md new file mode 100644 index 0000000..f9e1acf --- /dev/null +++ b/docs/api/tests.avt.md @@ -0,0 +1,20 @@ +--- +anta_title: ANTA catalog for Adaptive Virtual Topology (AVT) 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.avt + 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 1db3a8b..b11f0ba 100644 --- a/docs/api/tests.md +++ b/docs/api/tests.md @@ -13,6 +13,7 @@ This section describes all the available tests provided by the ANTA package. Here are the tests that we currently provide: - [AAA](tests.aaa.md) +- [Adaptive Virtual Topology](tests.avt.md) - [BFD](tests.bfd.md) - [Configuration](tests.configuration.md) - [Connectivity](tests.connectivity.md) @@ -26,6 +27,7 @@ Here are the tests that we currently provide: - [Multicast](tests.multicast.md) - [Profiles](tests.profiles.md) - [PTP](tests.ptp.md) +- [Router Path Selection](tests.path_selection.md) - [Routing Generic](tests.routing.generic.md) - [Routing BGP](tests.routing.bgp.md) - [Routing OSPF](tests.routing.ospf.md) diff --git a/docs/api/tests.path_selection.md b/docs/api/tests.path_selection.md new file mode 100644 index 0000000..b7f6b46 --- /dev/null +++ b/docs/api/tests.path_selection.md @@ -0,0 +1,20 @@ +--- +anta_title: ANTA catalog for Router path-selection 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.path_selection + 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.isis.md b/docs/api/tests.routing.isis.md new file mode 100644 index 0000000..b545f33 --- /dev/null +++ b/docs/api/tests.routing.isis.md @@ -0,0 +1,20 @@ +--- +anta_title: ANTA catalog for IS-IS 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.routing.isis + 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/cli/inv-from-ansible.md b/docs/cli/inv-from-ansible.md index ebe7da3..b2672e2 100644 --- a/docs/cli/inv-from-ansible.md +++ b/docs/cli/inv-from-ansible.md @@ -14,17 +14,28 @@ In large setups, it might be beneficial to construct your inventory based on you $ anta get from-ansible --help Usage: anta get from-ansible [OPTIONS] - Build ANTA inventory from an ansible inventory YAML file + Build ANTA inventory from an ansible inventory YAML file. + + NOTE: This command does not support inline vaulted variables. Make sure to + comment them out. Options: - -g, --ansible-group TEXT Ansible group to filter - --ansible-inventory FILENAME - Path to your ansible inventory file to read - -o, --output FILENAME Path to save inventory file - -d, --inventory-directory PATH Directory to save inventory file - --help Show this message and exit. + -o, --output FILE Path to save inventory file [env var: + ANTA_INVENTORY; required] + --overwrite Do not prompt when overriding current inventory + [env var: ANTA_GET_FROM_ANSIBLE_OVERWRITE] + -g, --ansible-group TEXT Ansible group to filter + --ansible-inventory FILE Path to your ansible inventory file to read + [required] + --help Show this message and exit. ``` +!!! warning + + `anta get from-ansible` does not support inline vaulted variables, comment them out to generate your inventory. + If the vaulted variable is necessary to build the inventory (e.g. `ansible_host`), it needs to be unvaulted for `from-ansible` command to work." + + The output is an inventory where the name of the container is added as a tag for each host: ```yaml diff --git a/docs/cli/nrfu.md b/docs/cli/nrfu.md index 7427f62..76605cb 100644 --- a/docs/cli/nrfu.md +++ b/docs/cli/nrfu.md @@ -173,7 +173,7 @@ The `--output` option allows you to choose the path where the final report will ```bash anta nrfu --tags LEAF tpl-report --template ./custom_template.j2 ``` -[![anta nrfu json results](../imgs/anta-nrfu-tpl-report-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-tpl-report-output.png) +[![anta nrfu tpl_resultss](../imgs/anta-nrfu-tpl-report-output.png){ loading=lazy width="1600" }](../imgs/anta-nrfu-tpl-report-output.png) The template `./custom_template.j2` is a simple Jinja2 template: @@ -200,3 +200,9 @@ cat nrfu-tpl-report.txt * VerifyMlagConfigSanity is [green]SUCCESS[/green] for DC1-LEAF1A * VerifyMlagReloadDelay is [green]SUCCESS[/green] for DC1-LEAF1A ``` + +## Dry-run mode + +It is possible to run `anta nrfu --dry-run` to execute ANTA up to the point where it should communicate with the network to execute the tests. When using `--dry-run`, all inventory devices are assumed to be online. This can be useful to check how many tests would be run using the catalog and inventory. + +[![anta nrfu dry_run](../imgs/anta_nrfu___dry_run.svg){ loading=lazy width="1600" }](../imgs/anta_nrfu___dry_run.svg) diff --git a/docs/cli/overview.md b/docs/cli/overview.md index 5e95ff5..107976a 100644 --- a/docs/cli/overview.md +++ b/docs/cli/overview.md @@ -12,9 +12,6 @@ ANTA can also be used as a Python library, allowing you to build your own tools To start using the ANTA CLI, open your terminal and type `anta`. -!!! warning - The ANTA CLI options have changed after version 0.11 and have moved away from the top level `anta` and are now required at their respective commands (e.g. `anta nrfu`). This breaking change occurs after users feedback on making the CLI more intuitive. This change should not affect user experience when using environment variables. - ## Invoking ANTA CLI ```bash diff --git a/docs/contribution.md b/docs/contribution.md index 5c6ae8e..cc3a1c0 100644 --- a/docs/contribution.md +++ b/docs/contribution.md @@ -21,12 +21,14 @@ $ cd anta # Install ANTA in editable mode and its development tools $ pip install -e .[dev] +# To also install the CLI +$ pip install -e .[dev,cli] # Verify installation $ pip list -e Package Version Editable project location ------- ------- ------------------------- -anta 0.14.0 /mnt/lab/projects/anta +anta 0.15.0 /mnt/lab/projects/anta ``` Then, [`tox`](https://tox.wiki/) is configured with few environments to run CI locally: @@ -91,17 +93,20 @@ All submodule should have its own pytest section under `tests/units/anta_tests/< The Python modules in the `tests/units/anta_tests` folder define test parameters for AntaTest subclasses unit tests. A generic test function is written for all unit tests in `tests.lib.anta` module. + The `pytest_generate_tests` function definition in `conftest.py` is called during test collection. + The `pytest_generate_tests` function will parametrize the generic test function based on the `DATA` data structure defined in `tests.units.anta_tests` modules. + See https://docs.pytest.org/en/7.3.x/how-to/parametrize.html#basic-pytest-generate-tests-example -The `DATA` structure is a list of dictionaries used to parametrize the test. -The list elements have the following keys: -- `name` (str): Test name as displayed by Pytest. -- `test` (AntaTest): An AntaTest subclass imported in the test module - e.g. VerifyUptime. -- `eos_data` (list[dict]): List of data mocking EOS returned data to be passed to the test. -- `inputs` (dict): Dictionary to instantiate the `test` inputs as defined in the class from `test`. -- `expected` (dict): Expected test result structure, a dictionary containing a key +The `DATA` structure is a list of dictionaries used to parametrize the test. The list elements have the following keys: + + - `name` (str): Test name as displayed by Pytest. + - `test` (AntaTest): An AntaTest subclass imported in the test module - e.g. VerifyUptime. + - `eos_data` (list[dict]): List of data mocking EOS returned data to be passed to the test. + - `inputs` (dict): Dictionary to instantiate the `test` inputs as defined in the class from `test`. + - `expected` (dict): Expected test result structure, a dictionary containing a key `result` containing one of the allowed status (`Literal['success', 'failure', 'unset', 'skipped', 'error']`) and optionally a key `messages` which is a list(str) and each message is expected to be a substring of one of the actual messages in the TestResult object. diff --git a/docs/faq.md b/docs/faq.md index 1cce990..c71d1c6 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,5 +1,5 @@ --- -toc_depth: 4 +toc_depth: 2 --- <!-- ~ Copyright (c) 2023-2024 Arista Networks, Inc. @@ -7,7 +7,7 @@ toc_depth: 4 ~ that can be found in the LICENSE file. --> <style> - h4 { + .md-typeset h2 { visibility: hidden; font-size: 0em; height: 0em; diff --git a/docs/getting-started.md b/docs/getting-started.md index 4386485..bab1cea 100644 --- a/docs/getting-started.md +++ b/docs/getting-started.md @@ -13,7 +13,7 @@ This section shows how to use ANTA with basic configuration. All examples are ba The easiest way to install ANTA package is to run Python (`>=3.9`) and its pip package to install: ```bash -pip install anta +pip install anta[cli] ``` For more details about how to install package, please see the [requirements and installation](./requirements-and-installation.md) section. @@ -121,6 +121,14 @@ anta.tests.configuration: ## Test your network +### Basic usage in a python script + +```python +--8<-- "anta_runner.py" +``` + +### CLI + ANTA comes with a generic CLI entrypoint to run tests in your network. It requires an inventory file as well as a test catalog. This entrypoint has multiple options to manage test coverage and reporting. @@ -135,7 +143,7 @@ This entrypoint has multiple options to manage test coverage and reporting. To run the NRFU, you need to select an output format amongst ["json", "table", "text", "tpl-report"]. For a first usage, `table` is recommended. By default all test results for all devices are rendered but it can be changed to a report per test case or per host -### Default report using table +#### Default report using table ```bash anta nrfu \ @@ -176,7 +184,7 @@ anta nrfu \ └───────────┴──────────────────────────┴─────────────┴──────────────────┴──────────────────────────────────────────────────────────────────────┴───────────────┘ ``` -### Report in text mode +#### Report in text mode ```bash $ anta nrfu \ @@ -206,7 +214,7 @@ leaf01 :: VerifyMlagConfigSanity :: SKIPPED (MLAG is disabled) [...] ``` -### Report in JSON format +#### Report in JSON format ```bash $ anta nrfu \ diff --git a/docs/imgs/anta_nrfu___dry_run.svg b/docs/imgs/anta_nrfu___dry_run.svg new file mode 100644 index 0000000..9b5876e --- /dev/null +++ b/docs/imgs/anta_nrfu___dry_run.svg @@ -0,0 +1,127 @@ +<svg class="rich-terminal" viewBox="0 0 1482 440.4" xmlns="http://www.w3.org/2000/svg"> + <!-- Generated with Rich https://www.textualize.io --> + <style> + + @font-face { + font-family: "Fira Code"; + src: local("FiraCode-Regular"), + url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Regular.woff2") format("woff2"), + url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Regular.woff") format("woff"); + font-style: normal; + font-weight: 400; + } + @font-face { + font-family: "Fira Code"; + src: local("FiraCode-Bold"), + url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff2/FiraCode-Bold.woff2") format("woff2"), + url("https://cdnjs.cloudflare.com/ajax/libs/firacode/6.2.0/woff/FiraCode-Bold.woff") format("woff"); + font-style: bold; + font-weight: 700; + } + + .terminal-2602327173-matrix { + font-family: Fira Code, monospace; + font-size: 20px; + line-height: 24.4px; + font-variant-east-asian: full-width; + } + + .terminal-2602327173-title { + font-size: 18px; + font-weight: bold; + font-family: arial; + } + + .terminal-2602327173-r1 { fill: #c5c8c6 } +.terminal-2602327173-r2 { fill: #68a0b3 } +.terminal-2602327173-r3 { fill: #98a84b } +.terminal-2602327173-r4 { fill: #4e707b } +.terminal-2602327173-r5 { fill: #608ab1 } +.terminal-2602327173-r6 { fill: #d0b344 } +.terminal-2602327173-r7 { fill: #868887 } +.terminal-2602327173-r8 { fill: #00823d;font-weight: bold } +.terminal-2602327173-r9 { fill: #68a0b3;font-weight: bold } +.terminal-2602327173-r10 { fill: #c5c8c6;font-weight: bold } + </style> + + <defs> + <clipPath id="terminal-2602327173-clip-terminal"> + <rect x="0" y="0" width="1463.0" height="389.4" /> + </clipPath> + <clipPath id="terminal-2602327173-line-0"> + <rect x="0" y="1.5" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-1"> + <rect x="0" y="25.9" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-2"> + <rect x="0" y="50.3" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-3"> + <rect x="0" y="74.7" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-4"> + <rect x="0" y="99.1" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-5"> + <rect x="0" y="123.5" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-6"> + <rect x="0" y="147.9" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-7"> + <rect x="0" y="172.3" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-8"> + <rect x="0" y="196.7" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-9"> + <rect x="0" y="221.1" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-10"> + <rect x="0" y="245.5" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-11"> + <rect x="0" y="269.9" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-12"> + <rect x="0" y="294.3" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-13"> + <rect x="0" y="318.7" width="1464" height="24.65"/> + </clipPath> +<clipPath id="terminal-2602327173-line-14"> + <rect x="0" y="343.1" width="1464" height="24.65"/> + </clipPath> + </defs> + + <rect fill="#292929" stroke="rgba(255,255,255,0.35)" stroke-width="1" x="1" y="1" width="1480" height="438.4" rx="8"/><text class="terminal-2602327173-title" fill="#c5c8c6" text-anchor="middle" x="740" y="27">anta nrfu --dry-run</text> + <g transform="translate(26,22)"> + <circle cx="0" cy="0" r="7" fill="#ff5f57"/> + <circle cx="22" cy="0" r="7" fill="#febc2e"/> + <circle cx="44" cy="0" r="7" fill="#28c840"/> + </g> + + <g transform="translate(9, 41)" clip-path="url(#terminal-2602327173-clip-terminal)"> + + <g class="terminal-2602327173-matrix"> + <text class="terminal-2602327173-r1" x="0" y="20" textLength="390.4" clip-path="url(#terminal-2602327173-line-0)">ant@anthill$ anta nrfu --dry-run</text><text class="terminal-2602327173-r1" x="1464" y="20" textLength="12.2" clip-path="url(#terminal-2602327173-line-0)"> +</text><text class="terminal-2602327173-r2" x="0" y="44.4" textLength="24.4" clip-path="url(#terminal-2602327173-line-1)">╭─</text><text class="terminal-2602327173-r2" x="24.4" y="44.4" textLength="256.2" clip-path="url(#terminal-2602327173-line-1)">─────────────────────</text><text class="terminal-2602327173-r3" x="292.8" y="44.4" textLength="97.6" clip-path="url(#terminal-2602327173-line-1)">Settings</text><text class="terminal-2602327173-r2" x="402.6" y="44.4" textLength="256.2" clip-path="url(#terminal-2602327173-line-1)">─────────────────────</text><text class="terminal-2602327173-r2" x="658.8" y="44.4" textLength="24.4" clip-path="url(#terminal-2602327173-line-1)">─╮</text><text class="terminal-2602327173-r1" x="1464" y="44.4" textLength="12.2" clip-path="url(#terminal-2602327173-line-1)"> +</text><text class="terminal-2602327173-r2" x="0" y="68.8" textLength="12.2" clip-path="url(#terminal-2602327173-line-2)">│</text><text class="terminal-2602327173-r2" x="24.4" y="68.8" textLength="634.4" clip-path="url(#terminal-2602327173-line-2)">- ANTA Inventory contains 3 devices (AsyncEOSDevice)</text><text class="terminal-2602327173-r2" x="671" y="68.8" textLength="12.2" clip-path="url(#terminal-2602327173-line-2)">│</text><text class="terminal-2602327173-r1" x="1464" y="68.8" textLength="12.2" clip-path="url(#terminal-2602327173-line-2)"> +</text><text class="terminal-2602327173-r2" x="0" y="93.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-3)">│</text><text class="terminal-2602327173-r2" x="24.4" y="93.2" textLength="390.4" clip-path="url(#terminal-2602327173-line-3)">- Tests catalog contains 9 tests</text><text class="terminal-2602327173-r2" x="671" y="93.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-3)">│</text><text class="terminal-2602327173-r1" x="1464" y="93.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-3)"> +</text><text class="terminal-2602327173-r2" x="0" y="117.6" textLength="683.2" clip-path="url(#terminal-2602327173-line-4)">╰──────────────────────────────────────────────────────╯</text><text class="terminal-2602327173-r1" x="1464" y="117.6" textLength="12.2" clip-path="url(#terminal-2602327173-line-4)"> +</text><text class="terminal-2602327173-r1" x="1464" y="142" textLength="12.2" clip-path="url(#terminal-2602327173-line-5)"> +</text><text class="terminal-2602327173-r4" x="0" y="166.4" textLength="231.8" clip-path="url(#terminal-2602327173-line-6)">[04/29/24 12:12:25]</text><text class="terminal-2602327173-r5" x="244" y="166.4" textLength="97.6" clip-path="url(#terminal-2602327173-line-6)">INFO    </text><text class="terminal-2602327173-r1" x="353.8" y="166.4" textLength="292.8" clip-path="url(#terminal-2602327173-line-6)">Preparing ANTA NRFU Run </text><text class="terminal-2602327173-r6" x="646.6" y="166.4" textLength="36.6" clip-path="url(#terminal-2602327173-line-6)">...</text><text class="terminal-2602327173-r7" x="1317.6" y="166.4" textLength="97.6" clip-path="url(#terminal-2602327173-line-6)">tools.py</text><text class="terminal-2602327173-r7" x="1415.2" y="166.4" textLength="12.2" clip-path="url(#terminal-2602327173-line-6)">:</text><text class="terminal-2602327173-r7" x="1427.4" y="166.4" textLength="36.6" clip-path="url(#terminal-2602327173-line-6)">288</text><text class="terminal-2602327173-r1" x="1464" y="166.4" textLength="12.2" clip-path="url(#terminal-2602327173-line-6)"> +</text><text class="terminal-2602327173-r5" x="244" y="190.8" textLength="97.6" clip-path="url(#terminal-2602327173-line-7)">INFO    </text><text class="terminal-2602327173-r1" x="353.8" y="190.8" textLength="244" clip-path="url(#terminal-2602327173-line-7)">Preparing the tests </text><text class="terminal-2602327173-r6" x="597.8" y="190.8" textLength="36.6" clip-path="url(#terminal-2602327173-line-7)">...</text><text class="terminal-2602327173-r7" x="1317.6" y="190.8" textLength="97.6" clip-path="url(#terminal-2602327173-line-7)">tools.py</text><text class="terminal-2602327173-r7" x="1415.2" y="190.8" textLength="12.2" clip-path="url(#terminal-2602327173-line-7)">:</text><text class="terminal-2602327173-r7" x="1427.4" y="190.8" textLength="36.6" clip-path="url(#terminal-2602327173-line-7)">288</text><text class="terminal-2602327173-r1" x="1464" y="190.8" textLength="12.2" clip-path="url(#terminal-2602327173-line-7)"> +</text><text class="terminal-2602327173-r5" x="244" y="215.2" textLength="97.6" clip-path="url(#terminal-2602327173-line-8)">INFO    </text><text class="terminal-2602327173-r1" x="353.8" y="215.2" textLength="414.8" clip-path="url(#terminal-2602327173-line-8)">Preparing the tests completed in: </text><text class="terminal-2602327173-r8" x="768.6" y="215.2" textLength="85.4" clip-path="url(#terminal-2602327173-line-8)">0:00:00</text><text class="terminal-2602327173-r1" x="854" y="215.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-8)">.</text><text class="terminal-2602327173-r9" x="866.2" y="215.2" textLength="36.6" clip-path="url(#terminal-2602327173-line-8)">001</text><text class="terminal-2602327173-r1" x="902.8" y="215.2" textLength="402.6" clip-path="url(#terminal-2602327173-line-8)">.                                </text><text class="terminal-2602327173-r7" x="1317.6" y="215.2" textLength="97.6" clip-path="url(#terminal-2602327173-line-8)">tools.py</text><text class="terminal-2602327173-r7" x="1415.2" y="215.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-8)">:</text><text class="terminal-2602327173-r7" x="1427.4" y="215.2" textLength="36.6" clip-path="url(#terminal-2602327173-line-8)">296</text><text class="terminal-2602327173-r1" x="1464" y="215.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-8)"> +</text><text class="terminal-2602327173-r5" x="244" y="239.6" textLength="97.6" clip-path="url(#terminal-2602327173-line-9)">INFO    </text><text class="terminal-2602327173-r1" x="353.8" y="239.6" textLength="939.4" clip-path="url(#terminal-2602327173-line-9)">--- ANTA NRFU Run Information ---                                            </text><text class="terminal-2602327173-r7" x="1305.4" y="239.6" textLength="109.8" clip-path="url(#terminal-2602327173-line-9)">runner.py</text><text class="terminal-2602327173-r7" x="1415.2" y="239.6" textLength="12.2" clip-path="url(#terminal-2602327173-line-9)">:</text><text class="terminal-2602327173-r7" x="1427.4" y="239.6" textLength="36.6" clip-path="url(#terminal-2602327173-line-9)">245</text><text class="terminal-2602327173-r1" x="1464" y="239.6" textLength="12.2" clip-path="url(#terminal-2602327173-line-9)"> +</text><text class="terminal-2602327173-r1" x="353.8" y="264" textLength="231.8" clip-path="url(#terminal-2602327173-line-10)">Number of devices: </text><text class="terminal-2602327173-r9" x="585.6" y="264" textLength="12.2" clip-path="url(#terminal-2602327173-line-10)">3</text><text class="terminal-2602327173-r10" x="610" y="264" textLength="12.2" clip-path="url(#terminal-2602327173-line-10)">(</text><text class="terminal-2602327173-r9" x="622.2" y="264" textLength="12.2" clip-path="url(#terminal-2602327173-line-10)">3</text><text class="terminal-2602327173-r1" x="634.4" y="264" textLength="146.4" clip-path="url(#terminal-2602327173-line-10)"> established</text><text class="terminal-2602327173-r10" x="780.8" y="264" textLength="12.2" clip-path="url(#terminal-2602327173-line-10)">)</text><text class="terminal-2602327173-r1" x="1464" y="264" textLength="12.2" clip-path="url(#terminal-2602327173-line-10)"> +</text><text class="terminal-2602327173-r1" x="353.8" y="288.4" textLength="390.4" clip-path="url(#terminal-2602327173-line-11)">Total number of selected tests: </text><text class="terminal-2602327173-r9" x="744.2" y="288.4" textLength="24.4" clip-path="url(#terminal-2602327173-line-11)">27</text><text class="terminal-2602327173-r1" x="1464" y="288.4" textLength="12.2" clip-path="url(#terminal-2602327173-line-11)"> +</text><text class="terminal-2602327173-r1" x="353.8" y="312.8" textLength="854" clip-path="url(#terminal-2602327173-line-12)">Maximum number of open file descriptors for the current ANTA process: </text><text class="terminal-2602327173-r9" x="1207.8" y="312.8" textLength="61" clip-path="url(#terminal-2602327173-line-12)">16384</text><text class="terminal-2602327173-r1" x="1464" y="312.8" textLength="12.2" clip-path="url(#terminal-2602327173-line-12)"> +</text><text class="terminal-2602327173-r1" x="353.8" y="337.2" textLength="939.4" clip-path="url(#terminal-2602327173-line-13)">---------------------------------                                            </text><text class="terminal-2602327173-r1" x="1464" y="337.2" textLength="12.2" clip-path="url(#terminal-2602327173-line-13)"> +</text><text class="terminal-2602327173-r5" x="244" y="361.6" textLength="97.6" clip-path="url(#terminal-2602327173-line-14)">INFO    </text><text class="terminal-2602327173-r1" x="353.8" y="361.6" textLength="463.6" clip-path="url(#terminal-2602327173-line-14)">Preparing ANTA NRFU Run completed in: </text><text class="terminal-2602327173-r8" x="817.4" y="361.6" textLength="85.4" clip-path="url(#terminal-2602327173-line-14)">0:00:00</text><text class="terminal-2602327173-r1" x="902.8" y="361.6" textLength="12.2" clip-path="url(#terminal-2602327173-line-14)">.</text><text class="terminal-2602327173-r9" x="915" y="361.6" textLength="36.6" clip-path="url(#terminal-2602327173-line-14)">006</text><text class="terminal-2602327173-r1" x="951.6" y="361.6" textLength="353.8" clip-path="url(#terminal-2602327173-line-14)">.                            </text><text class="terminal-2602327173-r7" x="1317.6" y="361.6" textLength="97.6" clip-path="url(#terminal-2602327173-line-14)">tools.py</text><text class="terminal-2602327173-r7" x="1415.2" y="361.6" textLength="12.2" clip-path="url(#terminal-2602327173-line-14)">:</text><text class="terminal-2602327173-r7" x="1427.4" y="361.6" textLength="36.6" clip-path="url(#terminal-2602327173-line-14)">296</text><text class="terminal-2602327173-r1" x="1464" y="361.6" textLength="12.2" clip-path="url(#terminal-2602327173-line-14)"> +</text><text class="terminal-2602327173-r5" x="244" y="386" textLength="97.6" clip-path="url(#terminal-2602327173-line-15)">INFO    </text><text class="terminal-2602327173-r1" x="353.8" y="386" textLength="939.4" clip-path="url(#terminal-2602327173-line-15)">Dry-run mode, exiting before running the tests.                              </text><text class="terminal-2602327173-r7" x="1305.4" y="386" textLength="109.8" clip-path="url(#terminal-2602327173-line-15)">runner.py</text><text class="terminal-2602327173-r7" x="1415.2" y="386" textLength="12.2" clip-path="url(#terminal-2602327173-line-15)">:</text><text class="terminal-2602327173-r7" x="1427.4" y="386" textLength="36.6" clip-path="url(#terminal-2602327173-line-15)">257</text><text class="terminal-2602327173-r1" x="1464" y="386" textLength="12.2" clip-path="url(#terminal-2602327173-line-15)"> +</text> + </g> + </g> +</svg> diff --git a/docs/requirements-and-installation.md b/docs/requirements-and-installation.md index b3107a6..75560d3 100644 --- a/docs/requirements-and-installation.md +++ b/docs/requirements-and-installation.md @@ -22,25 +22,57 @@ This installation will deploy tests collection, scripts and all their Python req The ANTA package and the cli require some packages that are not part of the Python standard library. They are indicated in the [pyproject.toml](https://github.com/arista-netdevops-community/anta/blob/main/pyproject.toml) file, under dependencies. -### Install from Pypi server +### Install library from Pypi server ```bash pip install anta ``` +!!! Warning + + * This command alone **will not** install the ANTA CLI requirements. + * When using ANTA mode in [AVD](https://avd.arista.com) `eos_validate` role, (currently in preview), ensure you install the documented supported ANTA version for your AVD version.</br> + The latest documented version can be found at: https://avd.arista.com/stable/roles/eos_validate_state/ANTA-Preview.html + +### Install ANTA CLI as an application with `pipx` + +[`pipx`](https://pipx.pypa.io/stable/) is a tool to install and run python applications in isolated environments. If you plan to use ANTA only as a CLI tool you can use `pipx` to install it. `pipx` installs ANTA in an isolated python environment and makes it available globally. + +``` +pipx install anta[cli] +``` + +!!! Info + + Please take the time to read through the installation instructions of `pipx` before getting started. + + +### Install CLI from Pypi server + +Alternatively, pip install with `cli` extra is enough to install the ANTA CLI. + +```bash +pip install anta[cli] +``` + ### Install ANTA from github ```bash pip install git+https://github.com/arista-netdevops-community/anta.git +pip install git+https://github.com/arista-netdevops-community/anta.git#egg=anta[cli] # You can even specify the branch, tag or commit: pip install git+https://github.com/arista-netdevops-community/anta.git@<cool-feature-branch> +pip install git+https://github.com/arista-netdevops-community/anta.git@<cool-feature-branch>#egg=anta[cli] + pip install git+https://github.com/arista-netdevops-community/anta.git@<cool-tag> +pip install git+https://github.com/arista-netdevops-community/anta.git@<cool-tag>#egg=anta[cli] + pip install git+https://github.com/arista-netdevops-community/anta.git@<more-or-less-cool-hash> +pip install git+https://github.com/arista-netdevops-community/anta.git@<more-or-less-cool-hash>#egg=anta[cli] ``` - ### Check installation After installing ANTA, verify the installation with the following commands: @@ -61,12 +93,12 @@ which anta ```bash # Check ANTA version anta --version -anta, version v0.14.0 +anta, version v0.15.0 ``` ## EOS Requirements -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): +To get ANTA working, the targeted Arista EOS devices must have eAPI enabled. They need to use the following configuration (assuming you connect to the device using Management interface in MGMT VRF): ```eos configure diff --git a/docs/scripts/generate_svg.py b/docs/scripts/generate_svg.py index 426a785..0048160 100644 --- a/docs/scripts/generate_svg.py +++ b/docs/scripts/generate_svg.py @@ -13,6 +13,7 @@ python generate_svg.py anta ... # ruff: noqa: T201 import io +import logging import os import pathlib import sys @@ -22,10 +23,17 @@ from importlib.metadata import entry_points from unittest.mock import patch from rich.console import Console +from rich.logging import RichHandler from anta.cli.console import console from anta.cli.nrfu.utils import anta_progress_bar +root = logging.getLogger() + +r = RichHandler(console=console) +root.addHandler(r) + + OUTPUT_DIR = pathlib.Path(__file__).parent.parent / "imgs" @@ -43,7 +51,7 @@ def custom_progress_bar() -> None: if __name__ == "__main__": # Sane rich size - os.environ["COLUMNS"] = "165" + os.environ["COLUMNS"] = "120" # stolen from https://github.com/ewels/rich-click/blob/main/src/rich_click/cli.py args = sys.argv[1:] @@ -64,6 +72,8 @@ if __name__ == "__main__": print("Usage: python generate_svg.py anta <options>") sys.exit(1) + # possibly-used-before-assignment - prog / function_name -> not understanding sys.exit here... + # pylint: disable=E0606 sys.argv = [prog, *args[1:]] module = import_module(module_path) function = getattr(module, function_name) @@ -71,22 +81,24 @@ if __name__ == "__main__": # Console to captur everything new_console = Console(record=True) - # tweaks to record and redirect to a dummy file pipe = io.StringIO() console.record = True console.file = pipe + with redirect_stdout(io.StringIO()) as f: + # tweaks to record and redirect to a dummy file + + console.print(f"ant@anthill$ {' '.join(sys.argv)}") + + # Redirect stdout of the program towards another StringIO to capture help + # that is not part or anta rich console + # redirect potential progress bar output to console by patching + with patch("anta.cli.nrfu.anta_progress_bar", custom_progress_bar), suppress(SystemExit): + function() - # Redirect stdout of the program towards another StringIO to capture help - # that is not part or anta rich console - # 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()) + if "--help" in args: + console.print(f.getvalue()) 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)) + console.save_svg(filename, title=" ".join(args)) diff --git a/docs/snippets/anta_nrfu_help.txt b/docs/snippets/anta_nrfu_help.txt index 87e5195..68cb4b8 100644 --- a/docs/snippets/anta_nrfu_help.txt +++ b/docs/snippets/anta_nrfu_help.txt @@ -42,6 +42,10 @@ Options: ANTA_NRFU_IGNORE_ERROR] --hide [success|failure|error|skipped] Group result by test or device. + --dry-run Run anta nrfu command but stop before + starting to execute the tests. Considers all + devices as connected. [env var: + ANTA_NRFU_DRY_RUN] --help Show this message and exit. Commands: diff --git a/docs/stylesheets/extra.material.css b/docs/stylesheets/extra.material.css index b401c9a..09d7c8d 100644 --- a/docs/stylesheets/extra.material.css +++ b/docs/stylesheets/extra.material.css @@ -2,11 +2,15 @@ --md-hue: 210; } +#page { + counter-reset: heading; +} + :root { /* Color schema based on Arista Color Schema */ /* Default color shades */ --md-default-fg-color: #000000; - --md-default-fg-color--light: #a1a0a0; + --md-default-fg-color--light: #444343; --md-default-fg-color--lighter: #FFFFFF; --md-default-fg-color--lightest: #FFFFFF; --md-default-bg-color: #FFFFFF; @@ -35,12 +39,8 @@ --md-code-bg-color: #E6E6E6; --md-code-border-color: #0000004f; --block-code-bg-color: #e4e4e4; - /* --md-code-fg-color: ...; */ font-size: 1.1rem; - /* min-height: 100%; - position: relative; - width: 100%; */ font-feature-settings: "kern","liga"; font-family: var(--md-text-font-family,_),-apple-system,BlinkMacSystemFont,Helvetica,Arial,sans-serif; -webkit-font-smoothing: antialiased; @@ -49,15 +49,16 @@ [data-md-color-scheme="slate"] { + /* Default color shades */ + --md-default-fg-color--light: #949393; + /* Link color */ --md-typeset-a-color: #75aaf8; --md-typeset-a-color-fg: #FFFFFF; --md-typeset-a-color-bg: #27569B; /* Code block color shades */ - /* --md-code-bg-color: #E6E6E6; */ --md-code-border-color: #aec6db4f; - /* --block-code-bg-color: #e4e4e4; */ } @media only screen and (min-width: 76.25em) { @@ -76,6 +77,7 @@ } @media only screen { + .md-typeset a:hover { background-color: var(--md-typeset-a-color-bg); color: var(--md-typeset-a-color-fg); @@ -102,12 +104,56 @@ color: var(--md-default-fg-color--light); } - .md-typeset h4 h5 h6 { - font-size: 1.5rem; - margin: 1em 0; - /* font-weight: 700; */ - letter-spacing: -.01em; - line-height: 3em; + .md-typeset h2 { + line-height: 2em; + font-size: 1.5rem; + margin: 1em 0; + /* font-weight: 700; */ + letter-spacing: -.01em; + color: var(--md-default-fg-color--light); + text-transform: capitalize; + font-style: normal; + font-weight: bolder; + } + + .md-typeset h3 { + line-height: 1em; + font-size: 1.3rem; + margin: 1em 0; + /* font-weight: 700; */ + letter-spacing: -.01em; + color: var(--md-default-fg-color--light); + text-transform: capitalize; + font-style: normal; + font-weight: bold; + } + + .md-typeset h4::before { + content: ">> "; + } + + .md-typeset h4 { + font-size: 1.1rem; + margin: 1em 0; + font-weight: 700; + letter-spacing: -.01em; + line-height: 1em; + color: var(--md-default-fg-color--light); + font-style: italic; + text-transform: capitalize; + } + + .md-typeset h5, + .md-typeset h6 { + font-size: 0.9rem; + margin: 1em 0; + /* font-weight: 700; */ + letter-spacing: -.01em; + /* line-height: 2em; */ + color: var(--md-default-fg-color--light); + font-style: italic; + text-transform: capitalize; + text-decoration: underline; } .md-typeset table:not([class]) th { @@ -178,8 +224,6 @@ .md-typeset table:not([class]) th { min-width: 5rem; padding: .6rem .8rem; - /* color: var(--md-primary-fg-color--light); */ - bg: var(--md-footer-fg-color--lighter); } .md-footer-copyright { @@ -195,7 +239,6 @@ margin-left: auto; margin-right: auto; border-radius: 1%; - /* width: 50%; */ } } diff --git a/docs/troubleshooting.md b/docs/troubleshooting.md index 596aad6..f27de7a 100644 --- a/docs/troubleshooting.md +++ b/docs/troubleshooting.md @@ -77,3 +77,14 @@ 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 ``` + +### Troubleshooting on EOS + +ANTA is using a specific ID in eAPI requests towards EOS. This allows for easier eAPI requests debugging on the device using EOS configuration `trace CapiApp setting UwsgiRequestContext/4,CapiUwsgiServer/4` to set up CapiApp agent logs. + +Then, you can view agent logs using: +```bash +bash tail -f /var/log/agents/CapiApp-* + +2024-05-15 15:32:54.056166 1429 UwsgiRequestContext 4 request content b'{"jsonrpc": "2.0", "method": "runCmds", "params": {"version": "latest", "cmds": [{"cmd": "show ip route vrf default 10.255.0.3", "revision": 4}], "format": "json", "autoComplete": false, "expandAliases": false}, "id": "ANTA-VerifyRoutingTableEntry-132366530677328"}' +``` diff --git a/docs/usage-inventory-catalog.md b/docs/usage-inventory-catalog.md index 370f573..e698dca 100644 --- a/docs/usage-inventory-catalog.md +++ b/docs/usage-inventory-catalog.md @@ -244,3 +244,32 @@ Once you run `anta nrfu table`, you will see following output: │ spine01 │ VerifyInterfaceUtilization │ success │ │ Verifies interfaces utilization is below 75%. │ interfaces │ └───────────┴────────────────────────────┴─────────────┴────────────┴───────────────────────────────────────────────┴───────────────┘ ``` + +### Example script to merge catalogs + +The following script reads all the files in `intended/test_catalogs/` with names `<device_name>-catalog.yml` and merge them together inside one big catalog `anta-catalog.yml`. + +```python +#!/usr/bin/env python +from anta.catalog import AntaCatalog + +from pathlib import Path +from anta.models import AntaTest + + +CATALOG_SUFFIX = '-catalog.yml' +CATALOG_DIR = 'intended/test_catalogs/' + +if __name__ == "__main__": + catalog = AntaCatalog() + for file in Path(CATALOG_DIR).glob('*'+CATALOG_SUFFIX): + c = AntaCatalog.parse(file) + device = str(file).removesuffix(CATALOG_SUFFIX).removeprefix(CATALOG_DIR) + print(f"Merging test catalog for device {device}") + # Apply filters to all tests for this device + for test in c.tests: + test.inputs.filters = AntaTest.Input.Filters(tags=[device]) + catalog.merge(c) + with open(Path('anta-catalog.yml'), "w") as f: + f.write(catalog.dump().yaml()) +``` |