feat: add config manager module with YAML loading for settings and services
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
44
backend/modules/config_manager.py
Normal file
44
backend/modules/config_manager.py
Normal file
@@ -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 = {}
|
||||||
0
backend/tests/__init__.py
Normal file
0
backend/tests/__init__.py
Normal file
93
backend/tests/test_config_manager.py
Normal file
93
backend/tests/test_config_manager.py
Normal file
@@ -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"
|
||||||
Reference in New Issue
Block a user