Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Various f5 fixes #44858

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
42 changes: 24 additions & 18 deletions lib/ansible/module_utils/network/f5/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -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):
Expand All @@ -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:
Expand Down
89 changes: 35 additions & 54 deletions lib/ansible/modules/network/f5/bigip_data_group.py
Original file line number Diff line number Diff line change
Expand Up @@ -265,7 +265,7 @@
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
Expand All @@ -283,7 +283,7 @@
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
Expand Down Expand Up @@ -351,33 +351,24 @@ def encode_dict(self, record):
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:
Expand Down Expand Up @@ -418,37 +409,27 @@ def encode_address_from_string(self, record):
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))
Expand Down Expand Up @@ -706,7 +687,7 @@ def records(self):
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
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -415,7 +415,7 @@ def variables(self):
)
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

Expand Down
12 changes: 8 additions & 4 deletions lib/ansible/modules/network/f5/bigip_gtm_virtual_server.py
Original file line number Diff line number Diff line change
Expand Up @@ -244,13 +244,14 @@
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
Expand All @@ -260,13 +261,14 @@
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
Expand Down Expand Up @@ -534,7 +536,8 @@ def address(self):
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."
)
Expand Down Expand Up @@ -758,7 +761,8 @@ def virtual_server_dependencies(self):
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):
Expand Down