diff --git a/ads/aqua/extension/common_handler.py b/ads/aqua/extension/common_handler.py index 002c7c860..40c6e7b0c 100644 --- a/ads/aqua/extension/common_handler.py +++ b/ads/aqua/extension/common_handler.py @@ -1,8 +1,8 @@ #!/usr/bin/env python # Copyright (c) 2025 Oracle and/or its affiliates. # Licensed under the Universal Permissive License v 1.0 as shown at https://oss.oracle.com/licenses/upl/ - - +import json +import os from importlib import metadata import huggingface_hub @@ -18,6 +18,10 @@ ) from ads.aqua.extension.base_handler import AquaAPIhandler from ads.aqua.extension.errors import Errors +from ads.common.object_storage_details import ObjectStorageDetails +from ads.common.utils import read_file +from ads.config import CONDA_BUCKET_NAME, CONDA_BUCKET_NS +from ads.opctl.operator.common.utils import default_signer class ADSVersionHandler(AquaAPIhandler): @@ -28,6 +32,46 @@ def get(self): self.finish({"data": metadata.version("oracle_ads")}) +class AquaVersionHandler(AquaAPIhandler): + @handle_exceptions + def get(self): + """ + Returns the current and latest deployed version of AQUA + + { + "installed": { + "aqua": "0.1.3.0", + "ads": "2.14.2" + }, + "latest": { + "aqua": "0.1.4.0", + "ads": "2.14.4" + } + } + + """ + + current_aqua_version_path = os.path.join( + os.path.dirname(os.path.abspath(__file__)), "..", "version.json" + ) + current_aqua_version = json.loads(read_file(current_aqua_version_path)) + current_ads_version = {"ads": metadata.version("oracle_ads")} + current_version = {"installed": {**current_aqua_version, **current_ads_version}} + try: + latest_version_artifact_path = ObjectStorageDetails( + CONDA_BUCKET_NAME, + CONDA_BUCKET_NS, + "service_pack/aqua_latest_version.json", + ).path + latest_version = json.loads( + read_file(latest_version_artifact_path, auth=default_signer()) + ) + except Exception: + latest_version = {"latest": current_version["installed"]} + response = {**current_version, **latest_version} + return self.finish(response) + + class CompatibilityCheckHandler(AquaAPIhandler): """The handler to check if the extension is compatible.""" @@ -118,4 +162,5 @@ def get(self): ("network_status", NetworkStatusHandler), ("hf_login", HFLoginHandler), ("hf_logged_in", HFUserStatusHandler), + ("aqua_version", AquaVersionHandler), ] diff --git a/ads/aqua/version.json b/ads/aqua/version.json new file mode 100644 index 000000000..5e39675c5 --- /dev/null +++ b/ads/aqua/version.json @@ -0,0 +1,3 @@ +{ + "aqua": "1.0.7" +} diff --git a/tests/unitary/with_extras/aqua/test_common_handler.py b/tests/unitary/with_extras/aqua/test_common_handler.py index f253b76d3..7a0c282ef 100644 --- a/tests/unitary/with_extras/aqua/test_common_handler.py +++ b/tests/unitary/with_extras/aqua/test_common_handler.py @@ -14,14 +14,17 @@ import ads.aqua import ads.config -from ads.aqua.extension.common_handler import CompatibilityCheckHandler +from ads.aqua.extension.common_handler import ( + CompatibilityCheckHandler, + AquaVersionHandler, +) class TestDataset: SERVICE_COMPARTMENT_ID = "ocid1.compartment.oc1.." -class TestEvaluationHandler(unittest.TestCase): +class TestCompatibilityCheckHandler(unittest.TestCase): @patch.object(IPythonHandler, "__init__") def setUp(self, ipython_init_mock) -> None: ipython_init_mock.return_value = None @@ -29,7 +32,7 @@ def setUp(self, ipython_init_mock) -> None: self.common_handler.request = MagicMock() def test_get_ok(self): - """Test to check if ok is returned when ODSC_MODEL_COMPARTMENT_OCID is set.""" + """Test to check if ok is returned.""" reload(ads.config) reload(ads.aqua) reload(ads.aqua.extension.utils) @@ -42,3 +45,26 @@ def test_get_ok(self): self.common_handler.request.path = "aqua/hello" result = self.common_handler.get() assert result["status"] == "ok" + + +class TestAquaVersionHandler(unittest.TestCase): + @patch.object(IPythonHandler, "__init__") + def setUp(self, ipython_init_mock) -> None: + ipython_init_mock.return_value = None + self.version_handler = AquaVersionHandler(MagicMock(), MagicMock()) + self.version_handler.request = MagicMock() + + @patch("ads.common.utils.read_file") + def test_get(self, mock_read_file): + reload(ads.config) + reload(ads.aqua) + reload(ads.aqua.extension.utils) + reload(ads.aqua.extension.common_handler) + mock_read_file.return_value = '{"installed":{"aqua":"1.0.4","ads":"2.13.12"}}' + with patch( + "ads.aqua.extension.base_handler.AquaAPIhandler.finish" + ) as mock_finish: + mock_finish.side_effect = lambda x: x + self.version_handler.request.path = "aqua/aqua_version" + result = self.version_handler.get() + assert result == {"installed": {"aqua": "1.0.4", "ads": "2.13.12"}}