Skip to content

Commit

Permalink
ipagroup: Implement state:quers using IPAAnsibleModule.execute_query
Browse files Browse the repository at this point in the history
The query_param parameter has been added, together with the dict
query_param_settings. The existing find_group function has been
transformed into user_show to get the result for a single user and
new convert_result and user_find function have been added.
  • Loading branch information
t-woerner committed Aug 29, 2022
1 parent 54665c6 commit 864c54c
Show file tree
Hide file tree
Showing 4 changed files with 386 additions and 30 deletions.
14 changes: 10 additions & 4 deletions plugins/module_utils/ansible_freeipa_module.py
Original file line number Diff line number Diff line change
Expand Up @@ -1272,7 +1272,7 @@ def exception_handler(module, ex, exit_args, one_name):
return changed

def execute_query(self, names, prefix, name_ipa_param,
query_param, query_command, query_param_settings):
query_param, find_command, query_param_settings):
"""
Execute query state.
Expand All @@ -1295,7 +1295,7 @@ def execute_query(self, names, prefix, name_ipa_param,
mapping of the default module paramter name to IPA option name
if it is not the same.
Example: "uid" for user name of the user commands.
query_command: The Query function
find_command: The find function
This is a module function that returns the structure(s) from
the show or find command.
Expand Down Expand Up @@ -1335,13 +1335,19 @@ def store_params(exit_args, name, prefix, name_ipa_param, result,
if names and isinstance(names, list):
with_name = len(names) > 1
for name in names:
result = query_command(self, name)
if query_param is None:
result = find_command(self, name, pkey_only=True)
else:
result = find_command(self, name)
if result:
store_params(exit_args, name if with_name else None,
prefix, name_ipa_param, result,
query_param)
else:
results = query_command(self, None)
if query_param is None:
results = find_command(self, None, pkey_only=True)
else:
results = find_command(self, None)
if results is not None:
for result in results:
name = result[name_ipa_param]
Expand Down
142 changes: 119 additions & 23 deletions plugins/modules/ipagroup.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
- ipamodule_base_docs
options:
name:
description: The group name
description: The group namename
required: false
aliases: ["cn"]
description:
Expand Down Expand Up @@ -102,14 +102,18 @@
- User ID overrides to add
required: false
type: list
query_param:
description: The fields to query with state=query
required: false
action:
description: Work on group or member level
default: group
choices: ["member", "group"]
state:
description: State to ensure
default: present
choices: ["present", "absent"]
choices: ["present", "absent",
"query"]
author:
- Thomas Woerner
"""
Expand Down Expand Up @@ -189,31 +193,70 @@
from ansible.module_utils._text import to_text
from ansible.module_utils.ansible_freeipa_module import \
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, \
gen_add_list, gen_intersection_list, api_check_param
gen_add_list, gen_intersection_list, api_check_param, ipalib_errors


def find_group(module, name):
def group_show(module, name):
_args = {
"all": True,
"cn": name,
}

_result = module.ipa_command("group_find", name, _args)

if len(_result["result"]) > 1:
module.fail_json(
msg="There is more than one group '%s'" % (name))
elif len(_result["result"]) == 1:
_res = _result["result"][0]
# The returned services are of type ipapython.kerberos.Principal,
# also services are not case sensitive. Therefore services are
# converted to lowercase strings to be able to do the comparison.
if "member_service" in _res:
_res["member_service"] = \
[to_text(svc).lower() for svc in _res["member_service"]]
return _res
try:
_result = module.ipa_command("group_show", name, _args).get("result")
except ipalib_errors.NotFound:
return None

# The returned services are of type ipapython.kerberos.Principal,
# also services are not case sensitive. Therefore services are
# converted to lowercase strings to be able to do the comparison.
if "member_service" in _result:
_result["member_service"] = \
[to_text(svc).lower() for svc in _result["member_service"]]
return _result


def convert_result(res):
_res = {}
for key in res:
if isinstance(res[key], list):
# All single value parameters should not be lists
# This does not apply to manager, krbprincipalname,
# usercertificate and ipacertmapdata
if len(res[key]) == 1:
_res[key] = to_text(res[key][0])
else:
_res[key] = [to_text(item) for item in res[key]]
elif key in ["gidNumber"]:
_res[key] = int(res[key])
else:
_res[key] = to_text(res[key])
return _res


def group_find(module, name, pkey_only=False, sizelimit=None, timelimit=None):
_args = {"all": True}

if name:
_args["cn"] = name
if pkey_only:
_args["pkey_only"] = True
if sizelimit is not None:
_args["sizelimit"] = sizelimit
if timelimit is not None:
_args["timelimit"] = timelimit

try:
_result = module.ipa_command_no_name("group_find", _args).get("result")
if _result:
if name:
_result = convert_result(_result[0])
else:
_result = [convert_result(res) for res in _result]

return None
except ipalib_errors.NotFound:
return None
else:
return _result


def gen_args(description, gid, nomembers):
Expand Down Expand Up @@ -271,12 +314,37 @@ def check_objectclass_args(module, res_find, posix, external):
"`non-posix`.")


query_param_settings = {
"ALL": [
"dn", "objectclass", "ipauniqueid", "ipantsecurityidentifier",
"name",
"description",
"gid",
"nomembers",
"user", "group", "service", "external",
"idoverrideuser"
],
"BASE": [
"name", "description", "gid"
],
"mapping": {
"name": "cn",
"gid": "gidnumber",
"user": "member_user",
"group": "member_group",
"service": "member_service",
"externalmember": "member_external",
"idoverrideuser": "member_idoverrideuser",
}
}


def main():
ansible_module = IPAAnsibleModule(
argument_spec=dict(
# general
name=dict(type="list", aliases=["cn"], default=None,
required=True),
required=False),
# present
description=dict(type="str", default=None),
gid=dict(type="int", aliases=["gidnumber"], default=None),
Expand All @@ -296,11 +364,17 @@ def main():
"ipaexternalmember",
"external_member"
]),
# query
query_param=dict(type="list", default=None,
choices=["ALL", "BASE"].extend(
query_param_settings["ALL"]),
required=False),
# action
action=dict(type="str", default="group",
choices=["member", "group"]),
# state
state=dict(type="str", default="present",
choices=["present", "absent"]),
choices=["present", "absent", "query"]),
),
# It does not make sense to set posix, nonposix or external at the
# same time
Expand Down Expand Up @@ -330,6 +404,9 @@ def main():
membermanager_user = ansible_module.params_get("membermanager_user")
membermanager_group = ansible_module.params_get("membermanager_group")
externalmember = ansible_module.params_get("externalmember")
# query
query_param = ansible_module.params_get("query_param")
# action
action = ansible_module.params_get("action")
# state
state = ansible_module.params_get("state")
Expand All @@ -354,6 +431,18 @@ def main():
if action == "group":
invalid.extend(["user", "group", "service", "externalmember"])

# if state == "query":
# invalid.append("groups")
#
# if action == "member":
# module.fail_json(
# msg="Query is not possible with action=member")

if state != "query":
if names is None or len(names) < 1:
ansible_module.fail_json(msg="name is required")
invalid.append("query_param")

ansible_module.params_fail_used_invalid(invalid, state, action)

if external is False:
Expand All @@ -372,6 +461,13 @@ def main():
# Connect to IPA API
with ansible_module.ipa_connect():

if state == "query":
exit_args = ansible_module.execute_query(
names, "groups", "cn", query_param, group_find,
query_param_settings)

ansible_module.exit_json(changed=False, group=exit_args)

has_add_member_service = ansible_module.ipa_command_param_exists(
"group_add_member", "service")
if service is not None and not has_add_member_service:
Expand Down Expand Up @@ -399,7 +495,7 @@ def main():

for name in names:
# Make sure group exists
res_find = find_group(ansible_module, name)
res_find = group_show(ansible_module, name)

user_add, user_del = [], []
group_add, group_del = [], []
Expand Down
8 changes: 5 additions & 3 deletions plugins/modules/ipauser.py
Original file line number Diff line number Diff line change
Expand Up @@ -524,17 +524,19 @@ def convert_result(res):
return _res


def user_find(module, name, sizelimit=None, timelimit=None):
def user_find(module, name, pkey_only=False, sizelimit=None, timelimit=None):
_args = {"all": True}

if name:
_args["uid"] = name
if pkey_only:
_args["pkey_only"] = True
if sizelimit is not None:
_args["sizelimit"] = sizelimit
if timelimit is not None:
_args["timelimit"] = timelimit

try:
if name:
_args["uid"] = name
_result = module.ipa_command_no_name("user_find", _args).get("result")
if _result:
if name:
Expand Down
Loading

0 comments on commit 864c54c

Please sign in to comment.