diff --git a/gso/services/librenms_client.py b/gso/services/librenms_client.py index 5ade04c620629ded19fcd31c2bc08cf56711d3cd..c700c92fc349afdb6521c65d0ef6720548f78597 100644 --- a/gso/services/librenms_client.py +++ b/gso/services/librenms_client.py @@ -91,22 +91,26 @@ class LibreNMSClient: return device.json() - def validate_device(self, fqdn: str) -> list[str]: + def validate_device(self, fqdn: str) -> str | None: """Validate a device in LibreNMS by fetching the record match the queried :term:`FQDN` against its hostname. :param str fqdn: The :term:`FQDN` of the host that is validated. :return list[str]: A list of errors, if empty the device is successfully validated. """ - errors = [] + error = None try: device = self.get_device(fqdn) + received_hostname = device["devices"][0]["hostname"] - if device["devices"][0]["hostname"] != fqdn: - errors.append("Device hostname in LibreNMS does not match FQDN.") + if received_hostname != fqdn: + error = ( + f"Device hostname in LibreNMS does not match FQDN.\n" + f"Expected '{fqdn}' but got '{received_hostname}'." + ) except HTTPError as e: if e.response.status_code == HTTPStatus.NOT_FOUND: - errors.append("Device does not exist in LibreNMS.") + error = "Device does not exist in LibreNMS." else: raise - return errors + return error diff --git a/gso/workflows/router/validate_router.py b/gso/workflows/router/validate_router.py index f6b38b0393ad7ff5ba119ee0028988f8180f3efe..1bedf16f2c432957d86703b674fe74361c503551 100644 --- a/gso/workflows/router/validate_router.py +++ b/gso/workflows/router/validate_router.py @@ -54,7 +54,9 @@ def check_librenms_entry_exists(subscription: Router) -> None: Raises an HTTP error 404 when the device is not present in LibreNMS. """ client = LibreNMSClient() - client.get_device(subscription.router.router_fqdn) + errors = client.validate_device(subscription.router.router_fqdn) + if errors: + raise ProcessFailureError(message="LibreNMS configuration error", details=errors) @step("Check base config for drift") diff --git a/test/services/test_librenms_client.py b/test/services/test_librenms_client.py index d07da93a1be847be29c267c4c2188b5533a0af65..7668ddea0ad41a31b2fa92e5462eb2931da3207b 100644 --- a/test/services/test_librenms_client.py +++ b/test/services/test_librenms_client.py @@ -447,15 +447,13 @@ def test_validate_device_success(mock_get_device_success): def test_validate_device_non_existing(mock_get_device_not_found): client = LibreNMSClient() - errors = client.validate_device("localhost") + error = client.validate_device("localhost") - assert len(errors) == 1 - assert errors[0] == "Device does not exist in LibreNMS." + assert error == "Device does not exist in LibreNMS." def test_validate_device_misconfigured(mock_get_device_misconfigured): client = LibreNMSClient() - errors = client.validate_device("localhost") + error = client.validate_device("localhost") - assert len(errors) == 1 - assert errors[0] == "Device hostname in LibreNMS does not match FQDN." + assert error == "Device hostname in LibreNMS does not match FQDN.\nExpected 'localhost' but got '127.0.0.1'." diff --git a/test/workflows/router/test_validate_router.py b/test/workflows/router/test_validate_router.py index d603d53769e9f56ce1948e5c1e8d438ed08bc992..98ac2ad979e3cbb05ada44233214b3341c92001a 100644 --- a/test/workflows/router/test_validate_router.py +++ b/test/workflows/router/test_validate_router.py @@ -16,9 +16,9 @@ from test.workflows import ( @patch("gso.services.infoblox.find_host_by_fqdn") @patch("gso.services.lso_client.execute_playbook") @patch("gso.services.netbox_client.NetboxClient.get_device_by_name") -@patch("gso.services.librenms_client.LibreNMSClient.get_device") +@patch("gso.services.librenms_client.LibreNMSClient.validate_device") def test_validate_nokia_router_success( - mock_get_librenms_device, + mock_validate_librenms_device, mock_get_device_by_name, mock_execute_playbook, mock_find_host_by_fqdn, @@ -27,6 +27,7 @@ def test_validate_nokia_router_success( data_config_filename, geant_partner, ): + mock_validate_librenms_device.return_value = None # Run workflow subscription_id = nokia_router_subscription_factory() mock_fqdn = Router.from_subscription(subscription_id).router.router_fqdn @@ -65,7 +66,7 @@ def test_validate_nokia_router_success( assert mock_execute_playbook.call_count == 2 assert mock_find_host_by_fqdn.call_count == 1 assert mock_get_device_by_name.call_count == 1 - assert mock_get_librenms_device.call_count == 1 + assert mock_validate_librenms_device.call_count == 1 assert "ipam_warning" not in state