From 2158dddb09b8312a2763d97e87e930b7c4d61148 Mon Sep 17 00:00:00 2001 From: "I. Alcaraz Salazar" Date: Sun, 15 Feb 2026 08:57:32 +0000 Subject: [PATCH] feat: add config manager module with YAML loading for settings and services Co-Authored-By: Claude Opus 4.6 --- backend/modules/config_manager.py | 44 +++++++++++++ backend/tests/__init__.py | 0 backend/tests/test_config_manager.py | 93 ++++++++++++++++++++++++++++ 3 files changed, 137 insertions(+) create mode 100644 backend/modules/config_manager.py create mode 100644 backend/tests/__init__.py create mode 100644 backend/tests/test_config_manager.py diff --git a/backend/modules/config_manager.py b/backend/modules/config_manager.py new file mode 100644 index 0000000..e18650f --- /dev/null +++ b/backend/modules/config_manager.py @@ -0,0 +1,44 @@ +from pathlib import Path +from typing import Any + +import yaml + + +class ConfigManager: + def __init__(self, settings_path: str, services_path: str): + self._settings_path = settings_path + self._services_path = services_path + self._settings: dict[str, Any] = {} + self._services: dict[str, Any] = {} + + def _load_yaml(self, path: str) -> dict[str, Any]: + p = Path(path) + if not p.exists(): + return {} + with open(p) as f: + return yaml.safe_load(f) or {} + + def get_settings(self) -> dict[str, Any]: + if not self._settings: + self._settings = self._load_yaml(self._settings_path) + return self._settings + + def get_nodes(self) -> list[dict[str, Any]]: + if not self._services: + self._services = self._load_yaml(self._services_path) + return self._services.get("nodes", []) + + def get_node_by_ip(self, ip: str) -> dict[str, Any] | None: + for node in self.get_nodes(): + if node.get("ip") == ip: + return node + return None + + def get_network_scan_config(self) -> dict[str, Any]: + if not self._services: + self._services = self._load_yaml(self._services_path) + return self._services.get("network_scan", {}) + + def reload(self) -> None: + self._settings = {} + self._services = {} diff --git a/backend/tests/__init__.py b/backend/tests/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/backend/tests/test_config_manager.py b/backend/tests/test_config_manager.py new file mode 100644 index 0000000..3ed5c24 --- /dev/null +++ b/backend/tests/test_config_manager.py @@ -0,0 +1,93 @@ +import os +import tempfile +import pytest +import yaml +from modules.config_manager import ConfigManager + + +@pytest.fixture +def sample_settings(tmp_path): + settings = { + "display": { + "resolution": "3840x2160", + "rotation_interval_seconds": 30, + "transition": "fade", + "theme": "dark", + }, + "odoo": { + "url": "http://localhost:8069", + "database": "test_db", + "username": "admin", + "password": "admin", + }, + "refresh": { + "odoo_minutes": 5, + "network_minutes": 10, + "ping_seconds": 60, + }, + } + path = tmp_path / "settings.yaml" + path.write_text(yaml.dump(settings)) + return str(path) + + +@pytest.fixture +def sample_services(tmp_path): + services = { + "nodes": [ + { + "name": "Router", + "ip": "192.168.1.1", + "username": "admin", + "password": "pass", + "icon": "router", + "connections": [], + }, + { + "name": "Server", + "ip": "192.168.1.10", + "username": "root", + "password": "secret", + "public_url": "https://example.com", + "icon": "server", + "connections": ["Router"], + }, + ], + "network_scan": { + "enabled": True, + "subnet": "192.168.1.0/24", + "interval_minutes": 10, + }, + } + path = tmp_path / "services.yaml" + path.write_text(yaml.dump(services)) + return str(path) + + +def test_load_settings(sample_settings): + cm = ConfigManager(settings_path=sample_settings, services_path="dummy") + settings = cm.get_settings() + assert settings["odoo"]["database"] == "test_db" + assert settings["display"]["rotation_interval_seconds"] == 30 + + +def test_load_services(sample_services): + cm = ConfigManager(settings_path="dummy", services_path=sample_services) + nodes = cm.get_nodes() + assert len(nodes) == 2 + assert nodes[0]["name"] == "Router" + assert nodes[1]["public_url"] == "https://example.com" + + +def test_get_node_by_ip(sample_services): + cm = ConfigManager(settings_path="dummy", services_path=sample_services) + node = cm.get_node_by_ip("192.168.1.10") + assert node["name"] == "Server" + assert cm.get_node_by_ip("10.0.0.1") is None + + +def test_get_network_scan_config(sample_services): + cm = ConfigManager(settings_path="dummy", services_path=sample_services) + scan = cm.get_network_scan_config() + assert scan["enabled"] is True + assert scan["subnet"] == "192.168.1.0/24"