|
|
|
@ -267,6 +267,12 @@ try:
|
|
|
|
|
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 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
|
|
|
|
|
from library.module_utils.network.f5.ipaddress import is_valid_ip_interface
|
|
|
|
|
from library.module_utils.compat.ipaddress import ip_address
|
|
|
|
|
from library.module_utils.compat.ipaddress import ip_network
|
|
|
|
|
from library.module_utils.compat.ipaddress import ip_interface
|
|
|
|
|
try:
|
|
|
|
|
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
|
|
|
|
except ImportError:
|
|
|
|
@ -279,17 +285,17 @@ except ImportError:
|
|
|
|
|
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 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
|
|
|
|
|
from ansible.module_utils.network.f5.ipaddress import is_valid_ip_interface
|
|
|
|
|
from ansible.module_utils.compat.ipaddress import ip_address
|
|
|
|
|
from ansible.module_utils.compat.ipaddress import ip_network
|
|
|
|
|
from ansible.module_utils.compat.ipaddress import ip_interface
|
|
|
|
|
try:
|
|
|
|
|
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
|
|
|
|
except ImportError:
|
|
|
|
|
HAS_F5SDK = False
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
import netaddr
|
|
|
|
|
HAS_NETADDR = True
|
|
|
|
|
except ImportError:
|
|
|
|
|
HAS_NETADDR = False
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
LINE_LIMIT = 65000
|
|
|
|
|
SIZE_LIMIT_BYTES = 4000000
|
|
|
|
@ -345,22 +351,33 @@ class RecordsEncoder(object):
|
|
|
|
|
return self.encode_string_from_dict(record)
|
|
|
|
|
|
|
|
|
|
def encode_address_from_dict(self, record):
|
|
|
|
|
try:
|
|
|
|
|
key = netaddr.IPNetwork(record['key'])
|
|
|
|
|
except netaddr.core.AddrFormatError:
|
|
|
|
|
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']):
|
|
|
|
|
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:
|
|
|
|
|
if key.prefixlen in [32, 128]:
|
|
|
|
|
return self.encode_host(key.ip, record['value'])
|
|
|
|
|
else:
|
|
|
|
|
return self.encode_network(key.network, key.prefixlen, record['value'])
|
|
|
|
|
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'])
|
|
|
|
|
elif key:
|
|
|
|
|
if key.prefixlen in [32, 128]:
|
|
|
|
|
return self.encode_host(key.ip, key.ip)
|
|
|
|
|
else:
|
|
|
|
|
return self.encode_network(key.network, key.prefixlen, key.network)
|
|
|
|
|
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)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def encode_integer_from_dict(self, record):
|
|
|
|
|
try:
|
|
|
|
@ -401,24 +418,37 @@ class RecordsEncoder(object):
|
|
|
|
|
else:
|
|
|
|
|
# 192.168.0.0/16 := "Network3",
|
|
|
|
|
# 2402:9400:1000:0::/64 := "Network4",
|
|
|
|
|
try:
|
|
|
|
|
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:
|
|
|
|
|
key = netaddr.IPNetwork(parts[0])
|
|
|
|
|
if key.prefixlen in [32, 128]:
|
|
|
|
|
return self.encode_host(key.ip, parts[1])
|
|
|
|
|
else:
|
|
|
|
|
return self.encode_network(key.network, key.prefixlen, parts[1])
|
|
|
|
|
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] != '':
|
|
|
|
|
key = netaddr.IPNetwork(parts[0])
|
|
|
|
|
if key.prefixlen in [32, 128]:
|
|
|
|
|
return self.encode_host(key.ip, key.ip)
|
|
|
|
|
else:
|
|
|
|
|
return self.encode_network(key.network, key.prefixlen, key.network)
|
|
|
|
|
except netaddr.core.AddrFormatError:
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"When specifying an 'address' type, the value to the left of the separator must be an IP."
|
|
|
|
|
)
|
|
|
|
|
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)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def encode_host(self, key, value):
|
|
|
|
|
return 'host {0} {1} {2}'.format(str(key), self._separator, str(value))
|
|
|
|
@ -466,29 +496,27 @@ class RecordsDecoder(object):
|
|
|
|
|
return self.decode_from_string(record)
|
|
|
|
|
|
|
|
|
|
def decode_address_from_string(self, record):
|
|
|
|
|
try:
|
|
|
|
|
matches = self._network_pattern.match(record)
|
|
|
|
|
if matches:
|
|
|
|
|
# network 192.168.0.0 prefixlen 16 := "Network3",
|
|
|
|
|
# network 2402:9400:1000:0:: prefixlen 64 := "Network4",
|
|
|
|
|
key = "{0}/{1}".format(matches.group('addr'), matches.group('prefix'))
|
|
|
|
|
addr = netaddr.IPNetwork(key)
|
|
|
|
|
value = record.split(self._separator)[1].strip().strip('"')
|
|
|
|
|
result = dict(name=str(addr), data=value)
|
|
|
|
|
return result
|
|
|
|
|
matches = self._host_pattern.match(record)
|
|
|
|
|
if matches:
|
|
|
|
|
# host 172.16.1.1/32 := "Host3"
|
|
|
|
|
# host 2001:0db8:85a3:0000:0000:8a2e:0370:7334 := "Host4"
|
|
|
|
|
key = matches.group('addr')
|
|
|
|
|
addr = netaddr.IPNetwork(key)
|
|
|
|
|
value = record.split(self._separator)[1].strip().strip('"')
|
|
|
|
|
result = dict(name=str(addr), data=value)
|
|
|
|
|
return result
|
|
|
|
|
except netaddr.core.AddrFormatError:
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
'The value "{0}" is not an address'.format(record)
|
|
|
|
|
)
|
|
|
|
|
matches = self._network_pattern.match(record)
|
|
|
|
|
if matches:
|
|
|
|
|
# network 192.168.0.0 prefixlen 16 := "Network3",
|
|
|
|
|
# network 2402:9400:1000:0:: prefixlen 64 := "Network4",
|
|
|
|
|
key = u"{0}/{1}".format(matches.group('addr'), matches.group('prefix'))
|
|
|
|
|
addr = ip_network(key)
|
|
|
|
|
value = record.split(self._separator)[1].strip().strip('"')
|
|
|
|
|
result = dict(name=str(addr), data=value)
|
|
|
|
|
return result
|
|
|
|
|
matches = self._host_pattern.match(record)
|
|
|
|
|
if matches:
|
|
|
|
|
# host 172.16.1.1/32 := "Host3"
|
|
|
|
|
# host 2001:0db8:85a3:0000:0000:8a2e:0370:7334 := "Host4"
|
|
|
|
|
key = matches.group('addr')
|
|
|
|
|
addr = ip_interface(u"{0}".format(str(key)))
|
|
|
|
|
value = record.split(self._separator)[1].strip().strip('"')
|
|
|
|
|
result = dict(name=str(addr), data=value)
|
|
|
|
|
return result
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
'The value "{0}" is not an address'.format(record)
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
def decode_from_string(self, record):
|
|
|
|
|
parts = record.split(self._separator)
|
|
|
|
@ -589,7 +617,7 @@ class ModuleParameters(Parameters):
|
|
|
|
|
data = records.read(4096)
|
|
|
|
|
if not data:
|
|
|
|
|
break
|
|
|
|
|
result.update(data)
|
|
|
|
|
result.update(data.encode('utf-8'))
|
|
|
|
|
result = result.hexdigest()
|
|
|
|
|
self._values['checksum'] = result
|
|
|
|
|
return result
|
|
|
|
@ -600,7 +628,7 @@ class ModuleParameters(Parameters):
|
|
|
|
|
name = self.name
|
|
|
|
|
else:
|
|
|
|
|
name = self._values['external_file_name']
|
|
|
|
|
if re.search(r'[^a-z0-9-_.]', name):
|
|
|
|
|
if re.search(r'[^a-zA-Z0-9-_.]', name):
|
|
|
|
|
raise F5ModuleError(
|
|
|
|
|
"'external_file_name' may only contain letters, numbers, underscores, dashes, or a period."
|
|
|
|
|
)
|
|
|
|
@ -1051,8 +1079,6 @@ def main():
|
|
|
|
|
)
|
|
|
|
|
if not HAS_F5SDK:
|
|
|
|
|
module.fail_json(msg="The python f5-sdk module is required")
|
|
|
|
|
if not HAS_NETADDR:
|
|
|
|
|
module.fail_json(msg="The python netaddr module is required")
|
|
|
|
|
|
|
|
|
|
try:
|
|
|
|
|
client = F5Client(**module.params)
|
|
|
|
|