diff --git a/README-automountlocation.md b/README-automountlocation.md new file mode 100644 index 0000000000000000000000000000000000000000..f28afc2ac73e5543fe90254c5848a9ebb4869887 --- /dev/null +++ b/README-automountlocation.md @@ -0,0 +1,114 @@ +Automountlocation module +===================== + +Description +----------- + +The automountlocation module allows the addition and removal of locations for automount maps + +It is desgined to follow the IPA api as closely as possible while ensuring ease of use. + + +Features +-------- +* Automount location management + +Supported FreeIPA Versions +-------------------------- + +FreeIPA versions 4.4.0 and up are supported by the ipaautomountlocation 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 location: + +```yaml +--- +- name: Playbook to add an automount location + hosts: ipaserver + become: true + + tasks: + - name: ensure a automount location named DMZ exists + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: DMZ + state: present + +``` + +Example playbook to ensure presence of multiple automount locations: + +```yaml +--- +- name: Playbook to add an automount location + hosts: ipaserver + become: true + + tasks: + - name: ensure a automount location named DMZ exists + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - DMZ + - PROD + - development + - test + state: present +``` + + +Example playbook to ensure absence of an automount location: + +```yaml +--- +- name: Playbook to ensure an automount location is absent + hosts: ipaserver + become: true + + tasks: + - name: ensure automount locations LOCATION1 and LOCATION2 do not exist + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - LOCATION1 + - LOCATION2 + state: absent +``` + +Variables +========= + +ipaautomountlocation +------- + +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` \| `cn` \| `location` | List of one or more automountlocation names. | yes +`state` | The state to ensure. It can be one of `present`, or `absent`, default: `present`. | no + + +Authors +======= + +Chris Procter diff --git a/playbooks/automount/automount-location-absent.yml b/playbooks/automount/automount-location-absent.yml new file mode 100644 index 0000000000000000000000000000000000000000..f31a43940bf01cb79211d1acf7ddf2490d699cbc --- /dev/null +++ b/playbooks/automount/automount-location-absent.yml @@ -0,0 +1,13 @@ +--- +- name: Automount locations absnet example + hosts: ipaserver + become: true + tasks: + - name: Ensure automount locations DMZ and internal are absent + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - DMZ + - internal + state: absent + diff --git a/playbooks/automount/automount-location-present.yml b/playbooks/automount/automount-location-present.yml new file mode 100644 index 0000000000000000000000000000000000000000..72e7a4028305c2e0314b4bc1763ffcc0d2eba636 --- /dev/null +++ b/playbooks/automount/automount-location-present.yml @@ -0,0 +1,13 @@ +--- +- name: Automount location present example + hosts: ipaserver + become: true + tasks: + - name: Ensure automount locations DMZ and internal are present + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - DMZ + - internal + state: present + diff --git a/plugins/modules/ipaautomountlocation.py b/plugins/modules/ipaautomountlocation.py new file mode 100644 index 0000000000000000000000000000000000000000..c88578b259592f464d9930e39635c54932780269 --- /dev/null +++ b/plugins/modules/ipaautomountlocation.py @@ -0,0 +1,141 @@ +#!/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/>. + +ANSIBLE_METADATA = { + "metadata_version": "1.0", + "supported_by": "community", + "status": ["preview"], +} + + +DOCUMENTATION = ''' +--- +module: ipaautomountlocation +author: chris procter +short_description: Manage FreeIPA autommount locations +description: +- Add and delete an IPA automount location +options: + ipaadmin_principal: + description: The admin principal + default: admin + ipaadmin_password: + description: The admin password + required: false + name: + description: The automount location to be managed + required: true + aliases: ["cn","location"] + state: + description: State to ensure + required: false + default: present + choices: ["present", "absent"] +''' + +EXAMPLES = ''' + - name: ensure a automount location named DMZ exists + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: DMZ + state: present + + - name: ensure a automount location named DMZ is absent + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: DMZ + state: absent +''' + +RETURN = ''' +''' + +from ansible.module_utils.ansible_freeipa_module import ( + FreeIPABaseModule, ipalib_errors +) + + +class AutomountLocation(FreeIPABaseModule): + + ipa_param_mapping = {} + + def get_location(self, location): + response = dict() + try: + response = self.api_command("automountlocation_show", + location, + {}) + except ipalib_errors.NotFound: + pass + + return response.get("result", None) + + def check_ipa_params(self): + if len(self.ipa_params.name) == 0: + self.fail_json(msg="At least one location must be provided.") + + def define_ipa_commands(self): + + for location_name in self.ipa_params.name: + location = self.get_location(location_name) + + if not location and self.ipa_params.state == "present": + # does not exist and is wanted + self.add_ipa_command( + "automountlocation_add", + name=location_name, + args=None, + ) + elif location and self.ipa_params.state == "absent": + # exists and is not wanted + self.add_ipa_command( + "automountlocation_del", + name=location_name, + args=None, + ) + + +def main(): + ipa_module = AutomountLocation( + argument_spec=dict( + ipaadmin_principal=dict(type="str", + default="admin" + ), + ipaadmin_password=dict(type="str", + required=False, + no_log=True + ), + state=dict(type='str', + default='present', + choices=['present', 'absent'] + ), + name=dict(type="list", + aliases=["cn", "location"], + default=None, + required=True + ), + ), + ) + ipa_module.ipa_run() + + +if __name__ == "__main__": + main() diff --git a/tests/automount/test_automountlocation.yml b/tests/automount/test_automountlocation.yml new file mode 100644 index 0000000000000000000000000000000000000000..1eb11a65de10c2288f4c5fa83f77afed24eefead --- /dev/null +++ b/tests/automount/test_automountlocation.yml @@ -0,0 +1,104 @@ +--- +- name: Test automountlocation + hosts: ipaserver + become: true + gather_facts: false + + tasks: + - name: ensure automountlocation TestLocations are absent before testing + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - TestLocation_01 + - TestLocation_02 + state: absent + + - name: ensure empty automountlocation does nothing + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: [] + state: present + register: result + failed_when: not result.failed or "At least one location must be provided" not in result.msg + + - name: ensure empty automountlocation does nothing on absent + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: [] + state: absent + register: result + failed_when: not result.failed or "At least one location must be provided" not in result.msg + + - name: ensure automountlocation TestLocation is present + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: TestLocation_01 + state: present + register: result + failed_when: not result.changed or result.failed + + - name: ensure automountlocation TestLocation is present again + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: TestLocation_01 + state: present + register: result + failed_when: result.changed or result.failed + + - name: ensure automountlocation TestLocation is absent + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: TestLocation_01 + state: absent + register: result + failed_when: not result.changed or result.failed + + - name: ensure automountlocation TestLocation is absent again + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: TestLocation_01 + state: absent + register: result + failed_when: result.changed or result.failed + + - name: ensure a list of automountlocations are present + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - TestLocation_01 + - TestLocation_02 + state: present + register: result + failed_when: result.failed or not result.changed + + - name: ensure a list of automountlocations exist + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - TestLocation_01 + - TestLocation_02 + state: present + register: result + failed_when: result.changed or result.failed + + - name: ensure a list of automountlocations are absent + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - TestLocation_01 + - TestLocation_02 + state: absent + register: result + failed_when: result.failed or not result.changed + + - name: ensure multiple automountlocations are absent + ipaautomountlocation: + ipaadmin_password: SomeADMINpassword + name: + - TestLocation_01 + - TestLocation_02 + - TestLocation_03 + - TestLocation_04 + state: absent + register: result + failed_when: result.changed or result.failed