mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-08-01 20:34:41 +00:00
iparole: Case insensitive comparison of service members.
Service members in IPA role objects must be compared ignoring character capitalization, but are stored in a case preserving manner. This patch modifies the way service members are handled, creating a map between a lowercase version of the service parameter and the parameter itself, and using the map key to compare against existing services. The mapped value is then added as role member, if necessary.
This commit is contained in:
@@ -196,10 +196,12 @@ def ensure_absent_state(module, name, action, res_find):
|
|||||||
if items:
|
if items:
|
||||||
member_args[key] = items
|
member_args[key] = items
|
||||||
|
|
||||||
_services = filter_service(module, res_find,
|
_services = get_service_param(module, "service")
|
||||||
lambda res, svc: res.startswith(svc))
|
|
||||||
if _services:
|
if _services:
|
||||||
member_args['service'] = _services
|
_existing = get_lowercase(res_find, "member_service")
|
||||||
|
items = gen_intersection_list(_services.keys(), _existing)
|
||||||
|
if items:
|
||||||
|
member_args["service"] = [_services[key] for key in items]
|
||||||
|
|
||||||
# Only add remove command if there's at least one member no manage.
|
# Only add remove command if there's at least one member no manage.
|
||||||
if member_args:
|
if member_args:
|
||||||
@@ -208,27 +210,59 @@ def ensure_absent_state(module, name, action, res_find):
|
|||||||
return commands
|
return commands
|
||||||
|
|
||||||
|
|
||||||
def filter_service(module, res_find, predicate):
|
def get_service_param(module, key):
|
||||||
"""
|
"""
|
||||||
Filter service based on predicate.
|
Retrieve dict of services, with realm, from the module parameters.
|
||||||
|
|
||||||
Compare service name with existing ones matching
|
As the services are compared in a case insensitive manner, but
|
||||||
at least until `@` from principal name.
|
are recorded in a case preserving way, a dict mapping the services
|
||||||
|
in lowercase to the provided module parameter is generated, so
|
||||||
Predicate is a callable that accepts the existing service, and the
|
that dict keys can be used for comparison and the values are used
|
||||||
modified service to be compared to.
|
with IPA API.
|
||||||
"""
|
"""
|
||||||
_services = []
|
_services = module.params_get(key)
|
||||||
service = module.params_get('service')
|
if _services is not None:
|
||||||
if service:
|
ipa_realm = module.ipa_get_realm()
|
||||||
existing = [to_text(x) for x in res_find.get('member_service', [])]
|
_services = [
|
||||||
for svc in service:
|
to_text(svc) if '@' in svc else ('%s@%s' % (svc, ipa_realm))
|
||||||
svc = svc if '@' in svc else ('%s@' % svc)
|
for svc in _services
|
||||||
found = [x for x in existing if predicate(x, svc)]
|
]
|
||||||
_services.extend(found)
|
if _services:
|
||||||
|
_services = {svc.lower(): svc for svc in _services}
|
||||||
return _services
|
return _services
|
||||||
|
|
||||||
|
|
||||||
|
def get_lowercase(res_find, key, default=None):
|
||||||
|
"""
|
||||||
|
Retrieve a member of a dictionary converted to lowercase.
|
||||||
|
|
||||||
|
If 'key' is not found in the dictionary, return 'default'.
|
||||||
|
"""
|
||||||
|
existing = res_find.get(key)
|
||||||
|
if existing is not None:
|
||||||
|
if isinstance(existing, (list, tuple)):
|
||||||
|
existing = [to_text(item).lower() for item in existing]
|
||||||
|
if isinstance(existing, (str, unicode)):
|
||||||
|
existing = existing.lower()
|
||||||
|
else:
|
||||||
|
existing = default
|
||||||
|
return existing
|
||||||
|
|
||||||
|
|
||||||
|
def gen_services_add_del_lists(module, mod_member, res_find, res_member):
|
||||||
|
"""Generate add/del lists for service principals."""
|
||||||
|
add_list, del_list = None, None
|
||||||
|
_services = get_service_param(module, mod_member)
|
||||||
|
if _services is not None:
|
||||||
|
_existing = result_get_value_lowercase(res_find, res_member)
|
||||||
|
add_list, del_list = gen_add_del_lists(_services.keys(), _existing)
|
||||||
|
if add_list:
|
||||||
|
add_list = [_services[key] for key in add_list]
|
||||||
|
if del_list:
|
||||||
|
del_list = [to_text(item) for item in del_list]
|
||||||
|
return add_list, del_list
|
||||||
|
|
||||||
|
|
||||||
def ensure_role_with_members_is_present(module, name, res_find, action):
|
def ensure_role_with_members_is_present(module, name, res_find, action):
|
||||||
"""Define commands to ensure member are present for action `role`."""
|
"""Define commands to ensure member are present for action `role`."""
|
||||||
commands = []
|
commands = []
|
||||||
@@ -256,18 +290,12 @@ def ensure_role_with_members_is_present(module, name, res_find, action):
|
|||||||
if del_list:
|
if del_list:
|
||||||
del_members[key] = [to_text(item) for item in del_list]
|
del_members[key] = [to_text(item) for item in del_list]
|
||||||
|
|
||||||
service = [
|
(add_services, del_services) = gen_services_add_del_lists(
|
||||||
to_text(svc)
|
module, "service", res_find, "member_service")
|
||||||
if '@' in svc
|
if add_services:
|
||||||
else ('%s@%s' % (svc, module.ipa_get_realm()))
|
add_members["service"] = add_services
|
||||||
for svc in (module.params_get('service') or [])
|
if del_services:
|
||||||
]
|
del_members["service"] = del_services
|
||||||
existing = [str(svc) for svc in res_find.get('member_service', [])]
|
|
||||||
add_list, del_list = gen_add_del_lists(service, existing)
|
|
||||||
if add_list:
|
|
||||||
add_members['service'] = add_list
|
|
||||||
if del_list:
|
|
||||||
del_members['service'] = [to_text(item) for item in del_list]
|
|
||||||
|
|
||||||
if add_members:
|
if add_members:
|
||||||
commands.append([name, "role_add_member", add_members])
|
commands.append([name, "role_add_member", add_members])
|
||||||
|
|||||||
Reference in New Issue
Block a user