Test models
Test definition¶
AntaTest ¶
AntaTest(
device: AntaDevice,
inputs: dict[str, Any] | AntaTest.Input | None = None,
eos_data: list[dict[Any, Any] | str] | None = None,
)
Bases: ABC
Abstract class defining a test in ANTA.
The goal of this class is to handle the heavy lifting and make writing a test as simple as possible.
Examples
The following is an example of an AntaTest subclass implementation:
class VerifyReachability(AntaTest):
name = "VerifyReachability"
description = "Test the network reachability to one or many destination IP(s)."
categories = ["connectivity"]
commands = [AntaTemplate(template="ping vrf {vrf} {dst} source {src} repeat 2")]
class Input(AntaTest.Input):
hosts: list[Host]
class Host(BaseModel):
dst: IPv4Address
src: IPv4Address
vrf: str = "default"
def render(self, template: AntaTemplate) -> list[AntaCommand]:
return [template.render(dst=host.dst, src=host.src, vrf=host.vrf) for host in self.inputs.hosts]
@AntaTest.anta_test
def test(self) -> None:
failures = []
for command in self.instance_commands:
src, dst = command.params.src, command.params.dst
if "2 received" not in command.json_output["messages"][0]:
failures.append((str(src), str(dst)))
if not failures:
self.result.is_success()
else:
self.result.is_failure(f"Connectivity test failed for the following source-destination pairs: {failures}")
Attributes:
Name | Type | Description |
---|---|---|
device |
AntaDevice
|
AntaDevice instance on which this test is run. |
inputs |
Input
|
AntaTest.Input instance carrying the test inputs. |
instance_commands |
list[AntaCommand]
|
List of AntaCommand instances of this test. |
result |
TestResult
|
TestResult instance representing the result of this test. |
logger |
Logger
|
Python logger for this test instance. |
Parameters:
Name | Type | Description | Default |
---|---|---|---|
device |
AntaDevice
|
AntaDevice instance on which the test will be run. |
required |
inputs |
dict[str, Any] | Input | None
|
Dictionary of attributes used to instantiate the AntaTest.Input instance. |
None
|
eos_data |
list[dict[Any, Any] | str] | None
|
Populate outputs of the test commands instead of collecting from devices.
This list must have the same length and order than the |
None
|
Source code in anta/models.py
403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 |
|
failed_commands
property
¶
failed_commands: list[AntaCommand]
Return a list of all the commands that have failed.
Input ¶
Bases: BaseModel
Class defining inputs for a test in ANTA.
Examples
A valid test catalog will look like the following:
<Python module>:
- <AntaTest subclass>:
result_overwrite:
categories:
- "Overwritten category 1"
description: "Test with overwritten description"
custom_field: "Test run by John Doe"
Attributes:
Name | Type | Description |
---|---|---|
result_overwrite |
ResultOverwrite | None
|
Define fields to overwrite in the TestResult object. |
Filters ¶
ResultOverwrite ¶
Bases: BaseModel
Test inputs model to overwrite result fields.
Attributes:
Name | Type | Description |
---|---|---|
description |
str | None
|
Overwrite |
categories |
list[str] | None
|
Overwrite |
custom_field |
str | None
|
A free string that will be included in the TestResult object. |
__hash__ ¶
__hash__() -> int
Implement generic hashing for AntaTest.Input.
This will work in most cases but this does not consider 2 lists with different ordering as equal.
Source code in anta/models.py
365 366 367 368 369 370 |
|
anta_test
staticmethod
¶
anta_test(
function: F,
) -> Callable[..., Coroutine[Any, Any, TestResult]]
Decorate the test()
method in child classes.
This decorator implements (in this order):
- Instantiate the command outputs if
eos_data
is provided to thetest()
method - Collect the commands from the device
- Run the
test()
method - Catches any exception in
test()
user code and set theresult
instance attribute
Source code in anta/models.py
569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 |
|
collect
async
¶
collect() -> None
Collect outputs of all commands of this test class from the device of this test instance.
Source code in anta/models.py
556 557 558 559 560 561 562 563 564 565 566 567 |
|
render ¶
render(template: AntaTemplate) -> list[AntaCommand]
Render an AntaTemplate instance of this AntaTest using the provided AntaTest.Input instance at self.inputs.
This is not an abstract method because it does not need to be implemented if there is no AntaTemplate for this test.
Source code in anta/models.py
530 531 532 533 534 535 536 537 538 |
|
save_commands_data ¶
save_commands_data(
eos_data: list[dict[str, Any] | str]
) -> None
Populate output of all AntaCommand instances in instance_commands
.
Source code in anta/models.py
496 497 498 499 500 501 502 503 504 505 |
|
test
abstractmethod
¶
test() -> Coroutine[Any, Any, TestResult]
Core of the test logic.
This is an abstractmethod that must be implemented by child classes.
It must set the correct status of the result
instance attribute with the appropriate outcome of the test.
Examples
It must be implemented using the AntaTest.anta_test
decorator:
@AntaTest.anta_test
def test(self) -> None:
self.result.is_success()
for command in self.instance_commands:
if not self._test_command(command): # _test_command() is an arbitrary test logic
self.result.is_failure("Failure reason")
Source code in anta/models.py
653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 |
|
Command definition¶
AntaCommand ¶
Bases: BaseModel
Class to define a command.
Info
eAPI models are revisioned, this means that if a model is modified in a non-backwards compatible way, then its revision will be bumped up (revisions are numbers, default value is 1).
By default an eAPI request will return revision 1 of the model instance, this ensures that older management software will not suddenly stop working when a switch is upgraded. A revision applies to a particular CLI command whereas a version is global and is internally translated to a specific revision for each CLI command in the RPC.
Revision has precedence over version.
Attributes:
Name | Type | Description |
---|---|---|
command |
str
|
Device command. |
version |
Literal[1, 'latest']
|
eAPI version - valid values are 1 or “latest”. |
revision |
Revision | None
|
eAPI revision of the command. Valid values are 1 to 99. Revision has precedence over version. |
ofmt |
Literal['json', 'text']
|
eAPI output - json or text. |
output |
dict[str, Any] | str | None
|
Output of the command. Only defined if there was no errors. |
template |
AntaTemplate | None
|
AntaTemplate object used to render this command. |
errors |
list[str]
|
If the command execution fails, eAPI returns a list of strings detailing the error(s). |
params |
AntaParamsBaseModel
|
Pydantic Model containing the variables values used to render the template. |
use_cache |
bool
|
Enable or disable caching for this AntaCommand if the AntaDevice supports it. |
collected
property
¶
collected: bool
Return True if the command has been collected, False otherwise.
A command that has not been collected could have returned an error. See error property.
requires_privileges
property
¶
requires_privileges: bool
Return True if the command requires privileged mode, False otherwise.
Raises:
Type | Description |
---|---|
RuntimeError
|
If the command has not been collected and has not returned an error. AntaDevice.collect() must be called before this property. |
supported
property
¶
supported: bool
Return True if the command is supported on the device hardware platform, False otherwise.
Raises:
Type | Description |
---|---|
RuntimeError
|
If the command has not been collected and has not returned an error. AntaDevice.collect() must be called before this property. |
Warning
CLI commands are protected to avoid execution of critical commands such as reload
or write erase
.
- Reload command:
^reload\s*\w*
- Configure mode:
^conf\w*\s*(terminal|session)*
- Write:
^wr\w*\s*\w+
Template definition¶
AntaTemplate ¶
AntaTemplate(
template: str,
version: Literal[1, "latest"] = "latest",
revision: Revision | None = None,
ofmt: Literal["json", "text"] = "json",
*,
use_cache: bool = True
)
Class to define a command template as Python f-string.
Can render a command from parameters.
Attributes:
Name | Type | Description |
---|---|---|
template |
Python f-string. Example: ‘show vlan {vlan_id}’. |
|
version |
eAPI version - valid values are 1 or “latest”. |
|
revision |
Revision of the command. Valid values are 1 to 99. Revision has precedence over version. |
|
ofmt |
eAPI output - json or text. |
|
use_cache |
Enable or disable caching for this AntaTemplate if the AntaDevice supports it. |
Source code in anta/models.py
65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 |
|
__repr__ ¶
__repr__() -> str
Return the representation of the class.
Copying pydantic model style, excluding params_schema
Source code in anta/models.py
90 91 92 93 94 95 |
|
render ¶
render(**params: str | int | bool) -> AntaCommand
Render an AntaCommand from an AntaTemplate instance.
Keep the parameters used in the AntaTemplate instance.
Parameters:
Name | Type | Description | Default |
---|---|---|---|
params |
str | int | bool
|
Dictionary of variables with string values to render the Python f-string. |
{}
|
Returns:
Type | Description |
---|---|
AntaCommand
|
The rendered AntaCommand. This AntaCommand instance have a template attribute that references this AntaTemplate instance. |
Raises:
Type | Description |
---|---|
AntaTemplateRenderError
|
If a parameter is missing to render the AntaTemplate instance. |
Source code in anta/models.py
97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 |
|