Adapt automount to IPAAnsibleModule and add code review modifications.

This commit is contained in:
Rafael Guterres Jeffman
2022-01-05 15:23:38 -03:00
parent 0d47429000
commit e1e8ff5916
5 changed files with 203 additions and 179 deletions

View File

@@ -37,14 +37,13 @@ Example inventory file
ipaserver.test.local ipaserver.test.local
``` ```
Example playbook to ensure presence of an automount map: Example playbook to ensure presence of an automount map:
```yaml ```yaml
--- ---
- name: Playbook to add an automount map - name: Playbook to add an automount map
hosts: ipaserver hosts: ipaserver
become: true become: no
tasks: tasks:
- name: ensure map named auto.DMZ in location DMZ is created - name: ensure map named auto.DMZ in location DMZ is created
@@ -55,20 +54,20 @@ Example playbook to ensure presence of an automount map:
desc: "this is a map for servers in the DMZ" desc: "this is a map for servers in the DMZ"
``` ```
Example playbook to ensure auto.DMZi is absent:
Example playbook to ensure auto.DMZi does not exist
```yaml ```yaml
--- ---
- name: Playbook to remove an automount map - name: Playbook to remove an automount map
hosts: ipaserver hosts: ipaserver
become: true become: no
tasks: tasks:
- name: ensure map auto.DMZ has been removed - name: ensure map auto.DMZ has been removed
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: auto.DMZ name: auto.DMZ
location: DMX location: DMZ
state: absent state: absent
``` ```
@@ -76,9 +75,6 @@ Example playbook to ensure auto.DMZi does not exist
Variables Variables
========= =========
ipaautomountmap
-------
Variable | Description | Required Variable | Description | Required
-------- | ----------- | -------- -------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no `ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
@@ -89,6 +85,11 @@ Variable | Description | Required
`state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no `state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no
Notes
=====
Creation of indirect mount points are not supported.
Authors Authors
======= =======

View File

@@ -1,7 +1,8 @@
--- ---
- name: Automount map absent example - name: Automount map absent example
hosts: ipaserver hosts: ipaserver
become: true become: no
tasks: tasks:
- name: ensure map TestMap is absent - name: ensure map TestMap is absent
ipaautomountmap: ipaautomountmap:
@@ -9,4 +10,3 @@
name: TestMap name: TestMap
location: TestLocation location: TestLocation
state: absent state: absent

View File

@@ -1,7 +1,8 @@
--- ---
- name: Automount map present example - name: Automount map present example
hosts: ipaserver hosts: ipaserver
become: true become: no
tasks: tasks:
- name: ensure map TestMap is present - name: ensure map TestMap is present
ipaautomountmap: ipaautomountmap:
@@ -9,4 +10,3 @@
name: TestMap name: TestMap
location: TestLocation location: TestLocation
desc: "this is a test map" desc: "this is a test map"

View File

@@ -19,6 +19,10 @@
# You should have received a copy of the GNU General Public License # You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>. # along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = { ANSIBLE_METADATA = {
"metadata_version": "1.0", "metadata_version": "1.0",
"supported_by": "community", "supported_by": "community",
@@ -29,27 +33,27 @@ ANSIBLE_METADATA = {
DOCUMENTATION = ''' DOCUMENTATION = '''
--- ---
module: ipaautomountmap module: ipaautomountmap
author: chris procter author: Chris Procter
short_description: Manage FreeIPA autommount map short_description: Manage FreeIPA autommount map
description: description:
- Add, delete, and modify an IPA automount map - Add, delete, and modify an IPA automount map
options: options:
ipaadmin_principal: ipaadmin_principal:
description: The admin principal description: The admin principal.
default: admin default: admin
ipaadmin_password: ipaadmin_password:
description: The admin password description: The admin password.
required: false required: false
automountlocation: automountlocation:
description: automount location map is anchored to description: automount location map is anchored to
choices: ["location", "automountlocationcn"] choices: ["location", "automountlocationcn"]
required: True required: True
name: name:
description: automount map to be managed description: automount map to be managed.
choices: ["mapname", "map", "automountmapname"] choices: ["mapname", "map", "automountmapname"]
required: True required: True
desc: desc:
description: description of automount map description: description of automount map.
choices: ["description"] choices: ["description"]
required: false required: false
state: state:
@@ -78,84 +82,85 @@ EXAMPLES = '''
RETURN = ''' RETURN = '''
''' '''
from ansible.module_utils.ansible_freeipa_module import FreeIPABaseModule from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, compare_args_ipa
)
class AutomountMap(FreeIPABaseModule): class AutomountMap(IPAAnsibleModule):
ipa_param_mapping = { def __init__(self, *args, **kwargs):
"automountmapname": "name", # pylint: disable=super-with-arguments
} super(AutomountMap, self).__init__(*args, **kwargs)
self.commands = []
def get_map(self, location, name): def get_automountmap(self, location, name):
response = dict()
try: try:
response = self.api_command("automountmap_show", response = self.ipa_command(
location, "automountmap_show",
{"automountmapname": name}) location,
except Exception: {"automountmapname": name, "all": True}
pass )
except Exception: # pylint: disable=broad-except
return response.get("result", None) return None
else:
return response["result"]
def check_ipa_params(self): def check_ipa_params(self):
invalid = []
if self.ipa_params.state == "present": name = self.params_get("name")
if len(self.ipa_params.name) != 1: state = self.params_get("state")
if state == "present":
if len(name) != 1:
self.fail_json(msg="Exactly one name must be provided \ self.fail_json(msg="Exactly one name must be provided \
for state=present.") for state=present.")
else: if state == "absent":
if len(self.ipa_params.name) == 0 : if len(name) == 0 :
self.fail_json(msg="At least one name must be provided \ self.fail_json(msg="Argument 'map_type' can not be used with "
when state=absent.") "state 'absent'")
invalid = ["desc"]
self.params_fail_used_invalid(invalid, state)
def get_args(self, mapname, desc): # pylint: disable=no-self-use
_args = {}
if mapname:
_args["automountmapname"] = mapname
if desc:
_args["description"] = desc
return _args
def define_ipa_commands(self): def define_ipa_commands(self):
args = self.get_ipa_command_args() name = self.params_get("name")
state = self.params_get("state")
location = self.params_get("location")
desc = self.params_get("desc")
if self.ipa_params.state == "present": for mapname in name:
automountmap = self.get_map(self.ipa_params.location, automountmap = self.get_automountmap(location, mapname)
self.ipa_params.name[0])
args['automountmapname'] = self.ipa_params.name[0]
if automountmap is None:
# does not exist and is wanted
self.add_ipa_command(
"automountmap_add",
name=self.ipa_params.location,
args=args
)
else:
# exists and is wanted, check for changes
if self.ipa_params.desc != \
automountmap.get('description', [None])[0]:
args['description'] = self.ipa_params.desc
self.add_ipa_command(
"automountmap_mod",
name=self.ipa_params.location,
args=args
)
else:
# exists and is not wanted (i.e. self.ipa_params.state == "absent")
to_del = [x for x in self.ipa_params.name
if self.get_map(self.ipa_params.location, x) is not None]
if len(to_del) > 0: if state == "present":
self.add_ipa_command( args = self.get_args(mapname, desc)
"automountmap_del", if automountmap is None:
name=self.ipa_params.location, self.commands.append([location, "automountmap_add", args])
args={"automountmapname": to_del} else:
) if not compare_args_ipa(self, args, automountmap):
self.commands.append(
[location, "automountmap_mod", args]
)
if state == "absent":
if automountmap is not None:
self.commands.append([
location,
"automountmap_del",
{"automountmapname": [mapname]}
])
def main(): def main():
ipa_module = AutomountMap( ipa_module = AutomountMap(
argument_spec=dict( argument_spec=dict(
ipaadmin_principal=dict(type="str",
default="admin"
),
ipaadmin_password=dict(type="str",
required=False,
no_log=True
),
state=dict(type='str', state=dict(type='str',
default='present', default='present',
choices=['present', 'absent'] choices=['present', 'absent']
@@ -177,7 +182,13 @@ def main():
), ),
), ),
) )
ipa_module.ipa_run() changed = False
ipaapi_context = ipa_module.params_get("ipaapi_context")
with ipa_module.ipa_connect(context=ipaapi_context):
ipa_module.check_ipa_params()
ipa_module.define_ipa_commands()
changed = ipa_module.execute_ipa_commands(ipa_module.commands)
ipa_module.exit_json(changed=changed)
if __name__ == "__main__": if __name__ == "__main__":

View File

@@ -1,10 +1,20 @@
--- ---
- name: Test automountmap - name: Test automountmap
hosts: ipaserver hosts: ipaserver
become: true become: no
gather_facts: false gather_facts: no
tasks: tasks:
# setup environment
- name: ensure test maps are absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
- name: ensure location TestLocation is absent - name: ensure location TestLocation is absent
ipaautomountlocation: ipaautomountlocation:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
@@ -24,112 +34,114 @@
name: TestLocation name: TestLocation
state: present state: present
- name: ensure map TestMap is present # TESTS
ipaautomountmap: - block:
ipaadmin_password: SomeADMINpassword - name: ensure map TestMap is present
name: TestMap ipaautomountmap:
location: TestLocation ipaadmin_password: SomeADMINpassword
desc: "this is a test map that should be deleted by the test" name: TestMap
register: result location: TestLocation
failed_when: result.failed or not result.changed desc: "this is a test map that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: ensure map TestMap is present again - name: ensure map TestMap is present again
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
- name: ensure map TestMap has a different description - name: ensure map TestMap has a different description
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
desc: "this is a changed description that should be deleted by the test" desc: "this is a changed description that should be deleted by the test"
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
- name: ensure map TestMap has a different description - name: ensure map TestMap has a different description, again
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
desc: "this is a changed description that should be deleted by the test" desc: "this is a changed description that should be deleted by the test"
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
- name: ensure map TestMap is removed - name: ensure map TestMap is removed
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
state: absent state: absent
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
- name: ensure map TestMap has been removed - name: ensure map TestMap has been removed
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
state: absent state: absent
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
- name: ensure map TestMap01 is present - name: ensure map TestMap01 is present
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap01 name: TestMap01
location: TestLocation location: TestLocation
desc: "this is a changed description that should be deleted by the test" desc: "this is a changed description that should be deleted by the test"
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
- name: ensure map TestMap02 is present - name: ensure map TestMap02 is present
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap02 name: TestMap02
location: TestLocation location: TestLocation
desc: "this is a changed description that should be deleted by the test" desc: "this is a changed description that should be deleted by the test"
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
- name: ensure TestMap01 and TestMap02 are both absent - name: ensure TestMap01 and TestMap02 are both absent
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: name:
- TestMap01 - TestMap01
- TestMap02 - TestMap02
location: TestLocation location: TestLocation
state: absent state: absent
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
- name: ensure TestMap01 and TestMap02 are both absent again - name: ensure TestMap01 and TestMap02 are both absent again
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: name:
- TestMap01 - TestMap01
- TestMap02 - TestMap02
location: TestLocation location: TestLocation
state: absent state: absent
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
- name: ensure location TestLocation is absent # CLEAN UP
ipaautomountlocation: always:
ipaadmin_password: SomeADMINpassword - name: ensure test maps are absent
name: TestLocation ipaautomountmap:
state: absent ipaadmin_password: SomeADMINpassword
register: result name:
failed_when: result.failed or not result.changed - TestMap01
- TestMap02
- name: ensure location TestLocation is absent again location: TestLocation
ipaautomountlocation: state: absent
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
register: result
failed_when: result.failed or result.changed
- name: ensure location TestLocation is absent
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent