This commit is contained in:
2026-06-01 18:27:15 +03:00
parent ae986fa9e6
commit 1ab446e05d
34 changed files with 5135 additions and 2113 deletions

View File

@@ -7,9 +7,9 @@ module: decort_account
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
'''
from typing import Iterable
from typing import Any, Iterable
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.decort_utils import DecortController
from ansible.module_utils.decort_utils import DecortController, sdk_types
class DecortAccount(DecortController):
@@ -23,7 +23,7 @@ class DecortAccount(DecortController):
def amodule_init_args(self) -> dict:
return self.pack_amodule_init_args(
argument_spec=dict(
access_emails=dict(
send_access_emails=dict(
type='bool',
),
acl=dict(
@@ -45,8 +45,13 @@ class DecortAccount(DecortController):
options=dict(
rights=dict(
type='str',
choices=['R', 'RCX', 'ARCXDU'],
default='R',
choices=(
sdk_types.AccessTypeForSet
._member_names_
),
default=(
sdk_types.AccessTypeForSet.R.name
),
),
id=dict(
type='str',
@@ -69,19 +74,19 @@ class DecortAccount(DecortController):
quotas=dict(
type='dict',
options=dict(
cpu=dict(
cpu_count=dict(
type='int',
),
disks_size=dict(
storage_size_gb=dict(
type='int',
),
gpu=dict(
gpu_count=dict(
type='int',
),
public_ip=dict(
ext_ip_count=dict(
type='int',
),
ram=dict(
ram_size_mb=dict(
type='int',
),
),
@@ -135,7 +140,7 @@ class DecortAccount(DecortController):
# Parameters or combinations of parameters that can
# cause changing the object.
changing_params = [
'access_emails',
'send_access_emails',
'acl',
['id', 'name'],
'quotas',
@@ -188,110 +193,308 @@ class DecortAccount(DecortController):
self.acc_id, self._acc_info = self.account_find(
account_name=self.aparams['name'],
account_id=self.aparams['id'],
resource_consumption=self.aparams['get_resource_consumption'],
)
)
# If this is a repeated getting info
else:
# If check mode is enabled, there is no needed to
# request info again
if not self.amodule.check_mode:
self.acc_id, self._acc_info = self.account_find(
account_id=self.acc_id,
resource_consumption=(
self.aparams['get_resource_consumption']
),
account_id=self._acc_info.id,
)
self.facts = self.acc_info
if self._acc_info is not None:
acc_info_dict = self.acc_info.model_dump()
if self.aparams['get_resource_consumption']:
resource_consumption_dict = (
self.api.cloudapi.account.get_resource_consumption(
account_id=self.acc_info.id,
).model_dump()
)
resource_consumption_dict.pop('id')
resource_consumption_dict.pop('quotas')
acc_info_dict['resource_consumption'] = (
resource_consumption_dict
)
self.facts = acc_info_dict
def change(self):
self.change_state()
self.change_acl()
if self.account_update_args:
self.account_update(account_id=self.acc_id,
**self.account_update_args)
need_account_update_api_call: bool = False
sdk_param_send_access_emails = None
aparam_send_access_emails: bool | None = self.aparams[
'send_access_emails'
]
if (
aparam_send_access_emails is not None
and self.acc_info.send_access_emails != aparam_send_access_emails
):
sdk_param_send_access_emails = aparam_send_access_emails
need_account_update_api_call = True
sdk_param_name = None
aparam_name: str | None = self.aparams['name']
if (
self.aparams['id'] and aparam_name
and self.acc_info.name != aparam_name
):
sdk_param_name = aparam_name
need_account_update_api_call = True
sdk_param_cpu_count_quota = None
sdk_param_storage_size_quota_gb = None
sdk_param_gpu_count_quota = None
sdk_param_ext_ip_count_quota = None
sdk_param_ram_size_quota_mb = None
aparam_quotas: dict[str, Any] = self.aparams['quotas']
if aparam_quotas:
aparam_quotas_cpu_count: int | None = aparam_quotas['cpu_count']
if (
aparam_quotas_cpu_count is not None
and self.acc_info.quotas.cpu_count != aparam_quotas_cpu_count
):
sdk_param_cpu_count_quota = aparam_quotas_cpu_count
need_account_update_api_call = True
aparam_quotas_storage_size_gb: int | None = aparam_quotas[
'storage_size_gb'
]
if (
aparam_quotas_storage_size_gb is not None
and (
self.acc_info.quotas.storage_size_gb
!= aparam_quotas_storage_size_gb
)
):
sdk_param_storage_size_quota_gb = aparam_quotas_storage_size_gb
need_account_update_api_call = True
aparam_quotas_gpu_count: int | None = aparam_quotas['gpu_count']
if (
aparam_quotas_gpu_count is not None
and self.acc_info.quotas.gpu_count != aparam_quotas_gpu_count
):
sdk_param_gpu_count_quota = aparam_quotas_gpu_count
need_account_update_api_call = True
aparam_quotas_ext_ip_count: int | None = aparam_quotas[
'ext_ip_count'
]
if (
aparam_quotas_ext_ip_count is not None
and (
self.acc_info.quotas.ext_ip_count
!= aparam_quotas_ext_ip_count
)
):
sdk_param_ext_ip_count_quota = aparam_quotas_ext_ip_count
need_account_update_api_call = True
aparam_quotas_ram_size_mb: int | None = aparam_quotas[
'ram_size_mb'
]
if (
aparam_quotas_ram_size_mb is not None
and (
self.acc_info.quotas.ram_size_mb
!= aparam_quotas_ram_size_mb
)
):
sdk_param_ram_size_quota_mb = aparam_quotas_ram_size_mb
need_account_update_api_call = True
sdk_param_sep_pools = None
aparam_sep_pools: list[dict[str, Any]] = self.aparams['sep_pools']
if aparam_sep_pools is not None:
sep_pools: set[str] = set()
for sep in aparam_sep_pools:
sep_pool_names: list[str] = sep['pool_names']
for pool_name in sep_pool_names:
sep_pools.add(f'{sep["sep_id"]}_{pool_name}')
if set(self.acc_info.sep_pools) != sep_pools:
sdk_param_sep_pools = list(sep_pools)
need_account_update_api_call = True
sdk_param_description = None
aparam_desc: str | None = self.aparams['description']
if (
aparam_desc is not None
and self.acc_info.description != aparam_desc
):
sdk_param_description = aparam_desc
need_account_update_api_call = True
sdk_param_default_zone_id = None
aparam_default_zone_id: int | None = self.aparams['default_zone_id']
if (
aparam_default_zone_id is not None
and self.acc_info.default_zone_id != aparam_default_zone_id
):
sdk_param_default_zone_id = aparam_default_zone_id
need_account_update_api_call = True
if need_account_update_api_call:
OBJ = 'account'
self.sdk_checkmode(self.api.ca.account.update)(
account_id=self.acc_info.id,
cpu_count_quota=sdk_param_cpu_count_quota,
gpu_count_quota=sdk_param_gpu_count_quota,
name=sdk_param_name,
ext_ip_count_quota=sdk_param_ext_ip_count_quota,
ram_size_quota_mb=sdk_param_ram_size_quota_mb,
send_access_emails=sdk_param_send_access_emails,
storage_size_quota_gb=sdk_param_storage_size_quota_gb,
sep_pools=sdk_param_sep_pools,
description=sdk_param_description,
default_zone_id=sdk_param_default_zone_id,
)
if sdk_param_send_access_emails is not None:
smth = 'sending access emails'
if sdk_param_send_access_emails:
self.message(
self.MESSAGES.obj_smth_enabled(
obj=OBJ,
id=self.acc_info.id,
smth=smth,
)
)
else:
self.message(
self.MESSAGES.obj_smth_disabled(
obj=OBJ,
id=self.acc_info.id,
smth=smth,
)
)
if sdk_param_name is not None:
self.message(
self.MESSAGES.obj_renamed(
obj=OBJ,
id=self.acc_info.id,
new_name=sdk_param_name,
)
)
quotas = {
'CPU count quota': sdk_param_cpu_count_quota,
'storage size quota GB': sdk_param_storage_size_quota_gb,
'GPU count quota': sdk_param_gpu_count_quota,
'ext IP count quota': sdk_param_ext_ip_count_quota,
'RAM size quota MB': sdk_param_ram_size_quota_mb,
}
for q_name, q_value in quotas.items():
if q_value is not None:
self.message(
self.MESSAGES.obj_smth_changed(
obj=OBJ,
id=self.acc_info.id,
smth=q_name,
new_value=q_value
)
)
if sdk_param_default_zone_id is not None:
self.message(
self.MESSAGES.obj_smth_changed(
obj=OBJ,
id=self.acc_info.id,
smth='default_zone_id',
new_value=sdk_param_default_zone_id,
)
)
self.get_info()
def change_state(self):
match self._acc_info:
case None:
self.message(self.MESSAGES.obj_not_found(obj=self.OBJ))
match self.aparams:
case {'state': 'absent' | 'absent_permanently'}:
pass
case {'state': 'confirmed' | 'disabled' | 'present'}:
self.exit(fail=True)
case {'status': 'DESTROYED'}:
match self.aparams:
case {'state': 'absent' | 'absent_permanently'}:
self.message(
self.MESSAGES.obj_deleted(
obj=self.OBJ,
id=self.acc_id,
permanently=True,
already=True,
)
if self._acc_info is None:
self.message(self.MESSAGES.obj_not_found(obj=self.OBJ))
match self.aparams:
case {'state': 'absent' | 'absent_permanently'}:
pass
case {'state': 'confirmed' | 'disabled' | 'present'}:
self.exit(fail=True)
elif self._acc_info.status == sdk_types.AccountStatus.DESTROYED:
match self.aparams:
case {'state': 'absent' | 'absent_permanently'}:
self.message(
self.MESSAGES.obj_deleted(
obj=self.OBJ,
id=self.acc_info.id,
permanently=True,
already=True,
)
case {'state': 'confirmed' | 'disabled' | 'present'}:
self.message(
self.MESSAGES.obj_not_restored(obj=self.OBJ,
id=self.acc_id)
)
self.exit(fail=True)
case {'status': 'DELETED'}:
match self.aparams:
case {'state': 'absent'}:
self.message(
self.MESSAGES.obj_deleted(
obj=self.OBJ,
id=self.acc_id,
permanently=False,
already=True,
)
)
case {'state': 'confirmed' | 'disabled' | 'present'}:
self.message(
self.MESSAGES.obj_not_restored(obj=self.OBJ,
id=self.acc_info.id)
)
case {'state': 'absent_permanently'}:
self.delete(permanently=True)
case {'state': 'confirmed' | 'present'}:
self.restore()
case {'state': 'disabled'}:
self.restore()
self.disable()
case {'status': 'CONFIRMED'}:
match self.aparams:
case {'state': 'absent'}:
self.delete()
case {'state': 'absent_permanently'}:
self.delete(permanently=True)
case {'state': 'confirmed' | 'present'}:
pass
case {'state': 'disabled'}:
self.disable()
case {'status': 'DISABLED'}:
match self.aparams:
case {'state': 'absent'}:
self.delete()
case {'state': 'absent_permanently'}:
self.delete(permanently=True)
case {'state': 'confirmed'}:
self.enable()
case {'state': 'present' | 'disabled'}:
pass
self.exit(fail=True)
elif self._acc_info.status == sdk_types.AccountStatus.DELETED:
match self.aparams:
case {'state': 'absent'}:
self.message(
self.MESSAGES.obj_deleted(
obj=self.OBJ,
id=self.acc_info.id,
permanently=False,
already=True,
)
)
case {'state': 'absent_permanently'}:
self.delete(permanently=True)
case {'state': 'confirmed' | 'present'}:
self.restore()
case {'state': 'disabled'}:
self.restore()
self.disable()
elif self._acc_info.status == sdk_types.AccountStatus.CONFIRMED:
match self.aparams:
case {'state': 'absent'}:
self.delete()
case {'state': 'absent_permanently'}:
self.delete(permanently=True)
case {'state': 'confirmed' | 'present'}:
pass
case {'state': 'disabled'}:
self.disable()
elif self._acc_info.status == sdk_types.AccountStatus.DISABLED:
match self.aparams:
case {'state': 'absent'}:
self.delete()
case {'state': 'absent_permanently'}:
self.delete(permanently=True)
case {'state': 'confirmed'}:
self.enable()
case {'state': 'present' | 'disabled'}:
pass
def delete(self, permanently=False):
self.account_delete(account_id=self.acc_id, permanently=permanently)
self.account_delete(
account_id=self.acc_info.id,
permanently=permanently
)
self.get_info()
def disable(self):
self.account_disable(account_id=self.acc_id)
self.sdk_checkmode(self.api.ca.account.disable)(
account_id=self.acc_info.id
)
self.get_info()
def enable(self):
self.account_enable(account_id=self.acc_id)
self.sdk_checkmode(self.api.ca.account.enable)(
account_id=self.acc_info.id
)
self.get_info()
def restore(self):
self.account_restore(account_id=self.acc_id)
self.account_restore(account_id=self.acc_info.id)
self.get_info()
def change_acl(self):
@@ -299,7 +502,7 @@ class DecortAccount(DecortController):
return
actual_users = {
u['userGroupId']: u['right'] for u in self.acc_info['acl']
u.user_name: u.access_type for u in self.acc_info.acl
}
actual_users_ids = set(actual_users.keys())
@@ -328,8 +531,8 @@ class DecortAccount(DecortController):
aparams_users_ids.intersection(actual_users_ids)
upd_users = dict()
for id in upd_users_ids:
if actual_users[id] == 'CXDRAU':
actual_user_rights = 'ARCXDU'
if actual_users[id] == sdk_types.AccessType.CXDRAU:
actual_user_rights = sdk_types.AccessTypeForSet.ARCXDU
else:
actual_user_rights = actual_users[id]
@@ -341,68 +544,12 @@ class DecortAccount(DecortController):
actual_users_ids.difference(aparams_users_ids)
if del_users_ids or new_users or upd_users:
self.account_change_acl(account_id=self.acc_id,
self.account_change_acl(account_id=self.acc_info.id,
del_users=del_users_ids,
add_users=new_users,
upd_users=upd_users)
self.get_info()
@property
def account_update_args(self) -> dict:
result_args = dict()
aparam_access_emails = self.aparams['access_emails']
if (aparam_access_emails is not None
and self.acc_info['sendAccessEmails'] != aparam_access_emails):
result_args['access_emails'] = aparam_access_emails
aparam_name = self.aparams['name']
if (self.aparams['id'] and aparam_name
and self.acc_info['name'] != aparam_name):
result_args['name'] = aparam_name
aparam_quotas = self.aparams['quotas']
if aparam_quotas:
quotas_naming = [
['cpu', 'CU_C', 'cpu_quota'],
['disks_size', 'CU_DM', 'disks_size_quota'],
['gpu', 'gpu_units', 'gpu_quota'],
['public_ip', 'CU_I', 'public_ip_quota'],
['ram', 'CU_M', 'ram_quota'],
]
for aparam, info_key, result_arg in quotas_naming:
current_value = int(self.acc_info['resourceLimits'][info_key])
if (aparam_quotas[aparam] is not None
and current_value != aparam_quotas[aparam]):
result_args[result_arg] = aparam_quotas[aparam]
aparam_sep_pools = self.aparams['sep_pools']
if aparam_sep_pools is not None:
sep_pools = set()
for sep in aparam_sep_pools:
for pool_name in sep['pool_names']:
sep_pools.add(
f'{sep["sep_id"]}_{pool_name}'
)
if set(self.acc_info['uniqPools']) != sep_pools:
result_args['sep_pools'] = sep_pools
aparam_desc = self.aparams['description']
if (
aparam_desc is not None
and self.acc_info['description'] != aparam_desc
):
result_args['description'] = aparam_desc
aparam_default_zone_id = self.aparams['default_zone_id']
if (
aparam_default_zone_id is not None
and self.acc_info['defaultZoneId'] != aparam_default_zone_id
):
result_args['default_zone_id'] = aparam_default_zone_id
return result_args
def check_aparam_default_zone_id(self) -> bool | None:
aparam_default_zone_id = self.aparams['default_zone_id']
if aparam_default_zone_id is not None: