mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
* ldap_entry - Recursive deletion
* Recursive deletion can be enabled with the `recursive` option. It is
disabled by default.
* When enabled, deletion is attempted by sending a single delete
request with the Subtree Delete control. If that request fails with
the `NOT_ALLOWED_ON_NONLEAF` error, try deleting the whole branch in
reverse order using individual delete requests.
* ldap_entry recursive deletion - Changelog fragment
* ldap_entry - Refactored to avoid lint message
* Update changelogs/fragments/4355-ldap-recursive-delete.yml
Co-authored-by: Felix Fontein <felix@fontein.de>
* ldap_entry - Add version_added to the recursive flag
Co-authored-by: Felix Fontein <felix@fontein.de>
* ldap_entry - Moved member assignment to a more suitable location
Co-authored-by: Felix Fontein <felix@fontein.de>
(cherry picked from commit 0b71d123d2
)
Co-authored-by: Emmanuel Benoît <tseeker@nocternity.net>
This commit is contained in:
parent
7fcb21e044
commit
89663a0688
2 changed files with 33 additions and 2 deletions
4
changelogs/fragments/4355-ldap-recursive-delete.yml
Normal file
4
changelogs/fragments/4355-ldap-recursive-delete.yml
Normal file
|
@ -0,0 +1,4 @@
|
||||||
|
---
|
||||||
|
minor_changes:
|
||||||
|
- ldap_entry - add support for recursive deletion
|
||||||
|
(https://github.com/ansible-collections/community.general/issues/3613).
|
|
@ -49,6 +49,13 @@ options:
|
||||||
choices: [present, absent]
|
choices: [present, absent]
|
||||||
default: present
|
default: present
|
||||||
type: str
|
type: str
|
||||||
|
recursive:
|
||||||
|
description:
|
||||||
|
- If I(state=delete), a flag indicating whether a single entry or the
|
||||||
|
whole branch must be deleted.
|
||||||
|
type: bool
|
||||||
|
default: false
|
||||||
|
version_added: 4.6.0
|
||||||
extends_documentation_fragment:
|
extends_documentation_fragment:
|
||||||
- community.general.ldap.documentation
|
- community.general.ldap.documentation
|
||||||
|
|
||||||
|
@ -110,6 +117,7 @@ from ansible_collections.community.general.plugins.module_utils.ldap import Ldap
|
||||||
LDAP_IMP_ERR = None
|
LDAP_IMP_ERR = None
|
||||||
try:
|
try:
|
||||||
import ldap.modlist
|
import ldap.modlist
|
||||||
|
import ldap.controls
|
||||||
|
|
||||||
HAS_LDAP = True
|
HAS_LDAP = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
@ -123,6 +131,7 @@ class LdapEntry(LdapGeneric):
|
||||||
|
|
||||||
# Shortcuts
|
# Shortcuts
|
||||||
self.state = self.module.params['state']
|
self.state = self.module.params['state']
|
||||||
|
self.recursive = self.module.params['recursive']
|
||||||
|
|
||||||
# Add the objectClass into the list of attributes
|
# Add the objectClass into the list of attributes
|
||||||
self.module.params['attributes']['objectClass'] = (
|
self.module.params['attributes']['objectClass'] = (
|
||||||
|
@ -158,11 +167,28 @@ class LdapEntry(LdapGeneric):
|
||||||
return action
|
return action
|
||||||
|
|
||||||
def delete(self):
|
def delete(self):
|
||||||
""" If self.dn exists, returns a callable that will delete it. """
|
""" If self.dn exists, returns a callable that will delete either
|
||||||
|
the item itself if the recursive option is not set or the whole branch
|
||||||
|
if it is. """
|
||||||
def _delete():
|
def _delete():
|
||||||
self.connection.delete_s(self.dn)
|
self.connection.delete_s(self.dn)
|
||||||
|
|
||||||
|
def _delete_recursive():
|
||||||
|
""" Attempt recurive deletion using the subtree-delete control.
|
||||||
|
If that fails, do it manually. """
|
||||||
|
try:
|
||||||
|
subtree_delete = ldap.controls.ValueLessRequestControl('1.2.840.113556.1.4.805')
|
||||||
|
self.connection.delete_ext_s(self.dn, serverctrls=[subtree_delete])
|
||||||
|
except ldap.NOT_ALLOWED_ON_NONLEAF:
|
||||||
|
search = self.connection.search_s(self.dn, ldap.SCOPE_SUBTREE, attrlist=('dn',))
|
||||||
|
search.reverse()
|
||||||
|
for entry in search:
|
||||||
|
self.connection.delete_s(entry[0])
|
||||||
|
|
||||||
if self._is_entry_present():
|
if self._is_entry_present():
|
||||||
|
if self.recursive:
|
||||||
|
action = _delete_recursive
|
||||||
|
else:
|
||||||
action = _delete
|
action = _delete
|
||||||
else:
|
else:
|
||||||
action = None
|
action = None
|
||||||
|
@ -186,6 +212,7 @@ def main():
|
||||||
attributes=dict(default={}, type='dict'),
|
attributes=dict(default={}, type='dict'),
|
||||||
objectClass=dict(type='list', elements='str'),
|
objectClass=dict(type='list', elements='str'),
|
||||||
state=dict(default='present', choices=['present', 'absent']),
|
state=dict(default='present', choices=['present', 'absent']),
|
||||||
|
recursive=dict(default=False, type='bool'),
|
||||||
),
|
),
|
||||||
required_if=[('state', 'present', ['objectClass'])],
|
required_if=[('state', 'present', ['objectClass'])],
|
||||||
supports_check_mode=True,
|
supports_check_mode=True,
|
||||||
|
|
Loading…
Reference in a new issue