homelab_automation/tests/backend/test_routes_docker.py
Bruno Charest 68a9b0f390
Some checks failed
Tests / Backend Tests (Python) (3.10) (push) Has been cancelled
Tests / Backend Tests (Python) (3.11) (push) Has been cancelled
Tests / Backend Tests (Python) (3.12) (push) Has been cancelled
Tests / Frontend Tests (JS) (push) Has been cancelled
Tests / Integration Tests (push) Has been cancelled
Tests / All Tests Passed (push) Has been cancelled
Remove Node.js cache files containing npm vulnerability data for vitest and vite packages
2025-12-15 20:36:06 -05:00

316 lines
12 KiB
Python

"""Tests for Docker API routes."""
import pytest
from unittest.mock import AsyncMock, patch, MagicMock
from httpx import AsyncClient
class TestDockerHostsRoutes:
"""Tests for Docker hosts endpoints."""
@pytest.mark.asyncio
async def test_list_docker_hosts(self, client: AsyncClient, api_key_header):
"""Test listing Docker hosts."""
with patch('app.services.docker_service.docker_service.get_docker_hosts', new_callable=AsyncMock) as mock:
mock.return_value = [
{
"host_id": "host-1",
"host_name": "server1",
"host_ip": "192.168.1.10",
"docker_enabled": True,
"docker_version": "24.0.7",
"docker_status": "online",
"docker_last_collect_at": None,
"containers_total": 5,
"containers_running": 3,
"images_total": 10,
"volumes_total": 2,
"open_alerts": 0
},
{
"host_id": "host-2",
"host_name": "server2",
"host_ip": "192.168.1.11",
"docker_enabled": False,
"docker_version": None,
"docker_status": None,
"docker_last_collect_at": None,
"containers_total": 0,
"containers_running": 0,
"images_total": 0,
"volumes_total": 0,
"open_alerts": 0
}
]
response = await client.get("/api/docker/hosts", headers=api_key_header)
assert response.status_code == 200
data = response.json()
assert "hosts" in data
assert len(data["hosts"]) == 2
assert data["hosts"][0]["host_name"] == "server1"
hosts_by_id = {h["host_id"]: h for h in data["hosts"]}
assert hosts_by_id["host-1"]["docker_enabled"] is True
assert hosts_by_id["host-2"]["docker_enabled"] is False
@pytest.mark.asyncio
async def test_enable_docker_monitoring(self, client: AsyncClient, api_key_header):
"""Test enabling Docker monitoring on a host."""
with patch('app.services.docker_service.docker_service.enable_docker_monitoring', new_callable=AsyncMock) as mock:
mock.return_value = True
response = await client.post(
"/api/docker/hosts/host-1/enable",
headers=api_key_header,
json={"enabled": True}
)
assert response.status_code == 200
data = response.json()
assert "message" in data
@pytest.mark.asyncio
async def test_collect_docker_now(self, client: AsyncClient, api_key_header):
"""Test forcing Docker collection on a host."""
with patch('app.services.docker_service.docker_service.collect_docker_host', new_callable=AsyncMock) as mock:
mock.return_value = {
"success": True,
"host_id": "host-1",
"host_name": "server1",
"docker_version": "24.0.7",
"containers_count": 5,
"images_count": 10,
"volumes_count": 2,
"duration_ms": 1500,
"error": None
}
response = await client.post(
"/api/docker/hosts/host-1/collect",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["containers_count"] == 5
class TestDockerContainersRoutes:
"""Tests for Docker containers endpoints."""
@pytest.mark.asyncio
async def test_list_containers(self, client: AsyncClient, api_key_header, db_session):
"""Test listing containers for a host."""
# This test would require setting up container data in the database
# For now, test that the endpoint returns correctly structured data
response = await client.get(
"/api/docker/hosts/host-1/containers",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert "containers" in data
assert "total" in data
assert "running" in data
@pytest.mark.asyncio
async def test_start_container(self, client: AsyncClient, api_key_header):
"""Test starting a container."""
with patch('app.services.docker_actions.docker_actions.start_container', new_callable=AsyncMock) as mock:
mock.return_value = {
"success": True,
"message": "Container started successfully",
"container_id": "abc123",
"action": "start",
"output": "abc123",
"error": None
}
response = await client.post(
"/api/docker/containers/host-1/abc123/start",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["action"] == "start"
@pytest.mark.asyncio
async def test_stop_container(self, client: AsyncClient, api_key_header):
"""Test stopping a container."""
with patch('app.services.docker_actions.docker_actions.stop_container', new_callable=AsyncMock) as mock:
mock.return_value = {
"success": True,
"message": "Container stopped successfully",
"container_id": "abc123",
"action": "stop",
"output": "abc123",
"error": None
}
response = await client.post(
"/api/docker/containers/host-1/abc123/stop",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["action"] == "stop"
@pytest.mark.asyncio
async def test_restart_container(self, client: AsyncClient, api_key_header):
"""Test restarting a container."""
with patch('app.services.docker_actions.docker_actions.restart_container', new_callable=AsyncMock) as mock:
mock.return_value = {
"success": True,
"message": "Container restarted successfully",
"container_id": "abc123",
"action": "restart",
"output": "abc123",
"error": None
}
response = await client.post(
"/api/docker/containers/host-1/abc123/restart",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert data["success"] is True
assert data["action"] == "restart"
@pytest.mark.asyncio
async def test_get_container_logs(self, client: AsyncClient, api_key_header):
"""Test getting container logs."""
with patch('app.services.docker_actions.docker_actions.get_container_logs', new_callable=AsyncMock) as mock:
mock.return_value = {
"container_id": "abc123",
"container_name": "nginx",
"logs": "2024-01-15 10:00:00 Starting nginx...\n2024-01-15 10:00:01 Ready",
"lines": 2
}
response = await client.get(
"/api/docker/containers/host-1/abc123/logs?tail=100",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert "logs" in data
assert data["lines"] == 2
class TestDockerAlertsRoutes:
"""Tests for Docker alerts endpoints."""
@pytest.mark.asyncio
async def test_list_alerts(self, client: AsyncClient, api_key_header):
"""Test listing Docker alerts."""
with patch('app.services.docker_alerts.docker_alerts_service.get_alerts', new_callable=AsyncMock) as mock:
mock.return_value = {
"alerts": [
{
"id": 1,
"host_id": "host-1",
"host_name": "server1",
"container_name": "nginx",
"severity": "error",
"state": "open",
"message": "Container is down",
"opened_at": "2024-01-15T10:00:00Z"
}
],
"total": 1,
"open_count": 1,
"acknowledged_count": 0
}
response = await client.get(
"/api/docker/alerts",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert "alerts" in data
assert data["total"] == 1
assert data["open_count"] == 1
@pytest.mark.asyncio
async def test_acknowledge_alert(self, client: AsyncClient, api_key_header):
"""Test acknowledging an alert."""
with patch('app.services.docker_alerts.docker_alerts_service.acknowledge_alert', new_callable=AsyncMock) as mock:
mock.return_value = {
"id": 1,
"state": "acknowledged",
"acknowledged_by": "admin",
"acknowledged_at": "2024-01-15T10:30:00Z"
}
response = await client.post(
"/api/docker/alerts/1/acknowledge",
headers=api_key_header,
json={"note": "Investigating"}
)
assert response.status_code == 200
data = response.json()
assert "alert" in data
@pytest.mark.asyncio
async def test_close_alert(self, client: AsyncClient, api_key_header):
"""Test closing an alert."""
with patch('app.services.docker_alerts.docker_alerts_service.close_alert', new_callable=AsyncMock) as mock:
mock.return_value = {
"id": 1,
"state": "closed",
"closed_at": "2024-01-15T11:00:00Z"
}
response = await client.post(
"/api/docker/alerts/1/close",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert "alert" in data
class TestDockerStatsRoute:
"""Tests for Docker stats endpoint."""
@pytest.mark.asyncio
async def test_get_docker_stats(self, client: AsyncClient, api_key_header):
"""Test getting global Docker statistics."""
with patch('app.services.docker_alerts.docker_alerts_service.get_stats', new_callable=AsyncMock) as mock:
mock.return_value = {
"total_hosts": 5,
"enabled_hosts": 3,
"online_hosts": 2,
"total_containers": 25,
"running_containers": 20,
"total_images": 50,
"total_volumes": 10,
"open_alerts": 2,
"last_collection": "2024-01-15T10:00:00Z"
}
response = await client.get(
"/api/docker/stats",
headers=api_key_header
)
assert response.status_code == 200
data = response.json()
assert data["total_hosts"] == 5
assert data["running_containers"] == 20
assert data["open_alerts"] == 2