Removes netaddr dependency (#44519)
One more dep removed from bigip_selfip
This commit is contained in:
parent
1682ce5263
commit
9a17ee6d84
1 changed files with 122 additions and 124 deletions
|
@ -74,11 +74,7 @@ options:
|
|||
other resources on a BIG-IP are.
|
||||
default: Common
|
||||
version_added: 2.5
|
||||
notes:
|
||||
- Requires the netaddr Python package on the host.
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- netaddr
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
'''
|
||||
|
@ -229,6 +225,11 @@ 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.ipaddress import is_valid_ip
|
||||
from library.module_utils.network.f5.ipaddress import ipv6_netmask_to_cidr
|
||||
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:
|
||||
|
@ -241,17 +242,16 @@ 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.ipaddress import is_valid_ip
|
||||
from ansible.module_utils.network.f5.ipaddress import ipv6_netmask_to_cidr
|
||||
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
|
||||
|
||||
|
||||
class Parameters(AnsibleF5Parameters):
|
||||
api_map = {
|
||||
|
@ -297,10 +297,9 @@ class ModuleParameters(Parameters):
|
|||
def ip(self):
|
||||
if self._values['address'] is None:
|
||||
return None
|
||||
try:
|
||||
ip = str(netaddr.IPAddress(self._values['address']))
|
||||
return ip
|
||||
except netaddr.AddrFormatError:
|
||||
if is_valid_ip(self._values['address']):
|
||||
return self._values['address']
|
||||
else:
|
||||
raise F5ModuleError(
|
||||
'The provided address is not a valid IP address'
|
||||
)
|
||||
|
@ -322,30 +321,23 @@ class ModuleParameters(Parameters):
|
|||
def netmask(self):
|
||||
if self._values['netmask'] is None:
|
||||
return None
|
||||
|
||||
# Check if numeric
|
||||
if isinstance(self._values['netmask'], int):
|
||||
result = -1
|
||||
try:
|
||||
result = int(self._values['netmask'])
|
||||
if 0 < result < 256:
|
||||
return result
|
||||
pass
|
||||
except ValueError:
|
||||
if is_valid_ip(self._values['netmask']):
|
||||
addr = ip_address(u'{0}'.format(str(self._values['netmask'])))
|
||||
if addr.version == 4:
|
||||
ip = ip_network(u'0.0.0.0/%s' % str(self._values['netmask']))
|
||||
result = ip.prefixlen
|
||||
else:
|
||||
result = ipv6_netmask_to_cidr(self._values['netmask'])
|
||||
if result < 0:
|
||||
raise F5ModuleError(
|
||||
'The provided netmask {0} is neither in IP or CIDR format'.format(result)
|
||||
)
|
||||
else:
|
||||
try:
|
||||
# IPv4 netmask
|
||||
address = '0.0.0.0/' + self._values['netmask']
|
||||
ip = netaddr.IPNetwork(address)
|
||||
except netaddr.AddrFormatError as ex:
|
||||
try:
|
||||
# IPv6 netmask
|
||||
address = '::/' + self._values['netmask']
|
||||
ip = netaddr.IPNetwork(address)
|
||||
except netaddr.AddrFormatError as ex:
|
||||
raise F5ModuleError(
|
||||
'The provided netmask {0} is neither in IP or CIDR format'.format(self._values['netmask'])
|
||||
)
|
||||
result = int(ip.prefixlen)
|
||||
return result
|
||||
|
||||
@property
|
||||
|
@ -424,21 +416,21 @@ class ApiParameters(Parameters):
|
|||
try:
|
||||
pattern = r'(?P<rd>%[0-9]+)'
|
||||
addr = re.sub(pattern, '', self._values['address'])
|
||||
ip = netaddr.IPNetwork(addr)
|
||||
return '{0}/{1}'.format(ip.ip, ip.prefixlen)
|
||||
except netaddr.AddrFormatError:
|
||||
ip = ip_interface(u'{0}'.format(addr))
|
||||
return ip.with_prefixlen
|
||||
except ValueError:
|
||||
raise F5ModuleError(
|
||||
"The provided destination is not an IP address"
|
||||
)
|
||||
|
||||
@property
|
||||
def netmask(self):
|
||||
ip = netaddr.IPNetwork(self.destination_ip)
|
||||
return int(ip.prefixlen)
|
||||
ip = ip_interface(self.destination_ip)
|
||||
return int(ip.network.prefixlen)
|
||||
|
||||
@property
|
||||
def ip(self):
|
||||
result = netaddr.IPNetwork(self.destination_ip)
|
||||
result = ip_interface(self.destination_ip)
|
||||
return str(result.ip)
|
||||
|
||||
|
||||
|
@ -446,6 +438,89 @@ class Changes(Parameters):
|
|||
pass
|
||||
|
||||
|
||||
class Difference(object):
|
||||
def __init__(self, want, have=None):
|
||||
self.want = want
|
||||
self.have = have
|
||||
|
||||
def compare(self, param):
|
||||
try:
|
||||
result = getattr(self, param)
|
||||
return result
|
||||
except AttributeError:
|
||||
return self.__default(param)
|
||||
|
||||
def __default(self, param):
|
||||
attr1 = getattr(self.want, param)
|
||||
try:
|
||||
attr2 = getattr(self.have, param)
|
||||
if attr1 != attr2:
|
||||
return attr1
|
||||
except AttributeError:
|
||||
return attr1
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
return None
|
||||
|
||||
@property
|
||||
def allow_service(self):
|
||||
"""Returns services formatted for consumption by f5-sdk update
|
||||
|
||||
The BIG-IP endpoint for services takes different values depending on
|
||||
what you want the "allowed services" to be. It can be any of the
|
||||
following
|
||||
|
||||
- a list containing "protocol:port" values
|
||||
- the string "all"
|
||||
- a null value, or None
|
||||
|
||||
This is a convenience function to massage the values the user has
|
||||
supplied so that they are formatted in such a way that BIG-IP will
|
||||
accept them and apply the specified policy.
|
||||
"""
|
||||
if self.want.allow_service is None:
|
||||
return None
|
||||
result = self.want.allow_service
|
||||
if result[0] == 'none' and self.have.allow_service is None:
|
||||
return None
|
||||
elif self.have.allow_service is None:
|
||||
return result
|
||||
elif result[0] == 'all' and self.have.allow_service[0] != 'all':
|
||||
return ['all']
|
||||
elif result[0] == 'none':
|
||||
return []
|
||||
elif set(self.want.allow_service) != set(self.have.allow_service):
|
||||
return result
|
||||
|
||||
@property
|
||||
def netmask(self):
|
||||
if self.want.netmask is None:
|
||||
return None
|
||||
ip = self.have.ip
|
||||
if is_valid_ip(ip):
|
||||
if self.want.route_domain is not None:
|
||||
want = "{0}%{1}/{2}".format(ip, self.want.route_domain, self.want.netmask)
|
||||
have = "{0}%{1}/{2}".format(ip, self.want.route_domain, self.have.netmask)
|
||||
elif self.have.route_domain is not None:
|
||||
want = "{0}%{1}/{2}".format(ip, self.have.route_domain, self.want.netmask)
|
||||
have = "{0}%{1}/{2}".format(ip, self.have.route_domain, self.have.netmask)
|
||||
else:
|
||||
want = "{0}/{1}".format(ip, self.want.netmask)
|
||||
have = "{0}/{1}".format(ip, self.have.netmask)
|
||||
if want != have:
|
||||
return want
|
||||
else:
|
||||
raise F5ModuleError(
|
||||
'The provided address/netmask value "{0}" was invalid'.format(self.have.ip)
|
||||
)
|
||||
|
||||
@property
|
||||
def traffic_group(self):
|
||||
if self.want.traffic_group != self.have.traffic_group:
|
||||
return self.want.traffic_group
|
||||
|
||||
|
||||
class UsableChanges(Changes):
|
||||
@property
|
||||
def allow_service(self):
|
||||
|
@ -557,6 +632,10 @@ class ModuleManager(object):
|
|||
)
|
||||
resource.modify(**params)
|
||||
|
||||
def read_partition_default_route_domain_from_device(self):
|
||||
resource = self.client.api.tm.auth.partitions.partition.load(name=self.want.partition)
|
||||
return int(resource.defaultRouteDomain)
|
||||
|
||||
def create(self):
|
||||
if self.want.address is None or self.want.netmask is None:
|
||||
raise F5ModuleError(
|
||||
|
@ -566,6 +645,10 @@ class ModuleManager(object):
|
|||
raise F5ModuleError(
|
||||
'A VLAN name must be specified'
|
||||
)
|
||||
if self.want.route_domain is None:
|
||||
rd = self.read_partition_default_route_domain_from_device()
|
||||
self.want.update({'route_domain': rd})
|
||||
|
||||
if self.want.traffic_group is None:
|
||||
self.want.update({'traffic_group': '/Common/traffic-group-local-only'})
|
||||
if self.want.route_domain is None:
|
||||
|
@ -617,89 +700,6 @@ class ModuleManager(object):
|
|||
return result
|
||||
|
||||
|
||||
class Difference(object):
|
||||
def __init__(self, want, have=None):
|
||||
self.want = want
|
||||
self.have = have
|
||||
|
||||
def compare(self, param):
|
||||
try:
|
||||
result = getattr(self, param)
|
||||
return result
|
||||
except AttributeError:
|
||||
return self.__default(param)
|
||||
|
||||
def __default(self, param):
|
||||
attr1 = getattr(self.want, param)
|
||||
try:
|
||||
attr2 = getattr(self.have, param)
|
||||
if attr1 != attr2:
|
||||
return attr1
|
||||
except AttributeError:
|
||||
return attr1
|
||||
|
||||
@property
|
||||
def address(self):
|
||||
pass
|
||||
|
||||
@property
|
||||
def allow_service(self):
|
||||
"""Returns services formatted for consumption by f5-sdk update
|
||||
|
||||
The BIG-IP endpoint for services takes different values depending on
|
||||
what you want the "allowed services" to be. It can be any of the
|
||||
following
|
||||
|
||||
- a list containing "protocol:port" values
|
||||
- the string "all"
|
||||
- a null value, or None
|
||||
|
||||
This is a convenience function to massage the values the user has
|
||||
supplied so that they are formatted in such a way that BIG-IP will
|
||||
accept them and apply the specified policy.
|
||||
"""
|
||||
if self.want.allow_service is None:
|
||||
return None
|
||||
result = self.want.allow_service
|
||||
if result[0] == 'none' and self.have.allow_service is None:
|
||||
return None
|
||||
elif result[0] == 'all' and self.have.allow_service[0] != 'all':
|
||||
return ['all']
|
||||
elif result[0] == 'none':
|
||||
return []
|
||||
elif self.have.allow_service is None:
|
||||
return result
|
||||
elif set(self.want.allow_service) != set(self.have.allow_service):
|
||||
return result
|
||||
|
||||
@property
|
||||
def netmask(self):
|
||||
if self.want.netmask is None:
|
||||
return None
|
||||
try:
|
||||
address = netaddr.IPNetwork(self.have.ip)
|
||||
if self.want.route_domain is not None:
|
||||
nipnet = "{0}%{1}/{2}".format(address.ip, self.want.route_domain, self.want.netmask)
|
||||
cipnet = "{0}%{1}/{2}".format(address.ip, self.want.route_domain, self.have.netmask)
|
||||
elif self.have.route_domain is not None:
|
||||
nipnet = "{0}%{1}/{2}".format(address.ip, self.have.route_domain, self.want.netmask)
|
||||
cipnet = "{0}%{1}/{2}".format(address.ip, self.have.route_domain, self.have.netmask)
|
||||
else:
|
||||
nipnet = "{0}/{1}".format(address.ip, self.want.netmask)
|
||||
cipnet = "{0}/{1}".format(address.ip, self.have.netmask)
|
||||
if nipnet != cipnet:
|
||||
return nipnet
|
||||
except netaddr.AddrFormatError:
|
||||
raise F5ModuleError(
|
||||
'The provided address/netmask value "{0}" was invalid'.format(self.have.ip)
|
||||
)
|
||||
|
||||
@property
|
||||
def traffic_group(self):
|
||||
if self.want.traffic_group != self.have.traffic_group:
|
||||
return self.want.traffic_group
|
||||
|
||||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
|
@ -734,8 +734,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)
|
||||
|
|
Loading…
Reference in a new issue