From b0b7cd4efeb77202bb1fe32b0aff746885c8008d Mon Sep 17 00:00:00 2001 From: Jacob Boddey Date: Mon, 30 Oct 2023 13:59:42 +0000 Subject: [PATCH] Add version endpoint --- framework/python/src/api/api.py | 45 ++++++++++++++++++++++++++ framework/python/src/common/session.py | 15 +++++++++ 2 files changed, 60 insertions(+) diff --git a/framework/python/src/api/api.py b/framework/python/src/api/api.py index 5964b6244..63f4eea48 100644 --- a/framework/python/src/api/api.py +++ b/framework/python/src/api/api.py @@ -18,6 +18,7 @@ import json from json import JSONDecodeError import psutil +import requests import threading import uvicorn @@ -31,6 +32,8 @@ DEVICE_MODEL_KEY = "model" DEVICE_TEST_MODULES_KEY = "test_modules" +LATEST_RELEASE_CHECK = "https://api.github.com/repos/google/testrun/releases/latest" + class Api: """Provide REST endpoints to manage Testrun""" @@ -52,6 +55,8 @@ def __init__(self, test_run): methods=["POST"]) self._router.add_api_route("/system/status", self.get_status) + self._router.add_api_route("/system/version", self.get_version) + # Deprecated: /history will be removed in version 1.1 self._router.add_api_route("/history", self.get_reports) @@ -192,6 +197,46 @@ async def stop_test_run(self): async def get_status(self): return self._test_run.get_session().to_json() + async def get_version(self, response: Response): + json_response = {} + + # Obtain the current version + current_version = self._session.get_version() + + # Check if current version was able to be obtained + if current_version is None: + response.status_code = 500 + return self._generate_msg(False, "Could not fetch current version") + + # Set the installed version + json_response["installed_version"] = current_version + + # Check latest version number from GitHub API + version_check = requests.get(LATEST_RELEASE_CHECK, timeout=5) + + # Check OK response was received + if version_check.status_code != 200: + response.status_code = 500 + return self._generate_msg(False, "Failed to fetch latest version") + + # Extract version number from response, removing the leading 'v' + latest_version_no = version_check.json()["name"].strip("v") + LOGGER.debug(f"Latest version available is {latest_version_no}") + + # Craft JSON response + json_response["latest_version"] = latest_version_no + json_response["latest_version_url"] = version_check.json()["html_url"] + + # String comparison between current and latest version + if latest_version_no > current_version: + json_response["update_available"] = True + LOGGER.debug("An update is available") + else: + json_response["update_available"] = False + LOGGER.debug("The latest version is installed") + + return json_response + async def get_reports(self): LOGGER.debug("Received reports list request") return self._session.get_all_reports() diff --git a/framework/python/src/common/session.py b/framework/python/src/common/session.py index 14594f658..c08ba76fc 100644 --- a/framework/python/src/common/session.py +++ b/framework/python/src/common/session.py @@ -43,6 +43,10 @@ def __init__(self, config_file): self._runtime_params = [] self._device_repository = [] self._total_tests = 0 + + self._version = None + self._load_version() + self._config_file = config_file self._config = self._get_default_config() self._load_config() @@ -121,6 +125,17 @@ def _load_config(self): LOGGER.debug(self._config) + def _load_version(self): + version_cmd = util.run_command('dpkg-query --showformat=\'${Version}\' --show testrun') + + if version_cmd: + version = version_cmd[0] + LOGGER.info(f'Running Testrun version {version}') + self._version = version + + def get_version(self): + return self._version + def _save_config(self): with open(self._config_file, 'w', encoding='utf-8') as f: f.write(json.dumps(self._config, indent=2))