Exemple #1
0
def find_dnsconfig(module):
    _args = {
        "all": True,
    }

    _result = api_command_no_name(module, "dnsconfig_show", _args)

    if "result" in _result:
        if _result["result"].get('idnsforwarders', None) is None:
            _result["result"]['idnsforwarders'] = ['']
        return _result["result"]
    else:
        module.fail("Could not retrieve current DNS configuration.")
    return None
def server_role_status(module, name):
    """Get server role of a hidden server with the given name."""
    try:
        _result = api_command_no_name(module, "server_role_find",
                                      {"server_server": name,
                                       "role_servrole": 'IPA master',
                                       "include_master": True,
                                       "raw": True,
                                       "all": True})
    except Exception:  # pylint: disable=broad-except
        # An exception is raised if server name is not found.
        return None
    else:
        return _result["result"][0]
Exemple #3
0
def main():
    forwarder_spec = dict(ip_address=dict(type=str, required=True),
                          port=dict(type=int, required=False, default=None))

    ansible_module = AnsibleModule(argument_spec=dict(
        # general
        ipaadmin_principal=dict(type='str', default='admin'),
        ipaadmin_password=dict(type='str', no_log=True),

        # dnsconfig
        forwarders=dict(type='list',
                        default=None,
                        required=False,
                        options=dict(**forwarder_spec)),
        forward_policy=dict(type='str',
                            required=False,
                            default=None,
                            choices=['only', 'first', 'none']),
        allow_sync_ptr=dict(type='bool', required=False, default=None),

        # general
        state=dict(
            type="str", default="present", choices=["present", "absent"]),
    ))

    ansible_module._ansible_debug = True

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")

    forwarders = module_params_get(ansible_module, 'forwarders') or []
    forward_policy = module_params_get(ansible_module, 'forward_policy')
    allow_sync_ptr = module_params_get(ansible_module, 'allow_sync_ptr')

    state = module_params_get(ansible_module, 'state')

    # Check parameters.
    invalid = []
    if state == 'absent':
        invalid = ['forward_policy', 'allow_sync_ptr']

    for x in invalid:
        if vars()[x] is not None:
            ansible_module.fail_json(
                msg="Argument '%s' can not be used with state '%s'" %
                (x, state))

    # Init

    changed = False
    ccache_dir = None
    ccache_name = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        res_find = find_dnsconfig(ansible_module)
        args = gen_args(ansible_module, state, res_find, forwarders,
                        forward_policy, allow_sync_ptr)

        # Execute command only if configuration changes.
        if not compare_args_ipa(ansible_module, args, res_find):
            try:
                api_command_no_name(ansible_module, 'dnsconfig_mod', args)
                # If command did not fail, something changed.
                changed = True

            except Exception as e:
                msg = str(e)
                ansible_module.fail_json(msg="dnsconfig_mod: %s" % msg)

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done

    ansible_module.exit_json(changed=changed)
Exemple #4
0
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),

            inclusive=dict(type="list",
                           aliases=["automemberinclusiveregex"], default=None,
                           options=dict(
                               key=dict(type="str", required=True),
                               expression=dict(type="str", required=True)
                           ),
                           elements="dict", required=False),
            exclusive=dict(type="list", aliases=[
                           "automemberexclusiveregex"], default=None,
                           options=dict(
                               key=dict(type="str", required=True),
                               expression=dict(type="str", required=True)
                           ),
                           elements="dict", required=False),
            name=dict(type="list", aliases=["cn"],
                      default=None, required=True),
            description=dict(type="str", default=None),
            automember_type=dict(type='str', required=False,
                                 choices=['group', 'hostgroup']),
            action=dict(type="str", default="automember",
                        choices=["member", "automember"]),
            state=dict(type="str", default="present",
                       choices=["present", "absent", "rebuild"]),
            users=dict(type="list", default=None),
            hosts=dict(type="list", default=None),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
    ipaadmin_password = ansible_module.params.get("ipaadmin_password")
    names = ansible_module.params.get("name")

    # present
    description = ansible_module.params.get("description")

    # conditions
    inclusive = ansible_module.params.get("inclusive")
    exclusive = ansible_module.params.get("exclusive")

    # action
    action = ansible_module.params.get("action")
    # state
    state = ansible_module.params.get("state")

    # grouping/type
    automember_type = ansible_module.params.get("automember_type")

    rebuild_users = ansible_module.params.get("users")
    rebuild_hosts = ansible_module.params.get("hosts")

    if (rebuild_hosts or rebuild_users) and state != "rebuild":
        ansible_module.fail_json(
            msg="'hosts' and 'users' are only valid with state: rebuild")
    if not automember_type and state != "rebuild":
        ansible_module.fail_json(
            msg="'automember_type' is required unless state: rebuild")

    # Init
    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    res_find = None

    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        commands = []

        for name in names:
            # Make sure automember rule exists
            res_find = find_automember(ansible_module, name, automember_type)

            # Check inclusive and exclusive conditions
            if inclusive is not None or exclusive is not None:
                # automember_type is either "group" or "hostgorup"
                if automember_type == "group":
                    _type = "user"
                elif automember_type == "hostgroup":
                    _type = "host"
                else:
                    ansible_module.fail_json(
                        msg="Bad automember type '%s'" % automember_type)

                try:
                    aciattrs = api_command(
                        ansible_module, "json_metadata", to_text(_type), {}
                    )['objects'][_type]['aciattrs']
                except Exception as ex:
                    ansible_module.fail_json(
                        msg="%s: %s: %s" % ("json_metadata", _type, str(ex)))

                check_condition_keys(ansible_module, inclusive, aciattrs)
                check_condition_keys(ansible_module, exclusive, aciattrs)

            # Create command
            if state == 'present':
                args = gen_args(description, automember_type)

                if action == "automember":
                    if res_find is not None:
                        if not compare_args_ipa(ansible_module,
                                                args,
                                                res_find,
                                                ignore=['type']):
                            commands.append([name, 'automember_mod', args])
                    else:
                        commands.append([name, 'automember_add', args])
                        res_find = {}

                    inclusive_add, inclusive_del = gen_add_del_lists(
                        transform_conditions(inclusive or []),
                        res_find.get("automemberinclusiveregex", [])
                    )

                    exclusive_add, exclusive_del = gen_add_del_lists(
                        transform_conditions(exclusive or []),
                        res_find.get("automemberexclusiveregex", [])
                    )

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(
                            msg="No automember '%s'" % name)

                    inclusive_add = transform_conditions(inclusive or [])
                    inclusive_del = []
                    exclusive_add = transform_conditions(exclusive or [])
                    exclusive_del = []

                for _inclusive in inclusive_add:
                    key, regex = _inclusive.split("=", 1)
                    condition_args = gen_condition_args(
                        automember_type, key, inclusiveregex=regex)
                    commands.append([name, 'automember_add_condition',
                                     condition_args])

                for _inclusive in inclusive_del:
                    key, regex = _inclusive.split("=", 1)
                    condition_args = gen_condition_args(
                        automember_type, key, inclusiveregex=regex)
                    commands.append([name, 'automember_remove_condition',
                                     condition_args])

                for _exclusive in exclusive_add:
                    key, regex = _exclusive.split("=", 1)
                    condition_args = gen_condition_args(
                        automember_type, key, exclusiveregex=regex)
                    commands.append([name, 'automember_add_condition',
                                     condition_args])

                for _exclusive in exclusive_del:
                    key, regex = _exclusive.split("=", 1)
                    condition_args = gen_condition_args(
                        automember_type, key, exclusiveregex=regex)
                    commands.append([name, 'automember_remove_condition',
                                     condition_args])

            elif state == 'absent':
                if action == "automember":
                    if res_find is not None:
                        commands.append([name, 'automember_del',
                                         {'type': to_text(automember_type)}])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(
                            msg="No automember '%s'" % name)

                    if inclusive is not None:
                        for _inclusive in transform_conditions(inclusive):
                            key, regex = _inclusive.split("=", 1)
                            condition_args = gen_condition_args(
                                automember_type, key, inclusiveregex=regex)
                            commands.append(
                                [name, 'automember_remove_condition',
                                 condition_args])

                    if exclusive is not None:
                        for _exclusive in transform_conditions(exclusive):
                            key, regex = _exclusive.split("=", 1)
                            condition_args = gen_condition_args(
                                automember_type, key, exclusiveregex=regex)
                            commands.append([name,
                                             'automember_remove_condition',
                                            condition_args])

            elif state == "rebuild":
                if automember_type:
                    commands.append([None, 'automember_rebuild',
                                     {"type": to_text(automember_type)}])
                if rebuild_users:
                    commands.append([None, 'automember_rebuild',
                                    {"users": [
                                        to_text(_u)
                                        for _u in rebuild_users]}])
                if rebuild_hosts:
                    commands.append([None, 'automember_rebuild',
                                    {"hosts": [
                                        to_text(_h)
                                        for _h in rebuild_hosts]}])

        # Check mode exit
        if ansible_module.check_mode:
            ansible_module.exit_json(changed=len(commands) > 0, **exit_args)

        for name, command, args in commands:
            try:
                if name is None:
                    result = api_command_no_name(ansible_module, command, args)
                else:
                    result = api_command(ansible_module, command,
                                         to_text(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)))

            # 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.

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done
    ansible_module.exit_json(changed=changed, **exit_args)
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            maxusername=dict(type="int",
                             required=False,
                             aliases=['ipamaxusernamelength']),
            maxhostname=dict(type="int",
                             required=False,
                             aliases=['ipamaxhostnamelength']),
            homedirectory=dict(type="str",
                               required=False,
                               aliases=['ipahomesrootdir']),
            defaultshell=dict(type="str",
                              required=False,
                              aliases=['ipadefaultloginshell', 'loginshell']),
            defaultgroup=dict(type="str",
                              required=False,
                              aliases=['ipadefaultprimarygroup']),
            emaildomain=dict(type="str",
                             required=False,
                             aliases=['ipadefaultemaildomain']),
            searchtimelimit=dict(type="int",
                                 required=False,
                                 aliases=['ipasearchtimelimit']),
            searchrecordslimit=dict(type="int",
                                    required=False,
                                    aliases=['ipasearchrecordslimit']),
            usersearch=dict(type="list",
                            required=False,
                            aliases=['ipausersearchfields']),
            groupsearch=dict(type="list",
                             required=False,
                             aliases=['ipagroupsearchfields']),
            enable_migration=dict(type="bool",
                                  required=False,
                                  aliases=['ipamigrationenabled']),
            groupobjectclasses=dict(type="list",
                                    required=False,
                                    aliases=['ipagroupobjectclasses']),
            userobjectclasses=dict(type="list",
                                   required=False,
                                   aliases=['ipauserobjectclasses']),
            pwdexpnotify=dict(type="int",
                              required=False,
                              aliases=['ipapwdexpadvnotify']),
            configstring=dict(type="list",
                              required=False,
                              aliases=['ipaconfigstring'],
                              choices=[
                                  "AllowNThash", "KDC:Disable Last Success",
                                  "KDC:Disable Lockout",
                                  "KDC:Disable Default Preauth for SPNs", ""
                              ]),  # noqa E128
            selinuxusermaporder=dict(type="list",
                                     required=False,
                                     aliases=['ipaselinuxusermaporder']),
            selinuxusermapdefault=dict(type="str",
                                       required=False,
                                       aliases=['ipaselinuxusermapdefault']),
            pac_type=dict(type="list",
                          required=False,
                          aliases=["ipakrbauthzdata"],
                          choices=["MS-PAC", "PAD", "nfs:NONE", ""]),
            user_auth_type=dict(
                type="list",
                required=False,
                choices=["password", "radius", "otp", "disabled", ""],
                aliases=["ipauserauthtype"]),
            ca_renewal_master_server=dict(type="str", required=False),
            domain_resolution_order=dict(type="list",
                                         required=False,
                                         aliases=["ipadomainresolutionorder"
                                                  ])),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = module_params_get(ansible_module,
                                           "ipaadmin_principal")
    ipaadmin_password = module_params_get(ansible_module, "ipaadmin_password")

    field_map = {
        "maxusername": "******",
        "maxhostname": "ipamaxhostnamelength",
        "homedirectory": "ipahomesrootdir",
        "defaultshell": "ipadefaultloginshell",
        "defaultgroup": "ipadefaultprimarygroup",
        "emaildomain": "ipadefaultemaildomain",
        "searchtimelimit": "ipasearchtimelimit",
        "searchrecordslimit": "ipasearchrecordslimit",
        "usersearch": "ipausersearchfields",
        "groupsearch": "ipagroupsearchfields",
        "enable_migration": "ipamigrationenabled",
        "groupobjectclasses": "ipagroupobjectclasses",
        "userobjectclasses": "ipauserobjectclasses",
        "pwdexpnotify": "ipapwdexpadvnotify",
        "configstring": "ipaconfigstring",
        "selinuxusermaporder": "ipaselinuxusermaporder",
        "selinuxusermapdefault": "ipaselinuxusermapdefault",
        "pac_type": "ipakrbauthzdata",
        "user_auth_type": "ipauserauthtype",
        "ca_renewal_master_server": "ca_renewal_master_server",
        "domain_resolution_order": "ipadomainresolutionorder"
    }
    reverse_field_map = {v: k for k, v in field_map.items()}

    params = {}
    for x in field_map.keys():
        val = module_params_get(ansible_module, x)

        if val is not None:
            params[field_map.get(x, x)] = val

    if params.get("ipamigrationenabled") is not None:
        params["ipamigrationenabled"] = \
            str(params["ipamigrationenabled"]).upper()

    if params.get("ipaselinuxusermaporder", None):
        params["ipaselinuxusermaporder"] = \
            "$".join(params["ipaselinuxusermaporder"])

    if params.get("ipadomainresolutionorder", None):
        params["ipadomainresolutionorder"] = \
             ":".join(params["ipadomainresolutionorder"])

    if params.get("ipausersearchfields", None):
        params["ipausersearchfields"] = \
             ",".join(params["ipausersearchfields"])

    if params.get("ipagroupsearchfields", None):
        params["ipagroupsearchfields"] = \
             ",".join(params["ipagroupsearchfields"])

    # verify limits on INT values.
    args_with_limits = [
        ("ipamaxusernamelength", 1, 255),
        ("ipamaxhostnamelength", 64, 255),
        ("ipasearchtimelimit", -1, 2147483647),
        ("ipasearchrecordslimit", -1, 2147483647),
        ("ipapwdexpadvnotify", 0, 2147483647),
    ]
    for arg, min, max in args_with_limits:
        if arg in params and (params[arg] > max or params[arg] < min):
            ansible_module.fail_json(
                msg="Argument '%s' must be between %d and %d." %
                (arg, min, max))

    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    res_show = None
    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()
        if params:
            res_show = config_show(ansible_module)
            params = {
                k: v
                for k, v in params.items()
                if k not in res_show or res_show[k] != v
            }
            if params \
               and not compare_args_ipa(ansible_module, params, res_show):
                changed = True
                if not ansible_module.check_mode:
                    api_command_no_name(ansible_module, "config_mod", params)

        else:
            rawresult = api_command_no_name(ansible_module, "config_show", {})
            result = rawresult['result']
            del result['dn']
            for key, v in result.items():
                k = reverse_field_map.get(key, key)
                if ansible_module.argument_spec.get(k):
                    if k == 'ipaselinuxusermaporder':
                        exit_args['ipaselinuxusermaporder'] = \
                            result.get(key)[0].split('$')
                    elif k == 'domain_resolution_order':
                        exit_args['domain_resolution_order'] = \
                           result.get(key)[0].split('$')
                    elif k == 'usersearch':
                        exit_args['usersearch'] = \
                            result.get(key)[0].split(',')
                    elif k == 'groupsearch':
                        exit_args['groupsearch'] = \
                            result.get(key)[0].split(',')
                    elif isinstance(v, str) and \
                            ansible_module.argument_spec[k]['type'] == "list":
                        exit_args[k] = [v]
                    elif isinstance(v, list) and \
                            ansible_module.argument_spec[k]['type'] == "str":
                        exit_args[k] = ",".join(v)
                    elif isinstance(v, list) and \
                            ansible_module.argument_spec[k]['type'] == "int":
                        exit_args[k] = ",".join(v)
                    elif isinstance(v, list) and \
                            ansible_module.argument_spec[k]['type'] == "bool":
                        exit_args[k] = (v[0] == "TRUE")
                    else:
                        exit_args[k] = v
    except ipalib.errors.EmptyModlist:
        changed = False
    except Exception as e:
        ansible_module.fail_json(msg="%s %s" % (params, str(e)))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done
    ansible_module.exit_json(changed=changed, config=exit_args)
def config_show(module):
    _result = api_command_no_name(module, "config_show", {})

    return _result["result"]
def main():
    ansible_module = AnsibleModule(
        argument_spec=dict(
            # general
            ipaadmin_principal=dict(type="str", default="admin"),
            ipaadmin_password=dict(type="str", required=False, no_log=True),
            inclusive=dict(type="list",
                           aliases=["automemberinclusiveregex"],
                           default=None),
            exclusive=dict(type="list",
                           aliases=["automemberexclusiveregex"],
                           default=None),
            name=dict(type="list", aliases=["cn"], default=None,
                      required=True),
            description=dict(type="str", default=None),
            automember_type=dict(type='str',
                                 required=False,
                                 choices=['group', 'hostgroup']),
            action=dict(type="str",
                        default="service",
                        choices=["member", "service"]),
            state=dict(type="str",
                       default="present",
                       choices=["present", "absent", "rebuild"]),
            users=dict(type="list", default=None),
            hosts=dict(type="list", default=None),
        ),
        supports_check_mode=True,
    )

    ansible_module._ansible_debug = True

    # Get parameters

    # general
    ipaadmin_principal = ansible_module.params.get("ipaadmin_principal")
    ipaadmin_password = ansible_module.params.get("ipaadmin_password")
    names = ansible_module.params.get("name")

    # present
    description = ansible_module.params.get("description")

    # conditions
    inclusive = ansible_module.params.get("inclusive")
    exclusive = ansible_module.params.get("exclusive")

    # action
    action = ansible_module.params.get("action")
    # state
    state = ansible_module.params.get("state")

    # grouping/type
    automember_type = ansible_module.params.get("automember_type")

    rebuild_users = ansible_module.params.get("users")
    rebuild_hosts = ansible_module.params.get("hosts")

    if (rebuild_hosts or rebuild_users) and state != "rebuild":
        ansible_module.fail_json(
            msg="'hosts' and 'users' are only valid with state: rebuild")
    if not automember_type and state != "rebuild":
        ansible_module.fail_json(
            msg="'automember_type' is required unless state: rebuild")

    # Init
    changed = False
    exit_args = {}
    ccache_dir = None
    ccache_name = None
    res_find = None

    try:
        if not valid_creds(ansible_module, ipaadmin_principal):
            ccache_dir, ccache_name = temp_kinit(ipaadmin_principal,
                                                 ipaadmin_password)
        api_connect()

        commands = []

        for name in names:
            # Make sure automember rule exists
            res_find = find_automember(ansible_module, name, automember_type)

            # Create command
            if state == 'present':
                args = gen_args(description, automember_type)

                if action == "service":
                    if res_find is not None:
                        if not compare_args_ipa(
                                ansible_module, args, res_find,
                                ignore=['type']):
                            commands.append([name, 'automember_mod', args])
                    else:
                        commands.append([name, 'automember_add', args])
                        res_find = {}

                    inclusive_add, inclusive_del = gen_add_del_lists(
                        transform_conditions(inclusive or []),
                        res_find.get("automemberinclusiveregex", []))

                    exclusive_add, exclusive_del = gen_add_del_lists(
                        transform_conditions(exclusive or []),
                        res_find.get("automemberexclusiveregex", []))

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No service '%s'" % name)

                    inclusive_add = transform_conditions(inclusive or [])
                    inclusive_del = []
                    exclusive_add = transform_conditions(exclusive or [])
                    exclusive_del = []

                for _inclusive in inclusive_add:
                    key, regex = _inclusive.split("=", 1)
                    condition_args = gen_condition_args(automember_type,
                                                        key,
                                                        inclusiveregex=regex)
                    commands.append(
                        [name, 'automember_add_condition', condition_args])

                for _inclusive in inclusive_del:
                    key, regex = _inclusive.split("=", 1)
                    condition_args = gen_condition_args(automember_type,
                                                        key,
                                                        inclusiveregex=regex)
                    commands.append(
                        [name, 'automember_remove_condition', condition_args])

                for _exclusive in exclusive_add:
                    key, regex = _exclusive.split("=", 1)
                    condition_args = gen_condition_args(automember_type,
                                                        key,
                                                        exclusiveregex=regex)
                    commands.append(
                        [name, 'automember_add_condition', condition_args])

                for _exclusive in exclusive_del:
                    key, regex = _exclusive.split("=", 1)
                    condition_args = gen_condition_args(automember_type,
                                                        key,
                                                        exclusiveregex=regex)
                    commands.append(
                        [name, 'automember_remove_condition', condition_args])

            elif state == 'absent':
                if action == "service":
                    if res_find is not None:
                        commands.append([
                            name, 'automember_del', {
                                'type': to_text(automember_type)
                            }
                        ])

                elif action == "member":
                    if res_find is None:
                        ansible_module.fail_json(msg="No service '%s'" % name)

                    if inclusive is not None:
                        for _inclusive in transform_conditions(inclusive):
                            key, regex = _inclusive.split("=", 1)
                            condition_args = gen_condition_args(
                                automember_type, key, inclusiveregex=regex)
                            commands.append([
                                name, 'automember_remove_condition',
                                condition_args
                            ])

                    if exclusive is not None:
                        for _exclusive in transform_conditions(exclusive):
                            key, regex = _exclusive.split("=", 1)
                            condition_args = gen_condition_args(
                                automember_type, key, exclusiveregex=regex)
                            commands.append([
                                name, 'automember_remove_condition',
                                condition_args
                            ])

            elif state == "rebuild":
                if automember_type:
                    commands.append([
                        None, 'automember_rebuild', {
                            "type": to_text(automember_type)
                        }
                    ])
                if rebuild_users:
                    commands.append([
                        None, 'automember_rebuild', {
                            "users": [to_text(_u) for _u in rebuild_users]
                        }
                    ])
                if rebuild_hosts:
                    commands.append([
                        None, 'automember_rebuild', {
                            "hosts": [to_text(_h) for _h in rebuild_hosts]
                        }
                    ])

        # Check mode exit
        if ansible_module.check_mode:
            ansible_module.exit_json(changed=len(commands) > 0, **exit_args)

        errors = []
        for name, command, args in commands:
            try:
                if name is None:
                    result = api_command_no_name(ansible_module, command, args)
                else:
                    result = api_command(ansible_module, command,
                                         to_text(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
            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))

    except Exception as e:
        ansible_module.fail_json(msg=str(e))

    finally:
        temp_kdestroy(ccache_dir, ccache_name)

    # Done
    ansible_module.exit_json(changed=changed, **exit_args)