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]
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)
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)