236 lines
6.8 KiB
Python
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()
|