From 9728f0f3c90bf19f63ef316af3316fdb26ea9975 Mon Sep 17 00:00:00 2001 From: ImMin5 Date: Thu, 21 Dec 2023 17:07:57 +0900 Subject: [PATCH] feat: modify create budget api --- .../cost_analysis/info/budget_info.py | 1 - .../cost_analysis/info/data_source_info.py | 1 + .../info/data_source_rule_info.py | 2 +- .../cost_analysis/manager/budget_manager.py | 2 +- .../manager/budget_usage_manager.py | 8 ++-- .../manager/data_source_rule_manager.py | 3 +- .../cost_analysis/manager/identity_manager.py | 44 +++++++++++++------ .../cost_analysis/manager/secret_manager.py | 2 +- .../cost_analysis/model/budget_model.py | 2 +- .../cost_analysis/model/budget_usage_model.py | 3 +- .../cost_analysis/model/cost_model.py | 2 +- .../cost_analysis/model/data_source_model.py | 1 + .../cost_analysis/service/budget_service.py | 22 ++++++---- .../service/data_source_rule_service.py | 20 ++++----- .../service/data_source_service.py | 13 +++--- 15 files changed, 76 insertions(+), 50 deletions(-) diff --git a/src/spaceone/cost_analysis/info/budget_info.py b/src/spaceone/cost_analysis/info/budget_info.py index b96775f2..5f8905fa 100644 --- a/src/spaceone/cost_analysis/info/budget_info.py +++ b/src/spaceone/cost_analysis/info/budget_info.py @@ -66,7 +66,6 @@ def BudgetInfo(budget_vo: Budget, minimal=False): "provider_filter": ProviderFilterInfo(budget_vo.provider_filter), "resource_group": budget_vo.resource_group, "project_id": budget_vo.project_id, - "project_group_id": budget_vo.project_group_id, "data_source_id": budget_vo.data_source_id, } diff --git a/src/spaceone/cost_analysis/info/data_source_info.py b/src/spaceone/cost_analysis/info/data_source_info.py index cb10ad0d..51469db3 100644 --- a/src/spaceone/cost_analysis/info/data_source_info.py +++ b/src/spaceone/cost_analysis/info/data_source_info.py @@ -40,6 +40,7 @@ def PluginInfo(vo): def DataSourceInfo(data_source_vo: DataSource, minimal=False): info = { "data_source_id": data_source_vo.data_source_id, + "workspace_id": data_source_vo.workspace_id, "name": data_source_vo.name, "state": data_source_vo.state, "data_source_type": data_source_vo.data_source_type, diff --git a/src/spaceone/cost_analysis/info/data_source_rule_info.py b/src/spaceone/cost_analysis/info/data_source_rule_info.py index 7f410171..2bc9c73a 100644 --- a/src/spaceone/cost_analysis/info/data_source_rule_info.py +++ b/src/spaceone/cost_analysis/info/data_source_rule_info.py @@ -85,7 +85,7 @@ def DataSourceRuleInfo(data_source_rule_vo: DataSourceRule, minimal=False): "actions": DataSourceRuleActionsInfo(data_source_rule_vo.actions), "options": DataSourceRuleOptionsInfo(data_source_rule_vo.options), "tags": change_struct_type(data_source_rule_vo.tags), - "workspcae_id": data_source_rule_vo.workspace_id, + "workspace_id": data_source_rule_vo.workspace_id, "domain_id": data_source_rule_vo.domain_id, "created_at": utils.datetime_to_iso8601(data_source_rule_vo.created_at), } diff --git a/src/spaceone/cost_analysis/manager/budget_manager.py b/src/spaceone/cost_analysis/manager/budget_manager.py index b495f8d1..f5b162d5 100644 --- a/src/spaceone/cost_analysis/manager/budget_manager.py +++ b/src/spaceone/cost_analysis/manager/budget_manager.py @@ -55,7 +55,7 @@ def get_budget(self, budget_id: str, domain_id: str, workspace_id: str = None): def filter_budgets(self, **conditions): return self.budget_model.filter(**conditions) - def list_budgets(self, query={}): + def list_budgets(self, query: dict): return self.budget_model.query(**query) def stat_budgets(self, query): diff --git a/src/spaceone/cost_analysis/manager/budget_usage_manager.py b/src/spaceone/cost_analysis/manager/budget_usage_manager.py index d120f18f..2d69dd9e 100644 --- a/src/spaceone/cost_analysis/manager/budget_usage_manager.py +++ b/src/spaceone/cost_analysis/manager/budget_usage_manager.py @@ -28,7 +28,7 @@ def __init__(self, *args, **kwargs): "DataSourceManager" ) - def create_budget_usages(self, budget_vo: Budget): + def create_budget_usages(self, budget_vo: Budget) -> None: if budget_vo.time_unit == "TOTAL": start_dt = datetime.strptime(budget_vo.start, "%Y-%m") end_dt = datetime.strptime(budget_vo.end, "%Y-%m") @@ -86,7 +86,7 @@ def _rollback(old_data): self.transaction.add_rollback(_rollback, budget_usage_vo.to_dict()) return budget_usage_vo.update(params) - def update_cost_usage(self, budget_id, workspace_id, domain_id): + def update_cost_usage(self, budget_id: str, workspace_id: str, domain_id: str): _LOGGER.info(f"[update_cost_usage] Update Budget Usage: {budget_id}") cost_mgr: CostManager = self.locator.get_manager("CostManager") @@ -98,7 +98,9 @@ def update_budget_usage(self, domain_id, data_source_id): domain_id=domain_id, data_source_id=data_source_id ) for budget_vo in budget_vos: - self.update_cost_usage(budget_vo.budget_id, domain_id) + self.update_cost_usage( + budget_vo.budget_id, budget_vo.workspace_id, domain_id + ) self.notify_budget_usage(budget_vo) def notify_budget_usage(self, budget_vo: Budget): diff --git a/src/spaceone/cost_analysis/manager/data_source_rule_manager.py b/src/spaceone/cost_analysis/manager/data_source_rule_manager.py index 2a07523a..fb3beba7 100644 --- a/src/spaceone/cost_analysis/manager/data_source_rule_manager.py +++ b/src/spaceone/cost_analysis/manager/data_source_rule_manager.py @@ -61,7 +61,8 @@ def delete_data_source_rule(self, data_source_rule_id, domain_id): ) self.delete_data_source_rule_by_vo(data_source_rule_vo) - def delete_data_source_rule_by_vo(self, data_source_rule_vo): + @staticmethod + def delete_data_source_rule_by_vo(data_source_rule_vo): data_source_rule_vo.delete() def get_data_source_rule(self, data_source_rule_id, domain_id, workspace_id=None): diff --git a/src/spaceone/cost_analysis/manager/identity_manager.py b/src/spaceone/cost_analysis/manager/identity_manager.py index 2b4b9358..5e746d58 100644 --- a/src/spaceone/cost_analysis/manager/identity_manager.py +++ b/src/spaceone/cost_analysis/manager/identity_manager.py @@ -6,35 +6,51 @@ class IdentityManager(BaseManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.identity_conn: SpaceConnector = self.locator.get_connector( - "SpaceConnector", service="identity" + SpaceConnector, service="identity" ) - def get_workspace(self, workspace_id): + def get_workspace(self, workspace_id: str) -> dict: + token = self.transaction.get_meta("token") return self.identity_conn.dispatch( - "Workspace.get", - {"workspace_id": workspace_id}, + "Workspace.get", {"workspace_id": workspace_id}, token=token ) - def get_trusted_account(self, trusted_account_id): + def get_trusted_account(self, trusted_account_id: str) -> dict: + token = self.transaction.get_meta("token") return self.identity_conn.dispatch( "TrustedAccount.get", {"trusted_account_id": trusted_account_id}, + token=token, ) - def list_trusted_accounts(self, query): - return self.identity_conn.dispatch("TrustedAccount.list", {"query": query}) + def list_trusted_accounts(self, query: dict): + token = self.transaction.get_meta("token") + return self.identity_conn.dispatch( + "TrustedAccount.list", {"query": query}, token=token + ) - def get_service_account(self, service_account_id): + def get_service_account(self, service_account_id: str): + token = self.transaction.get_meta("token") return self.identity_conn.dispatch( "ServiceAccount.get", {"service_account_id": service_account_id}, + token=token, ) - def list_service_accounts(self, query): - return self.identity_conn.dispatch("ServiceAccount.list", {"query": query}) + def list_service_accounts(self, query: dict) -> dict: + token = self.transaction.get_meta("token") + return self.identity_conn.dispatch( + "ServiceAccount.list", {"query": query}, token=token + ) - def get_project(self, project_id): - return self.identity_conn.dispatch("Project.get", {"project_id": project_id}) + def get_project(self, project_id: str): + token = self.transaction.get_meta("token") + return self.identity_conn.dispatch( + "Project.get", {"project_id": project_id}, token=token + ) - def list_projects(self, query): - return self.identity_conn.dispatch("Project.list", {"query": query}) + def list_projects(self, query: dict): + token = self.transaction.get_meta("token") + return self.identity_conn.dispatch( + "Project.list", {"query": query}, token=token + ) diff --git a/src/spaceone/cost_analysis/manager/secret_manager.py b/src/spaceone/cost_analysis/manager/secret_manager.py index 1ebea309..a8d5c934 100644 --- a/src/spaceone/cost_analysis/manager/secret_manager.py +++ b/src/spaceone/cost_analysis/manager/secret_manager.py @@ -13,7 +13,7 @@ class SecretManager(BaseManager): def __init__(self, *args, **kwargs): super().__init__(*args, **kwargs) self.secret_connector: SpaceConnector = self.locator.get_connector( - "SpaceConnector", service="secret", token=config.get_global("TOKEN") + SpaceConnector, service="secret", token=config.get_global("TOKEN") ) def create_secret( diff --git a/src/spaceone/cost_analysis/model/budget_model.py b/src/spaceone/cost_analysis/model/budget_model.py index 169fe959..d5064af3 100644 --- a/src/spaceone/cost_analysis/model/budget_model.py +++ b/src/spaceone/cost_analysis/model/budget_model.py @@ -45,7 +45,7 @@ class Budget(MongoModel): resource_group = StringField(max_length=40, choices=("WORKSPACE", "PROJECT")) project_id = StringField(max_length=40, default=None, null=True) data_source_id = StringField(max_length=40) - workspace_id = StringField(max_length=40) + workspace_id = StringField(max_length=40, default=None, null=True) domain_id = StringField(max_length=40) created_at = DateTimeField(auto_now_add=True) updated_at = DateTimeField(auto_now=True) diff --git a/src/spaceone/cost_analysis/model/budget_usage_model.py b/src/spaceone/cost_analysis/model/budget_usage_model.py index 1305b0e7..ac750f71 100644 --- a/src/spaceone/cost_analysis/model/budget_usage_model.py +++ b/src/spaceone/cost_analysis/model/budget_usage_model.py @@ -25,7 +25,7 @@ class BudgetUsage(MongoModel): resource_group = StringField(max_length=40, choices=["WORKSPACE", "PROJECT"]) project_id = StringField(max_length=40, default=None, null=True) data_source_id = StringField(max_length=40) - workspace_id = StringField(max_length=40) + workspace_id = StringField(max_length=40, default=None, null=True) domain_id = StringField(max_length=40) updated_at = DateTimeField(auto_now=True) @@ -40,6 +40,7 @@ class BudgetUsage(MongoModel): "date", "project_id", "data_source_id", + "workspace_id", "domain_id", ], } diff --git a/src/spaceone/cost_analysis/model/cost_model.py b/src/spaceone/cost_analysis/model/cost_model.py index b8d6edc0..d3869f57 100644 --- a/src/spaceone/cost_analysis/model/cost_model.py +++ b/src/spaceone/cost_analysis/model/cost_model.py @@ -21,7 +21,7 @@ class Cost(MongoModel): data_source_id = StringField(max_length=40) job_id = StringField(max_length=40, default=None, null=True) job_task_id = StringField(max_length=40, default=None, null=True) - workspace_id = StringField(max_length=40) + workspace_id = StringField(max_length=40, default=None, null=True) domain_id = StringField(max_length=40) billed_year = StringField(max_length=4, required=True) billed_month = StringField(max_length=7, required=True) diff --git a/src/spaceone/cost_analysis/model/data_source_model.py b/src/spaceone/cost_analysis/model/data_source_model.py index 3cca2441..9e60284b 100644 --- a/src/spaceone/cost_analysis/model/data_source_model.py +++ b/src/spaceone/cost_analysis/model/data_source_model.py @@ -73,6 +73,7 @@ class DataSource(MongoModel): ], "minimal_fields": [ "data_source_id", + "workspace_id", "name", "state", "data_source_type", diff --git a/src/spaceone/cost_analysis/service/budget_service.py b/src/spaceone/cost_analysis/service/budget_service.py index 68910915..63f4ce0f 100644 --- a/src/spaceone/cost_analysis/service/budget_service.py +++ b/src/spaceone/cost_analysis/service/budget_service.py @@ -10,6 +10,7 @@ from spaceone.cost_analysis.manager.identity_manager import IdentityManager from spaceone.cost_analysis.model.budget_model import Budget from spaceone.cost_analysis.model.data_source_model import DataSource +from spaceone.cost_analysis.model.budget_usage_model import BudgetUsage _LOGGER = logging.getLogger(__name__) @@ -82,7 +83,6 @@ def create(self, params): if resource_group == "WORKSPACE": params["project_id"] = "*" - else: identity_mgr: IdentityManager = self.locator.get_manager("IdentityManager") identity_mgr.get_project(project_id) @@ -138,8 +138,12 @@ def create(self, params): budget_usage_mgr: BudgetUsageManager = self.locator.get_manager( "BudgetUsageManager" ) - budget_usage_vo = budget_usage_mgr.create_budget_usages(budget_vo) - budget_usage_mgr.update_cost_usage(budget_vo.budget_id, budget_vo.domain_id) + budget_usage_mgr.create_budget_usages(budget_vo) + budget_usage_mgr.update_cost_usage( + budget_vo.budget_id, + budget_vo.workspace_id, + budget_vo.domain_id, + ) budget_usage_mgr.notify_budget_usage(budget_vo) return budget_vo @@ -197,7 +201,9 @@ def update(self, params): {"name": params["name"]}, budget_usage_vo ) - budget_usage_mgr.update_cost_usage(budget_vo.budget_id, budget_vo.domain_id) + budget_usage_mgr.update_cost_usage( + budget_vo.budget_id, budget_vo.workspace_id, budget_vo.domain_id + ) budget_usage_mgr.notify_budget_usage(budget_vo) return budget_vo @@ -322,7 +328,7 @@ def list(self, params): total_count """ - query = self._set_user_project_or_project_group_filter(params) + query: dict = self._set_user_project_or_project_group_filter(params) return self.budget_mgr.list_budgets(query) @transaction( @@ -351,7 +357,7 @@ def stat(self, params): query = self._set_user_project_or_project_group_filter(params) return self.budget_mgr.stat_budgets(query) - def _check_target(self, project_id, project_group_id, domain_id): + def _check_target(self, project_id, project_group_id): if project_id is None and project_group_id is None: raise ERROR_REQUIRED_PARAMETER(key="project_id or project_group_id") @@ -361,9 +367,7 @@ def _check_target(self, project_id, project_group_id, domain_id): identity_mgr: IdentityManager = self.locator.get_manager("IdentityManager") if project_id: - identity_mgr.get_project(project_id, domain_id) - else: - identity_mgr.get_project_group(project_group_id, domain_id) + identity_mgr.get_project(project_id) @staticmethod def _check_time_period(start, end): diff --git a/src/spaceone/cost_analysis/service/data_source_rule_service.py b/src/spaceone/cost_analysis/service/data_source_rule_service.py index a3bdf6cf..a9c3f9df 100644 --- a/src/spaceone/cost_analysis/service/data_source_rule_service.py +++ b/src/spaceone/cost_analysis/service/data_source_rule_service.py @@ -76,12 +76,12 @@ def create(self, params): ) @change_date_value(["start", "end"]) def create_data_source_rule(self, params): - domain_id = params["domain_id"] - data_source_id = params["data_source_id"] - conditions = params.get("conditions", []) - conditions_policy = params["conditions_policy"] - actions = params["actions"] - rule_type = params.get("rule_type", "CUSTOM") + domain_id: str = params["domain_id"] + data_source_id: str = params["data_source_id"] + conditions: list = params.get("conditions", []) + conditions_policy: str = params["conditions_policy"] + actions: dict = params["actions"] + rule_type: str = params.get("rule_type", "CUSTOM") identity_mgr: IdentityManager = self.locator.get_manager("IdentityManager") @@ -98,7 +98,7 @@ def create_data_source_rule(self, params): else: self._check_conditions(conditions) - self._check_actions(actions, domain_id) + self._check_actions(actions) data_source_mgr: DataSourceManager = self.locator.get_manager( "DataSourceManager" @@ -159,7 +159,7 @@ def update(self, params): self._check_conditions(conditions) if "actions" in params: - self._check_actions(params["actions"], domain_id) + self._check_actions(params["actions"]) return self.data_source_rule_mgr.update_data_source_rule_by_vo( params, data_source_rule_vo @@ -391,10 +391,10 @@ def _check_conditions(conditions): f'({" | ".join(_SUPPORTED_CONDITION_OPERATORS)})', ) - def _check_actions(self, actions, domain_id): + def _check_actions(self, actions: dict) -> None: if project_id := actions.get("change_project"): identity_mgr: IdentityManager = self.locator.get_manager("IdentityManager") - identity_mgr.get_project(project_id, domain_id) + identity_mgr.get_project(project_id) if match_project := actions.get("match_project"): if "source" not in match_project: diff --git a/src/spaceone/cost_analysis/service/data_source_service.py b/src/spaceone/cost_analysis/service/data_source_service.py index aad40ed8..1042a0c8 100644 --- a/src/spaceone/cost_analysis/service/data_source_service.py +++ b/src/spaceone/cost_analysis/service/data_source_service.py @@ -43,8 +43,8 @@ def register(self, params): Args: params (dict): { - 'name': 'str', - 'data_source_type': 'str', + 'name': 'str', # required + 'data_source_type': 'str', # required 'provider': 'str', 'secret_type': 'str', 'secret_filter': 'dict', @@ -438,7 +438,7 @@ def get(self, params): Args: params (dict): { 'data_source_id': 'str', # required - 'workspace_id': 'list' + 'workspace_id': 'str' 'domain_id': 'str', # injected from auth } @@ -448,10 +448,10 @@ def get(self, params): data_source_id = params["data_source_id"] domain_id = params["domain_id"] - workspcae_id = params.get("workspace_id") + workspace_id = params.get("workspace_id") return self.data_source_mgr.get_data_source( - data_source_id, domain_id, workspcae_id + data_source_id, domain_id, workspace_id ) @transaction( @@ -492,6 +492,7 @@ def list(self, params): permission="cost-analysis:DataSource.read", role_types=["DOMAIN_ADMIN", "WORKSPACE_OWNER", "WORKSPACE_MEMBER"], ) + @change_value_by_rule("APPEND", "workspace_id", "*") @check_required(["query", "domain_id"]) @append_query_filter(["domain_id"]) @change_tag_filter("tags") @@ -535,7 +536,7 @@ def validate_secret_filter(self, secret_filter, domain_id): ] } identity_mgr: IdentityManager = self.locator.get_manager(IdentityManager) - response = identity_mgr.list_service_accounts(_query, domain_id) + response = identity_mgr.list_service_accounts(_query) if response.get("total_count", 0) != len(secret_filter["service_accounts"]): raise ERROR_INVALID_PARAMETER( key="secret_filter.service_accounts",