Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
17 changes: 15 additions & 2 deletions src/imgtests/web/static/js/launch_test.js
Original file line number Diff line number Diff line change
Expand Up @@ -85,12 +85,25 @@ document.getElementById("runTestsBtn").addEventListener("click", function () {
"Content-Type": "application/json",
},
body: JSON.stringify({
distro_id: window.distroId,
test_runs_count: testRunsCount,
testing_mode: testing_mode,
config: config,
}),
})
.then((response) => response.json())
.then((response) => {
if (response.status === 409 || response.status === 503) {
return response.json().then((data) => {
throw new Error(data.error);
});
}
if (!response.ok) {
return response.json().then((data) => {
throw new Error(data.error || "Failed to start tests");
});
}
return response.json();
})
.then((data) => {
if (data.success && data.task_id) {
outputContainer.textContent =
Expand All @@ -104,7 +117,7 @@ document.getElementById("runTestsBtn").addEventListener("click", function () {
}
})
.catch((error) => {
outputContainer.textContent = "Error: " + error;
outputContainer.textContent = "Error: " + error.message;
btn.disabled = false;
btn.textContent = "Run tests";
});
Expand Down
1 change: 1 addition & 0 deletions src/imgtests/web/tests_interface/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ class Distribution(models.Model):
description = models.TextField(blank=True)
order = models.PositiveSmallIntegerField(default=0)
is_active = models.BooleanField(default=True)
current_task_id = models.UUIDField(null=True, db_index=True)

class Meta:
"""Metadata options for Distribution model."""
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -153,6 +153,7 @@ <h4>Subsystems</h4>
{% load static %}
<script>
window.csrfToken = "{{ csrf_token }}";
window.distroId = {{ distro.id }};
window.distroName = "{{ distro.name }}";
document.getElementById("configTestingMode").addEventListener("change", function() {
const basicConfig = document.getElementById("basicTestConfig");
Expand Down
89 changes: 71 additions & 18 deletions src/imgtests/web/tests_interface/views.py
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
import json
import logging
import re
from pathlib import Path
from typing import TYPE_CHECKING
from typing import TYPE_CHECKING, Final

import paramiko
from django.core.management import call_command
from django.http import FileResponse, Http404, HttpRequest, JsonResponse
from django.http.response import HttpResponse
Expand All @@ -17,6 +17,7 @@

from imgtests.constant import CONFIG_DIR, EXCEL_REPORTS_DIR, REPORTS_DIR
from imgtests.database.database import ImgtestsDatabase, PostgresCreds
from imgtests.environment import env_var_to_type
from imgtests.reporting.excel_export import export_database_to_excel
from imgtests.reporting.html_report import ReportGenerator
from imgtests.runner import get_test_name
Expand Down Expand Up @@ -194,34 +195,83 @@ def report_static_files(request: HttpRequest, report_dir: str, file_path: str) -
raise Http404(error_message) from e


def run_tests(request: HttpRequest) -> JsonResponse:
referer = request.META.get("HTTP_REFERER", "")
DISTRO_SSH_MAP: Final = {
"yocto": ("SSH_YOCTO_ADDR", "SSH_YOCTO_USER", "SSH_YOCTO_PASS", "SSH_YOCTO_PORT"),
"opensuse": ("SSH_SUSE_ADDR_156", "SSH_SUSE_USER", "SSH_SUSE_PASS", "SSH_SUSE_PORT_156"),
}

match = re.search(r"/([^/]+)/$", referer)
if match:
distro_id = match.group(1)
distro = get_object_or_404(Distribution, id=distro_id, is_active=True)
try:
body = json.loads(request.body)
except json.JSONDecodeError, AttributeError:
body = {}
test_runs_count = body.get("test_runs_count", 1)

def check_ssh(distro_name: str) -> tuple[bool, str]:
conf = DISTRO_SSH_MAP.get(distro_name)
if not conf:
return False, "Error! No such distro."

try:
host = env_var_to_type(conf[0], str)
user = env_var_to_type(conf[1], str)
password = env_var_to_type(conf[2], str)
port = env_var_to_type(conf[3], int)
except ValueError as e:
return False, str(e)

try:
client = paramiko.SSHClient()
client.set_missing_host_key_policy(paramiko.WarningPolicy()) # noqa: S507
client.connect(host, port=port, username=user, password=password, timeout=10)
client.close()
except (paramiko.SSHException, OSError) as e:
return False, str(e)
else:
return JsonResponse({"error": "Invalid referer"}, status=400)
return True, ""
Comment on lines +204 to +225

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Думаю, что пока с этой задачей стоит повременить, т.к. хотелось как раз постепенно отказываться от хардкода с Yocto и Suse, но в данной задаче количество хардкода данных переменных окружения только возрастает.



def run_tests(request: HttpRequest) -> JsonResponse:
try:
mode = body.get("testing_mode", "default")
except AttributeError:
return JsonResponse({"error": "Invalid JSON"}, status=400)
body = json.loads(request.body)
except json.JSONDecodeError:
return JsonResponse({"error": "Invalid JSON body"}, status=400)

distro_id = body.get("distro_id")
if not distro_id:
return JsonResponse({"error": "distro_id is required"}, status=400)

distro = get_object_or_404(Distribution, id=distro_id, is_active=True)
mode = body.get("testing_mode", "default")
test_runs_count = body.get("test_runs_count", 1)
config = body.get("config") if mode == "profiled" else None

if distro.current_task_id:
task_id = str(distro.current_task_id)
task_data = test_runs.get(task_id)
if task_data:
result = task_data["result"]
result.refresh()
if not result.is_finished:
return JsonResponse(
{"error": "Tests are already running for this distribution"},
status=409,
)
distro.current_task_id = None
distro.save(update_fields=["current_task_id"])

ssh_ok, ssh_error = check_ssh(distro.name)
if not ssh_ok:
return JsonResponse(
{"error": f"Cannot connect to {distro.name}: {ssh_error}"},
status=503,
)

result: TaskResult = run_test_task.enqueue(
distro=distro.name,
mode=mode,
test_runs_count=test_runs_count,
config=body.get("config") if mode == "profiled" else None,
config=config,
)

task_id = str(result.id)
distro.current_task_id = result.id
distro.save(update_fields=["current_task_id"])

test_runs[task_id] = {
"status": "running",
"result": result,
Expand All @@ -240,6 +290,9 @@ def get_test_status(request: HttpRequest, task_id: str) -> JsonResponse: # noqa

result.refresh()

if result.is_finished:
Distribution.objects.filter(current_task_id=task_id).update(current_task_id=None)

if not result.is_finished:
return JsonResponse(
{
Expand Down
Loading