Adding upstream version 1.1.0.
Signed-off-by: Daniel Baumann <daniel@debian.org>
This commit is contained in:
parent
f13b7abbd8
commit
77504588ab
196 changed files with 10121 additions and 3780 deletions
119
anta/runner.py
119
anta/runner.py
|
@ -40,7 +40,8 @@ def adjust_rlimit_nofile() -> tuple[int, int]:
|
|||
|
||||
Returns
|
||||
-------
|
||||
tuple[int, int]: The new soft and hard limits for open file descriptors.
|
||||
tuple[int, int]
|
||||
The new soft and hard limits for open file descriptors.
|
||||
"""
|
||||
try:
|
||||
nofile = int(os.environ.get("ANTA_NOFILE", DEFAULT_NOFILE))
|
||||
|
@ -50,7 +51,7 @@ def adjust_rlimit_nofile() -> tuple[int, int]:
|
|||
|
||||
limits = resource.getrlimit(resource.RLIMIT_NOFILE)
|
||||
logger.debug("Initial limit numbers for open file descriptors for the current ANTA process: Soft Limit: %s | Hard Limit: %s", limits[0], limits[1])
|
||||
nofile = nofile if limits[1] > nofile else limits[1]
|
||||
nofile = min(limits[1], nofile)
|
||||
logger.debug("Setting soft limit for open file descriptors for the current ANTA process to %s", nofile)
|
||||
resource.setrlimit(resource.RLIMIT_NOFILE, (nofile, limits[1]))
|
||||
return resource.getrlimit(resource.RLIMIT_NOFILE)
|
||||
|
@ -59,9 +60,10 @@ def adjust_rlimit_nofile() -> tuple[int, int]:
|
|||
def log_cache_statistics(devices: list[AntaDevice]) -> None:
|
||||
"""Log cache statistics for each device in the inventory.
|
||||
|
||||
Args:
|
||||
----
|
||||
devices: List of devices in the inventory.
|
||||
Parameters
|
||||
----------
|
||||
devices
|
||||
List of devices in the inventory.
|
||||
"""
|
||||
for device in devices:
|
||||
if device.cache_statistics is not None:
|
||||
|
@ -78,15 +80,21 @@ def log_cache_statistics(devices: list[AntaDevice]) -> None:
|
|||
async def setup_inventory(inventory: AntaInventory, tags: set[str] | None, devices: set[str] | None, *, established_only: bool) -> AntaInventory | None:
|
||||
"""Set up the inventory for the ANTA run.
|
||||
|
||||
Args:
|
||||
----
|
||||
inventory: AntaInventory object that includes the device(s).
|
||||
tags: Tags to filter devices from the inventory.
|
||||
devices: Devices on which to run tests. None means all devices.
|
||||
Parameters
|
||||
----------
|
||||
inventory
|
||||
AntaInventory object that includes the device(s).
|
||||
tags
|
||||
Tags to filter devices from the inventory.
|
||||
devices
|
||||
Devices on which to run tests. None means all devices.
|
||||
established_only
|
||||
If True use return only devices where a connection is established.
|
||||
|
||||
Returns
|
||||
-------
|
||||
AntaInventory | None: The filtered inventory or None if there are no devices to run tests on.
|
||||
AntaInventory | None
|
||||
The filtered inventory or None if there are no devices to run tests on.
|
||||
"""
|
||||
if len(inventory) == 0:
|
||||
logger.info("The inventory is empty, exiting")
|
||||
|
@ -116,15 +124,20 @@ def prepare_tests(
|
|||
) -> defaultdict[AntaDevice, set[AntaTestDefinition]] | None:
|
||||
"""Prepare the tests to run.
|
||||
|
||||
Args:
|
||||
----
|
||||
inventory: AntaInventory object that includes the device(s).
|
||||
catalog: AntaCatalog object that includes the list of tests.
|
||||
tests: Tests to run against devices. None means all tests.
|
||||
tags: Tags to filter devices from the inventory.
|
||||
Parameters
|
||||
----------
|
||||
inventory
|
||||
AntaInventory object that includes the device(s).
|
||||
catalog
|
||||
AntaCatalog object that includes the list of tests.
|
||||
tests
|
||||
Tests to run against devices. None means all tests.
|
||||
tags
|
||||
Tags to filter devices from the inventory.
|
||||
|
||||
Returns
|
||||
-------
|
||||
defaultdict[AntaDevice, set[AntaTestDefinition]] | None
|
||||
A mapping of devices to the tests to run or None if there are no tests to run.
|
||||
"""
|
||||
# Build indexes for the catalog. If `tests` is set, filter the indexes based on these tests
|
||||
|
@ -133,21 +146,20 @@ def prepare_tests(
|
|||
# Using a set to avoid inserting duplicate tests
|
||||
device_to_tests: defaultdict[AntaDevice, set[AntaTestDefinition]] = defaultdict(set)
|
||||
|
||||
# Create AntaTestRunner tuples from the tags
|
||||
# Create the device to tests mapping from the tags
|
||||
for device in inventory.devices:
|
||||
if tags:
|
||||
# If there are CLI tags, only execute tests with matching tags
|
||||
device_to_tests[device].update(catalog.get_tests_by_tags(tags))
|
||||
if not any(tag in device.tags for tag in tags):
|
||||
# The device does not have any selected tag, skipping
|
||||
continue
|
||||
else:
|
||||
# If there is no CLI tags, execute all tests that do not have any tags
|
||||
device_to_tests[device].update(catalog.tag_to_tests[None])
|
||||
|
||||
# Then add the tests with matching tags from device tags
|
||||
device_to_tests[device].update(catalog.get_tests_by_tags(device.tags))
|
||||
# Add the tests with matching tags from device tags
|
||||
device_to_tests[device].update(catalog.get_tests_by_tags(device.tags))
|
||||
|
||||
catalog.final_tests_count += len(device_to_tests[device])
|
||||
|
||||
if catalog.final_tests_count == 0:
|
||||
if len(device_to_tests.values()) == 0:
|
||||
msg = (
|
||||
f"There are no tests{f' matching the tags {tags} ' if tags else ' '}to run in the current test catalog and device inventory, please verify your inputs."
|
||||
)
|
||||
|
@ -157,15 +169,19 @@ def prepare_tests(
|
|||
return device_to_tests
|
||||
|
||||
|
||||
def get_coroutines(selected_tests: defaultdict[AntaDevice, set[AntaTestDefinition]]) -> list[Coroutine[Any, Any, TestResult]]:
|
||||
def get_coroutines(selected_tests: defaultdict[AntaDevice, set[AntaTestDefinition]], manager: ResultManager) -> list[Coroutine[Any, Any, TestResult]]:
|
||||
"""Get the coroutines for the ANTA run.
|
||||
|
||||
Args:
|
||||
----
|
||||
selected_tests: A mapping of devices to the tests to run. The selected tests are generated by the `prepare_tests` function.
|
||||
Parameters
|
||||
----------
|
||||
selected_tests
|
||||
A mapping of devices to the tests to run. The selected tests are generated by the `prepare_tests` function.
|
||||
manager
|
||||
A ResultManager
|
||||
|
||||
Returns
|
||||
-------
|
||||
list[Coroutine[Any, Any, TestResult]]
|
||||
The list of coroutines to run.
|
||||
"""
|
||||
coros = []
|
||||
|
@ -173,13 +189,14 @@ def get_coroutines(selected_tests: defaultdict[AntaDevice, set[AntaTestDefinitio
|
|||
for test in test_definitions:
|
||||
try:
|
||||
test_instance = test.test(device=device, inputs=test.inputs)
|
||||
manager.add(test_instance.result)
|
||||
coros.append(test_instance.test())
|
||||
except Exception as e: # noqa: PERF203, pylint: disable=broad-exception-caught
|
||||
except Exception as e: # noqa: PERF203, BLE001
|
||||
# An AntaTest instance is potentially user-defined code.
|
||||
# We need to catch everything and exit gracefully with an error message.
|
||||
message = "\n".join(
|
||||
[
|
||||
f"There is an error when creating test {test.test.module}.{test.test.__name__}.",
|
||||
f"There is an error when creating test {test.test.__module__}.{test.test.__name__}.",
|
||||
f"If this is not a custom test implementation: {GITHUB_SUGGESTION}",
|
||||
],
|
||||
)
|
||||
|
@ -199,22 +216,29 @@ async def main( # noqa: PLR0913
|
|||
established_only: bool = True,
|
||||
dry_run: bool = False,
|
||||
) -> None:
|
||||
# pylint: disable=too-many-arguments
|
||||
"""Run ANTA.
|
||||
|
||||
Use this as an entrypoint to the test framework in your script.
|
||||
ResultManager object gets updated with the test results.
|
||||
|
||||
Args:
|
||||
----
|
||||
manager: ResultManager object to populate with the test results.
|
||||
inventory: AntaInventory object that includes the device(s).
|
||||
catalog: AntaCatalog object that includes the list of tests.
|
||||
devices: Devices on which to run tests. None means all devices. These may come from the `--device / -d` CLI option in NRFU.
|
||||
tests: Tests to run against devices. None means all tests. These may come from the `--test / -t` CLI option in NRFU.
|
||||
tags: Tags to filter devices from the inventory. These may come from the `--tags` CLI option in NRFU.
|
||||
established_only: Include only established device(s).
|
||||
dry_run: Build the list of coroutine to run and stop before test execution.
|
||||
Parameters
|
||||
----------
|
||||
manager
|
||||
ResultManager object to populate with the test results.
|
||||
inventory
|
||||
AntaInventory object that includes the device(s).
|
||||
catalog
|
||||
AntaCatalog object that includes the list of tests.
|
||||
devices
|
||||
Devices on which to run tests. None means all devices. These may come from the `--device / -d` CLI option in NRFU.
|
||||
tests
|
||||
Tests to run against devices. None means all tests. These may come from the `--test / -t` CLI option in NRFU.
|
||||
tags
|
||||
Tags to filter devices from the inventory. These may come from the `--tags` CLI option in NRFU.
|
||||
established_only
|
||||
Include only established device(s).
|
||||
dry_run
|
||||
Build the list of coroutine to run and stop before test execution.
|
||||
"""
|
||||
# Adjust the maximum number of open file descriptors for the ANTA process
|
||||
limits = adjust_rlimit_nofile()
|
||||
|
@ -233,25 +257,26 @@ async def main( # noqa: PLR0913
|
|||
selected_tests = prepare_tests(selected_inventory, catalog, tests, tags)
|
||||
if selected_tests is None:
|
||||
return
|
||||
final_tests_count = sum(len(tests) for tests in selected_tests.values())
|
||||
|
||||
run_info = (
|
||||
"--- ANTA NRFU Run Information ---\n"
|
||||
f"Number of devices: {len(inventory)} ({len(selected_inventory)} established)\n"
|
||||
f"Total number of selected tests: {catalog.final_tests_count}\n"
|
||||
f"Total number of selected tests: {final_tests_count}\n"
|
||||
f"Maximum number of open file descriptors for the current ANTA process: {limits[0]}\n"
|
||||
"---------------------------------"
|
||||
)
|
||||
|
||||
logger.info(run_info)
|
||||
|
||||
if catalog.final_tests_count > limits[0]:
|
||||
if final_tests_count > limits[0]:
|
||||
logger.warning(
|
||||
"The number of concurrent tests is higher than the open file descriptors limit for this ANTA process.\n"
|
||||
"Errors may occur while running the tests.\n"
|
||||
"Please consult the ANTA FAQ."
|
||||
)
|
||||
|
||||
coroutines = get_coroutines(selected_tests)
|
||||
coroutines = get_coroutines(selected_tests, manager)
|
||||
|
||||
if dry_run:
|
||||
logger.info("Dry-run mode, exiting before running the tests.")
|
||||
|
@ -263,8 +288,6 @@ async def main( # noqa: PLR0913
|
|||
AntaTest.nrfu_task = AntaTest.progress.add_task("Running NRFU Tests...", total=len(coroutines))
|
||||
|
||||
with Catchtime(logger=logger, message="Running ANTA tests"):
|
||||
test_results = await asyncio.gather(*coroutines)
|
||||
for r in test_results:
|
||||
manager.add(r)
|
||||
await asyncio.gather(*coroutines)
|
||||
|
||||
log_cache_statistics(selected_inventory.devices)
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue