Merge branch 'BANS-462' into 'dev_5.4.0'

Implement `cloudapi/account/get` API

See merge request rudecs/dev/decort-ansible!98
main
commit ce4ac4630c

@ -1,137 +1,16 @@
# Список изменений в версии 5.3.0
# Список изменений в версии 5.4.0
## Обновления
### Глобальные
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-62 | Добавлен вывод текста ответа в сообщение об ошибке запроса к API. |
### Модуль decort_bservice
### Модуль decort_account_info
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-434 | В модуле **decort_bservice** в возвращаемом словаре `facts` ключи `groupsIds` и `groupsName` заменены на ключ `groups`, который содержит словари с информацией о группах базовой службы. |
| BANS-471 | Добавлен новый модуль **decort_account_info**, который позволяет получить основную информацию об аккаунте. |
## Исправления
### Модуль decort_bservice
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-366 | Работа модуля **decort_bservice** завершалась ошибкой Python при удалении базовой службы. |
| BANS-367 | Работа модуля **decort_bservice** завершалась ошибкой модуля при использовании параметров `rg_name` и `account_name` вместо параметра `rg_id`. |
| BANS-368 | Работа модуля **decort_bservice** завершалась ошибкой Python при повторном запуске создания базовой службы. |
| BANS-369 | Модуль **decort_bservice** не реагировал на режим **check mode** при создании базовой службы. |
### Модуль decort_disk
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-246 | Работа модуля **decort_disk** завершалась ошибкой Python при обработке ошибочных сценариев работы. |
| BANS-248 | Работа модуля **decort_disk** завершалась ошибкой Python при попытке валидировать заданный параметр `limitIO`. |
| BANS-249 | Работа модуля **decort_disk** завершалась ошибкой Python при попытке при попытке выполнить изменения в соответствии с заданным параметром `limitIO`. |
| BANS-250 | Работа модуля **decort_disk** завершалась ошибкой Python при заданном параметре `shareable`. |
| BANS-255 | Модуль **decort_disk** не выполнял безвозвратное удаление кластера из корзины. |
| BANS-260 | Работа модуля **decort_disk** завершалась ошибкой Python при попытке переименовать диск. |
| BANS-264 | Работа модуля **decort_disk** завершалась ошибкой Python при попытке изменить объём диска в режиме **check mode**. |
### Модуль decort_group
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-390 | Работа модуля **decort_group** завершалась ошибкой запроса к API при создании группы БС. |
| BANS-391 | Модуль **decort_group** не использовал заданные в параметре `networks` внешние сети при создании группы БС. |
| BANS-395 | Работа модуля **decort_group** завершалась ошибкой запроса к API при повторном запуске создания группы БС. |
| BANS-396 | Модуль **decort_group** при повторном запуске создания сообщал о том, что были выполнены изменения. |
| BANS-399 | Работа модуля **decort_group** завершалась ошибкой запроса к API при удалении группы БС. |
| BANS-419 | Модуль **decort_group** при повторном запуске изменения параметра networks сообщал о том, что были выполнены изменения. |
### Модуль decort_k8s
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-197 | Работа модуля **decort_k8s** завершалась ошибкой Python если не задан параметр `oidc_cert`. |
| BANS-202 | Работа модуля **decort_k8s** завершалась ошибкой модуля при попытке использовать `rg_name` и `account_name` вместо `rg_id` при создании кластера. |
| BANS-203 | В модуле **decort_k8s** был задан неверный тип данных для параметров `cluster_conf`, `kublet_conf`, `kubeproxy_conf`, `join_conf` |
| BANS-216 | Работа модуля **decort_k8s** завершалась ошибкой модуля при попытке создать кластер в режиме **check mode**. |
| BANS-218 | Модуль **decort_k8s** не выполнял безвозвратное удаление кластера из корзины. |
| BANS-221 | Модуль **decort_k8s** некорректно обрабатывал параметр `vins_id`, что вызывало создание новой внутренней сети при заданном параметре `vins_id`. |
| BANS-225 | Модуль **decort_k8s** не сообщал о выполненных изменениях при выполнении восстановления кластера из корзины. |
| BANS-226 | Модуль **decort_k8s** не выполнял запуск кластера после его восстановления из корзины. |
| BANS-236 | Модуль **decort_k8s** игнорировал заданный параметр `getConfig` при запуске в режиме **check mode**. |
| BANS-243 | Модуль **decort_k8s** выполнял изменения в соответствии с заданным параметром `workers` при запуске в режиме **check mode**. |
### Модуль decort_kvmvm
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-38 | Работа модуля **decort_kvmvm** завершалась ошибкой Python при попытке удалить все существующие правила affinity у ВМ. |
| BANS-39 | Работа модуля **decort_kvmvm** завершалась ошибкой Python при попытке удалить все существующие правила anti affinity у ВМ. |
| BANS-60 | Работа модуля **decort_kvmvm** завершалась ошибкой Python при незаданном параметре `boot_disk` для существующей ВМ. |
| BANS-61 | В модуле **decort_kvmvm** происходила автоматическая конвертация из ГБ в МБ при изменении параметра `ram` на значение менее 512 для существующей ВМ. |
| BANS-445 | В модуле **decort_kvmvm** был задан неверный тип данных для параметра `ci_user_data`. |
### Модуль decort_lb
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-321 | Работа модуля **decort_lb** завершалась ошибкой модуля при использовании параметра `rg_name`. |
| BANS-322 | Работа модуля **decort_lb** завершалась ошибкой Python при использовании параметра `account_id`. |
| BANS-323 | Модуль **decort_lb** игнорировал параметр `vins_name` и создавал балансировщик без подключения к внутренней сети. |
| BANS-324 | Модуль **decort_lb** при повторном запуске создания сообщал о том, что были выполнены изменения. |
| BANS-325 | Модуль **decort_lb** не реагировал на параметр `annotation`. |
| BANS-326 | Модуль **decort_lb** при указании нескольких конфигураций frontend в параметре `frontends` добавлял в балансировщик только первую конфигурацию frontend. |
| BANS-331 | Работа модуля **decort_lb** завершалась ошибкой Python при выполнении создания балансировщика в режиме **check mode**. |
| BANS-334 | Модуль **decort_lb** не выполнял безвозвратное удаление балансировщика из корзины. |
| BANS-338 | Работа модуля **decort_lb** завершалась ошибкой Python при запуске восстановления балансировщика из корзины. |
| BANS-339 | Работа модуля **decort_lb** завершалась ошибкой Python при запуске восстановления балансировщика из корзины. |
| BANS-340 | Модуль **decort_lb** оставлял балансировщик выключенным после его восстановления из корзины. |
| BANS-341 | Модуль **decort_lb** оставлял балансировщик остановленным после его восстановления из корзины. |
| BANS-346 | Модуль **decort_lb** не производил запуск балансировщика при запуске с заданным параметром `state: enabled` или `state: present`. |
| BANS-352 | Работа модуля **decort_lb** завершалась ошибкой Python при удалении конфигурации frontend у балансировщика. |
| BANS-353 | Работа модуля **decort_lb** завершалась ошибкой запроса к API при удалении конфигурации frontend и связанной с ней конфигурации backend у балансировщика |
| BANS-354 | Модуль **decort_lb** не применял значения из подпараметров `check` и `server_settings` при добавлении нового сервера в существующую конфигурацию backend балансировщика. |
| BANS-357 | Модуль **decort_lb** игнорировал режим **check mode** для параметров `backends`, `frontends`, `servers`. |
| BANS-457 | Модуль **decort_lb** возвращал некорректный статус для удалённого балансировщика и указывал некорректный статус балансировщика в сообщении при повторном запуске модуля.
### Модуль decort_osimage
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-295 | Работа модуля **decort_osimage** завершалась ошибкой запроса к API при повторном запуске удаления шаблонного образа. |
| BANS-296 | Работа модуля **decort_osimage** завершалась ошибкой модуля при повторном запуске удаления шаблонного образа. |
| BANS-297 | Работа модуля **decort_osimage** завершалась ошибкой запроса к API при указании параметра `account_name` вместо параметра `account_Id` |
| BANS-299 | Модуль **decort_osimage** при повторном запуске переименования образа сообщал о том, что были выполнены изменения. |
| BANS-300 | Работа модуля **decort_osimage** завершалась ошибкой Python при создании виртуального образа. |
| BANS-301 | Работа модуля **decort_osimage** завершалась ошибкой модуля при повторном запуске удаления виртуального образа. |
| BANS-302 | Работа модуля **decort_osimage** завершалась ошибкой Python с удалением шаблонного образа при попытке удалить виртуальный образ. |
| BANS-303 | Модуль **decort_osimage** не выполнял переименование виртуального образа. |
| BANS-304 | Работа модуля **decort_osimage** завершалась ошибкой Python при повторном запуске удаления виртуального образа. |
### Модуль decort_pfw
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-283 | Работа модуля **decort_pfw** завершалась ошибкой Python при повторном запуске удаления правил. |
| BANS-451 | Модуль **decort_pfw** при запуске удаления удалял все правила переадресации портов на виртуальном маршрутизаторе заданной внутренней сети, вместо удаления правил только для заданной ВМ. |
### Модуль decort_rg
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-58 | Работа модуля **decort_rg** завершалась ошибкой Python при передаче некорректных данных об аккаунте и/или пользователе. |
| BANS-63 | Модуль **decort_rg** выполнял некорректное получение/изменение квоты на объём дисков. |
| BANS-64 | Работа модуля **decort_rg** завершалась ошибкой Python при повторном запуске на создание. |
| BANS-65 | Модуль **decort_rg** не выполнял восстановление РГ из корзины при заданном параметре `state: disabled` или `state: enabled`. |
| BANS-66 | В модуле **decort_rg** не выполнялась проверка наличия параметра `rg_name` при создании РГ. |
| BANS-67 | Работа модуля **decort_rg** завершалась ошибкой запроса к API при создании РГ когда РГ с таким именем есть в корзине. |
| BANS-68 | Модуль **decort_rg** не выполнял восстановление РГ из корзины при указании `rg_name` вместо `rg_id`. |
| BANS-425 | Работа модуля **decort_rg** завершалась ошибкой модуля при создании РГ в режиме **check mode**. |
### Модуль decort_vins
### Глобальные
| Идентификатор<br>задачи | Описание |
| --- | --- |
| BANS-59 | Работа модуля **decort_vins** завершалась ошибкой Python при создании внутренней сети на уровне аккаунта. |
| BANS-467 | При указании идентификатора аккаунта, который не существует или к которому у пользователя нет доступа, модули завершались с ошибкой запроса к API. |

@ -5,7 +5,7 @@
| Версия платформы | Версия модулей Ansible |
| :---: | :---: |
| 4.0.0 | 5.3.0 |
| 4.0.0 | 5.4.0 |
| 3.8.9 | 5.2.6 |
| 3.8.8 | 5.2.6 |
| 3.8.7 | 5.2.5 |

@ -0,0 +1,108 @@
#!/usr/bin/python
# Copyright: ...
# ...
DOCUMENTATION = r'''
---
module: decort_account_info
version_added: "2.16"
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home).
'''
# EXAMPLES = r'''
# '''
# RETURN = r'''
# '''
from ansible.module_utils.basic import AnsibleModule, env_fallback
from ansible.module_utils.decort_utils import DecortController
class DecortAccountInfo(DecortController):
MODULE_ARGS = dict(
argument_spec=dict(
app_id=dict(
type='str',
required=False,
fallback=(env_fallback, ['DECORT_APP_ID'])
),
app_secret=dict(
type='str',
required=False,
fallback=(env_fallback, ['DECORT_APP_SECRET']),
no_log=True
),
authenticator=dict(
type='str',
required=True,
choices=['oauth2', 'jwt']
),
controller_url=dict(
type='str',
required=True
),
id=dict(
type='int',
required=False
),
jwt=dict(
type='str',
required=False,
fallback=(env_fallback, ['DECORT_JWT']),
no_log=True
),
name=dict(
type='str',
required=False
),
oauth2_url=dict(
type='str',
required=False,
fallback=(env_fallback, ['DECORT_OAUTH2_URL'])
),
verify_ssl=dict(
type='bool',
required=False,
default=True
),
),
mutually_exclusive=[
('id', 'name')
],
required_one_of=[
('id', 'name')
],
required_if=[
('authenticator', 'oauth2',
('oauth2_url', 'app_id', 'app_secret')),
('authenticator', 'jwt', ('jwt',))
]
)
def __init__(self):
amodule = AnsibleModule(**self.MODULE_ARGS, supports_check_mode=True)
super().__init__(amodule)
self.id, self.facts = self.account_find(
account_name=amodule.params['name'],
account_id=amodule.params['id'],
fail_if_not_found=True
)
def exit(self):
self.result['facts'] = self.facts
self.amodule.exit_json(**self.result)
def main():
decort_account_info = DecortAccountInfo()
decort_account_info.exit()
if __name__ == '__main__':
main()

@ -74,16 +74,16 @@ class DecortController(object):
self.app_id = arg_amodule.params['app_id']
self.app_secret = arg_amodule.params['app_secret']
self.oauth2_url = arg_amodule.params['oauth2_url']
self.password = arg_amodule.params['password']
self.user = arg_amodule.params['user']
# self.password = arg_amodule.params['password']
# self.user = arg_amodule.params['user']
self.session_key = ''
# self.iconf = arg_iconf
self.verify_ssl = arg_amodule.params['verify_ssl']
self.workflow_callback_present = False
self.workflow_callback = arg_amodule.params['workflow_callback']
self.workflow_context = arg_amodule.params['workflow_context']
if self.workflow_callback != "":
self.workflow_callback_present = True
# self.workflow_callback = arg_amodule.params['workflow_callback']
# self.workflow_context = arg_amodule.params['workflow_context']
# if self.workflow_callback != "":
# self.workflow_callback_present = True
# The following will be initialized to the name of the user in DECORT controller, who corresponds to
# the credentials supplied as authentication information parameters.
@ -153,6 +153,12 @@ class DecortController(object):
# self.run_phase = "Initializing DecortController instance complete."
return
@staticmethod
def sec_to_dt_str(sec: int, str_format: str = '%Y-%m-%d_%H-%M-%S') -> str:
if sec:
return time.strftime(str_format, time.gmtime(sec))
return ''
def check_amodule_argument(self, arg_name, abort=True):
"""Checks if the argument identified by the arg_name is defined in the module parameters.
@ -335,7 +341,8 @@ class DecortController(object):
return True
def decort_api_call(self, arg_req_function, arg_api_name, arg_params, arg_files=None):
def decort_api_call(self, arg_req_function, arg_api_name, arg_params,
arg_files=None, not_fail_codes: None | list = None):
"""Wrapper around DECORT API calls. It uses authorization mode and credentials validated at the class
instance creation to properly format API call and send it to the DECORT controller URL.
If connection errors are detected, it aborts execution of the script and relay error messages to upstream
@ -386,6 +393,8 @@ class DecortController(object):
if api_resp.status_code == 200:
return api_resp
elif not_fail_codes and api_resp.status_code in not_fail_codes:
return api_resp
elif api_resp.status_code == 503:
retry_timeout = 5 + 10 * (max_retries - retry_counter)
time.sleep(retry_timeout)
@ -1920,7 +1929,8 @@ class DecortController(object):
self.result['changed'] = True
return
def account_find(self, account_name, account_id=0):
def account_find(self, account_name, account_id=0,
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).
@ -1935,36 +1945,65 @@ class DecortController(object):
self.result['waypoints'] = "{} -> {}".format(self.result['waypoints'], "account_find")
if account_name == "" and account_id == 0:
self.result['failed'] = True
self.result['msg'] = "Cannot find account if account name is empty and account ID is zero."
if not account_id and not account_name:
self.result['msg'] = ('Cannot find account if account name and'
' id are not specified.')
self.amodule.fail_json(**self.result)
api_params = dict()
account_details = None
_account_id = account_id
if account_name and not account_id:
api_params = {
'name': account_name
}
api_resp = self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/account/list',
arg_params=api_params
)
accounts_list = api_resp.json()['data']
for account in accounts_list:
if account['name'] == account_name:
_account_id = account['id']
break
if account_name == "":
api_params['accountId'] = account_id
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/get", api_params)
if api_resp.status_code == 200:
account_details = json.loads(api_resp.content.decode('utf8'))
return account_details['id'], account_details
else:
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/list", api_params)
if _account_id:
api_params = {
'accountId': _account_id
}
api_resp = self.decort_api_call(
arg_req_function=requests.post,
arg_api_name='/restmachine/cloudapi/account/get',
arg_params=api_params,
not_fail_codes=[404]
)
if api_resp.status_code == 200:
# Parse response to see if a account matching arg_account_name is found in the output
# If it is found, assign its ID to the return variable and copy dictionary with the facts
accounts_list = json.loads(api_resp.content.decode('utf8'))
for runner in accounts_list['data']:
if runner['name'] == account_name:
# get detailed information about the account from "accounts/get" call as
# "accounts/list" does not return all necessary fields
api_params['accountId'] = runner['id']
api_resp = self.decort_api_call(requests.post, "/restmachine/cloudapi/account/get", api_params)
if api_resp.status_code == 200:
account_details = json.loads(api_resp.content.decode('utf8'))
return account_details['id'], account_details
account_details = api_resp.json()
return 0, None
if account_details:
account_details['createdTime_readable'] = self.sec_to_dt_str(
account_details['createdTime']
)
account_details['deactivationTime_readable'] = self.sec_to_dt_str(
account_details['deactivationTime']
)
account_details['deletedTime_readable'] = self.sec_to_dt_str(
account_details['deletedTime']
)
account_details['updatedTime_readable'] = self.sec_to_dt_str(
account_details['updatedTime']
)
return account_details['id'], account_details
else:
if fail_if_not_found:
self.result['msg'] = ("Current user does not have access to"
" the requested account or non-existent"
" account specified.")
self.amodule.fail_json(**self.result)
else:
return 0, None
###################################
# GPU resource manipulation methods

Loading…
Cancel
Save