Various fixes and changes for F5 (#34817)

Primarily, this patch contains refactors to remove tracebacks that
are generated when libraries are missing. There is also,

* Removed re-def of cleanup_tokens.
* Changed parameter args to be keywords.
* Changed imports to include new module_util locations.
* Imports also include developing (sideband) module_util locations.
* Changed to using F5Client and plain AnsibleModule to prevent tracebacks caused by missing libraries.
* Removed init and update methods from most Parameter classes (optimization) as its now included in module_utils.
* Changed module and module param references to take into account the new self.module arg. Minor bug fixes made during this refactor.
pull/34820/head
Tim Rupp 7 years ago committed by GitHub
parent 085a250575
commit eace686044
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -44,19 +44,18 @@ options:
the virtual address and enables it. If C(enabled), enable the virtual the virtual address and enables it. If C(enabled), enable the virtual
address if it exists. If C(disabled), create the virtual address if address if it exists. If C(disabled), create the virtual address if
needed, and set state to C(disabled). needed, and set state to C(disabled).
required: False
default: present default: present
choices: choices:
- present - present
- absent - absent
- enabled - enabled
- disabled - disabled
notes: partition:
- Requires the f5-sdk Python package on the host. This is as easy as description:
pip install f5-sdk. - Device partition to manage resources on.
default: Common
version_added: 2.5
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements:
- f5-sdk
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
''' '''
@ -105,14 +104,37 @@ location:
sample: 222 West 23rd sample: 222 West 23rd
''' '''
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import AnsibleF5Parameters from ansible.module_utils.basic import env_fallback
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError HAS_DEVEL_IMPORTS = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -258,9 +280,10 @@ class Difference(object):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.pop('module', None)
self.want = ModuleParameters(params=self.client.module.params) self.client = kwargs.pop('client', None)
self.want = ModuleParameters(params=self.module.params)
self.have = ApiParameters() self.have = ApiParameters()
self.changes = UsableChanges() self.changes = UsableChanges()
@ -277,7 +300,7 @@ class ModuleManager(object):
except iControlUnexpectedHTTPError as e: except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e)) raise F5ModuleError(str(e))
reportable = ReportableChanges(self.changes.to_return()) reportable = ReportableChanges(params=self.changes.to_return())
changes = reportable.to_return() changes = reportable.to_return()
result.update(**changes) result.update(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
@ -287,7 +310,7 @@ class ModuleManager(object):
def _announce_deprecations(self, result): def _announce_deprecations(self, result):
warnings = result.pop('__warnings', []) warnings = result.pop('__warnings', [])
for warning in warnings: for warning in warnings:
self.client.module.deprecate( self.module.deprecate(
msg=warning['msg'], msg=warning['msg'],
version=warning['version'] version=warning['version']
) )
@ -306,7 +329,7 @@ class ModuleManager(object):
else: else:
changed[k] = change changed[k] = change
if changed: if changed:
self.changes = UsableChanges(changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
@ -334,7 +357,7 @@ class ModuleManager(object):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return ApiParameters(result) return ApiParameters(params=result)
def exists(self): def exists(self):
result = self.client.api.tm.gtm.datacenters.datacenter.exists( result = self.client.api.tm.gtm.datacenters.datacenter.exists(
@ -347,7 +370,7 @@ class ModuleManager(object):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -363,7 +386,7 @@ class ModuleManager(object):
def create(self): def create(self):
self.have = ApiParameters() self.have = ApiParameters()
self.should_update() self.should_update()
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
if self.exists(): if self.exists():
@ -380,7 +403,7 @@ class ModuleManager(object):
) )
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -398,50 +421,44 @@ class ModuleManager(object):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
contact=dict(), contact=dict(),
description=dict(), description=dict(),
location=dict(), location=dict(),
name=dict(required=True), name=dict(required=True),
state=dict( state=dict(
type='str',
default='present', default='present',
choices=['present', 'absent', 'disabled', 'enabled'] choices=['present', 'absent', 'disabled', 'enabled']
),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
) )
self.f5_product_name = 'bigip' self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(ex))
if __name__ == '__main__': if __name__ == '__main__':

@ -33,12 +33,7 @@ options:
- Perform regex filter of response. Filtering is done on the name of - Perform regex filter of response. Filtering is done on the name of
the resource. Valid filters are anything that can be provided to the resource. Valid filters are anything that can be provided to
Python's C(re) module. Python's C(re) module.
notes:
- Requires the f5-sdk Python package on the host. This is as easy as
pip install f5-sdk
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements:
- f5-sdk
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
''' '''
@ -173,18 +168,45 @@ virtual_server:
import re import re
from ansible.module_utils.basic import AnsibleModule
HAS_DEVEL_IMPORTS = False
try:
# Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError:
# Upstream Ansible
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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
try: try:
import json import json
except ImportError: except ImportError:
import simplejson as json import simplejson as json
from ansible.module_utils.f5_utils import AnsibleF5Client
from ansible.module_utils.f5_utils import AnsibleF5Parameters
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError
from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
from collections import defaultdict
from distutils.version import LooseVersion from distutils.version import LooseVersion
try: try:
@ -195,8 +217,11 @@ except ImportError:
class BaseManager(object): class BaseManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.kwargs = kwargs
self.types = dict( self.types = dict(
a_s='a', a_s='a',
aaaas='aaaa', aaaas='aaaa',
@ -269,10 +294,6 @@ class TypedManager(BaseManager):
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
def __init__(self, params=None):
super(Parameters, self).__init__(params)
self._values['__warnings'] = []
@property @property
def include(self): def include(self):
requested = self._values['include'] requested = self._values['include']
@ -296,36 +317,7 @@ class Parameters(AnsibleF5Parameters):
return requested return requested
class BaseParameters(AnsibleF5Parameters): class BaseParameters(Parameters):
def __init__(self, params=None):
self._values = defaultdict(lambda: None)
if params:
self.update(params=params)
self._values['__warnings'] = []
def update(self, params=None):
if params:
for k, v in iteritems(params):
if self.api_map is not None and k in self.api_map:
map_key = self.api_map[k]
else:
map_key = k
# Handle weird API parameters like `dns.proxy.__iter__` by
# using a map provided by the module developer
class_attr = getattr(type(self), map_key, None)
if isinstance(class_attr, property):
# There is a mapped value for the api_map key
if class_attr.fset is None:
# If the mapped value does not have an associated setter
self._values[map_key] = v
else:
# The mapped value has a setter
setattr(self, map_key, v)
else:
# If the mapped value is not a @property
self._values[map_key] = v
@property @property
def enabled(self): def enabled(self):
if self._values['enabled'] is None: if self._values['enabled'] is None:
@ -697,6 +689,12 @@ class ServerParameters(BaseParameters):
class PoolFactManager(BaseManager): class PoolFactManager(BaseManager):
def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
super(PoolFactManager, self).__init__(**kwargs)
self.kwargs = kwargs
def exec_module(self): def exec_module(self):
if self.version_is_less_than_12(): if self.version_is_less_than_12():
manager = self.get_manager('untyped') manager = self.get_manager('untyped')
@ -708,15 +706,17 @@ class PoolFactManager(BaseManager):
def get_manager(self, type): def get_manager(self, type):
if type == 'typed': if type == 'typed':
return TypedPoolFactManager(self.client) return TypedPoolFactManager(**self.kwargs)
elif type == 'untyped': elif type == 'untyped':
return UntypedPoolFactManager(self.client) return UntypedPoolFactManager(**self.kwargs)
class TypedPoolFactManager(TypedManager): class TypedPoolFactManager(TypedManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(TypedPoolFactManager, self).__init__(client) self.module = kwargs.get('module', None)
self.want = PoolParameters(self.client.module.params) self.client = kwargs.get('client', None)
super(TypedPoolFactManager, self).__init__(**kwargs)
self.want = PoolParameters(params=self.module.params)
def read_facts(self, collection): def read_facts(self, collection):
results = [] results = []
@ -740,9 +740,11 @@ class TypedPoolFactManager(TypedManager):
class UntypedPoolFactManager(UntypedManager): class UntypedPoolFactManager(UntypedManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(UntypedPoolFactManager, self).__init__(client) self.client = kwargs.get('client', None)
self.want = PoolParameters(self.client.module.params) self.module = kwargs.get('module', None)
super(UntypedPoolFactManager, self).__init__(**kwargs)
self.want = PoolParameters(params=self.module.params)
def read_facts(self): def read_facts(self):
results = [] results = []
@ -775,15 +777,17 @@ class WideIpFactManager(BaseManager):
def get_manager(self, type): def get_manager(self, type):
if type == 'typed': if type == 'typed':
return TypedWideIpFactManager(self.client) return TypedWideIpFactManager(**self.kwargs)
elif type == 'untyped': elif type == 'untyped':
return UntypedWideIpFactManager(self.client) return UntypedWideIpFactManager(**self.kwargs)
class TypedWideIpFactManager(TypedManager): class TypedWideIpFactManager(TypedManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(TypedWideIpFactManager, self).__init__(client) self.client = kwargs.get('client', None)
self.want = WideIpParameters(self.client.module.params) self.module = kwargs.get('module', None)
super(TypedWideIpFactManager, self).__init__(**kwargs)
self.want = WideIpParameters(params=self.module.params)
def read_facts(self, collection): def read_facts(self, collection):
results = [] results = []
@ -806,9 +810,11 @@ class TypedWideIpFactManager(TypedManager):
class UntypedWideIpFactManager(UntypedManager): class UntypedWideIpFactManager(UntypedManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(UntypedWideIpFactManager, self).__init__(client) self.client = kwargs.get('client', None)
self.want = WideIpParameters(self.client.module.params) self.module = kwargs.get('module', None)
super(UntypedWideIpFactManager, self).__init__(**kwargs)
self.want = WideIpParameters(params=self.module.params)
def read_facts(self): def read_facts(self):
results = [] results = []
@ -829,9 +835,11 @@ class UntypedWideIpFactManager(UntypedManager):
class ServerFactManager(UntypedManager): class ServerFactManager(UntypedManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(ServerFactManager, self).__init__(client) self.client = kwargs.get('client', None)
self.want = ServerParameters(self.client.module.params) self.module = kwargs.get('module', None)
super(ServerFactManager, self).__init__(**kwargs)
self.want = ServerParameters(params=self.module.params)
def exec_module(self): def exec_module(self):
facts = super(ServerFactManager, self).exec_module() facts = super(ServerFactManager, self).exec_module()
@ -857,9 +865,11 @@ class ServerFactManager(UntypedManager):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.want = Parameters(self.client.module.params) self.client = kwargs.get('client', None)
self.kwargs = kwargs
self.want = Parameters(params=self.module.params)
def exec_module(self): def exec_module(self):
if not self.gtm_provisioned(): if not self.gtm_provisioned():
@ -889,7 +899,7 @@ class ModuleManager(object):
if self.want: if self.want:
warnings += self.want._values.get('__warnings', []) warnings += self.want._values.get('__warnings', [])
for warning in warnings: for warning in warnings:
self.client.module.deprecate( self.module.deprecate(
msg=warning['msg'], msg=warning['msg'],
version=warning['version'] version=warning['version']
) )
@ -903,11 +913,11 @@ class ModuleManager(object):
def get_manager(self, which): def get_manager(self, which):
if 'pool' == which: if 'pool' == which:
return PoolFactManager(self.client) return PoolFactManager(**self.kwargs)
if 'wide_ip' == which: if 'wide_ip' == which:
return WideIpFactManager(self.client) return WideIpFactManager(**self.kwargs)
if 'server' == which: if 'server' == which:
return ServerFactManager(self.client) return ServerFactManager(**self.kwargs)
def gtm_provisioned(self): def gtm_provisioned(self):
resource = self.client.api.tm.sys.dbs.db.load( resource = self.client.api.tm.sys.dbs.db.load(
@ -921,43 +931,34 @@ class ModuleManager(object):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = False self.supports_check_mode = False
self.argument_spec = dict( argument_spec = dict(
include=dict(type='list', required=True), include=dict(type='list', required=True),
filter=dict(type='str', required=False) filter=dict()
)
self.f5_product_name = 'bigip'
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
) )
resource.delete() self.argument_spec = {}
except Exception: self.argument_spec.update(f5_argument_spec)
pass self.argument_spec.update(argument_spec)
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name,
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(ex))
if __name__ == '__main__': if __name__ == '__main__':

@ -123,13 +123,10 @@ options:
default: Common default: Common
version_added: 2.5 version_added: 2.5
notes: notes:
- Requires the f5-sdk Python package on the host. This is as easy as
pip install f5-sdk.
- Requires the netaddr Python package on the host. This is as easy as - Requires the netaddr Python package on the host. This is as easy as
pip install netaddr. pip install netaddr.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements: requirements:
- f5-sdk
- netaddr - netaddr
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
@ -177,18 +174,38 @@ EXAMPLES = r'''
delegate_to: localhost delegate_to: localhost
''' '''
from ansible.module_utils.f5_utils import AnsibleF5Client
from ansible.module_utils.f5_utils import AnsibleF5Parameters
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError
from ansible.module_utils.six import iteritems
from collections import defaultdict
from distutils.version import LooseVersion from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
HAS_DEVEL_IMPORTS = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
try: try:
@ -223,36 +240,6 @@ class Parameters(AnsibleF5Parameters):
'fallbackIpv4', 'fallbackIpv6', 'fallbackIp', 'enabled', 'disabled' 'fallbackIpv4', 'fallbackIpv6', 'fallbackIp', 'enabled', 'disabled'
] ]
def __init__(self, params=None):
self._values = defaultdict(lambda: None)
self._values['__warnings'] = []
if params:
self.update(params=params)
def update(self, params=None):
if params:
for k, v in iteritems(params):
if self.api_map is not None and k in self.api_map:
map_key = self.api_map[k]
else:
map_key = k
# Handle weird API parameters like `dns.proxy.__iter__` by
# using a map provided by the module developer
class_attr = getattr(type(self), map_key, None)
if isinstance(class_attr, property):
# There is a mapped value for the api_map key
if class_attr.fset is None:
# If the mapped value does not have
# an associated setter
self._values[map_key] = v
else:
# The mapped value has a setter
setattr(self, map_key, v)
else:
# If the mapped value is not a @property
self._values[map_key] = v
def to_return(self): def to_return(self):
result = {} result = {}
for returnable in self.returnables: for returnable in self.returnables:
@ -260,16 +247,6 @@ class Parameters(AnsibleF5Parameters):
result = self._filter_params(result) result = self._filter_params(result)
return result return result
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
@property @property
def collection(self): def collection(self):
type_map = dict( type_map = dict(
@ -377,8 +354,9 @@ class Difference(object):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.kwargs = kwargs
self.client = kwargs.get('client', None)
def exec_module(self): def exec_module(self):
if not self.gtm_provisioned(): if not self.gtm_provisioned():
@ -393,9 +371,9 @@ class ModuleManager(object):
def get_manager(self, type): def get_manager(self, type):
if type == 'typed': if type == 'typed':
return TypedManager(self.client) return TypedManager(**self.kwargs)
elif type == 'untyped': elif type == 'untyped':
return UntypedManager(self.client) return UntypedManager(**self.kwargs)
def version_is_less_than_12(self): def version_is_less_than_12(self):
version = self.client.api.tmos_version version = self.client.api.tmos_version
@ -414,10 +392,11 @@ class ModuleManager(object):
class BaseManager(object): class BaseManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.have = None self.have = None
self.want = Parameters(self.client.module.params) self.want = Parameters(params=self.module.params)
self.changes = Changes() self.changes = Changes()
def _set_changed_options(self): def _set_changed_options(self):
@ -426,7 +405,7 @@ class BaseManager(object):
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 = Changes(changed) self.changes = Changes(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -442,7 +421,7 @@ class BaseManager(object):
else: else:
changed[k] = change changed[k] = change
if changed: if changed:
self.changes = Changes(changed) self.changes = Changes(params=changed)
return True return True
return False return False
@ -485,7 +464,7 @@ class BaseManager(object):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -496,7 +475,7 @@ class BaseManager(object):
elif self.want.state in ['present', 'enabled']: elif self.want.state in ['present', 'enabled']:
self.want.update({'enabled': True}) self.want.update({'enabled': True})
self._set_changed_options() self._set_changed_options()
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
if self.exists(): if self.exists():
@ -505,7 +484,7 @@ class BaseManager(object):
raise F5ModuleError("Failed to create the GTM pool") raise F5ModuleError("Failed to create the GTM pool")
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -514,8 +493,8 @@ class BaseManager(object):
class TypedManager(BaseManager): class TypedManager(BaseManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(TypedManager, self).__init__(client) super(TypedManager, self).__init__(**kwargs)
if self.want.type is None: if self.want.type is None:
raise F5ModuleError( raise F5ModuleError(
"The 'type' option is required for BIG-IP instances " "The 'type' option is required for BIG-IP instances "
@ -567,7 +546,7 @@ class TypedManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = result.attrs result = result.attrs
return Parameters(result) return Parameters(params=result)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.want.api_params()
@ -614,7 +593,7 @@ class UntypedManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return Parameters(result) return Parameters(params=result)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.want.api_params()
@ -655,7 +634,7 @@ class ArgumentSpec(object):
'a', 'aaaa', 'cname', 'mx', 'naptr', 'srv' 'a', 'aaaa', 'cname', 'mx', 'naptr', 'srv'
] ]
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
name=dict(required=True), name=dict(required=True),
state=dict( state=dict(
default='present', default='present',
@ -673,50 +652,44 @@ class ArgumentSpec(object):
fallback_ip=dict(), fallback_ip=dict(),
type=dict( type=dict(
choices=self.types choices=self.types
),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
) )
self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
self.required_if = [ self.required_if = [
['preferred_lb_method', 'fallback-ip', ['fallback_ip']], ['preferred_lb_method', 'fallback-ip', ['fallback_ip']],
['fallback_lb_method', 'fallback-ip', ['fallback_ip']], ['fallback_lb_method', 'fallback-ip', ['fallback_ip']],
['alternate_lb_method', 'fallback-ip', ['fallback_ip']] ['alternate_lb_method', 'fallback-ip', ['fallback_ip']]
] ]
self.f5_product_name = 'bigip'
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
if not HAS_NETADDR:
raise F5ModuleError("The python netaddr module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode,
f5_product_name=spec.f5_product_name,
required_if=spec.required_if required_if=spec.required_if
) )
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: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(ex))
if __name__ == '__main__': if __name__ == '__main__':

@ -102,15 +102,9 @@ options:
partition: partition:
description: description:
- Device partition to manage resources on. - Device partition to manage resources on.
required: False default: Common
default: 'Common'
version_added: 2.5 version_added: 2.5
notes:
- Requires the f5-sdk Python package on the host. This is as easy as
pip install f5-sdk.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements:
- f5-sdk
author: author:
- Robert Teller - Robert Teller
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
@ -188,26 +182,48 @@ datacenter:
sample: datacenter01 sample: datacenter01
''' '''
from ansible.module_utils.f5_utils import AnsibleF5Client
from ansible.module_utils.f5_utils import AnsibleF5Parameters
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError
from ansible.module_utils.six import iteritems
from collections import defaultdict
from distutils.version import LooseVersion from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
HAS_DEVEL_IMPORTS = False
try: try:
from collections import OrderedDict # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try: try:
from ordereddict import OrderedDict from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
pass HAS_F5SDK = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from collections import OrderedDict
except ImportError: except ImportError:
HAS_F5SDK = False try:
from ordereddict import OrderedDict
except ImportError:
pass
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
@ -233,47 +249,6 @@ class Parameters(AnsibleF5Parameters):
'datacenter', 'enabled', 'disabled' 'datacenter', 'enabled', 'disabled'
] ]
def __init__(self, params=None):
self._values = defaultdict(lambda: None)
self._values['__warnings'] = []
if params:
self.update(params=params)
def update(self, params=None):
if params:
for k, v in iteritems(params):
if self.api_map is not None and k in self.api_map:
map_key = self.api_map[k]
else:
map_key = k
# Handle weird API parameters like `dns.proxy.__iter__` by
# using a map provided by the module developer
class_attr = getattr(type(self), map_key, None)
if isinstance(class_attr, property):
# There is a mapped value for the api_map key
if class_attr.fset is None:
# If the mapped value does not have
# an associated setter
self._values[map_key] = v
else:
# The mapped value has a setter
setattr(self, map_key, v)
else:
# If the mapped value is not a @property
self._values[map_key] = v
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if api_attribute in self.api_map:
result[api_attribute] = getattr(
self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
def _fqdn_name(self, value): def _fqdn_name(self, value):
if value is not None and not value.startswith('/'): if value is not None and not value.startswith('/'):
return '/{0}/{1}'.format(self.partition, value) return '/{0}/{1}'.format(self.partition, value)
@ -549,8 +524,10 @@ class Difference(object):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.kwargs = kwargs
def exec_module(self): def exec_module(self):
if not self.gtm_provisioned(): if not self.gtm_provisioned():
@ -565,9 +542,9 @@ class ModuleManager(object):
def get_manager(self, type): def get_manager(self, type):
if type == 'v1': if type == 'v1':
return V1Manager(self.client) return V1Manager(**self.kwargs)
elif type == 'v2': elif type == 'v2':
return V2Manager(self.client) return V2Manager(**self.kwargs)
def version_is_less_than(self, version): def version_is_less_than(self, version):
tmos_version = self.client.api.tmos_version tmos_version = self.client.api.tmos_version
@ -586,10 +563,11 @@ class ModuleManager(object):
class BaseManager(object): class BaseManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.want = ModuleParameters(params=self.client.module.params) self.client = kwargs.get('client', None)
self.want.update(dict(client=client)) self.want = ModuleParameters(params=self.module.params)
self.want.update(dict(client=self.client))
self.have = ApiParameters() self.have = ApiParameters()
self.changes = UsableChanges() self.changes = UsableChanges()
@ -599,7 +577,7 @@ class BaseManager(object):
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 = UsableChanges(changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -616,7 +594,7 @@ class BaseManager(object):
else: else:
changed[k] = change changed[k] = change
if changed: if changed:
self.changes = UsableChanges(changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
@ -633,7 +611,7 @@ class BaseManager(object):
except iControlUnexpectedHTTPError as e: except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e)) raise F5ModuleError(str(e))
reportable = ReportableChanges(self.changes.to_return()) reportable = ReportableChanges(params=self.changes.to_return())
changes = reportable.to_return() changes = reportable.to_return()
result.update(**changes) result.update(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
@ -643,7 +621,7 @@ class BaseManager(object):
def _announce_deprecations(self, result): def _announce_deprecations(self, result):
warnings = result.pop('__warnings', []) warnings = result.pop('__warnings', [])
for warning in warnings: for warning in warnings:
self.client.module.deprecate( self.module.deprecate(
msg=warning['msg'], msg=warning['msg'],
version=warning['version'] version=warning['version']
) )
@ -673,7 +651,7 @@ class BaseManager(object):
) )
self._assign_creation_defaults() self._assign_creation_defaults()
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
if self.exists(): if self.exists():
@ -693,7 +671,7 @@ class BaseManager(object):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -704,7 +682,7 @@ class BaseManager(object):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return ApiParameters(result) return ApiParameters(params=result)
def should_update(self): def should_update(self):
result = self._update_changed_options() result = self._update_changed_options()
@ -727,7 +705,7 @@ class BaseManager(object):
return changed return changed
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -795,7 +773,7 @@ class ArgumentSpec(object):
'redundant-bigip', 'windows-2000-server' 'redundant-bigip', 'windows-2000-server'
] ]
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
state=dict( state=dict(
default='present', default='present',
choices=self.states, choices=self.states,
@ -814,39 +792,36 @@ class ArgumentSpec(object):
), ),
devices=dict( devices=dict(
type='list' type='list'
),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
) )
self.f5_product_name = 'bigip' self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
client.module.exit_json(**results) cleanup_tokens(client)
except F5ModuleError as e: module.exit_json(**results)
client.module.fail_json(msg=str(e)) except F5ModuleError as ex:
cleanup_tokens(client)
module.fail_json(msg=str(ex))
if __name__ == '__main__': if __name__ == '__main__':
main() main()

@ -87,17 +87,11 @@ options:
- Ratio for the pool. - Ratio for the pool.
- The system uses this number with the Ratio load balancing method. - The system uses this number with the Ratio load balancing method.
version_added: 2.5 version_added: 2.5
notes:
- Requires the f5-sdk Python package on the host. This is as easy as pip
install f5-sdk.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements:
- f5-sdk
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
''' '''
EXAMPLES = r''' EXAMPLES = r'''
- name: Set lb method - name: Set lb method
bigip_gtm_wide_ip: bigip_gtm_wide_ip:
@ -124,16 +118,40 @@ state:
import re import re
from ansible.module_utils.f5_utils import AnsibleF5Client
from ansible.module_utils.f5_utils import AnsibleF5Parameters
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
from distutils.version import LooseVersion from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
HAS_DEVEL_IMPORTS = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -145,16 +163,6 @@ class Parameters(AnsibleF5Parameters):
returnables = ['name', 'pool_lb_method', 'state', 'pools'] returnables = ['name', 'pool_lb_method', 'state', 'pools']
api_attributes = ['poolLbMode', 'enabled', 'disabled', 'pools'] api_attributes = ['poolLbMode', 'enabled', 'disabled', 'pools']
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
def _fqdn_name(self, value): def _fqdn_name(self, value):
if value is not None and not value.startswith('/'): if value is not None and not value.startswith('/'):
return '/{0}/{1}'.format(self.partition, value) return '/{0}/{1}'.format(self.partition, value)
@ -369,8 +377,10 @@ class Difference(object):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.kwargs = kwargs
def exec_module(self): def exec_module(self):
if self.version_is_less_than_12(): if self.version_is_less_than_12():
@ -381,9 +391,9 @@ class ModuleManager(object):
def get_manager(self, type): def get_manager(self, type):
if type == 'typed': if type == 'typed':
return TypedManager(self.client) return TypedManager(**self.kwargs)
elif type == 'untyped': elif type == 'untyped':
return UntypedManager(self.client) return UntypedManager(**self.kwargs)
def version_is_less_than_12(self): def version_is_less_than_12(self):
version = self.client.api.tmos_version version = self.client.api.tmos_version
@ -394,9 +404,10 @@ class ModuleManager(object):
class BaseManager(object): class BaseManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.want = ModuleParameters(params=self.client.module.params) self.client = kwargs.get('client', None)
self.want = ModuleParameters(params=self.module.params)
self.have = ApiParameters() self.have = ApiParameters()
self.changes = UsableChanges() self.changes = UsableChanges()
@ -406,7 +417,7 @@ class BaseManager(object):
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 = UsableChanges(changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -422,7 +433,7 @@ class BaseManager(object):
else: else:
changed[k] = change changed[k] = change
if changed: if changed:
self.changes = UsableChanges(changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
@ -439,7 +450,7 @@ class BaseManager(object):
except iControlUnexpectedHTTPError as e: except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e)) raise F5ModuleError(str(e))
reportable = ReportableChanges(self.changes.to_return()) reportable = ReportableChanges(params=self.changes.to_return())
changes = reportable.to_return() changes = reportable.to_return()
result.update(**changes) result.update(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
@ -449,7 +460,7 @@ class BaseManager(object):
def _announce_deprecations(self, result): def _announce_deprecations(self, result):
warnings = result.pop('__warnings', []) warnings = result.pop('__warnings', [])
for warning in warnings: for warning in warnings:
self.client.module.deprecate( self.module.deprecate(
msg=warning['msg'], msg=warning['msg'],
version=warning['version'] version=warning['version']
) )
@ -466,7 +477,7 @@ class BaseManager(object):
def create(self): def create(self):
self._set_changed_options() self._set_changed_options()
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
return True return True
@ -481,7 +492,7 @@ class BaseManager(object):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -492,7 +503,7 @@ class BaseManager(object):
return False return False
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -521,7 +532,7 @@ class UntypedManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return ApiParameters(result) return ApiParameters(params=result)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.want.api_params()
@ -541,8 +552,8 @@ class UntypedManager(BaseManager):
class TypedManager(BaseManager): class TypedManager(BaseManager):
def __init__(self, client): def __init__(self, *args, **kwargs):
super(TypedManager, self).__init__(client) super(TypedManager, self).__init__(**kwargs)
if self.want.type is None: if self.want.type is None:
raise F5ModuleError( raise F5ModuleError(
"The 'type' option is required for BIG-IP instances " "The 'type' option is required for BIG-IP instances "
@ -588,7 +599,7 @@ class TypedManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = result.attrs result = result.attrs
return ApiParameters(result) return ApiParameters(params=result)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.want.api_params()
@ -626,7 +637,7 @@ class ArgumentSpec(object):
] ]
lb_method_choices = deprecated + supported lb_method_choices = deprecated + supported
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
pool_lb_method=dict( pool_lb_method=dict(
choices=lb_method_choices, choices=lb_method_choices,
aliases=['lb_method'] aliases=['lb_method']
@ -650,41 +661,36 @@ class ArgumentSpec(object):
name=dict(required=True), name=dict(required=True),
ratio=dict(type='int') ratio=dict(type='int')
) )
),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
) )
self.f5_product_name = 'bigip' self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as e:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(e))
if __name__ == '__main__': if __name__ == '__main__':

@ -24,12 +24,7 @@ options:
description: description:
- Hostname of the BIG-IP host. - Hostname of the BIG-IP host.
required: True required: True
notes:
- Requires the f5-sdk Python package on the host. This is as easy as pip
install f5-sdk.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements:
- f5-sdk
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
- Matthew Lam (@mryanlam) - Matthew Lam (@mryanlam)
@ -53,14 +48,36 @@ hostname:
sample: big-ip01.internal sample: big-ip01.internal
''' '''
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import AnsibleF5Parameters
from ansible.module_utils.f5_utils import HAS_F5SDK HAS_DEVEL_IMPORTS = False
from ansible.module_utils.f5_utils import F5ModuleError
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -76,16 +93,6 @@ class Parameters(AnsibleF5Parameters):
result = self._filter_params(result) result = self._filter_params(result)
return result return result
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
@property @property
def hostname(self): def hostname(self):
if self._values['hostname'] is None: if self._values['hostname'] is None:
@ -94,10 +101,11 @@ class Parameters(AnsibleF5Parameters):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.have = None self.have = None
self.want = Parameters(self.client.module.params) self.want = Parameters(params=self.module.params)
self.changes = Parameters() self.changes = Parameters()
def _set_changed_options(self): def _set_changed_options(self):
@ -106,7 +114,7 @@ class ModuleManager(object):
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 = Parameters(changed) self.changes = Parameters(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
changed = {} changed = {}
@ -116,7 +124,7 @@ class ModuleManager(object):
attr2 = getattr(self.have, key) attr2 = getattr(self.have, key)
if attr1 != attr2: if attr1 != attr2:
changed[key] = attr1 changed[key] = attr1
self.changes = Parameters(changed) self.changes = Parameters(params=changed)
if changed: if changed:
return True return True
return False return False
@ -137,13 +145,13 @@ class ModuleManager(object):
def read_current_from_device(self): def read_current_from_device(self):
resource = self.client.api.tm.sys.global_settings.load() resource = self.client.api.tm.sys.global_settings.load()
result = resource.attrs result = resource.attrs
return Parameters(result) return Parameters(params=result)
def update(self): def update(self):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -166,46 +174,35 @@ class ModuleManager(object):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
hostname=dict( hostname=dict(
required=True, required=True
default=None,
type='str'
) )
) )
self.f5_product_name = 'bigip' self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as e:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(e))
if __name__ == '__main__': if __name__ == '__main__':

@ -82,11 +82,6 @@ options:
over any similar setting in the iApp Server payload that you provide in over any similar setting in the iApp Server payload that you provide in
the C(parameters) field. the C(parameters) field.
version_added: 2.5 version_added: 2.5
notes:
- Requires the f5-sdk Python package on the host. This is as easy as pip
install f5-sdk.
requirements:
- f5-sdk
extends_documentation_fragment: f5 extends_documentation_fragment: f5
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
@ -215,16 +210,38 @@ RETURN = r'''
# only common fields returned # only common fields returned
''' '''
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import AnsibleF5Parameters from ansible.module_utils.basic import env_fallback
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
from collections import defaultdict
HAS_DEVEL_IMPORTS = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -241,35 +258,6 @@ class Parameters(AnsibleF5Parameters):
] ]
updatables = ['tables', 'variables', 'lists', 'strict_updates', 'traffic_group'] updatables = ['tables', 'variables', 'lists', 'strict_updates', 'traffic_group']
def __init__(self, params=None):
self._values = defaultdict(lambda: None)
if params:
self.update(params=params)
self._values['__warnings'] = []
def update(self, params=None):
if params:
for k, v in iteritems(params):
if self.api_map is not None and k in self.api_map:
map_key = self.api_map[k]
else:
map_key = k
# Handle weird API parameters like `dns.proxy.__iter__` by
# using a map provided by the module developer
class_attr = getattr(type(self), map_key, None)
if isinstance(class_attr, property):
# There is a mapped value for the api_map key
if class_attr.fset is None:
# If the mapped value does not have an associated setter
self._values[map_key] = v
else:
# The mapped value has a setter
setattr(self, map_key, v)
else:
# If the mapped value is not a @property
self._values[map_key] = v
def _fqdn_name(self, value): def _fqdn_name(self, value):
if value is not None and not value.startswith('/'): if value is not None and not value.startswith('/'):
return '/{0}/{1}'.format(self.partition, value) return '/{0}/{1}'.format(self.partition, value)
@ -282,16 +270,6 @@ class Parameters(AnsibleF5Parameters):
result = self._filter_params(result) result = self._filter_params(result)
return result return result
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
@property @property
def tables(self): def tables(self):
result = [] result = []
@ -489,10 +467,11 @@ class Difference(object):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.have = None self.have = None
self.want = Parameters(self.client.module.params) self.want = Parameters(params=self.module.params)
self.changes = Changes() self.changes = Changes()
def _set_changed_options(self): def _set_changed_options(self):
@ -501,7 +480,7 @@ class ModuleManager(object):
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 = Changes(changed) self.changes = Changes(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -517,7 +496,7 @@ class ModuleManager(object):
else: else:
changed[k] = change changed[k] = change
if changed: if changed:
self.changes = Changes(changed) self.changes = Changes(params=changed)
return True return True
return False return False
@ -556,7 +535,7 @@ class ModuleManager(object):
self._set_changed_options() self._set_changed_options()
if self.want.traffic_group is None and self.want.trafficGroup is None: if self.want.traffic_group is None and self.want.trafficGroup is None:
self.want.update({'traffic_group': '/Common/traffic-group-1'}) self.want.update({'traffic_group': '/Common/traffic-group-1'})
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
return True return True
@ -565,7 +544,7 @@ class ModuleManager(object):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update() and not self.want.force: if not self.should_update() and not self.want.force:
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -591,7 +570,7 @@ class ModuleManager(object):
partition=self.want.partition partition=self.want.partition
).to_dict() ).to_dict()
result.pop('_meta_data', None) result.pop('_meta_data', None)
return Parameters(result) return Parameters(params=result)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.want.api_params()
@ -607,7 +586,7 @@ class ModuleManager(object):
return False return False
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -626,7 +605,7 @@ class ModuleManager(object):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
name=dict(required=True), name=dict(required=True),
template=dict(), template=dict(),
parameters=dict( parameters=dict(
@ -643,41 +622,36 @@ class ArgumentSpec(object):
strict_updates=dict( strict_updates=dict(
type='bool' type='bool'
), ),
traffic_group=dict() traffic_group=dict(),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
self.f5_product_name = 'bigip'
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
) )
resource.delete() self.argument_spec = {}
except Exception: self.argument_spec.update(f5_argument_spec)
pass self.argument_spec.update(argument_spec)
def main(): def main():
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name
) )
try:
if not HAS_F5SDK: if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required") module.fail_json(msg="The python f5-sdk module is required")
mm = ModuleManager(client) try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as e:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(e))
if __name__ == '__main__': if __name__ == '__main__':

@ -39,9 +39,7 @@ options:
using it. This will not update the running service though. Use using it. This will not update the running service though. Use
C(bigip_iapp_service) to do that. When C(no), will update the iApp C(bigip_iapp_service) to do that. When C(no), will update the iApp
only if there are no iApp services using the template. only if there are no iApp services using the template.
choices: type: bool
- yes
- no
name: name:
description: description:
- The name of the iApp template that you want to delete. This option - The name of the iApp template that you want to delete. This option
@ -65,9 +63,6 @@ options:
description: description:
- Device partition to manage resources on. - Device partition to manage resources on.
default: Common default: Common
notes:
- Requires the f5-sdk Python package on the host. This is as easy as pip
install f5-sdk.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
@ -110,15 +105,40 @@ RETURN = r'''
import re import re
import uuid import uuid
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import AnsibleF5Parameters from ansible.module_utils.basic import env_fallback
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError HAS_DEVEL_IMPORTS = False
from ansible.module_utils.six import iteritems
from collections import defaultdict try:
# Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
HAS_DEVEL_IMPORTS = True
except ImportError:
# Upstream Ansible
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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
from f5.utils.iapp_parser import NonextantTemplateNameException from f5.utils.iapp_parser import NonextantTemplateNameException
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -133,34 +153,6 @@ class Parameters(AnsibleF5Parameters):
api_attributes = [] api_attributes = []
returnables = [] returnables = []
def __init__(self, params=None):
self._values = defaultdict(lambda: None)
if params:
self.update(params=params)
def update(self, params=None):
if params:
for k, v in iteritems(params):
if self.api_map is not None and k in self.api_map:
map_key = self.api_map[k]
else:
map_key = k
# Handle weird API parameters like `dns.proxy.__iter__` by
# using a map provided by the module developer
class_attr = getattr(type(self), map_key, None)
if isinstance(class_attr, property):
# There is a mapped value for the api_map key
if class_attr.fset is None:
# If the mapped value does not have an associated setter
self._values[map_key] = v
else:
# The mapped value has a setter
setattr(self, map_key, v)
else:
# If the mapped value is not a @property
self._values[map_key] = v
@property @property
def name(self): def name(self):
if self._values['name']: if self._values['name']:
@ -198,16 +190,6 @@ class Parameters(AnsibleF5Parameters):
pass pass
return result return result
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
def _squash_template_name_prefix(self): def _squash_template_name_prefix(self):
"""Removes the template name prefix """Removes the template name prefix
@ -252,9 +234,11 @@ class Parameters(AnsibleF5Parameters):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.want = Parameters(self.client.module.params) self.client = kwargs.get('client', None)
self.have = None
self.want = Parameters(params=self.module.params)
self.changes = Parameters() self.changes = Parameters()
def exec_module(self): def exec_module(self):
@ -290,7 +274,7 @@ class ModuleManager(object):
if not self.want.force and self.template_in_use(): if not self.want.force and self.template_in_use():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self._remove_iapp_checksum() self._remove_iapp_checksum()
@ -314,7 +298,7 @@ class ModuleManager(object):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return Parameters(result) return Parameters(params=result)
def absent(self): def absent(self):
changed = False changed = False
@ -392,7 +376,7 @@ class ModuleManager(object):
) )
def create(self): def create(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
if self.exists(): if self.exists():
@ -419,7 +403,7 @@ class ModuleManager(object):
raise F5ModuleError(output.commandResult) raise F5ModuleError(output.commandResult)
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -437,7 +421,7 @@ class ModuleManager(object):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
name=dict(), name=dict(),
state=dict( state=dict(
default='present', default='present',
@ -446,41 +430,36 @@ class ArgumentSpec(object):
force=dict( force=dict(
type='bool' type='bool'
), ),
content=dict() content=dict(),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
self.f5_product_name = 'bigip'
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
) )
resource.delete() self.argument_spec = {}
except Exception: self.argument_spec.update(f5_argument_spec)
pass self.argument_spec.update(argument_spec)
def main(): def main():
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode
f5_product_name=spec.f5_product_name
) )
try:
if not HAS_F5SDK: if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required") module.fail_json(msg="The python f5-sdk module is required")
mm = ModuleManager(client) try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as e:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(e))
if __name__ == '__main__': if __name__ == '__main__':

@ -37,8 +37,6 @@ options:
- present - present
- absent - absent
notes: notes:
- Requires the f5-sdk Python package on the host. This is as easy as pip
install f5-sdk.
- Requires the rpm tool be installed on the host. This can be accomplished through - Requires the rpm tool be installed on the host. This can be accomplished through
different ways on each platform. On Debian based systems with C(apt); different ways on each platform. On Debian based systems with C(apt);
C(apt-get install rpm). On Mac with C(brew); C(brew install rpm). C(apt-get install rpm). On Mac with C(brew); C(brew install rpm).
@ -46,7 +44,6 @@ notes:
- Requires BIG-IP >= 12.1.0 because the required functionality is missing - Requires BIG-IP >= 12.1.0 because the required functionality is missing
on versions earlier than that. on versions earlier than that.
requirements: requirements:
- f5-sdk >= 2.2.3
- Requires BIG-IP >= 12.1.0 - Requires BIG-IP >= 12.1.0
- The 'rpm' tool installed on the Ansible controller - The 'rpm' tool installed on the Ansible controller
extends_documentation_fragment: f5 extends_documentation_fragment: f5
@ -91,15 +88,37 @@ import os
import subprocess import subprocess
import time import time
from ansible.module_utils.f5_utils import AnsibleF5Client
from ansible.module_utils.f5_utils import AnsibleF5Parameters
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError
from distutils.version import LooseVersion from distutils.version import LooseVersion
from ansible.module_utils.basic import AnsibleModule
HAS_DEVEL_IMPORTS = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -162,9 +181,10 @@ class Parameters(AnsibleF5Parameters):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.want = Parameters(self.client.module.params) self.client = kwargs.get('client', None)
self.want = Parameters(params=self.module.params)
self.changes = Parameters() self.changes = Parameters()
def exec_module(self): def exec_module(self):
@ -230,11 +250,16 @@ class ModuleManager(object):
) )
def create(self): def create(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
if not os.path.exists(self.want.package): if not os.path.exists(self.want.package):
if self.want.package.startswith('/'):
raise F5ModuleError( raise F5ModuleError(
"The specified iAppLX package was not found." "The specified iAppLX package was not found at {0}.".format(self.want.package)
)
else:
raise F5ModuleError(
"The specified iAppLX package was not found in {0}.".format(os.getcwd())
) )
self.upload_to_device() self.upload_to_device()
self.create_on_device() self.create_on_device()
@ -271,7 +296,7 @@ class ModuleManager(object):
raise F5ModuleError(task.errorMessage) raise F5ModuleError(task.errorMessage)
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -307,50 +332,42 @@ class ModuleManager(object):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
state=dict( state=dict(
default='present', default='present',
choices=['present', 'absent'] choices=['present', 'absent']
), ),
package=dict() package=dict()
) )
self.f5_product_name = 'bigip' self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
self.required_if = [ self.required_if = [
['state', 'present', ['package']] ['state', 'present', ['package']]
] ]
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required")
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode,
f5_product_name=spec.f5_product_name,
required_if=spec.required_if required_if=spec.required_if
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required")
try: try:
mm = ModuleManager(client) client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as e:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(e))
if __name__ == '__main__': if __name__ == '__main__':
main() main()

@ -54,12 +54,7 @@ options:
- Device partition to manage resources on. - Device partition to manage resources on.
default: Common default: Common
version_added: 2.5 version_added: 2.5
notes:
- Requires the f5-sdk Python package on the host. This is as easy as
pip install f5-sdk.
extends_documentation_fragment: f5 extends_documentation_fragment: f5
requirements:
- f5-sdk
author: author:
- Tim Rupp (@caphrim007) - Tim Rupp (@caphrim007)
''' '''
@ -108,14 +103,37 @@ content:
import os import os
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import AnsibleF5Parameters from ansible.module_utils.basic import env_fallback
from ansible.module_utils.f5_utils import HAS_F5SDK
from ansible.module_utils.f5_utils import F5ModuleError HAS_DEVEL_IMPORTS = False
try: try:
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError # Sideband repository used for dev
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 fqdn_name
from library.module_utils.network.f5.common import f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
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 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 fqdn_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
@ -146,16 +164,6 @@ class Parameters(AnsibleF5Parameters):
pass pass
return result return result
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
@property @property
def content(self): def content(self):
if self._values['content'] is None: if self._values['content'] is None:
@ -183,13 +191,15 @@ class Parameters(AnsibleF5Parameters):
class ModuleManager(object): class ModuleManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.client = kwargs.get('client', None)
self.module = kwargs.get('module', None)
self.kwargs = kwargs
def exec_module(self): def exec_module(self):
if self.client.module.params['module'] == 'ltm': if self.module.params['module'] == 'ltm':
manager = self.get_manager('ltm') manager = self.get_manager('ltm')
elif self.client.module.params['module'] == 'gtm': elif self.module.params['module'] == 'gtm':
manager = self.get_manager('gtm') manager = self.get_manager('gtm')
else: else:
raise F5ModuleError( raise F5ModuleError(
@ -199,15 +209,16 @@ class ModuleManager(object):
def get_manager(self, type): def get_manager(self, type):
if type == 'ltm': if type == 'ltm':
return LtmManager(self.client) return LtmManager(**self.kwargs)
elif type == 'gtm': elif type == 'gtm':
return GtmManager(self.client) return GtmManager(**self.kwargs)
class BaseManager(object): class BaseManager(object):
def __init__(self, client): def __init__(self, *args, **kwargs):
self.client = client self.module = kwargs.get('module', None)
self.want = Parameters(self.client.module.params) self.client = kwargs.get('client', None)
self.want = Parameters(params=self.module.params)
self.changes = Parameters() self.changes = Parameters()
def exec_module(self): def exec_module(self):
@ -234,7 +245,7 @@ class BaseManager(object):
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 = Parameters(changed) self.changes = Parameters(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
changed = {} changed = {}
@ -245,7 +256,7 @@ class BaseManager(object):
if attr1 != attr2: if attr1 != attr2:
changed[key] = attr1 changed[key] = attr1
if changed: if changed:
self.changes = Parameters(changed) self.changes = Parameters(params=changed)
return True return True
return False return False
@ -261,7 +272,7 @@ class BaseManager(object):
def create(self): def create(self):
self._set_changed_options() self._set_changed_options()
if self.client.check_mode: if self.module.check_mode:
return True return True
self.create_on_device() self.create_on_device()
if not self.exists(): if not self.exists():
@ -278,7 +289,7 @@ class BaseManager(object):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
return False return False
if self.client.check_mode: if self.module.check_mode:
return True return True
self.update_on_device() self.update_on_device()
return True return True
@ -289,7 +300,7 @@ class BaseManager(object):
return False return False
def remove(self): def remove(self):
if self.client.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
@ -328,7 +339,7 @@ class LtmManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return Parameters(result) return Parameters(params=result)
def remove_from_device(self): def remove_from_device(self):
resource = self.client.api.tm.ltm.rules.rule.load( resource = self.client.api.tm.ltm.rules.rule.load(
@ -345,7 +356,7 @@ class GtmManager(BaseManager):
partition=self.want.partition partition=self.want.partition
) )
result = resource.attrs result = resource.attrs
return Parameters(result) return Parameters(params=result)
def remove_from_device(self): def remove_from_device(self):
resource = self.client.api.tm.gtm.rules.rule.load( resource = self.client.api.tm.gtm.rules.rule.load(
@ -382,7 +393,7 @@ class GtmManager(BaseManager):
class ArgumentSpec(object): class ArgumentSpec(object):
def __init__(self): def __init__(self):
self.supports_check_mode = True self.supports_check_mode = True
self.argument_spec = dict( argument_spec = dict(
content=dict( content=dict(
required=False, required=False,
default=None default=None
@ -395,45 +406,44 @@ class ArgumentSpec(object):
module=dict( module=dict(
required=True, required=True,
choices=['gtm', 'ltm'] choices=['gtm', 'ltm']
),
state=dict(
default='present',
choices=['present', 'absent']
),
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
) )
) )
self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)
self.argument_spec.update(argument_spec)
self.mutually_exclusive = [ self.mutually_exclusive = [
['content', 'src'] ['content', 'src']
] ]
self.f5_product_name = 'bigip'
def cleanup_tokens(client):
try:
resource = client.api.shared.authz.tokens_s.token.load(
name=client.api.icrs.token
)
resource.delete()
except Exception:
pass
def main(): def main():
spec = ArgumentSpec() spec = ArgumentSpec()
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode,
f5_product_name=spec.f5_product_name, mutually_exclusive=spec.mutually_exclusive
mutually_exclusive=spec.mutually_exclusive,
) )
try:
if not HAS_F5SDK: if not HAS_F5SDK:
raise F5ModuleError("The python f5-sdk module is required") module.fail_json(msg="The python f5-sdk module is required")
mm = ModuleManager(client) try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
client.module.exit_json(**results) module.exit_json(**results)
except F5ModuleError as e: except F5ModuleError as e:
cleanup_tokens(client) cleanup_tokens(client)
client.module.fail_json(msg=str(e)) module.fail_json(msg=str(e))
if __name__ == '__main__': if __name__ == '__main__':

@ -41,13 +41,6 @@ lib/ansible/modules/net_tools/cloudflare_dns.py E317
lib/ansible/modules/net_tools/haproxy.py E317 lib/ansible/modules/net_tools/haproxy.py E317
lib/ansible/modules/net_tools/omapi_host.py E317 lib/ansible/modules/net_tools/omapi_host.py E317
lib/ansible/modules/network/cloudengine/ce_reboot.py E317 lib/ansible/modules/network/cloudengine/ce_reboot.py E317
lib/ansible/modules/network/f5/bigip_gtm_datacenter.py E321
lib/ansible/modules/network/f5/bigip_gtm_facts.py E321
lib/ansible/modules/network/f5/bigip_gtm_pool.py E321
lib/ansible/modules/network/f5/bigip_gtm_server.py E321
lib/ansible/modules/network/f5/bigip_gtm_wide_ip.py E321
lib/ansible/modules/network/f5/bigip_hostname.py E317
lib/ansible/modules/network/f5/bigip_iapplx_package.py E321
lib/ansible/modules/network/f5/bigip_partition.py E321 lib/ansible/modules/network/f5/bigip_partition.py E321
lib/ansible/modules/network/f5/bigip_policy.py E321 lib/ansible/modules/network/f5/bigip_policy.py E321
lib/ansible/modules/network/f5/bigip_policy_rule.py E321 lib/ansible/modules/network/f5/bigip_policy_rule.py E321

@ -17,14 +17,15 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_gtm_datacenter import ApiParameters from library.bigip_gtm_datacenter import ApiParameters
from library.bigip_gtm_datacenter import ModuleParameters from library.bigip_gtm_datacenter import ModuleParameters
from library.bigip_gtm_datacenter import ModuleManager from library.bigip_gtm_datacenter import ModuleManager
from library.bigip_gtm_datacenter import ArgumentSpec from library.bigip_gtm_datacenter import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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:
@ -32,7 +33,8 @@ except ImportError:
from ansible.modules.network.f5.bigip_gtm_datacenter import ModuleParameters from ansible.modules.network.f5.bigip_gtm_datacenter import ModuleParameters
from ansible.modules.network.f5.bigip_gtm_datacenter import ModuleManager from ansible.modules.network.f5.bigip_gtm_datacenter import ModuleManager
from ansible.modules.network.f5.bigip_gtm_datacenter import ArgumentSpec from ansible.modules.network.f5.bigip_gtm_datacenter import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -68,19 +70,19 @@ class TestParameters(unittest.TestCase):
location='baz', location='baz',
name='datacenter' name='datacenter'
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.state == 'present' assert p.state == 'present'
def test_api_parameters(self): def test_api_parameters(self):
args = load_fixture('load_gtm_datacenter_default.json') args = load_fixture('load_gtm_datacenter_default.json')
p = ApiParameters(args) p = ApiParameters(params=args)
assert p.name == 'asd' assert p.name == 'asd'
def test_module_parameters_state_present(self): def test_module_parameters_state_present(self):
args = dict( args = dict(
state='present' state='present'
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.state == 'present' assert p.state == 'present'
assert p.enabled is True assert p.enabled is True
@ -88,14 +90,14 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
state='absent' state='absent'
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.state == 'absent' assert p.state == 'absent'
def test_module_parameters_state_enabled(self): def test_module_parameters_state_enabled(self):
args = dict( args = dict(
state='enabled' state='enabled'
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.state == 'enabled' assert p.state == 'enabled'
assert p.enabled is True assert p.enabled is True
assert p.disabled is None assert p.disabled is None
@ -104,14 +106,12 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
state='disabled' state='disabled'
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.state == 'disabled' assert p.state == 'disabled'
assert p.enabled is None assert p.enabled is None
assert p.disabled is True assert p.disabled is True
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -126,12 +126,11 @@ class TestManager(unittest.TestCase):
name='foo' name='foo'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, True]) mm.exists = Mock(side_effect=[False, True])
@ -150,12 +149,11 @@ class TestManager(unittest.TestCase):
name='foo' name='foo'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, True]) mm.exists = Mock(side_effect=[False, True])
@ -175,12 +173,11 @@ class TestManager(unittest.TestCase):
name='foo' name='foo'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, True]) mm.exists = Mock(side_effect=[False, True])
@ -200,15 +197,14 @@ class TestManager(unittest.TestCase):
name='foo' name='foo'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
current = ApiParameters(load_fixture('load_gtm_datacenter_disabled.json')) current = ApiParameters(params=load_fixture('load_gtm_datacenter_disabled.json'))
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(return_value=True) mm.exists = Mock(return_value=True)

@ -17,7 +17,7 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems from ansible.module_utils.six import iteritems
try: try:
@ -34,7 +34,8 @@ try:
from library.bigip_gtm_facts import TypedWideIpFactManager from library.bigip_gtm_facts import TypedWideIpFactManager
from library.bigip_gtm_facts import UntypedWideIpFactManager from library.bigip_gtm_facts import UntypedWideIpFactManager
from library.bigip_gtm_facts import ArgumentSpec from library.bigip_gtm_facts import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
from f5.bigip.tm.gtm.pool import A from f5.bigip.tm.gtm.pool import A
from f5.utils.responses.handlers import Stats from f5.utils.responses.handlers import Stats
from test.unit.modules.utils import set_module_args from test.unit.modules.utils import set_module_args
@ -53,7 +54,8 @@ except ImportError:
from ansible.modules.network.f5.bigip_gtm_pool import TypedWideIpFactManager from ansible.modules.network.f5.bigip_gtm_pool import TypedWideIpFactManager
from ansible.modules.network.f5.bigip_gtm_pool import UntypedWideIpFactManager from ansible.modules.network.f5.bigip_gtm_pool import UntypedWideIpFactManager
from ansible.modules.network.f5.bigip_gtm_pool import ArgumentSpec from ansible.modules.network.f5.bigip_gtm_pool import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from f5.bigip.tm.gtm.pool import A from f5.bigip.tm.gtm.pool import A
from f5.utils.responses.handlers import Stats from f5.utils.responses.handlers import Stats
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
@ -100,13 +102,11 @@ class TestParameters(unittest.TestCase):
include=['pool'], include=['pool'],
filter='name.*' filter='name.*'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.include == ['pool'] assert p.include == ['pool']
assert p.filter == 'name.*' assert p.filter == 'name.*'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -125,23 +125,22 @@ class TestManager(unittest.TestCase):
collection = [FakeARecord(attrs=x) for x in fixture1['items']] collection = [FakeARecord(attrs=x) for x in fixture1['items']]
stats = Stats(FakeStatResource(fixture2['entries'])) stats = Stats(FakeStatResource(fixture2['entries']))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tfm = TypedPoolFactManager(client) tfm = TypedPoolFactManager(module=module)
tfm.read_collection_from_device = Mock(return_value=collection) tfm.read_collection_from_device = Mock(return_value=collection)
tfm.read_stats_from_device = Mock(return_value=stats.stat) tfm.read_stats_from_device = Mock(return_value=stats.stat)
tm = PoolFactManager(client) tm = PoolFactManager(module=module)
tm.version_is_less_than_12 = Mock(return_value=False) tm.version_is_less_than_12 = Mock(return_value=False)
tm.get_manager = Mock(return_value=tfm) tm.get_manager = Mock(return_value=tfm)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)

@ -17,7 +17,7 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_gtm_pool import Parameters from library.bigip_gtm_pool import Parameters
@ -25,7 +25,8 @@ try:
from library.bigip_gtm_pool import ArgumentSpec from library.bigip_gtm_pool import ArgumentSpec
from library.bigip_gtm_pool import UntypedManager from library.bigip_gtm_pool import UntypedManager
from library.bigip_gtm_pool import TypedManager from library.bigip_gtm_pool import TypedManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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:
@ -34,7 +35,8 @@ except ImportError:
from ansible.modules.network.f5.bigip_gtm_pool import ArgumentSpec from ansible.modules.network.f5.bigip_gtm_pool import ArgumentSpec
from ansible.modules.network.f5.bigip_gtm_pool import UntypedManager from ansible.modules.network.f5.bigip_gtm_pool import UntypedManager
from ansible.modules.network.f5.bigip_gtm_pool import TypedManager from ansible.modules.network.f5.bigip_gtm_pool import TypedManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -71,7 +73,7 @@ class TestParameters(unittest.TestCase):
fallback_ip='10.10.10.10', fallback_ip='10.10.10.10',
type='a' type='a'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.name == 'foo' assert p.name == 'foo'
assert p.preferred_lb_method == 'topology' assert p.preferred_lb_method == 'topology'
assert p.alternate_lb_method == 'ratio' assert p.alternate_lb_method == 'ratio'
@ -87,7 +89,7 @@ class TestParameters(unittest.TestCase):
fallbackMode='fewest-hops', fallbackMode='fewest-hops',
fallbackIp='10.10.10.10' fallbackIp='10.10.10.10'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.name == 'foo' assert p.name == 'foo'
assert p.preferred_lb_method == 'topology' assert p.preferred_lb_method == 'topology'
assert p.alternate_lb_method == 'ratio' assert p.alternate_lb_method == 'ratio'
@ -95,8 +97,6 @@ class TestParameters(unittest.TestCase):
assert p.fallback_ip == '10.10.10.10' assert p.fallback_ip == '10.10.10.10'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestUntypedManager(unittest.TestCase): class TestUntypedManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -111,19 +111,18 @@ class TestUntypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = UntypedManager(client) tm = UntypedManager(module=module)
tm.exists = Mock(side_effect=[False, True]) tm.exists = Mock(side_effect=[False, True])
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=True) mm.version_is_less_than_12 = Mock(return_value=True)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)
@ -144,22 +143,21 @@ class TestUntypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
current = Parameters(load_fixture('load_gtm_pool_untyped_default.json')) current = Parameters(params=load_fixture('load_gtm_pool_untyped_default.json'))
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = UntypedManager(client) tm = UntypedManager(module=module)
tm.exists = Mock(side_effect=[True, True]) tm.exists = Mock(side_effect=[True, True])
tm.update_on_device = Mock(return_value=True) tm.update_on_device = Mock(return_value=True)
tm.read_current_from_device = Mock(return_value=current) tm.read_current_from_device = Mock(return_value=current)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=True) mm.version_is_less_than_12 = Mock(return_value=True)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)
@ -180,19 +178,18 @@ class TestUntypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = UntypedManager(client) tm = UntypedManager(module=module)
tm.exists = Mock(side_effect=[True, False]) tm.exists = Mock(side_effect=[True, False])
tm.remove_from_device = Mock(return_value=True) tm.remove_from_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=True) mm.version_is_less_than_12 = Mock(return_value=True)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)
@ -202,8 +199,6 @@ class TestUntypedManager(unittest.TestCase):
assert results['changed'] is True assert results['changed'] is True
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestTypedManager(unittest.TestCase): class TestTypedManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -219,19 +214,18 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module)
tm.exists = Mock(side_effect=[False, True]) tm.exists = Mock(side_effect=[False, True])
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)
@ -253,22 +247,21 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
current = Parameters(load_fixture('load_gtm_pool_a_default.json')) current = Parameters(params=load_fixture('load_gtm_pool_a_default.json'))
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module)
tm.exists = Mock(side_effect=[True, True]) tm.exists = Mock(side_effect=[True, True])
tm.update_on_device = Mock(return_value=True) tm.update_on_device = Mock(return_value=True)
tm.read_current_from_device = Mock(return_value=current) tm.read_current_from_device = Mock(return_value=current)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)
@ -290,19 +283,18 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module)
tm.exists = Mock(side_effect=[True, False]) tm.exists = Mock(side_effect=[True, False])
tm.remove_from_device = Mock(return_value=True) tm.remove_from_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)

@ -18,8 +18,7 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import F5ModuleError
try: try:
from library.bigip_gtm_server import ApiParameters from library.bigip_gtm_server import ApiParameters
@ -28,7 +27,8 @@ try:
from library.bigip_gtm_server import V1Manager from library.bigip_gtm_server import V1Manager
from library.bigip_gtm_server import V2Manager from library.bigip_gtm_server import V2Manager
from library.bigip_gtm_server import ArgumentSpec from library.bigip_gtm_server import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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:
@ -38,7 +38,8 @@ except ImportError:
from ansible.modules.network.f5.bigip_gtm_server import V1Manager from ansible.modules.network.f5.bigip_gtm_server import V1Manager
from ansible.modules.network.f5.bigip_gtm_server import V2Manager from ansible.modules.network.f5.bigip_gtm_server import V2Manager
from ansible.modules.network.f5.bigip_gtm_server import ArgumentSpec from ansible.modules.network.f5.bigip_gtm_server import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -114,7 +115,7 @@ class TestParameters(unittest.TestCase):
] ]
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.name == 'GTM_Server' assert p.name == 'GTM_Server'
assert p.datacenter == '/Common/New York' assert p.datacenter == '/Common/New York'
assert p.server_type == 'bigip' assert p.server_type == 'bigip'
@ -124,7 +125,7 @@ class TestParameters(unittest.TestCase):
def test_api_parameters(self): def test_api_parameters(self):
args = load_fixture('load_gtm_server_1.json') args = load_fixture('load_gtm_server_1.json')
p = ApiParameters(args) p = ApiParameters(params=args)
assert p.name == 'baz' assert p.name == 'baz'
assert p.datacenter == '/Common/foo' assert p.datacenter == '/Common/foo'
assert p.server_type == 'bigip' assert p.server_type == 'bigip'
@ -132,8 +133,6 @@ class TestParameters(unittest.TestCase):
assert p.virtual_server_discovery == 'disabled' assert p.virtual_server_discovery == 'disabled'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestV1Manager(unittest.TestCase): class TestV1Manager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -189,18 +188,17 @@ class TestV1Manager(unittest.TestCase):
] ]
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
m1 = V1Manager(client) m1 = V1Manager(module=module, params=module.params)
m1.exists = Mock(side_effect=[False, True]) m1.exists = Mock(side_effect=[False, True])
m1.create_on_device = Mock(return_value=True) m1.create_on_device = Mock(return_value=True)
# Override methods in the specific type of manager # Override methods in the specific type of manager
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.get_manager = Mock(return_value=m1) mm.get_manager = Mock(return_value=m1)
mm.version_is_less_than = Mock(return_value=True) mm.version_is_less_than = Mock(return_value=True)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)
@ -211,8 +209,6 @@ class TestV1Manager(unittest.TestCase):
assert results['server_type'] == 'bigip' assert results['server_type'] == 'bigip'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestV2Manager(unittest.TestCase): class TestV2Manager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -268,18 +264,17 @@ class TestV2Manager(unittest.TestCase):
] ]
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
m1 = V2Manager(client) m1 = V2Manager(module=module)
m1.exists = Mock(side_effect=[False, True]) m1.exists = Mock(side_effect=[False, True])
m1.create_on_device = Mock(return_value=True) m1.create_on_device = Mock(return_value=True)
# Override methods in the specific type of manager # Override methods in the specific type of manager
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.get_manager = Mock(return_value=m1) mm.get_manager = Mock(return_value=m1)
mm.version_is_less_than = Mock(return_value=False) mm.version_is_less_than = Mock(return_value=False)
mm.gtm_provisioned = Mock(return_value=True) mm.gtm_provisioned = Mock(return_value=True)

@ -18,8 +18,7 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.f5_utils import F5ModuleError
try: try:
from library.bigip_gtm_wide_ip import ApiParameters from library.bigip_gtm_wide_ip import ApiParameters
@ -28,7 +27,8 @@ try:
from library.bigip_gtm_wide_ip import ArgumentSpec from library.bigip_gtm_wide_ip import ArgumentSpec
from library.bigip_gtm_wide_ip import UntypedManager from library.bigip_gtm_wide_ip import UntypedManager
from library.bigip_gtm_wide_ip import TypedManager from library.bigip_gtm_wide_ip import TypedManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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:
@ -38,7 +38,8 @@ except ImportError:
from ansible.modules.network.f5.bigip_gtm_wide_ip import ArgumentSpec from ansible.modules.network.f5.bigip_gtm_wide_ip import ArgumentSpec
from ansible.modules.network.f5.bigip_gtm_wide_ip import UntypedManager from ansible.modules.network.f5.bigip_gtm_wide_ip import UntypedManager
from ansible.modules.network.f5.bigip_gtm_wide_ip import TypedManager from ansible.modules.network.f5.bigip_gtm_wide_ip import TypedManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -71,7 +72,7 @@ class TestParameters(unittest.TestCase):
name='foo.baz.bar', name='foo.baz.bar',
lb_method='round-robin', lb_method='round-robin',
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.name == 'foo.baz.bar' assert p.name == 'foo.baz.bar'
assert p.pool_lb_method == 'round-robin' assert p.pool_lb_method == 'round-robin'
@ -84,7 +85,7 @@ class TestParameters(unittest.TestCase):
) )
] ]
) )
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert len(p.pools) == 1 assert len(p.pools) == 1
def test_api_parameters(self): def test_api_parameters(self):
@ -92,13 +93,13 @@ class TestParameters(unittest.TestCase):
name='foo.baz.bar', name='foo.baz.bar',
poolLbMode='round-robin' poolLbMode='round-robin'
) )
p = ApiParameters(args) p = ApiParameters(params=args)
assert p.name == 'foo.baz.bar' assert p.name == 'foo.baz.bar'
assert p.pool_lb_method == 'round-robin' assert p.pool_lb_method == 'round-robin'
def test_api_pools(self): def test_api_pools(self):
args = load_fixture('load_gtm_wide_ip_with_pools.json') args = load_fixture('load_gtm_wide_ip_with_pools.json')
p = ApiParameters(args) p = ApiParameters(params=args)
assert len(p.pools) == 1 assert len(p.pools) == 1
assert 'name' in p.pools[0] assert 'name' in p.pools[0]
assert 'ratio' in p.pools[0] assert 'ratio' in p.pools[0]
@ -111,13 +112,11 @@ class TestParameters(unittest.TestCase):
lb_method='round-robin' lb_method='round-robin'
) )
with pytest.raises(F5ModuleError) as excinfo: with pytest.raises(F5ModuleError) as excinfo:
p = ModuleParameters(args) p = ModuleParameters(params=args)
assert p.name == 'foo.baz' assert p.name == 'foo.baz'
assert 'The provided name must be a valid FQDN' in str(excinfo) assert 'The provided name must be a valid FQDN' in str(excinfo)
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestUntypedManager(unittest.TestCase): class TestUntypedManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -132,19 +131,18 @@ class TestUntypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = UntypedManager(client) tm = UntypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=False) tm.exists = Mock(return_value=False)
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=True) mm.version_is_less_than_12 = Mock(return_value=True)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
@ -156,8 +154,6 @@ class TestUntypedManager(unittest.TestCase):
assert results['lb_method'] == 'round-robin' assert results['lb_method'] == 'round-robin'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestTypedManager(unittest.TestCase): class TestTypedManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -173,19 +169,18 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=False) tm.exists = Mock(return_value=False)
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
@ -206,19 +201,18 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=False) tm.exists = Mock(return_value=False)
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
@ -239,19 +233,18 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=False) tm.exists = Mock(return_value=False)
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
@ -278,19 +271,18 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=False) tm.exists = Mock(return_value=False)
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
@ -317,20 +309,19 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
current = ApiParameters(load_fixture('load_gtm_wide_ip_with_pools.json')) current = ApiParameters(params=load_fixture('load_gtm_wide_ip_with_pools.json'))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=True) tm.exists = Mock(return_value=True)
tm.read_current_from_device = Mock(return_value=current) tm.read_current_from_device = Mock(return_value=current)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
@ -358,21 +349,20 @@ class TestTypedManager(unittest.TestCase):
user='admin' user='admin'
)) ))
current = ApiParameters(load_fixture('load_gtm_wide_ip_with_pools.json')) current = ApiParameters(params=load_fixture('load_gtm_wide_ip_with_pools.json'))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = TypedManager(client) tm = TypedManager(module=module, params=module.params)
tm.exists = Mock(return_value=True) tm.exists = Mock(return_value=True)
tm.read_current_from_device = Mock(return_value=current) tm.read_current_from_device = Mock(return_value=current)
tm.update_on_device = Mock(return_value=True) tm.update_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.version_is_less_than_12 = Mock(return_value=False) mm.version_is_less_than_12 = Mock(return_value=False)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)

@ -17,20 +17,22 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_hostname import Parameters from library.bigip_hostname import Parameters
from library.bigip_hostname import ModuleManager from library.bigip_hostname import ModuleManager
from library.bigip_hostname import ArgumentSpec from library.bigip_hostname import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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_hostname import Parameters from ansible.modules.network.f5.bigip_hostname import Parameters
from ansible.modules.network.f5.bigip_hostname import ModuleManager from ansible.modules.network.f5.bigip_hostname import ModuleManager
from ansible.modules.network.f5.bigip_hostname import ArgumentSpec from ansible.modules.network.f5.bigip_hostname import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -62,12 +64,10 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
hostname='foo.internal.com' hostname='foo.internal.com'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.hostname == 'foo.internal.com' assert p.hostname == 'foo.internal.com'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -88,14 +88,13 @@ class TestManager(unittest.TestCase):
hostname='foo.internal.com' hostname='foo.internal.com'
) )
) )
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.update_on_device = Mock(return_value=True) mm.update_on_device = Mock(return_value=True)
mm.read_current_from_device = Mock(return_value=current) mm.read_current_from_device = Mock(return_value=current)

@ -17,20 +17,22 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_iapp_service import Parameters from library.bigip_iapp_service import Parameters
from library.bigip_iapp_service import ModuleManager from library.bigip_iapp_service import ModuleManager
from library.bigip_iapp_service import ArgumentSpec from library.bigip_iapp_service import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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_iapp_service import Parameters from ansible.modules.network.f5.bigip_iapp_service import Parameters
from ansible.modules.network.f5.bigip_iapp_service import ModuleManager from ansible.modules.network.f5.bigip_iapp_service import ModuleManager
from ansible.modules.network.f5.bigip_iapp_service import ArgumentSpec from ansible.modules.network.f5.bigip_iapp_service import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -61,7 +63,7 @@ class TestParameters(unittest.TestCase):
def test_module_parameters_keys(self): def test_module_parameters_keys(self):
args = load_fixture('create_iapp_service_parameters_f5_http.json') args = load_fixture('create_iapp_service_parameters_f5_http.json')
p = Parameters(args) p = Parameters(params=args)
# Assert the top-level keys # Assert the top-level keys
assert p.name == 'http_example' assert p.name == 'http_example'
@ -74,7 +76,7 @@ class TestParameters(unittest.TestCase):
def test_module_parameters_lists(self): def test_module_parameters_lists(self):
args = load_fixture('create_iapp_service_parameters_f5_http.json') args = load_fixture('create_iapp_service_parameters_f5_http.json')
p = Parameters(args) p = Parameters(params=args)
assert 'lists' in p._values assert 'lists' in p._values
@ -90,7 +92,7 @@ class TestParameters(unittest.TestCase):
def test_module_parameters_tables(self): def test_module_parameters_tables(self):
args = load_fixture('create_iapp_service_parameters_f5_http.json') args = load_fixture('create_iapp_service_parameters_f5_http.json')
p = Parameters(args) p = Parameters(params=args)
assert 'tables' in p._values assert 'tables' in p._values
@ -117,7 +119,7 @@ class TestParameters(unittest.TestCase):
def test_module_parameters_variables(self): def test_module_parameters_variables(self):
args = load_fixture('create_iapp_service_parameters_f5_http.json') args = load_fixture('create_iapp_service_parameters_f5_http.json')
p = Parameters(args) p = Parameters(params=args)
assert 'variables' in p._values assert 'variables' in p._values
assert len(p.variables) == 34 assert len(p.variables) == 34
@ -140,13 +142,13 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
strict_updates=True strict_updates=True
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'enabled' assert p.strict_updates == 'enabled'
args = dict( args = dict(
strict_updates=False strict_updates=False
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'disabled' assert p.strict_updates == 'disabled'
def test_module_strict_updates_override_from_top_level(self): def test_module_strict_updates_override_from_top_level(self):
@ -156,7 +158,7 @@ class TestParameters(unittest.TestCase):
strictUpdates='disabled' strictUpdates='disabled'
) )
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'enabled' assert p.strict_updates == 'enabled'
args = dict( args = dict(
@ -165,7 +167,7 @@ class TestParameters(unittest.TestCase):
strictUpdates='enabled' strictUpdates='enabled'
) )
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'disabled' assert p.strict_updates == 'disabled'
def test_module_strict_updates_only_parameters(self): def test_module_strict_updates_only_parameters(self):
@ -174,7 +176,7 @@ class TestParameters(unittest.TestCase):
strictUpdates='disabled' strictUpdates='disabled'
) )
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'disabled' assert p.strict_updates == 'disabled'
args = dict( args = dict(
@ -182,20 +184,20 @@ class TestParameters(unittest.TestCase):
strictUpdates='enabled' strictUpdates='enabled'
) )
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'enabled' assert p.strict_updates == 'enabled'
def test_api_strict_updates_from_top_level(self): def test_api_strict_updates_from_top_level(self):
args = dict( args = dict(
strictUpdates='enabled' strictUpdates='enabled'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'enabled' assert p.strict_updates == 'enabled'
args = dict( args = dict(
strictUpdates='disabled' strictUpdates='disabled'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.strict_updates == 'disabled' assert p.strict_updates == 'disabled'
def test_api_parameters_variables(self): def test_api_parameters_variables(self):
@ -208,7 +210,7 @@ class TestParameters(unittest.TestCase):
) )
] ]
) )
p = Parameters(args) p = Parameters(params=args)
assert p.variables[0]['name'] == 'client__http_compression' assert p.variables[0]['name'] == 'client__http_compression'
def test_api_parameters_tables(self): def test_api_parameters_tables(self):
@ -240,7 +242,7 @@ class TestParameters(unittest.TestCase):
} }
] ]
) )
p = Parameters(args) p = Parameters(params=args)
assert p.tables[0]['name'] == 'pool__members' assert p.tables[0]['name'] == 'pool__members'
assert p.tables[0]['columnNames'] == ['addr', 'port', 'connection_limit'] assert p.tables[0]['columnNames'] == ['addr', 'port', 'connection_limit']
assert len(p.tables[0]['rows']) == 2 assert len(p.tables[0]['rows']) == 2
@ -253,28 +255,28 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
deviceGroup='none' deviceGroup='none'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.deviceGroup == 'none' assert p.deviceGroup == 'none'
def test_api_parameters_inherited_traffic_group(self): def test_api_parameters_inherited_traffic_group(self):
args = dict( args = dict(
inheritedTrafficGroup='true' inheritedTrafficGroup='true'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.inheritedTrafficGroup == 'true' assert p.inheritedTrafficGroup == 'true'
def test_api_parameters_inherited_devicegroup(self): def test_api_parameters_inherited_devicegroup(self):
args = dict( args = dict(
inheritedDevicegroup='true' inheritedDevicegroup='true'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.inheritedDevicegroup == 'true' assert p.inheritedDevicegroup == 'true'
def test_api_parameters_traffic_group(self): def test_api_parameters_traffic_group(self):
args = dict( args = dict(
trafficGroup='/Common/traffic-group-local-only' trafficGroup='/Common/traffic-group-local-only'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.traffic_group == '/Common/traffic-group-local-only' assert p.traffic_group == '/Common/traffic-group-local-only'
def test_module_template_same_partition(self): def test_module_template_same_partition(self):
@ -282,7 +284,7 @@ class TestParameters(unittest.TestCase):
template='foo', template='foo',
partition='bar' partition='bar'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.template == '/bar/foo' assert p.template == '/bar/foo'
def test_module_template_same_partition_full_path(self): def test_module_template_same_partition_full_path(self):
@ -290,7 +292,7 @@ class TestParameters(unittest.TestCase):
template='/bar/foo', template='/bar/foo',
partition='bar' partition='bar'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.template == '/bar/foo' assert p.template == '/bar/foo'
def test_module_template_different_partition_full_path(self): def test_module_template_different_partition_full_path(self):
@ -298,12 +300,10 @@ class TestParameters(unittest.TestCase):
template='/Common/foo', template='/Common/foo',
partition='bar' partition='bar'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.template == '/Common/foo' assert p.template == '/Common/foo'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -321,12 +321,11 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(return_value=False) mm.exists = Mock(return_value=False)
@ -352,12 +351,11 @@ class TestManager(unittest.TestCase):
parameters = load_fixture('create_iapp_service_parameters_f5_http.json') parameters = load_fixture('create_iapp_service_parameters_f5_http.json')
current = Parameters(parameters) current = Parameters(parameters)
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(return_value=True) mm.exists = Mock(return_value=True)

@ -17,20 +17,22 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_iapp_template import Parameters from library.bigip_iapp_template import Parameters
from library.bigip_iapp_template import ModuleManager from library.bigip_iapp_template import ModuleManager
from library.bigip_iapp_template import ArgumentSpec from library.bigip_iapp_template import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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_iapp_template import Parameters from ansible.modules.network.f5.bigip_iapp_template import Parameters
from ansible.modules.network.f5.bigip_iapp_template import ArgumentSpec from ansible.modules.network.f5.bigip_iapp_template import ArgumentSpec
from ansible.modules.network.f5.bigip_iapp_template import ModuleManager from ansible.modules.network.f5.bigip_iapp_template import ModuleManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -63,12 +65,10 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
content=iapp content=iapp
) )
p = Parameters(args) p = Parameters(params=args)
assert p.name == 'foo.iapp' assert p.name == 'foo.iapp'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -83,12 +83,11 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, True]) mm.exists = Mock(side_effect=[False, True])
@ -107,14 +106,13 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
current1 = Parameters(load_fixture('load_sys_application_template_w_new_checksum.json')) current1 = Parameters(params=load_fixture('load_sys_application_template_w_new_checksum.json'))
current2 = Parameters(load_fixture('load_sys_application_template_w_old_checksum.json')) current2 = Parameters(params=load_fixture('load_sys_application_template_w_old_checksum.json'))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[True, True]) mm.exists = Mock(side_effect=[True, True])
@ -138,12 +136,11 @@ class TestManager(unittest.TestCase):
state='absent' state='absent'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[True, False]) mm.exists = Mock(side_effect=[True, False])
@ -162,12 +159,11 @@ class TestManager(unittest.TestCase):
state='absent' state='absent'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, False]) mm.exists = Mock(side_effect=[False, False])

@ -17,20 +17,22 @@ if sys.version_info < (2, 7):
from ansible.compat.tests import unittest from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
try: try:
from library.bigip_iapp_template import Parameters from library.bigip_iapp_template import Parameters
from library.bigip_iapp_template import ModuleManager from library.bigip_iapp_template import ModuleManager
from library.bigip_iapp_template import ArgumentSpec from library.bigip_iapp_template import ArgumentSpec
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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_iapp_template import Parameters from ansible.modules.network.f5.bigip_iapp_template import Parameters
from ansible.modules.network.f5.bigip_iapp_template import ArgumentSpec from ansible.modules.network.f5.bigip_iapp_template import ArgumentSpec
from ansible.modules.network.f5.bigip_iapp_template import ModuleManager from ansible.modules.network.f5.bigip_iapp_template import ModuleManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -63,12 +65,10 @@ class TestParameters(unittest.TestCase):
package='MyApp-0.1.0-0001.noarch.rpm', package='MyApp-0.1.0-0001.noarch.rpm',
state='present' state='present'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.package == 'MyApp-0.1.0-0001.noarch.rpm' assert p.package == 'MyApp-0.1.0-0001.noarch.rpm'
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -84,12 +84,11 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode
f5_product_name=self.spec.f5_product_name
) )
mm = ModuleManager(client) mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, True]) mm.exists = Mock(side_effect=[False, True])

@ -18,7 +18,7 @@ from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch from ansible.compat.tests.mock import patch
from ansible.compat.tests.mock import mock_open from ansible.compat.tests.mock import mock_open
from ansible.module_utils.f5_utils import AnsibleF5Client from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import PY3 from ansible.module_utils.six import PY3
try: try:
@ -27,7 +27,8 @@ try:
from library.bigip_irule import ArgumentSpec from library.bigip_irule import ArgumentSpec
from library.bigip_irule import GtmManager from library.bigip_irule import GtmManager
from library.bigip_irule import LtmManager from library.bigip_irule import LtmManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import F5ModuleError
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:
@ -36,7 +37,8 @@ except ImportError:
from ansible.modules.network.f5.bigip_irule import ArgumentSpec from ansible.modules.network.f5.bigip_irule import ArgumentSpec
from ansible.modules.network.f5.bigip_irule import GtmManager from ansible.modules.network.f5.bigip_irule import GtmManager
from ansible.modules.network.f5.bigip_irule import LtmManager from ansible.modules.network.f5.bigip_irule import LtmManager
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args from units.modules.utils import set_module_args
except ImportError: except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library") raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
@ -77,7 +79,7 @@ class TestParameters(unittest.TestCase):
name='foo', name='foo',
state='present' state='present'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.content == content.strip() assert p.content == content.strip()
def test_module_parameters_gtm(self): def test_module_parameters_gtm(self):
@ -88,7 +90,7 @@ class TestParameters(unittest.TestCase):
name='foo', name='foo',
state='present' state='present'
) )
p = Parameters(args) p = Parameters(params=args)
assert p.content == content.strip() assert p.content == content.strip()
def test_api_parameters_ltm(self): def test_api_parameters_ltm(self):
@ -96,7 +98,7 @@ class TestParameters(unittest.TestCase):
args = dict( args = dict(
apiAnonymous=content apiAnonymous=content
) )
p = Parameters(args) p = Parameters(params=args)
assert p.content == content.strip() assert p.content == content.strip()
def test_return_api_params(self): def test_return_api_params(self):
@ -107,14 +109,12 @@ class TestParameters(unittest.TestCase):
name='foo', name='foo',
state='present' state='present'
) )
p = Parameters(args) p = Parameters(params=args)
params = p.api_params() params = p.api_params()
assert 'apiAnonymous' in params assert 'apiAnonymous' in params
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
return_value=True)
class TestManager(unittest.TestCase): class TestManager(unittest.TestCase):
def setUp(self): def setUp(self):
@ -141,20 +141,19 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode,
f5_product_name=self.spec.f5_product_name,
mutually_exclusive=self.spec.mutually_exclusive, mutually_exclusive=self.spec.mutually_exclusive,
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = LtmManager(client) tm = LtmManager(module=module, params=module.params)
tm.exists = Mock(side_effect=[False, True]) tm.exists = Mock(side_effect=[False, True])
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
results = mm.exec_module() results = mm.exec_module()
@ -173,20 +172,19 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode,
f5_product_name=self.spec.f5_product_name,
mutually_exclusive=self.spec.mutually_exclusive, mutually_exclusive=self.spec.mutually_exclusive,
) )
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = GtmManager(client) tm = GtmManager(module=module, params=module.params)
tm.exists = Mock(side_effect=[False, True]) tm.exists = Mock(side_effect=[False, True])
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
results = mm.exec_module() results = mm.exec_module()
@ -205,10 +203,9 @@ class TestManager(unittest.TestCase):
user='admin' user='admin'
)) ))
client = AnsibleF5Client( module = AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode,
f5_product_name=self.spec.f5_product_name,
mutually_exclusive=self.spec.mutually_exclusive, mutually_exclusive=self.spec.mutually_exclusive,
) )
@ -219,12 +216,12 @@ class TestManager(unittest.TestCase):
with patch(builtins_name + '.open', mock_open(read_data='this is my content'), create=True): with patch(builtins_name + '.open', mock_open(read_data='this is my content'), create=True):
# Override methods in the specific type of manager # Override methods in the specific type of manager
tm = GtmManager(client) tm = GtmManager(module=module, params=module.params)
tm.exists = Mock(side_effect=[False, True]) tm.exists = Mock(side_effect=[False, True])
tm.create_on_device = Mock(return_value=True) tm.create_on_device = Mock(return_value=True)
# Override methods to force specific logic in the module to happen # Override methods to force specific logic in the module to happen
mm = ModuleManager(client) mm = ModuleManager(module=module)
mm.get_manager = Mock(return_value=tm) mm.get_manager = Mock(return_value=tm)
results = mm.exec_module() results = mm.exec_module()
@ -249,10 +246,9 @@ class TestManager(unittest.TestCase):
)) ))
with patch('ansible.module_utils.basic.AnsibleModule.fail_json', unsafe=True) as mo: with patch('ansible.module_utils.basic.AnsibleModule.fail_json', unsafe=True) as mo:
AnsibleF5Client( AnsibleModule(
argument_spec=self.spec.argument_spec, argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode, supports_check_mode=self.spec.supports_check_mode,
f5_product_name=self.spec.f5_product_name,
mutually_exclusive=self.spec.mutually_exclusive, mutually_exclusive=self.spec.mutually_exclusive,
) )
mo.assert_called_once() mo.assert_called_once()

Loading…
Cancel
Save