From 954792192da1620a4663dcbe297037ebc32b0bef Mon Sep 17 00:00:00 2001 From: Fabien Boucher Date: Apr 07 2021 11:49:22 +0000 Subject: Move clean-koji-stalled-tasks.py --- diff --git a/files/clean-koji-stalled-tasks.py b/files/clean-koji-stalled-tasks.py deleted file mode 100755 index 569c33a..0000000 --- a/files/clean-koji-stalled-tasks.py +++ /dev/null @@ -1,125 +0,0 @@ -#!/bin/env python3 - -from typing import List, Optional -from subprocess import run, CalledProcessError -from datetime import datetime, timedelta -import unittest -import argparse -import sys - -KOJI_CMD = ["koji"] -MAX_HR = 12 - -mocked_list_tasks_ids = """ -64642854 20 zuul OPEN noarch build (rawhide, libkcapi-1.2.1-1.fc35.src.rpm) -64642908 19 zuul OPEN ppc64le +buildArch (libkcapi-1.2.1-1.fc35.src.rpm, ppc64le) -64642862 20 zuul OPEN noarch build (rawhide, libkcapi-1.2.1-1.fc35.src.rpm) -""" - -mocked_task_info_1 = """ -Task: 64642801 -Type: build -Owner: zuul -State: open -Created: Fri Mar 26 15:43:39 2021 -Started: Thu Apr 1 21:39:23 2021 -Host: buildvm-s390x-11.s390.fedoraproject.org -""" - -now = datetime.strftime(datetime.now(), "%c") -mocked_task_info_2 = """ -Task: 64642802 -Type: build -Owner: zuul -State: open -Created: %s -Started: %s -Host: buildvm-s390x-11.s390.fedoraproject.org -""" % ( - now, - now, -) - - -def call_koji_cmd(args: List[str], mock: bool = False) -> Optional[str]: - if mock and args == ["list-tasks", "--quiet", "--mine"]: - return mocked_list_tasks_ids - if mock and args == ["taskinfo", "64642801"]: - return mocked_task_info_1 - if mock and args == ["taskinfo", "64642802"]: - return mocked_task_info_2 - cmd = KOJI_CMD + args - compp = run(cmd, capture_output=True, text=True) - try: - compp.check_returncode() - except CalledProcessError as exc: - print("Command %s did not success: %s" % (" ".join(cmd), exc)) - return None - return compp.stdout - - -def get_tasks_ids_list(mocked: bool = False) -> Optional[List[str]]: - cmd_output = call_koji_cmd(["list-tasks", "--quiet", "--mine"], mock=mocked) - if not cmd_output: - return None - return list( - map(lambda l: l.split()[0], filter(lambda x: x, cmd_output.splitlines())) - ) - - -def check_stalled_task(task_id: str, mocked: bool = False) -> bool: - cmd_output = call_koji_cmd(["taskinfo", task_id], mock=mocked) - if not cmd_output: - return False - started_line = list( - filter( - lambda l: l.startswith("Started: "), - filter(lambda x: x, cmd_output.splitlines()), - ) - ) - if not started_line: - return False - started_date = datetime.strptime(started_line[0].replace("Started: ", ""), "%c") - stalled = started_date < datetime.now() - timedelta(hours=MAX_HR) - print("Tasks %s started at %s [stalled: %s]" % (task_id, started_date, stalled)) - return stalled - - -def run_check(noop: bool) -> None: - tasks_ids = get_tasks_ids_list() - if tasks_ids: - for task_id in tasks_ids: - if not check_stalled_task(task_id): - continue - if not noop: - print("Cancelling task %s ..." % task_id) - call_koji_cmd(["cancel", task_id]) - else: - print("Will cancel task %s ..." % task_id) - - -### Run tests with python -m unittest clean-koji-stalled-tasks.py ### -class ToolTests(unittest.TestCase): - def test_get_tasks_ids_list(self): - tasks_ids = get_tasks_ids_list(mocked=True) - self.assertListEqual(["64642854", "64642908", "64642862"], tasks_ids) - - def test_check_stalled_tasks(self): - self.assertTrue(check_stalled_task("64642801", mocked=True)) - self.assertFalse(check_stalled_task("64642802", mocked=True)) - - -def main() -> None: - parser = argparse.ArgumentParser() - parser.add_argument( - "--noop", help="Do not cancel tasks (only report)", action="store_true" - ) - if "-m unittest" in sys.argv[0]: - # Skip main if running local tests - pass - else: - args = parser.parse_args() - run_check(args.noop) - - -main() diff --git a/playbooks/koji/files/clean-koji-stalled-tasks.py b/playbooks/koji/files/clean-koji-stalled-tasks.py new file mode 100755 index 0000000..569c33a --- /dev/null +++ b/playbooks/koji/files/clean-koji-stalled-tasks.py @@ -0,0 +1,125 @@ +#!/bin/env python3 + +from typing import List, Optional +from subprocess import run, CalledProcessError +from datetime import datetime, timedelta +import unittest +import argparse +import sys + +KOJI_CMD = ["koji"] +MAX_HR = 12 + +mocked_list_tasks_ids = """ +64642854 20 zuul OPEN noarch build (rawhide, libkcapi-1.2.1-1.fc35.src.rpm) +64642908 19 zuul OPEN ppc64le +buildArch (libkcapi-1.2.1-1.fc35.src.rpm, ppc64le) +64642862 20 zuul OPEN noarch build (rawhide, libkcapi-1.2.1-1.fc35.src.rpm) +""" + +mocked_task_info_1 = """ +Task: 64642801 +Type: build +Owner: zuul +State: open +Created: Fri Mar 26 15:43:39 2021 +Started: Thu Apr 1 21:39:23 2021 +Host: buildvm-s390x-11.s390.fedoraproject.org +""" + +now = datetime.strftime(datetime.now(), "%c") +mocked_task_info_2 = """ +Task: 64642802 +Type: build +Owner: zuul +State: open +Created: %s +Started: %s +Host: buildvm-s390x-11.s390.fedoraproject.org +""" % ( + now, + now, +) + + +def call_koji_cmd(args: List[str], mock: bool = False) -> Optional[str]: + if mock and args == ["list-tasks", "--quiet", "--mine"]: + return mocked_list_tasks_ids + if mock and args == ["taskinfo", "64642801"]: + return mocked_task_info_1 + if mock and args == ["taskinfo", "64642802"]: + return mocked_task_info_2 + cmd = KOJI_CMD + args + compp = run(cmd, capture_output=True, text=True) + try: + compp.check_returncode() + except CalledProcessError as exc: + print("Command %s did not success: %s" % (" ".join(cmd), exc)) + return None + return compp.stdout + + +def get_tasks_ids_list(mocked: bool = False) -> Optional[List[str]]: + cmd_output = call_koji_cmd(["list-tasks", "--quiet", "--mine"], mock=mocked) + if not cmd_output: + return None + return list( + map(lambda l: l.split()[0], filter(lambda x: x, cmd_output.splitlines())) + ) + + +def check_stalled_task(task_id: str, mocked: bool = False) -> bool: + cmd_output = call_koji_cmd(["taskinfo", task_id], mock=mocked) + if not cmd_output: + return False + started_line = list( + filter( + lambda l: l.startswith("Started: "), + filter(lambda x: x, cmd_output.splitlines()), + ) + ) + if not started_line: + return False + started_date = datetime.strptime(started_line[0].replace("Started: ", ""), "%c") + stalled = started_date < datetime.now() - timedelta(hours=MAX_HR) + print("Tasks %s started at %s [stalled: %s]" % (task_id, started_date, stalled)) + return stalled + + +def run_check(noop: bool) -> None: + tasks_ids = get_tasks_ids_list() + if tasks_ids: + for task_id in tasks_ids: + if not check_stalled_task(task_id): + continue + if not noop: + print("Cancelling task %s ..." % task_id) + call_koji_cmd(["cancel", task_id]) + else: + print("Will cancel task %s ..." % task_id) + + +### Run tests with python -m unittest clean-koji-stalled-tasks.py ### +class ToolTests(unittest.TestCase): + def test_get_tasks_ids_list(self): + tasks_ids = get_tasks_ids_list(mocked=True) + self.assertListEqual(["64642854", "64642908", "64642862"], tasks_ids) + + def test_check_stalled_tasks(self): + self.assertTrue(check_stalled_task("64642801", mocked=True)) + self.assertFalse(check_stalled_task("64642802", mocked=True)) + + +def main() -> None: + parser = argparse.ArgumentParser() + parser.add_argument( + "--noop", help="Do not cancel tasks (only report)", action="store_true" + ) + if "-m unittest" in sys.argv[0]: + # Skip main if running local tests + pass + else: + args = parser.parse_args() + run_check(args.noop) + + +main()