mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Refactors and deprecation removals (#34830)
This patch is primarily a refactor to make the validate-modules arg-spec no longer generate a traceback. It additionally includes removal of deprecated code in the virtual server module.
This commit is contained in:
parent
a10aee0fc3
commit
c548ab0f18
26 changed files with 1612 additions and 2099 deletions
|
@ -30,7 +30,6 @@ options:
|
||||||
that an existing variable is set to C(value). When C(reset) sets the
|
that an existing variable is set to C(value). When C(reset) sets the
|
||||||
variable back to the default value. At least one of value and state
|
variable back to the default value. At least one of value and state
|
||||||
C(reset) are required.
|
C(reset) are required.
|
||||||
required: False
|
|
||||||
default: present
|
default: present
|
||||||
choices:
|
choices:
|
||||||
- present
|
- present
|
||||||
|
@ -39,14 +38,9 @@ options:
|
||||||
description:
|
description:
|
||||||
- The value to set the key to. At least one of value and state C(reset)
|
- The value to set the key to. At least one of value and state C(reset)
|
||||||
are required.
|
are required.
|
||||||
required: False
|
|
||||||
notes:
|
notes:
|
||||||
- Requires the f5-sdk Python package on the host. This is as easy as pip
|
|
||||||
install f5-sdk.
|
|
||||||
- Requires BIG-IP version 12.0.0 or greater
|
- Requires BIG-IP version 12.0.0 or greater
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
requirements:
|
|
||||||
- f5-sdk
|
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
'''
|
'''
|
||||||
|
@ -98,15 +92,37 @@ value:
|
||||||
sample: false
|
sample: false
|
||||||
'''
|
'''
|
||||||
|
|
||||||
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:
|
||||||
HAS_F5SDK = False
|
# 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
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
|
@ -124,16 +140,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 name(self):
|
def name(self):
|
||||||
return self._values['key']
|
return self._values['key']
|
||||||
|
@ -143,12 +149,17 @@ class Parameters(AnsibleF5Parameters):
|
||||||
self._values['key'] = value
|
self._values['key'] = value
|
||||||
|
|
||||||
|
|
||||||
|
class Changes(Parameters):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
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 = Changes()
|
||||||
|
|
||||||
def _update_changed_options(self):
|
def _update_changed_options(self):
|
||||||
changed = {}
|
changed = {}
|
||||||
|
@ -159,10 +170,10 @@ class ModuleManager(object):
|
||||||
if attr1 != attr2:
|
if attr1 != attr2:
|
||||||
changed[key] = attr1
|
changed[key] = attr1
|
||||||
if self.want.state == 'reset':
|
if self.want.state == 'reset':
|
||||||
if str(self.want.value) == str(self.want.default_value):
|
if str(self.have.value) != str(self.have.default_value):
|
||||||
changed[self.want.key] = self.want.value
|
changed[self.want.key] = self.have.default_value
|
||||||
if changed:
|
if changed:
|
||||||
self.changes = Parameters(changed)
|
self.changes = Changes(params=changed)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -189,7 +200,7 @@ class ModuleManager(object):
|
||||||
name=self.want.key
|
name=self.want.key
|
||||||
)
|
)
|
||||||
result = resource.attrs
|
result = resource.attrs
|
||||||
return Parameters(result)
|
return Parameters(params=result)
|
||||||
|
|
||||||
def exists(self):
|
def exists(self):
|
||||||
resource = self.client.api.tm.sys.dbs.db.load(
|
resource = self.client.api.tm.sys.dbs.db.load(
|
||||||
|
@ -213,7 +224,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
|
||||||
|
@ -235,9 +246,11 @@ 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.reset_on_device()
|
||||||
|
self.want.update({'key': self.want.key})
|
||||||
|
self.want.update({'value': self.have.default_value})
|
||||||
if self.exists():
|
if self.exists():
|
||||||
return True
|
return True
|
||||||
else:
|
else:
|
||||||
|
@ -249,13 +262,13 @@ class ModuleManager(object):
|
||||||
resource = self.client.api.tm.sys.dbs.db.load(
|
resource = self.client.api.tm.sys.dbs.db.load(
|
||||||
name=self.want.key
|
name=self.want.key
|
||||||
)
|
)
|
||||||
resource.update(value=self.want.default_value)
|
resource.update(value=self.have.default_value)
|
||||||
|
|
||||||
|
|
||||||
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(
|
||||||
key=dict(required=True),
|
key=dict(required=True),
|
||||||
state=dict(
|
state=dict(
|
||||||
default='present',
|
default='present',
|
||||||
|
@ -263,27 +276,30 @@ class ArgumentSpec(object):
|
||||||
),
|
),
|
||||||
value=dict()
|
value=dict()
|
||||||
)
|
)
|
||||||
self.f5_product_name = 'bigip'
|
self.argument_spec = {}
|
||||||
|
self.argument_spec.update(f5_argument_spec)
|
||||||
|
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()
|
||||||
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__':
|
||||||
|
|
|
@ -30,48 +30,44 @@ options:
|
||||||
gui_setup:
|
gui_setup:
|
||||||
description:
|
description:
|
||||||
- C(enable) or C(disabled) the Setup utility in the browser-based
|
- C(enable) or C(disabled) the Setup utility in the browser-based
|
||||||
Configuration utility
|
Configuration utility.
|
||||||
choices: ['yes', 'no']
|
type: bool
|
||||||
lcd_display:
|
lcd_display:
|
||||||
description:
|
description:
|
||||||
- Specifies, when C(enabled), that the system menu displays on the
|
- Specifies, when C(enabled), that the system menu displays on the
|
||||||
LCD screen on the front of the unit. This setting has no effect
|
LCD screen on the front of the unit. This setting has no effect
|
||||||
when used on the VE platform.
|
when used on the VE platform.
|
||||||
choices: ['yes', 'no']
|
type: bool
|
||||||
mgmt_dhcp:
|
mgmt_dhcp:
|
||||||
description:
|
description:
|
||||||
- Specifies whether or not to enable DHCP client on the management
|
- Specifies whether or not to enable DHCP client on the management
|
||||||
interface
|
interface
|
||||||
choices: ['yes', 'no']
|
type: bool
|
||||||
net_reboot:
|
net_reboot:
|
||||||
description:
|
description:
|
||||||
- Specifies, when C(enabled), that the next time you reboot the system,
|
- Specifies, when C(enabled), that the next time you reboot the system,
|
||||||
the system boots to an ISO image on the network, rather than an
|
the system boots to an ISO image on the network, rather than an
|
||||||
internal media drive.
|
internal media drive.
|
||||||
choices: ['yes', 'no']
|
type: bool
|
||||||
quiet_boot:
|
quiet_boot:
|
||||||
description:
|
description:
|
||||||
- Specifies, when C(enabled), that the system suppresses informational
|
- Specifies, when C(enabled), that the system suppresses informational
|
||||||
text on the console during the boot cycle. When C(disabled), the
|
text on the console during the boot cycle. When C(disabled), the
|
||||||
system presents messages and informational text on the console during
|
system presents messages and informational text on the console during
|
||||||
the boot cycle.
|
the boot cycle.
|
||||||
choices: ['yes', 'no']
|
type: bool
|
||||||
security_banner:
|
security_banner:
|
||||||
description:
|
description:
|
||||||
- Specifies whether the system displays an advisory message on the
|
- Specifies whether the system displays an advisory message on the
|
||||||
login screen.
|
login screen.
|
||||||
choices: ['yes', 'no']
|
type: bool
|
||||||
state:
|
state:
|
||||||
description:
|
description:
|
||||||
- The state of the variable on the system. When C(present), guarantees
|
- The state of the variable on the system. When C(present), guarantees
|
||||||
that an existing variable is set to C(value).
|
that an existing variable is set to C(value).
|
||||||
required: false
|
|
||||||
default: present
|
default: present
|
||||||
choices:
|
choices:
|
||||||
- present
|
- present
|
||||||
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:
|
requirements:
|
||||||
- f5-sdk
|
- f5-sdk
|
||||||
|
@ -139,20 +135,40 @@ security_banner:
|
||||||
sample: enabled
|
sample: enabled
|
||||||
'''
|
'''
|
||||||
|
|
||||||
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
|
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
|
||||||
from ansible.module_utils.parsing.convert_bool import BOOLEANS
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS
|
||||||
from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
|
||||||
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE
|
||||||
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:
|
||||||
HAS_F5SDK = False
|
# 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
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
|
@ -182,46 +198,6 @@ class Parameters(AnsibleF5Parameters):
|
||||||
'mgmt_dhcp', 'net_reboot', 'quiet_boot', 'console_timeout'
|
'mgmt_dhcp', 'net_reboot', 'quiet_boot', 'console_timeout'
|
||||||
]
|
]
|
||||||
|
|
||||||
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 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
|
|
||||||
|
|
||||||
|
|
||||||
class ApiParameters(Parameters):
|
class ApiParameters(Parameters):
|
||||||
pass
|
pass
|
||||||
|
@ -323,9 +299,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.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()
|
||||||
|
|
||||||
|
@ -335,7 +312,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 = 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)
|
||||||
|
@ -351,7 +328,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
|
||||||
|
|
||||||
|
@ -369,7 +346,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))
|
||||||
|
@ -379,7 +356,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']
|
||||||
)
|
)
|
||||||
|
@ -390,13 +367,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 ApiParameters(result)
|
return ApiParameters(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
|
||||||
|
@ -412,7 +389,7 @@ class ArgumentSpec(object):
|
||||||
self.supports_check_mode = True
|
self.supports_check_mode = True
|
||||||
self.states = ['present']
|
self.states = ['present']
|
||||||
self.on_off_choices = ['enabled', 'disabled', 'True', 'False'] + list(BOOLEANS)
|
self.on_off_choices = ['enabled', 'disabled', 'True', 'False'] + list(BOOLEANS)
|
||||||
self.argument_spec = dict(
|
argument_spec = dict(
|
||||||
security_banner=dict(
|
security_banner=dict(
|
||||||
choices=self.on_off_choices
|
choices=self.on_off_choices
|
||||||
),
|
),
|
||||||
|
@ -435,39 +412,30 @@ class ArgumentSpec(object):
|
||||||
console_timeout=dict(required=False, type='int', default=None),
|
console_timeout=dict(required=False, type='int', default=None),
|
||||||
state=dict(default='present', choices=['present'])
|
state=dict(default='present', choices=['present'])
|
||||||
)
|
)
|
||||||
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__':
|
||||||
|
|
|
@ -24,11 +24,20 @@ options:
|
||||||
description:
|
description:
|
||||||
- The name of the traffic group.
|
- The name of the traffic group.
|
||||||
required: True
|
required: True
|
||||||
notes:
|
partition:
|
||||||
- Requires the f5-sdk Python package on the host. This is as easy as
|
description:
|
||||||
C(pip install f5-sdk).
|
- Device partition to manage resources on.
|
||||||
requirements:
|
default: Common
|
||||||
- f5-sdk >= 3.0.5
|
version_added: 2.5
|
||||||
|
state:
|
||||||
|
description:
|
||||||
|
- When C(present), ensures that the traffic group exists.
|
||||||
|
- When C(absent), ensures the traffic group is removed.
|
||||||
|
default: present
|
||||||
|
choices:
|
||||||
|
- present
|
||||||
|
- absent
|
||||||
|
version_added: 2.5
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
|
@ -49,18 +58,38 @@ RETURN = r'''
|
||||||
# only common fields returned
|
# only common fields returned
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.basic import env_fallback
|
||||||
|
|
||||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
HAS_DEVEL_IMPORTS = False
|
||||||
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
|
|
||||||
|
|
||||||
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:
|
||||||
HAS_F5SDK = False
|
# 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
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
|
@ -80,36 +109,6 @@ class Parameters(AnsibleF5Parameters):
|
||||||
|
|
||||||
]
|
]
|
||||||
|
|
||||||
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 = {}
|
||||||
try:
|
try:
|
||||||
|
@ -120,16 +119,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
|
|
||||||
|
|
||||||
|
|
||||||
class Changes(Parameters):
|
class Changes(Parameters):
|
||||||
pass
|
pass
|
||||||
|
@ -164,9 +153,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.want = Parameters(self.client.module.params)
|
self.client = kwargs.get('client', None)
|
||||||
|
self.want = Parameters(params=self.module.params)
|
||||||
self.changes = Changes()
|
self.changes = Changes()
|
||||||
|
|
||||||
def _set_changed_options(self):
|
def _set_changed_options(self):
|
||||||
|
@ -175,38 +165,9 @@ 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):
|
||||||
"""Sets the changed updatables when updating a resource
|
|
||||||
|
|
||||||
A module needs to know what changed to determine whether to update
|
|
||||||
a resource (or set of resources). This method accomplishes this by
|
|
||||||
invoking the Difference engine code.
|
|
||||||
|
|
||||||
Each parameter in the `Parameter` class' `updatables` array will be
|
|
||||||
given to the Difference engine's `compare` method. This is done in the
|
|
||||||
order the updatables are listed in the array.
|
|
||||||
|
|
||||||
The `compare` method updates the `changes` dictionary if the following
|
|
||||||
way,
|
|
||||||
|
|
||||||
* If `None` is returned, a change will not be registered.
|
|
||||||
* If a dictionary is returned, the `changes` dictionary will be updated
|
|
||||||
with the values in what was returned.
|
|
||||||
* Otherwise, the `changes` dictionary's key (the parameter being
|
|
||||||
compared) will be set to the value that is returned by `compare`
|
|
||||||
|
|
||||||
The dictionary behavior is in place to allow you to change the key
|
|
||||||
that is set in the `changes` dictionary. There are frequently cases
|
|
||||||
where there is not a clean API map that can be set, nor a way to
|
|
||||||
otherwise allow you to change the attribute name of the resource being
|
|
||||||
updated before it is sent off to the remote device. Using a dictionary
|
|
||||||
return value of `compare` allows you to do this.
|
|
||||||
|
|
||||||
Returns:
|
|
||||||
bool: True when changes are present. False otherwise.
|
|
||||||
"""
|
|
||||||
diff = Difference(self.want, self.have)
|
diff = Difference(self.want, self.have)
|
||||||
updatables = Parameters.updatables
|
updatables = Parameters.updatables
|
||||||
changed = dict()
|
changed = dict()
|
||||||
|
@ -220,7 +181,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
|
||||||
|
|
||||||
|
@ -252,7 +213,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']
|
||||||
)
|
)
|
||||||
|
@ -274,13 +235,13 @@ 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
|
||||||
|
|
||||||
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():
|
||||||
|
@ -293,7 +254,7 @@ class ModuleManager(object):
|
||||||
raise F5ModuleError(
|
raise F5ModuleError(
|
||||||
"Traffic groups can only be created in the /Common partition"
|
"Traffic groups can only be created in the /Common partition"
|
||||||
)
|
)
|
||||||
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
|
||||||
|
@ -333,49 +294,44 @@ class ModuleManager(object):
|
||||||
partition=self.want.partition
|
partition=self.want.partition
|
||||||
)
|
)
|
||||||
result = resource.attrs
|
result = resource.attrs
|
||||||
return Parameters(result)
|
return Parameters(params=result)
|
||||||
|
|
||||||
|
|
||||||
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),
|
||||||
state=dict(default='present', choices=['absent', 'present'])
|
state=dict(default='present', choices=['absent', 'present']),
|
||||||
|
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__':
|
||||||
|
|
|
@ -87,8 +87,6 @@ options:
|
||||||
- installed
|
- installed
|
||||||
- present
|
- present
|
||||||
notes:
|
notes:
|
||||||
- Requires the f5-sdk Python package on the host. This is as easy as
|
|
||||||
pip install f5-sdk.
|
|
||||||
- Only the most basic checks are performed by this module. Other checks and
|
- Only the most basic checks are performed by this module. Other checks and
|
||||||
considerations need to be taken into account. See the following URL.
|
considerations need to be taken into account. See the following URL.
|
||||||
https://support.f5.com/kb/en-us/solutions/public/11000/300/sol11318.html
|
https://support.f5.com/kb/en-us/solutions/public/11000/300/sol11318.html
|
||||||
|
@ -110,8 +108,6 @@ notes:
|
||||||
- This module does not support restoring encrypted archives on replacement
|
- This module does not support restoring encrypted archives on replacement
|
||||||
RMA units.
|
RMA units.
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
requirements:
|
|
||||||
- f5-sdk
|
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
'''
|
'''
|
||||||
|
@ -182,15 +178,41 @@ RETURN = r'''
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import re
|
import re
|
||||||
import sys
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from distutils.version import LooseVersion
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
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
|
||||||
|
|
||||||
|
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:
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
@ -200,11 +222,6 @@ except ImportError:
|
||||||
except ImportError:
|
except ImportError:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
try:
|
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
|
||||||
except ImportError:
|
|
||||||
HAS_F5SDK = False
|
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
api_map = {}
|
api_map = {}
|
||||||
|
@ -292,14 +309,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.kwargs = kwargs
|
||||||
|
|
||||||
def exec_module(self):
|
def exec_module(self):
|
||||||
if self.is_version_v1():
|
if self.is_version_v1():
|
||||||
manager = V1Manager(self.client)
|
manager = V1Manager(**self.kwargs)
|
||||||
else:
|
else:
|
||||||
manager = V2Manager(self.client)
|
manager = V2Manager(**self.kwargs)
|
||||||
|
|
||||||
return manager.exec_module()
|
return manager.exec_module()
|
||||||
|
|
||||||
|
@ -321,10 +339,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.have = None
|
self.client = kwargs.get('client', None)
|
||||||
self.want = Parameters(self.client.module.params)
|
self.want = Parameters(params=self.module.params)
|
||||||
self.changes = Parameters()
|
self.changes = Parameters()
|
||||||
|
|
||||||
def exec_module(self):
|
def exec_module(self):
|
||||||
|
@ -352,7 +370,7 @@ class BaseManager(object):
|
||||||
return self.create()
|
return self.create()
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
if self.client.check_mode:
|
if self.module.check_mode:
|
||||||
if self.want.force:
|
if self.want.force:
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
@ -365,7 +383,7 @@ class BaseManager(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
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 not self.exists():
|
if not self.exists():
|
||||||
|
@ -386,7 +404,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():
|
||||||
|
@ -466,7 +484,6 @@ class V1Manager(BaseManager):
|
||||||
* No API to upload UCS files
|
* No API to upload UCS files
|
||||||
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def create_on_device(self):
|
def create_on_device(self):
|
||||||
remote_path = "/var/local/ucs"
|
remote_path = "/var/local/ucs"
|
||||||
tpath_name = '/var/config/rest/downloads'
|
tpath_name = '/var/config/rest/downloads'
|
||||||
|
@ -563,7 +580,7 @@ class V2Manager(V1Manager):
|
||||||
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(
|
||||||
force=dict(
|
force=dict(
|
||||||
type='bool',
|
type='bool',
|
||||||
default='no'
|
default='no'
|
||||||
|
@ -585,30 +602,30 @@ class ArgumentSpec(object):
|
||||||
),
|
),
|
||||||
ucs=dict(required=True)
|
ucs=dict(required=True)
|
||||||
)
|
)
|
||||||
self.f5_product_name = 'bigip'
|
self.argument_spec = {}
|
||||||
|
self.argument_spec.update(f5_argument_spec)
|
||||||
|
self.argument_spec.update(argument_spec)
|
||||||
|
|
||||||
|
|
||||||
def main():
|
def main():
|
||||||
if not HAS_F5SDK:
|
|
||||||
raise F5ModuleError("The python f5-sdk module is required")
|
|
||||||
|
|
||||||
if sys.version_info < (2, 7):
|
|
||||||
raise F5ModuleError("F5 Ansible modules require Python >= 2.7")
|
|
||||||
|
|
||||||
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__':
|
||||||
|
|
|
@ -74,13 +74,14 @@ options:
|
||||||
choices:
|
choices:
|
||||||
- always
|
- always
|
||||||
- on_create
|
- on_create
|
||||||
|
partition:
|
||||||
|
description:
|
||||||
|
- Device partition to manage resources on.
|
||||||
|
default: Common
|
||||||
|
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 BIG-IP versions >= 12.0.0
|
- Requires BIG-IP versions >= 12.0.0
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
requirements:
|
|
||||||
- f5-sdk
|
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
- Wojciech Wypior (@wojtek0806)
|
- Wojciech Wypior (@wojtek0806)
|
||||||
|
@ -191,24 +192,45 @@ shell:
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.basic import env_fallback
|
||||||
from distutils.version import LooseVersion
|
from distutils.version import LooseVersion
|
||||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
|
||||||
from ansible.module_utils.f5_utils import AnsibleF5Parameters
|
HAS_DEVEL_IMPORTS = False
|
||||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
try:
|
||||||
from ansible.module_utils.six import iteritems
|
# Sideband repository used for dev
|
||||||
from collections import defaultdict
|
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 StringIO import StringIO
|
from StringIO import StringIO
|
||||||
except ImportError:
|
except ImportError:
|
||||||
from io import StringIO
|
from io import StringIO
|
||||||
|
|
||||||
try:
|
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
|
||||||
except ImportError:
|
|
||||||
HAS_F5SDK = False
|
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
api_map = {
|
api_map = {
|
||||||
|
@ -228,36 +250,6 @@ class Parameters(AnsibleF5Parameters):
|
||||||
'shell', 'partitionAccess', 'description', 'name', 'password'
|
'shell', 'partitionAccess', 'description', 'name', 'password'
|
||||||
]
|
]
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def partition_access(self):
|
def partition_access(self):
|
||||||
"""Partition access values will require some transformation.
|
"""Partition access values will require some transformation.
|
||||||
|
@ -324,18 +316,28 @@ 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.kwargs = kwargs
|
||||||
|
|
||||||
def exec_module(self):
|
def exec_module(self):
|
||||||
if self.is_root_username_credential():
|
if self.is_root_username_credential():
|
||||||
manager = RootUserManager(self.client)
|
manager = self.get_manager('root')
|
||||||
elif self.is_version_less_than_13():
|
elif self.is_version_less_than_13():
|
||||||
manager = UnparitionedManager(self.client)
|
manager = self.get_manager('v1')
|
||||||
else:
|
else:
|
||||||
manager = PartitionedManager(self.client)
|
manager = self.get_manager('v2')
|
||||||
return manager.exec_module()
|
return manager.exec_module()
|
||||||
|
|
||||||
|
def get_manager(self, type):
|
||||||
|
if type == 'root':
|
||||||
|
return RootUserManager(**self.kwargs)
|
||||||
|
elif type == 'v1':
|
||||||
|
return UnparitionedManager(**self.kwargs)
|
||||||
|
elif type == 'v2':
|
||||||
|
return PartitionedManager(**self.kwargs)
|
||||||
|
|
||||||
def is_version_less_than_13(self):
|
def is_version_less_than_13(self):
|
||||||
"""Checks to see if the TMOS version is less than 13
|
"""Checks to see if the TMOS version is less than 13
|
||||||
|
|
||||||
|
@ -351,17 +353,18 @@ class ModuleManager(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def is_root_username_credential(self):
|
def is_root_username_credential(self):
|
||||||
user = self.client.module.params.get('username_credential', None)
|
user = self.module.params.get('username_credential', None)
|
||||||
if user == 'root':
|
if user == 'root':
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
||||||
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 = Parameters()
|
self.changes = Parameters()
|
||||||
|
|
||||||
def exec_module(self):
|
def exec_module(self):
|
||||||
|
@ -388,7 +391,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 = {}
|
||||||
|
@ -411,7 +414,7 @@ class BaseManager(object):
|
||||||
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
|
||||||
|
|
||||||
|
@ -481,13 +484,13 @@ 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
|
||||||
|
|
||||||
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():
|
||||||
|
@ -499,7 +502,7 @@ class BaseManager(object):
|
||||||
if self.want.shell == 'bash':
|
if self.want.shell == 'bash':
|
||||||
self.validate_shell_parameter()
|
self.validate_shell_parameter()
|
||||||
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
|
||||||
|
@ -518,7 +521,7 @@ class UnparitionedManager(BaseManager):
|
||||||
def read_current_from_device(self):
|
def read_current_from_device(self):
|
||||||
tmp_res = self.client.api.tm.auth.users.user.load(name=self.want.name)
|
tmp_res = self.client.api.tm.auth.users.user.load(name=self.want.name)
|
||||||
result = tmp_res.attrs
|
result = tmp_res.attrs
|
||||||
return Parameters(result)
|
return Parameters(params=result)
|
||||||
|
|
||||||
def exists(self):
|
def exists(self):
|
||||||
return self.client.api.tm.auth.users.user.exists(name=self.want.name)
|
return self.client.api.tm.auth.users.user.exists(name=self.want.name)
|
||||||
|
@ -570,7 +573,7 @@ class PartitionedManager(BaseManager):
|
||||||
def read_current_from_device(self):
|
def read_current_from_device(self):
|
||||||
resource = self._read_one_resource_from_collection()
|
resource = self._read_one_resource_from_collection()
|
||||||
result = resource.attrs
|
result = resource.attrs
|
||||||
return Parameters(result)
|
return Parameters(params=result)
|
||||||
|
|
||||||
def exists(self):
|
def exists(self):
|
||||||
collection = self.client.api.tm.auth.users.get_collection(
|
collection = self.client.api.tm.auth.users.get_collection(
|
||||||
|
@ -646,7 +649,7 @@ class RootUserManager(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(
|
||||||
name=dict(
|
name=dict(
|
||||||
required=True,
|
required=True,
|
||||||
aliases=['username_credential']
|
aliases=['username_credential']
|
||||||
|
@ -664,41 +667,37 @@ class ArgumentSpec(object):
|
||||||
update_password=dict(
|
update_password=dict(
|
||||||
default='always',
|
default='always',
|
||||||
choices=['always', 'on_create']
|
choices=['always', 'on_create']
|
||||||
|
),
|
||||||
|
state=dict(default='present', choices=['absent', 'present']),
|
||||||
|
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__':
|
||||||
|
|
|
@ -112,9 +112,11 @@ options:
|
||||||
- The number you can specify depends on the type of hardware you have.
|
- The number you can specify depends on the type of hardware you have.
|
||||||
- In the event of a reboot, the system persists the guest to the same slot on
|
- In the event of a reboot, the system persists the guest to the same slot on
|
||||||
which it ran prior to the reboot.
|
which it ran prior to the reboot.
|
||||||
|
partition:
|
||||||
|
description:
|
||||||
|
- Device partition to manage resources on.
|
||||||
|
default: Common
|
||||||
notes:
|
notes:
|
||||||
- Requires the f5-sdk Python package on the host. This is as easy as pip
|
|
||||||
install f5-sdk.
|
|
||||||
- This module can take a lot of time to deploy vCMP guests. This is an intrinsic
|
- This module can take a lot of time to deploy vCMP guests. This is an intrinsic
|
||||||
limitation of the vCMP system because it is booting real VMs on the BIG-IP
|
limitation of the vCMP system because it is booting real VMs on the BIG-IP
|
||||||
device. This boot time is very similar in length to the time it takes to
|
device. This boot time is very similar in length to the time it takes to
|
||||||
|
@ -123,8 +125,6 @@ notes:
|
||||||
means that it is not unusual for a vCMP host with many guests to take a
|
means that it is not unusual for a vCMP host with many guests to take a
|
||||||
long time (60+ minutes) to reboot and bring all the guests online. The
|
long time (60+ minutes) to reboot and bring all the guests online. The
|
||||||
BIG-IP chassis will be available before all vCMP guests are online.
|
BIG-IP chassis will be available before all vCMP guests are online.
|
||||||
requirements:
|
|
||||||
- f5-sdk >= 3.0.3
|
|
||||||
- netaddr
|
- netaddr
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
author:
|
author:
|
||||||
|
@ -173,16 +173,41 @@ vlans:
|
||||||
sample: ['/Common/vlan1', '/Common/vlan2']
|
sample: ['/Common/vlan1', '/Common/vlan2']
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
import time
|
||||||
|
|
||||||
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 collections import defaultdict
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
import time
|
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:
|
||||||
from netaddr import IPAddress, AddrFormatError, IPNetwork
|
from netaddr import IPAddress, AddrFormatError, IPNetwork
|
||||||
|
@ -192,7 +217,6 @@ except ImportError:
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from f5.utils.responses.handlers import Stats
|
from f5.utils.responses.handlers import Stats
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_F5SDK = False
|
HAS_F5SDK = False
|
||||||
|
|
||||||
|
@ -222,37 +246,6 @@ class Parameters(AnsibleF5Parameters):
|
||||||
'state'
|
'state'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, params=None, client=None):
|
|
||||||
self._values = defaultdict(lambda: None)
|
|
||||||
self._values['__warnings'] = []
|
|
||||||
if params:
|
|
||||||
self.update(params=params)
|
|
||||||
self.client = client
|
|
||||||
|
|
||||||
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)
|
||||||
|
@ -268,16 +261,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 mgmt_route(self):
|
def mgmt_route(self):
|
||||||
if self._values['mgmt_route'] is None:
|
if self._values['mgmt_route'] is None:
|
||||||
|
@ -394,9 +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.want = Parameters(client=client, params=self.client.module.params)
|
self.client = kwargs.get('client', None)
|
||||||
|
self.want = Parameters(client=self.client, params=self.module.params)
|
||||||
self.changes = Changes()
|
self.changes = Changes()
|
||||||
|
|
||||||
def _set_changed_options(self):
|
def _set_changed_options(self):
|
||||||
|
@ -405,7 +389,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)
|
||||||
|
@ -418,7 +402,7 @@ class ModuleManager(object):
|
||||||
else:
|
else:
|
||||||
changed[k] = change
|
changed[k] = change
|
||||||
if changed:
|
if changed:
|
||||||
self.changes = Parameters(changed)
|
self.changes = Parameters(params=changed)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -450,7 +434,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']
|
||||||
)
|
)
|
||||||
|
@ -476,7 +460,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()
|
||||||
if self.want.state == 'provisioned':
|
if self.want.state == 'provisioned':
|
||||||
|
@ -488,7 +472,7 @@ class ModuleManager(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def remove(self):
|
def remove(self):
|
||||||
if self.client.check_mode:
|
if self.module.check_mode:
|
||||||
return True
|
return True
|
||||||
if self.want.delete_virtual_disk:
|
if self.want.delete_virtual_disk:
|
||||||
self.have = self.read_current_from_device()
|
self.have = self.read_current_from_device()
|
||||||
|
@ -501,7 +485,7 @@ class ModuleManager(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
|
||||||
if self.want.mgmt_tuple.subnet is None:
|
if self.want.mgmt_tuple.subnet is None:
|
||||||
self.want.update(dict(
|
self.want.update(dict(
|
||||||
|
@ -547,7 +531,7 @@ class ModuleManager(object):
|
||||||
name=self.want.name
|
name=self.want.name
|
||||||
)
|
)
|
||||||
result = resource.attrs
|
result = resource.attrs
|
||||||
return Parameters(result)
|
return Parameters(params=result)
|
||||||
|
|
||||||
def remove_virtual_disk(self):
|
def remove_virtual_disk(self):
|
||||||
if self.virtual_disk_exists():
|
if self.virtual_disk_exists():
|
||||||
|
@ -666,7 +650,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),
|
||||||
vlans=dict(type='list'),
|
vlans=dict(type='list'),
|
||||||
mgmt_network=dict(choices=['bridged', 'isolated', 'host only']),
|
mgmt_network=dict(choices=['bridged', 'isolated', 'host only']),
|
||||||
|
@ -680,47 +664,41 @@ class ArgumentSpec(object):
|
||||||
delete_virtual_disk=dict(
|
delete_virtual_disk=dict(
|
||||||
type='bool', default='no'
|
type='bool', default='no'
|
||||||
),
|
),
|
||||||
cores_per_slot=dict(type='int')
|
cores_per_slot=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)
|
||||||
self.required_if = [
|
self.required_if = [
|
||||||
['mgmt_network', 'bridged', ['mgmt_address']]
|
['mgmt_network', 'bridged', ['mgmt_address']]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
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__':
|
||||||
|
|
|
@ -100,14 +100,11 @@ options:
|
||||||
- Specifies whether the system uses route advertisement for this
|
- Specifies whether the system uses route advertisement for this
|
||||||
virtual address. When disabled, the system does not advertise
|
virtual address. When disabled, the system does not advertise
|
||||||
routes for this virtual address.
|
routes for this virtual address.
|
||||||
choices:
|
type: bool
|
||||||
- yes
|
|
||||||
- no
|
|
||||||
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
|
||||||
traffic_group:
|
traffic_group:
|
||||||
description:
|
description:
|
||||||
|
@ -116,13 +113,10 @@ options:
|
||||||
will be used.
|
will be used.
|
||||||
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 pip
|
- Requires the netaddr Python package on the host. This is as easy as pip
|
||||||
install netaddr.
|
install netaddr.
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
requirements:
|
requirements:
|
||||||
- f5-sdk
|
|
||||||
- netaddr
|
- netaddr
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
|
@ -193,24 +187,47 @@ state:
|
||||||
sample: disabled
|
sample: disabled
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
from ansible.module_utils.basic import env_fallback
|
||||||
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
|
||||||
|
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE
|
||||||
|
|
||||||
|
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 netaddr
|
import netaddr
|
||||||
HAS_NETADDR = True
|
HAS_NETADDR = True
|
||||||
except ImportError:
|
except ImportError:
|
||||||
HAS_NETADDR = False
|
HAS_NETADDR = False
|
||||||
|
|
||||||
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_FALSE
|
|
||||||
|
|
||||||
try:
|
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
|
||||||
except ImportError:
|
|
||||||
HAS_F5SDK = False
|
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
api_map = {
|
api_map = {
|
||||||
|
@ -349,17 +366,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 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
|
|
||||||
|
|
||||||
|
|
||||||
class Changes(Parameters):
|
class Changes(Parameters):
|
||||||
pass
|
pass
|
||||||
|
@ -393,10 +399,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(client=self.client, params=self.module.params)
|
||||||
self.changes = Changes()
|
self.changes = Changes()
|
||||||
|
|
||||||
def _set_changed_options(self):
|
def _set_changed_options(self):
|
||||||
|
@ -405,7 +412,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)
|
||||||
|
@ -421,7 +428,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
|
||||||
|
|
||||||
|
@ -467,7 +474,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 exists(self):
|
def exists(self):
|
||||||
result = self.client.api.tm.ltm.virtual_address_s.virtual_address.exists(
|
result = self.client.api.tm.ltm.virtual_address_s.virtual_address.exists(
|
||||||
|
@ -481,18 +488,18 @@ class ModuleManager(object):
|
||||||
if self.want.netmask is not None:
|
if self.want.netmask is not None:
|
||||||
if self.have.netmask != self.want.netmask:
|
if self.have.netmask != self.want.netmask:
|
||||||
raise F5ModuleError(
|
raise F5ModuleError(
|
||||||
"The netmask cannot be changed. Delete and recreate"
|
"The netmask cannot be changed. Delete and recreate "
|
||||||
"the virtual address if you need to do this."
|
"the virtual address if you need to do this."
|
||||||
)
|
)
|
||||||
if self.want.address is not None:
|
if self.want.address is not None:
|
||||||
if self.have.address != self.want.address:
|
if self.have.address != self.want.address:
|
||||||
raise F5ModuleError(
|
raise F5ModuleError(
|
||||||
"The address cannot be changed. Delete and recreate"
|
"The address cannot be changed. Delete and recreate "
|
||||||
"the virtual address if you need to do this."
|
"the virtual address if you need to do this."
|
||||||
)
|
)
|
||||||
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
|
||||||
|
@ -509,7 +516,7 @@ class ModuleManager(object):
|
||||||
self._set_changed_options()
|
self._set_changed_options()
|
||||||
if self.want.traffic_group is None:
|
if self.want.traffic_group 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()
|
||||||
if self.exists():
|
if self.exists():
|
||||||
|
@ -527,7 +534,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():
|
||||||
|
@ -545,7 +552,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(
|
||||||
state=dict(
|
state=dict(
|
||||||
default='present',
|
default='present',
|
||||||
choices=['present', 'absent', 'disabled', 'enabled']
|
choices=['present', 'absent', 'disabled', 'enabled']
|
||||||
|
@ -577,29 +584,38 @@ class ArgumentSpec(object):
|
||||||
use_route_advertisement=dict(
|
use_route_advertisement=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'
|
self.argument_spec = {}
|
||||||
|
self.argument_spec.update(f5_argument_spec)
|
||||||
|
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")
|
||||||
|
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()
|
||||||
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__':
|
||||||
|
|
|
@ -137,14 +137,6 @@ options:
|
||||||
- Default Profile which manages the session persistence.
|
- Default Profile which manages the session persistence.
|
||||||
- If you want to remove the existing default persistence profile, specify an
|
- If you want to remove the existing default persistence profile, specify an
|
||||||
empty value; C(""). See the documentation for an example.
|
empty value; C(""). See the documentation for an example.
|
||||||
route_advertisement_state:
|
|
||||||
description:
|
|
||||||
- Enable route advertisement for destination.
|
|
||||||
- Deprecated in 2.4. Use the C(bigip_virtual_address) module instead.
|
|
||||||
choices:
|
|
||||||
- enabled
|
|
||||||
- disabled
|
|
||||||
version_added: "2.3"
|
|
||||||
description:
|
description:
|
||||||
description:
|
description:
|
||||||
- Virtual server description.
|
- Virtual server description.
|
||||||
|
@ -171,12 +163,9 @@ options:
|
||||||
version_added: 2.5
|
version_added: 2.5
|
||||||
notes:
|
notes:
|
||||||
- Requires BIG-IP software version >= 11
|
- Requires BIG-IP software version >= 11
|
||||||
- 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 pip
|
- Requires the netaddr Python package on the host. This is as easy as pip
|
||||||
install netaddr.
|
install netaddr.
|
||||||
requirements:
|
requirements:
|
||||||
- f5-sdk
|
|
||||||
- netaddr
|
- netaddr
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
author:
|
author:
|
||||||
|
@ -381,18 +370,38 @@ metadata:
|
||||||
|
|
||||||
import re
|
import re
|
||||||
|
|
||||||
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
|
|
||||||
from collections import namedtuple
|
from collections import namedtuple
|
||||||
|
|
||||||
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:
|
||||||
HAS_F5SDK = False
|
# 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 netaddr
|
import netaddr
|
||||||
|
@ -402,100 +411,6 @@ except ImportError:
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
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
|
|
||||||
|
|
||||||
def to_return(self):
|
|
||||||
result = {}
|
|
||||||
for returnable in self.returnables:
|
|
||||||
try:
|
|
||||||
result[returnable] = getattr(self, returnable)
|
|
||||||
except Exception as ex:
|
|
||||||
pass
|
|
||||||
result = self._filter_params(result)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _fqdn_name(self, value):
|
|
||||||
if value is not None and not value.startswith('/'):
|
|
||||||
return '/{0}/{1}'.format(self.partition, value)
|
|
||||||
return value
|
|
||||||
|
|
||||||
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
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualAddressParameters(Parameters):
|
|
||||||
api_map = {
|
|
||||||
'routeAdvertisement': 'route_advertisement_state'
|
|
||||||
}
|
|
||||||
returnables = [
|
|
||||||
'route_advertisement_state'
|
|
||||||
]
|
|
||||||
|
|
||||||
updatables = [
|
|
||||||
'route_advertisement_state'
|
|
||||||
]
|
|
||||||
|
|
||||||
api_attributes = [
|
|
||||||
'routeAdvertisement'
|
|
||||||
]
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualAddressModuleParameters(VirtualAddressParameters):
|
|
||||||
@property
|
|
||||||
def route_advertisement_state(self):
|
|
||||||
# TODO: Remove in 2.5
|
|
||||||
if self._values['route_advertisement_state'] is None:
|
|
||||||
return None
|
|
||||||
if self._values['__warnings'] is None:
|
|
||||||
self._values['__warnings'] = []
|
|
||||||
self._values['__warnings'].append(
|
|
||||||
dict(
|
|
||||||
msg="Usage of the 'route_advertisement_state' parameter is deprecated. Use the bigip_virtual_address module instead",
|
|
||||||
version='2.4'
|
|
||||||
)
|
|
||||||
)
|
|
||||||
return str(self._values['route_advertisement_state'])
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualAddressApiParameters(VirtualAddressParameters):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualServerParameters(Parameters):
|
|
||||||
api_map = {
|
api_map = {
|
||||||
'sourceAddressTranslation': 'snat',
|
'sourceAddressTranslation': 'snat',
|
||||||
'fallbackPersistence': 'fallback_persistence_profile',
|
'fallbackPersistence': 'fallback_persistence_profile',
|
||||||
|
@ -566,12 +481,25 @@ class VirtualServerParameters(Parameters):
|
||||||
'vlans_disabled'
|
'vlans_disabled'
|
||||||
]
|
]
|
||||||
|
|
||||||
def __init__(self, params=None):
|
profiles_mutex = [
|
||||||
super(VirtualServerParameters, self).__init__(params)
|
'sip', 'sipsession', 'iiop', 'rtsp', 'http', 'diameter',
|
||||||
self.profiles_mutex = [
|
'diametersession', 'radius', 'ftp', 'tftp', 'dns', 'pptp', 'fix'
|
||||||
'sip', 'sipsession', 'iiop', 'rtsp', 'http', 'diameter',
|
]
|
||||||
'diametersession', 'radius', 'ftp', 'tftp', 'dns', 'pptp', 'fix'
|
|
||||||
]
|
def to_return(self):
|
||||||
|
result = {}
|
||||||
|
for returnable in self.returnables:
|
||||||
|
try:
|
||||||
|
result[returnable] = getattr(self, returnable)
|
||||||
|
except Exception as ex:
|
||||||
|
pass
|
||||||
|
result = self._filter_params(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
def _fqdn_name(self, value):
|
||||||
|
if value is not None and not value.startswith('/'):
|
||||||
|
return '/{0}/{1}'.format(self.partition, value)
|
||||||
|
return value
|
||||||
|
|
||||||
def is_valid_ip(self, value):
|
def is_valid_ip(self, value):
|
||||||
try:
|
try:
|
||||||
|
@ -618,7 +546,7 @@ class VirtualServerParameters(Parameters):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class VirtualServerApiParameters(VirtualServerParameters):
|
class ApiParameters(Parameters):
|
||||||
@property
|
@property
|
||||||
def destination(self):
|
def destination(self):
|
||||||
if self._values['destination'] is None:
|
if self._values['destination'] is None:
|
||||||
|
@ -648,7 +576,7 @@ class VirtualServerApiParameters(VirtualServerParameters):
|
||||||
if self._values['destination'] is None:
|
if self._values['destination'] is None:
|
||||||
result = Destination(ip=None, port=None, route_domain=None)
|
result = Destination(ip=None, port=None, route_domain=None)
|
||||||
return result
|
return result
|
||||||
destination = re.sub(r'^/[a-zA-Z_.-]+/', '', self._values['destination'])
|
destination = re.sub(r'^/[a-zA-Z0-9_.-]+/', '', self._values['destination'])
|
||||||
|
|
||||||
if self.is_valid_ip(destination):
|
if self.is_valid_ip(destination):
|
||||||
result = Destination(
|
result = Destination(
|
||||||
|
@ -816,7 +744,7 @@ class VirtualServerApiParameters(VirtualServerParameters):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class VirtualServerModuleParameters(VirtualServerParameters):
|
class ModuleParameters(Parameters):
|
||||||
def _handle_profile_context(self, tmp):
|
def _handle_profile_context(self, tmp):
|
||||||
if 'context' not in tmp:
|
if 'context' not in tmp:
|
||||||
tmp['context'] = 'all'
|
tmp['context'] = 'all'
|
||||||
|
@ -1106,7 +1034,11 @@ class VirtualServerModuleParameters(VirtualServerParameters):
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
class VirtualServerUsableChanges(VirtualServerParameters):
|
class Changes(Parameters):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class UsableChanges(Changes):
|
||||||
@property
|
@property
|
||||||
def vlans(self):
|
def vlans(self):
|
||||||
if self._values['vlans'] is None:
|
if self._values['vlans'] is None:
|
||||||
|
@ -1118,11 +1050,7 @@ class VirtualServerUsableChanges(VirtualServerParameters):
|
||||||
return self._values['vlans']
|
return self._values['vlans']
|
||||||
|
|
||||||
|
|
||||||
class VirtualAddressUsableChanges(VirtualAddressParameters):
|
class ReportableChanges(Changes):
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class VirtualServerReportableChanges(VirtualServerParameters):
|
|
||||||
@property
|
@property
|
||||||
def snat(self):
|
def snat(self):
|
||||||
if self._values['snat'] is None:
|
if self._values['snat'] is None:
|
||||||
|
@ -1137,13 +1065,13 @@ class VirtualServerReportableChanges(VirtualServerParameters):
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def destination(self):
|
def destination(self):
|
||||||
params = VirtualServerApiParameters(dict(destination=self._values['destination']))
|
params = ApiParameters(params=dict(destination=self._values['destination']))
|
||||||
result = params.destination_tuple.ip
|
result = params.destination_tuple.ip
|
||||||
return result
|
return result
|
||||||
|
|
||||||
@property
|
@property
|
||||||
def port(self):
|
def port(self):
|
||||||
params = VirtualServerApiParameters(dict(destination=self._values['destination']))
|
params = ApiParameters(params=dict(destination=self._values['destination']))
|
||||||
result = params.destination_tuple.port
|
result = params.destination_tuple.port
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
@ -1175,10 +1103,6 @@ class VirtualServerReportableChanges(VirtualServerParameters):
|
||||||
return self._values['vlans']
|
return self._values['vlans']
|
||||||
|
|
||||||
|
|
||||||
class VirtualAddressReportableChanges(VirtualAddressParameters):
|
|
||||||
pass
|
|
||||||
|
|
||||||
|
|
||||||
class Difference(object):
|
class Difference(object):
|
||||||
def __init__(self, want, have=None):
|
def __init__(self, want, have=None):
|
||||||
self.have = have
|
self.have = have
|
||||||
|
@ -1461,49 +1385,12 @@ 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)
|
||||||
def exec_module(self):
|
self.have = ApiParameters()
|
||||||
managers = list()
|
self.want = ModuleParameters(client=self.client, params=self.module.params)
|
||||||
managers.append(self.get_manager('virtual_server'))
|
self.changes = UsableChanges()
|
||||||
if self.client.module.params['route_advertisement_state'] is not None:
|
|
||||||
managers.append(self.get_manager('virtual_address'))
|
|
||||||
result = self.execute_managers(managers)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def execute_managers(self, managers):
|
|
||||||
results = dict(changed=False)
|
|
||||||
for manager in managers:
|
|
||||||
result = manager.exec_module()
|
|
||||||
for k, v in iteritems(result):
|
|
||||||
if k == 'changed':
|
|
||||||
if v is True:
|
|
||||||
results['changed'] = True
|
|
||||||
else:
|
|
||||||
results[k] = v
|
|
||||||
return results
|
|
||||||
|
|
||||||
def get_manager(self, type):
|
|
||||||
vsm = VirtualServerManager(self.client)
|
|
||||||
if type == 'virtual_server':
|
|
||||||
return vsm
|
|
||||||
elif type == 'virtual_address':
|
|
||||||
self.set_name_of_virtual_address()
|
|
||||||
result = VirtualAddressManager(self.client)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def set_name_of_virtual_address(self):
|
|
||||||
mgr = VirtualServerManager(self.client)
|
|
||||||
params = mgr.read_current_from_device()
|
|
||||||
destination = params.destination_tuple
|
|
||||||
self.client.module.params['name'] = destination.ip
|
|
||||||
|
|
||||||
|
|
||||||
class BaseManager(object):
|
|
||||||
def __init__(self, client):
|
|
||||||
self.client = client
|
|
||||||
self.have = None
|
|
||||||
|
|
||||||
def exec_module(self):
|
def exec_module(self):
|
||||||
changed = False
|
changed = False
|
||||||
|
@ -1518,7 +1405,7 @@ class BaseManager(object):
|
||||||
except iControlUnexpectedHTTPError as e:
|
except iControlUnexpectedHTTPError as e:
|
||||||
raise F5ModuleError(str(e))
|
raise F5ModuleError(str(e))
|
||||||
|
|
||||||
reportable = self.get_reportable_changes()
|
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))
|
||||||
|
@ -1528,7 +1415,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']
|
||||||
)
|
)
|
||||||
|
@ -1548,23 +1435,11 @@ 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
|
||||||
|
|
||||||
def create(self):
|
|
||||||
if self.client.check_mode:
|
|
||||||
return True
|
|
||||||
|
|
||||||
# This must be changed back to a list to make a valid REST API
|
|
||||||
# value. The module manipulates this as a normal dictionary
|
|
||||||
if self.want.default_persistence_profile is not None:
|
|
||||||
self.want.update({'default_persistence_profile': [self.want.default_persistence_profile]})
|
|
||||||
|
|
||||||
self.create_on_device()
|
|
||||||
return True
|
|
||||||
|
|
||||||
def should_update(self):
|
def should_update(self):
|
||||||
result = self._update_changed_options()
|
result = self._update_changed_options()
|
||||||
if result:
|
if result:
|
||||||
|
@ -1572,36 +1447,28 @@ 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():
|
||||||
raise F5ModuleError("Failed to delete the resource")
|
raise F5ModuleError("Failed to delete the resource")
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
class VirtualServerManager(BaseManager):
|
|
||||||
def __init__(self, client):
|
|
||||||
super(VirtualServerManager, self).__init__(client)
|
|
||||||
self.have = None
|
|
||||||
self.want = VirtualServerModuleParameters(self.client.module.params)
|
|
||||||
self.changes = VirtualServerUsableChanges()
|
|
||||||
|
|
||||||
def get_reportable_changes(self):
|
def get_reportable_changes(self):
|
||||||
result = VirtualServerReportableChanges(self.changes.to_return())
|
result = ReportableChanges(params=self.changes.to_return())
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _set_changed_options(self):
|
def _set_changed_options(self):
|
||||||
changed = {}
|
changed = {}
|
||||||
for key in VirtualServerParameters.returnables:
|
for key in Parameters.returnables:
|
||||||
if getattr(self.want, key) is not None:
|
if getattr(self.want, key) is not None:
|
||||||
changed[key] = getattr(self.want, key)
|
changed[key] = getattr(self.want, key)
|
||||||
if changed:
|
if changed:
|
||||||
self.changes = VirtualServerUsableChanges(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)
|
||||||
updatables = VirtualServerParameters.updatables
|
updatables = Parameters.updatables
|
||||||
changed = dict()
|
changed = dict()
|
||||||
for k in updatables:
|
for k in updatables:
|
||||||
change = diff.compare(k)
|
change = diff.compare(k)
|
||||||
|
@ -1613,7 +1480,7 @@ class VirtualServerManager(BaseManager):
|
||||||
else:
|
else:
|
||||||
changed[k] = change
|
changed[k] = change
|
||||||
if changed:
|
if changed:
|
||||||
self.changes = VirtualServerUsableChanges(changed)
|
self.changes = UsableChanges(params=changed)
|
||||||
return True
|
return True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
@ -1628,6 +1495,11 @@ class VirtualServerManager(BaseManager):
|
||||||
required_resources = ['destination', 'port']
|
required_resources = ['destination', 'port']
|
||||||
|
|
||||||
self._set_changed_options()
|
self._set_changed_options()
|
||||||
|
# This must be changed back to a list to make a valid REST API
|
||||||
|
# value. The module manipulates this as a normal dictionary
|
||||||
|
if self.want.default_persistence_profile is not None:
|
||||||
|
self.want.update({'default_persistence_profile': [self.want.default_persistence_profile]})
|
||||||
|
|
||||||
if self.want.destination is None:
|
if self.want.destination is None:
|
||||||
raise F5ModuleError(
|
raise F5ModuleError(
|
||||||
"'destination' must be specified when creating a virtual server"
|
"'destination' must be specified when creating a virtual server"
|
||||||
|
@ -1652,7 +1524,10 @@ class VirtualServerManager(BaseManager):
|
||||||
raise F5ModuleError(
|
raise F5ModuleError(
|
||||||
"The source and destination addresses for the virtual server must be be the same type (IPv4 or IPv6)."
|
"The source and destination addresses for the virtual server must be be the same type (IPv4 or IPv6)."
|
||||||
)
|
)
|
||||||
return super(VirtualServerManager, self).create()
|
if self.module.check_mode:
|
||||||
|
return True
|
||||||
|
self.create_on_device()
|
||||||
|
return True
|
||||||
|
|
||||||
def update_on_device(self):
|
def update_on_device(self):
|
||||||
params = self.changes.api_params()
|
params = self.changes.api_params()
|
||||||
|
@ -1674,7 +1549,7 @@ class VirtualServerManager(BaseManager):
|
||||||
)
|
)
|
||||||
params = result.attrs
|
params = result.attrs
|
||||||
params.update(dict(kind=result.to_dict().get('kind', None)))
|
params.update(dict(kind=result.to_dict().get('kind', None)))
|
||||||
result = VirtualServerApiParameters(params)
|
result = ApiParameters(params=params)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def create_on_device(self):
|
def create_on_device(self):
|
||||||
|
@ -1694,71 +1569,10 @@ class VirtualServerManager(BaseManager):
|
||||||
resource.delete()
|
resource.delete()
|
||||||
|
|
||||||
|
|
||||||
class VirtualAddressManager(BaseManager):
|
|
||||||
def __init__(self, client):
|
|
||||||
super(VirtualAddressManager, self).__init__(client)
|
|
||||||
self.want = VirtualAddressModuleParameters(self.client.module.params)
|
|
||||||
self.have = VirtualAddressApiParameters()
|
|
||||||
self.changes = VirtualAddressUsableChanges()
|
|
||||||
|
|
||||||
def get_reportable_changes(self):
|
|
||||||
result = VirtualAddressReportableChanges(self.changes.to_return())
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _set_changed_options(self):
|
|
||||||
changed = {}
|
|
||||||
for key in VirtualAddressParameters.returnables:
|
|
||||||
if getattr(self.want, key) is not None:
|
|
||||||
changed[key] = getattr(self.want, key)
|
|
||||||
if changed:
|
|
||||||
self.changes = VirtualAddressUsableChanges(changed)
|
|
||||||
|
|
||||||
def _update_changed_options(self):
|
|
||||||
diff = Difference(self.want, self.have)
|
|
||||||
updatables = VirtualAddressParameters.updatables
|
|
||||||
changed = dict()
|
|
||||||
for k in updatables:
|
|
||||||
change = diff.compare(k)
|
|
||||||
if change is None:
|
|
||||||
continue
|
|
||||||
else:
|
|
||||||
if isinstance(change, dict):
|
|
||||||
changed.update(change)
|
|
||||||
else:
|
|
||||||
changed[k] = change
|
|
||||||
if changed:
|
|
||||||
self.changes = VirtualAddressUsableChanges(changed)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def read_current_from_device(self):
|
|
||||||
result = self.client.api.tm.ltm.virtual_address_s.virtual_address.load(
|
|
||||||
name=self.want.name,
|
|
||||||
partition=self.want.partition
|
|
||||||
)
|
|
||||||
result = VirtualAddressParameters(result.attrs)
|
|
||||||
return result
|
|
||||||
|
|
||||||
def update_on_device(self):
|
|
||||||
params = self.want.api_params()
|
|
||||||
resource = self.client.api.tm.ltm.virtual_address_s.virtual_address.load(
|
|
||||||
name=self.want.name,
|
|
||||||
partition=self.want.partition
|
|
||||||
)
|
|
||||||
resource.modify(**params)
|
|
||||||
|
|
||||||
def exists(self):
|
|
||||||
result = self.client.api.tm.ltm.virtual_address_s.virtual_address.exists(
|
|
||||||
name=self.want.name,
|
|
||||||
partition=self.want.partition
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
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', 'disabled', 'enabled']
|
choices=['present', 'absent', 'disabled', 'enabled']
|
||||||
|
@ -1798,54 +1612,45 @@ class ArgumentSpec(object):
|
||||||
pool=dict(),
|
pool=dict(),
|
||||||
description=dict(),
|
description=dict(),
|
||||||
snat=dict(),
|
snat=dict(),
|
||||||
route_advertisement_state=dict(
|
|
||||||
choices=['enabled', 'disabled']
|
|
||||||
),
|
|
||||||
default_persistence_profile=dict(),
|
default_persistence_profile=dict(),
|
||||||
fallback_persistence_profile=dict(),
|
fallback_persistence_profile=dict(),
|
||||||
source=dict(),
|
source=dict(),
|
||||||
metadata=dict(type='raw')
|
metadata=dict(type='raw'),
|
||||||
|
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)
|
||||||
self.mutually_exclusive = [
|
self.mutually_exclusive = [
|
||||||
['enabled_vlans', 'disabled_vlans']
|
['enabled_vlans', 'disabled_vlans']
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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,
|
|
||||||
mutually_exclusive=spec.mutually_exclusive
|
mutually_exclusive=spec.mutually_exclusive
|
||||||
)
|
)
|
||||||
|
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__':
|
||||||
|
|
|
@ -55,13 +55,46 @@ options:
|
||||||
- Tag number for the VLAN. The tag number can be any integer between 1
|
- Tag number for the VLAN. The tag number can be any integer between 1
|
||||||
and 4094. The system automatically assigns a tag number if you do not
|
and 4094. The system automatically assigns a tag number if you do not
|
||||||
specify a value.
|
specify a value.
|
||||||
|
mtu:
|
||||||
|
description:
|
||||||
|
- Specifies the maximum transmission unit (MTU) for traffic on this VLAN.
|
||||||
|
When creating a new VLAN, if this parameter is not specified, the default
|
||||||
|
value used will be C(1500).
|
||||||
|
- This number must be between 576 to 9198.
|
||||||
|
version_added: 2.5
|
||||||
|
cmp_hash:
|
||||||
|
description:
|
||||||
|
- Specifies how the traffic on the VLAN will be disaggregated. The value
|
||||||
|
selected determines the traffic disaggregation method. You can choose to
|
||||||
|
disaggregate traffic based on C(source-address) (the source IP address),
|
||||||
|
C(destination-address) (destination IP address), or C(default), which
|
||||||
|
specifies that the default CMP hash uses L4 ports.
|
||||||
|
- When creating a new VLAN, if this parameter is not specified, the default
|
||||||
|
of C(default) is used.
|
||||||
|
version_added: 2.5
|
||||||
|
dag_tunnel:
|
||||||
|
description:
|
||||||
|
- Specifies how the disaggregator (DAG) distributes received tunnel-encapsulated
|
||||||
|
packets to TMM instances. Select C(inner) to distribute packets based on information
|
||||||
|
in inner headers. Select C(outer) to distribute packets based on information in
|
||||||
|
outer headers without inspecting inner headers.
|
||||||
|
- When creating a new VLAN, if this parameter is not specified, the default
|
||||||
|
of C(outer) is used.
|
||||||
|
- This parameter is not supported on Virtual Editions of BIG-IP.
|
||||||
|
version_added: 2.5
|
||||||
|
dag_round_robin:
|
||||||
|
description:
|
||||||
|
- Specifies whether some of the stateless traffic on the VLAN should be
|
||||||
|
disaggregated in a round-robin order instead of using a static hash. The
|
||||||
|
stateless traffic includes non-IP L2 traffic, ICMP, some UDP protocols,
|
||||||
|
and so on.
|
||||||
|
- When creating a new VLAN, if this parameter is not specified, the default
|
||||||
|
of (no) is used.
|
||||||
|
version_added: 2.5
|
||||||
|
choices: [yes, no]
|
||||||
notes:
|
notes:
|
||||||
- Requires the f5-sdk Python package on the host. This is as easy as pip
|
|
||||||
install f5-sdk.
|
|
||||||
- Requires BIG-IP versions >= 12.0.0
|
- Requires BIG-IP versions >= 12.0.0
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
requirements:
|
|
||||||
- f5-sdk
|
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
- Wojciech Wypior (@wojtek0806)
|
- Wojciech Wypior (@wojtek0806)
|
||||||
|
@ -114,134 +147,92 @@ EXAMPLES = r'''
|
||||||
|
|
||||||
RETURN = r'''
|
RETURN = r'''
|
||||||
description:
|
description:
|
||||||
description: The description set on the VLAN
|
description: The description set on the VLAN.
|
||||||
returned: changed
|
returned: changed
|
||||||
type: string
|
type: string
|
||||||
sample: foo VLAN
|
sample: foo VLAN
|
||||||
interfaces:
|
interfaces:
|
||||||
description: Interfaces that the VLAN is assigned to
|
description: Interfaces that the VLAN is assigned to.
|
||||||
returned: changed
|
returned: changed
|
||||||
type: list
|
type: list
|
||||||
sample: ['1.1','1.2']
|
sample: ['1.1','1.2']
|
||||||
name:
|
|
||||||
description: The name of the VLAN
|
|
||||||
returned: changed
|
|
||||||
type: string
|
|
||||||
sample: net1
|
|
||||||
partition:
|
partition:
|
||||||
description: The partition that the VLAN was created on
|
description: The partition that the VLAN was created on.
|
||||||
returned: changed
|
returned: changed
|
||||||
type: string
|
type: string
|
||||||
sample: Common
|
sample: Common
|
||||||
tag:
|
tag:
|
||||||
description: The ID of the VLAN
|
description: The ID of the VLAN.
|
||||||
returned: changed
|
returned: changed
|
||||||
type: int
|
type: int
|
||||||
sample: 2345
|
sample: 2345
|
||||||
|
cmp_hash:
|
||||||
|
description: New traffic disaggregation method.
|
||||||
|
returned: changed
|
||||||
|
type: string
|
||||||
|
sample: source-address
|
||||||
|
dag_tunnel:
|
||||||
|
description: The new DAG tunnel setting.
|
||||||
|
returned: changed
|
||||||
|
type: string
|
||||||
|
sample: outer
|
||||||
'''
|
'''
|
||||||
|
|
||||||
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 collections import defaultdict
|
|
||||||
|
|
||||||
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:
|
||||||
HAS_F5SDK = False
|
# 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
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
def __init__(self, params=None):
|
api_map = {
|
||||||
self._values = defaultdict(lambda: None)
|
'cmpHash': 'cmp_hash',
|
||||||
if params:
|
'dagTunnel': 'dag_tunnel',
|
||||||
self.update(params=params)
|
'dagRoundRobin': 'dag_round_robin'
|
||||||
|
}
|
||||||
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
|
|
||||||
|
|
||||||
updatables = [
|
updatables = [
|
||||||
'tagged_interfaces', 'untagged_interfaces', 'tag',
|
'tagged_interfaces', 'untagged_interfaces', 'tag',
|
||||||
'description'
|
'description', 'mtu', 'cmp_hash', 'dag_tunnel',
|
||||||
|
'dag_round_robin'
|
||||||
]
|
]
|
||||||
|
|
||||||
returnables = [
|
returnables = [
|
||||||
'description', 'partition', 'name', 'tag', 'interfaces',
|
'description', 'partition', 'tag', 'interfaces',
|
||||||
'tagged_interfaces', 'untagged_interfaces'
|
'tagged_interfaces', 'untagged_interfaces', 'mtu',
|
||||||
|
'cmp_hash', 'dag_tunnel', 'dag_round_robin'
|
||||||
]
|
]
|
||||||
|
|
||||||
api_attributes = [
|
api_attributes = [
|
||||||
'description', 'interfaces', 'partition', 'name', 'tag'
|
'description', 'interfaces', 'tag', 'mtu', 'cmpHash',
|
||||||
|
'dagTunnel', 'dagRoundRobin'
|
||||||
]
|
]
|
||||||
api_map = {}
|
|
||||||
|
|
||||||
@property
|
|
||||||
def interfaces(self):
|
|
||||||
tagged = self._values['tagged_interfaces']
|
|
||||||
untagged = self._values['untagged_interfaces']
|
|
||||||
if tagged:
|
|
||||||
return [dict(name=x, tagged=True) for x in tagged]
|
|
||||||
if untagged:
|
|
||||||
return [dict(name=x, untagged=True) for x in untagged]
|
|
||||||
|
|
||||||
@property
|
|
||||||
def tagged_interfaces(self):
|
|
||||||
value = self._values['tagged_interfaces']
|
|
||||||
if value is None:
|
|
||||||
return None
|
|
||||||
ifcs = self._parse_return_ifcs()
|
|
||||||
for ifc in value:
|
|
||||||
if ifc not in ifcs:
|
|
||||||
err = 'The specified interface "%s" was not found' % ifc
|
|
||||||
raise F5ModuleError(err)
|
|
||||||
return value
|
|
||||||
|
|
||||||
@property
|
|
||||||
def untagged_interfaces(self):
|
|
||||||
value = self._values['untagged_interfaces']
|
|
||||||
if value is None:
|
|
||||||
return None
|
|
||||||
ifcs = self._parse_return_ifcs()
|
|
||||||
for ifc in value:
|
|
||||||
if ifc not in ifcs:
|
|
||||||
err = 'The specified interface "%s" was not found' % ifc
|
|
||||||
raise F5ModuleError(err)
|
|
||||||
return value
|
|
||||||
|
|
||||||
def _get_interfaces_from_device(self):
|
|
||||||
lst = self.client.api.tm.net.interfaces.get_collection()
|
|
||||||
return lst
|
|
||||||
|
|
||||||
def _parse_return_ifcs(self):
|
|
||||||
ifclst = self._get_interfaces_from_device()
|
|
||||||
ifcs = [str(x.name) for x in ifclst]
|
|
||||||
if not ifcs:
|
|
||||||
err = 'No interfaces were found'
|
|
||||||
raise F5ModuleError(err)
|
|
||||||
return ifcs
|
|
||||||
|
|
||||||
def to_return(self):
|
def to_return(self):
|
||||||
result = {}
|
result = {}
|
||||||
|
@ -250,26 +241,202 @@ class Parameters(AnsibleF5Parameters):
|
||||||
result = self._filter_params(result)
|
result = self._filter_params(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def api_params(self):
|
|
||||||
|
class ApiParameters(Parameters):
|
||||||
|
@property
|
||||||
|
def tagged_interfaces(self):
|
||||||
|
if self._values['interfaces'] is None:
|
||||||
|
return None
|
||||||
|
result = [str(x.name) for x in self._values['interfaces'] if x.tagged is True]
|
||||||
|
result = sorted(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def untagged_interfaces(self):
|
||||||
|
if self._values['interfaces'] is None:
|
||||||
|
return None
|
||||||
|
result = [str(x.name) for x in self._values['interfaces'] if x.untagged is True]
|
||||||
|
result = sorted(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class ModuleParameters(Parameters):
|
||||||
|
@property
|
||||||
|
def untagged_interfaces(self):
|
||||||
|
if self._values['untagged_interfaces'] is None:
|
||||||
|
return None
|
||||||
|
if self._values['untagged_interfaces'] is None:
|
||||||
|
return None
|
||||||
|
if len(self._values['untagged_interfaces']) == 1 and self._values['untagged_interfaces'][0] == '':
|
||||||
|
return ''
|
||||||
|
result = sorted([str(x) for x in self._values['untagged_interfaces']])
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tagged_interfaces(self):
|
||||||
|
if self._values['tagged_interfaces'] is None:
|
||||||
|
return None
|
||||||
|
if self._values['tagged_interfaces'] is None:
|
||||||
|
return None
|
||||||
|
if len(self._values['tagged_interfaces']) == 1 and self._values['tagged_interfaces'][0] == '':
|
||||||
|
return ''
|
||||||
|
result = sorted([str(x) for x in self._values['tagged_interfaces']])
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def mtu(self):
|
||||||
|
if self._values['mtu'] is None:
|
||||||
|
return None
|
||||||
|
if int(self._values['mtu']) < 576 or int(self._values['mtu']) > 9198:
|
||||||
|
raise F5ModuleError(
|
||||||
|
"The mtu value must be between 576 - 9198"
|
||||||
|
)
|
||||||
|
return int(self._values['mtu'])
|
||||||
|
|
||||||
|
@property
|
||||||
|
def cmp_hash(self):
|
||||||
|
if self._values['cmp_hash'] is None:
|
||||||
|
return None
|
||||||
|
if self._values['cmp_hash'] in ['source-address', 'src', 'src-ip', 'source']:
|
||||||
|
return 'src-ip'
|
||||||
|
if self._values['cmp_hash'] in ['destination-address', 'dest', 'dst-ip', 'destination', 'dst']:
|
||||||
|
return 'dst-ip'
|
||||||
|
else:
|
||||||
|
return 'default'
|
||||||
|
|
||||||
|
@property
|
||||||
|
def dag_round_robin(self):
|
||||||
|
if self._values['dag_round_robin'] is None:
|
||||||
|
return None
|
||||||
|
if self._values['dag_round_robin'] is True:
|
||||||
|
return 'enabled'
|
||||||
|
else:
|
||||||
|
return 'disabled'
|
||||||
|
|
||||||
|
|
||||||
|
class Changes(Parameters):
|
||||||
|
def to_return(self):
|
||||||
result = {}
|
result = {}
|
||||||
for api_attribute in self.api_attributes:
|
try:
|
||||||
if api_attribute in self.api_map:
|
for returnable in self.returnables:
|
||||||
result[api_attribute] = getattr(
|
result[returnable] = getattr(self, returnable)
|
||||||
self, self.api_map[api_attribute])
|
result = self._filter_params(result)
|
||||||
else:
|
except Exception:
|
||||||
result[api_attribute] = getattr(self, api_attribute)
|
pass
|
||||||
result = self._filter_params(result)
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class UsableChanges(Changes):
|
||||||
|
pass
|
||||||
|
|
||||||
|
|
||||||
|
class ReportableChanges(Changes):
|
||||||
|
@property
|
||||||
|
def tagged_interfaces(self):
|
||||||
|
if self._values['interfaces'] is None:
|
||||||
|
return None
|
||||||
|
result = [str(x['name']) for x in self._values['interfaces'] if 'tagged' in x and x['tagged'] is True]
|
||||||
|
result = sorted(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def untagged_interfaces(self):
|
||||||
|
if self._values['interfaces'] is None:
|
||||||
|
return None
|
||||||
|
result = [str(x['name']) for x in self._values['interfaces'] if 'untagged' in x and x['untagged'] is True]
|
||||||
|
result = sorted(result)
|
||||||
|
return result
|
||||||
|
|
||||||
|
|
||||||
|
class Difference(object):
|
||||||
|
def __init__(self, want, have=None):
|
||||||
|
self.want = want
|
||||||
|
self.have = have
|
||||||
|
|
||||||
|
def compare(self, param):
|
||||||
|
try:
|
||||||
|
result = getattr(self, param)
|
||||||
|
return result
|
||||||
|
except AttributeError:
|
||||||
|
return self.__default(param)
|
||||||
|
|
||||||
|
def __default(self, param):
|
||||||
|
attr1 = getattr(self.want, param)
|
||||||
|
try:
|
||||||
|
attr2 = getattr(self.have, param)
|
||||||
|
if attr1 != attr2:
|
||||||
|
return attr1
|
||||||
|
except AttributeError:
|
||||||
|
return attr1
|
||||||
|
|
||||||
|
@property
|
||||||
|
def untagged_interfaces(self):
|
||||||
|
result = []
|
||||||
|
if self.want.untagged_interfaces is None:
|
||||||
|
return None
|
||||||
|
elif self.want.untagged_interfaces == '' and self.have.untagged_interfaces is None:
|
||||||
|
return None
|
||||||
|
elif self.want.untagged_interfaces == '' and len(self.have.untagged_interfaces) > 0:
|
||||||
|
pass
|
||||||
|
elif not self.have.untagged_interfaces:
|
||||||
|
result = dict(
|
||||||
|
interfaces=[dict(name=x, untagged=True) for x in self.want.untagged_interfaces]
|
||||||
|
)
|
||||||
|
elif set(self.want.untagged_interfaces) != set(self.have.untagged_interfaces):
|
||||||
|
result = dict(
|
||||||
|
interfaces=[dict(name=x, untagged=True) for x in self.want.untagged_interfaces]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
|
return result
|
||||||
|
|
||||||
|
@property
|
||||||
|
def tagged_interfaces(self):
|
||||||
|
result = []
|
||||||
|
if self.want.tagged_interfaces is None:
|
||||||
|
return None
|
||||||
|
elif self.want.tagged_interfaces == '' and self.have.tagged_interfaces is None:
|
||||||
|
return None
|
||||||
|
elif self.want.tagged_interfaces == '' and len(self.have.tagged_interfaces) > 0:
|
||||||
|
pass
|
||||||
|
elif not self.have.tagged_interfaces:
|
||||||
|
result = dict(
|
||||||
|
interfaces=[dict(name=x, tagged=True) for x in self.want.tagged_interfaces]
|
||||||
|
)
|
||||||
|
elif set(self.want.tagged_interfaces) != set(self.have.tagged_interfaces):
|
||||||
|
result = dict(
|
||||||
|
interfaces=[dict(name=x, tagged=True) for x in self.want.tagged_interfaces]
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
return None
|
||||||
return result
|
return result
|
||||||
|
|
||||||
|
|
||||||
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.have = None
|
self.client = kwargs.get('client', None)
|
||||||
self.want = Parameters()
|
self.want = ModuleParameters(params=self.module.params)
|
||||||
self.want.client = self.client
|
self.have = ApiParameters()
|
||||||
self.want.update(self.client.module.params)
|
self.changes = UsableChanges()
|
||||||
self.changes = Parameters()
|
|
||||||
|
def _update_changed_options(self):
|
||||||
|
diff = Difference(self.want, self.have)
|
||||||
|
updatables = Parameters.updatables
|
||||||
|
changed = dict()
|
||||||
|
for k in updatables:
|
||||||
|
change = diff.compare(k)
|
||||||
|
if change is None:
|
||||||
|
continue
|
||||||
|
else:
|
||||||
|
if isinstance(change, dict):
|
||||||
|
changed.update(change)
|
||||||
|
else:
|
||||||
|
changed[k] = change
|
||||||
|
if changed:
|
||||||
|
self.changes = UsableChanges(params=changed)
|
||||||
|
return True
|
||||||
|
return False
|
||||||
|
|
||||||
def exec_module(self):
|
def exec_module(self):
|
||||||
changed = False
|
changed = False
|
||||||
|
@ -284,39 +451,20 @@ class ModuleManager(object):
|
||||||
except iControlUnexpectedHTTPError as e:
|
except iControlUnexpectedHTTPError as e:
|
||||||
raise F5ModuleError(str(e))
|
raise F5ModuleError(str(e))
|
||||||
|
|
||||||
changes = self.changes.to_return()
|
reportable = ReportableChanges(params=self.changes.to_return())
|
||||||
|
changes = reportable.to_return()
|
||||||
result.update(**changes)
|
result.update(**changes)
|
||||||
result.update(dict(changed=changed))
|
result.update(dict(changed=changed))
|
||||||
|
self._announce_deprecations(result)
|
||||||
return result
|
return result
|
||||||
|
|
||||||
def _set_changed_options(self):
|
def _announce_deprecations(self, result):
|
||||||
changed = {}
|
warnings = result.pop('__warnings', [])
|
||||||
for key in Parameters.returnables:
|
for warning in warnings:
|
||||||
if getattr(self.want, key) is not None:
|
self.module.deprecate(
|
||||||
changed[key] = getattr(self.want, key)
|
msg=warning['msg'],
|
||||||
if changed:
|
version=warning['version']
|
||||||
self.changes = Parameters(changed)
|
)
|
||||||
|
|
||||||
def _update_changed_options(self):
|
|
||||||
changed = {}
|
|
||||||
for key in Parameters.updatables:
|
|
||||||
if getattr(self.want, key) is not None:
|
|
||||||
attr1 = getattr(self.want, key)
|
|
||||||
attr2 = getattr(self.have, key)
|
|
||||||
if attr1 != attr2:
|
|
||||||
changed[key] = attr1
|
|
||||||
if changed:
|
|
||||||
self.changes = Parameters(changed)
|
|
||||||
return True
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _have_interfaces(self, ifcs):
|
|
||||||
untagged = [str(x.name) for x in ifcs if hasattr(x, 'untagged')]
|
|
||||||
tagged = [str(x.name) for x in ifcs if hasattr(x, 'tagged')]
|
|
||||||
if untagged:
|
|
||||||
self.have.update({'untagged_interfaces': untagged})
|
|
||||||
if tagged:
|
|
||||||
self.have.update({'tagged_interfaces': tagged})
|
|
||||||
|
|
||||||
def present(self):
|
def present(self):
|
||||||
if self.exists():
|
if self.exists():
|
||||||
|
@ -336,18 +484,16 @@ class ModuleManager(object):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def update(self):
|
def update(self):
|
||||||
self.have, ifcs = self.read_current_from_device()
|
self.have = self.read_current_from_device()
|
||||||
if ifcs:
|
|
||||||
self._have_interfaces(ifcs)
|
|
||||||
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
|
||||||
|
|
||||||
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():
|
||||||
|
@ -355,49 +501,59 @@ class ModuleManager(object):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create(self):
|
def create(self):
|
||||||
self._set_changed_options()
|
self.have = ApiParameters()
|
||||||
if self.client.check_mode:
|
if self.want.mtu is None:
|
||||||
|
self.want.update({'mtu': 1500})
|
||||||
|
self._update_changed_options()
|
||||||
|
if self.module.check_mode:
|
||||||
return True
|
return True
|
||||||
self.create_on_device()
|
self.create_on_device()
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def create_on_device(self):
|
def create_on_device(self):
|
||||||
params = self.want.api_params()
|
params = self.changes.api_params()
|
||||||
self.client.api.tm.net.vlans.vlan.create(**params)
|
self.client.api.tm.net.vlans.vlan.create(
|
||||||
|
name=self.want.name,
|
||||||
|
partition=self.want.partition,
|
||||||
|
**params
|
||||||
|
)
|
||||||
|
|
||||||
def update_on_device(self):
|
def update_on_device(self):
|
||||||
params = self.want.api_params()
|
params = self.changes.api_params()
|
||||||
result = self.client.api.tm.net.vlans.vlan.load(
|
resource = self.client.api.tm.net.vlans.vlan.load(
|
||||||
name=self.want.name, partition=self.want.partition
|
name=self.want.name,
|
||||||
|
partition=self.want.partition
|
||||||
)
|
)
|
||||||
result.modify(**params)
|
resource.modify(**params)
|
||||||
|
|
||||||
def exists(self):
|
def exists(self):
|
||||||
return self.client.api.tm.net.vlans.vlan.exists(
|
return self.client.api.tm.net.vlans.vlan.exists(
|
||||||
name=self.want.name, partition=self.want.partition
|
name=self.want.name,
|
||||||
|
partition=self.want.partition
|
||||||
)
|
)
|
||||||
|
|
||||||
def remove_from_device(self):
|
def remove_from_device(self):
|
||||||
result = self.client.api.tm.net.vlans.vlan.load(
|
resource = self.client.api.tm.net.vlans.vlan.load(
|
||||||
name=self.want.name, partition=self.want.partition
|
name=self.want.name,
|
||||||
|
partition=self.want.partition
|
||||||
)
|
)
|
||||||
if result:
|
if resource:
|
||||||
result.delete()
|
resource.delete()
|
||||||
|
|
||||||
def read_current_from_device(self):
|
def read_current_from_device(self):
|
||||||
tmp_res = self.client.api.tm.net.vlans.vlan.load(
|
resource = self.client.api.tm.net.vlans.vlan.load(
|
||||||
name=self.want.name, partition=self.want.partition
|
name=self.want.name, partition=self.want.partition
|
||||||
)
|
)
|
||||||
ifcs = tmp_res.interfaces_s.get_collection()
|
interfaces = resource.interfaces_s.get_collection()
|
||||||
|
result = resource.attrs
|
||||||
result = tmp_res.attrs
|
result['interfaces'] = interfaces
|
||||||
return Parameters(result), ifcs
|
return ApiParameters(params=result)
|
||||||
|
|
||||||
|
|
||||||
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(
|
||||||
required=True,
|
required=True,
|
||||||
),
|
),
|
||||||
|
@ -412,32 +568,56 @@ class ArgumentSpec(object):
|
||||||
description=dict(),
|
description=dict(),
|
||||||
tag=dict(
|
tag=dict(
|
||||||
type='int'
|
type='int'
|
||||||
|
),
|
||||||
|
mtu=dict(type='int'),
|
||||||
|
cmp_hash=dict(
|
||||||
|
choices=[
|
||||||
|
'default',
|
||||||
|
'destination-address', 'dest', 'dst-ip', 'destination', 'dst',
|
||||||
|
'source-address', 'src', 'src-ip', 'source'
|
||||||
|
]
|
||||||
|
),
|
||||||
|
dag_tunnel=dict(
|
||||||
|
choices=['inner', 'outer']
|
||||||
|
),
|
||||||
|
dag_round_robin=dict(type='bool'),
|
||||||
|
state=dict(
|
||||||
|
default='present',
|
||||||
|
choices=['present', 'absent']
|
||||||
|
),
|
||||||
|
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)
|
||||||
|
self.mutually_exclusive = [
|
||||||
|
['tagged_interfaces', 'untagged_interfaces']
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
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,
|
mutually_exclusive=spec.mutually_exclusive
|
||||||
mutually_exclusive=[
|
|
||||||
['tagged_interfaces', 'untagged_interfaces']
|
|
||||||
]
|
|
||||||
)
|
)
|
||||||
|
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)
|
||||||
|
module.exit_json(**results)
|
||||||
except F5ModuleError as e:
|
except F5ModuleError as e:
|
||||||
client.module.fail_json(msg=str(e))
|
cleanup_tokens(client)
|
||||||
|
module.fail_json(msg=str(e))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -40,11 +40,6 @@ options:
|
||||||
msg:
|
msg:
|
||||||
description:
|
description:
|
||||||
- This overrides the normal error message from a failure to meet the required conditions.
|
- This overrides the normal error message from a failure to meet the required conditions.
|
||||||
notes:
|
|
||||||
- Requires the f5-sdk Python package on the host. This is as easy as pip
|
|
||||||
install f5-sdk.
|
|
||||||
requirements:
|
|
||||||
- f5-sdk >= 2.2.3
|
|
||||||
extends_documentation_fragment: f5
|
extends_documentation_fragment: f5
|
||||||
author:
|
author:
|
||||||
- Tim Rupp (@caphrim007)
|
- Tim Rupp (@caphrim007)
|
||||||
|
@ -84,133 +79,50 @@ import signal
|
||||||
import time
|
import time
|
||||||
|
|
||||||
from ansible.module_utils.basic import AnsibleModule
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
|
||||||
from ansible.module_utils.f5_utils import AnsibleF5Parameters
|
HAS_DEVEL_IMPORTS = False
|
||||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
|
||||||
from ansible.module_utils.f5_utils import F5_COMMON_ARGS
|
|
||||||
from ansible.module_utils.six import iteritems
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from f5.bigip import ManagementRoot as BigIpMgmt
|
# Sideband repository used for dev
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
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:
|
||||||
HAS_F5SDK = False
|
# 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
|
||||||
|
|
||||||
|
|
||||||
def hard_timeout(client, want, start):
|
def hard_timeout(module, want, start):
|
||||||
elapsed = datetime.datetime.utcnow() - start
|
elapsed = datetime.datetime.utcnow() - start
|
||||||
client.module.fail_json(
|
module.fail_json(
|
||||||
want.msg or "Timeout when waiting for BIG-IP", elapsed=elapsed.seconds
|
want.msg or "Timeout when waiting for BIG-IP", elapsed=elapsed.seconds
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
||||||
class AnsibleF5ClientStub(AnsibleF5Client):
|
|
||||||
"""Interim class to disconnect Params from connection
|
|
||||||
|
|
||||||
This module is an interim class that was made to separate the Ansible Module
|
|
||||||
Parameters from the connection to BIG-IP.
|
|
||||||
|
|
||||||
Since this module needs to be able to control the connection process, the default
|
|
||||||
class is not appropriate. Therefore, we overload it and re-define out the
|
|
||||||
connection related work to a separate method.
|
|
||||||
|
|
||||||
This class should serve as a reason to break apart this work itself into separate
|
|
||||||
classes in module_utils. There will be on-going work to do this and, when done,
|
|
||||||
the result will replace this work here.
|
|
||||||
|
|
||||||
"""
|
|
||||||
def __init__(self, argument_spec=None, supports_check_mode=False,
|
|
||||||
mutually_exclusive=None, required_together=None,
|
|
||||||
required_if=None, required_one_of=None, add_file_common_args=False,
|
|
||||||
f5_product_name='bigip'):
|
|
||||||
self.f5_product_name = f5_product_name
|
|
||||||
|
|
||||||
merged_arg_spec = dict()
|
|
||||||
merged_arg_spec.update(F5_COMMON_ARGS)
|
|
||||||
if argument_spec:
|
|
||||||
merged_arg_spec.update(argument_spec)
|
|
||||||
self.arg_spec = merged_arg_spec
|
|
||||||
|
|
||||||
mutually_exclusive_params = []
|
|
||||||
if mutually_exclusive:
|
|
||||||
mutually_exclusive_params += mutually_exclusive
|
|
||||||
|
|
||||||
required_together_params = []
|
|
||||||
if required_together:
|
|
||||||
required_together_params += required_together
|
|
||||||
|
|
||||||
self.module = AnsibleModule(
|
|
||||||
argument_spec=merged_arg_spec,
|
|
||||||
supports_check_mode=supports_check_mode,
|
|
||||||
mutually_exclusive=mutually_exclusive_params,
|
|
||||||
required_together=required_together_params,
|
|
||||||
required_if=required_if,
|
|
||||||
required_one_of=required_one_of,
|
|
||||||
add_file_common_args=add_file_common_args
|
|
||||||
)
|
|
||||||
|
|
||||||
self.check_mode = self.module.check_mode
|
|
||||||
self._connect_params = self._get_connect_params()
|
|
||||||
|
|
||||||
def connect(self):
|
|
||||||
try:
|
|
||||||
if 'transport' not in self.module.params or self.module.params['transport'] != 'cli':
|
|
||||||
self.api = self._get_mgmt_root(
|
|
||||||
self.f5_product_name, **self._connect_params
|
|
||||||
)
|
|
||||||
return True
|
|
||||||
except Exception:
|
|
||||||
return False
|
|
||||||
|
|
||||||
def _get_mgmt_root(self, type, **kwargs):
|
|
||||||
if type == 'bigip':
|
|
||||||
result = BigIpMgmt(
|
|
||||||
kwargs['server'],
|
|
||||||
kwargs['user'],
|
|
||||||
kwargs['password'],
|
|
||||||
port=kwargs['server_port'],
|
|
||||||
timeout=1,
|
|
||||||
token='tmos'
|
|
||||||
)
|
|
||||||
return result
|
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
returnables = [
|
returnables = [
|
||||||
'elapsed'
|
'elapsed'
|
||||||
]
|
]
|
||||||
|
|
||||||
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 to_return(self):
|
def to_return(self):
|
||||||
result = {}
|
result = {}
|
||||||
try:
|
try:
|
||||||
|
@ -245,10 +157,11 @@ class Changes(Parameters):
|
||||||
|
|
||||||
|
|
||||||
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 exec_module(self):
|
def exec_module(self):
|
||||||
|
@ -268,7 +181,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']
|
||||||
)
|
)
|
||||||
|
@ -276,7 +189,7 @@ class ModuleManager(object):
|
||||||
def execute(self):
|
def execute(self):
|
||||||
signal.signal(
|
signal.signal(
|
||||||
signal.SIGALRM,
|
signal.SIGALRM,
|
||||||
lambda sig, frame: hard_timeout(self.client, self.want, start)
|
lambda sig, frame: hard_timeout(self.module, self.want, start)
|
||||||
)
|
)
|
||||||
|
|
||||||
# setup handler before scheduling signal, to eliminate a race
|
# setup handler before scheduling signal, to eliminate a race
|
||||||
|
@ -291,8 +204,8 @@ class ModuleManager(object):
|
||||||
try:
|
try:
|
||||||
# The first test verifies that the REST API is available; this is done
|
# The first test verifies that the REST API is available; this is done
|
||||||
# by repeatedly trying to login to it.
|
# by repeatedly trying to login to it.
|
||||||
connected = self._connect_to_device()
|
self.client = F5Client(**self.module.params)
|
||||||
if not connected:
|
if not self.client:
|
||||||
continue
|
continue
|
||||||
|
|
||||||
if self._device_is_rebooting():
|
if self._device_is_rebooting():
|
||||||
|
@ -333,17 +246,13 @@ class ModuleManager(object):
|
||||||
continue
|
continue
|
||||||
else:
|
else:
|
||||||
elapsed = datetime.datetime.utcnow() - start
|
elapsed = datetime.datetime.utcnow() - start
|
||||||
self.client.module.fail_json(
|
self.module.fail_json(
|
||||||
msg=self.want.msg or "Timeout when waiting for BIG-IP", elapsed=elapsed.seconds
|
msg=self.want.msg or "Timeout when waiting for BIG-IP", elapsed=elapsed.seconds
|
||||||
)
|
)
|
||||||
elapsed = datetime.datetime.utcnow() - start
|
elapsed = datetime.datetime.utcnow() - start
|
||||||
self.changes.update({'elapsed': elapsed.seconds})
|
self.changes.update({'elapsed': elapsed.seconds})
|
||||||
return False
|
return False
|
||||||
|
|
||||||
def _connect_to_device(self):
|
|
||||||
result = self.client.connect()
|
|
||||||
return result
|
|
||||||
|
|
||||||
def _device_is_rebooting(self):
|
def _device_is_rebooting(self):
|
||||||
output = self.client.api.tm.util.bash.exec_cmd(
|
output = self.client.api.tm.util.bash.exec_cmd(
|
||||||
'run',
|
'run',
|
||||||
|
@ -386,45 +295,33 @@ 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(
|
||||||
timeout=dict(default=7200, type='int'),
|
timeout=dict(default=7200, type='int'),
|
||||||
delay=dict(default=0, type='int'),
|
delay=dict(default=0, type='int'),
|
||||||
sleep=dict(default=1, type='int'),
|
sleep=dict(default=1, type='int'),
|
||||||
msg=dict()
|
msg=dict()
|
||||||
)
|
)
|
||||||
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 = AnsibleF5ClientStub(
|
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)
|
mm = ModuleManager(module=module)
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
cleanup_tokens(client)
|
module.exit_json(**results)
|
||||||
client.module.exit_json(**results)
|
|
||||||
except F5ModuleError as e:
|
except F5ModuleError as e:
|
||||||
cleanup_tokens(client)
|
module.fail_json(msg=str(e))
|
||||||
client.module.fail_json(msg=str(e))
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -89,17 +89,37 @@ description:
|
||||||
|
|
||||||
import time
|
import time
|
||||||
|
|
||||||
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
|
|
||||||
from ansible.module_utils.six import iteritems
|
|
||||||
from collections import defaultdict
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
# Sideband repository used for dev
|
||||||
|
from library.module_utils.network.f5.bigiq import HAS_F5SDK
|
||||||
|
from library.module_utils.network.f5.bigiq 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:
|
||||||
HAS_F5SDK = False
|
# Upstream Ansible
|
||||||
|
from ansible.module_utils.network.f5.bigiq import HAS_F5SDK
|
||||||
|
from ansible.module_utils.network.f5.bigiq 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
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
|
@ -119,36 +139,6 @@ class Parameters(AnsibleF5Parameters):
|
||||||
'description'
|
'description'
|
||||||
]
|
]
|
||||||
|
|
||||||
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 = {}
|
||||||
try:
|
try:
|
||||||
|
@ -159,16 +149,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
|
|
||||||
|
|
||||||
|
|
||||||
class ApiParameters(Parameters):
|
class ApiParameters(Parameters):
|
||||||
pass
|
pass
|
||||||
|
@ -230,10 +210,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.want = ModuleParameters(params=self.client.module.params)
|
self.client = kwargs.get('client', None)
|
||||||
self.want.update(dict(client=client))
|
self.want = ModuleParameters(client=self.client, params=self.module.params)
|
||||||
self.have = ApiParameters()
|
self.have = ApiParameters()
|
||||||
self.changes = UsableChanges()
|
self.changes = UsableChanges()
|
||||||
|
|
||||||
|
@ -243,7 +223,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 = 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)
|
||||||
|
@ -259,7 +239,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
|
||||||
|
|
||||||
|
@ -282,7 +262,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))
|
||||||
|
@ -292,7 +272,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']
|
||||||
)
|
)
|
||||||
|
@ -316,13 +296,13 @@ 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
|
||||||
|
|
||||||
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():
|
||||||
|
@ -331,7 +311,7 @@ class ModuleManager(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
|
||||||
if self.want.accept_eula is False:
|
if self.want.accept_eula is False:
|
||||||
raise F5ModuleError(
|
raise F5ModuleError(
|
||||||
|
@ -401,42 +381,48 @@ class ModuleManager(object):
|
||||||
if resource is None:
|
if resource is None:
|
||||||
return False
|
return False
|
||||||
result = resource.attrs
|
result = resource.attrs
|
||||||
return ApiParameters(result)
|
return ApiParameters(params=result)
|
||||||
|
|
||||||
|
|
||||||
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(
|
||||||
regkey_pool=dict(required=True),
|
regkey_pool=dict(required=True),
|
||||||
license_key=dict(required=True, no_log=True),
|
license_key=dict(required=True, no_log=True),
|
||||||
description=dict(),
|
description=dict(),
|
||||||
accept_eula=dict(type='bool')
|
accept_eula=dict(type='bool'),
|
||||||
|
state=dict(
|
||||||
|
default='present',
|
||||||
|
choices=['present', 'absent']
|
||||||
|
),
|
||||||
)
|
)
|
||||||
self.f5_product_name = 'bigiq'
|
self.argument_spec = {}
|
||||||
|
self.argument_spec.update(f5_argument_spec)
|
||||||
|
self.argument_spec.update(argument_spec)
|
||||||
self.required_if = [
|
self.required_if = [
|
||||||
['state', 'present', ['accept_eula']]
|
['state', 'present', ['accept_eula']]
|
||||||
]
|
]
|
||||||
|
|
||||||
|
|
||||||
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
|
||||||
)
|
)
|
||||||
|
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)
|
module.exit_json(**results)
|
||||||
except F5ModuleError as e:
|
except F5ModuleError as e:
|
||||||
client.module.fail_json(msg=str(e))
|
module.fail_json(msg=str(e))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -69,18 +69,37 @@ description:
|
||||||
sample: My description
|
sample: My description
|
||||||
'''
|
'''
|
||||||
|
|
||||||
|
from ansible.module_utils.basic import AnsibleModule
|
||||||
|
|
||||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
HAS_DEVEL_IMPORTS = False
|
||||||
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
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
# Sideband repository used for dev
|
||||||
|
from library.module_utils.network.f5.bigiq import HAS_F5SDK
|
||||||
|
from library.module_utils.network.f5.bigiq 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:
|
||||||
HAS_F5SDK = False
|
# Upstream Ansible
|
||||||
|
from ansible.module_utils.network.f5.bigiq import HAS_F5SDK
|
||||||
|
from ansible.module_utils.network.f5.bigiq 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
|
||||||
|
|
||||||
|
|
||||||
class Parameters(AnsibleF5Parameters):
|
class Parameters(AnsibleF5Parameters):
|
||||||
|
@ -100,36 +119,6 @@ class Parameters(AnsibleF5Parameters):
|
||||||
'description'
|
'description'
|
||||||
]
|
]
|
||||||
|
|
||||||
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 = {}
|
||||||
try:
|
try:
|
||||||
|
@ -140,16 +129,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
|
|
||||||
|
|
||||||
|
|
||||||
class ModuleParameters(Parameters):
|
class ModuleParameters(Parameters):
|
||||||
@property
|
@property
|
||||||
|
@ -214,10 +193,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.want = ModuleParameters(self.client.module.params)
|
self.client = kwargs.get('client', None)
|
||||||
self.want.update({'client': client})
|
self.want = ModuleParameters(client=self.client, params=self.module.params)
|
||||||
self.have = ApiParameters()
|
self.have = ApiParameters()
|
||||||
self.changes = UsableChanges()
|
self.changes = UsableChanges()
|
||||||
|
|
||||||
|
@ -227,7 +206,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 = 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)
|
||||||
|
@ -243,7 +222,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
|
||||||
|
|
||||||
|
@ -266,7 +245,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))
|
||||||
|
@ -276,7 +255,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']
|
||||||
)
|
)
|
||||||
|
@ -297,13 +276,13 @@ 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
|
||||||
|
|
||||||
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():
|
||||||
|
@ -312,7 +291,7 @@ class ModuleManager(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
|
||||||
|
@ -348,13 +327,13 @@ class ModuleManager(object):
|
||||||
id=self.want.uuid
|
id=self.want.uuid
|
||||||
)
|
)
|
||||||
result = resource.attrs
|
result = resource.attrs
|
||||||
return ApiParameters(result)
|
return ApiParameters(params=result)
|
||||||
|
|
||||||
|
|
||||||
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),
|
||||||
description=dict(),
|
description=dict(),
|
||||||
state=dict(
|
state=dict(
|
||||||
|
@ -362,27 +341,28 @@ class ArgumentSpec(object):
|
||||||
choices=['absent', 'present']
|
choices=['absent', 'present']
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
self.f5_product_name = 'bigiq'
|
self.argument_spec = {}
|
||||||
|
self.argument_spec.update(f5_argument_spec)
|
||||||
|
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()
|
||||||
client.module.exit_json(**results)
|
module.exit_json(**results)
|
||||||
except F5ModuleError as e:
|
except F5ModuleError as e:
|
||||||
client.module.fail_json(msg=str(e))
|
module.fail_json(msg=str(e))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|
|
@ -41,18 +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_sys_db.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_sys_global.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_traffic_group.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_ucs.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_user.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_vcmp_guest.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_virtual_address.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_virtual_server.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_vlan.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigip_wait.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigiq_regkey_license.py E321
|
|
||||||
lib/ansible/modules/network/f5/bigiq_regkey_pool.py E321
|
|
||||||
lib/ansible/modules/network/illumos/dladm_linkprop.py E317
|
lib/ansible/modules/network/illumos/dladm_linkprop.py E317
|
||||||
lib/ansible/modules/network/illumos/ipadm_addrprop.py E317
|
lib/ansible/modules/network/illumos/ipadm_addrprop.py E317
|
||||||
lib/ansible/modules/network/illumos/ipadm_ifprop.py E317
|
lib/ansible/modules/network/illumos/ipadm_ifprop.py E317
|
||||||
|
|
|
@ -0,0 +1,15 @@
|
||||||
|
{
|
||||||
|
"kind": "tm:net:vlan:interfaces:interfacescollectionstate",
|
||||||
|
"selfLink": "https://localhost/mgmt/tm/net/vlan/~Common~vlan1/interfaces?ver=13.0.0",
|
||||||
|
"items": [
|
||||||
|
{
|
||||||
|
"kind": "tm:net:vlan:interfaces:interfacesstate",
|
||||||
|
"name": "1.2",
|
||||||
|
"fullPath": "1.2",
|
||||||
|
"generation": 105,
|
||||||
|
"selfLink": "https://localhost/mgmt/tm/net/vlan/~Common~vlan1/interfaces/1.2?ver=13.0.0",
|
||||||
|
"tagMode": "none",
|
||||||
|
"tagged": 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_sys_db import Parameters
|
from library.bigip_sys_db import Parameters
|
||||||
from library.bigip_sys_db import ModuleManager
|
from library.bigip_sys_db import ModuleManager
|
||||||
from library.bigip_sys_db import ArgumentSpec
|
from library.bigip_sys_db 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_sys_db import Parameters
|
from ansible.modules.network.f5.bigip_sys_db import Parameters
|
||||||
from ansible.modules.network.f5.bigip_sys_db import ModuleManager
|
from ansible.modules.network.f5.bigip_sys_db import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_sys_db import ArgumentSpec
|
from ansible.modules.network.f5.bigip_sys_db 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")
|
||||||
|
@ -66,7 +68,7 @@ class TestParameters(unittest.TestCase):
|
||||||
server='localhost',
|
server='localhost',
|
||||||
user='admin'
|
user='admin'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.key == 'foo'
|
assert p.key == 'foo'
|
||||||
assert p.value == 'bar'
|
assert p.value == 'bar'
|
||||||
|
|
||||||
|
@ -80,13 +82,11 @@ class TestParameters(unittest.TestCase):
|
||||||
user='admin'
|
user='admin'
|
||||||
|
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.key == 'foo'
|
assert p.key == 'foo'
|
||||||
assert p.value == 'bar'
|
assert p.value == 'bar'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -118,12 +118,11 @@ class TestManager(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
|
|
||||||
)
|
)
|
||||||
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)
|
||||||
|
|
|
@ -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_sys_global import ApiParameters
|
from library.bigip_sys_global import ApiParameters
|
||||||
from library.bigip_sys_global import ModuleParameters
|
from library.bigip_sys_global import ModuleParameters
|
||||||
from library.bigip_sys_global import ModuleManager
|
from library.bigip_sys_global import ModuleManager
|
||||||
from library.bigip_sys_global import ArgumentSpec
|
from library.bigip_sys_global 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_sys_global import ModuleParameters
|
from ansible.modules.network.f5.bigip_sys_global import ModuleParameters
|
||||||
from ansible.modules.network.f5.bigip_sys_global import ModuleManager
|
from ansible.modules.network.f5.bigip_sys_global import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_sys_global import ArgumentSpec
|
from ansible.modules.network.f5.bigip_sys_global 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")
|
||||||
|
@ -71,7 +73,7 @@ class TestParameters(unittest.TestCase):
|
||||||
quiet_boot='yes',
|
quiet_boot='yes',
|
||||||
security_banner='yes',
|
security_banner='yes',
|
||||||
)
|
)
|
||||||
p = ModuleParameters(args)
|
p = ModuleParameters(params=args)
|
||||||
assert p.banner_text == 'this is a banner'
|
assert p.banner_text == 'this is a banner'
|
||||||
assert p.console_timeout == 100
|
assert p.console_timeout == 100
|
||||||
assert p.gui_setup == 'enabled'
|
assert p.gui_setup == 'enabled'
|
||||||
|
@ -83,7 +85,7 @@ class TestParameters(unittest.TestCase):
|
||||||
|
|
||||||
def test_api_parameters(self):
|
def test_api_parameters(self):
|
||||||
args = load_fixture('load_sys_global_settings.json')
|
args = load_fixture('load_sys_global_settings.json')
|
||||||
p = ApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert 'Welcome to the BIG-IP Configuration Utility' in p.banner_text
|
assert 'Welcome to the BIG-IP Configuration Utility' in p.banner_text
|
||||||
assert p.console_timeout == 0
|
assert p.console_timeout == 0
|
||||||
assert p.gui_setup == 'disabled'
|
assert p.gui_setup == 'disabled'
|
||||||
|
@ -94,8 +96,6 @@ class TestParameters(unittest.TestCase):
|
||||||
assert p.security_banner == 'enabled'
|
assert p.security_banner == 'enabled'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -113,14 +113,13 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = ApiParameters(load_fixture('load_sys_global_settings.json'))
|
current = ApiParameters(params=load_fixture('load_sys_global_settings.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(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
|
@ -18,21 +18,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
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from library.bigip_traffic_group import Parameters
|
from library.bigip_traffic_group import Parameters
|
||||||
from library.bigip_traffic_group import ModuleManager
|
from library.bigip_traffic_group import ModuleManager
|
||||||
from library.bigip_traffic_group import ArgumentSpec
|
from library.bigip_traffic_group 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_traffic_group import Parameters
|
from ansible.modules.network.f5.bigip_traffic_group import Parameters
|
||||||
from ansible.modules.network.f5.bigip_traffic_group import ModuleManager
|
from ansible.modules.network.f5.bigip_traffic_group import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_traffic_group import ArgumentSpec
|
from ansible.modules.network.f5.bigip_traffic_group 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")
|
||||||
|
@ -65,12 +66,10 @@ class TestParameters(unittest.TestCase):
|
||||||
name='foo'
|
name='foo'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.name == 'foo'
|
assert p.name == '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):
|
||||||
|
@ -84,13 +83,12 @@ 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)
|
||||||
mm.create_on_device = Mock(return_value=True)
|
mm.create_on_device = Mock(return_value=True)
|
||||||
mm.exists = Mock(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
|
|
@ -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_ucs import Parameters
|
from library.bigip_ucs import Parameters
|
||||||
|
@ -27,7 +26,8 @@ try:
|
||||||
from library.bigip_ucs import ArgumentSpec
|
from library.bigip_ucs import ArgumentSpec
|
||||||
from library.bigip_ucs import V1Manager
|
from library.bigip_ucs import V1Manager
|
||||||
from library.bigip_ucs import V2Manager
|
from library.bigip_ucs import V2Manager
|
||||||
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 +36,8 @@ except ImportError:
|
||||||
from ansible.modules.network.f5.bigip_ucs import ArgumentSpec
|
from ansible.modules.network.f5.bigip_ucs import ArgumentSpec
|
||||||
from ansible.modules.network.f5.bigip_ucs import V1Manager
|
from ansible.modules.network.f5.bigip_ucs import V1Manager
|
||||||
from ansible.modules.network.f5.bigip_ucs import V2Manager
|
from ansible.modules.network.f5.bigip_ucs import V2Manager
|
||||||
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")
|
||||||
|
@ -76,7 +77,7 @@ class TestParameters(unittest.TestCase):
|
||||||
state='installed'
|
state='installed'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.ucs == '/root/bigip.localhost.localdomain.ucs'
|
assert p.ucs == '/root/bigip.localhost.localdomain.ucs'
|
||||||
assert p.force is True
|
assert p.force is True
|
||||||
assert p.include_chassis_level_config is True
|
assert p.include_chassis_level_config is True
|
||||||
|
@ -98,7 +99,7 @@ class TestParameters(unittest.TestCase):
|
||||||
reset_trust=False
|
reset_trust=False
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.ucs == '/root/bigip.localhost.localdomain.ucs'
|
assert p.ucs == '/root/bigip.localhost.localdomain.ucs'
|
||||||
assert p.include_chassis_level_config is False
|
assert p.include_chassis_level_config is False
|
||||||
assert p.no_license is False
|
assert p.no_license is False
|
||||||
|
@ -107,8 +108,6 @@ class TestParameters(unittest.TestCase):
|
||||||
assert p.install_command == "tmsh load sys ucs /var/local/ucs/bigip.localhost.localdomain.ucs"
|
assert p.install_command == "tmsh load sys ucs /var/local/ucs/bigip.localhost.localdomain.ucs"
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -122,17 +121,16 @@ class TestV1Manager(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 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.is_version_v1 = Mock(return_value=True)
|
mm.is_version_v1 = Mock(return_value=True)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.create_on_device = Mock(return_value=True)
|
vm.create_on_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[False, True])
|
vm.exists = Mock(side_effect=[False, True])
|
||||||
|
|
||||||
|
@ -149,17 +147,16 @@ class TestV1Manager(unittest.TestCase):
|
||||||
state='present'
|
state='present'
|
||||||
))
|
))
|
||||||
|
|
||||||
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.is_version_v1 = Mock(return_value=True)
|
mm.is_version_v1 = Mock(return_value=True)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.create_on_device = Mock(return_value=True)
|
vm.create_on_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[False, True])
|
vm.exists = Mock(side_effect=[False, True])
|
||||||
|
|
||||||
|
@ -176,17 +173,16 @@ class TestV1Manager(unittest.TestCase):
|
||||||
state='installed'
|
state='installed'
|
||||||
))
|
))
|
||||||
|
|
||||||
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.is_version_v1 = Mock(return_value=True)
|
mm.is_version_v1 = Mock(return_value=True)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.create_on_device = Mock(return_value=True)
|
vm.create_on_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(return_value=True)
|
vm.exists = Mock(return_value=True)
|
||||||
vm.install_on_device = Mock(return_value=True)
|
vm.install_on_device = Mock(return_value=True)
|
||||||
|
@ -204,17 +200,16 @@ class TestV1Manager(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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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.is_version_v1 = Mock(return_value=True)
|
mm.is_version_v1 = Mock(return_value=True)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.remove_from_device = Mock(return_value=True)
|
vm.remove_from_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[True, False])
|
vm.exists = Mock(side_effect=[True, False])
|
||||||
|
|
||||||
|
@ -231,17 +226,16 @@ class TestV1Manager(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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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.is_version_v1 = Mock(return_value=True)
|
mm.is_version_v1 = Mock(return_value=True)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.remove_from_device = Mock(return_value=True)
|
vm.remove_from_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[True, True])
|
vm.exists = Mock(side_effect=[True, True])
|
||||||
|
|
||||||
|
@ -250,8 +244,6 @@ class TestV1Manager(unittest.TestCase):
|
||||||
assert 'Failed to delete' in str(ex.value)
|
assert 'Failed to delete' in str(ex.value)
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -265,17 +257,16 @@ class TestV2Manager(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 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.is_version_v1 = Mock(return_value=False)
|
mm.is_version_v1 = Mock(return_value=False)
|
||||||
|
|
||||||
vm = V2Manager(client)
|
vm = V2Manager(module=module)
|
||||||
vm.create_on_device = Mock(return_value=True)
|
vm.create_on_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[False, True])
|
vm.exists = Mock(side_effect=[False, True])
|
||||||
|
|
||||||
|
@ -292,17 +283,16 @@ class TestV2Manager(unittest.TestCase):
|
||||||
state='present'
|
state='present'
|
||||||
))
|
))
|
||||||
|
|
||||||
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.is_version_v1 = Mock(return_value=False)
|
mm.is_version_v1 = Mock(return_value=False)
|
||||||
|
|
||||||
vm = V2Manager(client)
|
vm = V2Manager(module=module)
|
||||||
vm.create_on_device = Mock(return_value=True)
|
vm.create_on_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[False, True])
|
vm.exists = Mock(side_effect=[False, True])
|
||||||
|
|
||||||
|
@ -319,17 +309,16 @@ class TestV2Manager(unittest.TestCase):
|
||||||
state='installed'
|
state='installed'
|
||||||
))
|
))
|
||||||
|
|
||||||
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.is_version_v1 = Mock(return_value=False)
|
mm.is_version_v1 = Mock(return_value=False)
|
||||||
|
|
||||||
vm = V2Manager(client)
|
vm = V2Manager(module=module)
|
||||||
vm.create_on_device = Mock(return_value=True)
|
vm.create_on_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(return_value=True)
|
vm.exists = Mock(return_value=True)
|
||||||
vm.install_on_device = Mock(return_value=True)
|
vm.install_on_device = Mock(return_value=True)
|
||||||
|
@ -347,17 +336,16 @@ class TestV2Manager(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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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.is_version_v1 = Mock(return_value=False)
|
mm.is_version_v1 = Mock(return_value=False)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.remove_from_device = Mock(return_value=True)
|
vm.remove_from_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[True, False])
|
vm.exists = Mock(side_effect=[True, False])
|
||||||
|
|
||||||
|
@ -374,17 +362,16 @@ class TestV2Manager(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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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.is_version_v1 = Mock(return_value=False)
|
mm.is_version_v1 = Mock(return_value=False)
|
||||||
|
|
||||||
vm = V1Manager(client)
|
vm = V1Manager(module=module)
|
||||||
vm.remove_from_device = Mock(return_value=True)
|
vm.remove_from_device = Mock(return_value=True)
|
||||||
vm.exists = Mock(side_effect=[True, True])
|
vm.exists = Mock(side_effect=[True, 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_user import Parameters
|
from library.bigip_user import Parameters
|
||||||
|
@ -27,7 +26,8 @@ try:
|
||||||
from library.bigip_user import ArgumentSpec
|
from library.bigip_user import ArgumentSpec
|
||||||
from library.bigip_user import UnparitionedManager
|
from library.bigip_user import UnparitionedManager
|
||||||
from library.bigip_user import PartitionedManager
|
from library.bigip_user import PartitionedManager
|
||||||
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 +36,8 @@ except ImportError:
|
||||||
from ansible.modules.network.f5.bigip_user import ArgumentSpec
|
from ansible.modules.network.f5.bigip_user import ArgumentSpec
|
||||||
from ansible.modules.network.f5.bigip_user import UnparitionedManager
|
from ansible.modules.network.f5.bigip_user import UnparitionedManager
|
||||||
from ansible.modules.network.f5.bigip_user import PartitionedManager
|
from ansible.modules.network.f5.bigip_user import PartitionedManager
|
||||||
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")
|
||||||
|
@ -74,7 +75,7 @@ class TestParameters(unittest.TestCase):
|
||||||
update_password='always'
|
update_password='always'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.username_credential == 'someuser'
|
assert p.username_credential == 'someuser'
|
||||||
assert p.password_credential == 'testpass'
|
assert p.password_credential == 'testpass'
|
||||||
assert p.full_name == 'Fake Person'
|
assert p.full_name == 'Fake Person'
|
||||||
|
@ -91,7 +92,7 @@ class TestParameters(unittest.TestCase):
|
||||||
shell='none'
|
shell='none'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.name == 'someuser'
|
assert p.name == 'someuser'
|
||||||
assert p.password == 'testpass'
|
assert p.password == 'testpass'
|
||||||
assert p.full_name == 'Fake Person'
|
assert p.full_name == 'Fake Person'
|
||||||
|
@ -99,8 +100,6 @@ class TestParameters(unittest.TestCase):
|
||||||
assert p.shell == 'none'
|
assert p.shell == 'none'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -118,21 +117,21 @@ class TestManager(unittest.TestCase):
|
||||||
update_password='on_create'
|
update_password='on_create'
|
||||||
))
|
))
|
||||||
|
|
||||||
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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.create_on_device = Mock(return_value=True)
|
pm.create_on_device = Mock(return_value=True)
|
||||||
pm.exists = Mock(return_value=False)
|
pm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['partition_access'] == access
|
assert results['partition_access'] == access
|
||||||
|
@ -147,21 +146,21 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.create_on_device = Mock(return_value=True)
|
pm.create_on_device = Mock(return_value=True)
|
||||||
pm.exists = Mock(return_value=False)
|
pm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['partition_access'] == access
|
assert results['partition_access'] == access
|
||||||
|
@ -177,26 +176,26 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.create_on_device = Mock(return_value=True)
|
pm.create_on_device = Mock(return_value=True)
|
||||||
pm.exists = Mock(return_value=False)
|
pm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
msg = "The 'update_password' option " \
|
msg = "The 'update_password' option " \
|
||||||
"needs to be set to 'on_create' when creating " \
|
"needs to be set to 'on_create' when creating " \
|
||||||
"a resource with a password."
|
"a resource with a password."
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
pm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
def test_create_user_partition_access_raises(self, *args):
|
def test_create_user_partition_access_raises(self, *args):
|
||||||
|
@ -207,25 +206,25 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.create_on_device = Mock(return_value=True)
|
pm.create_on_device = Mock(return_value=True)
|
||||||
pm.exists = Mock(return_value=False)
|
pm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
msg = "The 'partition_access' option " \
|
msg = "The 'partition_access' option " \
|
||||||
"is required when creating a resource."
|
"is required when creating a resource."
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
pm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
def test_create_user_shell_bash(self, *args):
|
def test_create_user_shell_bash(self, *args):
|
||||||
|
@ -241,21 +240,21 @@ class TestManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.create_on_device = Mock(return_value=True)
|
pm.create_on_device = Mock(return_value=True)
|
||||||
pm.exists = Mock(return_value=False)
|
pm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['partition_access'] == access
|
assert results['partition_access'] == access
|
||||||
|
@ -273,25 +272,25 @@ class TestManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.create_on_device = Mock(return_value=True)
|
pm.create_on_device = Mock(return_value=True)
|
||||||
pm.exists = Mock(return_value=False)
|
pm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
msg = "Shell access is only available to 'admin' or " \
|
msg = "Shell access is only available to 'admin' or " \
|
||||||
"'resource-admin' roles"
|
"'resource-admin' roles"
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
pm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
def test_update_user_password_no_pass(self, *args):
|
def test_update_user_password_no_pass(self, *args):
|
||||||
|
@ -303,26 +302,26 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = Parameters(load_fixture('load_auth_user_no_pass.json'))
|
current = Parameters(params=load_fixture('load_auth_user_no_pass.json'))
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.exists = Mock(return_value=True)
|
pm.exists = Mock(return_value=True)
|
||||||
pm.update_on_device = Mock(return_value=True)
|
pm.update_on_device = Mock(return_value=True)
|
||||||
pm.read_current_from_device = Mock(return_value=current)
|
pm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
|
|
||||||
|
@ -335,26 +334,26 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = Parameters(load_fixture('load_auth_user_with_pass.json'))
|
current = Parameters(params=load_fixture('load_auth_user_with_pass.json'))
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.exists = Mock(return_value=True)
|
pm.exists = Mock(return_value=True)
|
||||||
pm.update_on_device = Mock(return_value=True)
|
pm.update_on_device = Mock(return_value=True)
|
||||||
pm.read_current_from_device = Mock(return_value=current)
|
pm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
|
|
||||||
|
@ -367,31 +366,31 @@ class TestManager(unittest.TestCase):
|
||||||
shell='none'
|
shell='none'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
shell='tmsh'
|
shell='tmsh'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.exists = Mock(return_value=True)
|
pm.exists = Mock(return_value=True)
|
||||||
pm.update_on_device = Mock(return_value=True)
|
pm.update_on_device = Mock(return_value=True)
|
||||||
pm.read_current_from_device = Mock(return_value=current)
|
pm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['shell'] == 'none'
|
assert results['shell'] == 'none'
|
||||||
|
@ -405,32 +404,32 @@ class TestManager(unittest.TestCase):
|
||||||
shell='none'
|
shell='none'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
access = [{'name': 'Common', 'role': 'guest'}]
|
access = [{'name': 'Common', 'role': 'guest'}]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
pm = PartitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
|
||||||
|
|
||||||
pm = PartitionedManager(client)
|
|
||||||
pm.exists = Mock(return_value=True)
|
pm.exists = Mock(return_value=True)
|
||||||
pm.update_on_device = Mock(return_value=True)
|
pm.update_on_device = Mock(return_value=True)
|
||||||
pm.read_current_from_device = Mock(return_value=current)
|
pm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = pm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||||
|
mm.get_manager = Mock(return_value=pm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is False
|
assert results['changed'] is False
|
||||||
assert not hasattr(results, 'shell')
|
assert not hasattr(results, 'shell')
|
||||||
|
@ -444,17 +443,16 @@ class TestManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
access = [{'name': 'all', 'role': 'admin'}]
|
access = [{'name': 'all', 'role': 'admin'}]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
shell='tmsh',
|
shell='tmsh',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
|
@ -462,15 +460,16 @@ class TestManager(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['shell'] == 'bash'
|
assert results['shell'] == 'bash'
|
||||||
|
@ -484,10 +483,9 @@ class TestManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
|
@ -497,7 +495,7 @@ class TestManager(unittest.TestCase):
|
||||||
{'name': 'all', 'role': 'guest'}
|
{'name': 'all', 'role': 'guest'}
|
||||||
]
|
]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
shell='tmsh',
|
shell='tmsh',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
|
@ -505,24 +503,23 @@ class TestManager(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
msg = "Shell access is only available to 'admin' or " \
|
msg = "Shell access is only available to 'admin' or " \
|
||||||
"'resource-admin' roles"
|
"'resource-admin' roles"
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
upm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
|
|
||||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
|
||||||
return_value=True)
|
|
||||||
class TestLegacyManager(unittest.TestCase):
|
class TestLegacyManager(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
def setUp(self):
|
||||||
|
@ -540,21 +537,21 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
update_password='on_create'
|
update_password='on_create'
|
||||||
))
|
))
|
||||||
|
|
||||||
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)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.create_on_device = Mock(return_value=True)
|
upm.create_on_device = Mock(return_value=True)
|
||||||
upm.exists = Mock(return_value=False)
|
upm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['partition_access'] == access
|
assert results['partition_access'] == access
|
||||||
|
@ -569,21 +566,21 @@ class TestLegacyManager(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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.create_on_device = Mock(return_value=True)
|
upm.create_on_device = Mock(return_value=True)
|
||||||
upm.exists = Mock(return_value=False)
|
upm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['partition_access'] == access
|
assert results['partition_access'] == access
|
||||||
|
@ -599,26 +596,26 @@ class TestLegacyManager(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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.create_on_device = Mock(return_value=True)
|
upm.create_on_device = Mock(return_value=True)
|
||||||
upm.exists = Mock(return_value=False)
|
upm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
msg = "The 'update_password' option " \
|
msg = "The 'update_password' option " \
|
||||||
"needs to be set to 'on_create' when creating " \
|
"needs to be set to 'on_create' when creating " \
|
||||||
"a resource with a password."
|
"a resource with a password."
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
upm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
def test_create_user_partition_access_raises(self, *args):
|
def test_create_user_partition_access_raises(self, *args):
|
||||||
|
@ -629,25 +626,25 @@ class TestLegacyManager(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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.create_on_device = Mock(return_value=True)
|
upm.create_on_device = Mock(return_value=True)
|
||||||
upm.exists = Mock(return_value=False)
|
upm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
msg = "The 'partition_access' option " \
|
msg = "The 'partition_access' option " \
|
||||||
"is required when creating a resource."
|
"is required when creating a resource."
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
upm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
def test_create_user_shell_bash(self, *args):
|
def test_create_user_shell_bash(self, *args):
|
||||||
|
@ -663,21 +660,21 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.create_on_device = Mock(return_value=True)
|
upm.create_on_device = Mock(return_value=True)
|
||||||
upm.exists = Mock(return_value=False)
|
upm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['partition_access'] == access
|
assert results['partition_access'] == access
|
||||||
|
@ -695,25 +692,25 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.create_on_device = Mock(return_value=True)
|
upm.create_on_device = Mock(return_value=True)
|
||||||
upm.exists = Mock(return_value=False)
|
upm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
msg = "Shell access is only available to 'admin' or " \
|
msg = "Shell access is only available to 'admin' or " \
|
||||||
"'resource-admin' roles"
|
"'resource-admin' roles"
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
upm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
||||||
def test_update_user_password(self, *args):
|
def test_update_user_password(self, *args):
|
||||||
|
@ -725,32 +722,32 @@ class TestLegacyManager(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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
access = [{'name': 'Common', 'role': 'guest'}]
|
access = [{'name': 'Common', 'role': 'guest'}]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
shell='tmsh',
|
shell='tmsh',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
|
|
||||||
|
@ -763,31 +760,31 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
shell='none'
|
shell='none'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
shell='tmsh'
|
shell='tmsh'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['shell'] == 'none'
|
assert results['shell'] == 'none'
|
||||||
|
@ -801,32 +798,32 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
shell='none'
|
shell='none'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
access = [{'name': 'Common', 'role': 'guest'}]
|
access = [{'name': 'Common', 'role': 'guest'}]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is False
|
assert results['changed'] is False
|
||||||
assert not hasattr(results, 'shell')
|
assert not hasattr(results, 'shell')
|
||||||
|
@ -840,17 +837,16 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
access = [{'name': 'all', 'role': 'admin'}]
|
access = [{'name': 'all', 'role': 'admin'}]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
shell='tmsh',
|
shell='tmsh',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
|
@ -858,15 +854,16 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = upm.exec_module()
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['shell'] == 'bash'
|
assert results['shell'] == 'bash'
|
||||||
|
@ -880,10 +877,9 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
shell='bash'
|
shell='bash'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
|
@ -893,7 +889,7 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
{'name': 'all', 'role': 'guest'}
|
{'name': 'all', 'role': 'guest'}
|
||||||
]
|
]
|
||||||
current = Parameters(
|
current = Parameters(
|
||||||
dict(
|
params=dict(
|
||||||
user='admin',
|
user='admin',
|
||||||
shell='tmsh',
|
shell='tmsh',
|
||||||
partition_access=access
|
partition_access=access
|
||||||
|
@ -901,17 +897,18 @@ class TestLegacyManager(unittest.TestCase):
|
||||||
)
|
)
|
||||||
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
mm = ModuleManager(client)
|
upm = UnparitionedManager(module=module, params=module.params)
|
||||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
|
||||||
|
|
||||||
upm = UnparitionedManager(client)
|
|
||||||
upm.exists = Mock(return_value=True)
|
upm.exists = Mock(return_value=True)
|
||||||
upm.update_on_device = Mock(return_value=True)
|
upm.update_on_device = Mock(return_value=True)
|
||||||
upm.read_current_from_device = Mock(return_value=current)
|
upm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
|
mm = ModuleManager(module=module)
|
||||||
|
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||||
|
mm.get_manager = Mock(return_value=upm)
|
||||||
|
|
||||||
msg = "Shell access is only available to 'admin' or " \
|
msg = "Shell access is only available to 'admin' or " \
|
||||||
"'resource-admin' roles"
|
"'resource-admin' roles"
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as ex:
|
with pytest.raises(F5ModuleError) as ex:
|
||||||
upm.exec_module()
|
mm.exec_module()
|
||||||
assert str(ex.value) == msg
|
assert str(ex.value) == msg
|
||||||
|
|
|
@ -18,20 +18,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_vcmp_guest import Parameters
|
from library.bigip_vcmp_guest import Parameters
|
||||||
from library.bigip_vcmp_guest import ModuleManager
|
from library.bigip_vcmp_guest import ModuleManager
|
||||||
from library.bigip_vcmp_guest import ArgumentSpec
|
from library.bigip_vcmp_guest 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_vcmp_guest import Parameters
|
from ansible.modules.network.f5.bigip_vcmp_guest import Parameters
|
||||||
from ansible.modules.network.f5.bigip_vcmp_guest import ModuleManager
|
from ansible.modules.network.f5.bigip_vcmp_guest import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_vcmp_guest import ArgumentSpec
|
from ansible.modules.network.f5.bigip_vcmp_guest 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")
|
||||||
|
@ -70,7 +72,7 @@ class TestParameters(unittest.TestCase):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.initial_image == 'BIGIP-12.1.0.1.0.1447-HF1.iso'
|
assert p.initial_image == 'BIGIP-12.1.0.1.0.1447-HF1.iso'
|
||||||
assert p.mgmt_network == 'bridged'
|
assert p.mgmt_network == 'bridged'
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ class TestParameters(unittest.TestCase):
|
||||||
mgmt_address='1.2.3.4'
|
mgmt_address='1.2.3.4'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.mgmt_network == 'bridged'
|
assert p.mgmt_network == 'bridged'
|
||||||
assert p.mgmt_address == '1.2.3.4/32'
|
assert p.mgmt_address == '1.2.3.4/32'
|
||||||
|
|
||||||
|
@ -90,7 +92,7 @@ class TestParameters(unittest.TestCase):
|
||||||
mgmt_address='1.2.3.4/24'
|
mgmt_address='1.2.3.4/24'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.mgmt_network == 'bridged'
|
assert p.mgmt_network == 'bridged'
|
||||||
assert p.mgmt_address == '1.2.3.4/24'
|
assert p.mgmt_address == '1.2.3.4/24'
|
||||||
|
|
||||||
|
@ -100,7 +102,7 @@ class TestParameters(unittest.TestCase):
|
||||||
mgmt_address='1.2.3.4/255.255.255.0'
|
mgmt_address='1.2.3.4/255.255.255.0'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.mgmt_network == 'bridged'
|
assert p.mgmt_network == 'bridged'
|
||||||
assert p.mgmt_address == '1.2.3.4/24'
|
assert p.mgmt_address == '1.2.3.4/24'
|
||||||
|
|
||||||
|
@ -109,7 +111,7 @@ class TestParameters(unittest.TestCase):
|
||||||
mgmt_route='1.2.3.4'
|
mgmt_route='1.2.3.4'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.mgmt_route == '1.2.3.4'
|
assert p.mgmt_route == '1.2.3.4'
|
||||||
|
|
||||||
def test_module_parameters_vcmp_software_image_facts(self):
|
def test_module_parameters_vcmp_software_image_facts(self):
|
||||||
|
@ -120,7 +122,7 @@ class TestParameters(unittest.TestCase):
|
||||||
initial_image='BIGIP-12.1.0.1.0.1447-HF1.iso/1',
|
initial_image='BIGIP-12.1.0.1.0.1447-HF1.iso/1',
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.initial_image == 'BIGIP-12.1.0.1.0.1447-HF1.iso/1'
|
assert p.initial_image == 'BIGIP-12.1.0.1.0.1447-HF1.iso/1'
|
||||||
|
|
||||||
def test_api_parameters(self):
|
def test_api_parameters(self):
|
||||||
|
@ -136,7 +138,7 @@ class TestParameters(unittest.TestCase):
|
||||||
]
|
]
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.initial_image == 'BIGIP-tmos-tier2-13.1.0.0.0.931.iso'
|
assert p.initial_image == 'BIGIP-tmos-tier2-13.1.0.0.0.931.iso'
|
||||||
assert p.mgmt_route == '2.2.2.2'
|
assert p.mgmt_route == '2.2.2.2'
|
||||||
assert p.mgmt_address == '1.1.1.1/24'
|
assert p.mgmt_address == '1.1.1.1/24'
|
||||||
|
@ -144,8 +146,6 @@ class TestParameters(unittest.TestCase):
|
||||||
assert '/Common/vlan2' in p.vlans
|
assert '/Common/vlan2' in p.vlans
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
self.spec = ArgumentSpec()
|
self.spec = ArgumentSpec()
|
||||||
|
@ -161,14 +161,13 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# 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.create_on_device = Mock(return_value=True)
|
mm.create_on_device = Mock(return_value=True)
|
||||||
mm.exists = Mock(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
mm.is_deployed = Mock(side_effect=[False, True, True, True, True])
|
mm.is_deployed = Mock(side_effect=[False, True, True, True, 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_virtual_address import Parameters
|
from library.bigip_virtual_address import Parameters
|
||||||
from library.bigip_virtual_address import ModuleManager
|
from library.bigip_virtual_address import ModuleManager
|
||||||
from library.bigip_virtual_address import ArgumentSpec
|
from library.bigip_virtual_address 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_virtual_address import Parameters
|
from ansible.modules.network.f5.bigip_virtual_address import Parameters
|
||||||
from ansible.modules.network.f5.bigip_virtual_address import ModuleManager
|
from ansible.modules.network.f5.bigip_virtual_address import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_virtual_address import ArgumentSpec
|
from ansible.modules.network.f5.bigip_virtual_address 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")
|
||||||
|
@ -70,7 +72,7 @@ class TestParameters(unittest.TestCase):
|
||||||
advertise_route='always',
|
advertise_route='always',
|
||||||
use_route_advertisement='yes'
|
use_route_advertisement='yes'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.state == 'present'
|
assert p.state == 'present'
|
||||||
assert p.address == '1.1.1.1'
|
assert p.address == '1.1.1.1'
|
||||||
assert p.netmask == '2.2.2.2'
|
assert p.netmask == '2.2.2.2'
|
||||||
|
@ -83,7 +85,7 @@ class TestParameters(unittest.TestCase):
|
||||||
|
|
||||||
def test_api_parameters(self):
|
def test_api_parameters(self):
|
||||||
args = load_fixture('load_ltm_virtual_address_default.json')
|
args = load_fixture('load_ltm_virtual_address_default.json')
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.name == '1.1.1.1'
|
assert p.name == '1.1.1.1'
|
||||||
assert p.address == '1.1.1.1'
|
assert p.address == '1.1.1.1'
|
||||||
assert p.arp_state == 'enabled'
|
assert p.arp_state == 'enabled'
|
||||||
|
@ -99,56 +101,56 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
advertise_route='when_all_available'
|
advertise_route='when_all_available'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.advertise_route == 'all'
|
assert p.advertise_route == 'all'
|
||||||
|
|
||||||
def test_module_parameters_advertise_route_any(self):
|
def test_module_parameters_advertise_route_any(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
advertise_route='when_any_available'
|
advertise_route='when_any_available'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.advertise_route == 'any'
|
assert p.advertise_route == 'any'
|
||||||
|
|
||||||
def test_module_parameters_icmp_echo_disabled(self):
|
def test_module_parameters_icmp_echo_disabled(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
icmp_echo='disabled'
|
icmp_echo='disabled'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.icmp_echo == 'disabled'
|
assert p.icmp_echo == 'disabled'
|
||||||
|
|
||||||
def test_module_parameters_icmp_echo_selective(self):
|
def test_module_parameters_icmp_echo_selective(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
icmp_echo='selective'
|
icmp_echo='selective'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.icmp_echo == 'selective'
|
assert p.icmp_echo == 'selective'
|
||||||
|
|
||||||
def test_module_parameters_auto_delete_disabled(self):
|
def test_module_parameters_auto_delete_disabled(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
auto_delete='disabled'
|
auto_delete='disabled'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.auto_delete is False
|
assert p.auto_delete is False
|
||||||
|
|
||||||
def test_module_parameters_arp_state_disabled(self):
|
def test_module_parameters_arp_state_disabled(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
arp_state='disabled'
|
arp_state='disabled'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.arp_state == 'disabled'
|
assert p.arp_state == 'disabled'
|
||||||
|
|
||||||
def test_module_parameters_use_route_advert_disabled(self):
|
def test_module_parameters_use_route_advert_disabled(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
use_route_advertisement='no'
|
use_route_advertisement='no'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.use_route_advertisement == 'disabled'
|
assert p.use_route_advertisement == 'disabled'
|
||||||
|
|
||||||
def test_module_parameters_state_present(self):
|
def test_module_parameters_state_present(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
state='present'
|
state='present'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.state == 'present'
|
assert p.state == 'present'
|
||||||
assert p.enabled == 'yes'
|
assert p.enabled == 'yes'
|
||||||
|
|
||||||
|
@ -156,14 +158,14 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
state='absent'
|
state='absent'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(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 = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.state == 'enabled'
|
assert p.state == 'enabled'
|
||||||
assert p.enabled == 'yes'
|
assert p.enabled == 'yes'
|
||||||
|
|
||||||
|
@ -171,13 +173,11 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
state='disabled'
|
state='disabled'
|
||||||
)
|
)
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.state == 'disabled'
|
assert p.state == 'disabled'
|
||||||
assert p.enabled == 'no'
|
assert p.enabled == 'no'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -199,12 +199,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])
|
||||||
|
@ -222,12 +221,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=[True, False])
|
mm.exists = Mock(side_effect=[True, False])
|
||||||
|
|
|
@ -17,28 +17,24 @@ 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_virtual_server import VirtualAddressParameters
|
from library.bigip_virtual_server import ModuleParameters
|
||||||
from library.bigip_virtual_server import VirtualServerModuleParameters
|
from library.bigip_virtual_server import ApiParameters
|
||||||
from library.bigip_virtual_server import VirtualServerApiParameters
|
|
||||||
from library.bigip_virtual_server import ModuleManager
|
from library.bigip_virtual_server import ModuleManager
|
||||||
from library.bigip_virtual_server import VirtualServerManager
|
|
||||||
from library.bigip_virtual_server import VirtualAddressManager
|
|
||||||
from library.bigip_virtual_server import ArgumentSpec
|
from library.bigip_virtual_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:
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualAddressParameters
|
from ansible.modules.network.f5.bigip_virtual_server import ApiParameters
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualServerApiParameters
|
from ansible.modules.network.f5.bigip_virtual_server import ModuleParameters
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualServerModuleParameters
|
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import ModuleManager
|
from ansible.modules.network.f5.bigip_virtual_server import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualServerManager
|
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualAddressManager
|
|
||||||
from ansible.modules.network.f5.bigip_virtual_server import ArgumentSpec
|
from ansible.modules.network.f5.bigip_virtual_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")
|
||||||
|
@ -70,14 +66,14 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='1.1.1.1'
|
destination='1.1.1.1'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
|
|
||||||
def test_destination_mutex_2(self):
|
def test_destination_mutex_2(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='1.1.1.1%2'
|
destination='1.1.1.1%2'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
assert p.destination_tuple.route_domain == 2
|
assert p.destination_tuple.route_domain == 2
|
||||||
|
|
||||||
|
@ -85,7 +81,7 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='1.1.1.1:80'
|
destination='1.1.1.1:80'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
assert p.destination_tuple.port == 80
|
assert p.destination_tuple.port == 80
|
||||||
|
|
||||||
|
@ -93,7 +89,7 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='1.1.1.1%2:80'
|
destination='1.1.1.1%2:80'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
assert p.destination_tuple.port == 80
|
assert p.destination_tuple.port == 80
|
||||||
assert p.destination_tuple.route_domain == 2
|
assert p.destination_tuple.route_domain == 2
|
||||||
|
@ -102,14 +98,14 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='/Common/1.1.1.1'
|
destination='/Common/1.1.1.1'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
|
|
||||||
def test_api_destination_mutex_6(self):
|
def test_api_destination_mutex_6(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='/Common/1.1.1.1%2'
|
destination='/Common/1.1.1.1%2'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
assert p.destination_tuple.route_domain == 2
|
assert p.destination_tuple.route_domain == 2
|
||||||
|
|
||||||
|
@ -117,7 +113,7 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='/Common/1.1.1.1:80'
|
destination='/Common/1.1.1.1:80'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
assert p.destination_tuple.port == 80
|
assert p.destination_tuple.port == 80
|
||||||
|
|
||||||
|
@ -125,7 +121,7 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='/Common/1.1.1.1%2:80'
|
destination='/Common/1.1.1.1%2:80'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '1.1.1.1'
|
assert p.destination_tuple.ip == '1.1.1.1'
|
||||||
assert p.destination_tuple.port == 80
|
assert p.destination_tuple.port == 80
|
||||||
assert p.destination_tuple.route_domain == 2
|
assert p.destination_tuple.route_domain == 2
|
||||||
|
@ -134,14 +130,14 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='2700:bc00:1f10:101::6'
|
destination='2700:bc00:1f10:101::6'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
||||||
|
|
||||||
def test_destination_mutex_10(self):
|
def test_destination_mutex_10(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='2700:bc00:1f10:101::6%2'
|
destination='2700:bc00:1f10:101::6%2'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
||||||
assert p.destination_tuple.route_domain == 2
|
assert p.destination_tuple.route_domain == 2
|
||||||
|
|
||||||
|
@ -149,7 +145,7 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='2700:bc00:1f10:101::6.80'
|
destination='2700:bc00:1f10:101::6.80'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
||||||
assert p.destination_tuple.port == 80
|
assert p.destination_tuple.port == 80
|
||||||
|
|
||||||
|
@ -157,26 +153,11 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
destination='2700:bc00:1f10:101::6%2.80'
|
destination='2700:bc00:1f10:101::6%2.80'
|
||||||
)
|
)
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
||||||
assert p.destination_tuple.port == 80
|
assert p.destination_tuple.port == 80
|
||||||
assert p.destination_tuple.route_domain == 2
|
assert p.destination_tuple.route_domain == 2
|
||||||
|
|
||||||
#
|
|
||||||
# def test_destination_mutex_6(self):
|
|
||||||
# args = dict(
|
|
||||||
# destination='/Common/2700:bc00:1f10:101::6'
|
|
||||||
# )
|
|
||||||
# p = VirtualServerParameters(args)
|
|
||||||
# assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
|
||||||
#
|
|
||||||
# def test_destination_mutex_5(self):
|
|
||||||
# args = dict(
|
|
||||||
# destination='/Common/2700:bc00:1f10:101::6'
|
|
||||||
# )
|
|
||||||
# p = VirtualServerParameters(args)
|
|
||||||
# assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
|
||||||
|
|
||||||
def test_module_no_partition_prefix_parameters(self):
|
def test_module_no_partition_prefix_parameters(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
server='localhost',
|
server='localhost',
|
||||||
|
@ -198,7 +179,7 @@ class TestParameters(unittest.TestCase):
|
||||||
],
|
],
|
||||||
enabled_vlans=['vlan2']
|
enabled_vlans=['vlan2']
|
||||||
)
|
)
|
||||||
p = VirtualServerModuleParameters(args)
|
p = ModuleParameters(params=args)
|
||||||
assert p.name == 'my-virtual-server'
|
assert p.name == 'my-virtual-server'
|
||||||
assert p.partition == 'Common'
|
assert p.partition == 'Common'
|
||||||
assert p.port == 443
|
assert p.port == 443
|
||||||
|
@ -235,7 +216,7 @@ class TestParameters(unittest.TestCase):
|
||||||
],
|
],
|
||||||
enabled_vlans=['/Common/vlan2']
|
enabled_vlans=['/Common/vlan2']
|
||||||
)
|
)
|
||||||
p = VirtualServerModuleParameters(args)
|
p = ModuleParameters(params=args)
|
||||||
assert p.name == 'my-virtual-server'
|
assert p.name == 'my-virtual-server'
|
||||||
assert p.partition == 'Common'
|
assert p.partition == 'Common'
|
||||||
assert p.port == 443
|
assert p.port == 443
|
||||||
|
@ -342,7 +323,7 @@ class TestParameters(unittest.TestCase):
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
p = VirtualServerApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.name == 'my-virtual-server'
|
assert p.name == 'my-virtual-server'
|
||||||
assert p.partition == 'Common'
|
assert p.partition == 'Common'
|
||||||
assert p.port == 443
|
assert p.port == 443
|
||||||
|
@ -358,8 +339,6 @@ class TestParameters(unittest.TestCase):
|
||||||
assert '/Common/net1' in p.vlans
|
assert '/Common/net1' in p.vlans
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -388,19 +367,15 @@ class TestManager(unittest.TestCase):
|
||||||
validate_certs="no"
|
validate_certs="no"
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
vsm.create_on_device = Mock(return_value=True)
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
|
@ -423,18 +398,14 @@ class TestManager(unittest.TestCase):
|
||||||
validate_certs="no"
|
validate_certs="no"
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
|
@ -460,26 +431,22 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = VirtualServerApiParameters(
|
current = ApiParameters(
|
||||||
dict(
|
dict(
|
||||||
agent_status_traps='disabled'
|
agent_status_traps='disabled'
|
||||||
)
|
)
|
||||||
)
|
)
|
||||||
|
|
||||||
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
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
vsm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
vsm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is False
|
assert results['changed'] is False
|
||||||
|
@ -498,22 +465,18 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = VirtualServerApiParameters(load_fixture('load_ltm_virtual_1.json'))
|
current = ApiParameters(params=load_fixture('load_ltm_virtual_1.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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
vsm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
vsm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
|
@ -532,21 +495,17 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = VirtualServerApiParameters(load_fixture('load_ltm_virtual_1.json'))
|
current = ApiParameters(params=load_fixture('load_ltm_virtual_1.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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
vsm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is False
|
assert results['changed'] is False
|
||||||
|
@ -567,21 +526,17 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = VirtualServerApiParameters(load_fixture('load_ltm_virtual_2.json'))
|
current = ApiParameters(params=load_fixture('load_ltm_virtual_2.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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
vsm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
|
@ -603,22 +558,18 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = VirtualServerApiParameters(load_fixture('load_ltm_virtual_2.json'))
|
current = ApiParameters(params=load_fixture('load_ltm_virtual_2.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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
vsm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
vsm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
|
@ -674,22 +625,18 @@ class TestManager(unittest.TestCase):
|
||||||
|
|
||||||
# Configure the parameters that would be returned by querying the
|
# Configure the parameters that would be returned by querying the
|
||||||
# remote device
|
# remote device
|
||||||
current = VirtualServerApiParameters(load_fixture('load_ltm_virtual_3.json'))
|
current = ApiParameters(params=load_fixture('load_ltm_virtual_3.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 to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
vsm = VirtualServerManager(client)
|
mm = ModuleManager(module=module)
|
||||||
vsm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
vsm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
vsm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(return_value=vsm)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
|
@ -727,47 +674,3 @@ class TestManager(unittest.TestCase):
|
||||||
assert 'context' in results['profiles'][1]
|
assert 'context' in results['profiles'][1]
|
||||||
assert results['profiles'][1]['name'] == 'clientssl'
|
assert results['profiles'][1]['name'] == 'clientssl'
|
||||||
assert results['profiles'][1]['context'] == 'clientside'
|
assert results['profiles'][1]['context'] == 'clientside'
|
||||||
|
|
||||||
|
|
||||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
|
||||||
return_value=True)
|
|
||||||
class TestDeprecatedAnsible24Manager(unittest.TestCase):
|
|
||||||
def setUp(self):
|
|
||||||
self.spec = ArgumentSpec()
|
|
||||||
|
|
||||||
def test_modify_port_idempotent(self, *args):
|
|
||||||
set_module_args(dict(
|
|
||||||
destination="10.10.10.10",
|
|
||||||
name="my-virtual-server",
|
|
||||||
route_advertisement_state="enabled",
|
|
||||||
partition="Common",
|
|
||||||
password="secret",
|
|
||||||
port="443",
|
|
||||||
server="localhost",
|
|
||||||
state="present",
|
|
||||||
user="admin",
|
|
||||||
validate_certs="no"
|
|
||||||
))
|
|
||||||
|
|
||||||
client = AnsibleF5Client(
|
|
||||||
argument_spec=self.spec.argument_spec,
|
|
||||||
supports_check_mode=self.spec.supports_check_mode,
|
|
||||||
f5_product_name=self.spec.f5_product_name
|
|
||||||
)
|
|
||||||
|
|
||||||
vsm_current = VirtualServerApiParameters(load_fixture('load_ltm_virtual_1.json'))
|
|
||||||
vam_current = VirtualAddressParameters(load_fixture('load_ltm_virtual_1_address.json'))
|
|
||||||
|
|
||||||
vsm = VirtualServerManager(client)
|
|
||||||
vsm.exists = Mock(return_value=True)
|
|
||||||
vsm.read_current_from_device = Mock(return_value=vsm_current)
|
|
||||||
vam = VirtualAddressManager(client)
|
|
||||||
vam.exists = Mock(return_value=True)
|
|
||||||
vam.read_current_from_device = Mock(return_value=vam_current)
|
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.get_manager = Mock(side_effect=[vsm, vam])
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
|
||||||
|
|
||||||
assert results['changed'] is False
|
|
||||||
|
|
|
@ -8,7 +8,6 @@ __metaclass__ = type
|
||||||
|
|
||||||
import os
|
import os
|
||||||
import json
|
import json
|
||||||
import pytest
|
|
||||||
import sys
|
import sys
|
||||||
|
|
||||||
from nose.plugins.skip import SkipTest
|
from nose.plugins.skip import SkipTest
|
||||||
|
@ -18,21 +17,24 @@ 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_vlan import Parameters
|
from library.bigip_vlan import ApiParameters
|
||||||
|
from library.bigip_vlan import ModuleParameters
|
||||||
from library.bigip_vlan import ModuleManager
|
from library.bigip_vlan import ModuleManager
|
||||||
from library.bigip_vlan import ArgumentSpec
|
from library.bigip_vlan 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_vlan import Parameters
|
from ansible.modules.network.f5.bigip_vlan import ApiParameters
|
||||||
|
from ansible.modules.network.f5.bigip_vlan import ModuleParameters
|
||||||
from ansible.modules.network.f5.bigip_vlan import ModuleManager
|
from ansible.modules.network.f5.bigip_vlan import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_vlan import ArgumentSpec
|
from ansible.modules.network.f5.bigip_vlan 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")
|
||||||
|
@ -65,13 +67,6 @@ class BigIpObj(object):
|
||||||
|
|
||||||
|
|
||||||
class TestParameters(unittest.TestCase):
|
class TestParameters(unittest.TestCase):
|
||||||
|
|
||||||
def setUp(self):
|
|
||||||
self.loaded_ifcs = []
|
|
||||||
ifcs_json = load_fixture('load_net_interfaces.json')
|
|
||||||
for item in ifcs_json:
|
|
||||||
self.loaded_ifcs.append(BigIpObj(**item))
|
|
||||||
|
|
||||||
def test_module_parameters(self):
|
def test_module_parameters(self):
|
||||||
args = dict(
|
args = dict(
|
||||||
name='somevlan',
|
name='somevlan',
|
||||||
|
@ -79,9 +74,7 @@ class TestParameters(unittest.TestCase):
|
||||||
description='fakevlan',
|
description='fakevlan',
|
||||||
untagged_interfaces=['1.1'],
|
untagged_interfaces=['1.1'],
|
||||||
)
|
)
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
p = ModuleParameters(params=args)
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
p = Parameters(args)
|
|
||||||
|
|
||||||
assert p.name == 'somevlan'
|
assert p.name == 'somevlan'
|
||||||
assert p.tag == 213
|
assert p.tag == 213
|
||||||
|
@ -92,38 +85,20 @@ class TestParameters(unittest.TestCase):
|
||||||
args = dict(
|
args = dict(
|
||||||
name='somevlan',
|
name='somevlan',
|
||||||
description='fakevlan',
|
description='fakevlan',
|
||||||
tag=213,
|
tag=213
|
||||||
tagged_interfaces=['1.2']
|
|
||||||
)
|
)
|
||||||
|
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
p = ApiParameters(params=args)
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
p = Parameters(args)
|
|
||||||
|
|
||||||
assert p.name == 'somevlan'
|
assert p.name == 'somevlan'
|
||||||
assert p.tag == 213
|
assert p.tag == 213
|
||||||
assert p.interfaces == [{'tagged': True, 'name': '1.2'}]
|
|
||||||
assert p.description == 'fakevlan'
|
assert p.description == 'fakevlan'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
self.spec = ArgumentSpec()
|
self.spec = ArgumentSpec()
|
||||||
self.loaded_ifcs = []
|
|
||||||
self.loaded_vlan_ifc_tag = []
|
|
||||||
self.loaded_vlan_ifc_untag = []
|
|
||||||
ifcs_tag = load_fixture('load_vlan_tagged_ifcs.json')
|
|
||||||
ifcs_untag = load_fixture('load_vlan_untag_ifcs.json')
|
|
||||||
ifcs_json = load_fixture('load_net_interfaces.json')
|
|
||||||
for item in ifcs_json:
|
|
||||||
self.loaded_ifcs.append(BigIpObj(**item))
|
|
||||||
for item in ifcs_tag:
|
|
||||||
self.loaded_vlan_ifc_tag.append(BigIpObj(**item))
|
|
||||||
for item in ifcs_untag:
|
|
||||||
self.loaded_vlan_ifc_untag.append(BigIpObj(**item))
|
|
||||||
|
|
||||||
def test_create_vlan(self, *args):
|
def test_create_vlan(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -135,24 +110,19 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common'
|
partition='Common'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
results = mm.exec_module()
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['name'] == 'somevlan'
|
|
||||||
assert results['description'] == 'fakevlan'
|
assert results['description'] == 'fakevlan'
|
||||||
|
|
||||||
def test_create_vlan_tagged_interface(self, *args):
|
def test_create_vlan_tagged_interface(self, *args):
|
||||||
|
@ -166,26 +136,21 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common'
|
partition='Common'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
results = mm.exec_module()
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['interfaces'] == [{'tagged': True, 'name': '2.1'}]
|
assert results['tagged_interfaces'] == ['2.1']
|
||||||
assert results['tag'] == 213
|
assert results['tag'] == 213
|
||||||
assert results['name'] == 'somevlan'
|
|
||||||
|
|
||||||
def test_create_vlan_untagged_interface(self, *args):
|
def test_create_vlan_untagged_interface(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -197,25 +162,20 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common'
|
partition='Common'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
results = mm.exec_module()
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['interfaces'] == [{'untagged': True, 'name': '2.1'}]
|
assert results['untagged_interfaces'] == ['2.1']
|
||||||
assert results['name'] == 'somevlan'
|
|
||||||
|
|
||||||
def test_create_vlan_tagged_interfaces(self, *args):
|
def test_create_vlan_tagged_interfaces(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -228,27 +188,21 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common'
|
partition='Common'
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
results = mm.exec_module()
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['interfaces'] == [{'tagged': True, 'name': '2.1'},
|
assert results['tagged_interfaces'] == ['1.1', '2.1']
|
||||||
{'tagged': True, 'name': '1.1'}]
|
|
||||||
assert results['tag'] == 213
|
assert results['tag'] == 213
|
||||||
assert results['name'] == 'somevlan'
|
|
||||||
|
|
||||||
def test_create_vlan_untagged_interfaces(self, *args):
|
def test_create_vlan_untagged_interfaces(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -260,26 +214,20 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common',
|
partition='Common',
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
mm.exists = Mock(return_value=False)
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
results = mm.exec_module()
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
results = mm.exec_module()
|
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['interfaces'] == [{'untagged': True, 'name': '2.1'},
|
assert results['untagged_interfaces'] == ['1.1', '2.1']
|
||||||
{'untagged': True, 'name': '1.1'}]
|
|
||||||
assert results['name'] == 'somevlan'
|
|
||||||
|
|
||||||
def test_update_vlan_untag_interface(self, *args):
|
def test_update_vlan_untag_interface(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -291,32 +239,26 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common',
|
partition='Common',
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
ifcs = self.loaded_vlan_ifc_untag
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
|
|
||||||
current = (
|
current = ApiParameters(params=load_fixture('load_vlan.json'))
|
||||||
Parameters(
|
interfaces = load_fixture('load_vlan_interfaces.json')
|
||||||
load_fixture('load_vlan.json')
|
current.update({'interfaces': interfaces})
|
||||||
),
|
|
||||||
ifcs
|
|
||||||
)
|
|
||||||
|
|
||||||
mm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
mm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
mm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['interfaces'] == [{'untagged': True, 'name': '2.1'}]
|
assert results['untagged_interfaces'] == ['2.1']
|
||||||
|
|
||||||
def test_update_vlan_tag_interface(self, *args):
|
def test_update_vlan_tag_interface(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -328,32 +270,24 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common',
|
partition='Common',
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
ifcs = self.loaded_vlan_ifc_tag
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
|
|
||||||
current = (
|
current = ApiParameters(params=load_fixture('load_vlan.json'))
|
||||||
Parameters(
|
|
||||||
load_fixture('load_vlan.json')
|
|
||||||
),
|
|
||||||
ifcs
|
|
||||||
)
|
|
||||||
|
|
||||||
mm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
mm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
mm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['interfaces'] == [{'tagged': True, 'name': '2.1'}]
|
assert results['tagged_interfaces'] == ['2.1']
|
||||||
|
|
||||||
def test_update_vlan_description(self, *args):
|
def test_update_vlan_description(self, *args):
|
||||||
set_module_args(dict(
|
set_module_args(dict(
|
||||||
|
@ -365,117 +299,21 @@ class TestManager(unittest.TestCase):
|
||||||
partition='Common',
|
partition='Common',
|
||||||
))
|
))
|
||||||
|
|
||||||
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
|
|
||||||
)
|
)
|
||||||
ifcs = self.loaded_vlan_ifc_tag
|
|
||||||
# Override methods to force specific logic in the module to happen
|
# Override methods to force specific logic in the module to happen
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
mm = ModuleManager(module=module)
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
|
|
||||||
current = (
|
current = ApiParameters(params=load_fixture('update_vlan_description.json'))
|
||||||
Parameters(
|
|
||||||
load_fixture('update_vlan_description.json')
|
|
||||||
),
|
|
||||||
ifcs
|
|
||||||
)
|
|
||||||
|
|
||||||
mm.update_on_device = Mock(return_value=True)
|
mm.update_on_device = Mock(return_value=True)
|
||||||
mm.exists = Mock(return_value=True)
|
mm.exists = Mock(return_value=True)
|
||||||
mm.read_current_from_device = Mock(return_value=current)
|
mm.read_current_from_device = Mock(return_value=current)
|
||||||
|
|
||||||
results = mm.exec_module()
|
results = mm.exec_module()
|
||||||
|
|
||||||
assert results['changed'] is True
|
assert results['changed'] is True
|
||||||
assert results['description'] == 'changed_that'
|
assert results['description'] == 'changed_that'
|
||||||
|
|
||||||
def test_untagged_ifc_raises(self, *args):
|
|
||||||
set_module_args(dict(
|
|
||||||
name='somevlan',
|
|
||||||
untagged_interface=['10.2'],
|
|
||||||
server='localhost',
|
|
||||||
password='password',
|
|
||||||
user='admin',
|
|
||||||
partition='Common'
|
|
||||||
))
|
|
||||||
|
|
||||||
client = AnsibleF5Client(
|
|
||||||
argument_spec=self.spec.argument_spec,
|
|
||||||
supports_check_mode=self.spec.supports_check_mode,
|
|
||||||
f5_product_name=self.spec.f5_product_name
|
|
||||||
)
|
|
||||||
msg = 'The specified interface "10.2" was not found'
|
|
||||||
# Override methods to force specific logic in the module to happen
|
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as err:
|
|
||||||
mm.exec_module()
|
|
||||||
|
|
||||||
assert str(err.value) == msg
|
|
||||||
|
|
||||||
def test_tagged_ifc_raises(self, *args):
|
|
||||||
set_module_args(dict(
|
|
||||||
name='somevlan',
|
|
||||||
tagged_interface=['10.2'],
|
|
||||||
tag=213,
|
|
||||||
server='localhost',
|
|
||||||
password='password',
|
|
||||||
user='admin',
|
|
||||||
partition='Common'
|
|
||||||
))
|
|
||||||
|
|
||||||
client = AnsibleF5Client(
|
|
||||||
argument_spec=self.spec.argument_spec,
|
|
||||||
supports_check_mode=self.spec.supports_check_mode,
|
|
||||||
f5_product_name=self.spec.f5_product_name
|
|
||||||
)
|
|
||||||
msg = 'The specified interface "10.2" was not found'
|
|
||||||
# Override methods to force specific logic in the module to happen
|
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
|
||||||
obj.return_value = self.loaded_ifcs
|
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as err:
|
|
||||||
mm.exec_module()
|
|
||||||
|
|
||||||
assert str(err.value) == msg
|
|
||||||
|
|
||||||
def test_parse_return_ifcs_raises(self, *args):
|
|
||||||
set_module_args(dict(
|
|
||||||
name='somevlan',
|
|
||||||
untagged_interface=['1.2'],
|
|
||||||
server='localhost',
|
|
||||||
password='password',
|
|
||||||
user='admin',
|
|
||||||
partition='Common'
|
|
||||||
))
|
|
||||||
|
|
||||||
client = AnsibleF5Client(
|
|
||||||
argument_spec=self.spec.argument_spec,
|
|
||||||
supports_check_mode=self.spec.supports_check_mode,
|
|
||||||
f5_product_name=self.spec.f5_product_name
|
|
||||||
)
|
|
||||||
msg = 'No interfaces were found'
|
|
||||||
# Override methods to force specific logic in the module to happen
|
|
||||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
|
||||||
obj.return_value = []
|
|
||||||
|
|
||||||
mm = ModuleManager(client)
|
|
||||||
mm.create_on_device = Mock(return_value=True)
|
|
||||||
mm.exists = Mock(return_value=False)
|
|
||||||
|
|
||||||
with pytest.raises(F5ModuleError) as err:
|
|
||||||
mm.exec_module()
|
|
||||||
|
|
||||||
assert str(err.value) == msg
|
|
||||||
|
|
|
@ -18,23 +18,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
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from library.bigip_wait import Parameters
|
from library.bigip_wait import Parameters
|
||||||
from library.bigip_wait import ModuleManager
|
from library.bigip_wait import ModuleManager
|
||||||
from library.bigip_wait import ArgumentSpec
|
from library.bigip_wait import ArgumentSpec
|
||||||
from library.bigip_wait import AnsibleF5ClientStub
|
from library.module_utils.network.f5.common import F5ModuleError
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
||||||
from test.unit.modules.utils import set_module_args
|
from test.unit.modules.utils import set_module_args
|
||||||
except ImportError:
|
except ImportError:
|
||||||
try:
|
try:
|
||||||
from ansible.modules.network.f5.bigip_wait import Parameters
|
from ansible.modules.network.f5.bigip_wait import Parameters
|
||||||
from ansible.modules.network.f5.bigip_wait import ModuleManager
|
from ansible.modules.network.f5.bigip_wait import ModuleManager
|
||||||
from ansible.modules.network.f5.bigip_wait import ArgumentSpec
|
from ansible.modules.network.f5.bigip_wait import ArgumentSpec
|
||||||
from ansible.modules.network.f5.bigip_wait import AnsibleF5ClientStub
|
from ansible.module_utils.network.f5.common import F5ModuleError
|
||||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
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")
|
||||||
|
@ -70,7 +69,7 @@ class TestParameters(unittest.TestCase):
|
||||||
msg='We timed out during waiting for BIG-IP :-('
|
msg='We timed out during waiting for BIG-IP :-('
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.delay == 3
|
assert p.delay == 3
|
||||||
assert p.timeout == 500
|
assert p.timeout == 500
|
||||||
assert p.sleep == 10
|
assert p.sleep == 10
|
||||||
|
@ -84,15 +83,13 @@ class TestParameters(unittest.TestCase):
|
||||||
msg='We timed out during waiting for BIG-IP :-('
|
msg='We timed out during waiting for BIG-IP :-('
|
||||||
)
|
)
|
||||||
|
|
||||||
p = Parameters(args)
|
p = Parameters(params=args)
|
||||||
assert p.delay == 3
|
assert p.delay == 3
|
||||||
assert p.timeout == 500
|
assert p.timeout == 500
|
||||||
assert p.sleep == 10
|
assert p.sleep == 10
|
||||||
assert p.msg == 'We timed out during waiting for BIG-IP :-('
|
assert p.msg == 'We timed out during waiting for BIG-IP :-('
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
self.spec = ArgumentSpec()
|
self.spec = ArgumentSpec()
|
||||||
|
@ -104,14 +101,13 @@ class TestManager(unittest.TestCase):
|
||||||
user='admin'
|
user='admin'
|
||||||
))
|
))
|
||||||
|
|
||||||
client = AnsibleF5ClientStub(
|
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._connect_to_device = Mock(return_value=True)
|
mm._connect_to_device = Mock(return_value=True)
|
||||||
mm._device_is_rebooting = Mock(return_value=False)
|
mm._device_is_rebooting = Mock(return_value=False)
|
||||||
mm._is_mprov_running_on_device = Mock(return_value=False)
|
mm._is_mprov_running_on_device = Mock(return_value=False)
|
||||||
|
|
|
@ -18,15 +18,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
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from library.bigiq_regkey_license import ModuleParameters
|
from library.bigiq_regkey_license import ModuleParameters
|
||||||
from library.bigiq_regkey_license import ApiParameters
|
from library.bigiq_regkey_license import ApiParameters
|
||||||
from library.bigiq_regkey_license import ModuleManager
|
from library.bigiq_regkey_license import ModuleManager
|
||||||
from library.bigiq_regkey_license import ArgumentSpec
|
from library.bigiq_regkey_license 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:
|
||||||
|
@ -34,7 +34,8 @@ except ImportError:
|
||||||
from ansible.modules.network.f5.bigiq_regkey_license import ApiParameters
|
from ansible.modules.network.f5.bigiq_regkey_license import ApiParameters
|
||||||
from ansible.modules.network.f5.bigiq_regkey_license import ModuleManager
|
from ansible.modules.network.f5.bigiq_regkey_license import ModuleManager
|
||||||
from ansible.modules.network.f5.bigiq_regkey_license import ArgumentSpec
|
from ansible.modules.network.f5.bigiq_regkey_license 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")
|
||||||
|
@ -70,7 +71,7 @@ class TestParameters(unittest.TestCase):
|
||||||
description='this is a description'
|
description='this is a description'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = ModuleParameters(args)
|
p = ModuleParameters(params=args)
|
||||||
assert p.regkey_pool == 'foo'
|
assert p.regkey_pool == 'foo'
|
||||||
assert p.license_key == 'XXXX-XXXX-XXXX-XXXX-XXXX'
|
assert p.license_key == 'XXXX-XXXX-XXXX-XXXX-XXXX'
|
||||||
assert p.accept_eula is True
|
assert p.accept_eula is True
|
||||||
|
@ -79,12 +80,10 @@ class TestParameters(unittest.TestCase):
|
||||||
def test_api_parameters(self):
|
def test_api_parameters(self):
|
||||||
args = load_fixture('load_regkey_license_key.json')
|
args = load_fixture('load_regkey_license_key.json')
|
||||||
|
|
||||||
p = ApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.description == 'foo bar baz'
|
assert p.description == 'foo bar baz'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -101,12 +100,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,14 +18,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
|
||||||
from ansible.module_utils.f5_utils import F5ModuleError
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from library.bigiq_regkey_pool import ModuleParameters
|
from library.bigiq_regkey_pool import ModuleParameters
|
||||||
from library.bigiq_regkey_pool import ApiParameters
|
from library.bigiq_regkey_pool import ApiParameters
|
||||||
from library.bigiq_regkey_pool import ModuleManager
|
from library.bigiq_regkey_pool import ModuleManager
|
||||||
from library.bigiq_regkey_pool import ArgumentSpec
|
from library.bigiq_regkey_pool import ArgumentSpec
|
||||||
|
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:
|
||||||
|
@ -33,6 +34,8 @@ except ImportError:
|
||||||
from ansible.modules.network.f5.bigiq_regkey_pool import ApiParameters
|
from ansible.modules.network.f5.bigiq_regkey_pool import ApiParameters
|
||||||
from ansible.modules.network.f5.bigiq_regkey_pool import ModuleManager
|
from ansible.modules.network.f5.bigiq_regkey_pool import ModuleManager
|
||||||
from ansible.modules.network.f5.bigiq_regkey_pool import ArgumentSpec
|
from ansible.modules.network.f5.bigiq_regkey_pool import ArgumentSpec
|
||||||
|
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")
|
||||||
|
@ -65,18 +68,16 @@ class TestParameters(unittest.TestCase):
|
||||||
description='this is a description'
|
description='this is a description'
|
||||||
)
|
)
|
||||||
|
|
||||||
p = ModuleParameters(args)
|
p = ModuleParameters(params=args)
|
||||||
assert p.description == 'this is a description'
|
assert p.description == 'this is a description'
|
||||||
|
|
||||||
def test_api_parameters(self):
|
def test_api_parameters(self):
|
||||||
args = load_fixture('load_regkey_license_pool.json')
|
args = load_fixture('load_regkey_license_pool.json')
|
||||||
|
|
||||||
p = ApiParameters(args)
|
p = ApiParameters(params=args)
|
||||||
assert p.description == 'this is a description'
|
assert p.description == 'this is a description'
|
||||||
|
|
||||||
|
|
||||||
@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):
|
||||||
|
@ -91,14 +92,13 @@ 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
|
|
||||||
)
|
)
|
||||||
|
|
||||||
# Override methods in the specific type of manager
|
# Override methods in the specific type of manager
|
||||||
mm = ModuleManager(client)
|
mm = ModuleManager(module=module)
|
||||||
mm.exists = Mock(return_value=False)
|
mm.exists = Mock(return_value=False)
|
||||||
mm.create_on_device = Mock(return_value=True)
|
mm.create_on_device = Mock(return_value=True)
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue