From 7880064ac1170b7698e3aaea9c59f2136de3ca9a Mon Sep 17 00:00:00 2001 From: Guillaume Mulocher Date: Fri, 11 Oct 2024 15:06:18 +0200 Subject: [PATCH] doc: Clean doc pre-release (#876) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --------- Co-authored-by: Carl Baillargeon Co-authored-by: Matthieu Tâche --- anta/reporter/__init__.py | 7 +- anta/reporter/md_reporter.py | 6 +- docs/advanced_usages/as-python-lib.md | 90 +--------- docs/advanced_usages/custom-tests.md | 3 - docs/api/csv_reporter.md | 13 ++ docs/api/md_reporter.md | 13 ++ docs/api/{report_manager.md => reporters.md} | 5 +- docs/api/tests.md | 3 +- docs/api/tests.routing.bgp.md | 1 + docs/api/tests.routing.isis.md | 1 + docs/api/tests.routing.ospf.md | 1 + docs/cli/debug.md | 6 +- docs/cli/get-inventory-information.md | 176 ++++++------------- docs/cli/nrfu.md | 21 +-- docs/cli/tag-management.md | 58 +++++- docs/faq.md | 7 +- docs/stylesheets/extra.material.css | 3 +- docs/usage-inventory-catalog.md | 28 +-- examples/README.md | 24 ++- examples/merge_catalogs.py | 30 ++++ examples/parse_anta_inventory_file.py | 34 ++++ examples/run_eos_commands.py | 59 +++++++ mkdocs.yml | 5 +- pyproject.toml | 11 +- 24 files changed, 329 insertions(+), 276 deletions(-) create mode 100644 docs/api/csv_reporter.md create mode 100644 docs/api/md_reporter.md rename docs/api/{report_manager.md => reporters.md} (63%) create mode 100644 examples/merge_catalogs.py create mode 100644 examples/parse_anta_inventory_file.py create mode 100644 examples/run_eos_commands.py diff --git a/anta/reporter/__init__.py b/anta/reporter/__init__.py index 38f2e8e68..9e5fa1b30 100644 --- a/anta/reporter/__init__.py +++ b/anta/reporter/__init__.py @@ -105,7 +105,7 @@ def _color_result(self, status: AntaTestStatus) -> str: def report_all(self, manager: ResultManager, title: str = "All tests results") -> Table: """Create a table report with all tests for one or all devices. - Create table with full output: Host / Test / Status / Message + Create table with full output: Device | Test Name | Test Status | Message(s) | Test description | Test category Parameters ---------- @@ -141,7 +141,8 @@ def report_summary_tests( ) -> Table: """Create a table report with result aggregated per test. - Create table with full output: Test | Number of success | Number of failure | Number of error | List of nodes in error or failure + Create table with full output: + Test Name | # of success | # of skipped | # of failure | # of errors | List of failed or error nodes Parameters ---------- @@ -187,7 +188,7 @@ def report_summary_devices( ) -> Table: """Create a table report with result aggregated per device. - Create table with full output: Host | Number of success | Number of failure | Number of error | List of nodes in error or failure + Create table with full output: Device | # of success | # of skipped | # of failure | # of errors | List of failed or error test cases Parameters ---------- diff --git a/anta/reporter/md_reporter.py b/anta/reporter/md_reporter.py index 887fd6689..be3e86faf 100644 --- a/anta/reporter/md_reporter.py +++ b/anta/reporter/md_reporter.py @@ -112,8 +112,8 @@ def generate_heading_name(self) -> str: Example ------- - - `ANTAReport` will become ANTA Report. - - `TestResultsSummary` will become Test Results Summary. + - `ANTAReport` will become `ANTA Report`. + - `TestResultsSummary` will become `Test Results Summary`. """ class_name = self.__class__.__name__ @@ -153,7 +153,7 @@ def write_heading(self, heading_level: int) -> None: Example ------- - ## Test Results Summary + `## Test Results Summary` """ # Ensure the heading level is within the valid range of 1 to 6 heading_level = max(1, min(heading_level, 6)) diff --git a/docs/advanced_usages/as-python-lib.md b/docs/advanced_usages/as-python-lib.md index d64104a95..49c010f80 100644 --- a/docs/advanced_usages/as-python-lib.md +++ b/docs/advanced_usages/as-python-lib.md @@ -44,98 +44,14 @@ The [AntaInventory](../api/inventory.md#anta.inventory.AntaInventory) class is a ### Parse an ANTA inventory file ```python -""" -This script parses an ANTA inventory file, connects to devices and print their status. -""" -import asyncio - -from anta.inventory import AntaInventory - - -async def main(inv: AntaInventory) -> None: - """ - Take an AntaInventory and: - 1. try to connect to every device in the inventory - 2. print a message for every device connection status - """ - await inv.connect_inventory() - - for device in inv.values(): - if device.established: - print(f"Device {device.name} is online") - else: - print(f"Could not connect to device {device.name}") - -if __name__ == "__main__": - # Create the AntaInventory instance - inventory = AntaInventory.parse( - filename="inv.yml", - username="arista", - password="@rista123", - ) - - # Run the main coroutine - res = asyncio.run(main(inventory)) +--8<-- "parse_anta_inventory_file.py" ``` -??? note "How to create your inventory file" +!!! note "How to create your inventory file" Please visit this [dedicated section](../usage-inventory-catalog.md) for how to use inventory and catalog files. ### Run EOS commands ```python -""" -This script runs a list of EOS commands on reachable devices. -""" -# This is needed to run the script for python < 3.10 for typing annotations -from __future__ import annotations - -import asyncio -from pprint import pprint - -from anta.inventory import AntaInventory -from anta.models import AntaCommand - - -async def main(inv: AntaInventory, commands: list[str]) -> dict[str, list[AntaCommand]]: - """ - Take an AntaInventory and a list of commands as string and: - 1. try to connect to every device in the inventory - 2. collect the results of the commands from each device - - Returns: - a dictionary where key is the device name and the value is the list of AntaCommand ran towards the device - """ - await inv.connect_inventory() - - # Make a list of coroutine to run commands towards each connected device - coros = [] - # dict to keep track of the commands per device - result_dict = {} - for name, device in inv.get_inventory(established_only=True).items(): - anta_commands = [AntaCommand(command=command, ofmt="json") for command in commands] - result_dict[name] = anta_commands - coros.append(device.collect_commands(anta_commands)) - - # Run the coroutines - await asyncio.gather(*coros) - - return result_dict - - -if __name__ == "__main__": - # Create the AntaInventory instance - inventory = AntaInventory.parse( - filename="inv.yml", - username="arista", - password="@rista123", - ) - - # Create a list of commands with json output - commands = ["show version", "show ip bgp summary"] - - # Run the main asyncio entry point - res = asyncio.run(main(inventory, commands)) - - pprint(res) +--8<-- "run_eos_commands.py" ``` diff --git a/docs/advanced_usages/custom-tests.md b/docs/advanced_usages/custom-tests.md index d81f32dcf..d79fe50e3 100644 --- a/docs/advanced_usages/custom-tests.md +++ b/docs/advanced_usages/custom-tests.md @@ -71,9 +71,6 @@ Full AntaTest API documentation is available in the [API documentation section]( ### Instance Attributes -!!! info - You can access an instance attribute in your code using the `self` reference. E.g. you can access the test input values using `self.inputs`. - ::: anta.models.AntaTest options: show_docstring_attributes: true diff --git a/docs/api/csv_reporter.md b/docs/api/csv_reporter.md new file mode 100644 index 000000000..0432c4590 --- /dev/null +++ b/docs/api/csv_reporter.md @@ -0,0 +1,13 @@ +--- +anta_title: CSV Reporter +--- + + +::: anta.reporter.csv_reporter + options: + show_root_heading: false + show_root_toc_entry: false diff --git a/docs/api/md_reporter.md b/docs/api/md_reporter.md new file mode 100644 index 000000000..7fa1a1537 --- /dev/null +++ b/docs/api/md_reporter.md @@ -0,0 +1,13 @@ +--- +anta_title: Markdown Reporter +--- + + +::: anta.reporter.md_reporter + options: + show_root_heading: false + show_root_toc_entry: false diff --git a/docs/api/report_manager.md b/docs/api/reporters.md similarity index 63% rename from docs/api/report_manager.md rename to docs/api/reporters.md index f0e381805..a72e107e2 100644 --- a/docs/api/report_manager.md +++ b/docs/api/reporters.md @@ -4,4 +4,7 @@ ~ that can be found in the LICENSE file. --> -### ::: anta.reporter.ReportTable +::: anta.reporter + options: + show_root_heading: false + show_root_toc_entry: false diff --git a/docs/api/tests.md b/docs/api/tests.md index 1ca4cb7b3..7dd74c133 100644 --- a/docs/api/tests.md +++ b/docs/api/tests.md @@ -18,7 +18,7 @@ Here are the tests that we currently provide: - [BFD](tests.bfd.md) - [Configuration](tests.configuration.md) - [Connectivity](tests.connectivity.md) -- [Field Notice](tests.field_notices.md) +- [Field Notices](tests.field_notices.md) - [Flow Tracking](tests.flow_tracking.md) - [GreenT](tests.greent.md) - [Hardware](tests.hardware.md) @@ -32,6 +32,7 @@ Here are the tests that we currently provide: - [Router Path Selection](tests.path_selection.md) - [Routing Generic](tests.routing.generic.md) - [Routing BGP](tests.routing.bgp.md) +- [Routing ISIS](tests.routing.isis.md) - [Routing OSPF](tests.routing.ospf.md) - [Security](tests.security.md) - [Services](tests.services.md) diff --git a/docs/api/tests.routing.bgp.md b/docs/api/tests.routing.bgp.md index 5c5467879..4537ec24b 100644 --- a/docs/api/tests.routing.bgp.md +++ b/docs/api/tests.routing.bgp.md @@ -18,3 +18,4 @@ anta_title: ANTA catalog for BGP tests filters: - "!test" - "!render" + - "!^_[^_]" diff --git a/docs/api/tests.routing.isis.md b/docs/api/tests.routing.isis.md index b545f33a7..bf50c72e7 100644 --- a/docs/api/tests.routing.isis.md +++ b/docs/api/tests.routing.isis.md @@ -18,3 +18,4 @@ anta_title: ANTA catalog for IS-IS tests filters: - "!test" - "!render" + - "!^_[^_]" diff --git a/docs/api/tests.routing.ospf.md b/docs/api/tests.routing.ospf.md index a01eb5011..2fd0cd410 100644 --- a/docs/api/tests.routing.ospf.md +++ b/docs/api/tests.routing.ospf.md @@ -18,3 +18,4 @@ anta_title: ANTA catalog for OSPF tests filters: - "!test" - "!render" + - "!^_[^_]" diff --git a/docs/cli/debug.md b/docs/cli/debug.md index 60ac74f69..4c864db0f 100644 --- a/docs/cli/debug.md +++ b/docs/cli/debug.md @@ -15,7 +15,7 @@ The ANTA CLI includes a set of debugging tools, making it easier to build and te These tools are especially helpful in building the tests, as they give a visual access to the output received from the eAPI. They also facilitate the extraction of output content for use in unit tests, as described in our [contribution guide](../contribution.md). !!! warning - The `debug` tools require a device from your inventory. Thus, you MUST use a valid [ANTA Inventory](../usage-inventory-catalog.md#device-inventory). + The `debug` tools require a device from your inventory. Thus, you must use a valid [ANTA Inventory](../usage-inventory-catalog.md#device-inventory). ## Executing an EOS command @@ -160,11 +160,11 @@ Run templated command 'show vlan {vlan_id}' with {'vlan_id': '10'} on DC1-LEAF1A } ``` +### Example of multiple arguments + !!! warning If multiple arguments of the same key are provided, only the last argument value will be kept in the template parameters. -### Example of multiple arguments - ```bash anta -log DEBUG debug run-template --template "ping {dst} source {src}" dst "8.8.8.8" src Loopback0 --device DC1-SPINE1     > {'dst': '8.8.8.8', 'src': 'Loopback0'} diff --git a/docs/cli/get-inventory-information.md b/docs/cli/get-inventory-information.md index 6fe9dc94d..ab1bebcd3 100644 --- a/docs/cli/get-inventory-information.md +++ b/docs/cli/get-inventory-information.md @@ -7,9 +7,55 @@ anta_title: Retrieving Inventory Information ~ that can be found in the LICENSE file. --> -The ANTA CLI offers multiple entrypoints to access data from your local inventory. +The ANTA CLI offers multiple commands to access data from your local inventory. -## Inventory used of examples +## List devices in inventory + +This command will list all devices available in the inventory. Using the `--tags` option, you can filter this list to only include devices with specific tags (visit [this page](tag-management.md) to learn more about tags). The `--connected` option allows to display only the devices where a connection has been established. + +### Command overview + +```bash +Usage: anta get inventory [OPTIONS] + + Show inventory loaded in ANTA. + +Options: + -u, --username TEXT Username to connect to EOS [env var: + ANTA_USERNAME; required] + -p, --password TEXT Password to connect to EOS that must be + provided. It can be prompted using '--prompt' + option. [env var: ANTA_PASSWORD] + --enable-password TEXT Password to access EOS Privileged EXEC mode. + It can be prompted using '--prompt' option. + Requires '--enable' option. [env var: + ANTA_ENABLE_PASSWORD] + --enable Some commands may require EOS Privileged EXEC + mode. This option tries to access this mode + before sending a command to the device. [env + var: ANTA_ENABLE] + -P, --prompt Prompt for passwords if they are not + provided. [env var: ANTA_PROMPT] + --timeout 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] + --connected / --not-connected Display inventory after connection has been + created + --help Show this message and exit. +``` + +!!! tip + By default, `anta get inventory` only provides information that doesn't rely on a device connection. If you are interested in obtaining connection-dependent details, like the hardware model, use the `--connected` option. + +### Example Let's consider the following inventory: @@ -66,122 +112,15 @@ anta_inventory: tags: ["BL", "DC2"] ``` -## Obtaining all configured tags - -As most of ANTA's commands accommodate tag filtering, this particular command is useful for enumerating all tags configured in the inventory. Running the `anta get tags` command will return a list of all tags that have been configured in the inventory. - -### Command overview - -```bash -Usage: anta get tags [OPTIONS] - - Get list of configured tags in user inventory. - -Options: - -u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME; - required] - -p, --password TEXT Password to connect to EOS that must be provided. It - can be prompted using '--prompt' option. [env var: - ANTA_PASSWORD] - --enable-password TEXT Password to access EOS Privileged EXEC mode. It can - be prompted using '--prompt' option. Requires '-- - enable' option. [env var: ANTA_ENABLE_PASSWORD] - --enable Some commands may require EOS Privileged EXEC mode. - This option tries to access this mode before sending - a command to the device. [env var: ANTA_ENABLE] - -P, --prompt Prompt for passwords if they are not provided. [env - var: ANTA_PROMPT] - --timeout 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] - --help Show this message and exit. -``` - -### Example - -To get the list of all configured tags in the inventory, run the following command: - -```bash -anta get tags -Tags found: -[ - "BL", - "DC1", - "DC2", - "LEAF", - "SPINE" -] - -* note that tag all has been added by anta -``` - -!!! note - Even if you haven't explicitly configured the `all` tag in the inventory, it is automatically added. This default tag allows to execute commands on all devices in the inventory when no tag is specified. - -## List devices in inventory - -This command will list all devices available in the inventory. Using the `--tags` option, you can filter this list to only include devices with specific tags. The `--connected` option allows to display only the devices where a connection has been established. - -### Command overview - -```bash -Usage: anta get inventory [OPTIONS] - - Show inventory loaded in ANTA. - -Options: - -u, --username TEXT Username to connect to EOS [env var: - ANTA_USERNAME; required] - -p, --password TEXT Password to connect to EOS that must be - provided. It can be prompted using '--prompt' - option. [env var: ANTA_PASSWORD] - --enable-password TEXT Password to access EOS Privileged EXEC mode. - It can be prompted using '--prompt' option. - Requires '--enable' option. [env var: - ANTA_ENABLE_PASSWORD] - --enable Some commands may require EOS Privileged EXEC - mode. This option tries to access this mode - before sending a command to the device. [env - var: ANTA_ENABLE] - -P, --prompt Prompt for passwords if they are not - provided. [env var: ANTA_PROMPT] - --timeout 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] - --connected / --not-connected Display inventory after connection has been - created - --help Show this message and exit. -``` - -!!! tip - In its default mode, `anta get inventory` provides only information that doesn't rely on a device connection. If you are interested in obtaining connection-dependent details, like the hardware model, please use the `--connected` option. - -### Example - To retrieve a comprehensive list of all devices along with their details, execute the following command. It will provide all the data loaded into the ANTA inventory from your [inventory file](../usage-inventory-catalog.md). ```bash -anta get inventory --tags SPINE +$ anta get inventory --tags SPINE Current inventory content is: { 'DC1-SPINE1': AsyncEOSDevice( name='DC1-SPINE1', - tags=['SPINE', 'DC1'], + tags={'DC1-SPINE1', 'DC1', 'SPINE'}, hw_model=None, is_online=False, established=False, @@ -189,13 +128,12 @@ Current inventory content is: host='172.20.20.101', eapi_port=443, username='arista', - enable=True, - enable_password='arista', + enable=False, insecure=False ), 'DC1-SPINE2': AsyncEOSDevice( name='DC1-SPINE2', - tags=['SPINE', 'DC1'], + tags={'DC1', 'SPINE', 'DC1-SPINE2'}, hw_model=None, is_online=False, established=False, @@ -203,12 +141,12 @@ Current inventory content is: host='172.20.20.102', eapi_port=443, username='arista', - enable=True, + enable=False, insecure=False ), 'DC2-SPINE1': AsyncEOSDevice( name='DC2-SPINE1', - tags=['SPINE', 'DC2'], + tags={'DC2', 'DC2-SPINE1', 'SPINE'}, hw_model=None, is_online=False, established=False, @@ -216,12 +154,12 @@ Current inventory content is: host='172.20.20.201', eapi_port=443, username='arista', - enable=True, + enable=False, insecure=False ), 'DC2-SPINE2': AsyncEOSDevice( name='DC2-SPINE2', - tags=['SPINE', 'DC2'], + tags={'DC2', 'DC2-SPINE2', 'SPINE'}, hw_model=None, is_online=False, established=False, @@ -229,7 +167,7 @@ Current inventory content is: host='172.20.20.202', eapi_port=443, username='arista', - enable=True, + enable=False, insecure=False ) } diff --git a/docs/cli/nrfu.md b/docs/cli/nrfu.md index 6c360b7f9..0f2b42524 100644 --- a/docs/cli/nrfu.md +++ b/docs/cli/nrfu.md @@ -9,10 +9,12 @@ anta_title: Execute Network Readiness For Use (NRFU) Testing ANTA provides a set of commands for performing NRFU tests on devices. These commands are under the `anta nrfu` namespace and offer multiple output format options: -- [Text view](#performing-nrfu-with-text-rendering) -- [Table view](#performing-nrfu-with-table-rendering) -- [JSON view](#performing-nrfu-with-json-rendering) -- [Custom template view](#performing-nrfu-with-custom-reports) +- [Text report](#performing-nrfu-with-text-rendering) +- [Table report](#performing-nrfu-with-table-rendering) +- [JSON report](#performing-nrfu-with-json-rendering) +- [Custom template report](#performing-nrfu-with-custom-reports) +- [CSV report](#performing-nrfu-and-saving-results-in-a-csv-file) +- [Markdown report](#performing-nrfu-and-saving-results-in-a-markdown-file) ## NRFU Command overview @@ -29,16 +31,7 @@ All commands under the `anta nrfu` namespace require a catalog yaml file specifi ### Tag management -The `--tags` option can be used to target specific devices in your inventory and run only tests configured with this specific tags from your catalog. The default tag is set to `all` and is implicit. Expected behaviour is provided below: - -| Command | Description | -| ------- | ----------- | -| `none` | Run all tests on all devices according `tag` definition in your inventory and test catalog. And tests with no tag are executed on all devices| -| `--tags leaf` | Run all tests marked with `leaf` tag on all devices configured with `leaf` tag.
All other tags are ignored | -| `--tags leaf,spine` | Run all tests marked with `leaf` tag on all devices configured with `leaf` tag.
Run all tests marked with `spine` tag on all devices configured with `spine` tag.
All other tags are ignored | - -!!! info - [More examples](tag-management.md) available on this dedicated page. +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. Refer to the [dedicated page](tag-management.md) for more information. ### Device and test filtering diff --git a/docs/cli/tag-management.md b/docs/cli/tag-management.md index 9a74b7f83..ad5ccf3ab 100644 --- a/docs/cli/tag-management.md +++ b/docs/cli/tag-management.md @@ -31,7 +31,7 @@ anta_inventory: Each device also has its own name automatically added as a tag: ```bash -anta get inventory +$ anta get inventory Current inventory content is: { 'leaf1': AsyncEOSDevice( @@ -170,7 +170,7 @@ In this case, only `leaf` devices defined in the inventory are used to run tests It is possible to use multiple tags using the `--tags tag1,tag2` syntax. ```bash -anta nrfu --tags leaf,spine text +$ anta nrfu --tags leaf,spine text ╭────────────────────── Settings ──────────────────────╮ │ - ANTA Inventory contains 3 devices (AsyncEOSDevice) │ │ - Tests catalog contains 11 tests │ @@ -197,3 +197,57 @@ spine1 :: VerifyUptime :: SUCCESS spine1 :: VerifyL3MTU :: SUCCESS spine1 :: VerifyUptime :: SUCCESS ``` + +## Obtaining all configured tags + +As most ANTA commands accommodate tag filtering, this command is useful for enumerating all tags configured in the inventory. Running the `anta get tags` command will return a list of all tags configured in the inventory. + +### Command overview + +```bash +Usage: anta get tags [OPTIONS] + + Get list of configured tags in user inventory. + +Options: + -u, --username TEXT Username to connect to EOS [env var: ANTA_USERNAME; + required] + -p, --password TEXT Password to connect to EOS that must be provided. It + can be prompted using '--prompt' option. [env var: + ANTA_PASSWORD] + --enable-password TEXT Password to access EOS Privileged EXEC mode. It can + be prompted using '--prompt' option. Requires '-- + enable' option. [env var: ANTA_ENABLE_PASSWORD] + --enable Some commands may require EOS Privileged EXEC mode. + This option tries to access this mode before sending + a command to the device. [env var: ANTA_ENABLE] + -P, --prompt Prompt for passwords if they are not provided. [env + var: ANTA_PROMPT] + --timeout 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] + --help Show this message and exit. +``` + +### Example + +To get the list of all configured tags in the inventory, run the following command: + +```bash +$ anta get tags +Tags found: +[ + "leaf", + "leaf1", + "leaf2", + "spine", + "spine1" +] +``` diff --git a/docs/faq.md b/docs/faq.md index 2d2ea6544..7a5866337 100644 --- a/docs/faq.md +++ b/docs/faq.md @@ -1,5 +1,6 @@ --- -toc_depth: 2 +toc_depth: 3 +anta_title: Frequently Asked Questions (FAQ) --- -# Frequently Asked Questions (FAQ) - ## A local OS error occurred while connecting to a device ???+ faq "A local OS error occurred while connecting to a device" diff --git a/docs/stylesheets/extra.material.css b/docs/stylesheets/extra.material.css index 44e7c1350..2476f8cf0 100644 --- a/docs/stylesheets/extra.material.css +++ b/docs/stylesheets/extra.material.css @@ -133,7 +133,7 @@ } .md-typeset h4 { - font-size: 0.9rem; + font-size: 1.1rem; margin: 1em 0; font-weight: 700; letter-spacing: -.01em; @@ -149,7 +149,6 @@ letter-spacing: -.01em; color: var(--md-default-fg-color--light); font-style: italic; - text-decoration: underline; } .md-typeset table:not([class]) th { diff --git a/docs/usage-inventory-catalog.md b/docs/usage-inventory-catalog.md index e180496ee..e41321ae5 100644 --- a/docs/usage-inventory-catalog.md +++ b/docs/usage-inventory-catalog.md @@ -314,33 +314,7 @@ Once you run `anta nrfu table`, you will see following output: The following script reads all the files in `intended/test_catalogs/` with names `-catalog.yml` and merge them together inside one big catalog `anta-catalog.yml` using the new `AntaCatalog.merge_catalogs()` class method. ```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__": - catalogs = [] - for file in Path(CATALOG_DIR).glob("*" + CATALOG_SUFFIX): - device = str(file).removesuffix(CATALOG_SUFFIX).removeprefix(CATALOG_DIR) - print(f"Loading test catalog for device {device}") - catalog = AntaCatalog.parse(file) - # Add the device name as a tag to all tests in the catalog - for test in catalog.tests: - test.inputs.filters = AntaTest.Input.Filters(tags={device}) - catalogs.append(catalog) - - # Merge all catalogs - merged_catalog = AntaCatalog.merge_catalogs(catalogs) - - # Save the merged catalog to a file - with open(Path('anta-catalog.yml'), "w") as f: - f.write(merged_catalog.dump().yaml()) +--8<-- "merge_catalogs.py" ``` !!! warning diff --git a/examples/README.md b/examples/README.md index b07cef28b..6fc1f4e9a 100644 --- a/examples/README.md +++ b/examples/README.md @@ -1,6 +1,6 @@ # ANTA Example files -This section provides some examples about how to use ANTA as listed in [the documentation](https://anta.arista.com) +This section provides some examples about how to use ANTA as listed in [the documentation](https://anta.arista.com). ## Device Inventory @@ -25,10 +25,28 @@ The file [eos-commands.yaml](eos-commands.yaml) is an example of input given wit - Filename: [`anta_runner.py`](./anta_runner.py) -The file is an example demonstrating how to run ANTA using a python script +The file is an example demonstrating how to run ANTA using a Python script. ## ANTA template for results rendering - Filename: [`template.j2`](./template.j2) -This file is a simple Jinja2 file to customize ANTA CLI output as documented in [anta documentation](https://anta.arista.com/stable/cli/nrfu/#performing-nrfu-with-custom-reports) \ No newline at end of file +This file is a simple Jinja2 file to customize ANTA CLI output as documented in [cli documentation](https://anta.arista.com/stable/cli/nrfu/#performing-nrfu-with-custom-reports). + +## Merge multiple catalogs + +- Filename: [`merge_catalogs.py`](./merge_catalogs.py) + +This file is an example demonstrating how to merge multiple catalogs into a single catalog and save it to a file, as documented in [usage test catalog](https://anta.arista.com/stable/usage-inventory-catalog/#example-script-to-merge-catalogs). + +## Run multiple commands + +- Filename: [`run_eos_commands.py`](./run_eos_commands.py) + +This file is an example demonstrating how to run multiple commands on multiple devices, as documented in [advanced usages](https://anta.arista.com/stable/advanced_usages/as-python-lib/#run-eos-commands). + +## Parse ANTA inventory file + +- Filename: [`parse_anta_inventory_file.py`](./parse_anta_inventory_file.py) + +This file is an example demonstrating how to parse an ANTA inventory file, as documented in [advanced usages](https://anta.arista.com/stable/advanced_usages/as-python-lib/#parse-anta-inventory-file). \ No newline at end of file diff --git a/examples/merge_catalogs.py b/examples/merge_catalogs.py new file mode 100644 index 000000000..1d594be40 --- /dev/null +++ b/examples/merge_catalogs.py @@ -0,0 +1,30 @@ +# 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. +"""Script that merge a collection of catalogs into one AntaCatalog.""" + +from pathlib import Path + +from anta.catalog import AntaCatalog +from anta.models import AntaTest + +CATALOG_SUFFIX = "-catalog.yml" +CATALOG_DIR = "intended/test_catalogs/" + +if __name__ == "__main__": + catalogs = [] + for file in Path(CATALOG_DIR).glob("*" + CATALOG_SUFFIX): + device = str(file).removesuffix(CATALOG_SUFFIX).removeprefix(CATALOG_DIR) + print(f"Loading test catalog for device {device}") + catalog = AntaCatalog.parse(file) + # Add the device name as a tag to all tests in the catalog + for test in catalog.tests: + test.inputs.filters = AntaTest.Input.Filters(tags={device}) + catalogs.append(catalog) + + # Merge all catalogs + merged_catalog = AntaCatalog.merge_catalogs(catalogs) + + # Save the merged catalog to a file + with Path("anta-catalog.yml").open("w") as f: + f.write(merged_catalog.dump().yaml()) diff --git a/examples/parse_anta_inventory_file.py b/examples/parse_anta_inventory_file.py new file mode 100644 index 000000000..fbbe04286 --- /dev/null +++ b/examples/parse_anta_inventory_file.py @@ -0,0 +1,34 @@ +# 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. +"""Script that parses an ANTA inventory file, connects to devices and print their status.""" + +import asyncio + +from anta.inventory import AntaInventory + + +async def main(inv: AntaInventory) -> None: + """Read an AntaInventory and try to connect to every device in the inventory. + + Print a message for every device connection status + """ + await inv.connect_inventory() + + for device in inv.values(): + if device.established: + print(f"Device {device.name} is online") + else: + print(f"Could not connect to device {device.name}") + + +if __name__ == "__main__": + # Create the AntaInventory instance + inventory = AntaInventory.parse( + filename="inventory.yaml", + username="arista", + password="@rista123", + ) + + # Run the main coroutine + res = asyncio.run(main(inventory)) diff --git a/examples/run_eos_commands.py b/examples/run_eos_commands.py new file mode 100644 index 000000000..165220f86 --- /dev/null +++ b/examples/run_eos_commands.py @@ -0,0 +1,59 @@ +# 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. +"""Script that runs a list of EOS commands on reachable devices.""" + +# This is needed to run the script for python < 3.10 for typing annotations +from __future__ import annotations + +import asyncio +from pprint import pprint + +from anta.inventory import AntaInventory +from anta.models import AntaCommand + + +async def main(inv: AntaInventory, commands: list[str]) -> dict[str, list[AntaCommand]]: + """Run a list of commands against each valid device in the inventory. + + Take an AntaInventory and a list of commands as string + 1. try to connect to every device in the inventory + 2. collect the results of the commands from each device + + Returns + ------- + dict[str, list[AntaCommand]] + a dictionary where key is the device name and the value is the list of AntaCommand ran towards the device + """ + await inv.connect_inventory() + + # Make a list of coroutine to run commands towards each connected device + coros = [] + # dict to keep track of the commands per device + result_dict = {} + for name, device in inv.get_inventory(established_only=True).items(): + anta_commands = [AntaCommand(command=command, ofmt="json") for command in commands] + result_dict[name] = anta_commands + coros.append(device.collect_commands(anta_commands)) + + # Run the coroutines + await asyncio.gather(*coros) + + return result_dict + + +if __name__ == "__main__": + # Create the AntaInventory instance + inventory = AntaInventory.parse( + filename="inventory.yaml", + username="arista", + password="@rista123", + ) + + # Create a list of commands with json output + command_list = ["show version", "show ip bgp summary"] + + # Run the main asyncio entry point + res = asyncio.run(main(inventory, command_list)) + + pprint(res) diff --git a/mkdocs.yml b/mkdocs.yml index dd417ded1..100042eac 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -230,7 +230,10 @@ nav: - Result Manager: - Result Manager module: api/result_manager.md - Result Manager models: api/result_manager_models.md - - Report Manager: api/report_manager.md + - Reporter: + - CSV reporter: api/csv_reporter.md + - Markdown reporter: api/md_reporter.md + - Other reporters: api/reporters.md - Runner: api/runner.md - Troubleshooting ANTA: troubleshooting.md - Contributions: contribution.md diff --git a/pyproject.toml b/pyproject.toml index 80a59e9ea..b72ec3a70 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -96,7 +96,8 @@ doc = [ "mkdocs-material-extensions>=1.3.1", "mkdocs-material>=9.5.34", "mkdocstrings[python]>=0.26.0", - "mkdocstrings-python>=1.11.0" + "mkdocstrings-python>=1.11.0", + "black>=24.10.0" ] [project.urls] @@ -435,10 +436,14 @@ runtime-evaluated-base-classes = ["pydantic.BaseModel", "anta.models.AntaTest.In "anta/inventory/__init__.py" = [ "PLR0913", # Ok to have more than 5 arguments in the AntaInventory class ] -"examples/anta_runner.py" = [ # This is an example script and linked in snippets - "S108", # Probable insecure usage of temporary file or directory +"examples/*.py" = [ # These are example scripts and linked in snippets "S105", # Possible hardcoded password + "S106", # Possible hardcoded password assigned to argument + "S108", # Probable insecure usage of temporary file or directory "INP001", # Implicit packages + "T201", # `print` found + "T203", # `pprint` found + ] ################################