1
0
Fork 0
mirror of https://github.com/ansible-collections/community.general.git synced 2026-02-04 07:51:50 +00:00
community.general/plugins/module_utils/mh/base.py
2026-01-10 14:41:52 +01:00

103 lines
3 KiB
Python

# (c) 2020, Alexei Znamensky <russoz@gmail.com>
# Copyright (c) 2020, Ansible Project
# Simplified BSD License (see LICENSES/BSD-2-Clause.txt or https://opensource.org/licenses/BSD-2-Clause)
# SPDX-License-Identifier: BSD-2-Clause
from __future__ import annotations
import typing as t
from ansible.module_utils.basic import AnsibleModule
from ansible_collections.community.general.plugins.module_utils.mh.deco import module_fails_on_exception
from ansible_collections.community.general.plugins.module_utils.mh.exceptions import ModuleHelperException as _MHE
class ModuleHelperBase:
# The type of module should be AnsibleModule, not something else.
# TODO: Rename the property of type dict[str, t.Any] | None to something like module_spec instead
module: dict[str, t.Any] | AnsibleModule | None = None # TODO: better spec using t.TypedDict
ModuleHelperException = _MHE
_delegated_to_module: tuple[str, ...] = (
"check_mode",
"get_bin_path",
"warn",
"deprecate",
"debug",
)
_module: AnsibleModule # TODO: remove once module has proper type
def __init__(self, module: AnsibleModule | dict[str, t.Any] | None = None) -> None:
self._changed = False
if module:
self.module = module
if not isinstance(self.module, AnsibleModule):
if self.module is None:
raise TypeError("module or module spec must be provided")
module = AnsibleModule(**self.module)
self.module = module # type: ignore
self._module = module
else:
self._module = self.module
@property
def diff_mode(self) -> bool:
return self._module._diff
@property
def verbosity(self) -> int:
return self._module._verbosity
def do_raise(self, *args, **kwargs) -> t.NoReturn:
raise _MHE(*args, **kwargs)
def __getattr__(self, attr):
if attr in self._delegated_to_module:
return getattr(self.module, attr)
raise AttributeError(f"ModuleHelperBase has no attribute '{attr}'")
def __init_module__(self):
pass
def __run__(self):
raise NotImplementedError()
def __quit_module__(self):
pass
def __changed__(self):
raise NotImplementedError()
@property
def changed(self) -> bool:
try:
return self.__changed__()
except NotImplementedError:
return self._changed
@changed.setter
def changed(self, value: bool) -> None:
self._changed = value
def has_changed(self):
raise NotImplementedError()
@property
def output(self):
raise NotImplementedError()
@module_fails_on_exception
def run(self):
self.__init_module__()
self.__run__()
self.__quit_module__()
output = self.output
if "failed" not in output:
output["failed"] = False
self.module.exit_json(changed=self.has_changed(), **output)
@classmethod
def execute(cls, module=None):
cls(module).run()