Merge pull request #630 from t-woerner/use_execute_ipa_commands

Use execute ipa commands
This commit is contained in:
Rafael Guterres Jeffman
2021-09-08 18:20:29 -03:00
committed by GitHub
22 changed files with 315 additions and 552 deletions

View File

@@ -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):

View File

@@ -390,32 +390,16 @@ def main():
commands.append([None, 'automember_rebuild', commands.append([None, 'automember_rebuild',
{"hosts": rebuild_hosts}]) {"hosts": rebuild_hosts}])
# Check mode exit # Execute commands
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
if name is None:
result = ansible_module.ipa_command_no_name(command, args)
else:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result: # result["failed"] is used only for INCLUDE_RE, EXCLUDE_RE
if result["completed"] > 0: # if entries could not be added that are already there and
changed = True # if entries could not be removed that are not there.
else: # All other issues like invalid attributes etc. are handled
changed = True # as exceptions. Therefore the error section is not here as
except Exception as ex: # in other modules.
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(ex)))
# result["failed"] is used only for INCLUDE_RE, EXCLUDE_RE
# if entries could not be added that are already there and
# it entries could not be removed that are not there.
# All other issues like invalid attributes etc. are handled
# as exceptions. Therefore the error section is not here as
# in other modules.
# Done # Done
ansible_module.exit_json(changed=changed, **exit_args) ansible_module.exit_json(changed=changed, **exit_args)

View File

@@ -289,23 +289,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done

View File

@@ -1241,7 +1241,7 @@ def create_reverse_ip_record(module, zone_name, name, ips):
'idnsname': to_text(reverse_host), 'idnsname': to_text(reverse_host),
"ptrrecord": "%s.%s" % (name, zone_name) "ptrrecord": "%s.%s" % (name, zone_name)
} }
_cmds.append([reverse_zone, 'dnsrecord_add', rev_args]) _cmds.append([to_text(reverse_zone), 'dnsrecord_add', rev_args])
return _cmds return _cmds
@@ -1408,6 +1408,14 @@ def define_commands_for_absent_state(module, zone_name, entry, res_find):
return _commands return _commands
# pylint: disable=unused-argument
def exception_handler(module, ex):
if isinstance(ex, (ipalib_errors.EmptyModlist,
ipalib_errors.DuplicateEntry)):
return True
return False
def main(): def main():
"""Execute DNS record playbook.""" """Execute DNS record playbook."""
ansible_module = configure_module() ansible_module = configure_module()
@@ -1468,30 +1476,10 @@ def main():
if cmds: if cmds:
commands.extend(cmds) commands.extend(cmds)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands:
try:
result = ansible_module.ipa_command(
command, to_text(name), args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except ipalib_errors.EmptyModlist: changed = ansible_module.execute_ipa_commands(
continue commands, exception_handler=exception_handler)
except ipalib_errors.DuplicateEntry:
continue
except Exception as e:
error_message = str(e)
ansible_module.fail_json(
msg="%s: %s: %s" % (command, name, error_message))
# Done # Done
ansible_module.exit_json(changed=changed, host=exit_args) ansible_module.exit_json(changed=changed, host=exit_args)

View File

@@ -658,34 +658,10 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(
try: commands, fail_on_member_errors=True)
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# result are ignored. All others are reported.
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))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -595,35 +595,10 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
errors = [] changed = ansible_module.execute_ipa_commands(
for name, command, args in commands: commands, fail_on_member_errors=True)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -180,19 +180,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
ansible_module.ipa_command(command, name, args)
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done

View File

@@ -136,6 +136,21 @@ def gen_member_args(hbacsvc):
return _args return _args
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main(): def main():
ansible_module = IPAAnsibleModule( ansible_module = IPAAnsibleModule(
argument_spec=dict( argument_spec=dict(
@@ -278,36 +293,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
errors = []
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands, result_handler)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and "member" in result["failed"]:
failed = result["failed"]["member"]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" not in failure \
and "not a member" not in failure:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -572,6 +572,54 @@ def check_parameters( # pylint: disable=unused-argument
"'member' for state '%s'" % (x, state)) "'member' for state '%s'" % (x, state))
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors, exit_args,
one_name):
if "random" in args and command in ["host_add", "host_mod"] \
and "randompassword" in result["result"]:
if one_name:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
# pylint: disable=unused-argument
def exception_handler(module, ex, errors, exit_args, one_name):
msg = str(ex)
if "already contains" in msg \
or "does not contain" in msg:
return True
# The canonical principal name may not be removed
if "equal to the canonical principal name must" in msg:
return True
# Host is already disabled, ignore error
if "This entry is already disabled" in msg:
return True
# Ignore no modification error.
if "no modifications to be performed" in msg:
return True
return False
def main(): def main():
host_spec = dict( host_spec = dict(
# present # present
@@ -1343,68 +1391,11 @@ def main():
del host_set del host_set
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
errors = [] changed = ansible_module.execute_ipa_commands(
for name, command, args in commands: commands, result_handler, exception_handler,
try: exit_args=exit_args, one_name=len(names) == 1)
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
if "random" in args and command in ["host_add", "host_mod"] \
and "randompassword" in result["result"]:
if len(names) == 1:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
except Exception as e:
msg = str(e)
if "already contains" in msg \
or "does not contain" in msg:
continue
# The canonical principal name may not be removed
if "equal to the canonical principal name must" in msg:
continue
# Host is already disabled, ignore error
if "This entry is already disabled" in msg:
continue
# Ignore no modification error.
if "no modifications to be performed" in msg:
continue
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
msg))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -490,34 +490,10 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands:
try: changed = ansible_module.execute_ipa_commands(
result = ansible_module.ipa_command(command, name, args) commands, fail_on_member_errors=True)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
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))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -168,23 +168,8 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
changed = ansible_module.execute_ipa_commands(commands)
for name, command, args in commands:
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done

View File

@@ -180,6 +180,22 @@ def gen_args(right, attrs, bindtype, subtree,
return _args return _args
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
for failed_item in result.get("failed", []):
failed = result["failed"][failed_item]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main(): def main():
ansible_module = IPAAnsibleModule( ansible_module = IPAAnsibleModule(
argument_spec=dict( argument_spec=dict(
@@ -425,38 +441,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unknown state '%s'" % state) ansible_module.fail_json(msg="Unknown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands, result_handler)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
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]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -126,6 +126,22 @@ def find_privilege(module, name):
return _result["result"] return _result["result"]
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
for failed_item in result.get("failed", []):
failed = result["failed"][failed_item]
for member_type in failed:
for member, failure in failed[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main(): def main():
ansible_module = IPAAnsibleModule( ansible_module = IPAAnsibleModule(
argument_spec=dict( argument_spec=dict(
@@ -304,38 +320,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands, result_handler)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(
msg="%s: %s: %s" % (command, name, str(e)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
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]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -272,19 +272,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
ansible_module.ipa_command(command, name, args)
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done

View File

@@ -314,12 +314,12 @@ def ensure_members_are_present(module, name, res_find):
return commands return commands
def process_command_failures(command, result): # pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
"""Process the result of a command, looking for errors.""" """Process the result of a command, looking for errors."""
# Get all errors # Get all errors
# All "already a member" and "not a member" failures in the # All "already a member" and "not a member" failures in the
# result are ignored. All others are reported. # result are ignored. All others are reported.
errors = []
if "failed" in result and len(result["failed"]) > 0: if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]: for item in result["failed"]:
failed_item = result["failed"][item] failed_item = result["failed"][item]
@@ -330,37 +330,6 @@ def process_command_failures(command, result):
continue continue
errors.append("%s: %s %s: %s" % ( errors.append("%s: %s %s: %s" % (
command, member_type, member, failure)) command, member_type, member, failure))
return errors
def process_commands(module, commands):
"""Process the list of IPA API commands."""
errors = []
exit_args = {}
changed = False
# Check mode exit
if module.check_mode:
return len(commands) > 0, exit_args
for name, command, args in commands:
try:
result = module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
errors = process_command_failures(command, result)
except Exception as exception: # pylint: disable=broad-except
module.fail_json(
msg="%s: %s: %s" % (command, name, str(exception)))
if errors:
module.fail_json(msg=", ".join(errors))
return changed, exit_args
def role_commands_for_name(module, state, action, name): def role_commands_for_name(module, state, action, name):
@@ -454,7 +423,11 @@ def main():
cmds = role_commands_for_name(ansible_module, state, action, name) cmds = role_commands_for_name(ansible_module, state, action, name)
commands.extend(cmds) commands.extend(cmds)
changed, exit_args = process_commands(ansible_module, commands) exit_args = {}
# Execute commands
changed = ansible_module.execute_ipa_commands(commands, result_handler)
# Done # Done
ansible_module.exit_json(changed=changed, **exit_args) ansible_module.exit_json(changed=changed, **exit_args)

View File

@@ -278,17 +278,7 @@ def main():
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done

View File

@@ -391,17 +391,7 @@ def main():
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done

View File

@@ -409,6 +409,23 @@ def init_ansible_module():
return ansible_module return ansible_module
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors):
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
def main(): def main():
ansible_module = init_ansible_module() ansible_module = init_ansible_module()
@@ -831,34 +848,8 @@ def main():
ansible_module.exit_json(changed=len(commands) > 0, **exit_args) ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
errors = []
for name, command, args in commands:
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result: changed = ansible_module.execute_ipa_commands(commands, result_handler)
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as ex:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(ex)))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done
ansible_module.exit_json(changed=changed, **exit_args) ansible_module.exit_json(changed=changed, **exit_args)

View File

@@ -824,36 +824,10 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
errors = [] changed = ansible_module.execute_ipa_commands(
for name, command, args in commands: commands, fail_on_member_errors=True)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as ex:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(ex)))
# Get all errors
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -716,6 +716,46 @@ def gen_certmapdata_args(certmapdata):
return {"ipacertmapdata": to_text(certmapdata)} return {"ipacertmapdata": to_text(certmapdata)}
# pylint: disable=unused-argument
def result_handler(module, result, command, name, args, errors, exit_args,
one_name):
if "random" in args and command in ["user_add", "user_mod"] \
and "randompassword" in result["result"]:
if one_name:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
# pylint: disable=unused-argument
def exception_handler(module, ex, errors, exit_args, one_name):
msg = str(ex)
if "already contains" in msg \
or "does not contain" in msg:
return True
# The canonical principal name may not be removed
if "equal to the canonical principal name must" in msg:
return True
return False
def main(): def main():
user_spec = dict( user_spec = dict(
# present # present
@@ -1359,58 +1399,11 @@ def main():
del user_set del user_set
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
errors = [] changed = ansible_module.execute_ipa_commands(
for name, command, args in commands: commands, result_handler, exception_handler,
try: exit_args=exit_args, one_name=len(names) == 1)
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
if "random" in args and command in ["user_add", "user_mod"] \
and "randompassword" in result["result"]:
if len(names) == 1:
exit_args["randompassword"] = \
result["result"]["randompassword"]
else:
exit_args.setdefault(name, {})["randompassword"] = \
result["result"]["randompassword"]
except Exception as e:
msg = str(e)
if "already contains" in msg \
or "does not contain" in msg:
continue
# The canonical principal name may not be removed
if "equal to the canonical principal name must" in msg:
continue
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
msg))
# Get all errors
# All "already a member" and "not a member" failures in the
# result are ignored. All others are reported.
if "failed" in result and len(result["failed"]) > 0:
for item in result["failed"]:
failed_item = result["failed"][item]
for member_type in failed_item:
for member, failure in failed_item[member_type]:
if "already a member" in failure \
or "not a member" in failure:
continue
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure))
if len(errors) > 0:
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done
ansible_module.exit_json(changed=changed, user=exit_args) ansible_module.exit_json(changed=changed, user=exit_args)

View File

@@ -286,38 +286,34 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: #
try: # To handle default member errors there is a static method
result = ansible_module.ipa_command(command, name, args) # IPAAnsibleModule.handle_member_errors. It can be enabled with
if "completed" in result: # fail_on_member_failures=True for execute_ipa_commands.
if result["completed"] > 0: # There might be cases in which this needs to be either done
changed = True # manually or extended.
else: #
changed = True # Example:
except Exception as e: #
ansible_module.fail_json(msg="%s: %s: %s" % (command, name, # pylint: disable=unused-argument
str(e))) # def result_handler(module, result, command, name, args, errors):
# Get all errors # # Get all errors
# All "already a member" and "not a member" failures in the # IPAAnsibleModule.handle_member_errors(module, result, command,
# result are ignored. All others are reported. # name, args, errors)
errors = [] # if "MY ERROR" in result.get("failed",[]):
for failed_item in result.get("failed", []): # errors.append("My error")
failed = result["failed"][failed_item] #
for member_type in failed: # # Execute commands
for member, failure in failed[member_type]: #
if "already a member" in failure \ # changed = ansible_module.execute_ipa_commands(commands,
or "not a member" in failure: # result_handler)
continue #
errors.append("%s: %s %s: %s" % (
command, member_type, member, failure)) changed = ansible_module.execute_ipa_commands(
if len(errors) > 0: commands, fail_on_member_failures=True)
ansible_module.fail_json(msg=", ".join(errors))
# Done # Done

View File

@@ -194,23 +194,9 @@ def main():
else: else:
ansible_module.fail_json(msg="Unkown state '%s'" % state) ansible_module.fail_json(msg="Unkown state '%s'" % state)
# Check mode exit
if ansible_module.check_mode:
ansible_module.exit_json(changed=len(commands) > 0, **exit_args)
# Execute commands # Execute commands
for name, command, args in commands: changed = ansible_module.execute_ipa_commands(commands)
try:
result = ansible_module.ipa_command(command, name, args)
if "completed" in result:
if result["completed"] > 0:
changed = True
else:
changed = True
except Exception as e:
ansible_module.fail_json(msg="%s: %s: %s" % (command, name,
str(e)))
# Done # Done