Fixes coding conventions, adds a small feature (#39211)

Fixes some coding conventions and adds allowed_addresses to bigip_snmp_trap.
This commit is contained in:
Tim Rupp 2018-04-23 22:06:33 -07:00 committed by GitHub
parent 39e4754fc9
commit 3227143dc8
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
8 changed files with 430 additions and 132 deletions

View file

@ -18,7 +18,7 @@ module: bigip_selfip
short_description: Manage Self-IPs on a BIG-IP system short_description: Manage Self-IPs on a BIG-IP system
description: description:
- Manage Self-IPs on a BIG-IP system. - Manage Self-IPs on a BIG-IP system.
version_added: "2.2" version_added: 2.2
options: options:
address: address:
description: description:
@ -190,27 +190,27 @@ allow_service:
sample: ['igmp:0','tcp:22','udp:53'] sample: ['igmp:0','tcp:22','udp:53']
address: address:
description: The address for the Self IP description: The address for the Self IP
returned: created returned: changed
type: string type: string
sample: 192.0.2.10 sample: 192.0.2.10
name: name:
description: The name of the Self IP description: The name of the Self IP
returned: created, changed and deleted returned: created
type: string type: string
sample: self1 sample: self1
netmask: netmask:
description: The netmask of the Self IP description: The netmask of the Self IP
returned: changed and created returned: changed
type: string type: string
sample: 255.255.255.0 sample: 255.255.255.0
traffic_group: traffic_group:
description: The traffic group that the Self IP is a member of description: The traffic group that the Self IP is a member of
returned: changed and created returned: changed
type: string type: string
sample: traffic-group-local-only sample: traffic-group-local-only
vlan: vlan:
description: The VLAN set on the Self IP description: The VLAN set on the Self IP
returned: changed and created returned: changed
type: string type: string
sample: vlan1 sample: vlan1
''' '''
@ -220,30 +220,25 @@ import re
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
HAS_DEVEL_IMPORTS = False
try: try:
# Sideband repository used for dev
from library.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from library.module_utils.network.f5.common import fqdn_name 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 f5_argument_spec
try: try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError: except ImportError:
# Upstream Ansible
from ansible.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from ansible.module_utils.network.f5.common import fqdn_name 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 f5_argument_spec
try: try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@ -282,16 +277,11 @@ class Parameters(AnsibleF5Parameters):
result = self._filter_params(result) result = self._filter_params(result)
return result return result
def _fqdn_name(self, value):
if value is not None and not value.startswith('/'):
return '/{0}/{1}'.format(self.partition, value)
return value
@property @property
def vlan(self): def vlan(self):
if self._values['vlan'] is None: if self._values['vlan'] is None:
return None return None
return self._fqdn_name(self._values['vlan']) return fq_name(self.partition, self._values['vlan'])
class ModuleParameters(Parameters): class ModuleParameters(Parameters):
@ -318,7 +308,7 @@ class ModuleParameters(Parameters):
def traffic_group(self): def traffic_group(self):
if self._values['traffic_group'] is None: if self._values['traffic_group'] is None:
return None return None
return self._fqdn_name(self._values['traffic_group']) return fq_name(self.partition, self._values['traffic_group'])
@property @property
def route_domain(self): def route_domain(self):

View file

@ -18,7 +18,7 @@ module: bigip_snat_pool
short_description: Manage SNAT pools on a BIG-IP short_description: Manage SNAT pools on a BIG-IP
description: description:
- Manage SNAT pools on a BIG-IP. - Manage SNAT pools on a BIG-IP.
version_added: "2.3" version_added: 2.3
options: options:
members: members:
description: description:
@ -96,30 +96,23 @@ import os
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
HAS_DEVEL_IMPORTS = False
try: try:
# Sideband repository used for dev
from library.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from library.module_utils.network.f5.common import fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
try: try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError: except ImportError:
# Upstream Ansible
from ansible.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from ansible.module_utils.network.f5.common import fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
try: try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError

View file

@ -19,6 +19,16 @@ description:
- Manipulate general SNMP settings on a BIG-IP. - Manipulate general SNMP settings on a BIG-IP.
version_added: 2.4 version_added: 2.4
options: options:
allowed_addresses:
description:
- Configures the IP addresses of the SNMP clients from which the snmpd
daemon accepts requests.
- This value can be hostnames, IP addresses, or IP networks.
- You may specify a single list item of C(default) to set the value back
to the system's default of C(127.0.0.0/8).
- You can remove all allowed addresses by either providing the word C(none), or
by providing the empty string C("").
version_added: 2.6
contact: contact:
description: description:
- Specifies the name of the person who administers the SNMP - Specifies the name of the person who administers the SNMP
@ -51,6 +61,11 @@ options:
description: description:
- Specifies the description of this system's physical location. - Specifies the description of this system's physical location.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
notes:
- Requires the netaddr Python package on the host. This is as easy as
C(pip install netaddr).
requirements:
- netaddr
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
''' '''
@ -101,40 +116,49 @@ location:
returned: changed returned: changed
type: string type: string
sample: US West 1a sample: US West 1a
allowed_addresses:
description: The new allowed addresses for SNMP client connections.
returned: changed
type: list
sample: ['127.0.0.0/8', 'foo.bar.com', '10.10.10.10']
''' '''
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import string_types
HAS_DEVEL_IMPORTS = False
try: try:
# Sideband repository used for dev
from library.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from library.module_utils.network.f5.common import fqdn_name from library.module_utils.network.f5.common import is_valid_hostname
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
try: try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError: except ImportError:
# Upstream Ansible
from ansible.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from ansible.module_utils.network.f5.common import fqdn_name from ansible.module_utils.network.f5.common import is_valid_hostname
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
try: try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
try:
import netaddr
HAS_NETADDR = True
except ImportError:
HAS_NETADDR = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
api_map = { api_map = {
@ -142,21 +166,23 @@ class Parameters(AnsibleF5Parameters):
'authTrap': 'agent_authentication_traps', 'authTrap': 'agent_authentication_traps',
'bigipTraps': 'device_warning_traps', 'bigipTraps': 'device_warning_traps',
'sysLocation': 'location', 'sysLocation': 'location',
'sysContact': 'contact' 'sysContact': 'contact',
'allowedAddresses': 'allowed_addresses'
} }
updatables = [ updatables = [
'agent_status_traps', 'agent_authentication_traps', 'agent_status_traps', 'agent_authentication_traps',
'device_warning_traps', 'location', 'contact' 'device_warning_traps', 'location', 'contact', 'allowed_addresses'
] ]
returnables = [ returnables = [
'agent_status_traps', 'agent_authentication_traps', 'agent_status_traps', 'agent_authentication_traps',
'device_warning_traps', 'location', 'contact' 'device_warning_traps', 'location', 'contact', 'allowed_addresses'
] ]
api_attributes = [ api_attributes = [
'agentTrap', 'authTrap', 'bigipTraps', 'sysLocation', 'sysContact' 'agentTrap', 'authTrap', 'bigipTraps', 'sysLocation', 'sysContact',
'allowedAddresses'
] ]
def to_return(self): def to_return(self):
@ -167,28 +193,121 @@ class Parameters(AnsibleF5Parameters):
return result return result
class ApiParameters(Parameters):
@property
def allowed_addresses(self):
if self._values['allowed_addresses'] is None:
return None
result = list(set(self._values['allowed_addresses']))
result.sort()
return result
class ModuleParameters(Parameters):
@property
def allowed_addresses(self):
if self._values['allowed_addresses'] is None:
return None
result = []
addresses = self._values['allowed_addresses']
if isinstance(addresses, string_types):
if addresses in ['', 'none']:
return []
else:
addresses = [addresses]
if len(addresses) == 1 and addresses[0] in ['default', '']:
result = ['127.0.0.0/8']
return result
for address in addresses:
try:
# Check for valid IPv4 or IPv6 entries
netaddr.IPNetwork(address)
result.append(address)
except netaddr.core.AddrFormatError:
# else fallback to checking reasonably well formatted hostnames
if is_valid_hostname(address):
result.append(str(address))
continue
raise F5ModuleError(
"The provided 'allowed_address' value {0} is not a valid IP or hostname".format(address)
)
result = list(set(result))
result.sort()
return result
class Changes(Parameters): class Changes(Parameters):
pass pass
class UsableChanges(Changes):
pass
class ReportableChanges(Changes):
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 allowed_addresses(self):
if self.want.allowed_addresses is None:
return None
if self.have.allowed_addresses is None:
if self.want.allowed_addresses:
return self.want.allowed_addresses
return None
want = set(self.want.allowed_addresses)
have = set(self.have.allowed_addresses)
if want != have:
result = list(want)
result.sort()
return result
class ModuleManager(object): class ModuleManager(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 = kwargs.get('client', None)
self.have = None self.have = ApiParameters()
self.want = Parameters(params=self.module.params) self.want = ModuleParameters(params=self.module.params)
self.changes = Changes() self.changes = UsableChanges()
def _update_changed_options(self): def _update_changed_options(self):
changed = {} diff = Difference(self.want, self.have)
for key in Parameters.updatables: updatables = Parameters.updatables
if getattr(self.want, key) is not None: changed = dict()
attr1 = getattr(self.want, key) for k in updatables:
attr2 = getattr(self.have, key) change = diff.compare(k)
if attr1 != attr2: if change is None:
changed[key] = attr1 continue
else:
if isinstance(change, dict):
changed.update(change)
else:
changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
@ -200,11 +319,21 @@ class ModuleManager(object):
except iControlUnexpectedHTTPError as e: except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e)) raise F5ModuleError(str(e))
changes = self.changes.to_return() reportable = ReportableChanges(params=self.changes.to_return())
changes = reportable.to_return()
result.update(**changes) result.update(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def should_update(self): def should_update(self):
result = self._update_changed_options() result = self._update_changed_options()
if result: if result:
@ -228,7 +357,7 @@ class ModuleManager(object):
def read_current_from_device(self): def read_current_from_device(self):
resource = self.client.api.tm.sys.snmp.load() resource = self.client.api.tm.sys.snmp.load()
result = resource.attrs result = resource.attrs
return Parameters(params=result) return ApiParameters(params=result)
class ArgumentSpec(object): class ArgumentSpec(object):
@ -246,7 +375,8 @@ class ArgumentSpec(object):
device_warning_traps=dict( device_warning_traps=dict(
choices=self.choices choices=self.choices
), ),
location=dict() location=dict(),
allowed_addresses=dict(type='raw')
) )
self.argument_spec = {} self.argument_spec = {}
self.argument_spec.update(f5_argument_spec) self.argument_spec.update(f5_argument_spec)
@ -262,6 +392,8 @@ def main():
) )
if not HAS_F5SDK: if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required") 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: try:
client = F5Client(**module.params) client = F5Client(**module.params)

View file

@ -27,9 +27,7 @@ options:
description: description:
- Specifies to which Simple Network Management Protocol (SNMP) version - Specifies to which Simple Network Management Protocol (SNMP) version
the trap destination applies. the trap destination applies.
choices: choices: ['1', '2c']
- 1
- 2c
community: community:
description: description:
- Specifies the community name for the trap destination. - Specifies the community name for the trap destination.
@ -45,14 +43,18 @@ options:
- Specifies the name of the trap network. This option is not supported in - Specifies the name of the trap network. This option is not supported in
versions of BIG-IP < 12.1.0. If used on versions < 12.1.0, it will simply versions of BIG-IP < 12.1.0. If used on versions < 12.1.0, it will simply
be ignored. be ignored.
- The value C(default) was removed in BIG-IP version 13.1.0. Specifying this
value when configuring a BIG-IP will cause the module to stop and report
an error. The usual remedy is to choose one of the other options, such as
C(management).
choices: choices:
- other - other
- management - management
- default - default
state: state:
description: description:
- When C(present), ensures that the cloud connector exists. When - When C(present), ensures that the resource exists.
C(absent), ensures that the cloud connector does not exist. - When C(absent), ensures that the resource does not exist.
default: present default: present
choices: choices:
- present - present
@ -132,30 +134,23 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
from distutils.version import LooseVersion from distutils.version import LooseVersion
HAS_DEVEL_IMPORTS = False
try: try:
# Sideband repository used for dev
from library.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from library.module_utils.network.f5.common import fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
try: try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError: except ImportError:
# Upstream Ansible
from ansible.module_utils.network.f5.bigip import HAS_F5SDK 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 F5Client
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 cleanup_tokens
from ansible.module_utils.network.f5.common import fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
try: try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@ -190,7 +185,36 @@ class Parameters(AnsibleF5Parameters):
return result return result
class NetworkedParameters(Parameters): class V3Parameters(Parameters):
updatables = [
'snmp_version', 'community', 'destination', 'port', 'network'
]
returnables = [
'snmp_version', 'community', 'destination', 'port', 'network'
]
api_attributes = [
'version', 'community', 'host', 'port', 'network'
]
@property
def network(self):
if self._values['network'] is None:
return None
network = str(self._values['network'])
if network == 'management':
return 'mgmt'
elif network == 'default':
raise F5ModuleError(
"'default' is not a valid option for this version of BIG-IP. "
"Use either 'management', 'or 'other' instead."
)
else:
return network
class V2Parameters(Parameters):
updatables = [ updatables = [
'snmp_version', 'community', 'destination', 'port', 'network' 'snmp_version', 'community', 'destination', 'port', 'network'
] ]
@ -216,7 +240,7 @@ class NetworkedParameters(Parameters):
return network return network
class NonNetworkedParameters(Parameters): class V1Parameters(Parameters):
updatables = [ updatables = [
'snmp_version', 'community', 'destination', 'port' 'snmp_version', 'community', 'destination', 'port'
] ]
@ -241,20 +265,20 @@ class ModuleManager(object):
self.kwargs = kwargs self.kwargs = kwargs
def exec_module(self): def exec_module(self):
if self.is_version_non_networked(): if self.is_version_without_network():
manager = NonNetworkedManager(**self.kwargs) manager = V1Manager(**self.kwargs)
elif self.is_version_with_default_network():
manager = V2Manager(**self.kwargs)
else: else:
manager = NetworkedManager(**self.kwargs) manager = V3Manager(**self.kwargs)
return manager.exec_module() return manager.exec_module()
def is_version_non_networked(self): def is_version_without_network(self):
"""Checks to see if the TMOS version is less than 13 """Is current BIG-IP version missing "network" value support
Anything less than BIG-IP 13.x does not support users Returns:
on different partitions. bool: True when it is missing. False otherwise.
:return: Bool
""" """
version = self.client.api.tmos_version version = self.client.api.tmos_version
if LooseVersion(version) < LooseVersion('12.1.0'): if LooseVersion(version) < LooseVersion('12.1.0'):
@ -262,6 +286,18 @@ class ModuleManager(object):
else: else:
return False return False
def is_version_with_default_network(self):
"""Is current BIG-IP version missing "default" network value support
Returns:
bool: True when it is missing. False otherwise.
"""
version = self.client.api.tmos_version
if LooseVersion(version) < LooseVersion('13.1.0'):
return True
else:
return False
class BaseManager(object): class BaseManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
@ -365,33 +401,72 @@ class BaseManager(object):
result.delete() result.delete()
class NetworkedManager(BaseManager): class V3Manager(BaseManager):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(NetworkedManager, self).__init__(**kwargs) super(V3Manager, self).__init__(**kwargs)
self.required_resources = [ self.required_resources = [
'version', 'community', 'destination', 'port', 'network' 'version', 'community', 'destination', 'port', 'network'
] ]
self.want = NetworkedParameters(params=self.module.params) self.want = V3Parameters(params=self.module.params)
self.changes = NetworkedParameters() self.changes = V3Parameters()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
for key in NetworkedParameters.returnables: for key in V3Parameters.returnables:
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = NetworkedParameters(params=changed) self.changes = V3Parameters(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
changed = {} changed = {}
for key in NetworkedParameters.updatables: for key in V3Parameters.updatables:
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
attr1 = getattr(self.want, key) attr1 = getattr(self.want, key)
attr2 = getattr(self.have, key) attr2 = getattr(self.have, key)
if attr1 != attr2: if attr1 != attr2:
changed[key] = attr1 changed[key] = attr1
if changed: if changed:
self.changes = NetworkedParameters(params=changed) self.changes = V3Parameters(params=changed)
return True
return False
def read_current_from_device(self):
resource = self.client.api.tm.sys.snmp.traps_s.trap.load(
name=self.want.name,
partition=self.want.partition
)
result = resource.attrs
return V3Parameters(params=result)
class V2Manager(BaseManager):
def __init__(self, *args, **kwargs):
super(V2Manager, self).__init__(**kwargs)
self.required_resources = [
'version', 'community', 'destination', 'port', 'network'
]
self.want = V2Parameters(params=self.module.params)
self.changes = V2Parameters()
def _set_changed_options(self):
changed = {}
for key in V2Parameters.returnables:
if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key)
if changed:
self.changes = V2Parameters(params=changed)
def _update_changed_options(self):
changed = {}
for key in V2Parameters.updatables:
if getattr(self.want, key) is not None:
attr1 = getattr(self.want, key)
attr2 = getattr(self.have, key)
if attr1 != attr2:
changed[key] = attr1
if changed:
self.changes = V2Parameters(params=changed)
return True return True
return False return False
@ -402,7 +477,7 @@ class NetworkedManager(BaseManager):
) )
result = resource.attrs result = resource.attrs
self._ensure_network(result) self._ensure_network(result)
return NetworkedParameters(params=result) return V2Parameters(params=result)
def _ensure_network(self, result): def _ensure_network(self, result):
# BIG-IP's value for "default" is that the key does not # BIG-IP's value for "default" is that the key does not
@ -415,33 +490,33 @@ class NetworkedManager(BaseManager):
result['network'] = 'default' result['network'] = 'default'
class NonNetworkedManager(BaseManager): class V1Manager(BaseManager):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
super(NonNetworkedManager, self).__init__(**kwargs) super(V1Manager, self).__init__(**kwargs)
self.required_resources = [ self.required_resources = [
'version', 'community', 'destination', 'port' 'version', 'community', 'destination', 'port'
] ]
self.want = NonNetworkedParameters(params=self.module.params) self.want = V1Parameters(params=self.module.params)
self.changes = NonNetworkedParameters() self.changes = V1Parameters()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
for key in NonNetworkedParameters.returnables: for key in V1Parameters.returnables:
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = NonNetworkedParameters(params=changed) self.changes = V1Parameters(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
changed = {} changed = {}
for key in NonNetworkedParameters.updatables: for key in V1Parameters.updatables:
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
attr1 = getattr(self.want, key) attr1 = getattr(self.want, key)
attr2 = getattr(self.have, key) attr2 = getattr(self.have, key)
if attr1 != attr2: if attr1 != attr2:
changed[key] = attr1 changed[key] = attr1
if changed: if changed:
self.changes = NonNetworkedParameters(params=changed) self.changes = V1Parameters(params=changed)
return True return True
return False return False
@ -451,7 +526,7 @@ class NonNetworkedManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return NonNetworkedParameters(params=result) return V1Parameters(params=result)
class ArgumentSpec(object): class ArgumentSpec(object):
@ -464,7 +539,7 @@ class ArgumentSpec(object):
snmp_version=dict( snmp_version=dict(
choices=['1', '2c'] choices=['1', '2c']
), ),
community=dict(), community=dict(no_log=True),
destination=dict(), destination=dict(),
port=dict(), port=dict(),
network=dict( network=dict(

View file

@ -21,10 +21,10 @@ from ansible.compat.tests.mock import patch
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_selfip import ApiParameters from library.modules.bigip_selfip import ApiParameters
from library.bigip_selfip import ModuleParameters from library.modules.bigip_selfip import ModuleParameters
from library.bigip_selfip import ModuleManager from library.modules.bigip_selfip import ModuleManager
from library.bigip_selfip import ArgumentSpec from library.modules.bigip_selfip import ArgumentSpec
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 iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
from test.unit.modules.utils import set_module_args from test.unit.modules.utils import set_module_args

View file

@ -20,9 +20,9 @@ from ansible.compat.tests.mock import patch
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_snat_pool import Parameters from library.modules.bigip_snat_pool import Parameters
from library.bigip_snat_pool import ModuleManager from library.modules.bigip_snat_pool import ModuleManager
from library.bigip_snat_pool import ArgumentSpec from library.modules.bigip_snat_pool import ArgumentSpec
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 iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
from test.unit.modules.utils import set_module_args from test.unit.modules.utils import set_module_args

View file

@ -20,15 +20,17 @@ from ansible.compat.tests.mock import patch
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_snmp import Parameters from library.modules.bigip_snmp import ApiParameters
from library.bigip_snmp import ModuleManager from library.modules.bigip_snmp import ModuleParameters
from library.bigip_snmp import ArgumentSpec from library.modules.bigip_snmp import ModuleManager
from library.modules.bigip_snmp import ArgumentSpec
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 iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
from test.unit.modules.utils import set_module_args from test.unit.modules.utils import set_module_args
except ImportError: except ImportError:
try: try:
from ansible.modules.network.f5.bigip_snmp import Parameters from ansible.modules.network.f5.bigip_snmp import ApiParameters
from ansible.modules.network.f5.bigip_snmp import ModuleParameters
from ansible.modules.network.f5.bigip_snmp import ModuleManager from ansible.modules.network.f5.bigip_snmp import ModuleManager
from ansible.modules.network.f5.bigip_snmp import ArgumentSpec from ansible.modules.network.f5.bigip_snmp import ArgumentSpec
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
@ -71,7 +73,7 @@ class TestParameters(unittest.TestCase):
server='localhost', server='localhost',
user='admin' user='admin'
) )
p = Parameters(params=args) p = ModuleParameters(params=args)
assert p.agent_status_traps == 'enabled' assert p.agent_status_traps == 'enabled'
assert p.agent_authentication_traps == 'enabled' assert p.agent_authentication_traps == 'enabled'
assert p.device_warning_traps == 'enabled' assert p.device_warning_traps == 'enabled'
@ -87,7 +89,7 @@ class TestParameters(unittest.TestCase):
server='localhost', server='localhost',
user='admin' user='admin'
) )
p = Parameters(params=args) p = ModuleParameters(params=args)
assert p.agent_status_traps == 'disabled' assert p.agent_status_traps == 'disabled'
assert p.agent_authentication_traps == 'disabled' assert p.agent_authentication_traps == 'disabled'
assert p.device_warning_traps == 'disabled' assert p.device_warning_traps == 'disabled'
@ -100,7 +102,7 @@ class TestParameters(unittest.TestCase):
sysLocation='Lunar orbit', sysLocation='Lunar orbit',
sysContact='Alice@foo.org', sysContact='Alice@foo.org',
) )
p = Parameters(params=args) p = ApiParameters(params=args)
assert p.agent_status_traps == 'enabled' assert p.agent_status_traps == 'enabled'
assert p.agent_authentication_traps == 'enabled' assert p.agent_authentication_traps == 'enabled'
assert p.device_warning_traps == 'enabled' assert p.device_warning_traps == 'enabled'
@ -113,7 +115,7 @@ class TestParameters(unittest.TestCase):
authTrap='disabled', authTrap='disabled',
bigipTraps='disabled', bigipTraps='disabled',
) )
p = Parameters(params=args) p = ApiParameters(params=args)
assert p.agent_status_traps == 'disabled' assert p.agent_status_traps == 'disabled'
assert p.agent_authentication_traps == 'disabled' assert p.agent_authentication_traps == 'disabled'
assert p.device_warning_traps == 'disabled' assert p.device_warning_traps == 'disabled'
@ -134,7 +136,7 @@ class TestManager(unittest.TestCase):
# Configure the parameters that would be returned by querying the # Configure the parameters that would be returned by querying the
# remote device # remote device
current = Parameters( current = ApiParameters(
params=dict( params=dict(
agent_status_traps='disabled' agent_status_traps='disabled'
) )
@ -154,3 +156,108 @@ class TestManager(unittest.TestCase):
assert results['changed'] is True assert results['changed'] is True
assert results['agent_status_traps'] == 'enabled' assert results['agent_status_traps'] == 'enabled'
def test_update_allowed_addresses(self, *args):
set_module_args(dict(
allowed_addresses=[
'127.0.0.0/8',
'10.10.10.10',
'foo',
'baz.foo.com'
],
password='passsword',
server='localhost',
user='admin'
))
# Configure the parameters that would be returned by querying the
# remote device
current = ApiParameters(
params=dict(
allowed_addresses=['127.0.0.0/8']
)
)
module = AnsibleModule(
argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode
)
mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen
mm.update_on_device = Mock(return_value=True)
mm.read_current_from_device = Mock(return_value=current)
results = mm.exec_module()
assert results['changed'] is True
assert len(results['allowed_addresses']) == 4
assert results['allowed_addresses'] == [
'10.10.10.10', '127.0.0.0/8', 'baz.foo.com', 'foo'
]
def test_update_allowed_addresses_default(self, *args):
set_module_args(dict(
allowed_addresses=[
'default'
],
password='passsword',
server='localhost',
user='admin'
))
# Configure the parameters that would be returned by querying the
# remote device
current = ApiParameters(
params=dict(
allowed_addresses=['10.0.0.0']
)
)
module = AnsibleModule(
argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode
)
mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen
mm.update_on_device = Mock(return_value=True)
mm.read_current_from_device = Mock(return_value=current)
results = mm.exec_module()
assert results['changed'] is True
assert len(results['allowed_addresses']) == 1
assert results['allowed_addresses'] == ['127.0.0.0/8']
def test_update_allowed_addresses_empty(self, *args):
set_module_args(dict(
allowed_addresses=[''],
password='passsword',
server='localhost',
user='admin'
))
# Configure the parameters that would be returned by querying the
# remote device
current = ApiParameters(
params=dict(
allowed_addresses=['10.0.0.0']
)
)
module = AnsibleModule(
argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode
)
mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen
mm.update_on_device = Mock(return_value=True)
mm.read_current_from_device = Mock(return_value=current)
results = mm.exec_module()
assert results['changed'] is True
assert len(results['allowed_addresses']) == 1
assert results['allowed_addresses'] == ['127.0.0.0/8']

View file

@ -21,22 +21,22 @@ from ansible.compat.tests.mock import DEFAULT
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_snmp_trap import NetworkedParameters from library.modules.bigip_snmp_trap import V2Parameters
from library.bigip_snmp_trap import NonNetworkedParameters from library.modules.bigip_snmp_trap import V1Parameters
from library.bigip_snmp_trap import ModuleManager from library.modules.bigip_snmp_trap import ModuleManager
from library.bigip_snmp_trap import NetworkedManager from library.modules.bigip_snmp_trap import V2Manager
from library.bigip_snmp_trap import NonNetworkedManager from library.modules.bigip_snmp_trap import V1Manager
from library.bigip_snmp_trap import ArgumentSpec from library.modules.bigip_snmp_trap import ArgumentSpec
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 iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
from test.unit.modules.utils import set_module_args from test.unit.modules.utils import set_module_args
except ImportError: except ImportError:
try: try:
from ansible.modules.network.f5.bigip_snmp_trap import NetworkedParameters from ansible.modules.network.f5.bigip_snmp_trap import V2Parameters
from ansible.modules.network.f5.bigip_snmp_trap import NonNetworkedParameters from ansible.modules.network.f5.bigip_snmp_trap import V1Parameters
from ansible.modules.network.f5.bigip_snmp_trap import ModuleManager from ansible.modules.network.f5.bigip_snmp_trap import ModuleManager
from ansible.modules.network.f5.bigip_snmp_trap import NetworkedManager from ansible.modules.network.f5.bigip_snmp_trap import V2Manager
from ansible.modules.network.f5.bigip_snmp_trap import NonNetworkedManager from ansible.modules.network.f5.bigip_snmp_trap import V1Manager
from ansible.modules.network.f5.bigip_snmp_trap import ArgumentSpec from ansible.modules.network.f5.bigip_snmp_trap import ArgumentSpec
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 iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@ -79,7 +79,7 @@ class TestParameters(unittest.TestCase):
server='localhost', server='localhost',
user='admin' user='admin'
) )
p = NetworkedParameters(params=args) p = V2Parameters(params=args)
assert p.name == 'foo' assert p.name == 'foo'
assert p.snmp_version == '1' assert p.snmp_version == '1'
assert p.community == 'public' assert p.community == 'public'
@ -99,7 +99,7 @@ class TestParameters(unittest.TestCase):
server='localhost', server='localhost',
user='admin' user='admin'
) )
p = NonNetworkedParameters(params=args) p = V1Parameters(params=args)
assert p.name == 'foo' assert p.name == 'foo'
assert p.snmp_version == '1' assert p.snmp_version == '1'
assert p.community == 'public' assert p.community == 'public'
@ -116,7 +116,7 @@ class TestParameters(unittest.TestCase):
version=1, version=1,
port=1000 port=1000
) )
p = NetworkedParameters(params=args) p = V2Parameters(params=args)
assert p.name == 'foo' assert p.name == 'foo'
assert p.snmp_version == '1' assert p.snmp_version == '1'
assert p.community == 'public' assert p.community == 'public'
@ -149,17 +149,18 @@ class TestManager(unittest.TestCase):
) )
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(module=module) m0 = ModuleManager(module=module)
mm.is_version_non_networked = Mock(return_value=False) m0.is_version_without_network = Mock(return_value=False)
m0.is_version_with_default_network = Mock(return_value=True)
patches = dict( patches = dict(
create_on_device=DEFAULT, create_on_device=DEFAULT,
exists=DEFAULT exists=DEFAULT
) )
with patch.multiple(NetworkedManager, **patches) as mo: with patch.multiple(V2Manager, **patches) as mo:
mo['create_on_device'].side_effect = Mock(return_value=True) mo['create_on_device'].side_effect = Mock(return_value=True)
mo['exists'].side_effect = Mock(return_value=False) mo['exists'].side_effect = Mock(return_value=False)
results = mm.exec_module() results = m0.exec_module()
assert results['changed'] is True assert results['changed'] is True
assert results['port'] == 1000 assert results['port'] == 1000
@ -183,17 +184,17 @@ class TestManager(unittest.TestCase):
) )
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(module=module) m0 = ModuleManager(module=module)
mm.is_version_non_networked = Mock(return_value=True) m0.is_version_without_network = Mock(return_value=True)
patches = dict( patches = dict(
create_on_device=DEFAULT, create_on_device=DEFAULT,
exists=DEFAULT exists=DEFAULT
) )
with patch.multiple(NonNetworkedManager, **patches) as mo: with patch.multiple(V1Manager, **patches) as mo:
mo['create_on_device'].side_effect = Mock(return_value=True) mo['create_on_device'].side_effect = Mock(return_value=True)
mo['exists'].side_effect = Mock(return_value=False) mo['exists'].side_effect = Mock(return_value=False)
results = mm.exec_module() results = m0.exec_module()
assert results['changed'] is True assert results['changed'] is True
assert results['port'] == 1000 assert results['port'] == 1000