mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-07-31 11:54:47 +00:00
IPAAnsibleModule: New staticethod member_error_handler
The staticmethod member_error_handler is handing the default member related failures that can occur for modules with member support. This can simply be enabled with fail_on_member_errors=True for execute_ipa_commands. An exception handler is also now usable with execute_ipa_commands. In addition to the the exception it is also getting the same user defined arguments that the result_handler is getting. handle_result has been renamed in result_handler and handle_result_user_args has been renamed to handlers_user_args. Additionally the errors list does not need to be defined in the module. The method execute_ipa_commands is doing this internally and is also adding error: error to handlers_user_args if the handler is having errors in the argspec and errors is not yet set in handlers_user_args. Tests have been added to make sure that no user args for the handler have been set without an own result or exception handler. Also the use of fail_on_member_errors together with a result_andler is leading to an error.
This commit is contained in:
@@ -45,6 +45,7 @@ else:
|
|||||||
import gssapi
|
import gssapi
|
||||||
from datetime import datetime
|
from datetime import datetime
|
||||||
from contextlib import contextmanager
|
from contextlib import contextmanager
|
||||||
|
import inspect
|
||||||
|
|
||||||
# ansible-freeipa requires locale to be C, IPA requires utf-8.
|
# ansible-freeipa requires locale to be C, IPA requires utf-8.
|
||||||
os.environ["LANGUAGE"] = "C"
|
os.environ["LANGUAGE"] = "C"
|
||||||
@@ -716,8 +717,21 @@ else:
|
|||||||
"""
|
"""
|
||||||
return api_check_ipa_version(oper, requested_version)
|
return api_check_ipa_version(oper, requested_version)
|
||||||
|
|
||||||
def execute_ipa_commands(self, commands, handle_result=None,
|
# pylint: disable=unused-argument
|
||||||
**handle_result_user_args):
|
@staticmethod
|
||||||
|
def member_error_handler(module, result, command, name, args, errors):
|
||||||
|
# Get all errors
|
||||||
|
for failed_item in result.get("failed", []):
|
||||||
|
failed = result["failed"][failed_item]
|
||||||
|
for member_type in failed:
|
||||||
|
for member, failure in failed[member_type]:
|
||||||
|
errors.append("%s: %s %s: %s" % (
|
||||||
|
command, member_type, member, failure))
|
||||||
|
|
||||||
|
def execute_ipa_commands(self, commands, result_handler=None,
|
||||||
|
exception_handler=None,
|
||||||
|
fail_on_member_errors=False,
|
||||||
|
**handlers_user_args):
|
||||||
"""
|
"""
|
||||||
Execute IPA API commands from command list.
|
Execute IPA API commands from command list.
|
||||||
|
|
||||||
@@ -727,30 +741,56 @@ else:
|
|||||||
The list of commands in the form (name, command and args)
|
The list of commands in the form (name, command and args)
|
||||||
For commands that do not require a 'name', None needs be
|
For commands that do not require a 'name', None needs be
|
||||||
used.
|
used.
|
||||||
handle_result: function
|
result_handler: function
|
||||||
The user function to handle results of the single commands
|
The user function to handle results of the single commands
|
||||||
handle_result_user_args: dict (user args mapping)
|
exception_handler: function
|
||||||
The user args to pass to handle_result function
|
The user function to handle exceptions of the single commands
|
||||||
|
Returns True to continue to next command, else False
|
||||||
|
fail_on_member_errors: bool
|
||||||
|
Use default member error handler handler member_error_handler
|
||||||
|
handlers_user_args: dict (user args mapping)
|
||||||
|
The user args to pass to result_handler and exception_handler
|
||||||
|
functions
|
||||||
|
|
||||||
Example (ipauser module):
|
Example (ipauser module):
|
||||||
|
|
||||||
def handle_result(module, result, command, name, args, exit_args):
|
def result_handler(module, result, command, name, args, exit_args,
|
||||||
|
one_name):
|
||||||
if "random" in args and command in ["user_add", "user_mod"] \
|
if "random" in args and command in ["user_add", "user_mod"] \
|
||||||
and "randompassword" in result["result"]:
|
and "randompassword" in result["result"]:
|
||||||
exit_args.setdefault(name, {})["randompassword"] = \
|
if one_name:
|
||||||
result["result"]["randompassword"]
|
exit_args["randompassword"] = \
|
||||||
|
result["result"]["randompassword"]
|
||||||
|
else:
|
||||||
|
exit_args.setdefault(name, {})["randompassword"] = \
|
||||||
|
result["result"]["randompassword"]
|
||||||
|
|
||||||
|
def exception_handler(module, ex, exit_args, one_name):
|
||||||
|
if ex.exception == ipalib_errors.EmptyModlist:
|
||||||
|
result = {}
|
||||||
|
return False
|
||||||
|
|
||||||
exit_args = {}
|
exit_args = {}
|
||||||
changed = module.execute_ipa_commands(commands, handle_result,
|
changed = module.execute_ipa_commands(commands, result_handler,
|
||||||
exit_args=exit_args)
|
exception_handler,
|
||||||
|
exit_args=exit_args,
|
||||||
|
one_name=len(names)==1)
|
||||||
|
|
||||||
if len(names) == 1:
|
ansible_module.exit_json(changed=changed, user=exit_args)
|
||||||
ansible_module.exit_json(changed=changed,
|
|
||||||
user=exit_args[names[0]])
|
|
||||||
else:
|
|
||||||
ansible_module.exit_json(changed=changed, user=exit_args)
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
# Fail on given handlers_user_args without result or exception
|
||||||
|
# handler
|
||||||
|
if result_handler is None and exception_handler is None and \
|
||||||
|
len(handlers_user_args) > 0:
|
||||||
|
self.fail_json(msg="Args without result and exception hander: "
|
||||||
|
"%s" % repr(handlers_user_args))
|
||||||
|
|
||||||
|
# Fail on given result_handler and fail_on_member_errors
|
||||||
|
if result_handler is not None and fail_on_member_errors:
|
||||||
|
self.fail_json(
|
||||||
|
msg="result_handler given and fail_on_member_errors set")
|
||||||
|
|
||||||
# No commands, report no changes
|
# No commands, report no changes
|
||||||
if commands is None:
|
if commands is None:
|
||||||
return False
|
return False
|
||||||
@@ -759,6 +799,24 @@ else:
|
|||||||
if self.check_mode:
|
if self.check_mode:
|
||||||
return len(commands) > 0
|
return len(commands) > 0
|
||||||
|
|
||||||
|
# Error list for result_handler and error_handler
|
||||||
|
_errors = []
|
||||||
|
|
||||||
|
# Handle fail_on_member_errors, set result_handler to
|
||||||
|
# member_error_handler
|
||||||
|
# Add internal _errors for result_hendler if the module is not
|
||||||
|
# adding it. This also activates the final fail_json if
|
||||||
|
# errors are found.
|
||||||
|
if fail_on_member_errors:
|
||||||
|
result_handler = IPAAnsibleModule.member_error_handler
|
||||||
|
handlers_user_args["errors"] = _errors
|
||||||
|
elif result_handler is not None:
|
||||||
|
if "errors" not in handlers_user_args:
|
||||||
|
# pylint: disable=deprecated-method
|
||||||
|
argspec = inspect.getargspec(result_handler)
|
||||||
|
if "errors" in argspec.args:
|
||||||
|
handlers_user_args["errors"] = _errors
|
||||||
|
|
||||||
changed = False
|
changed = False
|
||||||
for name, command, args in commands:
|
for name, command, args in commands:
|
||||||
try:
|
try:
|
||||||
@@ -773,13 +831,22 @@ else:
|
|||||||
else:
|
else:
|
||||||
changed = True
|
changed = True
|
||||||
|
|
||||||
if handle_result is not None:
|
# If result_handler is not None, call it with user args
|
||||||
handle_result(self, result, command, name, args,
|
# defined in **handlers_user_args
|
||||||
**handle_result_user_args)
|
if result_handler is not None:
|
||||||
|
result_handler(self, result, command, name, args,
|
||||||
|
**handlers_user_args)
|
||||||
|
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
|
if exception_handler is not None and \
|
||||||
|
exception_handler(self, e, **handlers_user_args):
|
||||||
|
continue
|
||||||
self.fail_json(msg="%s: %s: %s" % (command, name, str(e)))
|
self.fail_json(msg="%s: %s: %s" % (command, name, str(e)))
|
||||||
|
|
||||||
|
# Fail on errors from result_handler and exception_handler
|
||||||
|
if len(_errors) > 0:
|
||||||
|
self.fail_json(msg=", ".join(_errors))
|
||||||
|
|
||||||
return changed
|
return changed
|
||||||
|
|
||||||
class FreeIPABaseModule(IPAAnsibleModule):
|
class FreeIPABaseModule(IPAAnsibleModule):
|
||||||
|
|||||||
Reference in New Issue
Block a user