mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-03-26 21:33:05 +00:00
automember: Add support for action: orphans_removed
The removal of group or hostgroup orphans has been added to the automember module. It can be ensured that orphans have been removed using action: orphans_removed The automember_type needs to be set for this. New examples have been added to README-automember.md New playbooks: - playbooks/automember/automember-group-orphans-removed.yml - playbooks/automember/automember-hostgroup-orphans-removed.yml New tests: - tests/automember/test_automember_orphans_removed.yml
This commit is contained in:
@@ -230,6 +230,34 @@ Example playbook to ensure default hostgroup for all unmatched group entries is
|
|||||||
state: absent
|
state: absent
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure all orphan automember group rules are removed:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure all orphan automember group rules are removed
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure all orphan automember hostgroup rules are removed:
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure all orphan automember hostgroup rules are removed
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
@@ -253,7 +281,7 @@ Variable | Description | Required
|
|||||||
`no_wait` | Don't wait for rebuilding membership. | no
|
`no_wait` | Don't wait for rebuilding membership. | no
|
||||||
`default_group` | Default (fallback) group for all unmatched entries. Use the empty string "" for ensuring the default group is not set. | no
|
`default_group` | Default (fallback) group for all unmatched entries. Use the empty string "" for ensuring the default group is not set. | no
|
||||||
`action` | Work on automember or member level. It can be one of `member` or `automember` and defaults to `automember`. | no
|
`action` | Work on automember or member level. It can be one of `member` or `automember` and defaults to `automember`. | no
|
||||||
`state` | The state to ensure. It can be one of `present`, `absent`, 'rebuilt'. default: `present`. | no
|
`state` | The state to ensure. It can be one of `present`, `absent`, 'rebuilt'. 'orphans_removed' default: `present`. | no
|
||||||
|
|
||||||
|
|
||||||
Authors
|
Authors
|
||||||
|
|||||||
10
playbooks/automember/automember-group-orphans-removed.yml
Normal file
10
playbooks/automember/automember-group-orphans-removed.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember orphan group rules are removed example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure orphan group rules are removed
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember orphan hostgroup rules are removed example
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure orphan hostgroup rules are removed
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
@@ -100,7 +100,7 @@ options:
|
|||||||
state:
|
state:
|
||||||
description: State to ensure
|
description: State to ensure
|
||||||
default: present
|
default: present
|
||||||
choices: ["present", "absent", "rebuilt"]
|
choices: ["present", "absent", "rebuilt", "orphans_removed"]
|
||||||
author:
|
author:
|
||||||
- Mark Hahl
|
- Mark Hahl
|
||||||
- Jake Reynolds
|
- Jake Reynolds
|
||||||
@@ -191,6 +191,18 @@ EXAMPLES = """
|
|||||||
automember_type: hostgroup
|
automember_type: hostgroup
|
||||||
default_group: ""
|
default_group: ""
|
||||||
state: absent
|
state: absent
|
||||||
|
|
||||||
|
# Example playbook to ensure all orphan automember group rules are removed:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
|
|
||||||
|
# Example playbook to ensure all orphan automember hostgroup rules are removed:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = """
|
||||||
@@ -215,6 +227,19 @@ def find_automember(module, name, automember_type):
|
|||||||
return _result["result"]
|
return _result["result"]
|
||||||
|
|
||||||
|
|
||||||
|
def find_automember_orphans(module, automember_type):
|
||||||
|
_args = {
|
||||||
|
"all": True,
|
||||||
|
"type": automember_type
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
_result = module.ipa_command_no_name("automember_find_orphans", _args)
|
||||||
|
except ipalib_errors.NotFound:
|
||||||
|
return None
|
||||||
|
return _result
|
||||||
|
|
||||||
|
|
||||||
def find_automember_default_group(module, automember_type):
|
def find_automember_default_group(module, automember_type):
|
||||||
_args = {
|
_args = {
|
||||||
"all": True,
|
"all": True,
|
||||||
@@ -310,7 +335,8 @@ def main():
|
|||||||
action=dict(type="str", default="automember",
|
action=dict(type="str", default="automember",
|
||||||
choices=["member", "automember"]),
|
choices=["member", "automember"]),
|
||||||
state=dict(type="str", default="present",
|
state=dict(type="str", default="present",
|
||||||
choices=["present", "absent", "rebuilt"]),
|
choices=["present", "absent", "rebuilt",
|
||||||
|
"orphans_removed"]),
|
||||||
users=dict(type="list", default=None),
|
users=dict(type="list", default=None),
|
||||||
hosts=dict(type="list", default=None),
|
hosts=dict(type="list", default=None),
|
||||||
),
|
),
|
||||||
@@ -353,7 +379,7 @@ def main():
|
|||||||
# Check parameters
|
# Check parameters
|
||||||
invalid = []
|
invalid = []
|
||||||
|
|
||||||
if state in ["rebuilt"]:
|
if state in ["rebuilt", "orphans_removed"]:
|
||||||
invalid = ["name", "description", "exclusive", "inclusive",
|
invalid = ["name", "description", "exclusive", "inclusive",
|
||||||
"default_group"]
|
"default_group"]
|
||||||
|
|
||||||
@@ -371,6 +397,13 @@ def main():
|
|||||||
msg="state %s: users can not be set when type is '%s'" %
|
msg="state %s: users can not be set when type is '%s'" %
|
||||||
(state, automember_type))
|
(state, automember_type))
|
||||||
|
|
||||||
|
elif state == "orphans_removed":
|
||||||
|
invalid.extend(["users", "hosts"])
|
||||||
|
|
||||||
|
if not automember_type:
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="'automember_type' is required unless state: rebuilt")
|
||||||
|
|
||||||
else:
|
else:
|
||||||
if default_group is not None:
|
if default_group is not None:
|
||||||
for param in ["name", "exclusive", "inclusive", "users", "hosts"
|
for param in ["name", "exclusive", "inclusive", "users", "hosts"
|
||||||
@@ -533,6 +566,14 @@ def main():
|
|||||||
rebuild_hosts, no_wait)
|
rebuild_hosts, no_wait)
|
||||||
commands.append([None, 'automember_rebuild', args])
|
commands.append([None, 'automember_rebuild', args])
|
||||||
|
|
||||||
|
elif state == "orphans_removed":
|
||||||
|
res_find = find_automember_orphans(ansible_module,
|
||||||
|
automember_type)
|
||||||
|
if res_find["count"] > 0:
|
||||||
|
commands.append([None, 'automember_find_orphans',
|
||||||
|
{'type': automember_type,
|
||||||
|
'remove': True}])
|
||||||
|
|
||||||
elif default_group is not None and state == "present":
|
elif default_group is not None and state == "present":
|
||||||
res_find = find_automember_default_group(ansible_module,
|
res_find = find_automember_default_group(ansible_module,
|
||||||
automember_type)
|
automember_type)
|
||||||
|
|||||||
250
tests/automember/test_automember_orphans_removed.yml
Normal file
250
tests/automember/test_automember_orphans_removed.yml
Normal file
@@ -0,0 +1,250 @@
|
|||||||
|
---
|
||||||
|
- name: Test automember orphans_removed
|
||||||
|
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
|
||||||
|
# SET FACTS
|
||||||
|
|
||||||
|
- name: Get Domain from server name
|
||||||
|
set_fact:
|
||||||
|
ipaserver_domain: "{{ ansible_facts['fqdn'].split('.')[1:] |
|
||||||
|
join ('.') }}"
|
||||||
|
when: ipaserver_domain is not defined
|
||||||
|
|
||||||
|
# CLEANUP TEST ITEMS
|
||||||
|
|
||||||
|
- name: Ensure user testuser is absent
|
||||||
|
ipauser:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testuser
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure group testgroup is absent
|
||||||
|
ipagroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure host testhost is absent
|
||||||
|
ipahost:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: "{{ 'testhost.' + ipaserver_domain }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure hostgroup testhostgroup is absent
|
||||||
|
ipahostgroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure automember group testgroup is absent
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
automember_type: group
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure automember hostgroup testhostgroup is absent
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
# CREATE TEST ITEMS
|
||||||
|
|
||||||
|
- name: Ensure user testuser is present
|
||||||
|
ipauser:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testuser
|
||||||
|
first: Test
|
||||||
|
last: User
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure host testhost is present
|
||||||
|
ipahost:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: "{{ 'testhost.' + ipaserver_domain }}"
|
||||||
|
force: yes
|
||||||
|
reverse: no
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure group testgroup is present
|
||||||
|
ipagroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure hostgroup testhostgroup is present
|
||||||
|
ipahostgroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
state: present
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
# TESTS
|
||||||
|
|
||||||
|
# GROUP TEST
|
||||||
|
|
||||||
|
- name: Ensure automember group testgroup exists
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
automember_type: group
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember group condition exits for users
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
automember_type: group
|
||||||
|
action: member
|
||||||
|
inclusive:
|
||||||
|
- key: uid
|
||||||
|
expression: uid
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure group testgroup is absent
|
||||||
|
ipagroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure group orphans have been removed
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure group orphans have been removed again
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
automember_type: group
|
||||||
|
state: orphans_removed
|
||||||
|
register: result
|
||||||
|
failed_when: result.changed or result.failed
|
||||||
|
|
||||||
|
# HOSTGROUP TEST
|
||||||
|
|
||||||
|
- name: Ensure automember hostgroup testhostgroup exists
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
automember_type: hostgroup
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember hostgroup condition exits for hosts
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
automember_type: hostgroup
|
||||||
|
action: member
|
||||||
|
inclusive:
|
||||||
|
- key: fqdn
|
||||||
|
expression: "{{ '.*.' + ipaserver_domain }}"
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure hostgroup testhostgroup is absent
|
||||||
|
ipahostgroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
state: absent
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure hostgroup orphans have been removed
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure hostgroup orphans have been removed again
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: orphans_removed
|
||||||
|
register: result
|
||||||
|
failed_when: result.changed or result.failed
|
||||||
|
|
||||||
|
# CLEANUP TEST ITEMS
|
||||||
|
|
||||||
|
- name: Ensure user testuser is absent
|
||||||
|
ipauser:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testuser
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure group testgroup is absent
|
||||||
|
ipagroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure host testhost is absent
|
||||||
|
ipahost:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: "{{ 'testhost.' + ipaserver_domain }}"
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure hostgroup testhostgroup is absent
|
||||||
|
ipahostgroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure automember group testgroup is absent
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
automember_type: group
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
- name: Ensure automember hostgroup testhostgroup is absent
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testhostgroup
|
||||||
|
automember_type: hostgroup
|
||||||
|
state: absent
|
||||||
Reference in New Issue
Block a user