From dd95d24d6309e72b67cc367f0eb262e4ee9ee611 Mon Sep 17 00:00:00 2001 From: Przemek Rogala Date: Tue, 12 Mar 2024 14:32:19 +0000 Subject: [PATCH] Add tests covering metric generators. --- .../tests/conftest.py | 52 ++++++++- .../tests/test_metrics.py | 104 ++++++++++++++++++ .../tests/test_views.py | 12 +- 3 files changed, 156 insertions(+), 12 deletions(-) create mode 100644 nautobot_device_lifecycle_mgmt/tests/test_metrics.py diff --git a/nautobot_device_lifecycle_mgmt/tests/conftest.py b/nautobot_device_lifecycle_mgmt/tests/conftest.py index 2160e36a..a2074a28 100644 --- a/nautobot_device_lifecycle_mgmt/tests/conftest.py +++ b/nautobot_device_lifecycle_mgmt/tests/conftest.py @@ -1,9 +1,17 @@ """Params for testing.""" from datetime import date -from nautobot.dcim.models import DeviceType, Manufacturer, Platform, Site, Device, DeviceRole, InventoryItem +from nautobot.dcim.models import ( + DeviceType, + Manufacturer, + Platform, + Site, + Device, + DeviceRole, + InventoryItem, +) from nautobot.extras.models import Status -from nautobot_device_lifecycle_mgmt.models import CVELCM, SoftwareLCM, ValidatedSoftwareLCM +from nautobot_device_lifecycle_mgmt.models import CVELCM, HardwareLCM, SoftwareLCM, ValidatedSoftwareLCM def create_devices(): @@ -12,7 +20,8 @@ def create_devices(): manufacturer, _ = Manufacturer.objects.get_or_create(name="Cisco", slug="cisco") device_type, _ = DeviceType.objects.get_or_create(manufacturer=manufacturer, model="6509-E", slug="6509-e") device_role, _ = DeviceRole.objects.get_or_create(name="Core Switch", slug="core-switch") - site, _ = Site.objects.get_or_create(name="Test 1", slug="test-1") + site1, _ = Site.objects.get_or_create(name="TestSite 1", slug="testsite-1") + site2, _ = Site.objects.get_or_create(name="TestSite 2", slug="testsite-2") status_active = Status.objects.get(slug="active") return ( @@ -21,7 +30,7 @@ def create_devices(): platform=device_platform, device_type=device_type, device_role=device_role, - site=site, + site=site1, status=status_active, ), Device.objects.create( @@ -29,7 +38,7 @@ def create_devices(): platform=device_platform, device_type=device_type, device_role=device_role, - site=site, + site=site1, status=status_active, ), Device.objects.create( @@ -37,7 +46,7 @@ def create_devices(): platform=device_platform, device_type=device_type, device_role=device_role, - site=site, + site=site2, status=status_active, ), ) @@ -145,3 +154,34 @@ def create_validated_softwares(): ) return validated_items + + +def create_inventory_item_hardware_notices(): + """Create inventory item hardware notices for tests.""" + + return ( + HardwareLCM.objects.create( + inventory_item="VS-S2T-10G", + end_of_sale=date(2022, 4, 1), + end_of_support=date(2023, 4, 1), + end_of_sw_releases=date(2024, 4, 1), + end_of_security_patches=date(2025, 4, 1), + documentation_url="https://test.com", + ), + HardwareLCM.objects.create( + inventory_item="QSFP-100G-SR4-S", + end_of_sale=date(2022, 4, 1), + end_of_support=date(2024, 1, 1), + end_of_sw_releases=date(2024, 4, 1), + end_of_security_patches=date(2025, 4, 1), + documentation_url="https://test.com", + ), + HardwareLCM.objects.create( + inventory_item="WS-X6548-GE-TX", + end_of_sale=date(2022, 4, 1), + end_of_support=date(2999, 1, 1), + end_of_sw_releases=date(2024, 4, 1), + end_of_security_patches=date(2025, 4, 1), + documentation_url="https://test.com", + ), + ) diff --git a/nautobot_device_lifecycle_mgmt/tests/test_metrics.py b/nautobot_device_lifecycle_mgmt/tests/test_metrics.py new file mode 100644 index 00000000..431a41fd --- /dev/null +++ b/nautobot_device_lifecycle_mgmt/tests/test_metrics.py @@ -0,0 +1,104 @@ +"""nautobot_device_lifecycle_mgmt test class for metrics.""" +from django.db import ProgrammingError +from django.test import TestCase + +from nautobot_device_lifecycle_mgmt.metrics import ( + metrics_lcm_hw_end_of_support, + metrics_lcm_validation_report_device_type, + metrics_lcm_validation_report_inventory_item, +) + +from .conftest import create_devices, create_inventory_item_hardware_notices, create_inventory_items + + +class MetricsTest(TestCase): + """Test class for Device Lifecycle metrics.""" + + def setUp(self): + create_inventory_items() + create_inventory_item_hardware_notices() + + def test_metrics_lcm_validation_report_device_type(self): + """Test metric device_software_compliance_gauge.""" + create_devices() + # TODO: Generate DeviceSoftwareValidationResult + metric_gen = metrics_lcm_validation_report_device_type() + metric = next(metric_gen) + + expected_ts_samples = { + (("device_type", "6509-E"), ("is_valid", "False")): 0, + (("device_type", "6509-E"), ("is_valid", "True")): 0, + } + + for sample in metric.samples: + sample_labels = tuple(sample.labels.items()) + self.assertEqual(expected_ts_samples[sample_labels], sample.value) + + def test_metrics_lcm_validation_report_inventory_item(self): + """Test metric inventory_item_software_compliance_gauge.""" + # TODO: Generate InventoryItemSoftwareValidationResult + metric_gen = metrics_lcm_validation_report_inventory_item() + metric = next(metric_gen) + + expected_ts_samples = { + (("inventory_item", "VS-S2T-10G"), ("is_valid", "False")): 0, + (("inventory_item", "QSFP-100G-SR4-S"), ("is_valid", "False")): 0, + (("inventory_item", "WS-X6548-GE-TX"), ("is_valid", "False")): 0, + (("inventory_item", "VS-S2T-10G"), ("is_valid", "True")): 0, + (("inventory_item", "QSFP-100G-SR4-S"), ("is_valid", "True")): 0, + (("inventory_item", "WS-X6548-GE-TX"), ("is_valid", "True")): 0, + } + + for sample in metric.samples: + sample_labels = tuple(sample.labels.items()) + self.assertEqual(expected_ts_samples[sample_labels], sample.value) + + def test_metrics_lcm_hw_end_of_support_does_not_error(self): + """Query providing data to hw_end_of_support_site_gauge metric should not error out. + Guards against https://github.com/nautobot/nautobot-app-device-lifecycle-mgmt/issues/309 + """ + metric_gen = metrics_lcm_hw_end_of_support() + # skip hw_end_of_support_part_number_gauge + next(metric_gen) + try: + # Get hw_end_of_support_site_gauge + next(metric_gen) + except ProgrammingError: + self.fail("hw_end_of_support_site_gauge query bug") + + def test_metrics_lcm_hw_end_of_support_part_number(self): + """Test metric hw_end_of_support_part_number_gauge.""" + metric_gen = metrics_lcm_hw_end_of_support() + + # Get hw_end_of_support_part_number_gauge + metric = next(metric_gen) + + expected_ts_samples = { + ("part_number", "6509-E"): 0, + ("part_number", "VS-S2T-10G"): 1, + ("part_number", "QSFP-100G-SR4-S"): 1, + ("part_number", "WS-X6548-GE-TX"): 0, + } + + for sample in metric.samples: + sample_labels = tuple(sample.labels.items())[0] + self.assertEqual(expected_ts_samples[sample_labels], sample.value) + + def test_metrics_lcm_hw_end_of_support_site_gauge(self): + """Test metric hw_end_of_support_site_gauge.""" + metric_gen = metrics_lcm_hw_end_of_support() + + # skip hw_end_of_support_part_number_gauge + next(metric_gen) + + # Get hw_end_of_support_site_gauge + metric = next(metric_gen) + + expected_ts_samples = { + ("site", "testsite-1"): 2, + ("site", "testsite-2"): 0, + } + + for sample in metric.samples: + sample_labels = tuple(sample.labels.items())[0] + self.assertEqual(expected_ts_samples[sample_labels], sample.value) diff --git a/nautobot_device_lifecycle_mgmt/tests/test_views.py b/nautobot_device_lifecycle_mgmt/tests/test_views.py index c487ca8d..e0cf205f 100644 --- a/nautobot_device_lifecycle_mgmt/tests/test_views.py +++ b/nautobot_device_lifecycle_mgmt/tests/test_views.py @@ -594,8 +594,8 @@ def test_contract_devices_export(self): self.assertEqual( response_body, "Contract Name,Contract Type,Device Name,Device Serial,Device Manufacturer,Device Site" - "\nCiscoHW1,Hardware,sw1,,Cisco,Test 1" - "\nCiscoHW1,Hardware,sw2,,Cisco,Test 1", + "\nCiscoHW1,Hardware,sw1,,Cisco,TestSite 1" + "\nCiscoHW1,Hardware,sw2,,Cisco,TestSite 1", ) contract2 = ContractLCM.objects.filter(name="AristaHW1").first() @@ -606,7 +606,7 @@ def test_contract_devices_export(self): self.assertEqual( response_body, "Contract Name,Contract Type,Device Name,Device Serial,Device Manufacturer,Device Site" - "\nAristaHW1,Hardware,sw3,,Cisco,Test 1", + "\nAristaHW1,Hardware,sw3,,Cisco,TestSite 2", ) def test_contract_inventoryitems_export(self): @@ -626,7 +626,7 @@ def test_contract_inventoryitems_export(self): self.assertEqual( response_body, "Contract Name,Contract Type,Item Name,Item Part ID,Item Serial,Item Manufacturer,Item Parent Device,Item Site" - "\nCiscoHW1,Hardware,SUP2T Card,VS-S2T-10G,,Cisco,sw1,Test 1", + "\nCiscoHW1,Hardware,SUP2T Card,VS-S2T-10G,,Cisco,sw1,TestSite 1", ) contract2 = ContractLCM.objects.filter(name="AristaHW1").first() @@ -637,8 +637,8 @@ def test_contract_inventoryitems_export(self): self.assertEqual( response_body, "Contract Name,Contract Type,Item Name,Item Part ID,Item Serial,Item Manufacturer,Item Parent Device,Item Site" - "\nAristaHW1,Hardware,100GBASE-SR4 QSFP Transceiver,QSFP-100G-SR4-S,,Cisco,sw2,Test 1" - "\nAristaHW1,Hardware,48x RJ-45 Line Card,WS-X6548-GE-TX,,Cisco,sw3,Test 1", + "\nAristaHW1,Hardware,100GBASE-SR4 QSFP Transceiver,QSFP-100G-SR4-S,,Cisco,sw2,TestSite 1" + "\nAristaHW1,Hardware,48x RJ-45 Line Card,WS-X6548-GE-TX,,Cisco,sw3,TestSite 2", )