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
316 lines
12 KiB
Python
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
|