Files
decort-ansible/library/decort_vm_folder.py
Vladislav Nesterov ef4f57a1bd 13.0.2
2026-09-25 22:25:56 +07:00

236 lines
6.8 KiB
Python

#!/usr/bin/python
DOCUMENTATION = r'''
---
module: decort_vm_folder
description: See L(Module Documentation,https://repository.basistech.ru/BASIS/decort-ansible/wiki/Home). # noqa: E501
'''
from dataclasses import dataclass
from enum import Enum
from typing import Any
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.decort_utils import (
AnsibleModuleParamSet,
DecortController,
)
from dynamix_sdk import exceptions as sdk_exceptions
from dynamix_sdk import types as sdk_types
class VmFolderState(Enum):
absent = 'absent'
@dataclass(frozen=True)
class ParamSet(AnsibleModuleParamSet):
id: int | None
name: str | None
parent_id: int | None
rg_id: int | None
state: VmFolderState | None
class DecortVmFolder(DecortController):
param_set: ParamSet
facts: dict[str, Any]
_id: int | None = None
_vm_folder_info: sdk_types.CloudapiVmfolderGetResultModel | None = None
def __init__(self) -> None:
super().__init__(AnsibleModule(**self.amodule_init_args))
self.param_set = ParamSet.from_dict(self.amodule.params)
self.facts = {}
@property
def amodule_init_args(self) -> dict[str, Any]:
return self.pack_amodule_init_args(
argument_spec=ParamSet.get_arg_spec(),
supports_check_mode=True,
)
@property
def id(self) -> int:
if self._id is None:
raise TypeError
return self._id
@property
def vm_folder_info(self) -> sdk_types.CloudapiVmfolderGetResultModel:
if self._vm_folder_info is None:
try:
vm_folder_info = self.api.cloudapi.vmfolder.get(
folder_id=self.id,
)
except sdk_exceptions.RequestException as e:
if (
e.orig_exception.response is not None
and e.orig_exception.response.status_code == 404
):
self.message(
self.MESSAGES.obj_not_found(
obj='vm_folder',
id=self.id,
)
)
self.exit(fail=True)
raise e
self._vm_folder_info = vm_folder_info
return self._vm_folder_info
@DecortController.handle_sdk_exceptions
def run(self) -> None:
if self.param_set.id is not None:
self._id = self.param_set.id
elif self.param_set.name is not None:
self._id = self.find_id_by_name()
if self._id is not None:
self.get_info()
self.change()
else:
self.check_amodule_args_for_create()
self.create()
if self.result['changed']:
self.get_info()
self.exit()
def find_id_by_name(self) -> int | None:
rg_id = self.param_set.rg_id
name = self.param_set.name
if rg_id is None or name is None:
return None
matches: list[int] = []
page = 1
page_size = 100
while True:
folders = self.api.cloudapi.vmfolder.list(
rg_id=rg_id,
page=page,
size=page_size,
)
for folder in folders.data:
if folder.name != name:
continue
if (
self.param_set.parent_id is not None
and folder.parent_id != self.param_set.parent_id
):
continue
matches.append(folder.id)
if not folders.data or len(folders.data) < page_size:
break
if (
folders.entry_count
and page * page_size >= folders.entry_count
):
break
page += 1
if len(matches) > 1:
self.message(
msg='Check for parameter "name" failed: '
'multiple vm folders with this name were found; '
'specify parent_id or id'
)
self.exit(fail=True)
if matches:
return matches[0]
return None
def get_info(self) -> None:
if self._vm_folder_info is not None and not self.amodule.check_mode:
self._vm_folder_info = None
self.facts = self.vm_folder_info.model_dump()
def check_amodule_args_for_create(self) -> None:
check_errors = False
if self.param_set.rg_id is None:
check_errors = True
self.message(
msg='Check for parameter "rg_id" failed: '
'rg_id must be specified when creating '
'a new vm_folder'
)
if self.param_set.name is None:
check_errors = True
self.message(
msg='Check for parameter "name" failed: '
'name must be specified when creating '
'a new vm_folder'
)
if self.param_set.state == VmFolderState.absent:
check_errors = True
self.message(
msg='Check for parameter "state" failed: '
'state can not be "absent" when creating '
'a new vm_folder'
)
if check_errors:
self.exit(fail=True)
def create(self) -> None:
rg_id = self.param_set.rg_id
name = self.param_set.name
if rg_id is None or name is None:
raise TypeError
created_id = self.sdk_checkmode(
self.api.cloudapi.vmfolder.create
)(
rg_id=rg_id,
name=name,
parent_id=self.param_set.parent_id,
)
if created_id:
self._id = created_id
def change(self) -> None:
self.change_state()
self.change_params()
def change_state(self) -> None:
if self.param_set.state == VmFolderState.absent:
self.delete()
def change_params(self) -> None:
if (
self.param_set.name is not None
and self.param_set.name != self.vm_folder_info.name
):
self.sdk_checkmode(self.api.cloudapi.vmfolder.rename)(
folder_id=self.id,
name=self.param_set.name,
)
if (
self.param_set.parent_id is not None
and self.param_set.parent_id != self.vm_folder_info.parent_id
):
self.sdk_checkmode(self.api.cloudapi.vmfolder.move)(
folder_id=self.id,
new_parent_id=self.param_set.parent_id,
)
def delete(self) -> None:
self.sdk_checkmode(self.api.cloudapi.vmfolder.delete)(
folder_id=self.id,
)
self.exit()
def main() -> None:
DecortVmFolder().run()
if __name__ == '__main__':
main()