#!/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()