mirror of
https://github.com/freeipa/ansible-freeipa.git
synced 2026-07-25 00:44:42 +00:00
automember: Add automember default group handling
The fallback group and hostgroup for unmached entries can be set and unset using default_group. If default_group is empty, then the default group will be unset. DN and ipa_get_based provided by ansible_freeipa_module are used in the code. New parameters: - default_group: Default (fallback) group for all unmatched entries. New parameters and examples have been added to README-automember.md New playbooks: - playbooks/automember/automember-default-group-not-set.yml - playbooks/automember/automember-default-group-set.yml - playbooks/automember/automember-default-hostgroup-not-set.yml - playbooks/automember/automember-default-hostgroup-set.yml New tests: - tests/automember/test_automember_default_group.yml
This commit is contained in:
@@ -172,6 +172,64 @@ Example playbook to ensure hostgroup membership for given hosts has been rebuilt
|
|||||||
state: rebuilt
|
state: rebuilt
|
||||||
```
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default group fallback_group for all unmatched group entries is set
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default group fallback_group for all unmatched group entries is set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: fallback_group
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default group for all unmatched group entries is not set
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default group for all unmatched group entries is not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
state: absent
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default hostgroup fallback_hostgroup for all unmatched group entries
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default hostgroup fallback_hostgroup for all unmatched group entries
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: fallback_hostgroup
|
||||||
|
```
|
||||||
|
|
||||||
|
Example playbook to ensure default hostgroup for all unmatched group entries is not set
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- name: Playbook to ensure default hostgroup for all unmatched group entries is not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: yes
|
||||||
|
gather_facts: no
|
||||||
|
tasks:
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: ""
|
||||||
|
state: absent
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
Variables
|
Variables
|
||||||
---------
|
---------
|
||||||
@@ -193,6 +251,7 @@ Variable | Description | Required
|
|||||||
`users` | Users to rebuild membership for. | no
|
`users` | Users to rebuild membership for. | no
|
||||||
`hosts` | Hosts to rebuild membership for. | no
|
`hosts` | Hosts to rebuild membership for. | no
|
||||||
`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
|
||||||
`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'. default: `present`. | no
|
||||||
|
|
||||||
|
|||||||
10
playbooks/automember/automember-default-group-not-set.yml
Normal file
10
playbooks/automember/automember-default-group-not-set.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default group not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default group is not set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: ""
|
||||||
10
playbooks/automember/automember-default-group-set.yml
Normal file
10
playbooks/automember/automember-default-group-set.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default group set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default group is set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: fallback_group
|
||||||
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default hostgroup not set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default hostgroup is not set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: ""
|
||||||
10
playbooks/automember/automember-default-hostgroup-set.yml
Normal file
10
playbooks/automember/automember-default-hostgroup-set.yml
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
---
|
||||||
|
- name: Automember default hostgroup set
|
||||||
|
hosts: ipaserver
|
||||||
|
become: true
|
||||||
|
tasks:
|
||||||
|
- name: Ensure automember default hostgroup is set
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: fallback_hostgroup
|
||||||
@@ -90,6 +90,9 @@ options:
|
|||||||
no_wait:
|
no_wait:
|
||||||
description: Don't wait for rebuilding membership.
|
description: Don't wait for rebuilding membership.
|
||||||
type: bool
|
type: bool
|
||||||
|
default_group:
|
||||||
|
description: Default (fallback) group for all unmatched entries.
|
||||||
|
type: str
|
||||||
action:
|
action:
|
||||||
description: Work on automember or member level
|
description: Work on automember or member level
|
||||||
default: automember
|
default: automember
|
||||||
@@ -161,6 +164,33 @@ EXAMPLES = """
|
|||||||
- host1.mydomain.com
|
- host1.mydomain.com
|
||||||
- host2.mydomain.com
|
- host2.mydomain.com
|
||||||
state: rebuilt
|
state: rebuilt
|
||||||
|
|
||||||
|
# Ensure default group fallback_group for all unmatched group entries is set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: group
|
||||||
|
default_group: fallback_group
|
||||||
|
|
||||||
|
# Ensure default group for all unmatched group entries is not set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
state: absent
|
||||||
|
|
||||||
|
# Ensure default hostgroup fallback_hostgroup for all unmatched group entries
|
||||||
|
# is set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: fallback_hostgroup
|
||||||
|
|
||||||
|
# Ensure default hostgroup for all unmatched group entries is not set
|
||||||
|
- ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
automember_type: hostgroup
|
||||||
|
default_group: ""
|
||||||
|
state: absent
|
||||||
"""
|
"""
|
||||||
|
|
||||||
RETURN = """
|
RETURN = """
|
||||||
@@ -168,7 +198,7 @@ RETURN = """
|
|||||||
|
|
||||||
|
|
||||||
from ansible.module_utils.ansible_freeipa_module import (
|
from ansible.module_utils.ansible_freeipa_module import (
|
||||||
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, ipalib_errors
|
IPAAnsibleModule, compare_args_ipa, gen_add_del_lists, ipalib_errors, DN
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
@@ -185,6 +215,20 @@ def find_automember(module, name, automember_type):
|
|||||||
return _result["result"]
|
return _result["result"]
|
||||||
|
|
||||||
|
|
||||||
|
def find_automember_default_group(module, automember_type):
|
||||||
|
_args = {
|
||||||
|
"all": True,
|
||||||
|
"type": automember_type
|
||||||
|
}
|
||||||
|
|
||||||
|
try:
|
||||||
|
_result = module.ipa_command_no_name("automember_default_group_show",
|
||||||
|
_args)
|
||||||
|
except ipalib_errors.NotFound:
|
||||||
|
return None
|
||||||
|
return _result["result"]
|
||||||
|
|
||||||
|
|
||||||
def gen_condition_args(automember_type,
|
def gen_condition_args(automember_type,
|
||||||
key,
|
key,
|
||||||
inclusiveregex=None,
|
inclusiveregex=None,
|
||||||
@@ -262,6 +306,7 @@ def main():
|
|||||||
automember_type=dict(type='str', required=False,
|
automember_type=dict(type='str', required=False,
|
||||||
choices=['group', 'hostgroup']),
|
choices=['group', 'hostgroup']),
|
||||||
no_wait=dict(type="bool", default=None),
|
no_wait=dict(type="bool", default=None),
|
||||||
|
default_group=dict(type="str", default=None),
|
||||||
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",
|
||||||
@@ -291,6 +336,9 @@ def main():
|
|||||||
# no_wait for rebuilt
|
# no_wait for rebuilt
|
||||||
no_wait = ansible_module.params_get("no_wait")
|
no_wait = ansible_module.params_get("no_wait")
|
||||||
|
|
||||||
|
# default_group
|
||||||
|
default_group = ansible_module.params_get("default_group")
|
||||||
|
|
||||||
# action
|
# action
|
||||||
action = ansible_module.params_get("action")
|
action = ansible_module.params_get("action")
|
||||||
# state
|
# state
|
||||||
@@ -306,7 +354,8 @@ def main():
|
|||||||
invalid = []
|
invalid = []
|
||||||
|
|
||||||
if state in ["rebuilt"]:
|
if state in ["rebuilt"]:
|
||||||
invalid = ["name", "description", "exclusive", "inclusive"]
|
invalid = ["name", "description", "exclusive", "inclusive",
|
||||||
|
"default_group"]
|
||||||
|
|
||||||
if action == "member":
|
if action == "member":
|
||||||
ansible_module.fail_json(
|
ansible_module.fail_json(
|
||||||
@@ -323,7 +372,21 @@ def main():
|
|||||||
(state, automember_type))
|
(state, automember_type))
|
||||||
|
|
||||||
else:
|
else:
|
||||||
invalid = ["users", "hosts", "no_wait"]
|
if default_group is not None:
|
||||||
|
for param in ["name", "exclusive", "inclusive", "users", "hosts"
|
||||||
|
"no_wait"]:
|
||||||
|
if ansible_module.params.get(param) is not None:
|
||||||
|
msg = "Cannot use {0} together with default_group"
|
||||||
|
ansible_module.fail_json(msg=msg.format(param))
|
||||||
|
if action == "member":
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="Cannot use default_group with action:member")
|
||||||
|
if state == "absent":
|
||||||
|
ansible_module.fail_json(
|
||||||
|
msg="Cannot use default_group with state:absent")
|
||||||
|
|
||||||
|
else:
|
||||||
|
invalid = ["users", "hosts", "no_wait"]
|
||||||
|
|
||||||
if not automember_type:
|
if not automember_type:
|
||||||
ansible_module.fail_json(
|
ansible_module.fail_json(
|
||||||
@@ -470,6 +533,29 @@ def main():
|
|||||||
rebuild_hosts, no_wait)
|
rebuild_hosts, no_wait)
|
||||||
commands.append([None, 'automember_rebuild', args])
|
commands.append([None, 'automember_rebuild', args])
|
||||||
|
|
||||||
|
elif default_group is not None and state == "present":
|
||||||
|
res_find = find_automember_default_group(ansible_module,
|
||||||
|
automember_type)
|
||||||
|
|
||||||
|
if default_group == "":
|
||||||
|
if isinstance(res_find["automemberdefaultgroup"], list):
|
||||||
|
commands.append([None,
|
||||||
|
'automember_default_group_remove',
|
||||||
|
{'type': automember_type}])
|
||||||
|
ansible_module.warn("commands: %s" % repr(commands))
|
||||||
|
|
||||||
|
else:
|
||||||
|
dn_default_group = [DN(('cn', default_group),
|
||||||
|
('cn', '%ss' % automember_type),
|
||||||
|
('cn', 'accounts'),
|
||||||
|
ansible_module.ipa_get_basedn())]
|
||||||
|
if repr(res_find["automemberdefaultgroup"]) != \
|
||||||
|
repr(dn_default_group):
|
||||||
|
commands.append(
|
||||||
|
[None, 'automember_default_group_set',
|
||||||
|
{'type': automember_type,
|
||||||
|
'automemberdefaultgroup': default_group}])
|
||||||
|
|
||||||
else:
|
else:
|
||||||
ansible_module.fail_json(msg="Invalid operation")
|
ansible_module.fail_json(msg="Invalid operation")
|
||||||
|
|
||||||
|
|||||||
166
tests/automember/test_automember_default_group.yml
Normal file
166
tests/automember/test_automember_default_group.yml
Normal file
@@ -0,0 +1,166 @@
|
|||||||
|
---
|
||||||
|
- name: Test automember default groups
|
||||||
|
hosts: "{{ ipa_test_host | default('ipaserver') }}"
|
||||||
|
become: true
|
||||||
|
|
||||||
|
tasks:
|
||||||
|
|
||||||
|
# SET FACTS
|
||||||
|
|
||||||
|
# CLEANUP TEST ITEMS
|
||||||
|
|
||||||
|
- name: Ensure group testgroup is absent
|
||||||
|
ipagroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
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 default group is unset
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
|
||||||
|
- name: Ensure automember default hostgroup is unset
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: hostgroup
|
||||||
|
|
||||||
|
# CREATE TEST ITEMS
|
||||||
|
|
||||||
|
- 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 default group is set to testgroup
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: testgroup
|
||||||
|
automember_type: group
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember default group is set to testgroup, again
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: testgroup
|
||||||
|
automember_type: group
|
||||||
|
register: result
|
||||||
|
failed_when: result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember default group is unset
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember default group is unset, again
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
register: result
|
||||||
|
failed_when: result.changed or result.failed
|
||||||
|
|
||||||
|
# HOSTGROUP TEST
|
||||||
|
|
||||||
|
- name: Ensure automember default hostgroup is set to testhostgroup
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: testhostgroup
|
||||||
|
automember_type: hostgroup
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember default hostgroup is set to testhostgroup, again
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: testhostgroup
|
||||||
|
automember_type: hostgroup
|
||||||
|
register: result
|
||||||
|
failed_when: result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember default hostgroup is unset
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: hostgroup
|
||||||
|
register: result
|
||||||
|
failed_when: not result.changed or result.failed
|
||||||
|
|
||||||
|
- name: Ensure automember default hostgroup is unset, again
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: hostgroup
|
||||||
|
register: result
|
||||||
|
failed_when: result.changed or result.failed
|
||||||
|
|
||||||
|
# CLEANUP TEST ITEMS
|
||||||
|
|
||||||
|
- name: Ensure group testgroup is absent
|
||||||
|
ipagroup:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
name: testgroup
|
||||||
|
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 default group is unset
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: group
|
||||||
|
|
||||||
|
- name: Ensure automember default hostgroup is unset
|
||||||
|
ipaautomember:
|
||||||
|
ipaadmin_password: SomeADMINpassword
|
||||||
|
ipaapi_context: "{{ ipa_context | default(omit) }}"
|
||||||
|
default_group: ""
|
||||||
|
automember_type: hostgroup
|
||||||
Reference in New Issue
Block a user