anta/anta/result_manager/models.py
Daniel Baumann 8a6a3342fc
Merging upstream version 1.3.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
2025-03-17 07:33:51 +01:00

161 lines
4.5 KiB
Python

# Copyright (c) 2023-2025 Arista Networks, Inc.
# Use of this source code is governed by the Apache License 2.0
# that can be found in the LICENSE file.
"""Models related to anta.result_manager module."""
from __future__ import annotations
from dataclasses import dataclass, field
from enum import Enum
from pydantic import BaseModel
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):
"""Describe the result of a test from a single device.
Attributes
----------
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.
"""
name: str
test: str
categories: list[str]
description: str
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.
Parameters
----------
message
Optional message related to the test.
"""
self._set_status(AntaTestStatus.SUCCESS, message)
def is_failure(self, message: str | None = None) -> None:
"""Set status to failure.
Parameters
----------
message
Optional message related to the test.
"""
self._set_status(AntaTestStatus.FAILURE, message)
def is_skipped(self, message: str | None = None) -> None:
"""Set status to skipped.
Parameters
----------
message
Optional message related to the test.
"""
self._set_status(AntaTestStatus.SKIPPED, message)
def is_error(self, message: str | None = None) -> None:
"""Set status to error.
Parameters
----------
message
Optional message related to the test.
"""
self._set_status(AntaTestStatus.ERROR, message)
def _set_status(self, status: AntaTestStatus, message: str | None = None) -> None:
"""Set status and insert optional message.
Parameters
----------
status
Status of the test.
message
Optional message.
"""
self.result = status
if message is not None:
self.messages.append(message)
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)