Various f5 fixes (#44858)

* Remove sdk from modules
* Correct IP address bugs in data_group
* Correct compare_dictionary bug in several modules
pull/38159/merge
Tim Rupp 6 years ago committed by GitHub
parent 773c0982b0
commit 5bdcaff921
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -335,28 +335,34 @@ def transform_name(partition='', name='', sub_path=''):
return result
def dict2tuple(items):
"""Convert a dictionary to a list of tuples
def compare_complex_list(want, have):
"""Performs a complex list comparison
This method is used in cases where dictionaries need to be compared. Due
to dictionaries inherently having no order, it is easier to compare list
of tuples because these lists can be converted to sets.
This conversion only supports dicts of simple values. Do not give it dicts
that contain sub-dicts. This will not give you the result you want when using
the returned tuple for comparison.
A complex list is a list of dictionaries
Args:
items (dict): The dictionary of items that should be converted
want (list): List of dictionaries to compare with second parameter.
have (list): List of dictionaries compare with first parameter.
Returns:
list: Returns a list of tuples upon success. Otherwise, an empty list.
bool:
"""
result = []
for x in items:
if want == [] and have is None:
return None
if want is None:
return None
w = []
h = []
for x in want:
tmp = [(str(k), str(v)) for k, v in iteritems(x)]
result += tmp
return result
w += tmp
for x in have:
tmp = [(str(k), str(v)) for k, v in iteritems(x)]
h += tmp
if set(w) == set(h):
return None
else:
return want
def compare_dictionary(want, have):
@ -369,12 +375,12 @@ def compare_dictionary(want, have):
Returns:
bool:
"""
if want == [] and have is None:
if want == {} and have is None:
return None
if want is None:
return None
w = dict2tuple(want)
h = dict2tuple(have)
w = [(str(k), str(v)) for k, v in iteritems(want)]
h = [(str(k), str(v)) for k, v in iteritems(have)]
if set(w) == set(h):
return None
else:

@ -265,7 +265,7 @@ try:
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 cleanup_tokens
from library.module_utils.network.f5.common import compare_dictionary
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.ipaddress import is_valid_ip
from library.module_utils.network.f5.ipaddress import is_valid_ip_network
@ -283,7 +283,7 @@ except ImportError:
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 cleanup_tokens
from ansible.module_utils.network.f5.common import compare_dictionary
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.ipaddress import is_valid_ip
from ansible.module_utils.network.f5.ipaddress import is_valid_ip_network
@ -351,33 +351,24 @@ class RecordsEncoder(object):
return self.encode_string_from_dict(record)
def encode_address_from_dict(self, record):
if is_valid_ip_network(record['key']):
key = ip_network(u"{0}".format(str(record['key'])))
elif is_valid_ip(record['key']):
key = ip_address(u"{0}".format(str(record['key'])))
elif is_valid_ip_interface(record['key']):
if is_valid_ip_interface(record['key']):
key = ip_interface(u"{0}".format(str(record['key'])))
else:
raise F5ModuleError(
"When specifying an 'address' type, the value to the left of the separator must be an IP."
)
if key and 'value' in record:
try:
# Only ip_address's have max_prefixlen
if key.max_prefixlen in [32, 128]:
return self.encode_host(str(key), record['value'])
except ValueError:
return self.encode_network(
str(key.network_address), key.prefixlen, record['value'])
if key.network.prefixlen in [32, 128]:
return self.encode_host(str(key.ip), record['value'])
return self.encode_network(
str(key.network.network_address), key.network.prefixlen, record['value']
)
elif key:
try:
# Only ip_address's have max_prefixlen
if key.max_prefixlen in [32, 128]:
return self.encode_host(str(key), str(key))
except ValueError:
return self.encode_network(
str(key.network_address), key.prefixlen, str(key.network_address)
)
if key.network.prefixlen in [32, 128]:
return self.encode_host(str(key.ip), str(key.ip))
return self.encode_network(
str(key.network.network_address), key.network.prefixlen, str(key.network.network_address)
)
def encode_integer_from_dict(self, record):
try:
@ -418,37 +409,27 @@ class RecordsEncoder(object):
else:
# 192.168.0.0/16 := "Network3",
# 2402:9400:1000:0::/64 := "Network4",
parts = record.split(self._separator)
if is_valid_ip_network(parts[0]):
key = ip_network(u"{0}".format(str(parts[0])))
elif is_valid_ip(parts[0]):
key = ip_address(u"{0}".format(str(parts[0])))
elif is_valid_ip_interface(parts[0]):
key = ip_interface(u"{0}".format(str(parts[0])))
elif parts[0] == '':
pass
else:
raise F5ModuleError(
"When specifying an 'address' type, the value to the left of the separator must be an IP."
)
if len(parts) == 2:
try:
# Only ip_address's have max_prefixlen
if key.max_prefixlen in [32, 128]:
return self.encode_host(str(key), parts[1])
except ValueError:
return self.encode_network(
str(key.network_address), key.prefixlen, parts[1])
elif len(parts) == 1 and parts[0] != '':
try:
# Only ip_address's have max_prefixlen
if key.max_prefixlen in [32, 128]:
return self.encode_host(str(key), str(key))
except ValueError:
return self.encode_network(
str(key.network_address), key.prefixlen, str(key.network_address)
)
parts = record.split(self._separator)
if parts[0] == '':
return
if not is_valid_ip_interface(parts[0]):
raise F5ModuleError(
"When specifying an 'address' type, the value to the left of the separator must be an IP."
)
key = ip_interface(u"{0}".format(str(parts[0])))
if len(parts) == 2:
if key.network.prefixlen in [32, 128]:
return self.encode_host(str(key.ip), parts[1])
return self.encode_network(
str(key.network.network_address), key.network.prefixlen, parts[1]
)
elif len(parts) == 1 and parts[0] != '':
if key.network.prefixlen in [32, 128]:
return self.encode_host(str(key.ip), str(key.ip))
return self.encode_network(
str(key.network.network_address), key.network.prefixlen, str(key.network.network_address)
)
def encode_host(self, key, value):
return 'host {0} {1} {2}'.format(str(key), self._separator, str(value))
@ -706,7 +687,7 @@ class Difference(object):
return None
if self.have.records is None:
return self.want.records
result = compare_dictionary(self.want.records, self.have.records)
result = compare_complex_list(self.want.records, self.have.records)
return result
@property

@ -415,7 +415,7 @@ class Difference(object):
)
result = dict()
different = compare_dictionary([self.want.variables], [self.have.variables])
different = compare_dictionary(self.want.variables, self.have.variables)
if not different:
return None

@ -244,13 +244,14 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
try:
from library.module_utils.compat.ipaddress import ip_address
from library.module_utils.network.f5.bigip import HAS_F5SDK
from library.module_utils.network.f5.bigip import F5Client
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 cleanup_tokens
from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import compare_dictionary
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.ipaddress import is_valid_ip
from library.module_utils.network.f5.ipaddress import validate_ip_v6_address
@ -260,13 +261,14 @@ try:
except ImportError:
HAS_F5SDK = False
except ImportError:
from ansible.module_utils.compat.ipaddress import ip_address
from ansible.module_utils.network.f5.bigip import HAS_F5SDK
from ansible.module_utils.network.f5.bigip import F5Client
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 cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import compare_dictionary
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.ipaddress import is_valid_ip
from ansible.module_utils.network.f5.ipaddress import validate_ip_v6_address
@ -534,7 +536,8 @@ class ModuleParameters(Parameters):
if self._values['address'] is None:
return None
if is_valid_ip(self._values['address']):
return self._values['address']
ip = str(ip_address(u'{0}'.format(self._values['address'])))
return ip
raise F5ModuleError(
"Specified 'address' is not an IP address."
)
@ -758,7 +761,8 @@ class Difference(object):
return None
if self.want.virtual_server_dependencies is None:
return None
return compare_dictionary(self.want.virtual_server_dependencies, self.have.virtual_server_dependencies)
result = compare_complex_list(self.want.virtual_server_dependencies, self.have.virtual_server_dependencies)
return result
@property
def enabled(self):

@ -7,7 +7,6 @@
from __future__ import absolute_import, division, print_function
__metaclass__ = type
ANSIBLE_METADATA = {'metadata_version': '1.1',
'status': ['preview'],
'supported_by': 'community'}
@ -159,7 +158,6 @@ timeout:
sample: 10
'''
import os
import re
from ansible.module_utils.basic import AnsibleModule
@ -167,33 +165,29 @@ from ansible.module_utils.basic import env_fallback
from ansible.module_utils.six import iteritems
try:
from library.module_utils.network.f5.bigip import HAS_F5SDK
from library.module_utils.network.f5.bigip import F5Client
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 AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec
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.common import fail_json
from library.module_utils.network.f5.common import compare_dictionary
from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK
from ansible.module_utils.network.f5.bigip import F5Client
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 AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import compare_dictionary
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters):
@ -201,33 +195,24 @@ class Parameters(AnsibleF5Parameters):
'defaultsFrom': 'parent',
'apiRawValues': 'variables',
'run': 'external_program',
'args': 'arguments'
'args': 'arguments',
}
api_attributes = [
'defaultsFrom', 'interval', 'timeout', 'destination', 'run', 'args', 'description'
'defaultsFrom', 'interval', 'timeout', 'destination', 'run', 'args',
'description',
]
returnables = [
'parent', 'ip', 'port', 'interval', 'timeout', 'variables', 'external_program',
'arguments', 'description'
'arguments', 'description',
]
updatables = [
'destination', 'interval', 'timeout', 'variables', 'external_program',
'arguments', 'description'
'arguments', 'description',
]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
except Exception:
pass
return result
@property
def destination(self):
if self.ip is None and self.port is None:
@ -285,11 +270,7 @@ class Parameters(AnsibleF5Parameters):
def parent(self):
if self._values['parent'] is None:
return None
if self._values['parent'].startswith('/'):
parent = os.path.basename(self._values['parent'])
result = '/{0}/{1}'.format(self.partition, parent)
else:
result = '/{0}/{1}'.format(self.partition, self._values['parent'])
result = fq_name(self.partition, self._values['parent'])
return result
@property
@ -426,8 +407,7 @@ class Difference(object):
variables=self.want.variables
)
result = dict()
different = compare_dictionary([self.want.variables], [self.have.variables])
different = compare_dictionary(self.want.variables, self.have.variables)
if not different:
return None
@ -491,13 +471,10 @@ class ModuleManager(object):
result = dict()
state = self.want.state
try:
if state == "present":
changed = self.present()
elif state == "absent":
changed = self.absent()
except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e))
if state == "present":
changed = self.present()
elif state == "absent":
changed = self.absent()
reportable = ReportableChanges(params=self.changes.to_return())
changes = reportable.to_return()
@ -520,19 +497,19 @@ class ModuleManager(object):
else:
return self.create()
def create(self):
self._set_changed_options()
if self.want.timeout is None:
self.want.update({'timeout': 16})
if self.want.interval is None:
self.want.update({'interval': 5})
if self.want.ip is None:
self.want.update({'ip': '*'})
if self.want.port is None:
self.want.update({'port': '*'})
if self.module.check_mode:
return True
self.create_on_device()
def exists(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/external/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError:
return False
if resp.status == 404 or 'code' in response and response['code'] == 404:
return False
return True
def update(self):
@ -544,70 +521,132 @@ class ModuleManager(object):
self.update_on_device()
return True
def absent(self):
if self.exists():
return self.remove()
return False
def remove(self):
if self.module.check_mode:
return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the monitor.")
raise F5ModuleError("Failed to delete the resource.")
return True
def read_current_from_device(self):
resource = self.client.api.tm.ltm.monitor.externals.external.load(
name=self.want.name,
partition=self.want.partition
)
result = resource.attrs
return ApiParameters(params=result)
def create(self):
self._set_changed_options()
self._set_default_creation_values()
if self.module.check_mode:
return True
self.create_on_device()
return True
def exists(self):
result = self.client.api.tm.ltm.monitor.externals.external.exists(
name=self.want.name,
partition=self.want.partition
)
return result
def _set_default_creation_values(self):
if self.want.timeout is None:
self.want.update({'timeout': 16})
if self.want.interval is None:
self.want.update({'interval': 5})
if self.want.ip is None:
self.want.update({'ip': '*'})
if self.want.port is None:
self.want.update({'port': '*'})
def update_on_device(self):
def create_on_device(self):
params = self.changes.api_params()
result = self.client.api.tm.ltm.monitor.externals.external.load(
name=self.want.name,
partition=self.want.partition
params['name'] = self.want.name
params['partition'] = self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/external/".format(
self.client.provider['server'],
self.client.provider['server_port']
)
if params:
result.modify(**params)
if self.changes.variables:
self.set_variable_on_device(self.changes.variables)
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] in [400, 403]:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
if self.want.variables:
self.set_variable_on_device(self.want.variables)
def set_variable_on_device(self, commands):
command = ' '.join(['user-defined {0} \\\"{1}\\\"'.format(k, v) for k, v in iteritems(commands)])
command = 'tmsh modify ltm monitor external {0} {1}'.format(self.want.name, command)
self.client.api.tm.util.bash.exec_cmd(
'run',
uri = "https://{0}:{1}/mgmt/tm/util/bash".format(
self.client.provider['server'],
self.client.provider['server_port'],
)
args = dict(
command='run',
utilCmdArgs='-c "{0}"'.format(command)
)
resp = self.client.api.post(uri, json=args)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def create_on_device(self):
params = self.want.api_params()
self.client.api.tm.ltm.monitor.externals.external.create(
name=self.want.name,
partition=self.want.partition,
**params
)
if self.want.variables:
self.set_variable_on_device(self.want.variables)
def update_on_device(self):
params = self.changes.api_params()
if params:
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/external/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
if self.changes.variables:
self.set_variable_on_device(self.changes.variables)
def absent(self):
if self.exists():
return self.remove()
return False
def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.externals.external.load(
name=self.want.name,
partition=self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/external/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
if result:
result.delete()
resp = self.client.api.delete(uri)
if resp.status == 200:
return True
def read_current_from_device(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/external/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
return ApiParameters(params=response)
class ArgumentSpec(object):
@ -643,20 +682,19 @@ def main():
module = AnsibleModule(
argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode
supports_check_mode=spec.supports_check_mode,
)
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
client = F5RestClient(**module.params)
try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module()
cleanup_tokens(client)
module.exit_json(**results)
exit_json(module, results, client)
except F5ModuleError as ex:
cleanup_tokens(client)
module.fail_json(msg=str(ex))
fail_json(module, ex, client)
if __name__ == '__main__':

@ -478,12 +478,6 @@ class ModuleManager(object):
self.update_on_device()
return True
def should_update(self):
result = self._update_changed_options()
if result:
return True
return False
def remove(self):
if self.module.check_mode:
return True

@ -155,69 +155,57 @@ time_until_up:
sample: 2
'''
import os
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
try:
from library.module_utils.network.f5.bigip import HAS_F5SDK
from library.module_utils.network.f5.bigip import F5Client
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 AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec
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.common import fail_json
from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK
from ansible.module_utils.network.f5.bigip import F5Client
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 AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec
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.common import fail_json
from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters):
api_map = {
'timeUntilUp': 'time_until_up',
'defaultsFrom': 'parent',
'recv': 'receive'
'recv': 'receive',
}
api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send',
'destination', 'description'
'destination', 'description',
]
returnables = [
'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout',
'time_until_up', 'description'
'time_until_up', 'description',
]
updatables = [
'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up',
'description'
'description',
]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
except Exception:
pass
return result
@property
def destination(self):
if self.ip is None and self.port is None:
@ -281,11 +269,7 @@ class Parameters(AnsibleF5Parameters):
def parent(self):
if self._values['parent'] is None:
return None
if self._values['parent'].startswith('/'):
parent = os.path.basename(self._values['parent'])
result = '/{0}/{1}'.format(self.partition, parent)
else:
result = '/{0}/{1}'.format(self.partition, self._values['parent'])
result = fq_name(self.partition, self._values['parent'])
return result
@property
@ -293,7 +277,31 @@ class Parameters(AnsibleF5Parameters):
return 'udp'
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters):
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
except Exception:
pass
return result
class UsableChanges(Changes):
pass
class ReportableChanges(Changes):
pass
@ -368,9 +376,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.have = None
self.want = Parameters(params=self.module.params)
self.changes = Changes()
self.want = ModuleParameters(params=self.module.params)
self.have = ApiParameters()
self.changes = UsableChanges()
def _set_changed_options(self):
changed = {}
@ -378,7 +386,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key)
if changed:
self.changes = Changes(params=changed)
self.changes = UsableChanges(params=changed)
def _update_changed_options(self):
diff = Difference(self.want, self.have)
@ -394,7 +402,7 @@ class ModuleManager(object):
else:
changed[k] = change
if changed:
self.changes = Changes(params=changed)
self.changes = UsableChanges(params=changed)
return True
return False
@ -409,15 +417,13 @@ class ModuleManager(object):
result = dict()
state = self.want.state
try:
if state == "present":
changed = self.present()
elif state == "absent":
changed = self.absent()
except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e))
changes = self.changes.to_return()
if state == "present":
changed = self.present()
elif state == "absent":
changed = self.absent()
reportable = ReportableChanges(params=self.changes.to_return())
changes = reportable.to_return()
result.update(**changes)
result.update(dict(changed=changed))
self._announce_deprecations(result)
@ -426,7 +432,7 @@ class ModuleManager(object):
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.module.deprecate(
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
@ -437,31 +443,20 @@ class ModuleManager(object):
else:
return self.create()
def create(self):
self._set_changed_options()
if self.want.timeout is None:
self.want.update({'timeout': 16})
if self.want.interval is None:
self.want.update({'interval': 5})
if self.want.time_until_up is None:
self.want.update({'time_until_up': 0})
if self.want.ip is None:
self.want.update({'ip': '*'})
if self.want.port is None:
self.want.update({'port': '*'})
if self.want.send is None:
self.want.update({'send': 'default send string'})
if self.module.check_mode:
return True
self.create_on_device()
return True
def exists(self):
result = self.client.api.tm.ltm.monitor.udps.udp.exists(
name=self.want.name,
partition=self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/udp/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
return result
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError:
return False
if resp.status == 404 or 'code' in response and response['code'] == 404:
return False
return True
def update(self):
self.have = self.read_current_from_device()
@ -480,21 +475,66 @@ class ModuleManager(object):
raise F5ModuleError("Failed to delete the resource.")
return True
def create(self):
self._set_changed_options()
self._set_default_creation_values()
if self.module.check_mode:
return True
self.create_on_device()
return True
def _set_default_creation_values(self):
if self.want.timeout is None:
self.want.update({'timeout': 16})
if self.want.interval is None:
self.want.update({'interval': 5})
if self.want.time_until_up is None:
self.want.update({'time_until_up': 0})
if self.want.ip is None:
self.want.update({'ip': '*'})
if self.want.port is None:
self.want.update({'port': '*'})
if self.want.send is None:
self.want.update({'send': 'default send string'})
def create_on_device(self):
params = self.want.api_params()
self.client.api.tm.ltm.monitor.udps.udp.create(
name=self.want.name,
partition=self.want.partition,
**params
params = self.changes.api_params()
params['name'] = self.want.name
params['partition'] = self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/udp/".format(
self.client.provider['server'],
self.client.provider['server_port']
)
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] in [400, 403]:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def update_on_device(self):
params = self.want.api_params()
resource = self.client.api.tm.ltm.monitor.udps.udp.load(
name=self.want.name,
partition=self.want.partition
params = self.changes.api_params()
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/udp/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resource.modify(**params)
resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def absent(self):
if self.exists():
@ -502,20 +542,33 @@ class ModuleManager(object):
return False
def remove_from_device(self):
resource = self.client.api.tm.ltm.monitor.udps.udp.load(
name=self.want.name,
partition=self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/udp/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
if resource:
resource.delete()
resp = self.client.api.delete(uri)
if resp.status == 200:
return True
def read_current_from_device(self):
resource = self.client.api.tm.ltm.monitor.udps.udp.load(
name=self.want.name,
partition=self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/udp/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
result = resource.attrs
return Parameters(params=result)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
return ApiParameters(params=response)
class ArgumentSpec(object):
@ -552,20 +605,19 @@ def main():
module = AnsibleModule(
argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode
supports_check_mode=spec.supports_check_mode,
)
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
client = F5RestClient(**module.params)
try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module()
cleanup_tokens(client)
module.exit_json(**results)
exit_json(module, results, client)
except F5ModuleError as ex:
cleanup_tokens(client)
module.fail_json(msg=str(ex))
fail_json(module, ex, client)
if __name__ == '__main__':

@ -152,7 +152,7 @@ try:
from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.common import compare_dictionary
from library.module_utils.network.f5.common import compare_complex_list
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
@ -165,7 +165,7 @@ except ImportError:
from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import compare_dictionary
from ansible.module_utils.network.f5.common import compare_complex_list
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
@ -371,7 +371,7 @@ class Difference(object):
have = [tuple(x.pop('destination_ports')) for x in self.have.rules if 'destination_ports' in x]
if set(want) != set(have):
return self.want.rules
if compare_dictionary(self.want.rules, self.have.rules):
if compare_complex_list(self.want.rules, self.have.rules):
return self.want.rules

Loading…
Cancel
Save