diff --git a/main/404.html b/main/404.html index 89b6e0c19..7dc1f64e8 100644 --- a/main/404.html +++ b/main/404.html @@ -16,7 +16,7 @@ - + @@ -2103,7 +2103,7 @@

404 - Not found

- + diff --git a/main/advanced_usages/as-python-lib/index.html b/main/advanced_usages/as-python-lib/index.html index 13b885cfa..4f07b7818 100644 --- a/main/advanced_usages/as-python-lib/index.html +++ b/main/advanced_usages/as-python-lib/index.html @@ -20,7 +20,7 @@ - + @@ -798,23 +798,23 @@
  • - + - Use tests from ANTA + Examples -
  • @@ -2241,23 +2207,23 @@
  • - + - Use tests from ANTA + Examples -
  • The parse() static method creates an AntaInventory instance from a YAML file and returns it. The devices are AsyncEOSDevice instances.
  • -

    To parse a YAML inventory file and print the devices connection status:

    +

    Examples

    +
    Parse an ANTA inventory file
    +
    +

    This script parses an ANTA inventory file, connects to devices and print their status

    +
    """
     Example
     """
    @@ -2415,7 +2351,10 @@ 

    dedicated section for how to use inventory and catalog files.

    -

    To run an EOS commands list on the reachable devices from the inventory: +

    Run EOS commands
    +
    +

    This script runs a list of EOS commands on reachable devices

    +
    """
     Example
     """
    @@ -2470,152 +2409,7 @@ 

    res = asyncio.run(main(inventory, commands)) pprint(res) -

    -

    Use tests from ANTA

    -

    All the test classes inherit from the same abstract Base Class AntaTest. The Class definition indicates which commands are required for the test and the user should focus only on writing the test function with optional keywords argument. The instance of the class upon creation instantiates a TestResult object that can be accessed later on to check the status of the test ([unset, skipped, success, failure, error]).

    -

    Test structure

    -

    All tests are built on a class named AntaTest which provides a complete toolset for a test:

    -
      -
    • Object creation
    • -
    • Test definition
    • -
    • TestResult definition
    • -
    • Abstracted method to collect data
    • -
    -

    This approach means each time you create a test it will be based on this AntaTest class. Besides that, you will have to provide some elements:

    -
      -
    • name: Name of the test
    • -
    • description: A human readable description of your test
    • -
    • categories: a list of categories to sort test.
    • -
    • commands: a list of command to run. This list must be a list of AntaCommand which is described in the next part of this document.
    • -
    -

    Here is an example of a hardware test related to device temperature:

    -
    from __future__ import annotations
    -
    -import logging
    -from typing import Any, Dict, List, Optional, cast
    -
    -from anta.models import AntaTest, AntaCommand
    -
    -
    -class VerifyTemperature(AntaTest):
    -    """
    -    Verifies device temparture is currently OK.
    -    """
    -
    -    # The test name
    -    name = "VerifyTemperature"
    -    # A small description of the test, usually the first line of the class docstring
    -    description = "Verifies device temparture is currently OK"
    -    # The category of the test, usually the module name
    -    categories = ["hardware"]
    -    # The command(s) used for the test. Could be a template instead
    -    commands = [AntaCommand(command="show system environment temperature", ofmt="json")]
    -
    -    # Decorator
    -    @AntaTest.anta_test
    -    # abstract method that must be defined by the child Test class
    -    def test(self) -> None:
    -        """Run VerifyTemperature validation"""
    -        command_output = cast(Dict[str, Dict[Any, Any]], self.instance_commands[0].output)
    -        temperature_status = command_output["systemStatus"] if "systemStatus" in command_output.keys() else ""
    -        if temperature_status == "temperatureOk":
    -            self.result.is_success()
    -        else:
    -            self.result.is_failure(f"Device temperature is not OK, systemStatus: {temperature_status }")
    -
    -

    When you run the test, object will automatically call its anta.models.AntaTest.collect() method to get device output for each command if no pre-collected data was given to the test. This method does a loop to call anta.inventory.models.InventoryDevice.collect() methods which is in charge of managing device connection and how to get data.

    -
    -run test offline -

    You can also pass eos data directly to your test if you want to validate data collected in a different workflow. An example is provided below just for information:

    -
    test = VerifyTemperature(device, eos_data=test_data["eos_data"])
    -asyncio.run(test.test())
    -
    -
    -

    The test function is always the same and must be defined with the @AntaTest.anta_test decorator. This function takes at least one argument which is a anta.inventory.models.InventoryDevice object. -In some cases a test would rely on some additional inputs from the user, for instance the number of expected peers or some expected numbers. All parameters must come with a default value and the test function should validate the parameters values (at this stage this is the only place where validation can be done but there are future plans to make this better).

    -
    class VerifyTemperature(AntaTest):
    -    ...
    -    @AntaTest.anta_test
    -    def test(self) -> None:
    -        pass
    -
    -class VerifyTransceiversManufacturers(AntaTest):
    -    ...
    -    @AntaTest.anta_test
    -    def test(self, manufacturers: Optional[List[str]] = None) -> None:
    -        # validate the manufactures parameter
    -        pass
    -
    -

    The test itself does not return any value, but the result is directly 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.
    • -
    • test (str): Test name runs on the device.
    • -
    • categories (List[str]): List of categories the TestResult belongs to, by default the AntaTest categories.
    • -
    • description (str): TestResult description, by default the AntaTest description.
    • -
    • results (str): Result of the test. Can be one of [“unset”, “success”, “failure”, “error”, “skipped”].
    • -
    • message (str, optional): Message to report after the test if any.
    • -
    • custom_field (str, optional): Custom field to store a string for flexibility in integrating with ANTA
    • -
    -
    from anta.tests.hardware import VerifyTemperature
    -
    -test = VerifyTemperature(device, eos_data=test_data["eos_data"])
    -asyncio.run(test.test())
    -assert test.result.result == "success"
    -
    -

    Classes for commands

    -

    To make it easier to get data, ANTA defines 2 different classes to manage commands to send to devices:

    -
    AntaCommand Class
    -

    Represent a command with following information:

    -
      -
    • Command to run
    • -
    • Output format expected
    • -
    • eAPI version
    • -
    • Output of the command
    • -
    -

    Usage example:

    -
    from anta.models import AntaCommand
    -
    -cmd1 = AntaCommand(command="show zerotouch")
    -cmd2 = AntaCommand(command="show running-config diffs", ofmt="text")
    -
    -
    -

    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 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, integrations with existing tools are not broken. This is done by using by default version=1 in eAPI calls.
    • -
    -

    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 VerifyBFDPeersHealth test leverages the first revision of show bfd peers:

    -
    # revision 1 as later revision introduce additional nesting for type
    -commands = [AntaCommand(command="show bfd peers", revision=1)]
    -
    -
    -
    AntaTemplate Class
    -

    Because some command can require more dynamic than just a command with no parameter provided by user, ANTA supports command template: you define a template in your test class and user provide parameters when creating test object.

    -
    class RunArbitraryTemplateCommand(AntaTest):
    -    """
    -    Run an EOS command and return result
    -    Based on AntaTest to build relevant output for pytest
    -    """
    -
    -    name = "Run aributrary EOS command"
    -    description = "To be used only with anta debug commands"
    -    template = AntaTemplate(template="show interfaces {ifd}")
    -    categories = ["debug"]
    -
    -    @AntaTest.anta_test
    -    def test(self) -> None:
    -        errdisabled_interfaces = [interface for interface, value in response["interfaceStatuses"].items() if value["linkStatus"] == "errdisabled"]
    -        ...
    -
    -
    -params = [{"ifd": "Ethernet2"}, {"ifd": "Ethernet49/1"}]
    -run_command1 = RunArbitraryTemplateCommand(device_anta, params)
     
    -

    In this example, test waits for interfaces to check from user setup and will only check for interfaces in params

    @@ -2636,7 +2430,7 @@
    - September 11, 2024 + September 18, 2024 @@ -2732,7 +2526,7 @@
    - + diff --git a/main/advanced_usages/caching/index.html b/main/advanced_usages/caching/index.html index 4a1c0d164..ec8fb97a8 100644 --- a/main/advanced_usages/caching/index.html +++ b/main/advanced_usages/caching/index.html @@ -20,7 +20,7 @@ - + @@ -2414,7 +2414,7 @@

    Disable caching in a chi

    - + diff --git a/main/advanced_usages/custom-tests/index.html b/main/advanced_usages/custom-tests/index.html index bb72459b9..467a72d60 100644 --- a/main/advanced_usages/custom-tests/index.html +++ b/main/advanced_usages/custom-tests/index.html @@ -20,7 +20,7 @@ - + @@ -2943,6 +2943,21 @@

    Class definition) ] +
    +

    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 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, integrations with existing tools are not broken. This is done by using by default version=1 in eAPI calls.
    • +
    +

    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 VerifyBFDPeersHealth test leverages the first revision of show bfd peers:

    +
    # revision 1 as later revision introduce additional nesting for type
    +commands = [AntaCommand(command="show bfd peers", revision=1)]
    +
    +

    Inputs definition

    If the user needs to provide inputs for your test, you need to define a pydantic model that defines the schema of the test inputs:

    class <YourTestName>(AntaTest):
    @@ -3083,7 +3098,7 @@ 

    Access your custom tests i - June 11, 2024 + September 18, 2024 @@ -3179,7 +3194,7 @@

    Access your custom tests i

    - + diff --git a/main/api/catalog/index.html b/main/api/catalog/index.html index 0e852e689..5ec0510d9 100644 --- a/main/api/catalog/index.html +++ b/main/api/catalog/index.html @@ -20,7 +20,7 @@ - + @@ -4383,7 +4383,7 @@

    module_name = f".{module_name}" # noqa: PLW2901 try: module: ModuleType = importlib.import_module(name=module_name, package=package) - except Exception as e: # pylint: disable=broad-exception-caught + except Exception as e: # A test module is potentially user-defined code. # We need to catch everything if we want to have meaningful logs module_str = f"{module_name[1:] if module_name.startswith('.') else module_name}{f' from package {package}' if package else ''}" @@ -4664,7 +4664,7 @@

    - + diff --git a/main/api/device/index.html b/main/api/device/index.html index be2118fad..9adabde70 100644 --- a/main/api/device/index.html +++ b/main/api/device/index.html @@ -20,7 +20,7 @@ - + @@ -1691,6 +1691,20 @@ + +
  • + + + __repr__ + + + + + +
  • + + +
  • @@ -1799,6 +1813,20 @@