feat: project scaffold with models, config, and test fixtures

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
2026-03-05 18:52:39 -06:00
parent 3aa9f10d0d
commit fdfb9edfb0
13 changed files with 222 additions and 0 deletions
+6
View File
@@ -0,0 +1,6 @@
__pycache__/
*.pyc
.pytest_cache/
*.egg-info/
venv/
.env
View File
+28
View File
@@ -0,0 +1,28 @@
from pydantic import BaseModel
class ContainerInfo(BaseModel):
id: str
name: str
status: str
image: str
created: str
uptime: str | None = None
is_swarm: bool = False
swarm_service: str | None = None
class ContainerAction(BaseModel):
success: bool
message: str
class LogsResponse(BaseModel):
container: str
logs: str
class HealthResponse(BaseModel):
status: str
hostname: str
containers_total: int
+3
View File
@@ -0,0 +1,3 @@
fastapi>=0.115.0
uvicorn>=0.34.0
docker>=7.0.0
+7
View File
@@ -0,0 +1,7 @@
{
"nodes": [
{"name": "hf-pdocker-01", "host": "192.168.86.192", "agent_port": 8889},
{"name": "hf-pdocker-02", "host": "192.168.86.100", "agent_port": 8889},
{"name": "bart", "host": "192.168.86.167", "agent_port": 8889}
]
}
+103
View File
@@ -0,0 +1,103 @@
{
"groups": [
{
"id": "ai-agents",
"name": "AI Agents",
"services": [
{"node": "hf-pdocker-01", "container": "ai-agents_margaret"},
{"node": "hf-pdocker-01", "container": "ai-agents_spirit"},
{"node": "hf-pdocker-01", "container": "ai-agents_bob"},
{"node": "hf-pdocker-01", "container": "ai-agents_clippy"}
]
},
{
"id": "smart-home",
"name": "Smart Home",
"services": [
{"node": "hf-pdocker-01", "container": "smarthome_homeassistant"},
{"node": "hf-pdocker-01", "container": "smarthome_esphome"},
{"node": "hf-pdocker-01", "container": "smarthome_mosquitto"}
]
},
{
"id": "monitoring",
"name": "Monitoring",
"services": [
{"node": "hf-pdocker-01", "container": "monitoring_grafana"},
{"node": "hf-pdocker-01", "container": "monitoring_prometheus"},
{"node": "hf-pdocker-01", "container": "monitoring_alertmanager"},
{"node": "hf-pdocker-01", "container": "monitoring_influxdb"},
{"node": "hf-pdocker-01", "container": "monitoring_blackbox-exporter"}
]
},
{
"id": "media",
"name": "Media",
"services": [
{"node": "bart", "container": "jellyfin"},
{"node": "bart", "container": "sonarr"},
{"node": "bart", "container": "radarr"},
{"node": "bart", "container": "sabnzbd"},
{"node": "bart", "container": "nzbhydra2"},
{"node": "bart", "container": "jellyseerr"}
]
},
{
"id": "matrix",
"name": "Matrix",
"services": [
{"node": "hf-pdocker-01", "container": "matrix_synapse"},
{"node": "hf-pdocker-01", "container": "matrix_synapse-db"},
{"node": "hf-pdocker-01", "container": "matrix_wellknown"}
]
},
{
"id": "guacamole",
"name": "Guacamole",
"services": [
{"node": "hf-pdocker-01", "container": "guacamole_guacamole"},
{"node": "hf-pdocker-01", "container": "guacamole_guacd"},
{"node": "hf-pdocker-01", "container": "guacamole_guacamole-db"}
]
},
{
"id": "dev-tools",
"name": "Dev Tools",
"services": [
{"node": "hf-pdocker-02", "container": "gitea"},
{"node": "hf-pdocker-02", "container": "gitea-db"},
{"node": "hf-pdocker-02", "container": "semaphore"},
{"node": "hf-pdocker-02", "container": "semaphore-db"},
{"node": "hf-pdocker-02", "container": "wikijs"},
{"node": "hf-pdocker-02", "container": "wikijs-db"}
]
},
{
"id": "security",
"name": "Security",
"services": [
{"node": "hf-pdocker-02", "container": "vaultwarden"},
{"node": "hf-pdocker-02", "container": "trivy"},
{"node": "bart", "container": "openvas"}
]
},
{
"id": "network",
"name": "Network",
"services": [
{"node": "hf-pdocker-01", "container": "traefik_traefik"},
{"node": "hf-pdocker-01", "container": "adguard_adguardhome"},
{"node": "hf-pdocker-02", "container": "unifi"},
{"node": "hf-pdocker-02", "container": "unifi-db"}
]
},
{
"id": "frigate",
"name": "Frigate",
"services": [
{"node": "hf-pdocker-01", "container": "frigate"},
{"node": "hf-pdocker-01", "container": "frigate-notify"}
]
}
]
}
View File
+42
View File
@@ -0,0 +1,42 @@
from pydantic import BaseModel
class NodeConfig(BaseModel):
name: str
host: str
agent_port: int = 8889
class NodeStatus(BaseModel):
name: str
host: str
healthy: bool
containers_total: int = 0
error: str | None = None
class ServiceRef(BaseModel):
node: str
container: str
class Group(BaseModel):
id: str
name: str
services: list[ServiceRef] = []
class GroupsData(BaseModel):
groups: list[Group] = []
class ServiceInfo(BaseModel):
id: str
name: str
node: str
status: str
image: str
created: str
uptime: str | None = None
is_swarm: bool = False
swarm_service: str | None = None
+4
View File
@@ -0,0 +1,4 @@
fastapi>=0.115.0
uvicorn>=0.34.0
httpx>=0.28.0
aiofiles>=24.1.0
View File
View File
+26
View File
@@ -0,0 +1,26 @@
import pytest
@pytest.fixture
def sample_container():
return {
"id": "abc123",
"name": "test-container",
"status": "running",
"image": "nginx:latest",
"created": "2026-03-05T00:00:00Z",
"uptime": "2 hours",
"is_swarm": False,
"swarm_service": None,
}
@pytest.fixture
def sample_group():
return {
"id": "test-group",
"name": "Test Group",
"services": [
{"node": "hf-pdocker-01", "container": "test-container"},
],
}
+3
View File
@@ -0,0 +1,3 @@
pytest>=8.0.0
pytest-asyncio>=0.24.0
httpx>=0.28.0