Merging upstream version 1.1.0.

Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
Daniel Baumann 2025-02-05 11:54:55 +01:00
parent 50f8dbf7e8
commit 2044ea6182
Signed by: daniel
GPG key ID: FBB4F0E80A80222F
196 changed files with 10121 additions and 3780 deletions

View file

@ -5,9 +5,27 @@
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from pydantic import BaseModel
from anta.custom_types import TestStatus
class AntaTestStatus(str, Enum):
"""Test status Enum for the TestResult.
NOTE: This could be updated to StrEnum when Python 3.11 is the minimum supported version in ANTA.
"""
UNSET = "unset"
SUCCESS = "success"
FAILURE = "failure"
ERROR = "error"
SKIPPED = "skipped"
def __str__(self) -> str:
"""Override the __str__ method to return the value of the Enum, mimicking the behavior of StrEnum."""
return self.value
class TestResult(BaseModel):
@ -15,13 +33,20 @@ class TestResult(BaseModel):
Attributes
----------
name: Device name where the test has run.
test: Test name runs on the device.
categories: List of categories the TestResult belongs to, by default the AntaTest categories.
description: TestResult description, by default the AntaTest description.
result: Result of the test. Can be one of "unset", "success", "failure", "error" or "skipped".
messages: Message to report after the test if any.
custom_field: Custom field to store a string for flexibility in integrating with ANTA
name : str
Name of the device where the test was run.
test : str
Name of the test run on the device.
categories : list[str]
List of categories the TestResult belongs to. Defaults to the AntaTest categories.
description : str
Description of the TestResult. Defaults to the AntaTest description.
result : AntaTestStatus
Result of the test. Must be one of the AntaTestStatus Enum values: unset, success, failure, error or skipped.
messages : list[str]
Messages to report after the test, if any.
custom_field : str | None
Custom field to store a string for flexibility in integrating with ANTA.
"""
@ -29,57 +54,63 @@ class TestResult(BaseModel):
test: str
categories: list[str]
description: str
result: TestStatus = "unset"
result: AntaTestStatus = AntaTestStatus.UNSET
messages: list[str] = []
custom_field: str | None = None
def is_success(self, message: str | None = None) -> None:
"""Set status to success.
Args:
----
message: Optional message related to the test
Parameters
----------
message
Optional message related to the test.
"""
self._set_status("success", message)
self._set_status(AntaTestStatus.SUCCESS, message)
def is_failure(self, message: str | None = None) -> None:
"""Set status to failure.
Args:
----
message: Optional message related to the test
Parameters
----------
message
Optional message related to the test.
"""
self._set_status("failure", message)
self._set_status(AntaTestStatus.FAILURE, message)
def is_skipped(self, message: str | None = None) -> None:
"""Set status to skipped.
Args:
----
message: Optional message related to the test
Parameters
----------
message
Optional message related to the test.
"""
self._set_status("skipped", message)
self._set_status(AntaTestStatus.SKIPPED, message)
def is_error(self, message: str | None = None) -> None:
"""Set status to error.
Args:
----
message: Optional message related to the test
Parameters
----------
message
Optional message related to the test.
"""
self._set_status("error", message)
self._set_status(AntaTestStatus.ERROR, message)
def _set_status(self, status: TestStatus, message: str | None = None) -> None:
def _set_status(self, status: AntaTestStatus, message: str | None = None) -> None:
"""Set status and insert optional message.
Args:
----
status: status of the test
message: optional message
Parameters
----------
status
Status of the test.
message
Optional message.
"""
self.result = status
@ -89,3 +120,42 @@ class TestResult(BaseModel):
def __str__(self) -> str:
"""Return a human readable string of this TestResult."""
return f"Test '{self.test}' (on '{self.name}'): Result '{self.result}'\nMessages: {self.messages}"
# Pylint does not treat dataclasses differently: https://github.com/pylint-dev/pylint/issues/9058
# pylint: disable=too-many-instance-attributes
@dataclass
class DeviceStats:
"""Device statistics for a run of tests."""
tests_success_count: int = 0
tests_skipped_count: int = 0
tests_failure_count: int = 0
tests_error_count: int = 0
tests_unset_count: int = 0
tests_failure: set[str] = field(default_factory=set)
categories_failed: set[str] = field(default_factory=set)
categories_skipped: set[str] = field(default_factory=set)
@dataclass
class CategoryStats:
"""Category statistics for a run of tests."""
tests_success_count: int = 0
tests_skipped_count: int = 0
tests_failure_count: int = 0
tests_error_count: int = 0
tests_unset_count: int = 0
@dataclass
class TestStats:
"""Test statistics for a run of tests."""
devices_success_count: int = 0
devices_skipped_count: int = 0
devices_failure_count: int = 0
devices_error_count: int = 0
devices_unset_count: int = 0
devices_failure: set[str] = field(default_factory=set)