Skip to content
Snippets Groups Projects
Unverified Commit 6a1f6193 authored by Thomas Woerner's avatar Thomas Woerner Committed by GitHub
Browse files

Merge pull request #497 from chr15p/ipaautomountmap

add module to create and manage automount maps
parents 870dfec9 e1e8ff59
No related branches found
No related tags found
No related merge requests found
Automountmap module
=====================
Description
-----------
The automountmap module allows the addition and removal of maps within automount locations.
It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
Features
--------
* Automount map management
Supported FreeIPA Versions
--------------------------
FreeIPA versions 4.4.0 and up are supported by the ipaautomountmap module.
Requirements
------------
**Controller**
* Ansible version: 2.8+
**Node**
* Supported FreeIPA version (see above)
Usage
=====
Example inventory file
```ini
[ipaserver]
ipaserver.test.local
```
Example playbook to ensure presence of an automount map:
```yaml
---
- name: Playbook to add an automount map
hosts: ipaserver
become: no
tasks:
- name: ensure map named auto.DMZ in location DMZ is created
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
desc: "this is a map for servers in the DMZ"
```
Example playbook to ensure auto.DMZi is absent:
```yaml
---
- name: Playbook to remove an automount map
hosts: ipaserver
become: no
tasks:
- name: ensure map auto.DMZ has been removed
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
state: absent
```
Variables
=========
Variable | Description | Required
-------- | ----------- | --------
`ipaadmin_principal` | The admin principal is a string and defaults to `admin` | no
`ipaadmin_password` | The admin password is a string and is required if there is no admin ticket available on the node | no
`name` \| `mapname` \| `map` \| `automountmapname` | Name of the map to manage | yes
`location` \| `automountlocation` \| `automountlocationcn` | Location name. | yes
`desc` \| `description` | Description of the map | yes
`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
=======
Chris Procter
---
- name: Automount map absent example
hosts: ipaserver
become: no
tasks:
- name: ensure map TestMap is absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
---
- name: Automount map present example
hosts: ipaserver
become: no
tasks:
- name: ensure map TestMap is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a test map"
#!/usr/bin/python
# -*- coding: utf-8 -*-
# Authors:
# Chris Procter <cprocter@redhat.com>
#
# Copyright (C) 2021 Red Hat
# see file 'COPYING' for use and warranty information
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <http://www.gnu.org/licenses/>.
from __future__ import (absolute_import, division, print_function)
__metaclass__ = type
ANSIBLE_METADATA = {
"metadata_version": "1.0",
"supported_by": "community",
"status": ["preview"],
}
DOCUMENTATION = '''
---
module: ipaautomountmap
author: Chris Procter
short_description: Manage FreeIPA autommount map
description:
- Add, delete, and modify an IPA automount map
options:
ipaadmin_principal:
description: The admin principal.
default: admin
ipaadmin_password:
description: The admin password.
required: false
automountlocation:
description: automount location map is anchored to
choices: ["location", "automountlocationcn"]
required: True
name:
description: automount map to be managed.
choices: ["mapname", "map", "automountmapname"]
required: True
desc:
description: description of automount map.
choices: ["description"]
required: false
state:
description: State to ensure
required: false
default: present
choices: ["present", "absent"]
'''
EXAMPLES = '''
- name: ensure map named auto.DMZ in location DMZ is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
desc: "this is a map for servers in the DMZ"
- name: remove a map named auto.DMZ in location DMZ if it exists
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: auto.DMZ
location: DMZ
state: absent
'''
RETURN = '''
'''
from ansible.module_utils.ansible_freeipa_module import (
IPAAnsibleModule, compare_args_ipa
)
class AutomountMap(IPAAnsibleModule):
def __init__(self, *args, **kwargs):
# pylint: disable=super-with-arguments
super(AutomountMap, self).__init__(*args, **kwargs)
self.commands = []
def get_automountmap(self, location, name):
try:
response = self.ipa_command(
"automountmap_show",
location,
{"automountmapname": name, "all": True}
)
except Exception: # pylint: disable=broad-except
return None
else:
return response["result"]
def check_ipa_params(self):
invalid = []
name = self.params_get("name")
state = self.params_get("state")
if state == "present":
if len(name) != 1:
self.fail_json(msg="Exactly one name must be provided \
for state=present.")
if state == "absent":
if len(name) == 0 :
self.fail_json(msg="Argument 'map_type' can not be used with "
"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):
name = self.params_get("name")
state = self.params_get("state")
location = self.params_get("location")
desc = self.params_get("desc")
for mapname in name:
automountmap = self.get_automountmap(location, mapname)
if state == "present":
args = self.get_args(mapname, desc)
if automountmap is None:
self.commands.append([location, "automountmap_add", args])
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():
ipa_module = AutomountMap(
argument_spec=dict(
state=dict(type='str',
default='present',
choices=['present', 'absent']
),
location=dict(type="str",
aliases=["automountlocation", "automountlocationcn"],
default=None,
required=True
),
name=dict(type="list",
aliases=["mapname", "map", "automountmapname"],
default=None,
required=True
),
desc=dict(type="str",
aliases=["description"],
required=False,
default=None
),
),
)
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__":
main()
---
- name: Test automountmap
hosts: ipaserver
become: no
gather_facts: no
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
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
- name: ensure map TestMap is absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
- name: ensure location TestLocation is present
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: present
# TESTS
- block:
- name: ensure map TestMap is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
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
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
register: result
failed_when: result.failed or result.changed
- name: ensure map TestMap has a different description
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: ensure map TestMap has a different description, again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or result.changed
- name: ensure map TestMap is removed
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
register: result
failed_when: result.failed or not result.changed
- name: ensure map TestMap has been removed
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap
location: TestLocation
state: absent
register: result
failed_when: result.failed or result.changed
- name: ensure map TestMap01 is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap01
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: ensure map TestMap02 is present
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name: TestMap02
location: TestLocation
desc: "this is a changed description that should be deleted by the test"
register: result
failed_when: result.failed or not result.changed
- name: ensure TestMap01 and TestMap02 are both absent
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
register: result
failed_when: result.failed or not result.changed
- name: ensure TestMap01 and TestMap02 are both absent again
ipaautomountmap:
ipaadmin_password: SomeADMINpassword
name:
- TestMap01
- TestMap02
location: TestLocation
state: absent
register: result
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
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: absent
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment