Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Removes the f5-sdk from bigip_sys_db #48015

Merged
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
296 changes: 201 additions & 95 deletions lib/ansible/modules/network/f5/bigip_sys_db.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
#!/usr/bin/python
# -*- coding: utf-8 -*-
#
# Copyright (c) 2016 F5 Networks Inc.
# Copyright: (c) 2016, F5 Networks Inc.
# GNU General Public License v3.0 (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

from __future__ import absolute_import, division, print_function
Expand Down Expand Up @@ -95,80 +95,135 @@
from ansible.module_utils.basic import AnsibleModule

try:
from library.module_utils.network.f5.bigip import HAS_F5SDK
from library.module_utils.network.f5.bigip import F5Client
from library.module_utils.network.f5.bigip import F5RestClient
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 f5_argument_spec

try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
from library.module_utils.network.f5.common import exit_json
from library.module_utils.network.f5.common import fail_json
except ImportError:
from ansible.module_utils.network.f5.bigip import HAS_F5SDK
from ansible.module_utils.network.f5.bigip import F5Client
from ansible.module_utils.network.f5.bigip import F5RestClient
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 f5_argument_spec

try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError:
HAS_F5SDK = False
from ansible.module_utils.network.f5.common import exit_json
from ansible.module_utils.network.f5.common import fail_json


class Parameters(AnsibleF5Parameters):
api_map = {
'defaultValue': 'default_value'
}
api_attributes = ['value']
updatables = ['value']
returnables = ['name', 'value', 'default_value']
api_attributes = [
'value',
]
updatables = [
'value',
]
returnables = [
'name',
'value',
'default_value',
]


class ApiParameters(Parameters):
pass


class ModuleParameters(Parameters):
pass


class Changes(Parameters):
def to_return(self):
result = {}
for returnable in self.returnables:
result[returnable] = getattr(self, returnable)
result = self._filter_params(result)
try:
for returnable in self.returnables:
change = getattr(self, returnable)
if isinstance(change, dict):
result.update(change)
else:
result[returnable] = change
result = self._filter_params(result)
except Exception:
pass
return result

@property
def name(self):
return self._values['key']

@name.setter
def name(self, value):
self._values['key'] = value
class UsableChanges(Changes):
pass


class Changes(Parameters):
class ReportableChanges(Changes):
pass


class Difference(object):
def __init__(self, want, have=None):
self.want = want
self.have = have

def compare(self, param):
try:
result = getattr(self, param)
return result
except AttributeError:
return self.__default(param)

def __default(self, param):
attr1 = getattr(self.want, param)
try:
attr2 = getattr(self.have, param)
if attr1 != attr2:
return attr1
except AttributeError:
return attr1

@property
def value(self):
if self.want.state == 'reset':
if str(self.have.value) != str(self.have.default_value):
return self.have.default_value
if self.want.value != self.have.value:
return self.want.value


class ModuleManager(object):
def __init__(self, *args, **kwargs):
self.module = kwargs.get('module', None)
self.client = kwargs.get('client', None)
self.have = None
self.want = Parameters(params=self.module.params)
self.changes = Changes()
self.module = kwargs.pop('module', None)
self.client = kwargs.pop('client', None)
self.want = ModuleParameters(params=self.module.params)
self.have = ApiParameters()
self.changes = UsableChanges()

def _announce_deprecations(self, result):
warnings = result.pop('__warnings', [])
for warning in warnings:
self.module.deprecate(
msg=warning['msg'],
version=warning['version']
)

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 self.want.state == 'reset':
if str(self.have.value) != str(self.have.default_value):
changed[self.want.key] = self.have.default_value
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 = Changes(params=changed)
changed['name'] = self.want.key
changed['default_value'] = self.have.default_value
self.changes = UsableChanges(params=changed)
return True
return False

Expand All @@ -177,40 +232,40 @@ def exec_module(self):
result = dict()
state = self.want.state

try:
if state == "present":
changed = self.present()
elif state == "reset":
changed = self.reset()
except iControlUnexpectedHTTPError as e:
raise F5ModuleError(str(e))

changes = self.changes.to_return()
if state == "present":
changed = self.present()
elif state == "reset":
changed = self.reset()

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 read_current_from_device(self):
resource = self.client.api.tm.sys.dbs.db.load(
name=self.want.key
)
result = resource.attrs
return Parameters(params=result)

def exists(self):
resource = self.client.api.tm.sys.dbs.db.load(
name=self.want.key
)
if str(resource.value) == str(self.want.value):
return True
return False

def present(self):
if self.exists():
return False
else:
return self.update()

def reset(self):
self.have = self.read_current_from_device()
if not self.should_update():
return False
if self.module.check_mode:
return True
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:
raise F5ModuleError(
"Failed to reset the DB variable"
)

def update(self):
if self.want.value is None:
raise F5ModuleError(
Expand All @@ -230,34 +285,86 @@ def should_update(self):
return True
return False

def exists(self):
uri = "https://{0}:{1}/mgmt/tm/sys/db/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
self.want.key
)
resp = self.client.api.get(uri)
try:
response = resp.json()
except ValueError as ex:
raise F5ModuleError(str(ex))
if str(response['value']) == str(self.want.value):
return True
return False

def read_current_from_device(self):
uri = "https://{0}:{1}/mgmt/tm/sys/db/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
self.want.key
)

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)

def update_on_device(self):
params = self.want.api_params()
resource = self.client.api.tm.sys.dbs.db.load(
name=self.want.key
params = self.changes.api_params()
uri = "https://{0}:{1}/mgmt/tm/sys/db/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
self.want.key
)
resource.update(**params)

def reset(self):
self.have = self.read_current_from_device()
if not self.should_update():
return False
if self.module.check_mode:
return True
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:
raise F5ModuleError(
"Failed to reset the DB variable"
)
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 reset_on_device(self):
resource = self.client.api.tm.sys.dbs.db.load(
name=self.want.key
uri = "https://{0}:{1}/mgmt/tm/sys/db/{2}".format(
self.client.provider['server'],
self.client.provider['server_port'],
self.want.key
)
params = dict(
value=self.have.default_value
)
resource.update(value=self.have.default_value)

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)


class ArgumentSpec(object):
Expand All @@ -283,18 +390,17 @@ def main():
argument_spec=spec.argument_spec,
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:
client = F5Client(**module.params)
mm = ModuleManager(module=module, client=client)
results = mm.exec_module()
cleanup_tokens(client)
module.exit_json(**results)
exit_json(module, results, client)
except F5ModuleError as ex:
cleanup_tokens(client)
module.fail_json(msg=str(ex))
fail_json(module, ex, client)


if __name__ == '__main__':
Expand Down