refactor(proxy): move proxy logic to services.mitmproxy and update Docker service model
Build and Push to Registry / build (push) Successful in 29s

- Rename DockerService to DockerContainer and add folder attribute
- Move proxy-related modules (models, validator) to services.mitmproxy
- Update imports and references to new module locations
- Refactor Docker utilities to use DockerContainer and improve service discovery
- Add manager.py with create_proxy utility stub
- Initialize discovered Docker services at app startup and warn if none found
This commit is contained in:
2026-04-13 00:24:20 +02:00 Unverified
parent 4fa014f465
commit f9e33e2847
12 changed files with 61 additions and 29 deletions
+1 -1
View File
@@ -11,7 +11,7 @@ from repositories.proxy import (
from repositories.proxy import (
list_proxies as list_proxy_documents,
)
from services.proxy.validator import ProxyCodeValidationError, validate_proxy_code
from services.mitmproxy.validator import ProxyCodeValidationError, validate_proxy_code
router = APIRouter(
prefix="/proxy",
+2 -4
View File
@@ -2,15 +2,13 @@ from integrations.docker.compose import (
find_docker_compose,
get_all_services,
get_services,
get_visible_folders,
)
from integrations.docker.editor import change_port
from integrations.docker.models import DockerService
from integrations.docker.models import DockerContainer
__all__ = [
"DockerService",
"DockerContainer",
"find_docker_compose",
"get_visible_folders",
"get_services",
"get_all_services",
"change_port",
+11 -11
View File
@@ -2,7 +2,7 @@ from pathlib import Path
import yaml
from integrations.docker.models import DockerService
from integrations.docker.models import DockerContainer
from integrations.docker.ports import _get_service_port
COMPOSE_NAMES = (
@@ -13,7 +13,7 @@ COMPOSE_NAMES = (
)
def get_visible_folders(directory: Path) -> list[Path]:
def _get_visible_folders(directory: Path) -> list[Path]:
return [
p for p in Path(directory).iterdir() if p.is_dir() and not p.name.startswith(".")
]
@@ -32,8 +32,8 @@ def find_docker_compose(path: Path) -> tuple[dict, str] | None:
return None
def get_services(folder: Path) -> list[DockerService] | None:
services: list[DockerService] = []
def get_services(folder: Path) -> list[DockerContainer] | None:
services: list[DockerContainer] = []
compose_data = find_docker_compose(folder)
if compose_data is None:
return None
@@ -56,20 +56,20 @@ def get_services(folder: Path) -> list[DockerService] | None:
if not ports:
continue
services.append({"name": service_name, "ports": ports})
services.append({"name": service_name, "ports": ports, "folder": folder})
return services or None
return services
def get_all_services(directory: str | Path) -> list[DockerService] | None:
def get_all_services(directory: str | Path) -> list[DockerContainer]:
path = Path(directory)
if not path.is_dir():
return None
return []
services: list[DockerService] = []
for sub_folder in get_visible_folders(path):
services: list[DockerContainer] = []
for sub_folder in _get_visible_folders(path):
sub_services = get_services(sub_folder)
if sub_services:
services.extend(sub_services)
return services or None
return services
+3 -1
View File
@@ -1,6 +1,8 @@
from pathlib import Path
from typing import TypedDict
class DockerService(TypedDict):
class DockerContainer(TypedDict):
name: str
ports: list[int]
folder: Path
+15
View File
@@ -1,4 +1,6 @@
import sys
from contextlib import asynccontextmanager
from pathlib import Path
from fastapi import FastAPI
@@ -8,6 +10,7 @@ from core.config import settings
from core.mongodb import close_mongodb, init_mongodb
from core.redis import close_redis, init_redis
from core.security import hash_password
from integrations.docker import get_all_services
from repositories.auth import ensure_auth_indexes, ensure_single_account
from repositories.proxy import ensure_proxy_indexes
@@ -22,6 +25,18 @@ async def lifespan(_: FastAPI):
password_hash=hash_password(settings.AUTH_PASSWORD),
)
await ensure_proxy_indexes()
home_dir = str(Path.home())
app.state.services = get_all_services(home_dir) or []
if not app.state.services:
warning = (
"\n" + "!" * 60 + "\n"
" WARNING: No services found in home directory!\n"
f" Scanned: {home_dir}\n"
+ "!" * 60 + "\n"
)
print(warning, file=sys.stderr)
try:
yield
finally:
+1 -1
View File
@@ -8,7 +8,7 @@ from pymongo import ReturnDocument
from core.mongodb import get_database
from models.proxy import ProxyDocument, ProxyUpdateInput
from models.service import ServiceEndpointDocument
from services.proxy.models import ServiceConfig
from services.mitmproxy.models import ServiceConfig
COLLECTION_NAME = "proxies"
+27
View File
@@ -0,0 +1,27 @@
import uuid
from pathlib import Path
from integrations.docker import DockerContainer
from services.mitmproxy.models import ServiceConfig
async def create_proxy(
port: int,
name: str,
service: ServiceConfig,
code: str,
services: list[DockerContainer]
) -> int:
"""
Utility function that will:
- run ``integrations/docker`` utilities to change the old port of original service to a random one
- write ``code`` into ``/tmp/theplug/{random}.py``
- start a subprocess via asyncio
- return the proxy infos (pid, )
"""
path = Path("/tmp/theplug/{random}.py".format(random=str(uuid.uuid4())))
path.parent.mkdir(parents=True, exist_ok=True)
path.write_text(code, encoding="utf-8")
return 0
-10
View File
@@ -1,10 +0,0 @@
from services.proxy.models import ServiceConfig
async def create_proxy(
port: int,
name: str,
service: ServiceConfig,
code: str
):
return
+1 -1
View File
@@ -3,7 +3,7 @@ import importlib
from core.security import get_auth_context, require_authenticated_user
from models.proxy import ProxyDocument
from models.service import ServiceEndpointDocument
from services.proxy.validator import ProxyCodeValidationError
from services.mitmproxy.validator import ProxyCodeValidationError
proxy_router_module = importlib.import_module("api.proxy.router")