BIGIP: Bugfix.bigip.data.group (#53968)

* Moving comparision functions to compare.py from common.py

* fixes issue with data group elements containing IPs with Route Domains
refactors main() function and module_manager to accomodate new patterns
updates doc variables
pull/4420/head
Wojciech Wypior 2019-03-19 05:25:54 +01:00 committed by Tim Rupp
parent 2b00cb592d
commit 313e07dfd3
2 changed files with 89 additions and 51 deletions

View File

@ -24,10 +24,12 @@ options:
name: name:
description: description:
- Specifies the name of the data group. - Specifies the name of the data group.
type: str
required: True required: True
description: description:
description: description:
- The description of the monitor. - The description of the data group.
type: str
version_added: 2.8 version_added: 2.8
type: type:
description: description:
@ -37,6 +39,7 @@ options:
to specify a list of records containing IP addresses, but label them as a C(string) to specify a list of records containing IP addresses, but label them as a C(string)
type. type.
- This value cannot be changed once the data group is created. - This value cannot be changed once the data group is created.
type: str
choices: choices:
- address - address
- addr - addr
@ -71,6 +74,7 @@ options:
- If this value is not provided, it will be given the value specified in C(name) and, - If this value is not provided, it will be given the value specified in C(name) and,
therefore, match the name of the data group. therefore, match the name of the data group.
- This value may only contain letters, numbers, underscores, dashes, or a period. - This value may only contain letters, numbers, underscores, dashes, or a period.
type: str
records: records:
description: description:
- Specifies the records that you want to add to a data group. - Specifies the records that you want to add to a data group.
@ -81,15 +85,18 @@ options:
RAM. RAM.
- When C(internal) is C(no), at least one record must be specified in either C(records) - When C(internal) is C(no), at least one record must be specified in either C(records)
or C(records_content). or C(records_content).
type: list
suboptions: suboptions:
key: key:
description: description:
- The key describing the record in the data group. - The key describing the record in the data group.
- Your key will be used for validation of the C(type) parameter to this module. - Your key will be used for validation of the C(type) parameter to this module.
type: str
required: True required: True
value: value:
description: description:
- The value of the key describing the record in the data group. - The value of the key describing the record in the data group.
type: raw
records_src: records_src:
description: description:
- Path to a file with records in it. - Path to a file with records in it.
@ -108,6 +115,7 @@ options:
group file. group file.
- When C(internal) is C(no), at least one record must be specified in either C(records) - When C(internal) is C(no), at least one record must be specified in either C(records)
or C(records_content). or C(records_content).
type: path
separator: separator:
description: description:
- When specifying C(records_content), this is the string of characters that will - When specifying C(records_content), this is the string of characters that will
@ -116,25 +124,31 @@ options:
- This value cannot be changed once it is set. - This value cannot be changed once it is set.
- This parameter is only relevant when C(internal) is C(no). It will be ignored - This parameter is only relevant when C(internal) is C(no). It will be ignored
otherwise. otherwise.
type: str
default: ":=" default: ":="
delete_data_group_file: delete_data_group_file:
description: description:
- When C(yes), will ensure that the remote data group file is deleted. - When C(yes), will ensure that the remote data group file is deleted.
- This parameter is only relevant when C(state) is C(absent) and C(internal) is C(no). - This parameter is only relevant when C(state) is C(absent) and C(internal) is C(no).
default: no
type: bool type: bool
default: no
partition: partition:
description: description:
- Device partition to manage resources on. - Device partition to manage resources on.
type: str
default: Common default: Common
state: state:
description: description:
- When C(state) is C(present), ensures the data group exists. - When C(state) is C(present), ensures the data group exists.
- When C(state) is C(absent), ensures that the data group is removed. - When C(state) is C(absent), ensures that the data group is removed.
- The use of state in this module refers to the entire data group, not its members.
type: str
choices: choices:
- present - present
- absent - absent
default: present default: present
notes:
- This module does NOT support atomic updates of data group members in a type C(internal) data group.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
@ -145,6 +159,7 @@ EXAMPLES = r'''
- name: Create a data group of addresses - name: Create a data group of addresses
bigip_data_group: bigip_data_group:
name: foo name: foo
internal: yes
records: records:
- key: 0.0.0.0/32 - key: 0.0.0.0/32
value: External_NAT value: External_NAT
@ -160,6 +175,7 @@ EXAMPLES = r'''
- name: Create a data group of strings - name: Create a data group of strings
bigip_data_group: bigip_data_group:
name: foo name: foo
internal: yes
records: records:
- key: caddy - key: caddy
value: "" value: ""
@ -268,11 +284,8 @@ try:
from library.module_utils.network.f5.bigip import F5RestClient from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import transform_name from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import exit_json from library.module_utils.network.f5.compare import compare_complex_list
from library.module_utils.network.f5.common import fail_json
from library.module_utils.network.f5.common import compare_complex_list
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.ipaddress import is_valid_ip_interface from library.module_utils.network.f5.ipaddress import is_valid_ip_interface
from library.module_utils.compat.ipaddress import ip_network from library.module_utils.compat.ipaddress import ip_network
@ -283,11 +296,8 @@ except ImportError:
from ansible.module_utils.network.f5.bigip import F5RestClient from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import transform_name from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import exit_json from ansible.module_utils.network.f5.compare import compare_complex_list
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.common import compare_complex_list
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.ipaddress import is_valid_ip_interface from ansible.module_utils.network.f5.ipaddress import is_valid_ip_interface
from ansible.module_utils.compat.ipaddress import ip_network from ansible.module_utils.compat.ipaddress import ip_network
@ -580,6 +590,17 @@ class Parameters(AnsibleF5Parameters):
class ApiParameters(Parameters): class ApiParameters(Parameters):
def _strip_route_domain(self, item):
result = dict()
pattern = r'(?P<ip>[^%]+)%(?P<route_domain>[0-9]+)/(?P<mask>[0-9]+)'
matches = re.search(pattern, item['name'])
if matches:
result['data'] = item['data']
result['name'] = '{0}/{1}'.format(matches.group('ip'), matches.group('mask'))
return result
return item
@property @property
def checksum(self): def checksum(self):
if self._values['checksum'] is None: if self._values['checksum'] is None:
@ -591,7 +612,8 @@ class ApiParameters(Parameters):
def records(self): def records(self):
if self._values['records'] is None: if self._values['records'] is None:
return None return None
return self._values['records'] result = [self._strip_route_domain(item) for item in self._values['records']]
return result
@property @property
def records_list(self): def records_list(self):
@ -740,7 +762,7 @@ class Difference(object):
class BaseManager(object): class BaseManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = F5RestClient(**self.module.params)
self.want = ModuleParameters(params=self.module.params) self.want = ModuleParameters(params=self.module.params)
self.have = ApiParameters() self.have = ApiParameters()
self.changes = UsableChanges() self.changes = UsableChanges()
@ -1226,7 +1248,6 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.kwargs = kwargs self.kwargs = kwargs
self.module = kwargs.get('module') self.module = kwargs.get('module')
self.client = kwargs.get('client', None)
def exec_module(self): def exec_module(self):
if self.module.params['internal']: if self.module.params['internal']:
@ -1283,19 +1304,16 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
mutually_exclusive=spec.mutually_exclusive
) )
client = F5RestClient(**module.params)
try: try:
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) module.exit_json(**results)
exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) module.fail_json(msg=str(ex))
fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View File

@ -116,9 +116,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -150,9 +152,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -185,9 +189,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -217,9 +223,11 @@ class TestManager(unittest.TestCase):
internal=False, internal=False,
state='absent', state='absent',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -249,9 +257,11 @@ class TestManager(unittest.TestCase):
internal=False, internal=False,
state='absent', state='absent',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -284,9 +294,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -318,9 +330,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -353,9 +367,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -387,9 +403,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(
@ -442,9 +460,11 @@ class TestManager(unittest.TestCase):
separator=':=', separator=':=',
state='present', state='present',
partition='Common', partition='Common',
server='localhost', provider=dict(
password='password', server='localhost',
user='admin' password='password',
user='admin'
)
)) ))
module = AnsibleModule( module = AnsibleModule(