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(
"automountmap_show",
location, location,
{"automountmapname": name}) {"automountmapname": name, "all": True}
except Exception: )
pass except Exception: # pylint: disable=broad-except
return None
return response.get("result", 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 state == "present":
args = self.get_args(mapname, desc)
if automountmap is None: if automountmap is None:
# does not exist and is wanted self.commands.append([location, "automountmap_add", args])
self.add_ipa_command(
"automountmap_add",
name=self.ipa_params.location,
args=args
)
else: else:
# exists and is wanted, check for changes if not compare_args_ipa(self, args, automountmap):
if self.ipa_params.desc != \ self.commands.append(
automountmap.get('description', [None])[0]: [location, "automountmap_mod", args]
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 == "absent":
self.add_ipa_command( if automountmap is not None:
self.commands.append([
location,
"automountmap_del", "automountmap_del",
name=self.ipa_params.location, {"automountmapname": [mapname]}
args={"automountmapname": to_del} ])
)
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,6 +34,8 @@
name: TestLocation name: TestLocation
state: present state: present
# TESTS
- block:
- name: ensure map TestMap is present - name: ensure map TestMap is present
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
@@ -50,7 +62,7 @@
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
@@ -117,19 +129,19 @@
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
# CLEAN UP
always:
- 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
name: TestLocation name: TestLocation
state: absent state: absent
register: result
failed_when: result.failed or not result.changed
- name: ensure location TestLocation is absent again
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
register: result
failed_when: result.failed or result.changed