From c6e6a39dba4d3109cb611a0e59c2dc41be4778bb Mon Sep 17 00:00:00 2001 From: Carl Baillargeon Date: Mon, 28 Oct 2024 15:16:29 -0400 Subject: [PATCH 1/2] fix(anta): Fix tags behavior --- anta/runner.py | 11 +++++++---- docs/cli/tag-management.md | 4 +--- tests/data/test_inventory_with_tags.yml | 2 +- tests/units/test_runner.py | 1 + 4 files changed, 10 insertions(+), 8 deletions(-) diff --git a/anta/runner.py b/anta/runner.py index 0147c3ccd..0e017cf74 100644 --- a/anta/runner.py +++ b/anta/runner.py @@ -149,17 +149,20 @@ def prepare_tests( # Create the device to tests mapping from the tags for device in inventory.devices: if tags: - if not any(tag in device.tags for tag in tags): + # If there are CLI tags, execute tests with matching tags for this device + matching_tags = tags.intersection(device.tags) + if not matching_tags: # The device does not have any selected tag, skipping continue + device_to_tests[device].update(catalog.get_tests_by_tags(matching_tags)) 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]) - # Add the tests with matching tags from device tags - device_to_tests[device].update(catalog.get_tests_by_tags(device.tags)) + # Then add the tests with matching tags from device tags + device_to_tests[device].update(catalog.get_tests_by_tags(device.tags)) - if len(device_to_tests.values()) == 0: + if sum(len(tests) for tests in 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." ) diff --git a/docs/cli/tag-management.md b/docs/cli/tag-management.md index ad5ccf3ab..4108d75bb 100644 --- a/docs/cli/tag-management.md +++ b/docs/cli/tag-management.md @@ -4,9 +4,7 @@ ~ that can be found in the LICENSE file. --> -ANTA commands can be used with a `--tags` option. This option **filters the inventory** with the specified tag(s) when running the command. - -Tags can also be used to **restrict a specific test** to a set of devices when using `anta nrfu`. +ANTA uses tags to define test-to-device mappings (tests run on devices with matching tags) and the `--tags` CLI option acts as a filter to execute specific test/device combinations. ## Defining tags diff --git a/tests/data/test_inventory_with_tags.yml b/tests/data/test_inventory_with_tags.yml index cbbcd75e6..16a9df4c0 100644 --- a/tests/data/test_inventory_with_tags.yml +++ b/tests/data/test_inventory_with_tags.yml @@ -3,7 +3,7 @@ anta_inventory: hosts: - name: leaf1 host: leaf1.anta.arista.com - tags: ["leaf"] + tags: ["leaf", "dc1"] - name: leaf2 host: leaf2.anta.arista.com tags: ["leaf"] diff --git a/tests/units/test_runner.py b/tests/units/test_runner.py index b80259cc3..8d19a4d1a 100644 --- a/tests/units/test_runner.py +++ b/tests/units/test_runner.py @@ -138,6 +138,7 @@ def side_effect_setrlimit(resource_id: int, limits: tuple[int, int]) -> None: pytest.param({"filename": "test_inventory_with_tags.yml"}, None, {"VerifyMlagStatus", "VerifyUptime"}, 3, 5, id="filtered-tests"), pytest.param({"filename": "test_inventory_with_tags.yml"}, {"leaf"}, {"VerifyMlagStatus", "VerifyUptime"}, 2, 4, id="1-tag-filtered-tests"), pytest.param({"filename": "test_inventory_with_tags.yml"}, {"invalid"}, None, 0, 0, id="invalid-tag"), + pytest.param({"filename": "test_inventory_with_tags.yml"}, {"dc1"}, None, 0, 0, id="device-tag-no-tests"), ], indirect=["inventory"], ) From 26448db8ac13546b25090311cfdc730ccf2c5eab Mon Sep 17 00:00:00 2001 From: Carl Baillargeon Date: Mon, 28 Oct 2024 15:33:56 -0400 Subject: [PATCH 2/2] Use total_test_count for better performance --- anta/runner.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/anta/runner.py b/anta/runner.py index 0e017cf74..947757aff 100644 --- a/anta/runner.py +++ b/anta/runner.py @@ -146,6 +146,8 @@ def prepare_tests( # Using a set to avoid inserting duplicate tests device_to_tests: defaultdict[AntaDevice, set[AntaTestDefinition]] = defaultdict(set) + total_test_count = 0 + # Create the device to tests mapping from the tags for device in inventory.devices: if tags: @@ -162,7 +164,9 @@ def prepare_tests( # Then add the tests with matching tags from device tags device_to_tests[device].update(catalog.get_tests_by_tags(device.tags)) - if sum(len(tests) for tests in device_to_tests.values()) == 0: + total_test_count += len(device_to_tests[device]) + + if total_test_count == 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." )