From 6b1bc6c0274b80aae845565a3c61aa1ed71bb73c Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Thu, 19 Dec 2024 10:53:04 +0100 Subject: [PATCH 01/15] chore: partial updates --- operate/cli.py | 26 +++++++++++++++++++++++++- operate/operate_types.py | 2 +- operate/services/manage.py | 13 +++++++++++++ 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/operate/cli.py b/operate/cli.py index 3cf56245..f257cd1b 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -765,7 +765,6 @@ async def _update_service(request: Request) -> JSONResponse: service_config_id = request.path_params["service_config_id"] manager = operate.service_manager() - print(service_config_id) if not manager.exists(service_config_id=service_config_id): return service_not_found_error(service_config_id=service_config_id) @@ -781,6 +780,31 @@ async def _update_service(request: Request) -> JSONResponse: return JSONResponse(content=output.json) + @app.patch("/api/v2/service/{service_config_id}") + @with_retries + async def _partial_update_service(request: Request) -> JSONResponse: + """Partially update a service (merge update).""" + if operate.password is None: + return USER_NOT_LOGGED_IN_ERROR + + service_config_id = request.path_params["service_config_id"] + manager = operate.service_manager() + + if not manager.exists(service_config_id=service_config_id): + return service_not_found_error(service_config_id=service_config_id) + + template = await request.json() + allow_different_service_public_id = template.get( + "allow_different_service_public_id", False + ) + output = manager.partial_update( + service_config_id=service_config_id, + service_template=template, + allow_different_service_public_id=allow_different_service_public_id, + ) + + return JSONResponse(content=output.json) + @app.put("/api/v2/services") @with_retries async def _update_all_services(request: Request) -> JSONResponse: diff --git a/operate/operate_types.py b/operate/operate_types.py index 9a683837..b6b502c1 100644 --- a/operate/operate_types.py +++ b/operate/operate_types.py @@ -246,7 +246,7 @@ class EnvVariableAttributes(TypedDict): EnvVariables = t.Dict[str, EnvVariableAttributes] -class ServiceTemplate(TypedDict): +class ServiceTemplate(TypedDict, total=False): """Service template.""" name: str diff --git a/operate/services/manage.py b/operate/services/manage.py index fe919753..5511e4a6 100644 --- a/operate/services/manage.py +++ b/operate/services/manage.py @@ -1697,6 +1697,19 @@ def update( service.update(service_template, allow_different_service_public_id) return service + def update( + self, + service_config_id: str, + service_template: ServiceTemplate, + allow_different_service_public_id: bool = False, + ) -> Service: + """Update a service.""" + + self.logger.info(f"Updating {service_config_id=}") + service = self.load(service_config_id=service_config_id) + service.update(service_template, allow_different_service_public_id) + return service + def update_all_matching( self, service_template: ServiceTemplate, From b5296400e59e92ed9833bbe217c16e23199012f9 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 01:15:56 +0100 Subject: [PATCH 02/15] chore: fix update endpoint --- operate/cli.py | 6 +- operate/services/manage.py | 20 ++-- operate/services/service.py | 72 +++++++++----- tests/test_services_manage.py | 182 ++++++++++++++++++++++++++++++++++ 4 files changed, 237 insertions(+), 43 deletions(-) create mode 100644 tests/test_services_manage.py diff --git a/operate/cli.py b/operate/cli.py index f257cd1b..a5f65eb8 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -776,13 +776,14 @@ async def _update_service(request: Request) -> JSONResponse: service_config_id=service_config_id, service_template=template, allow_different_service_public_id=allow_different_service_public_id, + partial_update=False, ) return JSONResponse(content=output.json) @app.patch("/api/v2/service/{service_config_id}") @with_retries - async def _partial_update_service(request: Request) -> JSONResponse: + async def _partial_update_service(request: Request) -> JSONResponse: """Partially update a service (merge update).""" if operate.password is None: return USER_NOT_LOGGED_IN_ERROR @@ -797,10 +798,11 @@ async def _partial_update_service(request: Request) -> JSONResponse: allow_different_service_public_id = template.get( "allow_different_service_public_id", False ) - output = manager.partial_update( + output = manager.update( service_config_id=service_config_id, service_template=template, allow_different_service_public_id=allow_different_service_public_id, + partial_update=True, ) return JSONResponse(content=output.json) diff --git a/operate/services/manage.py b/operate/services/manage.py index c1d360d3..276be943 100644 --- a/operate/services/manage.py +++ b/operate/services/manage.py @@ -1689,25 +1689,17 @@ def update( service_config_id: str, service_template: ServiceTemplate, allow_different_service_public_id: bool = False, + partial_update: bool = True, ) -> Service: """Update a service.""" self.logger.info(f"Updating {service_config_id=}") service = self.load(service_config_id=service_config_id) - service.update(service_template, allow_different_service_public_id) - return service - - def update( - self, - service_config_id: str, - service_template: ServiceTemplate, - allow_different_service_public_id: bool = False, - ) -> Service: - """Update a service.""" - - self.logger.info(f"Updating {service_config_id=}") - service = self.load(service_config_id=service_config_id) - service.update(service_template, allow_different_service_public_id) + service.update( + service_template=service_template, + allow_different_service_public_id=allow_different_service_public_id, + partial_update=partial_update, + ) return service def update_all_matching( diff --git a/operate/services/service.py b/operate/services/service.py index ec6ca340..42c32f1d 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -98,7 +98,7 @@ SERVICE_CONFIG_VERSION = 4 SERVICE_CONFIG_PREFIX = "sc-" -DUMMY_MULTISIG = "0xm" +NON_EXISTENT_MULTISIG = "0xm" NON_EXISTENT_TOKEN = -1 DEFAULT_TRADER_ENV_VARS = { @@ -897,7 +897,7 @@ def new( # pylint: disable=too-many-locals chain_data = OnChainData( instances=[], token=NON_EXISTENT_TOKEN, - multisig=DUMMY_MULTISIG, + multisig=NON_EXISTENT_MULTISIG, staked=False, on_chain_state=OnChainState.NON_EXISTENT, user_params=OnChainUserParams.from_json(config), # type: ignore @@ -981,47 +981,65 @@ def update( self, service_template: ServiceTemplate, allow_different_service_public_id: bool = False, + partial_update: bool = False, ) -> None: """Update service.""" - target_hash = service_template["hash"] - target_service_public_id = Service.get_service_public_id(target_hash, self.path) - - if not allow_different_service_public_id and ( - self.service_public_id() != target_service_public_id - ): - raise ValueError( - f"Trying to update a service with a different public id: {self.service_public_id()=} {self.hash=} {target_service_public_id=} {target_hash=}." + target_hash = service_template.get("hash") + if target_hash: + target_service_public_id = Service.get_service_public_id( + target_hash, self.path ) + if not allow_different_service_public_id and ( + self.service_public_id() != target_service_public_id + ): + raise ValueError( + f"Trying to update a service with a different public id: {self.service_public_id()=} {self.hash=} {target_service_public_id=} {target_hash=}." + ) + + self.hash = service_template.get("hash", self.hash) + + # hash_history - Only update if latest inserted hash is different + if self.hash_history[max(self.hash_history.keys())] != self.hash: + current_timestamp = int(time.time()) + self.hash_history[current_timestamp] = self.hash + + self.home_chain = service_template.get("home_chain", self.home_chain) + self.description = service_template.get("description", self.description) + self.name = service_template.get("name", self.name) + shutil.rmtree(self.service_path) service_path = Path( IPFSTool().download( - hash_id=service_template["hash"], + hash_id=self.hash, target_dir=self.path, ) ) self.service_path = service_path - self.name = service_template["name"] - self.hash = service_template["hash"] - self.description = service_template["description"] - - # TODO temporarily disable update env variables - hotfix for Memeooorr - # self.env_variables = service_template["env_variables"] - - # Only update hash_history if latest inserted hash is different - if self.hash_history[max(self.hash_history.keys())] != service_template["hash"]: - current_timestamp = int(time.time()) - self.hash_history[current_timestamp] = service_template["hash"] - self.home_chain = service_template["home_chain"] + # env_variables + if partial_update: + for var, attrs in service_template.get("env_variables", {}).items(): + self.env_variables.setdefault(var, {}).update(attrs) + else: + self.env_variables = service_template["env_variables"] + # chain_configs + # TODO support remove chains for non-partial updates + # TODO ensure all and only existing chains are passed for non-partial updates ledger_configs = ServiceHelper(path=self.service_path).ledger_configs() - for chain, config in service_template["configurations"].items(): + for chain, new_config in service_template.get("configurations", {}).items(): if chain in self.chain_configs: # The template is providing a chain configuration that already # exists in this service - update only the user parameters. # This is to avoid losing on-chain data like safe, token, etc. + if partial_update: + config = self.chain_configs[chain].chain_data.user_params.json + config.update(new_config) + else: + config = new_config + self.chain_configs[ chain ].chain_data.user_params = OnChainUserParams.from_json( @@ -1032,15 +1050,15 @@ def update( # not currently exist in this service - copy all config as # when creating a new service. ledger_config = ledger_configs[chain] - ledger_config.rpc = config["rpc"] + ledger_config.rpc = new_config["rpc"] chain_data = OnChainData( instances=[], token=NON_EXISTENT_TOKEN, - multisig=DUMMY_MULTISIG, + multisig=NON_EXISTENT_MULTISIG, staked=False, on_chain_state=OnChainState.NON_EXISTENT, - user_params=OnChainUserParams.from_json(config), # type: ignore + user_params=OnChainUserParams.from_json(new_config), # type: ignore ) self.chain_configs[chain] = ChainConfig( diff --git a/tests/test_services_manage.py b/tests/test_services_manage.py new file mode 100644 index 00000000..7aa0a8c2 --- /dev/null +++ b/tests/test_services_manage.py @@ -0,0 +1,182 @@ +# -*- coding: utf-8 -*- +# ------------------------------------------------------------------------------ +# +# Copyright 2024 Valory AG +# +# Licensed under the Apache License, Version 2.0 (the "License"); +# you may not use this file except in compliance with the License. +# You may obtain a copy of the License at +# +# http://www.apache.org/licenses/LICENSE-2.0 +# +# Unless required by applicable law or agreed to in writing, software +# distributed under the License is distributed on an "AS IS" BASIS, +# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +# See the License for the specific language governing permissions and +# limitations under the License. +# +# ------------------------------------------------------------------------------ + +"""Tests for services.service module.""" + +import random +import string +import typing as t +from pathlib import Path + +import pytest +from deepdiff import DeepDiff + +from operate.cli import OperateApp +from operate.operate_types import ServiceTemplate +from .test_services_service import DEFAULT_CONFIG_KWARGS + +ROOT_PATH = Path(__file__).resolve().parent +OPERATE_HOME = ROOT_PATH / ".operate_test" + +from operate.services.service import Service + + +@pytest.fixture +def random_string() -> str: + length = 8 + chars = string.ascii_letters + string.digits + return "".join(random.choices(chars, k=length)) + + +def get_template(**kwargs: t.Any) -> ServiceTemplate: + """get_template""" + + return { + "name": kwargs.get("name"), + "hash": kwargs.get("hash"), + "description": kwargs.get("description"), + "image": "https://image_url", + "service_version": "", + "home_chain": "gnosis", + "configurations": { + "gnosis": { + "staking_program_id": kwargs.get("staking_program_id"), + "nft": kwargs.get("nft"), + "rpc": "http://localhost:8545", + "threshold": kwargs.get("threshold"), + "agent_id": kwargs.get("agent_id"), + "use_staking": kwargs.get("use_staking"), + "use_mech_marketplace": kwargs.get("use_mech_marketplace"), + "cost_of_bond": kwargs.get("cost_of_bond"), + "fund_requirements": { + "agent": kwargs.get("fund_requirements_agent"), + "safe": kwargs.get("fund_requirements_safe"), + }, + "fallback_chain_params": {} + } + }, + "env_variables": { + "VAR1": { + "name": "var1_name", + "description": "var1_description", + "value": "var1_value", + "provision_type": "var1_provision_type", + }, + "VAR2": { + "name": "var2_name", + "description": "var2_description", + "value": "var2_value", + "provision_type": "var2_provision_type", + }, + }, + } + + +class TestServiceManager: + """Tests for services.manager.ServiceManager class.""" + + @pytest.mark.parametrize("update_new_var", [True]) + @pytest.mark.parametrize("update_update_var", [True]) + @pytest.mark.parametrize("update_name", [True]) + @pytest.mark.parametrize("update_description", [True]) + @pytest.mark.parametrize("update_hash", [True]) + def test_service_update( + self, + update_new_var: bool, + update_update_var: bool, + update_name: bool, + update_description: bool, + update_hash: bool, + tmp_path: Path, + random_string: str, + ) -> None: + """Test operate.service_manager().update()""" + + operate = OperateApp( + home=tmp_path / ".operate_test", + ) + operate.setup() + password = random_string + operate.create_user_account(password=password) + operate.password = password + service_manager = operate.service_manager() + service_template = get_template(**DEFAULT_CONFIG_KWARGS) + service = service_manager.create(service_template) + service_config_id = service.service_config_id + service_json = service_manager.load(service_config_id).json + + new_hash = "bafybeicts6zhavxzz2rxahz3wzs2pzamoq64n64wp4q4cdanfuz7id6c2q" + VAR2_updated_attributes = { + "name": "var2_name_updated", + "description": "var2_description_updated", + "value": "var2_value_updated", + "provision_type": "var2_provision_type_updated", + "extra_attr": "extra_val", + } + + VAR3_attributes = { + "name": "var3_name", + "description": "var3_description", + "value": "var3_value", + "provision_type": "var3_provision_type", + } + + # Partial update + update_template: t.Dict = {} + expected_service_json = service_json.copy() + + if update_new_var: + update_template["env_variables"] = update_template.get("env_variables", {}) + update_template["env_variables"]["VAR3"] = VAR3_attributes + expected_service_json["env_variables"]["VAR3"] = VAR3_attributes + + if update_update_var: + update_template["env_variables"] = update_template.get("env_variables", {}) + update_template["env_variables"]["VAR2"] = VAR2_updated_attributes + expected_service_json["env_variables"]["VAR2"] = VAR2_updated_attributes + + if update_name: + update_template["name"] = "name_updated" + expected_service_json["name"] = "name_updated" + + if update_description: + update_template["description"] = "description_updated" + expected_service_json["description"] = "description_updated" + + if update_hash: + update_template["hash"] = new_hash + expected_service_json["hash"] = new_hash + + service_manager.update( + service_config_id=service_config_id, + service_template=update_template, + allow_different_service_public_id=False, + partial_update=True, + ) + service_json = service_manager.load(service_config_id).json + + if update_hash: + timestamp = max(service_json["hash_history"].keys()) + expected_service_json["hash_history"][timestamp] = new_hash + + diff = DeepDiff(service_json, expected_service_json) + if diff: + print(diff) + + assert not diff, "Updated service does not match expected service." From 4290e11a8d7d913d17fc03c1fe7a6d3535b63d4c Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 01:24:36 +0100 Subject: [PATCH 03/15] fix: linters --- tests/test_services_manage.py | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) diff --git a/tests/test_services_manage.py b/tests/test_services_manage.py index 7aa0a8c2..2a3b5281 100644 --- a/tests/test_services_manage.py +++ b/tests/test_services_manage.py @@ -29,19 +29,20 @@ from operate.cli import OperateApp from operate.operate_types import ServiceTemplate + from .test_services_service import DEFAULT_CONFIG_KWARGS + ROOT_PATH = Path(__file__).resolve().parent OPERATE_HOME = ROOT_PATH / ".operate_test" -from operate.services.service import Service - @pytest.fixture def random_string() -> str: + """random_string""" length = 8 chars = string.ascii_letters + string.digits - return "".join(random.choices(chars, k=length)) + return "".join(random.choices(chars, k=length)) # nosec B311 def get_template(**kwargs: t.Any) -> ServiceTemplate: @@ -91,11 +92,11 @@ def get_template(**kwargs: t.Any) -> ServiceTemplate: class TestServiceManager: """Tests for services.manager.ServiceManager class.""" - @pytest.mark.parametrize("update_new_var", [True]) - @pytest.mark.parametrize("update_update_var", [True]) - @pytest.mark.parametrize("update_name", [True]) - @pytest.mark.parametrize("update_description", [True]) - @pytest.mark.parametrize("update_hash", [True]) + @pytest.mark.parametrize("update_new_var", [True, False]) + @pytest.mark.parametrize("update_update_var", [True, False]) + @pytest.mark.parametrize("update_name", [True, False]) + @pytest.mark.parametrize("update_description", [True, False]) + @pytest.mark.parametrize("update_hash", [True, False]) def test_service_update( self, update_new_var: bool, From 7fae98a20c79a8d48d3fb7e34bd11c1c46aafd50 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 01:27:46 +0100 Subject: [PATCH 04/15] fix: linters --- tests/test_services_manage.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/test_services_manage.py b/tests/test_services_manage.py index 2a3b5281..7cc8a23f 100644 --- a/tests/test_services_manage.py +++ b/tests/test_services_manage.py @@ -69,7 +69,7 @@ def get_template(**kwargs: t.Any) -> ServiceTemplate: "agent": kwargs.get("fund_requirements_agent"), "safe": kwargs.get("fund_requirements_safe"), }, - "fallback_chain_params": {} + "fallback_chain_params": {}, } }, "env_variables": { From d6d5d2b64a552329fd4046d96fcfd1fb3c750ca0 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 01:30:23 +0100 Subject: [PATCH 05/15] fix: linters --- tox.ini | 3 +++ 1 file changed, 3 insertions(+) diff --git a/tox.ini b/tox.ini index f294bf30..27d456c3 100644 --- a/tox.ini +++ b/tox.ini @@ -230,6 +230,9 @@ ignore_missing_imports = True [mypy-deepdiff.*] ignore_missing_imports = True +[mypy-twikit.*] +ignore_missing_imports = True + [testenv:unit-tests] deps = pytest==7.2.1 From 9059b778762cc1457c2d7f8a579452375587f5d0 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 01:35:24 +0100 Subject: [PATCH 06/15] fix: linters --- operate/services/service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/operate/services/service.py b/operate/services/service.py index 42c32f1d..8a41859e 100644 --- a/operate/services/service.py +++ b/operate/services/service.py @@ -683,7 +683,7 @@ class Service(LocalResource): _file = "config.json" @classmethod - def migrate_format(cls, path: Path) -> bool: + def migrate_format(cls, path: Path) -> bool: # pylint: disable=too-many-statements """Migrate the JSON file format if needed.""" if not path.is_dir(): From 57e2ca4ebc0233dffbac58cb02976da5e33e10c0 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 12:39:25 +0100 Subject: [PATCH 07/15] chore: updates --- operate/cli.py | 10 +++- operate/services/manage.py | 33 +++++++++++- tests/test_services_manage.py | 99 ++++++++++++++++++++++++++++++++++- 3 files changed, 137 insertions(+), 5 deletions(-) diff --git a/operate/cli.py b/operate/cli.py index a5f65eb8..b2b9b497 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -756,6 +756,7 @@ def _fn() -> None: ) @app.put("/api/v2/service/{service_config_id}") + @app.patch("/api/v2/service/{service_config_id}") @with_retries async def _update_service(request: Request) -> JSONResponse: """Update a service.""" @@ -772,16 +773,21 @@ async def _update_service(request: Request) -> JSONResponse: allow_different_service_public_id = template.get( "allow_different_service_public_id", False ) + + if request.method == "PUT": + partial_update = False + else: + partial_update = True + output = manager.update( service_config_id=service_config_id, service_template=template, allow_different_service_public_id=allow_different_service_public_id, - partial_update=False, + partial_update=partial_update, ) return JSONResponse(content=output.json) - @app.patch("/api/v2/service/{service_config_id}") @with_retries async def _partial_update_service(request: Request) -> JSONResponse: """Partially update a service (merge update).""" diff --git a/operate/services/manage.py b/operate/services/manage.py index 276be943..f728ee3e 100644 --- a/operate/services/manage.py +++ b/operate/services/manage.py @@ -585,8 +585,37 @@ def _deploy_service_onchain_from_safe( # pylint: disable=too-many-statements,to ): # TODO: This is possibly not a good idea: we are setting up a computed variable based on # the value passed in the template. - db_path = service.path / "persistent_data/memeooorr.db" - cookies_path = service.path / "persistent_data/twikit_cookies.json" + db_path = ( + service.path + / "persistent_data" + / service.env_variables["TWIKIT_USERNAME"]["value"] + / "memeooorr.db" + ) + cookies_path = ( + service.path + / "persistent_data" + / service.env_variables["TWIKIT_USERNAME"]["value"] + / "twikit_cookies.json" + ) + + # Patch: Move existing configurations to the new location + old_db_path = service.path / "persistent_data" / "memeooorr.db" + old_cookies_path = service.path / "persistent_data" / "twikit_cookies.json" + + for old_path, new_path in [ + (old_db_path, db_path), + (old_cookies_path, cookies_path), + ]: + if old_path.exists(): + self.logger.info(f"Moving {old_path} -> {new_path}") + new_path.parent.mkdir(parents=True, exist_ok=True) + try: + os.rename(old_path, new_path) + except OSError: + self.logger.info("Fallback to shutil.move") + shutil.move(str(old_path), str(new_path)) + time.sleep(3) + # End patch env_var_to_value.update( { diff --git a/tests/test_services_manage.py b/tests/test_services_manage.py index 7cc8a23f..4f840ceb 100644 --- a/tests/test_services_manage.py +++ b/tests/test_services_manage.py @@ -97,7 +97,7 @@ class TestServiceManager: @pytest.mark.parametrize("update_name", [True, False]) @pytest.mark.parametrize("update_description", [True, False]) @pytest.mark.parametrize("update_hash", [True, False]) - def test_service_update( + def test_service_manager_partial_update( self, update_new_var: bool, update_update_var: bool, @@ -181,3 +181,100 @@ def test_service_update( print(diff) assert not diff, "Updated service does not match expected service." + + @pytest.mark.parametrize("update_new_var", [True, False]) + @pytest.mark.parametrize("update_update_var", [True, False]) + @pytest.mark.parametrize("update_delete_var", [True, False]) + @pytest.mark.parametrize("update_name", [True, False]) + @pytest.mark.parametrize("update_description", [True, False]) + @pytest.mark.parametrize("update_hash", [True, False]) + def test_service_manager_update( + self, + update_new_var: bool, + update_update_var: bool, + update_delete_var: bool, + update_name: bool, + update_description: bool, + update_hash: bool, + tmp_path: Path, + random_string: str, + ) -> None: + """Test operate.service_manager().update()""" + + operate = OperateApp( + home=tmp_path / ".operate_test", + ) + operate.setup() + password = random_string + operate.create_user_account(password=password) + operate.password = password + service_manager = operate.service_manager() + service_template = get_template(**DEFAULT_CONFIG_KWARGS) + service = service_manager.create(service_template) + service_config_id = service.service_config_id + service_json = service_manager.load(service_config_id).json + + new_hash = "bafybeicts6zhavxzz2rxahz3wzs2pzamoq64n64wp4q4cdanfuz7id6c2q" + VAR2_updated_attributes = { + "name": "var2_name_updated", + "description": "var2_description_updated", + "value": "var2_value_updated", + "provision_type": "var2_provision_type_updated", + "extra_attr": "extra_val", + } + + VAR3_attributes = { + "name": "var3_name", + "description": "var3_description", + "value": "var3_value", + "provision_type": "var3_provision_type", + } + + # Partial update + update_template: t.Dict = service_template.copy() + expected_service_json = service_json.copy() + + if update_new_var: + update_template["env_variables"] = update_template.get("env_variables", {}) + update_template["env_variables"]["VAR3"] = VAR3_attributes + expected_service_json["env_variables"]["VAR3"] = VAR3_attributes + + if update_update_var: + update_template["env_variables"] = update_template.get("env_variables", {}) + update_template["env_variables"]["VAR2"] = VAR2_updated_attributes + expected_service_json["env_variables"]["VAR2"] = VAR2_updated_attributes + + if update_delete_var: + update_template["env_variables"] = update_template.get("env_variables", {}) + del update_template["env_variables"]["VAR1"] + del expected_service_json["env_variables"]["VAR1"] + + if update_name: + update_template["name"] = "name_updated" + expected_service_json["name"] = "name_updated" + + if update_description: + update_template["description"] = "description_updated" + expected_service_json["description"] = "description_updated" + + if update_hash: + update_template["hash"] = new_hash + expected_service_json["hash"] = new_hash + + service_manager.update( + service_config_id=service_config_id, + service_template=update_template, + allow_different_service_public_id=False, + partial_update=False, + ) + service_json = service_manager.load(service_config_id).json + + if update_hash: + timestamp = max(service_json["hash_history"].keys()) + expected_service_json["hash_history"][timestamp] = new_hash + + diff = DeepDiff(service_json, expected_service_json) + if diff: + print(diff) + + assert not diff, "Updated service does not match expected service." From 231024893da883e12b3f4d6a5c36728a5f59578c Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 12:41:06 +0100 Subject: [PATCH 08/15] doc: api --- api.md | 56 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 56 insertions(+) diff --git a/api.md b/api.md index dff57591..546198ee 100644 --- a/api.md +++ b/api.md @@ -714,6 +714,62 @@ Update service configuration `service_config_id` with the provided template. --- +### `PUSH /api/v2/service/{service_config_id}` + +Partial update service configuration `service_config_id` with the provided (partial) template. + +
+ Request + +```json + { + "configurations": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeibpseosblmaw6sk6zsnic2kfxfsijrnfluuhkwboyqhx7ma7zw2me", + "image": "https://operate.olas.network/_next/image?url=%2Fimages%2Fprediction-agent.png&w=3840&q=75", + "home_chain": "gnosis", + "name": "valory/trader_omen_gnosis", + "service_version": "v0.19.0" + } +``` + +
+ +
+ Response + +- If the update is successful, the response contains the updated service configuration: + + ```json + { + "chain_configs": {...}, + "description": "Trader agent for omen prediction markets", + "env_variables": {...}, + "hash": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", + "hash_history": {"1731487112": "bafybeidicxsruh3r4a2xarawzan6ocwyvpn3ofv42po5kxf7x6ck7kn22u", "1731490000": "bafybeibpseosblmaw6sk6zsnic2kfxfsijrnfluuhkwboyqhx7ma7zw2me"}, + "home_chain": "gnosis", + "keys": [...], + "name": "valory/trader_omen_gnosis", + "service_config_id": "sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39", + "service_path": "/home/user/.operate/services/sc-85a7a12a-8c6b-46b8-919a-b8a3b8e3ad39/trader_omen_gnosis" + } + + ``` + +- If the update is not successful: + + ```json + { + "error": "Error message", + "traceback": "Traceback message" + } + ``` + +
+ +--- + ### `POST /api/service/{service_config_id}/stop` Stop service with service configuration `service_configuration_id`. From 10a247c12264273a8451b54a9b5b9c42df00e07f Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 12:42:43 +0100 Subject: [PATCH 09/15] chore: update --- operate/cli.py | 25 ------------------------- 1 file changed, 25 deletions(-) diff --git a/operate/cli.py b/operate/cli.py index b2b9b497..48c50648 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -788,31 +788,6 @@ async def _update_service(request: Request) -> JSONResponse: return JSONResponse(content=output.json) - @with_retries - async def _partial_update_service(request: Request) -> JSONResponse: - """Partially update a service (merge update).""" - if operate.password is None: - return USER_NOT_LOGGED_IN_ERROR - - service_config_id = request.path_params["service_config_id"] - manager = operate.service_manager() - - if not manager.exists(service_config_id=service_config_id): - return service_not_found_error(service_config_id=service_config_id) - - template = await request.json() - allow_different_service_public_id = template.get( - "allow_different_service_public_id", False - ) - output = manager.update( - service_config_id=service_config_id, - service_template=template, - allow_different_service_public_id=allow_different_service_public_id, - partial_update=True, - ) - - return JSONResponse(content=output.json) - @app.put("/api/v2/services") @with_retries async def _update_all_services(request: Request) -> JSONResponse: From 19cd810425ad48c61afbf8633f10d89ef671972e Mon Sep 17 00:00:00 2001 From: Atatakai Date: Fri, 20 Dec 2024 18:21:46 +0400 Subject: [PATCH 10/15] chore: change PUT to PATCH in updateService --- .../MainPage/header/AgentButton/AgentNotRunningButton.tsx | 4 ++++ frontend/service/Services.ts | 2 +- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index bee5fb72..1833da2b 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -248,6 +248,10 @@ const useServiceDeployment = () => { } // Update the service if the hash is different + // TODO: "updateService" now uses PATCH instead of PUT, + // which means it updates only the provided values. + // Ideally we should consider rewriting this code + // so that only hash value is passed if (!middlewareServiceResponse && service) { if (service.hash !== serviceTemplate.hash) { await ServicesService.updateService({ diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index 32bc2196..61c3b264 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -109,7 +109,7 @@ const updateService = async ({ useMechMarketplace?: boolean; }): Promise => fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { - method: 'PUT', + method: 'PATCH', body: JSON.stringify({ ...serviceTemplate, deploy, From ff7ce1fbb11f16d0ace6859a9d89df5b043fcead Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 15:37:07 +0100 Subject: [PATCH 11/15] chore: update doc --- api.md | 4 +++- docs/images/partial_update_examples.png | Bin 0 -> 120878 bytes 2 files changed, 3 insertions(+), 1 deletion(-) create mode 100644 docs/images/partial_update_examples.png diff --git a/api.md b/api.md index 546198ee..ae12f3f1 100644 --- a/api.md +++ b/api.md @@ -714,10 +714,12 @@ Update service configuration `service_config_id` with the provided template. --- -### `PUSH /api/v2/service/{service_config_id}` +### `PATCH /api/v2/service/{service_config_id}` Partial update service configuration `service_config_id` with the provided (partial) template. +![Partial updates](docs/images/partial_update_examples.png) +
Request diff --git a/docs/images/partial_update_examples.png b/docs/images/partial_update_examples.png new file mode 100644 index 0000000000000000000000000000000000000000..732ef3613b2c5337b0fe4268d0a5c4be5d3783ae GIT binary patch literal 120878 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 literal 0 HcmV?d00001 From be3e5c4478ff28232ccccb0439d15e7f1bb3dd75 Mon Sep 17 00:00:00 2001 From: jmoreira-valory Date: Fri, 20 Dec 2024 18:13:26 +0100 Subject: [PATCH 12/15] chore: updates --- frontend/service/Services.ts | 21 +-------------------- operate/cli.py | 6 +++++- 2 files changed, 6 insertions(+), 21 deletions(-) diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index 61c3b264..21f2ac25 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -110,26 +110,7 @@ const updateService = async ({ }): Promise => fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { method: 'PATCH', - body: JSON.stringify({ - ...serviceTemplate, - deploy, - configurations: { - ...serviceTemplate.configurations, - // overwrite defaults with chain-specific configurations - ...Object.entries(serviceTemplate.configurations).reduce( - (acc, [middlewareChain, config]) => { - acc[middlewareChain] = { - ...config, - rpc: CHAIN_CONFIG[asEvmChainId(middlewareChain)].rpc, - staking_program_id: stakingProgramId, - use_mech_marketplace: useMechMarketplace, - }; - return acc; - }, - {} as typeof serviceTemplate.configurations, - ), - }, - }), + body: JSON.stringify({ hash: serviceTemplate.hash }), headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { diff --git a/operate/cli.py b/operate/cli.py index 48c50648..6f156f5f 100644 --- a/operate/cli.py +++ b/operate/cli.py @@ -268,7 +268,7 @@ def pause_all_services_on_exit(signum: int, frame: t.Optional[FrameType]) -> Non app.add_middleware( CORSMiddleware, allow_origins=["*"], - allow_methods=["GET", "POST", "PUT", "DELETE"], + allow_methods=["GET", "POST", "PUT", "PATCH", "DELETE"], ) def with_retries(f: t.Callable) -> t.Callable: @@ -779,6 +779,10 @@ async def _update_service(request: Request) -> JSONResponse: else: partial_update = True + logger.info( + f"_update_service {partial_update=} {allow_different_service_public_id=}" + ) + output = manager.update( service_config_id=service_config_id, service_template=template, From f92c8463e96a08a067df33dbba491c3983329796 Mon Sep 17 00:00:00 2001 From: Atatakai Date: Tue, 24 Dec 2024 14:16:20 +0400 Subject: [PATCH 13/15] feat: support patch in update service --- frontend/client/types.ts | 4 +- .../AgentButton/AgentNotRunningButton.tsx | 15 ++----- .../StakingContractSection/MigrateButton.tsx | 45 ++++++++++++++----- frontend/service/Services.ts | 15 +++---- 4 files changed, 45 insertions(+), 34 deletions(-) diff --git a/frontend/client/types.ts b/frontend/client/types.ts index 7c811316..ccfd2c36 100644 --- a/frontend/client/types.ts +++ b/frontend/client/types.ts @@ -39,8 +39,8 @@ export type ChainData = { nft: string; staking_program_id: StakingProgramId; threshold: number; - use_mech_marketplace: true; - use_staking: true; + use_mech_marketplace: boolean; + use_staking: boolean; }; }; diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index 1833da2b..375d7101 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -248,22 +248,13 @@ const useServiceDeployment = () => { } // Update the service if the hash is different - // TODO: "updateService" now uses PATCH instead of PUT, - // which means it updates only the provided values. - // Ideally we should consider rewriting this code - // so that only hash value is passed if (!middlewareServiceResponse && service) { if (service.hash !== serviceTemplate.hash) { await ServicesService.updateService({ serviceConfigId: service.service_config_id, - stakingProgramId: selectedStakingProgramId, - // chainId: selectedAgentConfig.evmHomeChainId, - serviceTemplate, - deploy: false, // TODO: deprecated will remove - useMechMarketplace: - STAKING_PROGRAMS[selectedAgentConfig.evmHomeChainId][ - selectedStakingProgramId - ].mechType === MechType.Marketplace, + partialService: { + hash: serviceTemplate.hash, + }, }); } } diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx index 21de1504..0841235a 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -128,23 +128,48 @@ export const MigrateButton = ({ overrideSelectedServiceStatus(MiddlewareDeploymentStatus.DEPLOYING); goto(Pages.Main); - const serviceConfigParams = { - stakingProgramId: stakingProgramIdToMigrateTo, - serviceTemplate, - deploy: true, - useMechMarketplace: - stakingProgramIdToMigrateTo === - StakingProgramId.PearlBetaMechMarketplace, - }; - if (selectedService) { // update service await ServicesService.updateService({ - ...serviceConfigParams, serviceConfigId, + partialService: { + chain_configs: { + ...selectedService.chain_configs, + // overwrite defaults with chain-specific configurations + ...Object.entries(selectedService.chain_configs).reduce( + (acc, [middlewareChain, config]) => { + acc[middlewareChain] = { + ...config, + chain_data: { + ...config.chain_data, + user_params: { + ...config.chain_data.user_params, + staking_program_id: stakingProgramIdToMigrateTo, + use_mech_marketplace: + stakingProgramIdToMigrateTo === + StakingProgramId.PearlBetaMechMarketplace, + }, + }, + }; + return acc; + }, + {} as typeof selectedService.chain_configs, + ), + }, + }, }); } else { // create service if it doesn't exist + + const serviceConfigParams = { + stakingProgramId: stakingProgramIdToMigrateTo, + serviceTemplate, + deploy: true, + useMechMarketplace: + stakingProgramIdToMigrateTo === + StakingProgramId.PearlBetaMechMarketplace, + }; + await ServicesService.createService(serviceConfigParams); } diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index 21f2ac25..1cc43958 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -9,6 +9,7 @@ import { CONTENT_TYPE_JSON_UTF8 } from '@/constants/headers'; import { BACKEND_URL_V2 } from '@/constants/urls'; import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; +import { Service } from '@/types/Service'; import { asEvmChainId } from '@/utils/middlewareHelpers'; /** @@ -92,25 +93,19 @@ const createService = async ({ /** * Updates a service - * @param serviceTemplate + * @param partialService * @returns Promise */ const updateService = async ({ - deploy, - serviceTemplate, + partialService, serviceConfigId, - stakingProgramId, - useMechMarketplace = false, }: { - deploy: boolean; - serviceTemplate: ServiceTemplate; + partialService: Partial; serviceConfigId: string; - stakingProgramId: StakingProgramId; - useMechMarketplace?: boolean; }): Promise => fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { method: 'PATCH', - body: JSON.stringify({ hash: serviceTemplate.hash }), + body: JSON.stringify({ partialService }), headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { From 4fbb641dc91678d84eebf450c5c19855d9ff248c Mon Sep 17 00:00:00 2001 From: Atatakai Date: Tue, 24 Dec 2024 14:32:06 +0400 Subject: [PATCH 14/15] fix: pass spread object --- frontend/service/Services.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index 1cc43958..41852a4b 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -105,7 +105,7 @@ const updateService = async ({ }): Promise => fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { method: 'PATCH', - body: JSON.stringify({ partialService }), + body: JSON.stringify({ ...partialService }), headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { From 25c1a6bc59dd836f72e1b981bd7bcc7e97fa0f8b Mon Sep 17 00:00:00 2001 From: Atatakai Date: Tue, 24 Dec 2024 16:25:18 +0400 Subject: [PATCH 15/15] fix: pass template instead of service --- .../AgentButton/AgentNotRunningButton.tsx | 2 +- .../StakingContractSection/MigrateButton.tsx | 37 +++++++------------ frontend/service/Services.ts | 10 ++--- frontend/types/Util.ts | 4 ++ 4 files changed, 24 insertions(+), 29 deletions(-) diff --git a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx index 375d7101..aa96c4a6 100644 --- a/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx +++ b/frontend/components/MainPage/header/AgentButton/AgentNotRunningButton.tsx @@ -252,7 +252,7 @@ const useServiceDeployment = () => { if (service.hash !== serviceTemplate.hash) { await ServicesService.updateService({ serviceConfigId: service.service_config_id, - partialService: { + partialServiceTemplate: { hash: serviceTemplate.hash, }, }); diff --git a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx index 0841235a..52c05115 100644 --- a/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx +++ b/frontend/components/ManageStakingPage/StakingContractSection/MigrateButton.tsx @@ -20,6 +20,7 @@ import { } from '@/hooks/useStakingContractDetails'; import { useStakingProgram } from '@/hooks/useStakingProgram'; import { ServicesService } from '@/service/Services'; +import { DeepPartial } from '@/types/Util'; import { CountdownUntilMigration } from './CountdownUntilMigration'; import { CantMigrateReason, useMigrate } from './useMigrate'; @@ -45,11 +46,10 @@ export const MigrateButton = ({ const { service } = useService(serviceConfigId); const serviceTemplate = useMemo( () => - service - ? getServiceTemplate(service.hash) - : SERVICE_TEMPLATES.find( - (template) => template.agentType === selectedAgentType, - ), + (service && getServiceTemplate(service.hash)) ?? + SERVICE_TEMPLATES.find( + (template) => template.agentType === selectedAgentType, + ), [selectedAgentType, service], ); @@ -132,28 +132,19 @@ export const MigrateButton = ({ // update service await ServicesService.updateService({ serviceConfigId, - partialService: { - chain_configs: { - ...selectedService.chain_configs, - // overwrite defaults with chain-specific configurations - ...Object.entries(selectedService.chain_configs).reduce( - (acc, [middlewareChain, config]) => { + partialServiceTemplate: { + configurations: { + ...Object.entries(serviceTemplate.configurations).reduce( + (acc, [middlewareChain]) => { acc[middlewareChain] = { - ...config, - chain_data: { - ...config.chain_data, - user_params: { - ...config.chain_data.user_params, - staking_program_id: stakingProgramIdToMigrateTo, - use_mech_marketplace: - stakingProgramIdToMigrateTo === - StakingProgramId.PearlBetaMechMarketplace, - }, - }, + staking_program_id: stakingProgramIdToMigrateTo, + use_mech_marketplace: + stakingProgramIdToMigrateTo === + StakingProgramId.PearlBetaMechMarketplace, }; return acc; }, - {} as typeof selectedService.chain_configs, + {} as DeepPartial, ), }, }, diff --git a/frontend/service/Services.ts b/frontend/service/Services.ts index 41852a4b..86b13ed3 100644 --- a/frontend/service/Services.ts +++ b/frontend/service/Services.ts @@ -9,7 +9,7 @@ import { CONTENT_TYPE_JSON_UTF8 } from '@/constants/headers'; import { BACKEND_URL_V2 } from '@/constants/urls'; import { StakingProgramId } from '@/enums/StakingProgram'; import { Address } from '@/types/Address'; -import { Service } from '@/types/Service'; +import { DeepPartial } from '@/types/Util'; import { asEvmChainId } from '@/utils/middlewareHelpers'; /** @@ -93,19 +93,19 @@ const createService = async ({ /** * Updates a service - * @param partialService + * @param partialServiceTemplate * @returns Promise */ const updateService = async ({ - partialService, + partialServiceTemplate, serviceConfigId, }: { - partialService: Partial; + partialServiceTemplate: DeepPartial; serviceConfigId: string; }): Promise => fetch(`${BACKEND_URL_V2}/service/${serviceConfigId}`, { method: 'PATCH', - body: JSON.stringify({ ...partialService }), + body: JSON.stringify({ ...partialServiceTemplate }), headers: { ...CONTENT_TYPE_JSON_UTF8 }, }).then((response) => { if (response.ok) { diff --git a/frontend/types/Util.ts b/frontend/types/Util.ts index e4bed10e..b39a8830 100644 --- a/frontend/types/Util.ts +++ b/frontend/types/Util.ts @@ -4,6 +4,10 @@ export type Optional = T | undefined; export type Maybe = Nullable>; +export type DeepPartial = { + [P in keyof T]?: T[P] extends object ? DeepPartial : T[P]; +}; + /** * function to strip off the null or undefined types from a type by making an assertion. * @note This function should be used if you are confident that the value will never ever be null or undefined.