Remove f5-sdk usage (#44781)

This patch is part of an ongoing effort to remove the f5-sdk from
the f5 ansible modules for dependency reasons.
This commit is contained in:
Tim Rupp 2018-08-28 12:18:28 -07:00 committed by GitHub
parent edaa0b5245
commit c19a4932eb
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 1020 additions and 691 deletions

View file

@ -998,13 +998,15 @@ def main():
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode, supports_check_mode=spec.supports_check_mode,
) )
client = F5RestClient(**module.params)
try: try:
client = F5RestClient(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client)
exit_json(module, results, client) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client)
fail_json(module, ex, client) fail_json(module, ex, client)

View file

@ -176,31 +176,29 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
try: try:
from library.module_utils.network.f5.bigip import HAS_F5SDK from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import flatten_boolean
from library.module_utils.network.f5.common import exit_json
from library.module_utils.network.f5.common import fail_json
from library.module_utils.network.f5.ipaddress import is_valid_ip from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError: except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import flatten_boolean
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.ipaddress import is_valid_ip from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
@ -208,34 +206,24 @@ class Parameters(AnsibleF5Parameters):
'timeUntilUp': 'time_until_up', 'timeUntilUp': 'time_until_up',
'defaultsFrom': 'parent', 'defaultsFrom': 'parent',
'recv': 'receive', 'recv': 'receive',
'recvDisable': 'receive_disable' 'recvDisable': 'receive_disable',
} }
api_attributes = [ api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send', 'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send',
'destination', 'username', 'password', 'recvDisable', 'description' 'destination', 'username', 'password', 'recvDisable', 'description',
] ]
returnables = [ returnables = [
'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout', 'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout',
'time_until_up', 'receive_disable', 'description' 'time_until_up', 'receive_disable', 'description',
] ]
updatables = [ updatables = [
'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up', 'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up',
'target_username', 'target_password', 'receive_disable', 'description' 'target_username', 'target_password', 'receive_disable', 'description',
] ]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
except Exception:
pass
return result
@property @property
def destination(self): def destination(self):
if self.ip is None and self.port is None: if self.ip is None and self.port is None:
@ -315,7 +303,31 @@ class Parameters(AnsibleF5Parameters):
return self._values['target_password'] return self._values['target_password']
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters): class Changes(Parameters):
def to_return(self):
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):
pass pass
@ -390,9 +402,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = kwargs.get('client', None)
self.have = None self.want = ModuleParameters(params=self.module.params)
self.want = Parameters(params=self.module.params) self.have = ApiParameters()
self.changes = Changes() self.changes = UsableChanges()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
@ -400,7 +412,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -416,49 +428,88 @@ class ModuleManager(object):
else: else:
changed[k] = change changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
def _announce_deprecations(self): def should_update(self):
warnings = [] result = self._update_changed_options()
if self.want: if result:
warnings += self.want._values.get('__warnings', []) return True
if self.have: return False
warnings += self.have._values.get('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def exec_module(self): def exec_module(self):
changed = False changed = False
result = dict() result = dict()
state = self.want.state state = self.want.state
try: if state == "present":
if state == "present": changed = self.present()
changed = self.present() elif state == "absent":
elif state == "absent": changed = self.absent()
changed = self.absent()
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(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations() self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def present(self): def present(self):
if self.exists(): if self.exists():
return self.update() return self.update()
else: else:
return self.create() return self.create()
def exists(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/http/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError:
return False
if resp.status == 404 or 'code' in response and response['code'] == 404:
return False
return True
def update(self):
self.have = self.read_current_from_device()
if not self.should_update():
return False
if self.module.check_mode:
return True
self.update_on_device()
return True
def remove(self):
if self.module.check_mode:
return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the monitor.")
return True
def create(self): def create(self):
self._set_changed_options() self._set_changed_options()
self._set_default_creation_values()
if self.module.check_mode:
return True
self.create_on_device()
return True
def _set_default_creation_values(self):
if self.want.timeout is None: if self.want.timeout is None:
self.want.update({'timeout': 16}) self.want.update({'timeout': 16})
if self.want.interval is None: if self.want.interval is None:
@ -471,77 +522,79 @@ class ModuleManager(object):
self.want.update({'port': '*'}) self.want.update({'port': '*'})
if self.want.send is None: if self.want.send is None:
self.want.update({'send': 'GET /\r\n'}) self.want.update({'send': 'GET /\r\n'})
if self.module.check_mode:
return True
self.create_on_device()
return True
def should_update(self): def create_on_device(self):
result = self._update_changed_options() params = self.changes.api_params()
if result: params['name'] = self.want.name
return True params['partition'] = self.want.partition
return False uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/http/".format(
self.client.provider['server'],
self.client.provider['server_port']
)
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def update(self): if 'code' in response and response['code'] in [400, 403]:
self.have = self.read_current_from_device() if 'message' in response:
if not self.should_update(): raise F5ModuleError(response['message'])
return False else:
if self.module.check_mode: raise F5ModuleError(resp.content)
return True
self.update_on_device() def update_on_device(self):
return True params = self.changes.api_params()
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/http/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def absent(self): def absent(self):
if self.exists(): if self.exists():
return self.remove() return self.remove()
return False return False
def remove(self): def remove_from_device(self):
if self.module.check_mode: uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/http/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.delete(uri)
if resp.status == 200:
return True return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the monitor.")
return True
def read_current_from_device(self): def read_current_from_device(self):
resource = self.client.api.tm.ltm.monitor.https.http.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/http/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
result = resource.attrs resp = self.client.api.get(uri)
return Parameters(params=result) try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def exists(self): if 'code' in response and response['code'] == 400:
result = self.client.api.tm.ltm.monitor.https.http.exists( if 'message' in response:
name=self.want.name, raise F5ModuleError(response['message'])
partition=self.want.partition else:
) raise F5ModuleError(resp.content)
return result return ApiParameters(params=response)
def update_on_device(self):
params = self.want.api_params()
result = self.client.api.tm.ltm.monitor.https.http.load(
name=self.want.name,
partition=self.want.partition
)
result.modify(**params)
def create_on_device(self):
params = self.want.api_params()
self.client.api.tm.ltm.monitor.https.http.create(
name=self.want.name,
partition=self.want.partition,
**params
)
def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.https.http.load(
name=self.want.name,
partition=self.want.partition
)
if result:
result.delete()
class ArgumentSpec(object): class ArgumentSpec(object):
@ -580,20 +633,17 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
) )
if not HAS_F5SDK: client = F5RestClient(**module.params)
module.fail_json(msg="The python f5-sdk module is required")
try: try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
module.exit_json(**results) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
module.fail_json(msg=str(ex)) fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -164,31 +164,31 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
try: try:
from library.module_utils.network.f5.bigip import HAS_F5SDK from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import flatten_boolean
from library.module_utils.network.f5.common import exit_json
from library.module_utils.network.f5.common import fail_json
from library.module_utils.network.f5.ipaddress import is_valid_ip from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError: except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import flatten_boolean
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.ipaddress import is_valid_ip from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
@ -196,34 +196,24 @@ class Parameters(AnsibleF5Parameters):
'timeUntilUp': 'time_until_up', 'timeUntilUp': 'time_until_up',
'defaultsFrom': 'parent', 'defaultsFrom': 'parent',
'recv': 'receive', 'recv': 'receive',
'recvDisable': 'receive_disable' 'recvDisable': 'receive_disable',
} }
api_attributes = [ api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send', 'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send',
'destination', 'username', 'password', 'recvDisable', 'description' 'destination', 'username', 'password', 'recvDisable', 'description',
] ]
returnables = [ returnables = [
'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout', 'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout',
'time_until_up', 'receive_disable', 'description' 'time_until_up', 'receive_disable', 'description',
] ]
updatables = [ updatables = [
'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up', 'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up',
'target_username', 'target_password', 'receive_disable', 'description' 'target_username', 'target_password', 'receive_disable', 'description',
] ]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
return result
except Exception:
return result
@property @property
def username(self): def username(self):
return self._values['target_username'] return self._values['target_username']
@ -302,7 +292,31 @@ class Parameters(AnsibleF5Parameters):
return 'https' return 'https'
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters): class Changes(Parameters):
def to_return(self):
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):
pass pass
@ -377,9 +391,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = kwargs.get('client', None)
self.have = None self.want = ModuleParameters(params=self.module.params)
self.want = Parameters(params=self.module.params) self.have = ApiParameters()
self.changes = Changes() self.changes = UsableChanges()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
@ -387,7 +401,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -398,51 +412,93 @@ class ModuleManager(object):
if change is None: if change is None:
continue continue
else: else:
changed[k] = change if isinstance(change, dict):
changed.update(change)
else:
changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
def _announce_deprecations(self): def should_update(self):
warnings = [] result = self._update_changed_options()
if self.want: if result:
warnings += self.want._values.get('__warnings', []) return True
if self.have: return False
warnings += self.have._values.get('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def exec_module(self): def exec_module(self):
changed = False changed = False
result = dict() result = dict()
state = self.want.state state = self.want.state
try: if state == "present":
if state == "present": changed = self.present()
changed = self.present() elif state == "absent":
elif state == "absent": changed = self.absent()
changed = self.absent()
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(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations() self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def present(self): def present(self):
if self.exists(): if self.exists():
return self.update() return self.update()
else: else:
return self.create() return self.create()
def exists(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/https/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError:
return False
if resp.status == 404 or 'code' in response and response['code'] == 404:
return False
return True
def update(self):
self.have = self.read_current_from_device()
if not self.should_update():
return False
if self.module.check_mode:
return True
self.update_on_device()
return True
def remove(self):
if self.module.check_mode:
return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the resource.")
return True
def create(self): def create(self):
self._set_changed_options() self._set_changed_options()
self._set_default_creation_values()
if self.module.check_mode:
return True
self.create_on_device()
return True
def _set_default_creation_values(self):
if self.want.timeout is None: if self.want.timeout is None:
self.want.update({'timeout': 16}) self.want.update({'timeout': 16})
if self.want.interval is None: if self.want.interval is None:
@ -455,77 +511,79 @@ class ModuleManager(object):
self.want.update({'port': '*'}) self.want.update({'port': '*'})
if self.want.send is None: if self.want.send is None:
self.want.update({'send': 'GET /\r\n'}) self.want.update({'send': 'GET /\r\n'})
if self.module.check_mode:
return True
self.create_on_device()
return True
def should_update(self): def create_on_device(self):
result = self._update_changed_options() params = self.changes.api_params()
if result: params['name'] = self.want.name
return True params['partition'] = self.want.partition
return False uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/https/".format(
self.client.provider['server'],
self.client.provider['server_port']
)
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def update(self): if 'code' in response and response['code'] in [400, 403]:
self.have = self.read_current_from_device() if 'message' in response:
if not self.should_update(): raise F5ModuleError(response['message'])
return False else:
if self.module.check_mode: raise F5ModuleError(resp.content)
return True
self.update_on_device() def update_on_device(self):
return True params = self.changes.api_params()
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/https/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def absent(self): def absent(self):
if self.exists(): if self.exists():
return self.remove() return self.remove()
return False return False
def remove(self): def remove_from_device(self):
if self.module.check_mode: uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/https/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.delete(uri)
if resp.status == 200:
return True return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the monitor.")
return True
def read_current_from_device(self): def read_current_from_device(self):
resource = self.client.api.tm.ltm.monitor.https_s.https.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/https/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
result = resource.attrs resp = self.client.api.get(uri)
return Parameters(params=result) try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def exists(self): if 'code' in response and response['code'] == 400:
result = self.client.api.tm.ltm.monitor.https_s.https.exists( if 'message' in response:
name=self.want.name, raise F5ModuleError(response['message'])
partition=self.want.partition else:
) raise F5ModuleError(resp.content)
return result return ApiParameters(params=response)
def update_on_device(self):
params = self.want.api_params()
result = self.client.api.tm.ltm.monitor.https_s.https.load(
name=self.want.name,
partition=self.want.partition
)
result.modify(**params)
def create_on_device(self):
params = self.want.api_params()
self.client.api.tm.ltm.monitor.https_s.https.create(
name=self.want.name,
partition=self.want.partition,
**params
)
def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.https_s.https.load(
name=self.want.name,
partition=self.want.partition
)
if result:
result.delete()
class ArgumentSpec(object): class ArgumentSpec(object):
@ -564,20 +622,18 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
) )
if not HAS_F5SDK: client = F5RestClient(**module.params)
module.fail_json(msg="The python f5-sdk module is required")
try: try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
module.exit_json(**results) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
module.fail_json(msg=str(ex)) fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -229,29 +229,28 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
try: try:
from library.module_utils.network.f5.bigip import HAS_F5SDK from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
try: from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import flatten_boolean
except ImportError: from library.module_utils.network.f5.common import exit_json
HAS_F5SDK = False from library.module_utils.network.f5.common import fail_json
except ImportError: except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
try: from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import flatten_boolean
except ImportError: from ansible.module_utils.network.f5.common import exit_json
HAS_F5SDK = False from ansible.module_utils.network.f5.common import fail_json
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
@ -264,37 +263,27 @@ class Parameters(AnsibleF5Parameters):
'memoryCoefficient': 'memory_coefficient', 'memoryCoefficient': 'memory_coefficient',
'memoryThreshold': 'memory_threshold', 'memoryThreshold': 'memory_threshold',
'diskCoefficient': 'disk_coefficient', 'diskCoefficient': 'disk_coefficient',
'diskThreshold': 'disk_threshold' 'diskThreshold': 'disk_threshold',
} }
api_attributes = [ api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'destination', 'community', 'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'destination', 'community',
'version', 'agentType', 'cpuCoefficient', 'cpuThreshold', 'memoryCoefficient', 'version', 'agentType', 'cpuCoefficient', 'cpuThreshold', 'memoryCoefficient',
'memoryThreshold', 'diskCoefficient', 'diskThreshold', 'description' 'memoryThreshold', 'diskCoefficient', 'diskThreshold', 'description',
] ]
returnables = [ returnables = [
'parent', 'ip', 'interval', 'timeout', 'time_until_up', 'description', 'community', 'parent', 'ip', 'interval', 'timeout', 'time_until_up', 'description', 'community',
'version', 'agent_type', 'cpu_coefficient', 'cpu_threshold', 'memory_coefficient', 'version', 'agent_type', 'cpu_coefficient', 'cpu_threshold', 'memory_coefficient',
'memory_threshold', 'disk_coefficient', 'disk_threshold' 'memory_threshold', 'disk_coefficient', 'disk_threshold',
] ]
updatables = [ updatables = [
'ip', 'interval', 'timeout', 'time_until_up', 'description', 'community', 'ip', 'interval', 'timeout', 'time_until_up', 'description', 'community',
'version', 'agent_type', 'cpu_coefficient', 'cpu_threshold', 'memory_coefficient', 'version', 'agent_type', 'cpu_coefficient', 'cpu_threshold', 'memory_coefficient',
'memory_threshold', 'disk_coefficient', 'disk_threshold' 'memory_threshold', 'disk_coefficient', 'disk_threshold',
] ]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
return result
except Exception:
return result
@property @property
def interval(self): def interval(self):
if self._values['interval'] is None: if self._values['interval'] is None:
@ -370,7 +359,31 @@ class Parameters(AnsibleF5Parameters):
return 'snmp_dca' return 'snmp_dca'
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters): class Changes(Parameters):
def to_return(self):
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):
pass pass
@ -428,9 +441,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = kwargs.get('client', None)
self.have = None self.want = ModuleParameters(params=self.module.params)
self.want = Parameters(params=self.module.params) self.have = ApiParameters()
self.changes = Changes() self.changes = UsableChanges()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
@ -438,7 +451,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -449,52 +462,93 @@ class ModuleManager(object):
if change is None: if change is None:
continue continue
else: else:
changed[k] = change if isinstance(change, dict):
changed.update(change)
else:
changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
def _announce_deprecations(self): def should_update(self):
warnings = [] result = self._update_changed_options()
if self.want: if result:
warnings += self.want._values.get('__warnings', []) return True
if self.have: return False
warnings += self.have._values.get('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def exec_module(self): def exec_module(self):
changed = False changed = False
result = dict() result = dict()
state = self.want.state state = self.want.state
try: if state == "present":
if state == "present": changed = self.present()
changed = self.present() elif state == "absent":
elif state == "absent": changed = self.absent()
changed = self.absent()
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(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations() self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def present(self): def present(self):
if self.exists(): if self.exists():
return self.update() return self.update()
else: else:
return self.create() return self.create()
def exists(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/snmp-dca/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError:
return False
if resp.status == 404 or 'code' in response and response['code'] == 404:
return False
return True
def update(self):
self.have = self.read_current_from_device()
if not self.should_update():
return False
if self.module.check_mode:
return True
self.update_on_device()
return True
def remove(self):
if self.module.check_mode:
return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the resource.")
return True
def create(self): def create(self):
self._set_changed_options() self._set_changed_options()
self._set_default_creation_values()
if self.module.check_mode:
return True
self.create_on_device()
return True
def _set_default_creation_values(self):
if self.want.timeout is None: if self.want.timeout is None:
self.want.update({'timeout': 30}) self.want.update({'timeout': 30})
if self.want.interval is None: if self.want.interval is None:
@ -520,77 +574,78 @@ class ModuleManager(object):
if self.want.disk_threshold is None: if self.want.disk_threshold is None:
self.want.update({'disk_threshold': '90'}) self.want.update({'disk_threshold': '90'})
if self.module.check_mode: def create_on_device(self):
return True params = self.changes.api_params()
self.create_on_device() params['name'] = self.want.name
return True params['partition'] = self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/snmp-dca/".format(
self.client.provider['server'],
self.client.provider['server_port']
)
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def should_update(self): if 'code' in response and response['code'] in [400, 403]:
result = self._update_changed_options() if 'message' in response:
if result: raise F5ModuleError(response['message'])
return True else:
return False raise F5ModuleError(resp.content)
def update(self): def update_on_device(self):
self.have = self.read_current_from_device() params = self.changes.api_params()
if not self.should_update(): uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/snmp-dca/{2}".format(
return False self.client.provider['server'],
if self.module.check_mode: self.client.provider['server_port'],
return True transform_name(self.want.partition, self.want.name)
self.update_on_device() )
return True resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def absent(self): def absent(self):
if self.exists(): if self.exists():
return self.remove() return self.remove()
return False return False
def remove(self): def remove_from_device(self):
if self.module.check_mode: uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/snmp-dca/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.delete(uri)
if resp.status == 200:
return True return True
self.remove_from_device()
if self.exists():
raise F5ModuleError("Failed to delete the monitor.")
return True
def read_current_from_device(self): def read_current_from_device(self):
resource = self.client.api.tm.ltm.monitor.snmp_dcas.snmp_dca.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/snmp-dca/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
result = resource.attrs resp = self.client.api.get(uri)
return Parameters(params=result) try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def exists(self): if 'code' in response and response['code'] == 400:
result = self.client.api.tm.ltm.monitor.snmp_dcas.snmp_dca.exists( if 'message' in response:
name=self.want.name, raise F5ModuleError(response['message'])
partition=self.want.partition else:
) raise F5ModuleError(resp.content)
return result return ApiParameters(params=response)
def update_on_device(self):
params = self.want.api_params()
result = self.client.api.tm.ltm.monitor.snmp_dcas.snmp_dca.load(
name=self.want.name,
partition=self.want.partition
)
result.modify(**params)
def create_on_device(self):
params = self.want.api_params()
self.client.api.tm.ltm.monitor.snmp_dcas.snmp_dca.create(
name=self.want.name,
partition=self.want.partition,
**params
)
def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.snmp_dcas.snmp_dca.load(
name=self.want.name,
partition=self.want.partition
)
if result:
result.delete()
class ArgumentSpec(object): class ArgumentSpec(object):
@ -633,20 +688,19 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required") client = F5RestClient(**module.params)
try: try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
module.exit_json(**results) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
module.fail_json(msg=str(ex)) fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -172,75 +172,54 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
try: try:
from library.module_utils.network.f5.bigip import HAS_F5SDK from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import flatten_boolean
from library.module_utils.network.f5.common import exit_json
from library.module_utils.network.f5.common import fail_json
from library.module_utils.network.f5.ipaddress import is_valid_ip from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError: except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import flatten_boolean
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.ipaddress import is_valid_ip from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
api_map = { api_map = {
'timeUntilUp': 'time_until_up', 'timeUntilUp': 'time_until_up',
'defaultsFrom': 'parent', 'defaultsFrom': 'parent',
'recv': 'receive' 'recv': 'receive',
} }
api_attributes = [ api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send', 'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'recv', 'send',
'destination', 'description' 'destination', 'description',
] ]
returnables = [ returnables = [
'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout', 'parent', 'send', 'receive', 'ip', 'port', 'interval', 'timeout',
'time_until_up', 'description' 'time_until_up', 'description',
] ]
updatables = [ updatables = [
'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up', 'destination', 'send', 'receive', 'interval', 'timeout', 'time_until_up',
'description' 'description',
] ]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
return result
except Exception:
return result
def api_params(self):
result = {}
for api_attribute in self.api_attributes:
if self.api_map is not None and api_attribute in self.api_map:
result[api_attribute] = getattr(self, self.api_map[api_attribute])
else:
result[api_attribute] = getattr(self, api_attribute)
result = self._filter_params(result)
return result
@property @property
def interval(self): def interval(self):
if self._values['interval'] is None: if self._values['interval'] is None:
@ -309,7 +288,31 @@ class Parameters(AnsibleF5Parameters):
return 'tcp' return 'tcp'
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters): class Changes(Parameters):
def to_return(self):
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):
pass pass
@ -384,9 +387,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = kwargs.get('client', None)
self.have = None self.want = ModuleParameters(params=self.module.params)
self.want = Parameters(params=self.module.params) self.have = ApiParameters()
self.changes = Changes() self.changes = UsableChanges()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
@ -394,7 +397,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -405,63 +408,67 @@ class ModuleManager(object):
if change is None: if change is None:
continue continue
else: else:
changed[k] = change if isinstance(change, dict):
changed.update(change)
else:
changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
def _announce_deprecations(self): def should_update(self):
warnings = [] result = self._update_changed_options()
if self.want: if result:
warnings += self.want._values.get('__warnings', []) return True
if self.have: return False
warnings += self.have._values.get('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def exec_module(self): def exec_module(self):
changed = False changed = False
result = dict() result = dict()
state = self.want.state state = self.want.state
try: if state == "present":
if state == "present": changed = self.present()
changed = self.present() elif state == "absent":
elif state == "absent": changed = self.absent()
changed = self.absent()
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(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations() self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def present(self): def present(self):
if self.exists(): if self.exists():
return self.update() return self.update()
else: else:
return self.create() return self.create()
def create(self): def exists(self):
self._set_changed_options() uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp/{2}".format(
self._set_default_creation_values() self.client.provider['server'],
if self.module.check_mode: self.client.provider['server_port'],
return True transform_name(self.want.partition, self.want.name)
self.create_on_device() )
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError:
return False
if resp.status == 404 or 'code' in response and response['code'] == 404:
return False
return True return True
def should_update(self):
result = self._update_changed_options()
if result:
return True
return False
def update(self): def update(self):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
@ -471,9 +478,10 @@ class ModuleManager(object):
self.update_on_device() self.update_on_device()
return True return True
def absent(self): def should_update(self):
if self.exists(): result = self._update_changed_options()
return self.remove() if result:
return True
return False return False
def remove(self): def remove(self):
@ -481,7 +489,15 @@ class ModuleManager(object):
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
raise F5ModuleError("Failed to delete the monitor.") raise F5ModuleError("Failed to delete the resource.")
return True
def create(self):
self._set_changed_options()
self._set_default_creation_values()
if self.module.check_mode:
return True
self.create_on_device()
return True return True
def _set_default_creation_values(self): def _set_default_creation_values(self):
@ -496,44 +512,78 @@ class ModuleManager(object):
if self.want.port is None: if self.want.port is None:
self.want.update({'port': '*'}) self.want.update({'port': '*'})
def read_current_from_device(self): def create_on_device(self):
resource = self.client.api.tm.ltm.monitor.tcps.tcp.load( params = self.changes.api_params()
name=self.want.name, params['name'] = self.want.name
partition=self.want.partition params['partition'] = self.want.partition
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp/".format(
self.client.provider['server'],
self.client.provider['server_port']
) )
result = resource.attrs resp = self.client.api.post(uri, json=params)
return Parameters(params=result) try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def exists(self): if 'code' in response and response['code'] in [400, 403]:
result = self.client.api.tm.ltm.monitor.tcps.tcp.exists( if 'message' in response:
name=self.want.name, raise F5ModuleError(response['message'])
partition=self.want.partition else:
) raise F5ModuleError(resp.content)
return result
def update_on_device(self): def update_on_device(self):
params = self.changes.api_params() params = self.changes.api_params()
result = self.client.api.tm.ltm.monitor.tcps.tcp.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
result.modify(**params) resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
def create_on_device(self): if 'code' in response and response['code'] == 400:
params = self.want.api_params() if 'message' in response:
self.client.api.tm.ltm.monitor.tcps.tcp.create( raise F5ModuleError(response['message'])
name=self.want.name, else:
partition=self.want.partition, raise F5ModuleError(resp.content)
**params
) def absent(self):
if self.exists():
return self.remove()
return False
def remove_from_device(self): def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.tcps.tcp.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
if result: resp = self.client.api.delete(uri)
result.delete() if resp.status == 200:
return True
def read_current_from_device(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
return ApiParameters(params=response)
class ArgumentSpec(object): class ArgumentSpec(object):
@ -569,20 +619,19 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required") client = F5RestClient(**module.params)
try: try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
module.exit_json(**results) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
module.fail_json(msg=str(ex)) fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -144,60 +144,50 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
try: try:
from library.module_utils.network.f5.bigip import HAS_F5SDK from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import flatten_boolean
from library.module_utils.network.f5.common import exit_json
from library.module_utils.network.f5.common import fail_json
from library.module_utils.network.f5.ipaddress import is_valid_ip from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError: except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import flatten_boolean
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.ipaddress import is_valid_ip from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
api_map = { api_map = {
'timeUntilUp': 'time_until_up', 'timeUntilUp': 'time_until_up',
'defaultsFrom': 'parent' 'defaultsFrom': 'parent',
} }
api_attributes = [ api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'destination', 'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'destination',
'description' 'description',
] ]
returnables = [ returnables = [
'parent', 'ip', 'interval', 'timeout', 'time_until_up', 'description' 'parent', 'ip', 'interval', 'timeout', 'time_until_up', 'description',
] ]
updatables = [ updatables = [
'ip', 'interval', 'timeout', 'time_until_up', 'description' 'ip', 'interval', 'timeout', 'time_until_up', 'description',
] ]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
return result
except Exception:
return result
@property @property
def interval(self): def interval(self):
if self._values['interval'] is None: if self._values['interval'] is None:
@ -257,7 +247,31 @@ class Parameters(AnsibleF5Parameters):
return 'tcp_echo' return 'tcp_echo'
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters): class Changes(Parameters):
def to_return(self):
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):
pass pass
@ -322,9 +336,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = kwargs.get('client', None)
self.have = None self.want = ModuleParameters(params=self.module.params)
self.want = Parameters(params=self.module.params) self.have = ApiParameters()
self.changes = Changes() self.changes = UsableChanges()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
@ -332,7 +346,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -343,70 +357,67 @@ class ModuleManager(object):
if change is None: if change is None:
continue continue
else: else:
changed[k] = change if isinstance(change, dict):
changed.update(change)
else:
changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
def _announce_deprecations(self): def should_update(self):
warnings = [] result = self._update_changed_options()
if self.want: if result:
warnings += self.want._values.get('__warnings', []) return True
if self.have: return False
warnings += self.have._values.get('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def exec_module(self): def exec_module(self):
changed = False changed = False
result = dict() result = dict()
state = self.want.state state = self.want.state
try: if state == "present":
if state == "present": changed = self.present()
changed = self.present() elif state == "absent":
elif state == "absent": changed = self.absent()
changed = self.absent()
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(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations() self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def present(self): def present(self):
if self.exists(): if self.exists():
return self.update() return self.update()
else: else:
return self.create() return self.create()
def create(self): def exists(self):
self._set_changed_options() uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-echo/{2}".format(
if self.want.timeout is None: self.client.provider['server'],
self.want.update({'timeout': 16}) self.client.provider['server_port'],
if self.want.interval is None: transform_name(self.want.partition, self.want.name)
self.want.update({'interval': 5}) )
if self.want.time_until_up is None: resp = self.client.api.get(uri)
self.want.update({'time_until_up': 0}) try:
if self.want.ip is None: response = resp.json()
self.want.update({'ip': '*'}) except ValueError:
if self.module.check_mode: return False
return True if resp.status == 404 or 'code' in response and response['code'] == 404:
self.create_on_device() return False
return True return True
def should_update(self):
result = self._update_changed_options()
if result:
return True
return False
def update(self): def update(self):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
@ -416,57 +427,104 @@ class ModuleManager(object):
self.update_on_device() self.update_on_device()
return True return True
def absent(self):
if self.exists():
return self.remove()
return False
def remove(self): def remove(self):
if self.module.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
raise F5ModuleError("Failed to delete the monitor.") raise F5ModuleError("Failed to delete the resource.")
return True return True
def read_current_from_device(self): def create(self):
resource = self.client.api.tm.ltm.monitor.tcp_echos.tcp_echo.load( self._set_changed_options()
name=self.want.name, self._set_default_creation_values()
partition=self.want.partition if self.module.check_mode:
) return True
result = resource.attrs self.create_on_device()
return Parameters(params=result) return True
def exists(self): def _set_default_creation_values(self):
result = self.client.api.tm.ltm.monitor.tcp_echos.tcp_echo.exists( if self.want.timeout is None:
name=self.want.name, self.want.update({'timeout': 16})
partition=self.want.partition if self.want.interval is None:
) self.want.update({'interval': 5})
return result if self.want.time_until_up is None:
self.want.update({'time_until_up': 0})
def update_on_device(self): if self.want.ip is None:
params = self.want.api_params() self.want.update({'ip': '*'})
result = self.client.api.tm.ltm.monitor.tcp_echos.tcp_echo.load(
name=self.want.name,
partition=self.want.partition
)
result.modify(**params)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.changes.api_params()
self.client.api.tm.ltm.monitor.tcp_echos.tcp_echo.create( params['name'] = self.want.name
name=self.want.name, params['partition'] = self.want.partition
partition=self.want.partition, uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-echo/".format(
**params self.client.provider['server'],
self.client.provider['server_port']
) )
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] in [400, 403]:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def update_on_device(self):
params = self.changes.api_params()
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-echo/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def absent(self):
if self.exists():
return self.remove()
return False
def remove_from_device(self): def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.tcp_echos.tcp_echo.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-echo/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
if result: resp = self.client.api.delete(uri)
result.delete() if resp.status == 200:
return True
def read_current_from_device(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-echo/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
return ApiParameters(params=response)
class ArgumentSpec(object): class ArgumentSpec(object):
@ -499,20 +557,18 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
) )
if not HAS_F5SDK: client = F5RestClient(**module.params)
module.fail_json(msg="The python f5-sdk module is required")
try: try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
module.exit_json(**results) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
module.fail_json(msg=str(ex)) fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -159,63 +159,54 @@ import os
from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback from ansible.module_utils.basic import env_fallback
try: try:
from library.module_utils.network.f5.bigip import HAS_F5SDK from library.module_utils.network.f5.bigip import F5RestClient
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.common import F5ModuleError from library.module_utils.network.f5.common import F5ModuleError
from library.module_utils.network.f5.common import AnsibleF5Parameters from library.module_utils.network.f5.common import AnsibleF5Parameters
from library.module_utils.network.f5.common import cleanup_tokens from library.module_utils.network.f5.common import cleanup_tokens
from library.module_utils.network.f5.common import fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.network.f5.common import transform_name
from library.module_utils.network.f5.common import flatten_boolean
from library.module_utils.network.f5.common import exit_json
from library.module_utils.network.f5.common import fail_json
from library.module_utils.network.f5.ipaddress import is_valid_ip from library.module_utils.network.f5.ipaddress import is_valid_ip
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
except ImportError: except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK from ansible.module_utils.network.f5.bigip import F5RestClient
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.common import F5ModuleError from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import AnsibleF5Parameters from ansible.module_utils.network.f5.common import AnsibleF5Parameters
from ansible.module_utils.network.f5.common import cleanup_tokens from ansible.module_utils.network.f5.common import cleanup_tokens
from ansible.module_utils.network.f5.common import fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.network.f5.common import transform_name
from ansible.module_utils.network.f5.common import flatten_boolean
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json
from ansible.module_utils.network.f5.ipaddress import is_valid_ip from ansible.module_utils.network.f5.ipaddress import is_valid_ip
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
api_map = { api_map = {
'timeUntilUp': 'time_until_up', 'timeUntilUp': 'time_until_up',
'defaultsFrom': 'parent', 'defaultsFrom': 'parent',
'recv': 'receive' 'recv': 'receive',
} }
api_attributes = [ api_attributes = [
'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'destination', 'timeUntilUp', 'defaultsFrom', 'interval', 'timeout', 'destination',
'description' 'description',
] ]
returnables = [ returnables = [
'parent', 'ip', 'port', 'interval', 'timeout', 'time_until_up', 'parent', 'ip', 'port', 'interval', 'timeout', 'time_until_up',
'description' 'description',
] ]
updatables = [ updatables = [
'destination', 'interval', 'timeout', 'time_until_up', 'description' 'destination', 'interval', 'timeout', 'time_until_up', 'description',
] ]
def to_return(self):
result = {}
try:
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
return result
except Exception:
return result
@property @property
def destination(self): def destination(self):
if self.ip is None and self.port is None: if self.ip is None and self.port is None:
@ -290,7 +281,31 @@ class Parameters(AnsibleF5Parameters):
return 'tcp_half_open' return 'tcp_half_open'
class ApiParameters(Parameters):
pass
class ModuleParameters(Parameters):
pass
class Changes(Parameters): class Changes(Parameters):
def to_return(self):
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):
pass pass
@ -365,9 +380,9 @@ class ModuleManager(object):
def __init__(self, *args, **kwargs): def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None) self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None) self.client = kwargs.get('client', None)
self.have = None self.want = ModuleParameters(params=self.module.params)
self.want = Parameters(params=self.module.params) self.have = ApiParameters()
self.changes = Changes() self.changes = UsableChanges()
def _set_changed_options(self): def _set_changed_options(self):
changed = {} changed = {}
@ -375,7 +390,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None: if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key) changed[key] = getattr(self.want, key)
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
def _update_changed_options(self): def _update_changed_options(self):
diff = Difference(self.want, self.have) diff = Difference(self.want, self.have)
@ -386,72 +401,67 @@ class ModuleManager(object):
if change is None: if change is None:
continue continue
else: else:
changed[k] = change if isinstance(change, dict):
changed.update(change)
else:
changed[k] = change
if changed: if changed:
self.changes = Changes(params=changed) self.changes = UsableChanges(params=changed)
return True return True
return False return False
def _announce_deprecations(self): def should_update(self):
warnings = [] result = self._update_changed_options()
if self.want: if result:
warnings += self.want._values.get('__warnings', []) return True
if self.have: return False
warnings += self.have._values.get('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def exec_module(self): def exec_module(self):
changed = False changed = False
result = dict() result = dict()
state = self.want.state state = self.want.state
try: if state == "present":
if state == "present": changed = self.present()
changed = self.present() elif state == "absent":
elif state == "absent": changed = self.absent()
changed = self.absent()
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(**changes)
result.update(dict(changed=changed)) result.update(dict(changed=changed))
self._announce_deprecations() self._announce_deprecations(result)
return result return result
def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.client.module.deprecate(
msg=warning['msg'],
version=warning['version']
)
def present(self): def present(self):
if self.exists(): if self.exists():
return self.update() return self.update()
else: else:
return self.create() return self.create()
def create(self): def exists(self):
self._set_changed_options() uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-half-open/{2}".format(
if self.want.timeout is None: self.client.provider['server'],
self.want.update({'timeout': 16}) self.client.provider['server_port'],
if self.want.interval is None: transform_name(self.want.partition, self.want.name)
self.want.update({'interval': 5}) )
if self.want.time_until_up is None: resp = self.client.api.get(uri)
self.want.update({'time_until_up': 0}) try:
if self.want.ip is None: response = resp.json()
self.want.update({'ip': '*'}) except ValueError:
if self.want.port is None: return False
self.want.update({'port': '*'}) if resp.status == 404 or 'code' in response and response['code'] == 404:
if self.module.check_mode: return False
return True
self.create_on_device()
return True return True
def should_update(self):
result = self._update_changed_options()
if result:
return True
return False
def update(self): def update(self):
self.have = self.read_current_from_device() self.have = self.read_current_from_device()
if not self.should_update(): if not self.should_update():
@ -461,57 +471,106 @@ class ModuleManager(object):
self.update_on_device() self.update_on_device()
return True return True
def absent(self):
if self.exists():
return self.remove()
return False
def remove(self): def remove(self):
if self.module.check_mode: if self.module.check_mode:
return True return True
self.remove_from_device() self.remove_from_device()
if self.exists(): if self.exists():
raise F5ModuleError("Failed to delete the monitor.") raise F5ModuleError("Failed to delete the resource.")
return True return True
def read_current_from_device(self): def create(self):
resource = self.client.api.tm.ltm.monitor.tcp_half_opens.tcp_half_open.load( self._set_changed_options()
name=self.want.name, self._set_default_creation_values()
partition=self.want.partition if self.module.check_mode:
) return True
result = resource.attrs self.create_on_device()
return Parameters(params=result) return True
def exists(self): def _set_default_creation_values(self):
result = self.client.api.tm.ltm.monitor.tcp_half_opens.tcp_half_open.exists( if self.want.timeout is None:
name=self.want.name, self.want.update({'timeout': 16})
partition=self.want.partition if self.want.interval is None:
) self.want.update({'interval': 5})
return result if self.want.time_until_up is None:
self.want.update({'time_until_up': 0})
def update_on_device(self): if self.want.ip is None:
params = self.want.api_params() self.want.update({'ip': '*'})
result = self.client.api.tm.ltm.monitor.tcp_half_opens.tcp_half_open.load( if self.want.port is None:
name=self.want.name, self.want.update({'port': '*'})
partition=self.want.partition
)
result.modify(**params)
def create_on_device(self): def create_on_device(self):
params = self.want.api_params() params = self.changes.api_params()
self.client.api.tm.ltm.monitor.tcp_half_opens.tcp_half_open.create( params['name'] = self.want.name
name=self.want.name, params['partition'] = self.want.partition
partition=self.want.partition, uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-half-open/".format(
**params self.client.provider['server'],
self.client.provider['server_port']
) )
resp = self.client.api.post(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] in [400, 403]:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def update_on_device(self):
params = self.changes.api_params()
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-half-open/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.patch(uri, json=params)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
def absent(self):
if self.exists():
return self.remove()
return False
def remove_from_device(self): def remove_from_device(self):
result = self.client.api.tm.ltm.monitor.tcp_half_opens.tcp_half_open.load( uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-half-open/{2}".format(
name=self.want.name, self.client.provider['server'],
partition=self.want.partition self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
) )
if result: resp = self.client.api.delete(uri)
result.delete() if resp.status == 200:
return True
def read_current_from_device(self):
uri = "https://{0}:{1}/mgmt/tm/ltm/monitor/tcp-half-open/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
transform_name(self.want.partition, self.want.name)
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if 'code' in response and response['code'] == 400:
if 'message' in response:
raise F5ModuleError(response['message'])
else:
raise F5ModuleError(resp.content)
return ApiParameters(params=response)
class ArgumentSpec(object): class ArgumentSpec(object):
@ -545,20 +604,19 @@ def main():
module = AnsibleModule( module = AnsibleModule(
argument_spec=spec.argument_spec, argument_spec=spec.argument_spec,
supports_check_mode=spec.supports_check_mode supports_check_mode=spec.supports_check_mode,
) )
if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required") client = F5RestClient(**module.params)
try: try:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client) cleanup_tokens(client)
module.exit_json(**results) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client) cleanup_tokens(client)
module.fail_json(msg=str(ex)) fail_json(module, ex, client)
if __name__ == '__main__': if __name__ == '__main__':

View file

@ -672,8 +672,10 @@ def main():
try: try:
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client)
exit_json(module, results, client) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client)
fail_json(module, ex, client) fail_json(module, ex, client)

View file

@ -531,8 +531,10 @@ def main():
client = F5RestClient(**module.params) client = F5RestClient(**module.params)
mm = ModuleManager(module=module, client=client) mm = ModuleManager(module=module, client=client)
results = mm.exec_module() results = mm.exec_module()
cleanup_tokens(client)
exit_json(module, results, client) exit_json(module, results, client)
except F5ModuleError as ex: except F5ModuleError as ex:
cleanup_tokens(client)
fail_json(module, ex, client) fail_json(module, ex, client)