From 11b966af07251e1300f01881476c98485f367c1a Mon Sep 17 00:00:00 2001 From: lhhyung Date: Mon, 25 Nov 2024 13:51:24 +0900 Subject: [PATCH 01/11] fix: Add field "ref_region" in create region Signed-off-by: lhhyung --- src/spaceone/inventory_v2/service/region_service.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spaceone/inventory_v2/service/region_service.py b/src/spaceone/inventory_v2/service/region_service.py index 43c3db9..0c3c40d 100644 --- a/src/spaceone/inventory_v2/service/region_service.py +++ b/src/spaceone/inventory_v2/service/region_service.py @@ -51,7 +51,7 @@ def create_resource(self, params: dict) -> Region: params["updated_by"] = self.transaction.get_meta("collector_id") or "manual" params["region_key"] = f'{params["provider"]}.{params["region_code"]}' - # params["ref_region"] = f'{domain_id}.{workspace_id}.{params["region_key"]}' + params["ref_region"] = f'{domain_id}.{params["region_key"]}' return self.region_mgr.create_region(params) From 22678621c2f21b927f0d3fd1a35d251e611500f5 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 15:49:19 +0900 Subject: [PATCH 02/11] feat: Refactor Region service Signed-off-by: lhhyung --- src/spaceone/inventory_v2/error/region.py | 2 +- src/spaceone/inventory_v2/info/__init__.py | 2 - src/spaceone/inventory_v2/info/common_info.py | 20 --- src/spaceone/inventory_v2/info/region_info.py | 39 ----- .../inventory_v2/interface/grpc/region.py | 44 ++--- .../inventory_v2/manager/region_manager.py | 25 ++- src/spaceone/inventory_v2/model/__init__.py | 2 +- .../inventory_v2/model/region/database.py | 28 ++++ .../inventory_v2/model/region/region_model.py | 49 ------ .../inventory_v2/model/region/request.py | 60 +++++++ .../inventory_v2/model/region/response.py | 29 ++++ .../inventory_v2/service/region_service.py | 151 ++++++++++++------ 12 files changed, 252 insertions(+), 199 deletions(-) delete mode 100644 src/spaceone/inventory_v2/info/__init__.py delete mode 100644 src/spaceone/inventory_v2/info/common_info.py delete mode 100644 src/spaceone/inventory_v2/info/region_info.py create mode 100644 src/spaceone/inventory_v2/model/region/database.py delete mode 100644 src/spaceone/inventory_v2/model/region/region_model.py create mode 100644 src/spaceone/inventory_v2/model/region/request.py create mode 100644 src/spaceone/inventory_v2/model/region/response.py diff --git a/src/spaceone/inventory_v2/error/region.py b/src/spaceone/inventory_v2/error/region.py index 8499bee..ef8c36d 100644 --- a/src/spaceone/inventory_v2/error/region.py +++ b/src/spaceone/inventory_v2/error/region.py @@ -6,4 +6,4 @@ class ERROR_NOT_FOUND_USER_IN_REGION(ERROR_BASE): class ERROR_ALREADY_EXIST_USER_IN_REGION(ERROR_BASE): - _message = 'A user "{user_id}" is already exist in region ({region_id}).' \ No newline at end of file + _message = 'A user "{user_id}" is already exist in region ({region_id}).' diff --git a/src/spaceone/inventory_v2/info/__init__.py b/src/spaceone/inventory_v2/info/__init__.py deleted file mode 100644 index 96f2f5f..0000000 --- a/src/spaceone/inventory_v2/info/__init__.py +++ /dev/null @@ -1,2 +0,0 @@ -from spaceone.inventory_v2.info.common_info import * -from spaceone.inventory_v2.info.region_info import * \ No newline at end of file diff --git a/src/spaceone/inventory_v2/info/common_info.py b/src/spaceone/inventory_v2/info/common_info.py deleted file mode 100644 index 2a2b7dc..0000000 --- a/src/spaceone/inventory_v2/info/common_info.py +++ /dev/null @@ -1,20 +0,0 @@ -from google.protobuf.empty_pb2 import Empty -from spaceone.core.pygrpc.message_type import * - -__all__ = ['EmptyInfo', 'StatisticsInfo', 'AnalyzeInfo', 'ExportInfo'] - - -def EmptyInfo(): - return Empty() - - -def StatisticsInfo(result): - return change_struct_type(result) - - -def AnalyzeInfo(result): - return change_struct_type(result) - - -def ExportInfo(result): - return change_struct_type(result) diff --git a/src/spaceone/inventory_v2/info/region_info.py b/src/spaceone/inventory_v2/info/region_info.py deleted file mode 100644 index 0c0d77f..0000000 --- a/src/spaceone/inventory_v2/info/region_info.py +++ /dev/null @@ -1,39 +0,0 @@ -import functools -import logging -from spaceone.api.inventory.v2 import region_pb2 -from spaceone.core.pygrpc.message_type import * -from spaceone.core import utils -from spaceone.inventory_v2.model.region.region_model import Region - -__all__ = ["RegionInfo", "RegionsInfo"] - -_LOGGER = logging.getLogger(__name__) - - -def RegionInfo(region_vo: Region, minimal=False): - info = { - "region_id": region_vo.region_id, - "name": region_vo.name, - "region_code": region_vo.region_code, - "provider": region_vo.provider, - } - - if not minimal: - info.update( - { - "region_key": region_vo.region_key, - "tags": change_struct_type(region_vo.tags), - "domain_id": region_vo.domain_id, - "created_at": utils.datetime_to_iso8601(region_vo.created_at), - "updated_at": utils.datetime_to_iso8601(region_vo.updated_at), - } - ) - - return region_pb2.RegionInfo(**info) - - -def RegionsInfo(region_vos, total_count, **kwargs): - return region_pb2.RegionsInfo( - results=list(map(functools.partial(RegionInfo, **kwargs), region_vos)), - total_count=total_count, - ) diff --git a/src/spaceone/inventory_v2/interface/grpc/region.py b/src/spaceone/inventory_v2/interface/grpc/region.py index 88ab2af..239435a 100644 --- a/src/spaceone/inventory_v2/interface/grpc/region.py +++ b/src/spaceone/inventory_v2/interface/grpc/region.py @@ -1,45 +1,45 @@ -from spaceone.api.inventory.v2 import region_pb2, region_pb2_grpc +from spaceone.api.inventory_v2.v1 import region_pb2, region_pb2_grpc from spaceone.core.pygrpc import BaseAPI -class Region(BaseAPI, region_pb2_grpc.RegionServicer): +from spaceone.inventory_v2.service.region_service import RegionService + +class Region(BaseAPI, region_pb2_grpc.RegionServicer): pb2 = region_pb2 pb2_grpc = region_pb2_grpc def create(self, request, context): params, metadata = self.parse_request(request, context) - - with self.locator.get_service('RegionService', metadata) as region_service: - return self.locator.get_info('RegionInfo', region_service.create(params)) + region_svc = RegionService(metadata) + response: dict = region_svc.create(params) + return self.dict_to_message(response) def update(self, request, context): params, metadata = self.parse_request(request, context) - - with self.locator.get_service('RegionService', metadata) as region_service: - return self.locator.get_info('RegionInfo', region_service.update(params)) + region_svc = RegionService(metadata) + response: dict = region_svc.update(params) + return self.dict_to_message(response) def delete(self, request, context): params, metadata = self.parse_request(request, context) - - with self.locator.get_service('RegionService', metadata) as region_service: - region_service.delete(params) - return self.locator.get_info('EmptyInfo') + region_svc = RegionService(metadata) + region_svc.delete(params) + return self.empty() def get(self, request, context): params, metadata = self.parse_request(request, context) - - with self.locator.get_service('RegionService', metadata) as region_service: - return self.locator.get_info('RegionInfo', region_service.get(params)) + region_svc = RegionService(metadata) + response: dict = region_svc.get(params) + return self.dict_to_message(response) def list(self, request, context): params, metadata = self.parse_request(request, context) - - with self.locator.get_service('RegionService', metadata) as region_service: - region_vos, total_count = region_service.list(params) - return self.locator.get_info('RegionsInfo', region_vos, total_count, minimal=self.get_minimal(params)) + region_svc = RegionService(metadata) + response: dict = region_svc.list(params) + return self.dict_to_message(response) def stat(self, request, context): params, metadata = self.parse_request(request, context) - - with self.locator.get_service('RegionService', metadata) as region_service: - return self.locator.get_info('StatisticsInfo', region_service.stat(params)) \ No newline at end of file + region_svc = RegionService(metadata) + response: dict = region_svc.stat(params) + return self.dict_to_message(response) diff --git a/src/spaceone/inventory_v2/manager/region_manager.py b/src/spaceone/inventory_v2/manager/region_manager.py index 9f489df..084cda4 100644 --- a/src/spaceone/inventory_v2/manager/region_manager.py +++ b/src/spaceone/inventory_v2/manager/region_manager.py @@ -1,21 +1,19 @@ import logging -from typing import Tuple +from typing import Tuple, Union -from spaceone.core.model.mongo_model import QuerySet from spaceone.core.manager import BaseManager -from spaceone.inventory_v2.lib.resource_manager import ResourceManager -from spaceone.inventory_v2.model.region.region_model import Region +from spaceone.core.model.mongo_model import QuerySet +from spaceone.inventory_v2.model.region.database import Region -_LOGGER = logging.getLogger(__name__) +__ALL__ = ["RegionManager"] +_LOGGER = logging.getLogger(__name__) -class RegionManager(BaseManager, ResourceManager): - resource_keys = ["region_id"] - query_method = "list_regions" +class RegionManager(BaseManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) - self.region_model: Region = self.locator.get_model("Region") + self.region_model = Region() def create_region(self, params: dict) -> Region: def _rollback(vo: Region): @@ -24,7 +22,6 @@ def _rollback(vo: Region): region_vo: Region = self.region_model.create(params) self.transaction.add_rollback(_rollback, region_vo) - return region_vo def update_region_by_vo(self, params: dict, region_vo: Region) -> Region: @@ -41,11 +38,13 @@ def _rollback(old_data): def delete_region_by_vo(region_vo: Region) -> None: region_vo.delete() - def get_region(self, region_id: str, domain_id: str) -> Region: + def get_region( + self, region_id: str, domain_id: str, workspace_id: Union[str, None] = None + ) -> Region: conditions = {"region_id": region_id, "domain_id": domain_id} - # if workspace_id: - # conditions.update({"workspace_id": workspace_id}) + if workspace_id: + conditions.update({"workspace_id": workspace_id}) return self.region_model.get(**conditions) diff --git a/src/spaceone/inventory_v2/model/__init__.py b/src/spaceone/inventory_v2/model/__init__.py index 3602513..a40652a 100644 --- a/src/spaceone/inventory_v2/model/__init__.py +++ b/src/spaceone/inventory_v2/model/__init__.py @@ -1,6 +1,6 @@ from spaceone.inventory_v2.model.asset.database import Asset from spaceone.inventory_v2.model.asset_type.database import AssetType -from spaceone.inventory_v2.model.region.region_model import Region +from spaceone.inventory_v2.model.region.database import Region from spaceone.inventory_v2.model.collector.database import Collector from spaceone.inventory_v2.model.collector_rule.database import CollectorRule from spaceone.inventory_v2.model.collection_state.database import CollectionState diff --git a/src/spaceone/inventory_v2/model/region/database.py b/src/spaceone/inventory_v2/model/region/database.py new file mode 100644 index 0000000..02ced02 --- /dev/null +++ b/src/spaceone/inventory_v2/model/region/database.py @@ -0,0 +1,28 @@ +from mongoengine import * + +from spaceone.core.model.mongo_model import MongoModel + + +class Region(MongoModel): + region_id = StringField(max_length=40, unique=True) + name = StringField(max_length=255) + region_code = StringField(max_length=255) + provider = StringField(max_length=255) + tags = DictField() + resource_group = StringField(max_length=40, choices=("DOMAIN", "WORKSPACE")) + workspace_id = StringField(max_length=40) + domain_id = StringField(max_length=40) + created_at = DateTimeField(auto_now_add=True) + updated_at = DateTimeField(auto_now=True) + + meta = { + "updatable_fields": ["name", "tags", "updated_at"], + "minimal_fields": ["region_id", "name", "region_code", "provider"], + "ordering": ["name"], + "indexes": [ + "provider", + "resource_group", + "workspace_id", + "domain_id", + ], + } diff --git a/src/spaceone/inventory_v2/model/region/region_model.py b/src/spaceone/inventory_v2/model/region/region_model.py deleted file mode 100644 index 2b51044..0000000 --- a/src/spaceone/inventory_v2/model/region/region_model.py +++ /dev/null @@ -1,49 +0,0 @@ -from mongoengine import * -from spaceone.core.model.mongo_model import MongoModel - - -class Region(MongoModel): - region_id = StringField(max_length=40, generate_id="region", unique=True) - name = StringField(max_length=255) - region_key = StringField(max_length=255) - region_code = StringField( - max_length=255, unique_with=["provider", "domain_id"] - ) - provider = StringField(max_length=255) - ref_region = StringField(max_length=255) - tags = DictField() - domain_id = StringField(max_length=40) - updated_by = StringField(default=None, null=True) - created_at = DateTimeField(auto_now_add=True) - updated_at = DateTimeField(auto_now=True) - - meta = { - "updatable_fields": ["name", "tags", "updated_by", "updated_at"], - "minimal_fields": ["region_id", "name", "region_code", "provider"], - "ordering": ["name"], - "indexes": [ - { - "fields": ["domain_id", "-updated_at", "updated_by"], - "name": "COMPOUND_INDEX_FOR_GC_1", - }, - { - "fields": ["domain_id", "region_id"], - "name": "COMPOUND_INDEX_FOR_SEARCH_1", - }, - { - "fields": ["domain_id", "provider", "region_code"], - "name": "COMPOUND_INDEX_FOR_SEARCH_2", - }, - { - "fields": ["domain_id", "region_key"], - "name": "COMPOUND_INDEX_FOR_SEARCH_3", - }, - {"fields": ["region_id", "ref_region"], "name": "COMPOUND_INDEX_FOR_REF_1"}, - { - "fields": ["region_code", "provider", "ref_region"], - "name": "COMPOUND_INDEX_FOR_REF_2", - }, - "ref_region", - "domain_id", - ], - } diff --git a/src/spaceone/inventory_v2/model/region/request.py b/src/spaceone/inventory_v2/model/region/request.py new file mode 100644 index 0000000..b36b353 --- /dev/null +++ b/src/spaceone/inventory_v2/model/region/request.py @@ -0,0 +1,60 @@ +from typing import Union, Literal +from pydantic import BaseModel + +__all__ = [ + "RegionCreateRequest", + "RegionUpdateRequest", + "RegionDeleteRequest", + "RegionGetRequest", + "RegionSearchQueryRequest", + "RegionStatQueryRequest", +] + +ResourceGroup = Literal["DOMAIN", "WORKSPACE"] + + +class RegionCreateRequest(BaseModel): + name: str + region_code: str + provider: str + tags: Union[dict, None] = None + resource_group: ResourceGroup + workspace_id: Union[str, None] = None + domain_id: str + + +class RegionUpdateRequest(BaseModel): + region_id: str + name: str = None + tags: Union[dict, None] = None + workspace_id: Union[str, None] = None + domain_id: str + + +class RegionDeleteRequest(BaseModel): + region_id: str + workspace_id: Union[str, None] = None + domain_id: str + + +class RegionGetRequest(BaseModel): + region_id: str + workspace_id: Union[str, None] = None + domain_id: str + + +class RegionSearchQueryRequest(BaseModel): + query: Union[dict, None] = None + region_id: Union[str, None] = None + name: Union[str, None] = None + region_code: Union[str, None] = None + provider: Union[str, None] = None + exists_only: Union[bool, None] = None + workspace_id: Union[str, None] = None + domain_id: str + + +class RegionStatQueryRequest(BaseModel): + query: dict + workspace_id: Union[str, None] = None + domain_id: str diff --git a/src/spaceone/inventory_v2/model/region/response.py b/src/spaceone/inventory_v2/model/region/response.py new file mode 100644 index 0000000..bbaa319 --- /dev/null +++ b/src/spaceone/inventory_v2/model/region/response.py @@ -0,0 +1,29 @@ +from datetime import datetime +from typing import Union, List +from pydantic import BaseModel + +from spaceone.core import utils + +__all__ = ["RegionResponse", "RegionsResponse"] + + +class RegionResponse(BaseModel): + region_id: Union[str, None] = None + name: Union[str, None] = None + region_code: Union[str, None] = None + provider: Union[str, None] = None + tags: Union[dict, None] = None + domain_id: Union[str, None] = None + created_at: Union[datetime, None] = None + updated_at: Union[datetime, None] = None + + def dict(self, *args, **kwargs): + data = super().dict(*args, **kwargs) + data["created_at"] = utils.datetime_to_iso8601(data["created_at"]) + data["updated_at"] = utils.datetime_to_iso8601(data["updated_at"]) + return data + + +class RegionsResponse(BaseModel): + results: List[RegionResponse] + total_count: int diff --git a/src/spaceone/inventory_v2/service/region_service.py b/src/spaceone/inventory_v2/service/region_service.py index 1657cac..0e70a49 100644 --- a/src/spaceone/inventory_v2/service/region_service.py +++ b/src/spaceone/inventory_v2/service/region_service.py @@ -1,10 +1,16 @@ import logging -from typing import Tuple -from spaceone.core.service import * +from typing import Union + +from mongoengine import QuerySet from spaceone.core import utils -from spaceone.core.model.mongo_model import QuerySet +from spaceone.core.error import * +from spaceone.core.service import * + from spaceone.inventory_v2.manager.region_manager import RegionManager -from spaceone.inventory_v2.model.region.region_model import Region +from spaceone.inventory_v2.manager.identity_manager import IdentityManager +from spaceone.inventory_v2.model import Region +from spaceone.inventory_v2.model.region.request import * +from spaceone.inventory_v2.model.region.response import * _LOGGER = logging.getLogger(__name__) _KEYWORD_FILTER = ["region_id", "name", "region_code"] @@ -19,53 +25,72 @@ class RegionService(BaseService): def __init__(self, metadata): super().__init__(metadata) - self.region_mgr: RegionManager = self.locator.get_manager("RegionManager") + self.region_mgr = RegionManager() @transaction( - permission="inventory:Region.write", + permission="inventory-v2:Region.write", role_types=["DOMAIN_ADMIN"], ) - def create(self, params: dict) -> Region: + def create(self, params: RegionCreateRequest) -> Union[RegionResponse, dict]: """ Args: params (dict): { - 'name': 'str', # required - 'region_code': 'str', # required - 'provider': 'str', # required + 'region_id': 'str, + 'name': 'str', # required + 'region_code': 'str', # required + 'provider': 'str', # required 'tags': 'dict', - 'domain_id': 'str', # injected from auth (required) + 'resource_group': 'str', # required + 'workspace_id': 'str', # injected from auth + 'domain_id': 'str', # injected from auth (required) } Returns: - region_vo (object) + RegionResponse: """ return self.create_resource(params) - @check_required(["name", "region_code", "provider", "domain_id"]) - def create_resource(self, params: dict) -> Region: - if "tags" in params: - if isinstance(params["tags"], list): - params["tags"] = utils.tags_to_dict(params["tags"]) + @convert_model + def create_resource( + self, params: RegionCreateRequest + ) -> Union[RegionResponse, dict]: + + identity_mgr = IdentityManager() + + domain_id = params.domain_id + workspace_id = params.workspace_id + resource_group = params.resource_group - domain_id = params["domain_id"] + # Check permission by resource group + if resource_group == "WORKSPACE": + if workspace_id is None: + raise ERROR_REQUIRED_PARAMETER(key="workspace_id") - params["updated_by"] = self.transaction.get_meta("collector_id") or "manual" - params["region_key"] = f'{params["provider"]}.{params["region_code"]}' - params["ref_region"] = f'{domain_id}.{params["region_key"]}' + identity_mgr.check_workspace(workspace_id, domain_id) + else: + params.workspace_id = "*" - return self.region_mgr.create_region(params) + region_id = f"{params.provider}-{params.region_code}" + + params_data = params.dict() + params_data["region_id"] = region_id + + region_vo = self.region_mgr.create_region(params_data) + + return RegionResponse(**region_vo.to_dict()) @transaction( - permission="inventory:Region.write", + permission="inventory-v2:Region.write", role_types=["DOMAIN_ADMIN"], ) - def update(self, params: dict) -> Region: + def update(self, params: RegionUpdateRequest) -> Union[RegionResponse, dict]: """ Args: params (dict): { 'region_id': 'str', # required 'name': 'str', 'tags': 'dict', + 'workspace_id': 'str', # injected from auth 'domain_id': 'str', # injected from auth (required) } Returns: @@ -74,26 +99,31 @@ def update(self, params: dict) -> Region: return self.update_resource(params) - @check_required(["region_id", "domain_id"]) - def update_resource(self, params: dict) -> Region: - if "tags" in params: - if isinstance(params["tags"], list): - params["tags"] = utils.tags_to_dict(params["tags"]) + @convert_model + def update_resource( + self, params: RegionUpdateRequest + ) -> Union[RegionResponse, dict]: + + region_vo = self.region_mgr.get_region( + params.region_id, params.domain_id, params.workspace_id + ) - params["updated_by"] = self.transaction.get_meta("collector_id") or "manual" + region_vo = self.region_mgr.update_region_by_vo( + params.dict(exclude_unset=True), region_vo + ) - region_vo = self.region_mgr.get_region(params["region_id"], params["domain_id"]) - return self.region_mgr.update_region_by_vo(params, region_vo) + return RegionResponse(**region_vo.to_dict()) @transaction( - permission="inventory:Region.write", + permission="inventory-v2:Region.write", role_types=["DOMAIN_ADMIN"], ) - def delete(self, params: dict) -> None: + def delete(self, params: RegionDeleteRequest) -> None: """ Args: params (dict): { 'region_id': 'str', # required + 'workspace_id': 'str', # injected from auth 'domain_id': 'str' # injected from auth (required) } Returns: @@ -102,21 +132,25 @@ def delete(self, params: dict) -> None: self.delete_resource(params) - @check_required(["region_id", "domain_id"]) - def delete_resource(self, params: dict) -> None: - region_vo = self.region_mgr.get_region(params["region_id"], params["domain_id"]) + @convert_model + def delete_resource(self, params: RegionDeleteRequest) -> None: + region_vo = self.region_mgr.get_region( + params.region_id, params.domain_id, params.workspace_id + ) self.region_mgr.delete_region_by_vo(region_vo) @transaction( - permission="inventory:Region.read", + permission="inventory-v2:Region.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) - @check_required(["region_id", "domain_id"]) - def get(self, params: dict) -> Region: + @change_value_by_rule("APPEND", "workspace_id", "*") + @convert_model + def get(self, params: RegionGetRequest) -> Union[RegionResponse, dict]: """ Args: params (dict): { 'region_id': 'str', # required + 'workspace_id': 'str', # injected from auth 'domain_id': 'str', # injected from auth (required) } @@ -125,34 +159,41 @@ def get(self, params: dict) -> Region: """ - return self.region_mgr.get_region(params["region_id"], params["domain_id"]) + region_vo = self.region_mgr.get_region( + params.region_id, params.domain_id, params.workspace_id + ) + + return RegionResponse(**region_vo.to_dict()) @transaction( - permission="inventory:Region.read", + permission="inventory-v2:Region.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) - @check_required(["domain_id"]) @append_query_filter( [ "region_id", "name", - "region_key", "region_code", "provider", + "exists_only", + "workspace_id", "domain_id", ] ) @append_keyword_filter(_KEYWORD_FILTER) - def list(self, params: dict) -> Tuple[QuerySet, int]: + @change_value_by_rule("APPEND", "workspace_id", "*") + @convert_model + def list(self, params: RegionSearchQueryRequest) -> Union[RegionsResponse, dict]: """ Args: params (dict): { 'query': 'dict (spaceone.api.core.v1.Query)', 'region_id': 'str', 'name': 'str', - 'region_key': 'str', 'region_code': 'str', 'provider': 'str', + 'exists_only': 'bool', + 'workspace_id': 'str', # injected from auth 'domain_id': 'str', # injected from auth (required) } @@ -162,16 +203,22 @@ def list(self, params: dict) -> Tuple[QuerySet, int]: """ - return self.region_mgr.list_regions(params.get("query", {})) + query = params.query or {} + region_vos, total_count = self.region_mgr.list_regions(query=query) + + regions_info = [region_vo.to_dict() for region_vo in region_vos] + + return RegionsResponse(results=regions_info, total_count=total_count) @transaction( - permission="inventory:Region.read", + permission="inventory-v2:Region.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) - @check_required(["query", "domain_id"]) - @append_query_filter(["domain_id"]) + @append_query_filter(["workspace_id", "domain_id"]) @append_keyword_filter(_KEYWORD_FILTER) - def stat(self, params: dict) -> dict: + @change_value_by_rule("APPEND", "workspace_id", "*") + @convert_model + def stat(self, params: RegionStatQueryRequest) -> dict: """ Args: params (dict): { @@ -184,5 +231,5 @@ def stat(self, params: dict) -> dict: """ - query = params.get("query", {}) + query = params.query or {} return self.region_mgr.stat_regions(query) From ea9163c7c2e84c7801b752da1d1d872246cb5bf3 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 16:17:36 +0900 Subject: [PATCH 03/11] fix: Fix Region request model Signed-off-by: lhhyung --- src/spaceone/inventory_v2/model/region/request.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/spaceone/inventory_v2/model/region/request.py b/src/spaceone/inventory_v2/model/region/request.py index b36b353..c56ee2d 100644 --- a/src/spaceone/inventory_v2/model/region/request.py +++ b/src/spaceone/inventory_v2/model/region/request.py @@ -39,7 +39,7 @@ class RegionDeleteRequest(BaseModel): class RegionGetRequest(BaseModel): region_id: str - workspace_id: Union[str, None] = None + workspace_id: Union[list, str, None] = None domain_id: str @@ -50,11 +50,11 @@ class RegionSearchQueryRequest(BaseModel): region_code: Union[str, None] = None provider: Union[str, None] = None exists_only: Union[bool, None] = None - workspace_id: Union[str, None] = None + workspace_id: Union[list, str, None] = None domain_id: str class RegionStatQueryRequest(BaseModel): query: dict - workspace_id: Union[str, None] = None + workspace_id: Union[list, str, None] = None domain_id: str From c43da6178cba9726ff0afe6f707d39f58f4b7fd6 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 16:17:46 +0900 Subject: [PATCH 04/11] fix: Fix Collector request model Signed-off-by: lhhyung --- src/spaceone/inventory_v2/model/collector/request.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/spaceone/inventory_v2/model/collector/request.py b/src/spaceone/inventory_v2/model/collector/request.py index 1cbd1e1..f7e34f5 100644 --- a/src/spaceone/inventory_v2/model/collector/request.py +++ b/src/spaceone/inventory_v2/model/collector/request.py @@ -71,7 +71,7 @@ class CollectorGetRequest(BaseModel): class CollectorSearchQueryRequest(BaseModel): query: Union[dict, None] = None collector_id: Union[str, None] = None - workspace_id: Union[str, list, None] = None + workspace_id: Union[list, str, None] = None domain_id: str From 5a4e55760a93e1910de2624b03f0bc36f86e0eb5 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 16:19:56 +0900 Subject: [PATCH 05/11] fix: Refactor annotations by removing unnecessary Signed-off-by: lhhyung --- src/spaceone/inventory_v2/model/asset/database.py | 2 +- src/spaceone/inventory_v2/service/collector_service.py | 2 -- 2 files changed, 1 insertion(+), 3 deletions(-) diff --git a/src/spaceone/inventory_v2/model/asset/database.py b/src/spaceone/inventory_v2/model/asset/database.py index d21f4a8..5c3d957 100644 --- a/src/spaceone/inventory_v2/model/asset/database.py +++ b/src/spaceone/inventory_v2/model/asset/database.py @@ -5,7 +5,7 @@ from spaceone.inventory_v2.model.asset_type.database import AssetType from spaceone.inventory_v2.error.asset import ERROR_RESOURCE_ALREADY_DELETED -from spaceone.inventory_v2.model.region.region_model import Region +from spaceone.inventory_v2.model.region.database import Region class Asset(MongoModel): diff --git a/src/spaceone/inventory_v2/service/collector_service.py b/src/spaceone/inventory_v2/service/collector_service.py index 50befd2..29465c7 100644 --- a/src/spaceone/inventory_v2/service/collector_service.py +++ b/src/spaceone/inventory_v2/service/collector_service.py @@ -317,7 +317,6 @@ def verify_plugin(self, params: CollectorVerifyPluginRequest) -> None: permission="inventory-v2:Collector.write", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER"], ) - @check_required(["collector_id", "domain_id"]) @convert_model def delete(self, params: CollectorDeleteRequest) -> None: """Delete collector @@ -389,7 +388,6 @@ def get(self, params: CollectorGetRequest) -> Union[CollectorResponse, dict]: permission="inventory-v2:Collector.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) - @check_required(["domain_id"]) @append_query_filter( [ "collector_id", From 71b5445af3dd3d96984257ec18fece34df2f1673 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 18:33:19 +0900 Subject: [PATCH 06/11] fix: Fix type of workspace_id field in region request Signed-off-by: lhhyung --- src/spaceone/inventory_v2/model/region/request.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/spaceone/inventory_v2/model/region/request.py b/src/spaceone/inventory_v2/model/region/request.py index c56ee2d..5a9e6b5 100644 --- a/src/spaceone/inventory_v2/model/region/request.py +++ b/src/spaceone/inventory_v2/model/region/request.py @@ -27,13 +27,13 @@ class RegionUpdateRequest(BaseModel): region_id: str name: str = None tags: Union[dict, None] = None - workspace_id: Union[str, None] = None + workspace_id: Union[list, str, None] = None domain_id: str class RegionDeleteRequest(BaseModel): region_id: str - workspace_id: Union[str, None] = None + workspace_id: Union[list, str, None] = None domain_id: str From d50cc349913b496e947c4ed4dd4dbdd3e96a53ee Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 18:34:52 +0900 Subject: [PATCH 07/11] fix: Fix type of workspace_id in get_region Signed-off-by: lhhyung --- src/spaceone/inventory_v2/manager/region_manager.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/src/spaceone/inventory_v2/manager/region_manager.py b/src/spaceone/inventory_v2/manager/region_manager.py index 084cda4..fdc894f 100644 --- a/src/spaceone/inventory_v2/manager/region_manager.py +++ b/src/spaceone/inventory_v2/manager/region_manager.py @@ -39,7 +39,10 @@ def delete_region_by_vo(region_vo: Region) -> None: region_vo.delete() def get_region( - self, region_id: str, domain_id: str, workspace_id: Union[str, None] = None + self, + region_id: str, + domain_id: str, + workspace_id: Union[list, str, None] = None, ) -> Region: conditions = {"region_id": region_id, "domain_id": domain_id} From a3659c0242b8a9daada5a1eedf6dd08674f1b9a5 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Tue, 10 Dec 2024 18:39:04 +0900 Subject: [PATCH 08/11] refactor: Update transaction roles and refactor create, update, delete method in Region Service Signed-off-by: lhhyung --- .../inventory_v2/service/region_service.py | 65 +++++++++---------- 1 file changed, 29 insertions(+), 36 deletions(-) diff --git a/src/spaceone/inventory_v2/service/region_service.py b/src/spaceone/inventory_v2/service/region_service.py index 0e70a49..3c94875 100644 --- a/src/spaceone/inventory_v2/service/region_service.py +++ b/src/spaceone/inventory_v2/service/region_service.py @@ -1,16 +1,14 @@ import logging from typing import Union -from mongoengine import QuerySet -from spaceone.core import utils from spaceone.core.error import * from spaceone.core.service import * from spaceone.inventory_v2.manager.region_manager import RegionManager from spaceone.inventory_v2.manager.identity_manager import IdentityManager -from spaceone.inventory_v2.model import Region from spaceone.inventory_v2.model.region.request import * from spaceone.inventory_v2.model.region.response import * +from spaceone.inventory_v2.model.region.database import Region _LOGGER = logging.getLogger(__name__) _KEYWORD_FILTER = ["region_id", "name", "region_code"] @@ -29,8 +27,9 @@ def __init__(self, metadata): @transaction( permission="inventory-v2:Region.write", - role_types=["DOMAIN_ADMIN"], + role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER"], ) + @convert_model def create(self, params: RegionCreateRequest) -> Union[RegionResponse, dict]: """ Args: @@ -47,19 +46,18 @@ def create(self, params: RegionCreateRequest) -> Union[RegionResponse, dict]: Returns: RegionResponse: """ + region_vo = self.create_resource(params.dict()) - return self.create_resource(params) + # return self.create_resource(params) + return RegionResponse(**region_vo.to_dict()) - @convert_model - def create_resource( - self, params: RegionCreateRequest - ) -> Union[RegionResponse, dict]: + def create_resource(self, params: dict) -> Region: identity_mgr = IdentityManager() - domain_id = params.domain_id - workspace_id = params.workspace_id - resource_group = params.resource_group + domain_id = params["domain_id"] + workspace_id = params.get("workspace_id") + resource_group = params["resource_group"] # Check permission by resource group if resource_group == "WORKSPACE": @@ -68,21 +66,20 @@ def create_resource( identity_mgr.check_workspace(workspace_id, domain_id) else: - params.workspace_id = "*" + params["workspace_id"] = "*" - region_id = f"{params.provider}-{params.region_code}" + region_id = f'{params["provider"]}-{params["region_code"]}' - params_data = params.dict() - params_data["region_id"] = region_id + params["region_id"] = region_id - region_vo = self.region_mgr.create_region(params_data) - - return RegionResponse(**region_vo.to_dict()) + return self.region_mgr.create_region(params) @transaction( permission="inventory-v2:Region.write", - role_types=["DOMAIN_ADMIN"], + role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @convert_model def update(self, params: RegionUpdateRequest) -> Union[RegionResponse, dict]: """ Args: @@ -97,27 +94,24 @@ def update(self, params: RegionUpdateRequest) -> Union[RegionResponse, dict]: region_vo (object) """ - return self.update_resource(params) + region_vo = self.update_resource(params.dict(exclude_unset=True)) - @convert_model - def update_resource( - self, params: RegionUpdateRequest - ) -> Union[RegionResponse, dict]: + return RegionResponse(**region_vo.to_dict()) - region_vo = self.region_mgr.get_region( - params.region_id, params.domain_id, params.workspace_id - ) + def update_resource(self, params: dict) -> Region: - region_vo = self.region_mgr.update_region_by_vo( - params.dict(exclude_unset=True), region_vo + region_vo = self.region_mgr.get_region( + params["region_id"], params["domain_id"], params.get("workspace_id") ) - return RegionResponse(**region_vo.to_dict()) + return self.region_mgr.update_region_by_vo(params, region_vo) @transaction( permission="inventory-v2:Region.write", - role_types=["DOMAIN_ADMIN"], + role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") + @convert_model def delete(self, params: RegionDeleteRequest) -> None: """ Args: @@ -130,12 +124,11 @@ def delete(self, params: RegionDeleteRequest) -> None: None """ - self.delete_resource(params) + self.delete_resource(params.dict()) - @convert_model - def delete_resource(self, params: RegionDeleteRequest) -> None: + def delete_resource(self, params: dict) -> None: region_vo = self.region_mgr.get_region( - params.region_id, params.domain_id, params.workspace_id + params["region_id"], params["domain_id"], params.get("workspace_id") ) self.region_mgr.delete_region_by_vo(region_vo) From dd8c67c8babff7e2b157e73c56a9ba1992dd643b Mon Sep 17 00:00:00 2001 From: lhhyung Date: Wed, 11 Dec 2024 15:17:56 +0900 Subject: [PATCH 09/11] refactor: Add ResourceManager as a base class for RegionManager Signed-off-by: lhhyung --- src/spaceone/inventory_v2/manager/region_manager.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/spaceone/inventory_v2/manager/region_manager.py b/src/spaceone/inventory_v2/manager/region_manager.py index fdc894f..82de5a9 100644 --- a/src/spaceone/inventory_v2/manager/region_manager.py +++ b/src/spaceone/inventory_v2/manager/region_manager.py @@ -4,13 +4,14 @@ from spaceone.core.manager import BaseManager from spaceone.core.model.mongo_model import QuerySet from spaceone.inventory_v2.model.region.database import Region +from spaceone.inventory_v2.lib.resource_manager import ResourceManager __ALL__ = ["RegionManager"] _LOGGER = logging.getLogger(__name__) -class RegionManager(BaseManager): +class RegionManager(BaseManager, ResourceManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.region_model = Region() From 5a71536228dc165eb5d02970f9e3574624c6ae46 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Wed, 11 Dec 2024 15:21:35 +0900 Subject: [PATCH 10/11] fix: Remove change_value_by_rule annotation from update and delete methods Signed-off-by: lhhyung --- src/spaceone/inventory_v2/service/region_service.py | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/spaceone/inventory_v2/service/region_service.py b/src/spaceone/inventory_v2/service/region_service.py index 3c94875..c0766f2 100644 --- a/src/spaceone/inventory_v2/service/region_service.py +++ b/src/spaceone/inventory_v2/service/region_service.py @@ -34,7 +34,6 @@ def create(self, params: RegionCreateRequest) -> Union[RegionResponse, dict]: """ Args: params (dict): { - 'region_id': 'str, 'name': 'str', # required 'region_code': 'str', # required 'provider': 'str', # required @@ -48,13 +47,10 @@ def create(self, params: RegionCreateRequest) -> Union[RegionResponse, dict]: """ region_vo = self.create_resource(params.dict()) - # return self.create_resource(params) return RegionResponse(**region_vo.to_dict()) def create_resource(self, params: dict) -> Region: - identity_mgr = IdentityManager() - domain_id = params["domain_id"] workspace_id = params.get("workspace_id") resource_group = params["resource_group"] @@ -64,6 +60,7 @@ def create_resource(self, params: dict) -> Region: if workspace_id is None: raise ERROR_REQUIRED_PARAMETER(key="workspace_id") + identity_mgr = IdentityManager() identity_mgr.check_workspace(workspace_id, domain_id) else: params["workspace_id"] = "*" @@ -78,7 +75,6 @@ def create_resource(self, params: dict) -> Region: permission="inventory-v2:Region.write", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER"], ) - @change_value_by_rule("APPEND", "workspace_id", "*") @convert_model def update(self, params: RegionUpdateRequest) -> Union[RegionResponse, dict]: """ @@ -110,7 +106,6 @@ def update_resource(self, params: dict) -> Region: permission="inventory-v2:Region.write", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER"], ) - @change_value_by_rule("APPEND", "workspace_id", "*") @convert_model def delete(self, params: RegionDeleteRequest) -> None: """ From 0954939977817af2d82b06dd87ea6383ec1790b9 Mon Sep 17 00:00:00 2001 From: lhhyung Date: Wed, 11 Dec 2024 15:22:38 +0900 Subject: [PATCH 11/11] refactor: Update field types in RegionUpdateRequest and RegionDeleteRequest Signed-off-by: lhhyung --- src/spaceone/inventory_v2/model/region/request.py | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/spaceone/inventory_v2/model/region/request.py b/src/spaceone/inventory_v2/model/region/request.py index 5a9e6b5..a61e747 100644 --- a/src/spaceone/inventory_v2/model/region/request.py +++ b/src/spaceone/inventory_v2/model/region/request.py @@ -25,15 +25,15 @@ class RegionCreateRequest(BaseModel): class RegionUpdateRequest(BaseModel): region_id: str - name: str = None + name: Union[str, None] = None tags: Union[dict, None] = None - workspace_id: Union[list, str, None] = None + workspace_id: Union[str, None] = None domain_id: str class RegionDeleteRequest(BaseModel): region_id: str - workspace_id: Union[list, str, None] = None + workspace_id: Union[str, None] = None domain_id: str