diff --git a/examples/extension_service/Dockerfile b/examples/extension_service/Dockerfile index 9bb9a152b3343d3a48b5f07b511b528e2739955e..2c8ed85c1fe89a8792e59cd2999fe8ebb2f54d0a 100644 --- a/examples/extension_service/Dockerfile +++ b/examples/extension_service/Dockerfile @@ -11,7 +11,7 @@ ARG PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL} ENV PIP_EXTRA_INDEX_URL=$PIP_EXTRA_INDEX_URL COPY . /home/${USER}/app -RUN pip install perxis==0.0.16 +RUN pip install perxis==0.0.17 ENV PYTHONPATH="/home/perx/app" ENV PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python diff --git a/examples/extension_service/Dockerfile.local b/examples/extension_service/Dockerfile.local index 994d988a029b2c54363a269a7e55d0daff2f4da4..d8d0d31766a83b0069c695242665804a78e52890 100644 --- a/examples/extension_service/Dockerfile.local +++ b/examples/extension_service/Dockerfile.local @@ -11,7 +11,7 @@ ARG PIP_EXTRA_INDEX_URL=${PIP_EXTRA_INDEX_URL} ENV PIP_EXTRA_INDEX_URL=$PIP_EXTRA_INDEX_URL COPY . /home/${USER}/app -RUN pip install perxis==0.0.16 +RUN pip install perxis==0.0.17 RUN pip install 'watchdog[watchmedo]' ENV PYTHONPATH="/home/perx/app" diff --git a/examples/extension_service/server.py b/examples/extension_service/server.py index a4fb49cb79244b3f3bb8a01ef739f4a8e3361ad8..64bc3cf5ef3cb3bf21ed8d0175855932bbfb9ff5 100644 --- a/examples/extension_service/server.py +++ b/examples/extension_service/server.py @@ -18,7 +18,6 @@ def main(): interceptor = header_adder_interceptor( 'x-perxis-access', 'system' ) - with grpc.insecure_channel("extension-manager:9030") as extensions_manager_channel: intercept_channel_extensions_manager_channel = grpc.intercept_channel(extensions_manager_channel, interceptor) diff --git a/perxis/extensions/extension_setup.py b/perxis/extensions/extension_setup.py index 6f42a6261c44f98210dc80d7c5cc1243d95fb20c..a93e6fc64147bb8dd2c97309e8dec736c3ca6d3f 100644 --- a/perxis/extensions/extension_setup.py +++ b/perxis/extensions/extension_setup.py @@ -8,6 +8,7 @@ import typing from deepdiff import DeepDiff from perxis.collections import collections_pb2_grpc, collections_pb2 from perxis.roles import roles_pb2_grpc, roles_pb2 +from perxis.common import common_pb2 from perxis.clients import clients_pb2_grpc, clients_pb2 from perxis.environments import environments_pb2_grpc, environments_pb2 @@ -81,43 +82,82 @@ class ExtensionSetup: return errors_list - def __update_roles(self, space_id: str) -> list[str]: + def __update_roles(self, space_id: str, env_id: str) -> list[str]: errors_list = [] for local_role in self.roles: try: - cloned_role = copy.deepcopy(local_role) - cloned_role.space_id = space_id - - # Полностью замещать данные роли тем что имеется в расширении - # TODO: нужно ли мержить права чтобы не терять изменения? - self.roles_service.Update.with_call( - roles_pb2.UpdateRequest( - role=cloned_role + get_response, state = self.roles_service.Get.with_call( + roles_pb2.GetRequest( + space_id=space_id, + role_id=local_role.id ) ) + + role = get_response.role except grpc.RpcError as e: - errors_list.append(f"Не удалось обновить роль {local_role.id}, {e.details()}") + if "not found" not in e.details(): + errors_list.append(f"Не удалось получить роль {local_role.id}, {e.details()}") + continue - return errors_list + role = None - def __create_roles(self, space_id: str) -> list[str]: - errors_list = [] + cloned_role = copy.deepcopy(local_role) + cloned_role.space_id = space_id - for local_role in self.roles: - try: - cloned_role = copy.deepcopy(local_role) - cloned_role.space_id = space_id + if role: + if not role.environments: + role.environments[:] = [env_id] + elif env_id not in role.environments: + role.environments.append(env_id) - response, _ = self.roles_service.Create.with_call( - roles_pb2.CreateRequest( - role=cloned_role - ), - ) - except grpc.RpcError as e: - # На этапе install считается что ролей __нет__. При install с указанием force роли предварительно - # удаляются - errors_list.append(f"Не удалось создать роль {local_role.id}, {e.details()}") + cloned_role.environments[:] = role.environments + + # Произвести мерж правил доступа + for exist_rule in role.rules: + was_found = False + + for local_rule in cloned_role.rules: + # Если запись с правами доступа на коллекцию найдена - правила нужно совместить + if local_rule.collection_id == exist_rule.collection_id: + was_found = True + + local_rule.actions[:] = list(set(list(local_rule.actions) + list(exist_rule.actions))) + + break + + # Если правило для коллекций не было найдено - его нужно добавить + if not was_found: + cloned_role.rules.append(common_pb2.Rule( + collection_id=exist_rule.collection_id, + actions=list(exist_rule.actions) + )) + + try: + self.roles_service.Update.with_call( + roles_pb2.UpdateRequest( + role=cloned_role + ) + ) + except grpc.RpcError as e: + errors_list.append(f"Не удалось обновить роль {local_role.id}, {e.details()}") + else: + if env_id not in cloned_role.environments: + cloned_role.environments.append(env_id) + + try: + cloned_role = copy.deepcopy(local_role) + cloned_role.space_id = space_id + + response, _ = self.roles_service.Create.with_call( + roles_pb2.CreateRequest( + role=cloned_role + ), + ) + except grpc.RpcError as e: + # На этапе install считается что ролей __нет__. При install с указанием force роли предварительно + # удаляются + errors_list.append(f"Не удалось создать роль {local_role.id}, {e.details()}") return errors_list @@ -169,51 +209,47 @@ class ExtensionSetup: client = get_response.client except grpc.RpcError as e: - errors_list.append(f"Не удалось получить клиент {local_client.id}, {e.details()}") - - continue + if "not found" not in e.details(): + errors_list.append(f"Не удалось получить клиент {local_client.id}, {e.details()}") + continue - try: - # Нужно чтобы у клиента каждый раз не слетали данные токенов при переустановке - # свойства oauth, api_key и tls должны браться из __созданного__ клиента - new_client = clients_pb2.Client( - id=local_client.id, - space_id=space_id, - name=local_client.name, - description=local_client.description, - disabled=client.disabled, - role_id=local_client.role_id, - oauth=client.oauth, - api_key=client.api_key, - tls=client.tls - ) + client = None - self.clients_service.Update.with_call( - clients_pb2.UpdateRequest( - client=new_client + if client: + try: + # Нужно чтобы у клиента каждый раз не слетали данные токенов при переустановке + # свойства oauth, api_key и tls должны браться из __созданного__ клиента + new_client = clients_pb2.Client( + id=local_client.id, + space_id=space_id, + name=local_client.name, + description=local_client.description, + disabled=client.disabled, + role_id=local_client.role_id, + oauth=client.oauth or local_client.oauth, + api_key=client.api_key or local_client.api_key, + tls=client.tls ) - ) - except grpc.RpcError as e: - errors_list.append(f"Не удалось обновить клиент {local_client.id}, {e.details()}") - - return errors_list - - def __create_clients(self, space_id: str) -> list[str]: - errors_list = [] - for local_client in self.clients: - try: - cloned_client = copy.deepcopy(local_client) - cloned_client.space_id = space_id + self.clients_service.Update.with_call( + clients_pb2.UpdateRequest( + client=new_client + ) + ) + except grpc.RpcError as e: + errors_list.append(f"Не удалось обновить клиент {local_client.id}, {e.details()}") + else: + try: + cloned_client = copy.deepcopy(local_client) + cloned_client.space_id = space_id - response, _ = self.clients_service.Create.with_call( - clients_pb2.CreateRequest( - client=cloned_client - ), - ) - except grpc.RpcError as e: - # Как и с ролями считается что при install записей быть не должно в любом случае т.к. force всё удаляет - errors_list.append(f"Не удалось создать клиент {local_client.id}, {e.details()}") + response, _ = self.clients_service.Create.with_call( + clients_pb2.CreateRequest( + client=cloned_client + ), + ) + except grpc.RpcError as e: + errors_list.append(f"Не удалось создать клиент {local_client.id}, {e.details()}") return errors_list @@ -389,40 +425,6 @@ class ExtensionSetup: return error_message - def __create_collections(self, space_id: str, env_id: str) -> list[str]: - errors_list = [] - - for local_collection in self.collections: - try: - cloned_collection = copy.deepcopy(local_collection) - cloned_collection.space_id = space_id - cloned_collection.env_id = env_id - - response, _ = self.collections_service.Create.with_call( - collections_pb2.CreateRequest( - collection=cloned_collection - ), - ) - except grpc.RpcError as e: - errors_list.append(f"Не удалось создать коллекцию {local_collection.id}, {e.details()}") - - # Если коллекцию создать не удалось (по любой причине) дальнейшая обработка коллекции смысла - # не имеет - continue - - set_schema_error_message = self.__set_collection_schema( - space_id, env_id, local_collection.id, local_collection.schema - ) - if set_schema_error_message: - errors_list.append(set_schema_error_message) - - # Миграция окружения нужна в любом случае т.к. все коллекции были __созданы__ - migrate_environment_error_message = self.__migrate_environment(space_id, env_id) - if migrate_environment_error_message: - errors_list.append(migrate_environment_error_message) - - return errors_list - def install(self, space_id: str, env_id: str, use_force: bool) -> list[str]: errors = [] @@ -431,9 +433,9 @@ class ExtensionSetup: errors += self.__remove_clients(space_id) errors += self.__remove_roles(space_id) - errors += self.__create_collections(space_id, env_id) - errors += self.__create_roles(space_id) - errors += self.__create_clients(space_id) + errors += self.__update_collections(space_id, env_id) + errors += self.__update_roles(space_id, env_id) + errors += self.__update_clients(space_id) return errors @@ -441,19 +443,14 @@ class ExtensionSetup: errors = [] # В случае обновление расширения с флагом force нужно предварительно удалить все сущности. - # Фактически это переустановка а не удаление if use_force: errors += self.__remove_clients(space_id) errors += self.__remove_roles(space_id) errors += self.__remove_collections(space_id, env_id) - errors += self.__create_collections(space_id, env_id) - errors += self.__create_roles(space_id) - errors += self.__create_clients(space_id) - else: - errors += self.__update_collections(space_id, env_id) - errors += self.__update_roles(space_id) - errors += self.__update_clients(space_id) + errors += self.__update_collections(space_id, env_id) + errors += self.__update_roles(space_id, env_id) + errors += self.__update_clients(space_id) return errors diff --git a/setup.py b/setup.py index 1781eb7ca03cd21aa2036a67d541c2998393e190..97684b0a88e9b10112224c6939f5ac6d5ad724c9 100644 --- a/setup.py +++ b/setup.py @@ -14,7 +14,7 @@ def load_requirements(): setup( name='perxis', - version='0.0.16', + version='0.0.17', description='Perxis python client', long_description=long_description, long_description_content_type='text/markdown',