diff --git a/.env.dev b/.env.dev index 86b4830..d086a11 100644 --- a/.env.dev +++ b/.env.dev @@ -16,3 +16,4 @@ SESSION_SECRET_KEY=my-secret-key # Path where all logs for teuthology-suite or teuthology-kill would be collected ARCHIVE_DIR=/archive_dir/ +TEUTHOLOGY_PATH=/teuthology diff --git a/README.md b/README.md index 12a91a9..234b2e1 100644 --- a/README.md +++ b/README.md @@ -103,9 +103,10 @@ Example "--suite-repo": "https://github.com/ceph/ceph-ci.git", "--teuthology-branch": "main", "--verbose": "1", - "--user": "example" + "": ["/teuthology/containerized_node.yaml"] + "--owner": "example", }' -Note: "--user" in data body should be same as your github username (case sensitive). Otherwise, you wouldn't have permission to kill jobs/run. +Note: "--owner" in data body should be same as your github username (case sensitive). Otherwise, you wouldn't have permission to kill jobs/run. xxx diff --git a/src/teuthology_api/config.py b/src/teuthology_api/config.py index 377a2c6..e1b9be2 100644 --- a/src/teuthology_api/config.py +++ b/src/teuthology_api/config.py @@ -22,6 +22,7 @@ class APISettings(BaseSettings): session_secret_key: str = "" archive_dir: str = "" + teuthology_path: str = "" model_config = SettingsConfigDict( env_file=".env", env_file_encoding="utf-8", extra="ignore" diff --git a/src/teuthology_api/routes/kill.py b/src/teuthology_api/routes/kill.py index 9062f7e..472bde0 100644 --- a/src/teuthology_api/routes/kill.py +++ b/src/teuthology_api/routes/kill.py @@ -28,5 +28,5 @@ def create_run( or else it will SyntaxError: non-dafault argument follows default argument error. """ - args = args.model_dump(by_alias=True) + args = args.model_dump(by_alias=True, exclude_unset=True) return run(args, logs, access_token, request) diff --git a/src/teuthology_api/routes/suite.py b/src/teuthology_api/routes/suite.py index 8233ecf..ab97e9a 100644 --- a/src/teuthology_api/routes/suite.py +++ b/src/teuthology_api/routes/suite.py @@ -1,9 +1,9 @@ import logging -from fastapi import APIRouter, HTTPException, Depends +from fastapi import APIRouter, HTTPException, Depends, Request from teuthology_api.services.suite import run -from teuthology_api.services.helpers import get_token +from teuthology_api.services.helpers import get_token, get_username from teuthology_api.schemas.suite import SuiteArgs log = logging.getLogger(__name__) @@ -17,10 +17,12 @@ @router.post("/", status_code=200) def create_run( + request: Request, args: SuiteArgs, access_token: str = Depends(get_token), dry_run: bool = False, logs: bool = False, ): args = args.model_dump(by_alias=True) + args["--user"] = get_username(request) return run(args, dry_run, logs, access_token) diff --git a/src/teuthology_api/schemas/base.py b/src/teuthology_api/schemas/base.py index 5a624fa..791aa11 100644 --- a/src/teuthology_api/schemas/base.py +++ b/src/teuthology_api/schemas/base.py @@ -11,4 +11,3 @@ class BaseArgs(BaseModel): non_interactive: Union[bool, None] = Field(default=False, alias="--non-interactive") verbose: Union[int, None] = Field(default=1, alias="--verbose") help: Union[bool, None] = Field(default=False, alias="--help") - user: str = Field(alias="--user", description="Sepia username") diff --git a/src/teuthology_api/services/kill.py b/src/teuthology_api/services/kill.py index aa1b157..6ea99ef 100644 --- a/src/teuthology_api/services/kill.py +++ b/src/teuthology_api/services/kill.py @@ -1,11 +1,13 @@ -import teuthology.kill import logging +import subprocess from fastapi import HTTPException, Request -from teuthology_api.services.helpers import logs_run, get_username, get_run_details +from teuthology_api.config import settings +from teuthology_api.services.helpers import get_username, get_run_details +TEUTHOLOGY_PATH = settings.teuthology_path log = logging.getLogger(__name__) @@ -39,11 +41,23 @@ def run(args, send_logs: bool, access_token: str, request: Request): status_code=401, detail="You don't have permission to kill this run/job" ) try: + kill_cmd = [f"{TEUTHOLOGY_PATH}/virtualenv/bin/teuthology-kill"] + for flag, flag_value in args.items(): + if isinstance(flag_value, bool): + flag_value = int(flag_value) + kill_cmd += [flag, str(flag_value)] + log.info(kill_cmd) + proc = subprocess.Popen( + kill_cmd, stdout=subprocess.PIPE, stderr=subprocess.STDOUT + ) + stdout, stderr = proc.communicate() + returncode = proc.wait(timeout=120) + log.info(stdout) + if returncode != 0: + raise Exception(stdout) if send_logs: - logs = logs_run(teuthology.kill.main, args) - return {"logs": logs} - teuthology.kill.main(args) + return {"kill": "success", "logs": stdout} return {"kill": "success"} except Exception as exc: - log.error("teuthology.kill.main failed with the error: %s", repr(exc)) + log.error("teuthology-kill command failed with the error: %s", repr(exc)) raise HTTPException(status_code=500, detail=repr(exc)) from exc diff --git a/tests/test_kill.py b/tests/test_kill.py index 90adef8..7a30953 100644 --- a/tests/test_kill.py +++ b/tests/test_kill.py @@ -20,7 +20,6 @@ async def override_get_token(): "--non-interactive": False, "--verbose": 1, "--help": False, - "--user": "mock_user", "--owner": "user1", "--run": "mock_run", "--preserve-queue": None, @@ -31,13 +30,15 @@ async def override_get_token(): } -@patch("teuthology_api.services.kill.teuthology.kill.main") +@patch("subprocess.Popen") @patch("teuthology_api.services.kill.get_run_details") @patch("teuthology_api.services.kill.get_username") -def test_kill_run_success(m_get_username, m_get_run_details, m_teuth_kill_main): +def test_kill_run_success(m_get_username, m_get_run_details, m_popen): m_get_username.return_value = "user1" m_get_run_details.return_value = {"id": "7451978", "user": "user1"} - m_teuth_kill_main.return_value = None + mock_process = m_popen.return_value + mock_process.communicate.return_value = ("logs", "") + mock_process.wait.return_value = 0 response = client.post("/kill", data=json.dumps(mock_kill_args)) assert response.status_code == 200 assert response.json() == {"kill": "success"} diff --git a/tests/test_suite.py b/tests/test_suite.py index d39f1e8..ac912df 100644 --- a/tests/test_suite.py +++ b/tests/test_suite.py @@ -19,7 +19,6 @@ async def override_get_token(): "--non-interactive": False, "--verbose": 1, "--help": False, - "--user": "mock_user", "--timestamp": "2023-10-21_14:30:00", "--owner": "user1", "--suite": "rados", @@ -31,8 +30,10 @@ async def override_get_token(): # suite @patch("teuthology_api.services.suite.teuthology.suite.main") +@patch("teuthology_api.routes.suite.get_username") @patch("teuthology_api.services.suite.get_run_details") -def test_suite_run_success(m_get_run_details, m_teuth_suite_main): +def test_suite_run_success(m_get_run_details, m_get_username, m_teuth_suite_main): + m_get_username.return_value = "user1" m_get_run_details.return_value = {"id": "7451978", "user": "user1"} response = client.post("/suite", data=json.dumps(mock_suite_args)) assert response.status_code == 200