This commit is contained in:
ITQ
2025-03-02 23:28:14 +03:00
parent 8259ba1916
commit 121c29c2f3
7 changed files with 55 additions and 23 deletions
+6 -1
View File
@@ -375,13 +375,18 @@ services:
build:
context: ./services/checker
dockerfile: Dockerfile
restart: unless-stopped
env_file:
- path: ./infrastructure/checker/.env.template
required: true
- path: ./infrastructure/checker/.env
required: false
ports:
- name: web
target: 8000
published: 8009
host_ip: 0.0.0.0
protocol: tcp
restart: unless-stopped
volumes:
- type: bind
source: /var/run/docker.sock
+2
View File
@@ -0,0 +1,2 @@
REGISTRY_LOGIN=devitq
REGISTRY_PASSWORD=14zQrbzDTM0WXK@CogMQikAvP74Rj4
+3 -3
View File
@@ -19,6 +19,7 @@ from apps.task.models import (
CompetitionTaskAttachment,
CompetitionTaskSubmission,
)
from apps.task.tasks import analyze_data_task
router = Router(tags=["competition"])
@@ -123,6 +124,7 @@ def submit_task(
status=CompetitionTaskSubmission.StatusChoices.CHECKING,
content=content,
)
analyze_data_task.delay(submission_id=submission.id)
return TaskSubmissionOut(submission_id=submission.id)
@@ -154,6 +156,4 @@ def get_submissions_history(request, competition_id: UUID, task_id: UUID):
)
def get_task_attachments(request, competition_id: UUID, task_id: UUID):
task = get_object_or_404(CompetitionTask, id=task_id)
return status.OK, CompetitionTaskAttachment.objects.filter(
task=task
).all()
return status.OK, CompetitionTaskAttachment.objects.filter(task=task).all()
+4 -4
View File
@@ -1,4 +1,4 @@
import requests
import httpx
from celery import shared_task
from django.core.files.base import ContentFile
@@ -17,7 +17,7 @@ def analyze_data_task(self, submission_id):
for f in submission.task.attachments.filter(public=True)
]
response = requests.post(
response = httpx.post(
f"{settings.CHECKER_API_ENDPOINT}/execute",
files=[("files", (f.name, f)) for f in files]
+ [
@@ -40,10 +40,10 @@ def analyze_data_task(self, submission_id):
)
submission.status = CompetitionTaskSubmission.StatusChoices.CHECKED
except requests.exceptions.RequestException as e:
except httpx.RequestError as e:
self.retry(countdown=2**self.request.retries)
except Exception as e:
submission.result = {"error": str(e)}
submission.result = {"error": str(e), "success": False}
submission.status = CompetitionTaskSubmission.StatusChoices.CHECKED
submission.earned_points = 0
finally:
+18
View File
@@ -0,0 +1,18 @@
import os
from pathlib import Path
from dotenv import load_dotenv
BASE_DIR = Path(__file__).resolve().parent
load_dotenv(BASE_DIR / ".env")
REGISTRY_LOGIN = os.getenv("REGISTRY_USERNAME", None)
REGISTRY_PASSWORD = os.getenv("REGISTRY_USERNAME", None)
REGISTRY_URL = os.getenv("REGISTRY_URL", "gitlab.prodcontest.ru:5050")
DOCKER_IMAGE = os.getenv(
"IMAGE", default="gitlab.prodcontest.ru:5050/team-15/project/custom-python"
)
+21 -15
View File
@@ -10,19 +10,25 @@ import tempfile
import logging
from urllib.parse import urlparse
import re
app = FastAPI()
docker_client = docker.from_env()
logger = logging.getLogger(__name__)
logging.basicConfig(level=logging.INFO)
import config
DOCKER_IMAGE = "gitlab.python:3-slim"
CONTAINER_TIMEOUT = 60
MAX_FILE_SIZE = 4 * 1024 * 1024
ALLOWED_FILENAME_CHARS = r"[^a-zA-Z0-9_\-.]"
app = FastAPI()
docker_client = docker.from_env()
logger = logging.getLoggerQ(__name__)
logging.basicConfig(level=logging.INFO)
docker_client.login(
username=config.REGISTRY_LOGIN,
password=config.REGISTRY_PASSWORD,
registry=config.REGISTRY_URL,
)
class FileDetails(BaseModel):
url: HttpUrl = Field(
..., description="URL to download the file from (supports HTTP/HTTPS)"
@@ -130,7 +136,7 @@ def run_container_safely(
volumes[host_path] = {"bind": container_path, "mode": "ro"}
container = docker_client.containers.run(
image=DOCKER_IMAGE,
image=config.DOCKER_IMAGE,
command=command,
volumes=volumes,
working_dir="/execution",
@@ -166,6 +172,14 @@ def run_container_safely(
pass
def validate_file_path(path: str) -> bool:
return (
not os.path.isabs(path)
and os.path.basename(path) == path
and all(c.isalnum() or c in {"_", "-", "."} for c in path)
)
@app.post("/execute", response_model=ExecutionResponse)
async def execute_code(request: ExecutionRequest) -> ExecutionResponse:
try:
@@ -279,11 +293,3 @@ async def health_check() -> HealthCheckResponse:
return HealthCheckResponse(status="healthy", docker="connected")
except docker.errors.DockerException:
return HealthCheckResponse(status="degraded", docker="unavailable")
def validate_file_path(path: str) -> bool:
return (
not os.path.isabs(path)
and os.path.basename(path) == path
and all(c.isalnum() or c in {"_", "-", "."} for c in path)
)
+1
View File
@@ -7,6 +7,7 @@ dependencies = [
"aiohttp>=3.11.13",
"docker>=7.1.0",
"fastapi>=0.115.11",
"python-dotenv>=1.0.1",
"python-multipart>=0.0.20",
"regex>=2024.11.6",
"uvicorn>=0.34.0",