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
|
||||
variable back to the default value. At least one of value and state
|
||||
C(reset) are required.
|
||||
required: False
|
||||
default: present
|
||||
choices:
|
||||
- present
|
||||
|
@ -39,14 +38,9 @@ options:
|
|||
description:
|
||||
- The value to set the key to. At least one of value and state C(reset)
|
||||
are required.
|
||||
required: False
|
||||
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
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- f5-sdk
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
'''
|
||||
|
@ -98,15 +92,37 @@ value:
|
|||
sample: 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.basic import AnsibleModule
|
||||
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
|
||||
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:
|
||||
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):
|
||||
|
@ -124,16 +140,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
result = self._filter_params(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
|
||||
def name(self):
|
||||
return self._values['key']
|
||||
|
@ -143,12 +149,17 @@ class Parameters(AnsibleF5Parameters):
|
|||
self._values['key'] = value
|
||||
|
||||
|
||||
class Changes(Parameters):
|
||||
pass
|
||||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.have = None
|
||||
self.want = Parameters(self.client.module.params)
|
||||
self.changes = Parameters()
|
||||
self.want = Parameters(params=self.module.params)
|
||||
self.changes = Changes()
|
||||
|
||||
def _update_changed_options(self):
|
||||
changed = {}
|
||||
|
@ -159,10 +170,10 @@ class ModuleManager(object):
|
|||
if attr1 != attr2:
|
||||
changed[key] = attr1
|
||||
if self.want.state == 'reset':
|
||||
if str(self.want.value) == str(self.want.default_value):
|
||||
changed[self.want.key] = self.want.value
|
||||
if str(self.have.value) != str(self.have.default_value):
|
||||
changed[self.want.key] = self.have.default_value
|
||||
if changed:
|
||||
self.changes = Parameters(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -189,7 +200,7 @@ class ModuleManager(object):
|
|||
name=self.want.key
|
||||
)
|
||||
result = resource.attrs
|
||||
return Parameters(result)
|
||||
return Parameters(params=result)
|
||||
|
||||
def exists(self):
|
||||
resource = self.client.api.tm.sys.dbs.db.load(
|
||||
|
@ -213,7 +224,7 @@ class ModuleManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
@ -235,9 +246,11 @@ class ModuleManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
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():
|
||||
return True
|
||||
else:
|
||||
|
@ -249,13 +262,13 @@ class ModuleManager(object):
|
|||
resource = self.client.api.tm.sys.dbs.db.load(
|
||||
name=self.want.key
|
||||
)
|
||||
resource.update(value=self.want.default_value)
|
||||
resource.update(value=self.have.default_value)
|
||||
|
||||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
key=dict(required=True),
|
||||
state=dict(
|
||||
default='present',
|
||||
|
@ -263,27 +276,30 @@ class ArgumentSpec(object):
|
|||
),
|
||||
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():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
client.module.fail_json(msg=str(e))
|
||||
cleanup_tokens(client)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -30,48 +30,44 @@ options:
|
|||
gui_setup:
|
||||
description:
|
||||
- C(enable) or C(disabled) the Setup utility in the browser-based
|
||||
Configuration utility
|
||||
choices: ['yes', 'no']
|
||||
Configuration utility.
|
||||
type: bool
|
||||
lcd_display:
|
||||
description:
|
||||
- Specifies, when C(enabled), that the system menu displays on the
|
||||
LCD screen on the front of the unit. This setting has no effect
|
||||
when used on the VE platform.
|
||||
choices: ['yes', 'no']
|
||||
type: bool
|
||||
mgmt_dhcp:
|
||||
description:
|
||||
- Specifies whether or not to enable DHCP client on the management
|
||||
interface
|
||||
choices: ['yes', 'no']
|
||||
type: bool
|
||||
net_reboot:
|
||||
description:
|
||||
- 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
|
||||
internal media drive.
|
||||
choices: ['yes', 'no']
|
||||
type: bool
|
||||
quiet_boot:
|
||||
description:
|
||||
- Specifies, when C(enabled), that the system suppresses informational
|
||||
text on the console during the boot cycle. When C(disabled), the
|
||||
system presents messages and informational text on the console during
|
||||
the boot cycle.
|
||||
choices: ['yes', 'no']
|
||||
type: bool
|
||||
security_banner:
|
||||
description:
|
||||
- Specifies whether the system displays an advisory message on the
|
||||
login screen.
|
||||
choices: ['yes', 'no']
|
||||
type: bool
|
||||
state:
|
||||
description:
|
||||
- The state of the variable on the system. When C(present), guarantees
|
||||
that an existing variable is set to C(value).
|
||||
required: false
|
||||
default: present
|
||||
choices:
|
||||
- present
|
||||
notes:
|
||||
- Requires the f5-sdk Python package on the host. This is as easy as pip
|
||||
install f5-sdk.
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- f5-sdk
|
||||
|
@ -139,20 +135,40 @@ security_banner:
|
|||
sample: enabled
|
||||
'''
|
||||
|
||||
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.basic import AnsibleModule
|
||||
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_FALSE
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
|
||||
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:
|
||||
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):
|
||||
|
@ -182,46 +198,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
'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):
|
||||
pass
|
||||
|
@ -323,9 +299,10 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.want = ModuleParameters(params=self.client.module.params)
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = ModuleParameters(params=self.module.params)
|
||||
self.have = ApiParameters()
|
||||
self.changes = UsableChanges()
|
||||
|
||||
|
@ -335,7 +312,7 @@ class ModuleManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = UsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
diff = Difference(self.want, self.have)
|
||||
|
@ -351,7 +328,7 @@ class ModuleManager(object):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = UsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -369,7 +346,7 @@ class ModuleManager(object):
|
|||
except iControlUnexpectedHTTPError as e:
|
||||
raise F5ModuleError(str(e))
|
||||
|
||||
reportable = ReportableChanges(self.changes.to_return())
|
||||
reportable = ReportableChanges(params=self.changes.to_return())
|
||||
changes = reportable.to_return()
|
||||
result.update(**changes)
|
||||
result.update(dict(changed=changed))
|
||||
|
@ -379,7 +356,7 @@ class ModuleManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -390,13 +367,13 @@ class ModuleManager(object):
|
|||
def read_current_from_device(self):
|
||||
resource = self.client.api.tm.sys.global_settings.load()
|
||||
result = resource.attrs
|
||||
return ApiParameters(result)
|
||||
return ApiParameters(params=result)
|
||||
|
||||
def update(self):
|
||||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
@ -412,7 +389,7 @@ class ArgumentSpec(object):
|
|||
self.supports_check_mode = True
|
||||
self.states = ['present']
|
||||
self.on_off_choices = ['enabled', 'disabled', 'True', 'False'] + list(BOOLEANS)
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
security_banner=dict(
|
||||
choices=self.on_off_choices
|
||||
),
|
||||
|
@ -435,39 +412,30 @@ class ArgumentSpec(object):
|
|||
console_timeout=dict(required=False, type='int', default=None),
|
||||
state=dict(default='present', choices=['present'])
|
||||
)
|
||||
self.f5_product_name = 'bigip'
|
||||
|
||||
|
||||
def cleanup_tokens(client):
|
||||
try:
|
||||
resource = client.api.shared.authz.tokens_s.token.load(
|
||||
name=client.api.icrs.token
|
||||
)
|
||||
resource.delete()
|
||||
except Exception:
|
||||
pass
|
||||
self.argument_spec = {}
|
||||
self.argument_spec.update(f5_argument_spec)
|
||||
self.argument_spec.update(argument_spec)
|
||||
|
||||
|
||||
def main():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
cleanup_tokens(client)
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -24,11 +24,20 @@ options:
|
|||
description:
|
||||
- The name of the traffic group.
|
||||
required: True
|
||||
notes:
|
||||
- Requires the f5-sdk Python package on the host. This is as easy as
|
||||
C(pip install f5-sdk).
|
||||
requirements:
|
||||
- f5-sdk >= 3.0.5
|
||||
partition:
|
||||
description:
|
||||
- Device partition to manage resources on.
|
||||
default: Common
|
||||
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
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
|
@ -49,18 +58,38 @@ RETURN = r'''
|
|||
# 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
|
||||
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
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
|
||||
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:
|
||||
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):
|
||||
|
@ -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):
|
||||
result = {}
|
||||
try:
|
||||
|
@ -120,16 +119,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
pass
|
||||
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):
|
||||
pass
|
||||
|
@ -164,9 +153,10 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.want = Parameters(self.client.module.params)
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = Parameters(params=self.module.params)
|
||||
self.changes = Changes()
|
||||
|
||||
def _set_changed_options(self):
|
||||
|
@ -175,38 +165,9 @@ class ModuleManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = Changes(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
|
||||
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)
|
||||
updatables = Parameters.updatables
|
||||
changed = dict()
|
||||
|
@ -220,7 +181,7 @@ class ModuleManager(object):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = Changes(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -252,7 +213,7 @@ class ModuleManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -274,13 +235,13 @@ class ModuleManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -293,7 +254,7 @@ class ModuleManager(object):
|
|||
raise F5ModuleError(
|
||||
"Traffic groups can only be created in the /Common partition"
|
||||
)
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.create_on_device()
|
||||
return True
|
||||
|
@ -333,49 +294,44 @@ class ModuleManager(object):
|
|||
partition=self.want.partition
|
||||
)
|
||||
result = resource.attrs
|
||||
return Parameters(result)
|
||||
return Parameters(params=result)
|
||||
|
||||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
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'
|
||||
|
||||
|
||||
def cleanup_tokens(client):
|
||||
try:
|
||||
resource = client.api.shared.authz.tokens_s.token.load(
|
||||
name=client.api.icrs.token
|
||||
)
|
||||
resource.delete()
|
||||
except Exception:
|
||||
pass
|
||||
self.argument_spec = {}
|
||||
self.argument_spec.update(f5_argument_spec)
|
||||
self.argument_spec.update(argument_spec)
|
||||
|
||||
|
||||
def main():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
cleanup_tokens(client)
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -87,8 +87,6 @@ options:
|
|||
- installed
|
||||
- present
|
||||
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
|
||||
considerations need to be taken into account. See the following URL.
|
||||
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
|
||||
RMA units.
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- f5-sdk
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
'''
|
||||
|
@ -182,15 +178,41 @@ RETURN = r'''
|
|||
|
||||
import os
|
||||
import re
|
||||
import sys
|
||||
import time
|
||||
|
||||
from distutils.version import LooseVersion
|
||||
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.basic import AnsibleModule
|
||||
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:
|
||||
from collections import OrderedDict
|
||||
|
@ -200,11 +222,6 @@ except ImportError:
|
|||
except ImportError:
|
||||
pass
|
||||
|
||||
try:
|
||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
||||
except ImportError:
|
||||
HAS_F5SDK = False
|
||||
|
||||
|
||||
class Parameters(AnsibleF5Parameters):
|
||||
api_map = {}
|
||||
|
@ -292,14 +309,15 @@ class Parameters(AnsibleF5Parameters):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.client = kwargs.get('client', None)
|
||||
self.kwargs = kwargs
|
||||
|
||||
def exec_module(self):
|
||||
if self.is_version_v1():
|
||||
manager = V1Manager(self.client)
|
||||
manager = V1Manager(**self.kwargs)
|
||||
else:
|
||||
manager = V2Manager(self.client)
|
||||
manager = V2Manager(**self.kwargs)
|
||||
|
||||
return manager.exec_module()
|
||||
|
||||
|
@ -321,10 +339,10 @@ class ModuleManager(object):
|
|||
|
||||
|
||||
class BaseManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.have = None
|
||||
self.want = Parameters(self.client.module.params)
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = Parameters(params=self.module.params)
|
||||
self.changes = Parameters()
|
||||
|
||||
def exec_module(self):
|
||||
|
@ -352,7 +370,7 @@ class BaseManager(object):
|
|||
return self.create()
|
||||
|
||||
def update(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
if self.want.force:
|
||||
return True
|
||||
return False
|
||||
|
@ -365,7 +383,7 @@ class BaseManager(object):
|
|||
return False
|
||||
|
||||
def create(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.create_on_device()
|
||||
if not self.exists():
|
||||
|
@ -386,7 +404,7 @@ class BaseManager(object):
|
|||
return False
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -466,7 +484,6 @@ class V1Manager(BaseManager):
|
|||
* No API to upload UCS files
|
||||
|
||||
"""
|
||||
|
||||
def create_on_device(self):
|
||||
remote_path = "/var/local/ucs"
|
||||
tpath_name = '/var/config/rest/downloads'
|
||||
|
@ -563,7 +580,7 @@ class V2Manager(V1Manager):
|
|||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
force=dict(
|
||||
type='bool',
|
||||
default='no'
|
||||
|
@ -585,30 +602,30 @@ class ArgumentSpec(object):
|
|||
),
|
||||
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():
|
||||
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()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
client.module.fail_json(msg=str(e))
|
||||
cleanup_tokens(client)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -74,13 +74,14 @@ options:
|
|||
choices:
|
||||
- always
|
||||
- on_create
|
||||
partition:
|
||||
description:
|
||||
- Device partition to manage resources on.
|
||||
default: Common
|
||||
version_added: 2.5
|
||||
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
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- f5-sdk
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
- Wojciech Wypior (@wojtek0806)
|
||||
|
@ -191,24 +192,45 @@ shell:
|
|||
|
||||
import re
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
from distutils.version import LooseVersion
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Parameters
|
||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
|
||||
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:
|
||||
from StringIO import StringIO
|
||||
except ImportError:
|
||||
from io import StringIO
|
||||
|
||||
try:
|
||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
||||
except ImportError:
|
||||
HAS_F5SDK = False
|
||||
|
||||
|
||||
class Parameters(AnsibleF5Parameters):
|
||||
api_map = {
|
||||
|
@ -228,36 +250,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
'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
|
||||
def partition_access(self):
|
||||
"""Partition access values will require some transformation.
|
||||
|
@ -324,18 +316,28 @@ class Parameters(AnsibleF5Parameters):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.kwargs = kwargs
|
||||
|
||||
def exec_module(self):
|
||||
if self.is_root_username_credential():
|
||||
manager = RootUserManager(self.client)
|
||||
manager = self.get_manager('root')
|
||||
elif self.is_version_less_than_13():
|
||||
manager = UnparitionedManager(self.client)
|
||||
manager = self.get_manager('v1')
|
||||
else:
|
||||
manager = PartitionedManager(self.client)
|
||||
manager = self.get_manager('v2')
|
||||
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):
|
||||
"""Checks to see if the TMOS version is less than 13
|
||||
|
||||
|
@ -351,17 +353,18 @@ class ModuleManager(object):
|
|||
return False
|
||||
|
||||
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':
|
||||
return True
|
||||
return False
|
||||
|
||||
|
||||
class BaseManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.have = None
|
||||
self.want = Parameters(self.client.module.params)
|
||||
self.want = Parameters(params=self.module.params)
|
||||
self.changes = Parameters()
|
||||
|
||||
def exec_module(self):
|
||||
|
@ -388,7 +391,7 @@ class BaseManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = Parameters(changed)
|
||||
self.changes = Parameters(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
changed = {}
|
||||
|
@ -411,7 +414,7 @@ class BaseManager(object):
|
|||
changed[key] = attr1
|
||||
|
||||
if changed:
|
||||
self.changes = Parameters(changed)
|
||||
self.changes = Parameters(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -481,13 +484,13 @@ class BaseManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -499,7 +502,7 @@ class BaseManager(object):
|
|||
if self.want.shell == 'bash':
|
||||
self.validate_shell_parameter()
|
||||
self._set_changed_options()
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.create_on_device()
|
||||
return True
|
||||
|
@ -518,7 +521,7 @@ class UnparitionedManager(BaseManager):
|
|||
def read_current_from_device(self):
|
||||
tmp_res = self.client.api.tm.auth.users.user.load(name=self.want.name)
|
||||
result = tmp_res.attrs
|
||||
return Parameters(result)
|
||||
return Parameters(params=result)
|
||||
|
||||
def exists(self):
|
||||
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):
|
||||
resource = self._read_one_resource_from_collection()
|
||||
result = resource.attrs
|
||||
return Parameters(result)
|
||||
return Parameters(params=result)
|
||||
|
||||
def exists(self):
|
||||
collection = self.client.api.tm.auth.users.get_collection(
|
||||
|
@ -646,7 +649,7 @@ class RootUserManager(BaseManager):
|
|||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
name=dict(
|
||||
required=True,
|
||||
aliases=['username_credential']
|
||||
|
@ -664,41 +667,37 @@ class ArgumentSpec(object):
|
|||
update_password=dict(
|
||||
default='always',
|
||||
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'
|
||||
|
||||
|
||||
def cleanup_tokens(client):
|
||||
try:
|
||||
resource = client.api.shared.authz.tokens_s.token.load(
|
||||
name=client.api.icrs.token
|
||||
)
|
||||
resource.delete()
|
||||
except Exception:
|
||||
pass
|
||||
self.argument_spec = {}
|
||||
self.argument_spec.update(f5_argument_spec)
|
||||
self.argument_spec.update(argument_spec)
|
||||
|
||||
|
||||
def main():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
cleanup_tokens(client)
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -112,9 +112,11 @@ options:
|
|||
- 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
|
||||
which it ran prior to the reboot.
|
||||
partition:
|
||||
description:
|
||||
- Device partition to manage resources on.
|
||||
default: Common
|
||||
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
|
||||
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
|
||||
|
@ -123,8 +125,6 @@ notes:
|
|||
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
|
||||
BIG-IP chassis will be available before all vCMP guests are online.
|
||||
requirements:
|
||||
- f5-sdk >= 3.0.3
|
||||
- netaddr
|
||||
extends_documentation_fragment: f5
|
||||
author:
|
||||
|
@ -173,16 +173,41 @@ vlans:
|
|||
sample: ['/Common/vlan1', '/Common/vlan2']
|
||||
'''
|
||||
|
||||
import time
|
||||
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Parameters
|
||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
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:
|
||||
from netaddr import IPAddress, AddrFormatError, IPNetwork
|
||||
|
@ -192,7 +217,6 @@ except ImportError:
|
|||
|
||||
try:
|
||||
from f5.utils.responses.handlers import Stats
|
||||
from ansible.module_utils.f5_utils import iControlUnexpectedHTTPError
|
||||
except ImportError:
|
||||
HAS_F5SDK = False
|
||||
|
||||
|
@ -222,37 +246,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
'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):
|
||||
if value is not None and not value.startswith('/'):
|
||||
return '/{0}/{1}'.format(self.partition, value)
|
||||
|
@ -268,16 +261,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
pass
|
||||
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
|
||||
def mgmt_route(self):
|
||||
if self._values['mgmt_route'] is None:
|
||||
|
@ -394,9 +377,10 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.want = Parameters(client=client, params=self.client.module.params)
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = Parameters(client=self.client, params=self.module.params)
|
||||
self.changes = Changes()
|
||||
|
||||
def _set_changed_options(self):
|
||||
|
@ -405,7 +389,7 @@ class ModuleManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = Changes(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
diff = Difference(self.want, self.have)
|
||||
|
@ -418,7 +402,7 @@ class ModuleManager(object):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = Parameters(changed)
|
||||
self.changes = Parameters(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -450,7 +434,7 @@ class ModuleManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -476,7 +460,7 @@ class ModuleManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
if self.want.state == 'provisioned':
|
||||
|
@ -488,7 +472,7 @@ class ModuleManager(object):
|
|||
return True
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
if self.want.delete_virtual_disk:
|
||||
self.have = self.read_current_from_device()
|
||||
|
@ -501,7 +485,7 @@ class ModuleManager(object):
|
|||
|
||||
def create(self):
|
||||
self._set_changed_options()
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
if self.want.mgmt_tuple.subnet is None:
|
||||
self.want.update(dict(
|
||||
|
@ -547,7 +531,7 @@ class ModuleManager(object):
|
|||
name=self.want.name
|
||||
)
|
||||
result = resource.attrs
|
||||
return Parameters(result)
|
||||
return Parameters(params=result)
|
||||
|
||||
def remove_virtual_disk(self):
|
||||
if self.virtual_disk_exists():
|
||||
|
@ -666,7 +650,7 @@ class ModuleManager(object):
|
|||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
vlans=dict(type='list'),
|
||||
mgmt_network=dict(choices=['bridged', 'isolated', 'host only']),
|
||||
|
@ -680,47 +664,41 @@ class ArgumentSpec(object):
|
|||
delete_virtual_disk=dict(
|
||||
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 = [
|
||||
['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():
|
||||
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()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
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:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
cleanup_tokens(client)
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -100,14 +100,11 @@ options:
|
|||
- Specifies whether the system uses route advertisement for this
|
||||
virtual address. When disabled, the system does not advertise
|
||||
routes for this virtual address.
|
||||
choices:
|
||||
- yes
|
||||
- no
|
||||
type: bool
|
||||
partition:
|
||||
description:
|
||||
- Device partition to manage resources on.
|
||||
required: False
|
||||
default: 'Common'
|
||||
default: Common
|
||||
version_added: 2.5
|
||||
traffic_group:
|
||||
description:
|
||||
|
@ -116,13 +113,10 @@ options:
|
|||
will be used.
|
||||
version_added: 2.5
|
||||
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
|
||||
install netaddr.
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- f5-sdk
|
||||
- netaddr
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
|
@ -193,24 +187,47 @@ state:
|
|||
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:
|
||||
import netaddr
|
||||
HAS_NETADDR = True
|
||||
except ImportError:
|
||||
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):
|
||||
api_map = {
|
||||
|
@ -349,17 +366,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
result = self._filter_params(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):
|
||||
pass
|
||||
|
@ -393,10 +399,11 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.have = None
|
||||
self.want = Parameters(self.client.module.params)
|
||||
self.want = Parameters(client=self.client, params=self.module.params)
|
||||
self.changes = Changes()
|
||||
|
||||
def _set_changed_options(self):
|
||||
|
@ -405,7 +412,7 @@ class ModuleManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = Changes(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
diff = Difference(self.want, self.have)
|
||||
|
@ -421,7 +428,7 @@ class ModuleManager(object):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = Changes(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -467,7 +474,7 @@ class ModuleManager(object):
|
|||
partition=self.want.partition
|
||||
)
|
||||
result = resource.attrs
|
||||
return Parameters(result)
|
||||
return Parameters(params=result)
|
||||
|
||||
def exists(self):
|
||||
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.have.netmask != self.want.netmask:
|
||||
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."
|
||||
)
|
||||
if self.want.address is not None:
|
||||
if self.have.address != self.want.address:
|
||||
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."
|
||||
)
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
@ -509,7 +516,7 @@ class ModuleManager(object):
|
|||
self._set_changed_options()
|
||||
if self.want.traffic_group is None:
|
||||
self.want.update({'traffic_group': '/Common/traffic-group-1'})
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.create_on_device()
|
||||
if self.exists():
|
||||
|
@ -527,7 +534,7 @@ class ModuleManager(object):
|
|||
)
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -545,7 +552,7 @@ class ModuleManager(object):
|
|||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
state=dict(
|
||||
default='present',
|
||||
choices=['present', 'absent', 'disabled', 'enabled']
|
||||
|
@ -577,29 +584,38 @@ class ArgumentSpec(object):
|
|||
use_route_advertisement=dict(
|
||||
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():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
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:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
client.module.fail_json(msg=str(e))
|
||||
cleanup_tokens(client)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -137,14 +137,6 @@ options:
|
|||
- Default Profile which manages the session persistence.
|
||||
- If you want to remove the existing default persistence profile, specify an
|
||||
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:
|
||||
- Virtual server description.
|
||||
|
@ -171,12 +163,9 @@ options:
|
|||
version_added: 2.5
|
||||
notes:
|
||||
- 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
|
||||
install netaddr.
|
||||
requirements:
|
||||
- f5-sdk
|
||||
- netaddr
|
||||
extends_documentation_fragment: f5
|
||||
author:
|
||||
|
@ -381,18 +370,38 @@ metadata:
|
|||
|
||||
import re
|
||||
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Parameters
|
||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
from collections import namedtuple
|
||||
|
||||
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:
|
||||
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:
|
||||
import netaddr
|
||||
|
@ -402,100 +411,6 @@ except ImportError:
|
|||
|
||||
|
||||
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 = {
|
||||
'sourceAddressTranslation': 'snat',
|
||||
'fallbackPersistence': 'fallback_persistence_profile',
|
||||
|
@ -566,12 +481,25 @@ class VirtualServerParameters(Parameters):
|
|||
'vlans_disabled'
|
||||
]
|
||||
|
||||
def __init__(self, params=None):
|
||||
super(VirtualServerParameters, self).__init__(params)
|
||||
self.profiles_mutex = [
|
||||
'sip', 'sipsession', 'iiop', 'rtsp', 'http', 'diameter',
|
||||
'diametersession', 'radius', 'ftp', 'tftp', 'dns', 'pptp', 'fix'
|
||||
]
|
||||
profiles_mutex = [
|
||||
'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):
|
||||
try:
|
||||
|
@ -618,7 +546,7 @@ class VirtualServerParameters(Parameters):
|
|||
return result
|
||||
|
||||
|
||||
class VirtualServerApiParameters(VirtualServerParameters):
|
||||
class ApiParameters(Parameters):
|
||||
@property
|
||||
def destination(self):
|
||||
if self._values['destination'] is None:
|
||||
|
@ -648,7 +576,7 @@ class VirtualServerApiParameters(VirtualServerParameters):
|
|||
if self._values['destination'] is None:
|
||||
result = Destination(ip=None, port=None, route_domain=None)
|
||||
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):
|
||||
result = Destination(
|
||||
|
@ -816,7 +744,7 @@ class VirtualServerApiParameters(VirtualServerParameters):
|
|||
return result
|
||||
|
||||
|
||||
class VirtualServerModuleParameters(VirtualServerParameters):
|
||||
class ModuleParameters(Parameters):
|
||||
def _handle_profile_context(self, tmp):
|
||||
if 'context' not in tmp:
|
||||
tmp['context'] = 'all'
|
||||
|
@ -1106,7 +1034,11 @@ class VirtualServerModuleParameters(VirtualServerParameters):
|
|||
return result
|
||||
|
||||
|
||||
class VirtualServerUsableChanges(VirtualServerParameters):
|
||||
class Changes(Parameters):
|
||||
pass
|
||||
|
||||
|
||||
class UsableChanges(Changes):
|
||||
@property
|
||||
def vlans(self):
|
||||
if self._values['vlans'] is None:
|
||||
|
@ -1118,11 +1050,7 @@ class VirtualServerUsableChanges(VirtualServerParameters):
|
|||
return self._values['vlans']
|
||||
|
||||
|
||||
class VirtualAddressUsableChanges(VirtualAddressParameters):
|
||||
pass
|
||||
|
||||
|
||||
class VirtualServerReportableChanges(VirtualServerParameters):
|
||||
class ReportableChanges(Changes):
|
||||
@property
|
||||
def snat(self):
|
||||
if self._values['snat'] is None:
|
||||
|
@ -1137,13 +1065,13 @@ class VirtualServerReportableChanges(VirtualServerParameters):
|
|||
|
||||
@property
|
||||
def destination(self):
|
||||
params = VirtualServerApiParameters(dict(destination=self._values['destination']))
|
||||
params = ApiParameters(params=dict(destination=self._values['destination']))
|
||||
result = params.destination_tuple.ip
|
||||
return result
|
||||
|
||||
@property
|
||||
def port(self):
|
||||
params = VirtualServerApiParameters(dict(destination=self._values['destination']))
|
||||
params = ApiParameters(params=dict(destination=self._values['destination']))
|
||||
result = params.destination_tuple.port
|
||||
return result
|
||||
|
||||
|
@ -1175,10 +1103,6 @@ class VirtualServerReportableChanges(VirtualServerParameters):
|
|||
return self._values['vlans']
|
||||
|
||||
|
||||
class VirtualAddressReportableChanges(VirtualAddressParameters):
|
||||
pass
|
||||
|
||||
|
||||
class Difference(object):
|
||||
def __init__(self, want, have=None):
|
||||
self.have = have
|
||||
|
@ -1461,49 +1385,12 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
|
||||
def exec_module(self):
|
||||
managers = list()
|
||||
managers.append(self.get_manager('virtual_server'))
|
||||
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 __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.have = ApiParameters()
|
||||
self.want = ModuleParameters(client=self.client, params=self.module.params)
|
||||
self.changes = UsableChanges()
|
||||
|
||||
def exec_module(self):
|
||||
changed = False
|
||||
|
@ -1518,7 +1405,7 @@ class BaseManager(object):
|
|||
except iControlUnexpectedHTTPError as e:
|
||||
raise F5ModuleError(str(e))
|
||||
|
||||
reportable = self.get_reportable_changes()
|
||||
reportable = ReportableChanges(params=self.changes.to_return())
|
||||
changes = reportable.to_return()
|
||||
result.update(**changes)
|
||||
result.update(dict(changed=changed))
|
||||
|
@ -1528,7 +1415,7 @@ class BaseManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -1548,23 +1435,11 @@ class BaseManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
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):
|
||||
result = self._update_changed_options()
|
||||
if result:
|
||||
|
@ -1572,36 +1447,28 @@ class BaseManager(object):
|
|||
return False
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
raise F5ModuleError("Failed to delete the resource")
|
||||
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):
|
||||
result = VirtualServerReportableChanges(self.changes.to_return())
|
||||
result = ReportableChanges(params=self.changes.to_return())
|
||||
return result
|
||||
|
||||
def _set_changed_options(self):
|
||||
changed = {}
|
||||
for key in VirtualServerParameters.returnables:
|
||||
for key in Parameters.returnables:
|
||||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = VirtualServerUsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
diff = Difference(self.want, self.have)
|
||||
updatables = VirtualServerParameters.updatables
|
||||
updatables = Parameters.updatables
|
||||
changed = dict()
|
||||
for k in updatables:
|
||||
change = diff.compare(k)
|
||||
|
@ -1613,7 +1480,7 @@ class VirtualServerManager(BaseManager):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = VirtualServerUsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -1628,6 +1495,11 @@ class VirtualServerManager(BaseManager):
|
|||
required_resources = ['destination', 'port']
|
||||
|
||||
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:
|
||||
raise F5ModuleError(
|
||||
"'destination' must be specified when creating a virtual server"
|
||||
|
@ -1652,7 +1524,10 @@ class VirtualServerManager(BaseManager):
|
|||
raise F5ModuleError(
|
||||
"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):
|
||||
params = self.changes.api_params()
|
||||
|
@ -1674,7 +1549,7 @@ class VirtualServerManager(BaseManager):
|
|||
)
|
||||
params = result.attrs
|
||||
params.update(dict(kind=result.to_dict().get('kind', None)))
|
||||
result = VirtualServerApiParameters(params)
|
||||
result = ApiParameters(params=params)
|
||||
return result
|
||||
|
||||
def create_on_device(self):
|
||||
|
@ -1694,71 +1569,10 @@ class VirtualServerManager(BaseManager):
|
|||
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):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
state=dict(
|
||||
default='present',
|
||||
choices=['present', 'absent', 'disabled', 'enabled']
|
||||
|
@ -1798,54 +1612,45 @@ class ArgumentSpec(object):
|
|||
pool=dict(),
|
||||
description=dict(),
|
||||
snat=dict(),
|
||||
route_advertisement_state=dict(
|
||||
choices=['enabled', 'disabled']
|
||||
),
|
||||
default_persistence_profile=dict(),
|
||||
fallback_persistence_profile=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 = [
|
||||
['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():
|
||||
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()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name,
|
||||
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:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
cleanup_tokens(client)
|
||||
client.module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as ex:
|
||||
cleanup_tokens(client)
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(ex))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -55,13 +55,46 @@ options:
|
|||
- 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
|
||||
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:
|
||||
- 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
|
||||
extends_documentation_fragment: f5
|
||||
requirements:
|
||||
- f5-sdk
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
- Wojciech Wypior (@wojtek0806)
|
||||
|
@ -114,134 +147,92 @@ EXAMPLES = r'''
|
|||
|
||||
RETURN = r'''
|
||||
description:
|
||||
description: The description set on the VLAN
|
||||
returned: changed
|
||||
type: string
|
||||
sample: foo VLAN
|
||||
description: The description set on the VLAN.
|
||||
returned: changed
|
||||
type: string
|
||||
sample: foo VLAN
|
||||
interfaces:
|
||||
description: Interfaces that the VLAN is assigned to
|
||||
returned: changed
|
||||
type: list
|
||||
sample: ['1.1','1.2']
|
||||
name:
|
||||
description: The name of the VLAN
|
||||
returned: changed
|
||||
type: string
|
||||
sample: net1
|
||||
description: Interfaces that the VLAN is assigned to.
|
||||
returned: changed
|
||||
type: list
|
||||
sample: ['1.1','1.2']
|
||||
partition:
|
||||
description: The partition that the VLAN was created on
|
||||
returned: changed
|
||||
type: string
|
||||
sample: Common
|
||||
description: The partition that the VLAN was created on.
|
||||
returned: changed
|
||||
type: string
|
||||
sample: Common
|
||||
tag:
|
||||
description: The ID of the VLAN
|
||||
returned: changed
|
||||
type: int
|
||||
sample: 2345
|
||||
description: The ID of the VLAN.
|
||||
returned: changed
|
||||
type: int
|
||||
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.f5_utils import AnsibleF5Parameters
|
||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
|
||||
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:
|
||||
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):
|
||||
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
|
||||
api_map = {
|
||||
'cmpHash': 'cmp_hash',
|
||||
'dagTunnel': 'dag_tunnel',
|
||||
'dagRoundRobin': 'dag_round_robin'
|
||||
}
|
||||
|
||||
updatables = [
|
||||
'tagged_interfaces', 'untagged_interfaces', 'tag',
|
||||
'description'
|
||||
'description', 'mtu', 'cmp_hash', 'dag_tunnel',
|
||||
'dag_round_robin'
|
||||
]
|
||||
|
||||
returnables = [
|
||||
'description', 'partition', 'name', 'tag', 'interfaces',
|
||||
'tagged_interfaces', 'untagged_interfaces'
|
||||
'description', 'partition', 'tag', 'interfaces',
|
||||
'tagged_interfaces', 'untagged_interfaces', 'mtu',
|
||||
'cmp_hash', 'dag_tunnel', 'dag_round_robin'
|
||||
]
|
||||
|
||||
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):
|
||||
result = {}
|
||||
|
@ -250,26 +241,202 @@ class Parameters(AnsibleF5Parameters):
|
|||
result = self._filter_params(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 = {}
|
||||
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)
|
||||
try:
|
||||
for returnable in self.returnables:
|
||||
result[returnable] = getattr(self, returnable)
|
||||
result = self._filter_params(result)
|
||||
except Exception:
|
||||
pass
|
||||
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
|
||||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.have = None
|
||||
self.want = Parameters()
|
||||
self.want.client = self.client
|
||||
self.want.update(self.client.module.params)
|
||||
self.changes = Parameters()
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = ModuleParameters(params=self.module.params)
|
||||
self.have = ApiParameters()
|
||||
self.changes = UsableChanges()
|
||||
|
||||
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):
|
||||
changed = False
|
||||
|
@ -284,39 +451,20 @@ class ModuleManager(object):
|
|||
except iControlUnexpectedHTTPError as 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(dict(changed=changed))
|
||||
self._announce_deprecations(result)
|
||||
return result
|
||||
|
||||
def _set_changed_options(self):
|
||||
changed = {}
|
||||
for key in Parameters.returnables:
|
||||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
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 _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
||||
def present(self):
|
||||
if self.exists():
|
||||
|
@ -336,18 +484,16 @@ class ModuleManager(object):
|
|||
return False
|
||||
|
||||
def update(self):
|
||||
self.have, ifcs = self.read_current_from_device()
|
||||
if ifcs:
|
||||
self._have_interfaces(ifcs)
|
||||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -355,49 +501,59 @@ class ModuleManager(object):
|
|||
return True
|
||||
|
||||
def create(self):
|
||||
self._set_changed_options()
|
||||
if self.client.check_mode:
|
||||
self.have = ApiParameters()
|
||||
if self.want.mtu is None:
|
||||
self.want.update({'mtu': 1500})
|
||||
self._update_changed_options()
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.create_on_device()
|
||||
return True
|
||||
|
||||
def create_on_device(self):
|
||||
params = self.want.api_params()
|
||||
self.client.api.tm.net.vlans.vlan.create(**params)
|
||||
params = self.changes.api_params()
|
||||
self.client.api.tm.net.vlans.vlan.create(
|
||||
name=self.want.name,
|
||||
partition=self.want.partition,
|
||||
**params
|
||||
)
|
||||
|
||||
def update_on_device(self):
|
||||
params = self.want.api_params()
|
||||
result = self.client.api.tm.net.vlans.vlan.load(
|
||||
name=self.want.name, partition=self.want.partition
|
||||
params = self.changes.api_params()
|
||||
resource = self.client.api.tm.net.vlans.vlan.load(
|
||||
name=self.want.name,
|
||||
partition=self.want.partition
|
||||
)
|
||||
result.modify(**params)
|
||||
resource.modify(**params)
|
||||
|
||||
def exists(self):
|
||||
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):
|
||||
result = self.client.api.tm.net.vlans.vlan.load(
|
||||
name=self.want.name, partition=self.want.partition
|
||||
resource = self.client.api.tm.net.vlans.vlan.load(
|
||||
name=self.want.name,
|
||||
partition=self.want.partition
|
||||
)
|
||||
if result:
|
||||
result.delete()
|
||||
if resource:
|
||||
resource.delete()
|
||||
|
||||
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
|
||||
)
|
||||
ifcs = tmp_res.interfaces_s.get_collection()
|
||||
|
||||
result = tmp_res.attrs
|
||||
return Parameters(result), ifcs
|
||||
interfaces = resource.interfaces_s.get_collection()
|
||||
result = resource.attrs
|
||||
result['interfaces'] = interfaces
|
||||
return ApiParameters(params=result)
|
||||
|
||||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
name=dict(
|
||||
required=True,
|
||||
),
|
||||
|
@ -412,32 +568,56 @@ class ArgumentSpec(object):
|
|||
description=dict(),
|
||||
tag=dict(
|
||||
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():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name,
|
||||
mutually_exclusive=[
|
||||
['tagged_interfaces', 'untagged_interfaces']
|
||||
]
|
||||
mutually_exclusive=spec.mutually_exclusive
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
client.module.exit_json(**results)
|
||||
cleanup_tokens(client)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
client.module.fail_json(msg=str(e))
|
||||
cleanup_tokens(client)
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -40,11 +40,6 @@ options:
|
|||
msg:
|
||||
description:
|
||||
- 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
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
|
@ -84,133 +79,50 @@ import signal
|
|||
import time
|
||||
|
||||
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.f5_utils import F5_COMMON_ARGS
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
|
||||
try:
|
||||
from f5.bigip import ManagementRoot as BigIpMgmt
|
||||
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:
|
||||
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
|
||||
client.module.fail_json(
|
||||
module.fail_json(
|
||||
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):
|
||||
returnables = [
|
||||
'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):
|
||||
result = {}
|
||||
try:
|
||||
|
@ -245,10 +157,11 @@ class Changes(Parameters):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.have = None
|
||||
self.want = Parameters(self.client.module.params)
|
||||
self.want = Parameters(params=self.module.params)
|
||||
self.changes = Parameters()
|
||||
|
||||
def exec_module(self):
|
||||
|
@ -268,7 +181,7 @@ class ModuleManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -276,7 +189,7 @@ class ModuleManager(object):
|
|||
def execute(self):
|
||||
signal.signal(
|
||||
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
|
||||
|
@ -291,8 +204,8 @@ class ModuleManager(object):
|
|||
try:
|
||||
# The first test verifies that the REST API is available; this is done
|
||||
# by repeatedly trying to login to it.
|
||||
connected = self._connect_to_device()
|
||||
if not connected:
|
||||
self.client = F5Client(**self.module.params)
|
||||
if not self.client:
|
||||
continue
|
||||
|
||||
if self._device_is_rebooting():
|
||||
|
@ -333,17 +246,13 @@ class ModuleManager(object):
|
|||
continue
|
||||
else:
|
||||
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
|
||||
)
|
||||
elapsed = datetime.datetime.utcnow() - start
|
||||
self.changes.update({'elapsed': elapsed.seconds})
|
||||
return False
|
||||
|
||||
def _connect_to_device(self):
|
||||
result = self.client.connect()
|
||||
return result
|
||||
|
||||
def _device_is_rebooting(self):
|
||||
output = self.client.api.tm.util.bash.exec_cmd(
|
||||
'run',
|
||||
|
@ -386,45 +295,33 @@ class ModuleManager(object):
|
|||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
timeout=dict(default=7200, type='int'),
|
||||
delay=dict(default=0, type='int'),
|
||||
sleep=dict(default=1, type='int'),
|
||||
msg=dict()
|
||||
)
|
||||
self.f5_product_name = 'bigip'
|
||||
|
||||
|
||||
def cleanup_tokens(client):
|
||||
try:
|
||||
resource = client.api.shared.authz.tokens_s.token.load(
|
||||
name=client.api.icrs.token
|
||||
)
|
||||
resource.delete()
|
||||
except Exception:
|
||||
pass
|
||||
self.argument_spec = {}
|
||||
self.argument_spec.update(f5_argument_spec)
|
||||
self.argument_spec.update(argument_spec)
|
||||
|
||||
|
||||
def main():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5ClientStub(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name,
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
results = mm.exec_module()
|
||||
cleanup_tokens(client)
|
||||
client.module.exit_json(**results)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
cleanup_tokens(client)
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -89,17 +89,37 @@ description:
|
|||
|
||||
import time
|
||||
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Parameters
|
||||
from ansible.module_utils.f5_utils import HAS_F5SDK
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.six import iteritems
|
||||
from collections import defaultdict
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
|
||||
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:
|
||||
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):
|
||||
|
@ -119,36 +139,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
'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):
|
||||
result = {}
|
||||
try:
|
||||
|
@ -159,16 +149,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
pass
|
||||
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):
|
||||
pass
|
||||
|
@ -230,10 +210,10 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.want = ModuleParameters(params=self.client.module.params)
|
||||
self.want.update(dict(client=client))
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = ModuleParameters(client=self.client, params=self.module.params)
|
||||
self.have = ApiParameters()
|
||||
self.changes = UsableChanges()
|
||||
|
||||
|
@ -243,7 +223,7 @@ class ModuleManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = UsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
diff = Difference(self.want, self.have)
|
||||
|
@ -259,7 +239,7 @@ class ModuleManager(object):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = UsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -282,7 +262,7 @@ class ModuleManager(object):
|
|||
except iControlUnexpectedHTTPError as e:
|
||||
raise F5ModuleError(str(e))
|
||||
|
||||
reportable = ReportableChanges(self.changes.to_return())
|
||||
reportable = ReportableChanges(params=self.changes.to_return())
|
||||
changes = reportable.to_return()
|
||||
result.update(**changes)
|
||||
result.update(dict(changed=changed))
|
||||
|
@ -292,7 +272,7 @@ class ModuleManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -316,13 +296,13 @@ class ModuleManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -331,7 +311,7 @@ class ModuleManager(object):
|
|||
|
||||
def create(self):
|
||||
self._set_changed_options()
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
if self.want.accept_eula is False:
|
||||
raise F5ModuleError(
|
||||
|
@ -401,42 +381,48 @@ class ModuleManager(object):
|
|||
if resource is None:
|
||||
return False
|
||||
result = resource.attrs
|
||||
return ApiParameters(result)
|
||||
return ApiParameters(params=result)
|
||||
|
||||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
regkey_pool=dict(required=True),
|
||||
license_key=dict(required=True, no_log=True),
|
||||
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 = [
|
||||
['state', 'present', ['accept_eula']]
|
||||
]
|
||||
|
||||
|
||||
def main():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
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:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
client.module.exit_json(**results)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
if __name__ == '__main__':
|
||||
|
|
|
@ -69,18 +69,37 @@ description:
|
|||
sample: My description
|
||||
'''
|
||||
|
||||
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 collections import defaultdict
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
|
||||
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:
|
||||
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):
|
||||
|
@ -100,36 +119,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
'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):
|
||||
result = {}
|
||||
try:
|
||||
|
@ -140,16 +129,6 @@ class Parameters(AnsibleF5Parameters):
|
|||
pass
|
||||
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):
|
||||
@property
|
||||
|
@ -214,10 +193,10 @@ class Difference(object):
|
|||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, client):
|
||||
self.client = client
|
||||
self.want = ModuleParameters(self.client.module.params)
|
||||
self.want.update({'client': client})
|
||||
def __init__(self, *args, **kwargs):
|
||||
self.module = kwargs.get('module', None)
|
||||
self.client = kwargs.get('client', None)
|
||||
self.want = ModuleParameters(client=self.client, params=self.module.params)
|
||||
self.have = ApiParameters()
|
||||
self.changes = UsableChanges()
|
||||
|
||||
|
@ -227,7 +206,7 @@ class ModuleManager(object):
|
|||
if getattr(self.want, key) is not None:
|
||||
changed[key] = getattr(self.want, key)
|
||||
if changed:
|
||||
self.changes = UsableChanges(changed)
|
||||
self.changes = UsableChanges(params=changed)
|
||||
|
||||
def _update_changed_options(self):
|
||||
diff = Difference(self.want, self.have)
|
||||
|
@ -243,7 +222,7 @@ class ModuleManager(object):
|
|||
else:
|
||||
changed[k] = change
|
||||
if changed:
|
||||
self.changes = Changes(changed)
|
||||
self.changes = Changes(params=changed)
|
||||
return True
|
||||
return False
|
||||
|
||||
|
@ -266,7 +245,7 @@ class ModuleManager(object):
|
|||
except iControlUnexpectedHTTPError as e:
|
||||
raise F5ModuleError(str(e))
|
||||
|
||||
reportable = ReportableChanges(self.changes.to_return())
|
||||
reportable = ReportableChanges(params=self.changes.to_return())
|
||||
changes = reportable.to_return()
|
||||
result.update(**changes)
|
||||
result.update(dict(changed=changed))
|
||||
|
@ -276,7 +255,7 @@ class ModuleManager(object):
|
|||
def _announce_deprecations(self, result):
|
||||
warnings = result.pop('__warnings', [])
|
||||
for warning in warnings:
|
||||
self.client.module.deprecate(
|
||||
self.module.deprecate(
|
||||
msg=warning['msg'],
|
||||
version=warning['version']
|
||||
)
|
||||
|
@ -297,13 +276,13 @@ class ModuleManager(object):
|
|||
self.have = self.read_current_from_device()
|
||||
if not self.should_update():
|
||||
return False
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.update_on_device()
|
||||
return True
|
||||
|
||||
def remove(self):
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.remove_from_device()
|
||||
if self.exists():
|
||||
|
@ -312,7 +291,7 @@ class ModuleManager(object):
|
|||
|
||||
def create(self):
|
||||
self._set_changed_options()
|
||||
if self.client.check_mode:
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
self.create_on_device()
|
||||
return True
|
||||
|
@ -348,13 +327,13 @@ class ModuleManager(object):
|
|||
id=self.want.uuid
|
||||
)
|
||||
result = resource.attrs
|
||||
return ApiParameters(result)
|
||||
return ApiParameters(params=result)
|
||||
|
||||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
self.supports_check_mode = True
|
||||
self.argument_spec = dict(
|
||||
argument_spec = dict(
|
||||
name=dict(required=True),
|
||||
description=dict(),
|
||||
state=dict(
|
||||
|
@ -362,27 +341,28 @@ class ArgumentSpec(object):
|
|||
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():
|
||||
if not HAS_F5SDK:
|
||||
raise F5ModuleError("The python f5-sdk module is required")
|
||||
|
||||
spec = ArgumentSpec()
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=spec.argument_spec,
|
||||
supports_check_mode=spec.supports_check_mode,
|
||||
f5_product_name=spec.f5_product_name
|
||||
supports_check_mode=spec.supports_check_mode
|
||||
)
|
||||
if not HAS_F5SDK:
|
||||
module.fail_json(msg="The python f5-sdk module is required")
|
||||
|
||||
try:
|
||||
mm = ModuleManager(client)
|
||||
client = F5Client(**module.params)
|
||||
mm = ModuleManager(module=module, client=client)
|
||||
results = mm.exec_module()
|
||||
client.module.exit_json(**results)
|
||||
module.exit_json(**results)
|
||||
except F5ModuleError as e:
|
||||
client.module.fail_json(msg=str(e))
|
||||
module.fail_json(msg=str(e))
|
||||
|
||||
|
||||
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/omapi_host.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/ipadm_addrprop.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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_sys_db import Parameters
|
||||
from library.bigip_sys_db import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
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 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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -66,7 +68,7 @@ class TestParameters(unittest.TestCase):
|
|||
server='localhost',
|
||||
user='admin'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.key == 'foo'
|
||||
assert p.value == 'bar'
|
||||
|
||||
|
@ -80,13 +82,11 @@ class TestParameters(unittest.TestCase):
|
|||
user='admin'
|
||||
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.key == 'foo'
|
||||
assert p.value == 'bar'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -118,12 +118,11 @@ class TestManager(unittest.TestCase):
|
|||
)
|
||||
)
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_sys_global import ApiParameters
|
||||
from library.bigip_sys_global import ModuleParameters
|
||||
from library.bigip_sys_global import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
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 ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -71,7 +73,7 @@ class TestParameters(unittest.TestCase):
|
|||
quiet_boot='yes',
|
||||
security_banner='yes',
|
||||
)
|
||||
p = ModuleParameters(args)
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.banner_text == 'this is a banner'
|
||||
assert p.console_timeout == 100
|
||||
assert p.gui_setup == 'enabled'
|
||||
|
@ -83,7 +85,7 @@ class TestParameters(unittest.TestCase):
|
|||
|
||||
def test_api_parameters(self):
|
||||
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 p.console_timeout == 0
|
||||
assert p.gui_setup == 'disabled'
|
||||
|
@ -94,8 +96,6 @@ class TestParameters(unittest.TestCase):
|
|||
assert p.security_banner == 'enabled'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -113,14 +113,13 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_traffic_group import Parameters
|
||||
from library.bigip_traffic_group import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
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 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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -65,12 +66,10 @@ class TestParameters(unittest.TestCase):
|
|||
name='foo'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.name == 'foo'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -84,13 +83,12 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_ucs import Parameters
|
||||
|
@ -27,7 +26,8 @@ try:
|
|||
from library.bigip_ucs import ArgumentSpec
|
||||
from library.bigip_ucs import V1Manager
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
|
@ -36,7 +36,8 @@ except ImportError:
|
|||
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 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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -76,7 +77,7 @@ class TestParameters(unittest.TestCase):
|
|||
state='installed'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.ucs == '/root/bigip.localhost.localdomain.ucs'
|
||||
assert p.force is True
|
||||
assert p.include_chassis_level_config is True
|
||||
|
@ -98,7 +99,7 @@ class TestParameters(unittest.TestCase):
|
|||
reset_trust=False
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.ucs == '/root/bigip.localhost.localdomain.ucs'
|
||||
assert p.include_chassis_level_config 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"
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestV1Manager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -122,17 +121,16 @@ class TestV1Manager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.create_on_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[False, True])
|
||||
|
||||
|
@ -149,17 +147,16 @@ class TestV1Manager(unittest.TestCase):
|
|||
state='present'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.create_on_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[False, True])
|
||||
|
||||
|
@ -176,17 +173,16 @@ class TestV1Manager(unittest.TestCase):
|
|||
state='installed'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.create_on_device = Mock(return_value=True)
|
||||
vm.exists = Mock(return_value=True)
|
||||
vm.install_on_device = Mock(return_value=True)
|
||||
|
@ -204,17 +200,16 @@ class TestV1Manager(unittest.TestCase):
|
|||
state='absent'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.remove_from_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[True, False])
|
||||
|
||||
|
@ -231,17 +226,16 @@ class TestV1Manager(unittest.TestCase):
|
|||
state='absent'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.remove_from_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[True, True])
|
||||
|
||||
|
@ -250,8 +244,6 @@ class TestV1Manager(unittest.TestCase):
|
|||
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):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -265,17 +257,16 @@ class TestV2Manager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V2Manager(client)
|
||||
vm = V2Manager(module=module)
|
||||
vm.create_on_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[False, True])
|
||||
|
||||
|
@ -292,17 +283,16 @@ class TestV2Manager(unittest.TestCase):
|
|||
state='present'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V2Manager(client)
|
||||
vm = V2Manager(module=module)
|
||||
vm.create_on_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[False, True])
|
||||
|
||||
|
@ -319,17 +309,16 @@ class TestV2Manager(unittest.TestCase):
|
|||
state='installed'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V2Manager(client)
|
||||
vm = V2Manager(module=module)
|
||||
vm.create_on_device = Mock(return_value=True)
|
||||
vm.exists = Mock(return_value=True)
|
||||
vm.install_on_device = Mock(return_value=True)
|
||||
|
@ -347,17 +336,16 @@ class TestV2Manager(unittest.TestCase):
|
|||
state='absent'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.remove_from_device = Mock(return_value=True)
|
||||
vm.exists = Mock(side_effect=[True, False])
|
||||
|
||||
|
@ -374,17 +362,16 @@ class TestV2Manager(unittest.TestCase):
|
|||
state='absent'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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)
|
||||
|
||||
vm = V1Manager(client)
|
||||
vm = V1Manager(module=module)
|
||||
vm.remove_from_device = Mock(return_value=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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_user import Parameters
|
||||
|
@ -27,7 +26,8 @@ try:
|
|||
from library.bigip_user import ArgumentSpec
|
||||
from library.bigip_user import UnparitionedManager
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
|
@ -36,7 +36,8 @@ except ImportError:
|
|||
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 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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -74,7 +75,7 @@ class TestParameters(unittest.TestCase):
|
|||
update_password='always'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.username_credential == 'someuser'
|
||||
assert p.password_credential == 'testpass'
|
||||
assert p.full_name == 'Fake Person'
|
||||
|
@ -91,7 +92,7 @@ class TestParameters(unittest.TestCase):
|
|||
shell='none'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.name == 'someuser'
|
||||
assert p.password == 'testpass'
|
||||
assert p.full_name == 'Fake Person'
|
||||
|
@ -99,8 +100,6 @@ class TestParameters(unittest.TestCase):
|
|||
assert p.shell == 'none'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -118,21 +117,21 @@ class TestManager(unittest.TestCase):
|
|||
update_password='on_create'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.create_on_device = Mock(return_value=True)
|
||||
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['partition_access'] == access
|
||||
|
@ -147,21 +146,21 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.create_on_device = Mock(return_value=True)
|
||||
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['partition_access'] == access
|
||||
|
@ -177,26 +176,26 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.create_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"needs to be set to 'on_create' when creating " \
|
||||
"a resource with a password."
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
pm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
def test_create_user_partition_access_raises(self, *args):
|
||||
|
@ -207,25 +206,25 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.create_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"is required when creating a resource."
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
pm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
def test_create_user_shell_bash(self, *args):
|
||||
|
@ -241,21 +240,21 @@ class TestManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.create_on_device = Mock(return_value=True)
|
||||
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['partition_access'] == access
|
||||
|
@ -273,25 +272,25 @@ class TestManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.create_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"'resource-admin' roles"
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
pm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
def test_update_user_password_no_pass(self, *args):
|
||||
|
@ -303,26 +302,26 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.exists = Mock(return_value=True)
|
||||
pm.update_on_device = Mock(return_value=True)
|
||||
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
|
||||
|
||||
|
@ -335,26 +334,26 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.exists = Mock(return_value=True)
|
||||
pm.update_on_device = Mock(return_value=True)
|
||||
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
|
||||
|
||||
|
@ -367,31 +366,31 @@ class TestManager(unittest.TestCase):
|
|||
shell='none'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
shell='tmsh'
|
||||
)
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.exists = Mock(return_value=True)
|
||||
pm.update_on_device = Mock(return_value=True)
|
||||
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['shell'] == 'none'
|
||||
|
@ -405,32 +404,32 @@ class TestManager(unittest.TestCase):
|
|||
shell='none'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
access = [{'name': 'Common', 'role': 'guest'}]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
partition_access=access
|
||||
)
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=False)
|
||||
|
||||
pm = PartitionedManager(client)
|
||||
pm = PartitionedManager(module=module, params=module.params)
|
||||
pm.exists = Mock(return_value=True)
|
||||
pm.update_on_device = Mock(return_value=True)
|
||||
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 not hasattr(results, 'shell')
|
||||
|
@ -444,17 +443,16 @@ class TestManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
access = [{'name': 'all', 'role': 'admin'}]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
shell='tmsh',
|
||||
partition_access=access
|
||||
|
@ -462,15 +460,16 @@ class TestManager(unittest.TestCase):
|
|||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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['shell'] == 'bash'
|
||||
|
@ -484,10 +483,9 @@ class TestManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
|
@ -497,7 +495,7 @@ class TestManager(unittest.TestCase):
|
|||
{'name': 'all', 'role': 'guest'}
|
||||
]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
shell='tmsh',
|
||||
partition_access=access
|
||||
|
@ -505,24 +503,23 @@ class TestManager(unittest.TestCase):
|
|||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"'resource-admin' roles"
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
upm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestLegacyManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -540,21 +537,21 @@ class TestLegacyManager(unittest.TestCase):
|
|||
update_password='on_create'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.create_on_device = Mock(return_value=True)
|
||||
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['partition_access'] == access
|
||||
|
@ -569,21 +566,21 @@ class TestLegacyManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.create_on_device = Mock(return_value=True)
|
||||
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['partition_access'] == access
|
||||
|
@ -599,26 +596,26 @@ class TestLegacyManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.create_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"needs to be set to 'on_create' when creating " \
|
||||
"a resource with a password."
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
upm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
def test_create_user_partition_access_raises(self, *args):
|
||||
|
@ -629,25 +626,25 @@ class TestLegacyManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.create_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"is required when creating a resource."
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
upm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
def test_create_user_shell_bash(self, *args):
|
||||
|
@ -663,21 +660,21 @@ class TestLegacyManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.create_on_device = Mock(return_value=True)
|
||||
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['partition_access'] == access
|
||||
|
@ -695,25 +692,25 @@ class TestLegacyManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.create_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"'resource-admin' roles"
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
upm.exec_module()
|
||||
mm.exec_module()
|
||||
assert str(ex.value) == msg
|
||||
|
||||
def test_update_user_password(self, *args):
|
||||
|
@ -725,32 +722,32 @@ class TestLegacyManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
access = [{'name': 'Common', 'role': 'guest'}]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
shell='tmsh',
|
||||
partition_access=access
|
||||
)
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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
|
||||
|
||||
|
@ -763,31 +760,31 @@ class TestLegacyManager(unittest.TestCase):
|
|||
shell='none'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
shell='tmsh'
|
||||
)
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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['shell'] == 'none'
|
||||
|
@ -801,32 +798,32 @@ class TestLegacyManager(unittest.TestCase):
|
|||
shell='none'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
access = [{'name': 'Common', 'role': 'guest'}]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
partition_access=access
|
||||
)
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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 not hasattr(results, 'shell')
|
||||
|
@ -840,17 +837,16 @@ class TestLegacyManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
access = [{'name': 'all', 'role': 'admin'}]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
shell='tmsh',
|
||||
partition_access=access
|
||||
|
@ -858,15 +854,16 @@ class TestLegacyManager(unittest.TestCase):
|
|||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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['shell'] == 'bash'
|
||||
|
@ -880,10 +877,9 @@ class TestLegacyManager(unittest.TestCase):
|
|||
shell='bash'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
|
@ -893,7 +889,7 @@ class TestLegacyManager(unittest.TestCase):
|
|||
{'name': 'all', 'role': 'guest'}
|
||||
]
|
||||
current = Parameters(
|
||||
dict(
|
||||
params=dict(
|
||||
user='admin',
|
||||
shell='tmsh',
|
||||
partition_access=access
|
||||
|
@ -901,17 +897,18 @@ class TestLegacyManager(unittest.TestCase):
|
|||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm = ModuleManager(client)
|
||||
mm.is_version_less_than_13 = Mock(return_value=True)
|
||||
|
||||
upm = UnparitionedManager(client)
|
||||
upm = UnparitionedManager(module=module, params=module.params)
|
||||
upm.exists = Mock(return_value=True)
|
||||
upm.update_on_device = Mock(return_value=True)
|
||||
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 " \
|
||||
"'resource-admin' roles"
|
||||
|
||||
with pytest.raises(F5ModuleError) as ex:
|
||||
upm.exec_module()
|
||||
mm.exec_module()
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_vcmp_guest import Parameters
|
||||
from library.bigip_vcmp_guest import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
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 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
|
||||
except ImportError:
|
||||
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.mgmt_network == 'bridged'
|
||||
|
||||
|
@ -80,7 +82,7 @@ class TestParameters(unittest.TestCase):
|
|||
mgmt_address='1.2.3.4'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.mgmt_network == 'bridged'
|
||||
assert p.mgmt_address == '1.2.3.4/32'
|
||||
|
||||
|
@ -90,7 +92,7 @@ class TestParameters(unittest.TestCase):
|
|||
mgmt_address='1.2.3.4/24'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.mgmt_network == 'bridged'
|
||||
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'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.mgmt_network == 'bridged'
|
||||
assert p.mgmt_address == '1.2.3.4/24'
|
||||
|
||||
|
@ -109,7 +111,7 @@ class TestParameters(unittest.TestCase):
|
|||
mgmt_route='1.2.3.4'
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.mgmt_route == '1.2.3.4'
|
||||
|
||||
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',
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.initial_image == 'BIGIP-12.1.0.1.0.1447-HF1.iso/1'
|
||||
|
||||
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.mgmt_route == '2.2.2.2'
|
||||
assert p.mgmt_address == '1.1.1.1/24'
|
||||
|
@ -144,8 +146,6 @@ class TestParameters(unittest.TestCase):
|
|||
assert '/Common/vlan2' in p.vlans
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
def setUp(self):
|
||||
self.spec = ArgumentSpec()
|
||||
|
@ -161,14 +161,13 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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.exists = Mock(return_value=False)
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_virtual_address import Parameters
|
||||
from library.bigip_virtual_address import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
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 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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -70,7 +72,7 @@ class TestParameters(unittest.TestCase):
|
|||
advertise_route='always',
|
||||
use_route_advertisement='yes'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.state == 'present'
|
||||
assert p.address == '1.1.1.1'
|
||||
assert p.netmask == '2.2.2.2'
|
||||
|
@ -83,7 +85,7 @@ class TestParameters(unittest.TestCase):
|
|||
|
||||
def test_api_parameters(self):
|
||||
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.address == '1.1.1.1'
|
||||
assert p.arp_state == 'enabled'
|
||||
|
@ -99,56 +101,56 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
advertise_route='when_all_available'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.advertise_route == 'all'
|
||||
|
||||
def test_module_parameters_advertise_route_any(self):
|
||||
args = dict(
|
||||
advertise_route='when_any_available'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.advertise_route == 'any'
|
||||
|
||||
def test_module_parameters_icmp_echo_disabled(self):
|
||||
args = dict(
|
||||
icmp_echo='disabled'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.icmp_echo == 'disabled'
|
||||
|
||||
def test_module_parameters_icmp_echo_selective(self):
|
||||
args = dict(
|
||||
icmp_echo='selective'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.icmp_echo == 'selective'
|
||||
|
||||
def test_module_parameters_auto_delete_disabled(self):
|
||||
args = dict(
|
||||
auto_delete='disabled'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.auto_delete is False
|
||||
|
||||
def test_module_parameters_arp_state_disabled(self):
|
||||
args = dict(
|
||||
arp_state='disabled'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.arp_state == 'disabled'
|
||||
|
||||
def test_module_parameters_use_route_advert_disabled(self):
|
||||
args = dict(
|
||||
use_route_advertisement='no'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.use_route_advertisement == 'disabled'
|
||||
|
||||
def test_module_parameters_state_present(self):
|
||||
args = dict(
|
||||
state='present'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.state == 'present'
|
||||
assert p.enabled == 'yes'
|
||||
|
||||
|
@ -156,14 +158,14 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
state='absent'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.state == 'absent'
|
||||
|
||||
def test_module_parameters_state_enabled(self):
|
||||
args = dict(
|
||||
state='enabled'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.state == 'enabled'
|
||||
assert p.enabled == 'yes'
|
||||
|
||||
|
@ -171,13 +173,11 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
state='disabled'
|
||||
)
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.state == 'disabled'
|
||||
assert p.enabled == 'no'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -199,12 +199,11 @@ class TestManager(unittest.TestCase):
|
|||
user='admin',
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
mm.exists = Mock(side_effect=[False, True])
|
||||
|
@ -222,12 +221,11 @@ class TestManager(unittest.TestCase):
|
|||
user='admin',
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_virtual_server import VirtualAddressParameters
|
||||
from library.bigip_virtual_server import VirtualServerModuleParameters
|
||||
from library.bigip_virtual_server import VirtualServerApiParameters
|
||||
from library.bigip_virtual_server import ModuleParameters
|
||||
from library.bigip_virtual_server import ApiParameters
|
||||
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 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
|
||||
except ImportError:
|
||||
try:
|
||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualAddressParameters
|
||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualServerApiParameters
|
||||
from ansible.modules.network.f5.bigip_virtual_server import VirtualServerModuleParameters
|
||||
from ansible.modules.network.f5.bigip_virtual_server import ApiParameters
|
||||
from ansible.modules.network.f5.bigip_virtual_server import ModuleParameters
|
||||
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.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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -70,14 +66,14 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
destination='1.1.1.1'
|
||||
)
|
||||
p = VirtualServerApiParameters(args)
|
||||
p = ApiParameters(params=args)
|
||||
assert p.destination_tuple.ip == '1.1.1.1'
|
||||
|
||||
def test_destination_mutex_2(self):
|
||||
args = dict(
|
||||
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.route_domain == 2
|
||||
|
||||
|
@ -85,7 +81,7 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
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.port == 80
|
||||
|
||||
|
@ -93,7 +89,7 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
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.port == 80
|
||||
assert p.destination_tuple.route_domain == 2
|
||||
|
@ -102,14 +98,14 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
destination='/Common/1.1.1.1'
|
||||
)
|
||||
p = VirtualServerApiParameters(args)
|
||||
p = ApiParameters(params=args)
|
||||
assert p.destination_tuple.ip == '1.1.1.1'
|
||||
|
||||
def test_api_destination_mutex_6(self):
|
||||
args = dict(
|
||||
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.route_domain == 2
|
||||
|
||||
|
@ -117,7 +113,7 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
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.port == 80
|
||||
|
||||
|
@ -125,7 +121,7 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
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.port == 80
|
||||
assert p.destination_tuple.route_domain == 2
|
||||
|
@ -134,14 +130,14 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
destination='2700:bc00:1f10:101::6'
|
||||
)
|
||||
p = VirtualServerApiParameters(args)
|
||||
p = ApiParameters(params=args)
|
||||
assert p.destination_tuple.ip == '2700:bc00:1f10:101::6'
|
||||
|
||||
def test_destination_mutex_10(self):
|
||||
args = dict(
|
||||
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.route_domain == 2
|
||||
|
||||
|
@ -149,7 +145,7 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
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.port == 80
|
||||
|
||||
|
@ -157,26 +153,11 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
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.port == 80
|
||||
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):
|
||||
args = dict(
|
||||
server='localhost',
|
||||
|
@ -198,7 +179,7 @@ class TestParameters(unittest.TestCase):
|
|||
],
|
||||
enabled_vlans=['vlan2']
|
||||
)
|
||||
p = VirtualServerModuleParameters(args)
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.name == 'my-virtual-server'
|
||||
assert p.partition == 'Common'
|
||||
assert p.port == 443
|
||||
|
@ -235,7 +216,7 @@ class TestParameters(unittest.TestCase):
|
|||
],
|
||||
enabled_vlans=['/Common/vlan2']
|
||||
)
|
||||
p = VirtualServerModuleParameters(args)
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.name == 'my-virtual-server'
|
||||
assert p.partition == 'Common'
|
||||
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.partition == 'Common'
|
||||
assert p.port == 443
|
||||
|
@ -358,8 +339,6 @@ class TestParameters(unittest.TestCase):
|
|||
assert '/Common/net1' in p.vlans
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -388,19 +367,15 @@ class TestManager(unittest.TestCase):
|
|||
validate_certs="no"
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=False)
|
||||
vsm.create_on_device = Mock(return_value=True)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=False)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
|
@ -423,18 +398,14 @@ class TestManager(unittest.TestCase):
|
|||
validate_certs="no"
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=False)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
results = mm.exec_module()
|
||||
|
||||
|
@ -460,26 +431,22 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# remote device
|
||||
current = VirtualServerApiParameters(
|
||||
current = ApiParameters(
|
||||
dict(
|
||||
agent_status_traps='disabled'
|
||||
)
|
||||
)
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=False)
|
||||
vsm.update_on_device = Mock(return_value=True)
|
||||
vsm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=False)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is False
|
||||
|
@ -498,22 +465,18 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=True)
|
||||
vsm.read_current_from_device = Mock(return_value=current)
|
||||
vsm.update_on_device = Mock(return_value=True)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
|
@ -532,21 +495,17 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=True)
|
||||
vsm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is False
|
||||
|
@ -567,21 +526,17 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=True)
|
||||
vsm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
results = mm.exec_module()
|
||||
|
||||
|
@ -603,22 +558,18 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=True)
|
||||
vsm.read_current_from_device = Mock(return_value=current)
|
||||
vsm.update_on_device = Mock(return_value=True)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
|
||||
results = mm.exec_module()
|
||||
|
||||
|
@ -674,22 +625,18 @@ class TestManager(unittest.TestCase):
|
|||
|
||||
# Configure the parameters that would be returned by querying the
|
||||
# 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,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
vsm = VirtualServerManager(client)
|
||||
vsm.exists = Mock(return_value=True)
|
||||
vsm.read_current_from_device = Mock(return_value=current)
|
||||
vsm.update_on_device = Mock(return_value=True)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.get_manager = Mock(return_value=vsm)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
|
||||
results = mm.exec_module()
|
||||
|
||||
|
@ -727,47 +674,3 @@ class TestManager(unittest.TestCase):
|
|||
assert 'context' in results['profiles'][1]
|
||||
assert results['profiles'][1]['name'] == 'clientssl'
|
||||
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 json
|
||||
import pytest
|
||||
import sys
|
||||
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
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 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
|
||||
except ImportError:
|
||||
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 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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -65,13 +67,6 @@ class BigIpObj(object):
|
|||
|
||||
|
||||
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):
|
||||
args = dict(
|
||||
name='somevlan',
|
||||
|
@ -79,9 +74,7 @@ class TestParameters(unittest.TestCase):
|
|||
description='fakevlan',
|
||||
untagged_interfaces=['1.1'],
|
||||
)
|
||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
||||
obj.return_value = self.loaded_ifcs
|
||||
p = Parameters(args)
|
||||
p = ModuleParameters(params=args)
|
||||
|
||||
assert p.name == 'somevlan'
|
||||
assert p.tag == 213
|
||||
|
@ -92,38 +85,20 @@ class TestParameters(unittest.TestCase):
|
|||
args = dict(
|
||||
name='somevlan',
|
||||
description='fakevlan',
|
||||
tag=213,
|
||||
tagged_interfaces=['1.2']
|
||||
tag=213
|
||||
)
|
||||
|
||||
with patch.object(Parameters, '_get_interfaces_from_device') as obj:
|
||||
obj.return_value = self.loaded_ifcs
|
||||
p = Parameters(args)
|
||||
p = ApiParameters(params=args)
|
||||
|
||||
assert p.name == 'somevlan'
|
||||
assert p.tag == 213
|
||||
assert p.interfaces == [{'tagged': True, 'name': '1.2'}]
|
||||
assert p.description == 'fakevlan'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
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):
|
||||
set_module_args(dict(
|
||||
|
@ -135,24 +110,19 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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(module=module)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
assert results['name'] == 'somevlan'
|
||||
assert results['description'] == 'fakevlan'
|
||||
|
||||
def test_create_vlan_tagged_interface(self, *args):
|
||||
|
@ -166,26 +136,21 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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(module=module)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
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['name'] == 'somevlan'
|
||||
|
||||
def test_create_vlan_untagged_interface(self, *args):
|
||||
set_module_args(dict(
|
||||
|
@ -197,25 +162,20 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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(module=module)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
assert results['interfaces'] == [{'untagged': True, 'name': '2.1'}]
|
||||
assert results['name'] == 'somevlan'
|
||||
assert results['untagged_interfaces'] == ['2.1']
|
||||
|
||||
def test_create_vlan_tagged_interfaces(self, *args):
|
||||
set_module_args(dict(
|
||||
|
@ -228,27 +188,21 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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(module=module)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
assert results['interfaces'] == [{'tagged': True, 'name': '2.1'},
|
||||
{'tagged': True, 'name': '1.1'}]
|
||||
assert results['tagged_interfaces'] == ['1.1', '2.1']
|
||||
assert results['tag'] == 213
|
||||
assert results['name'] == 'somevlan'
|
||||
|
||||
def test_create_vlan_untagged_interfaces(self, *args):
|
||||
set_module_args(dict(
|
||||
|
@ -260,26 +214,20 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common',
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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(module=module)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
mm = ModuleManager(client)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=False)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
assert results['interfaces'] == [{'untagged': True, 'name': '2.1'},
|
||||
{'untagged': True, 'name': '1.1'}]
|
||||
assert results['name'] == 'somevlan'
|
||||
assert results['untagged_interfaces'] == ['1.1', '2.1']
|
||||
|
||||
def test_update_vlan_untag_interface(self, *args):
|
||||
set_module_args(dict(
|
||||
|
@ -291,32 +239,26 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common',
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
ifcs = self.loaded_vlan_ifc_untag
|
||||
|
||||
# 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 = ModuleManager(module=module)
|
||||
|
||||
current = (
|
||||
Parameters(
|
||||
load_fixture('load_vlan.json')
|
||||
),
|
||||
ifcs
|
||||
)
|
||||
current = ApiParameters(params=load_fixture('load_vlan.json'))
|
||||
interfaces = load_fixture('load_vlan_interfaces.json')
|
||||
current.update({'interfaces': interfaces})
|
||||
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
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):
|
||||
set_module_args(dict(
|
||||
|
@ -328,32 +270,24 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common',
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
ifcs = self.loaded_vlan_ifc_tag
|
||||
|
||||
# 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 = ModuleManager(module=module)
|
||||
|
||||
current = (
|
||||
Parameters(
|
||||
load_fixture('load_vlan.json')
|
||||
),
|
||||
ifcs
|
||||
)
|
||||
current = ApiParameters(params=load_fixture('load_vlan.json'))
|
||||
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
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):
|
||||
set_module_args(dict(
|
||||
|
@ -365,117 +299,21 @@ class TestManager(unittest.TestCase):
|
|||
partition='Common',
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
ifcs = self.loaded_vlan_ifc_tag
|
||||
|
||||
# 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 = ModuleManager(module=module)
|
||||
|
||||
current = (
|
||||
Parameters(
|
||||
load_fixture('update_vlan_description.json')
|
||||
),
|
||||
ifcs
|
||||
)
|
||||
current = ApiParameters(params=load_fixture('update_vlan_description.json'))
|
||||
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
mm.update_on_device = Mock(return_value=True)
|
||||
mm.exists = Mock(return_value=True)
|
||||
mm.read_current_from_device = Mock(return_value=current)
|
||||
|
||||
results = mm.exec_module()
|
||||
results = mm.exec_module()
|
||||
|
||||
assert results['changed'] is True
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_wait import Parameters
|
||||
from library.bigip_wait import ModuleManager
|
||||
from library.bigip_wait import ArgumentSpec
|
||||
from library.bigip_wait import AnsibleF5ClientStub
|
||||
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
|
||||
except ImportError:
|
||||
try:
|
||||
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 ArgumentSpec
|
||||
from ansible.modules.network.f5.bigip_wait import AnsibleF5ClientStub
|
||||
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
|
||||
except ImportError:
|
||||
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 :-('
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.delay == 3
|
||||
assert p.timeout == 500
|
||||
assert p.sleep == 10
|
||||
|
@ -84,15 +83,13 @@ class TestParameters(unittest.TestCase):
|
|||
msg='We timed out during waiting for BIG-IP :-('
|
||||
)
|
||||
|
||||
p = Parameters(args)
|
||||
p = Parameters(params=args)
|
||||
assert p.delay == 3
|
||||
assert p.timeout == 500
|
||||
assert p.sleep == 10
|
||||
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):
|
||||
def setUp(self):
|
||||
self.spec = ArgumentSpec()
|
||||
|
@ -104,14 +101,13 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5ClientStub(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# 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._device_is_rebooting = 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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigiq_regkey_license import ModuleParameters
|
||||
from library.bigiq_regkey_license import ApiParameters
|
||||
from library.bigiq_regkey_license import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
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 ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -70,7 +71,7 @@ class TestParameters(unittest.TestCase):
|
|||
description='this is a description'
|
||||
)
|
||||
|
||||
p = ModuleParameters(args)
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.regkey_pool == 'foo'
|
||||
assert p.license_key == 'XXXX-XXXX-XXXX-XXXX-XXXX'
|
||||
assert p.accept_eula is True
|
||||
|
@ -79,12 +80,10 @@ class TestParameters(unittest.TestCase):
|
|||
def test_api_parameters(self):
|
||||
args = load_fixture('load_regkey_license_key.json')
|
||||
|
||||
p = ApiParameters(args)
|
||||
p = ApiParameters(params=args)
|
||||
assert p.description == 'foo bar baz'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -101,12 +100,11 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
|
||||
# Override methods to force specific logic in the module to happen
|
||||
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.mock import Mock
|
||||
from ansible.compat.tests.mock import patch
|
||||
from ansible.module_utils.f5_utils import AnsibleF5Client
|
||||
from ansible.module_utils.f5_utils import F5ModuleError
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigiq_regkey_pool import ModuleParameters
|
||||
from library.bigiq_regkey_pool import ApiParameters
|
||||
from library.bigiq_regkey_pool import ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
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 ModuleManager
|
||||
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
|
||||
except ImportError:
|
||||
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
|
||||
|
@ -65,18 +68,16 @@ class TestParameters(unittest.TestCase):
|
|||
description='this is a description'
|
||||
)
|
||||
|
||||
p = ModuleParameters(args)
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.description == 'this is a description'
|
||||
|
||||
def test_api_parameters(self):
|
||||
args = load_fixture('load_regkey_license_pool.json')
|
||||
|
||||
p = ApiParameters(args)
|
||||
p = ApiParameters(params=args)
|
||||
assert p.description == 'this is a description'
|
||||
|
||||
|
||||
@patch('ansible.module_utils.f5_utils.AnsibleF5Client._get_mgmt_root',
|
||||
return_value=True)
|
||||
class TestManager(unittest.TestCase):
|
||||
|
||||
def setUp(self):
|
||||
|
@ -91,14 +92,13 @@ class TestManager(unittest.TestCase):
|
|||
user='admin'
|
||||
))
|
||||
|
||||
client = AnsibleF5Client(
|
||||
module = AnsibleModule(
|
||||
argument_spec=self.spec.argument_spec,
|
||||
supports_check_mode=self.spec.supports_check_mode,
|
||||
f5_product_name=self.spec.f5_product_name
|
||||
supports_check_mode=self.spec.supports_check_mode
|
||||
)
|
||||
|
||||
# Override methods in the specific type of manager
|
||||
mm = ModuleManager(client)
|
||||
mm = ModuleManager(module=module)
|
||||
mm.exists = Mock(return_value=False)
|
||||
mm.create_on_device = Mock(return_value=True)
|
||||
|
||||
|
|
Loading…
Reference in a new issue