Fixed automountkey code review issues.

Fixed several issues found during code review and change
AutomountkeyModule to use IPAAnsibleModule instead of deprecated
FreeIPABaseModule.
This commit is contained in:
Rafael Guterres Jeffman
2022-01-05 18:22:41 -03:00
parent 3ca9982c73
commit dd700d956b
7 changed files with 362 additions and 283 deletions

View File

@@ -4,7 +4,7 @@ Automountkey module
Description Description
----------- -----------
The automountkey module allows the addition and removal of keys within an automount map. The automountkey module allows management of keys within an automount map.
It is desgined to follow the IPA api as closely as possible while ensuring ease of use. It is desgined to follow the IPA api as closely as possible while ensuring ease of use.
@@ -38,16 +38,15 @@ ipaserver.test.local
``` ```
Example playbook to ensure presence of an automount map: Example playbook to ensure presence of an automount key:
```yaml ```yaml
--- ---
- name: Playbook to add an automount map - name: Playbook to manage automount key
hosts: ipaserver hosts: ipaserver
become: true
tasks: tasks:
- name: create key TestKey - name: ensure automount key TestKey is present
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
location: TestLocation location: TestLocation
@@ -55,8 +54,35 @@ Example playbook to ensure presence of an automount map:
key: TestKey key: TestKey
info: 192.168.122.1:/exports info: 192.168.122.1:/exports
state: present state: present
```
- name: ensure key TestKey is absent Example playbook to rename an automount map:
```yaml
---
- name: Playbook to add an automount map
hosts: ipaserver
tasks:
- name: ensure aumount key TestKey is renamed to NewKeyName
ipaautomountkey:
ipaadmin_password: password01
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
newname: NewKeyName
state: renamed
```
Example playbook to ensure an automount key is absent:
```yaml
---
- name: Playbook to manage an automount key
hosts: ipaserver
tasks:
- name: ensure automount key TestKey is absent
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
location: TestLocation location: TestLocation
@@ -65,28 +91,10 @@ Example playbook to ensure presence of an automount map:
state: absent state: absent
``` ```
Example playbook to rename an automount map:
```yaml
---
- name: Playbook to add an automount map
- name: ensure key TestKey has been renamed to NewKeyName
ipaautomountkey:
ipaadmin_password: password01
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
newname: NewKeyName
state: rename
```
Variables Variables
========= =========
ipaautomountkey
-------
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
@@ -94,9 +102,9 @@ Variable | Description | Required
`location` \| `automountlocationcn` \| `automountlocation` | Location name. | yes `location` \| `automountlocationcn` \| `automountlocation` | Location name. | yes
`mapname` \| `map` \| `automountmapname` \| `automountmap` | Map the key belongs to | yes `mapname` \| `map` \| `automountmapname` \| `automountmap` | Map the key belongs to | yes
`key` \| `name` \| `automountkey` | Automount key to manage | yes `key` \| `name` \| `automountkey` | Automount key to manage | yes
`newkey` \| newname` \| `newautomountkey` | the name to change the key to if state is `rename` | yes when state is `rename` `rename` \| `new_name` \| `newautomountkey` | the name to change the key to if state is `renamed` | yes when state is `renamed`
`info` \| `information` \| `automountinformation` | Mount information for the key | yes when state is `present` `info` \| `information` \| `automountinformation` | Mount information for the key | yes when state is `present`
`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`, `absent` or `renamed`, default: `present`. | no
Authors Authors
======= =======

View File

@@ -0,0 +1,13 @@
---
- name: Playbook to manage an automout key
hosts: ipaserver
tasks:
- name: Ensure autmount key is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
info: 192.168.122.1:/exports
state: present

View File

@@ -0,0 +1,13 @@
---
- name: Playbook to manage an automount key
hosts: ipaserver
tasks:
- name: Ensure aumount key TestKey is renamed to NewKeyName
ipaautomountkey:
ipaadmin_password: password01
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
newname: NewKeyName
state: renamed

View File

@@ -0,0 +1,12 @@
---
- name: Playbook to manage an automount key
hosts: ipaserver
tasks:
- name: Ensure autmount key is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
mapname: TestMap
key: TestKey
state: absent

View File

@@ -20,6 +20,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",
@@ -54,18 +58,18 @@ options:
required: True required: True
choices: ["name", "automountkey"] choices: ["name", "automountkey"]
newkey: newkey:
description: key to change to if state=rename description: key to change to if state is 'renamed'
required: True required: True
choices: ["newname", "newautomountkey"] choices: ["newname", "newautomountkey"]
info: info:
description: Mount information for the key description: Mount information for the key
required: True required: True
choices: ["information", "newinfo", "automountinformation"] choices: ["information", "automountinformation"]
state: state:
description: State to ensure description: State to ensure
required: False required: False
default: present default: present
choices: ["present", "absent", "rename"] choices: ["present", "absent", "renamed"]
''' '''
EXAMPLES = ''' EXAMPLES = '''
@@ -91,126 +95,140 @@ RETURN = '''
''' '''
from ansible.module_utils.ansible_freeipa_module import ( from ansible.module_utils.ansible_freeipa_module import (
FreeIPABaseModule, ipalib_errors IPAAnsibleModule, ipalib_errors
) )
class AutomountKey(FreeIPABaseModule): class AutomountKey(IPAAnsibleModule):
ipa_param_mapping = { def __init__(self, *args, **kwargs):
'automountkey': "key", # pylint: disable=super-with-arguments
'automountmapautomountmapname': "mapname", super(AutomountKey, self).__init__(*args, **kwargs)
} self.commands = []
def get_key(self, location, mapname, keyname): def get_key(self, location, mapname, key):
resp = dict()
try: try:
resp = self.api_command("automountkey_show", args = {
location, "automountmapautomountmapname": mapname,
{"automountmapautomountmapname": mapname, "automountkey": key,
"automountkey": keyname}) "all": True,
}
resp = self.ipa_command("automountkey_show", location, args)
except ipalib_errors.NotFound: except ipalib_errors.NotFound:
pass return None
else:
return resp.get("result", None) return resp.get("result")
def check_ipa_params(self): def check_ipa_params(self):
if not self.ipa_params.info and self.ipa_params.state == "present": invalid = []
state = self.params_get("state")
if state == "present":
invalid = ["rename"]
if not self.params_get("info"):
self.fail_json(msg="Value required for argument 'info'") self.fail_json(msg="Value required for argument 'info'")
if self.ipa_params.state == "rename" and \ if state == "rename":
self.ipa_params.newname is None: invalid = ["info"]
self.fail_json(msg="newname is required if state = 'rename'") if not self.params_get("rename"):
self.fail_json(msg="Value required for argument 'renamed'")
if state == "absent":
invalid = ["info", "rename"]
self.params_fail_used_invalid(invalid, state)
@staticmethod
def get_args(mapname, key, info, rename):
_args = {}
if mapname:
_args["automountmapautomountmapname"] = mapname
if key:
_args["automountkey"] = key
if info:
_args["automountinformation"] = info
if rename:
_args["rename"] = rename
return _args
def define_ipa_commands(self): def define_ipa_commands(self):
args = self.get_ipa_command_args() state = self.params_get("state")
key = self.get_key(self.ipa_params.location, location = self.params_get("location")
self.ipa_params.mapname, mapname = self.params_get("mapname")
self.ipa_params.key) key = self.params_get("key")
info = self.params_get("info")
rename = self.params_get("rename")
if self.ipa_params.state == "present": args = self.get_args(mapname, key, info, rename)
if key is None:
res_find = self.get_key(location, mapname, key)
if state == "present":
if res_find is None:
# does not exist and is wanted # does not exist and is wanted
args["automountinformation"] = self.ipa_params.info self.commands.append([location, "automountkey_add", args])
self.add_ipa_command(
"automountkey_add",
name=self.ipa_params.location,
args=args
)
elif key is not None:
# exists and is wanted, check for changes
if self.ipa_params.info != \
key.get('automountinformation', [None])[0]:
args["newautomountinformation"] = self.ipa_params.info
self.add_ipa_command(
"automountkey_mod",
name=self.ipa_params.location,
args=args
)
elif self.ipa_params.state == "rename":
if key is not None:
newkey = self.get_key(self.ipa_params.location,
self.ipa_params.mapname,
self.ipa_params.newname)
args["rename"] = self.ipa_params.newname
if newkey is None:
self.add_ipa_command(
"automountkey_mod",
name=self.ipa_params.location,
args=args
)
else: else:
# if key exists and self.ipa_params.state == "absent": # exists and is wanted, check for changes
if key is not None: if info not in res_find.get("automountinformation"):
self.add_ipa_command( self.commands.append([location, "automountkey_mod", args])
"automountkey_del",
name=self.ipa_params.location, if state == "renamed":
args=args if res_find is None:
self.fail_json(
msg=(
"Cannot rename inexistent key: '%s', '%s', '%s'"
% (location, mapname, key)
) )
)
self.commands.append([location, "automountkey_mod", args])
if state == "absent":
# if key exists and self.ipa_params.state == "absent":
if res_find is not None:
self.commands.append([location, "automountkey_del", args])
def main(): def main():
ipa_module = AutomountKey( ipa_module = AutomountKey(
argument_spec=dict( argument_spec=dict(
ipaadmin_principal=dict(type="str", state=dict(
default="admin" type='str',
), choices=['present', 'absent', 'renamed'],
ipaadmin_password=dict(type="str", required=None,
required=False,
no_log=True
),
state=dict(type='str',
default='present', default='present',
choices=['present', 'absent', 'rename']
), ),
location=dict(type="str", location=dict(
type="str",
aliases=["automountlocationcn", "automountlocation"], aliases=["automountlocationcn", "automountlocation"],
default=None,
required=True
),
newname=dict(type="str",
aliases=["newkey", "new_name",
"new_key", "newautomountkey"],
default=None,
required=False
),
mapname=dict(type="str",
aliases=["map", "automountmapname", "automountmap"],
default=None,
required=True
),
key=dict(type="str",
required=True, required=True,
aliases=["name", "automountkey"]
), ),
info=dict(type="str", rename=dict(
aliases=["information", "newinfo", type="str",
"automountinformation"] aliases=["new_name", "newautomountkey"],
required=False,
),
mapname=dict(
type="str",
aliases=["map", "automountmapname", "automountmap"],
required=True,
),
key=dict(
type="str",
aliases=["name", "automountkey"],
required=True,
),
info=dict(
type="str",
aliases=["information", "automountinformation"],
required=False,
), ),
), ),
) )
ipa_module.ipa_run() 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,52 +1,46 @@
--- ---
- name: Test automountmap - name: Test automountmap
hosts: ipaserver hosts: "{{ ipa_test_host | default('ipaserver') }}"
become: true become: no
gather_facts: false gather_facts: no
tasks: tasks:
- name: ensure location TestLocation is absent - name: ensure test location TestLocation is present
ipaautomountlocation: ipaautomountlocation:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestLocation name: TestLocation
state: absent
# - name: ensure map TestMap is absent - name: ensure test map TestMap is present
# ipaautomountmap:
# ipaadmin_password: SomeADMINpassword
# name: TestMap
# location: TestLocation
# state: absent
#
# - name: ensure key TestKey is absent
# ipaautomountkey:
# ipaadmin_password: SomeADMINpassword
# automountlocationcn: TestLocation
# automountmapname: TestMap
# automountkey: TestKey
# state: absent
- name: create location TestLocation
ipaautomountlocation:
ipaadmin_password: SomeADMINpassword
name: TestLocation
state: present
- name: create map TestMap
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
desc: "this is a test map that should be deleted by the test"
### test the key creation, and modification - name: ensure key NewKeyName is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
state: absent
- name: ensure key TestKey is absent
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
state: absent
- block:
### test the key creation, and modification
- name: ensure key TestKey is present - name: ensure key TestKey is present
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: TestKey key: TestKey
automountinformation: 192.168.122.1:/exports info: 192.168.122.1:/exports
state: present state: present
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
@@ -54,22 +48,22 @@
- name: ensure key TestKey is present again - name: ensure key TestKey is present again
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: TestKey key: TestKey
automountinformation: 192.168.122.1:/exports info: 192.168.122.1:/exports
state: present state: present
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
## modify the key ## modify the key
- name: ensure key TestKey information has been updated - name: ensure key TestKey information has been updated
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: TestKey key: TestKey
automountinformation: 192.168.122.1:/nfsshare info: 192.168.122.1:/nfsshare
state: present state: present
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
@@ -77,104 +71,84 @@
- name: ensure key TestKey information has been updated again - name: ensure key TestKey information has been updated again
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: TestKey key: TestKey
automountinformation: 192.168.122.1:/nfsshare info: 192.168.122.1:/nfsshare
state: present state: present
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
## modify the name ## modify the name
- name: ensure key TestKey has been renamed to NewKeyName - name: ensure key TestKey has been renamed to NewKeyName
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: TestKey key: TestKey
automountinformation: 192.168.122.1:/nfsshare new_name: NewKeyName
newname: NewKeyName state: renamed
state: rename
register: result register: result
failed_when: result.failed or not result.changed failed_when: result.failed or not result.changed
- name: ensure key TestKey does not exist - name: ensure key TestKey is absent
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: NewKeyName key: TestKey
automountinformation: 192.168.122.1:/nfsshare state: absent
register: result
failed_when: result.failed or result.changed
- name: ensure key NewKeyName is present
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
location: TestLocation
map: TestMap
key: NewKeyName
info: 192.168.122.1:/nfsshare
state: present state: present
register: result register: result
failed_when: result.failed or result.changed failed_when: result.failed or result.changed
- name: ensure key NewKeyName does exist - name: ensure failure when state is renamed and newname is not set
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: NewKeyName key: TestKey
automountinformation: 192.168.122.1:/nfsshare state: renamed
state: present
register: result
failed_when: result.failed or result.changed
- name: ensure key TestKey has been renamed to NewKeyName again
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
automountinformation: 192.168.122.1:/nfsshare
newname: NewKeyName
state: rename
register: result
failed_when: result.failed or result.changed
- name: ensure failure when state=present and newname is not set
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation
automountmapname: TestMap
automountkey: TestKey
automountinformation: 192.168.122.1:/nfsshare
state: rename
register: result register: result
failed_when: not result.failed failed_when: not result.failed
### cleanup after the tests
### cleanup after the tests always:
- name: ensure key NewKeyName is absent - name: ensure key NewKeyName is absent
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: NewKeyName key: NewKeyName
state: absent state: absent
register: result
failed_when: result.failed or not result.changed
- name: ensure key TestKey is absent again - name: ensure key TestKey is absent
ipaautomountkey: ipaautomountkey:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
automountlocationcn: TestLocation location: TestLocation
automountmapname: TestMap map: TestMap
automountkey: NewKeyName key: NewKeyName
state: absent state: absent
register: result
failed_when: result.failed or result.changed
- name: ensure map TestMap is removed - name: ensure map TestMap is absent
ipaautomountmap: ipaautomountmap:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestMap name: TestMap
location: TestLocation location: TestLocation
state: absent state: absent
- name: ensure location TestLocation is removed - name: ensure location TestLocation is absent
ipaautomountlocation: ipaautomountlocation:
ipaadmin_password: SomeADMINpassword ipaadmin_password: SomeADMINpassword
name: TestLocation name: TestLocation
state: absent state: absent

View File

@@ -0,0 +1,41 @@
---
- name: Test automountkey
hosts: ipaclients, ipaserver
become: no
gather_facts: no
tasks:
- name: Include FreeIPA facts.
include_tasks: ../env_freeipa_facts.yml
# Test will only be executed if host is not a server.
- name: Execute with server context in the client.
ipaautomountkey:
ipaadmin_password: SomeADMINpassword
ipaapi_context: server
location: NoLocation
map: NoMap
key: ThisShouldNotWork
register: result
failed_when: not (result.failed and result.msg is regex("No module named '*ipaserver'*"))
when: ipa_host_is_client
# Import basic module tests, and execute with ipa_context set to 'client'.
# If ipaclients is set, it will be executed using the client, if not,
# ipaserver will be used.
#
# With this setup, tests can be executed against an IPA client, against
# an IPA server using "client" context, and ensure that tests are executed
# in upstream CI.
- name: Test automountlocation using client context, in client host.
import_playbook: test_automountkey.yml
when: groups['ipaclients']
vars:
ipa_test_host: ipaclients
- name: Test automountlocation using client context, in server host.
import_playbook: test_automountkey.yml
when: groups['ipaclients'] is not defined or not groups['ipaclients']
vars:
ipa_context: client