From 412bd704f195c0996d3219107732a3e127c3a6aa Mon Sep 17 00:00:00 2001 From: Dmitriy Smirnov Date: Wed, 17 Jul 2024 15:02:18 +0300 Subject: [PATCH] Implement functionality of `/cloudapi/account/listRG` API method in `decort_account_info` module --- CHANGELOG.md | 2 +- library/decort_account_info.py | 86 ++++++++++++++++++++++++++++ module_utils/decort_utils.py | 100 ++++++++++++++++++++++++++++++++- 3 files changed, 186 insertions(+), 2 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 87c1265..8307a8f 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,7 +6,7 @@ | Идентификатор
задачи | Описание | | --- | --- | -| BANS-462
BANS-472 | Добавлен новый модуль **decort_account_info**, который позволяет получить следующую информацию об аккаунте:
• основная информация
• используемые и зарезервированные ресурсы | +| BANS-462
BANS-472
BANS-475 | Добавлен новый модуль **decort_account_info**, который позволяет получить следующую информацию об аккаунте:
• основная информация
• используемые и зарезервированные ресурсы
• ресурсные группы | ## Исправления diff --git a/library/decort_account_info.py b/library/decort_account_info.py index 6d331a4..801f990 100644 --- a/library/decort_account_info.py +++ b/library/decort_account_info.py @@ -32,6 +32,7 @@ class DecortAccountInfo(DecortController): account_name=amodule.params['name'], account_id=amodule.params['id'], resource_consumption=amodule.params['resource_consumption'], + resource_groups_params=self.mapped_rg_params, fail_if_not_found=True ) @@ -72,6 +73,60 @@ class DecortAccountInfo(DecortController): type='str', fallback=(env_fallback, ['DECORT_OAUTH2_URL']) ), + resource_groups=dict( + type='dict', + options=dict( + filter=dict( + type='dict', + options=dict( + id=dict( + type='int', + ), + name=dict( + type='str' + ), + status=dict( + type='str', + choices=self.RESOURCE_GROUP_STATUSES, + ), + vins_id=dict( + type='int' + ), + vm_id=dict( + type='int' + ), + ), + ), + pagination=dict( + type='dict', + options=dict( + number=dict( + type='int', + default=1, + ), + size=dict( + type='int', + required=True, + ), + ), + ), + sorting=dict( + type='dict', + options=dict( + asc=dict( + type='bool', + default=True, + ), + field=dict( + type='str', + choices=\ + self.FIELDS_FOR_SORTING_ACCOUNT_RG_LIST, + required=True, + ), + ), + ), + ), + ), resource_consumption=dict( type='bool', default=False @@ -94,6 +149,37 @@ class DecortAccountInfo(DecortController): ] ) + @property + def mapped_rg_params(self) -> None | dict: + input_params = self.amodule.params['resource_groups'] + if not input_params: + return input_params + + mapped_params = {} + if input_params['filter']: + mapped_params['rg_id'] =\ + input_params['filter']['id'] + mapped_params['rg_name'] =\ + input_params['filter']['name'] + mapped_params['rg_status'] =\ + input_params['filter']['status'] + mapped_params['vins_id'] =\ + input_params['filter']['vins_id'] + mapped_params['vm_id'] =\ + input_params['filter']['vm_id'] + if input_params['pagination']: + mapped_params['page_number'] =\ + input_params['pagination']['number'] + mapped_params['page_size'] =\ + input_params['pagination']['size'] + if input_params['sorting']: + mapped_params['sort_by_asc'] =\ + input_params['sorting']['asc'] + mapped_params['sort_by_field'] =\ + input_params['sorting']['field'] + + return mapped_params + def exit(self): self.result['facts'] = self.facts self.amodule.exit_json(**self.result) diff --git a/module_utils/decort_utils.py b/module_utils/decort_utils.py index b43adfe..f0453e7 100644 --- a/module_utils/decort_utils.py +++ b/module_utils/decort_utils.py @@ -41,6 +41,34 @@ class DecortController(object): based on the requested authentication type. """ + FIELDS_FOR_SORTING_ACCOUNT_RG_LIST = [ + 'createdBy', + 'createdTime', + 'deletedBy', + 'deletedTime', + 'id', + 'milestones', + 'name', + 'status', + 'updatedBy', + 'updatedTime', + 'vinses', + ] + + RESOURCE_GROUP_STATUSES = [ + 'CREATED', + 'DELETED', + 'DELETING', + 'DESTROYED', + 'DESTROYING', + 'DISABLED', + 'DISABLING', + 'ENABLED', + 'ENABLING', + 'MODELED', + 'RESTORING', + ] + VM_RESIZE_NOT = 0 VM_RESIZE_DOWN = 1 VM_RESIZE_UP = 2 @@ -1930,7 +1958,9 @@ class DecortController(object): return def account_find(self, account_name, account_id=0, - resource_consumption=False, fail_if_not_found=False): + resource_consumption=False, + resource_groups_params: None | dict = None, + fail_if_not_found=False): """Find cloud account specified by the name and return facts about the account. Knowing account is required for certain cloud resource management tasks (e.g. creating new RG). @@ -2012,6 +2042,13 @@ class DecortController(object): account_details['resource_reserved'] =\ resource_consumption['Reserved'] + if resource_groups_params is not None: + account_details['resource_groups'] =\ + self.account_resource_groups( + account_id=account_details['id'], + **resource_groups_params + ) + return account_details['id'], account_details def account_resource_consumption(self, account_id: int, @@ -2033,6 +2070,67 @@ class DecortController(object): " account specified.") self.amodule.fail_json(**self.result) + def account_resource_groups( + self, + account_id: int, + page_number: int = 1, + page_size: None | int = None, + rg_id: None | int = None, + rg_name: None | str = None, + rg_status: None | str = None, + sort_by_field: None | str = None, + sort_by_asc=True, + vins_id: None | int = None, + vm_id: None | int = None, + ) -> list[dict]: + self.result['waypoints'] += f' -> account_resource_groups' + + if rg_status and not rg_status in self.RESOURCE_GROUP_STATUSES: + self.result['msg'] = ( + f'{rg_status} is not valid RG status for filtering' + f' account resource groups list.' + ) + self.amodule.fail_json(**self.result) + + sort_by = None + if sort_by_field: + if not sort_by_field in self.FIELDS_FOR_SORTING_ACCOUNT_RG_LIST: + self.result['msg'] = ( + f'{sort_by_field} is not valid field for sorting' + f' account resource groups list.' + ) + self.amodule.fail_json(**self.result) + + sort_by_prefix = '+' if sort_by_asc else '-' + sort_by = f'{sort_by_prefix}{sort_by_field}' + + api_params = { + 'accountId': account_id, + 'name': rg_name, + 'page': page_number if page_size else None, + 'rgId': rg_id, + 'size': page_size, + 'sortBy': sort_by, + 'status': rg_status, + 'vinsId': vins_id, + 'vmId': vm_id, + } + + api_resp = self.decort_api_call( + arg_req_function=requests.post, + arg_api_name='/restmachine/cloudapi/account/listRG', + arg_params=api_params, + ) + + resource_groups = api_resp.json()['data'] + + for rg in resource_groups: + rg['createdTime_readable'] = self.sec_to_dt_str(rg['createdTime']) + rg['deletedTime_readable'] = self.sec_to_dt_str(rg['deletedTime']) + rg['updatedTime_readable'] = self.sec_to_dt_str(rg['updatedTime']) + + return resource_groups + ################################### # GPU resource manipulation methods ###################################