mirror of
https://github.com/ansible-collections/community.general.git
synced 2025-07-22 21:00:22 -07:00
Initial commit
This commit is contained in:
commit
aebc1b03fd
4861 changed files with 812621 additions and 0 deletions
0
plugins/module_utils/network/f5/__init__.py
Normal file
0
plugins/module_utils/network/f5/__init__.py
Normal file
57
plugins/module_utils/network/f5/iworkflow.py
Normal file
57
plugins/module_utils/network/f5/iworkflow.py
Normal file
|
@ -0,0 +1,57 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2017 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
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import time
|
||||
|
||||
try:
|
||||
from f5.iworkflow import ManagementRoot
|
||||
from icontrol.exceptions import iControlUnexpectedHTTPError
|
||||
HAS_F5SDK = True
|
||||
except ImportError:
|
||||
HAS_F5SDK = False
|
||||
|
||||
try:
|
||||
from library.module_utils.network.f5.common import F5BaseClient
|
||||
from library.module_utils.network.f5.common import F5ModuleError
|
||||
except ImportError:
|
||||
from ansible_collections.f5networks.f5_modules.plugins.module_utils.network.f5.common import F5BaseClient
|
||||
from ansible_collections.f5networks.f5_modules.plugins.module_utils.network.f5.common import F5ModuleError
|
||||
|
||||
|
||||
class F5Client(F5BaseClient):
|
||||
@property
|
||||
def api(self):
|
||||
exc = None
|
||||
if self._client:
|
||||
return self._client
|
||||
for x in range(0, 3):
|
||||
try:
|
||||
server = self.params['provider']['server'] or self.params['server']
|
||||
user = self.params['provider']['user'] or self.params['user']
|
||||
password = self.params['provider']['password'] or self.params['password']
|
||||
server_port = self.params['provider']['server_port'] or self.params['server_port'] or 443
|
||||
validate_certs = self.params['provider']['validate_certs'] or self.params['validate_certs']
|
||||
|
||||
result = ManagementRoot(
|
||||
server,
|
||||
user,
|
||||
password,
|
||||
port=server_port,
|
||||
verify=validate_certs,
|
||||
token='local'
|
||||
)
|
||||
self._client = result
|
||||
return self._client
|
||||
except Exception as ex:
|
||||
exc = ex
|
||||
time.sleep(3)
|
||||
error = 'Unable to connect to {0} on port {1}.'.format(self.params['server'], self.params['server_port'])
|
||||
if exc is not None:
|
||||
error += ' The reported error was "{0}".'.format(str(exc))
|
||||
raise F5ModuleError(error)
|
121
plugins/module_utils/network/f5/legacy.py
Normal file
121
plugins/module_utils/network/f5/legacy.py
Normal file
|
@ -0,0 +1,121 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2017 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
|
||||
__metaclass__ = type
|
||||
|
||||
try:
|
||||
import bigsuds
|
||||
bigsuds_found = True
|
||||
except ImportError:
|
||||
bigsuds_found = False
|
||||
|
||||
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
|
||||
|
||||
def f5_argument_spec():
|
||||
return dict(
|
||||
server=dict(
|
||||
type='str',
|
||||
required=True,
|
||||
fallback=(env_fallback, ['F5_SERVER'])
|
||||
),
|
||||
user=dict(
|
||||
type='str',
|
||||
required=True,
|
||||
fallback=(env_fallback, ['F5_USER'])
|
||||
),
|
||||
password=dict(
|
||||
type='str',
|
||||
aliases=['pass', 'pwd'],
|
||||
required=True,
|
||||
no_log=True,
|
||||
fallback=(env_fallback, ['F5_PASSWORD'])
|
||||
),
|
||||
validate_certs=dict(
|
||||
default='yes',
|
||||
type='bool',
|
||||
fallback=(env_fallback, ['F5_VALIDATE_CERTS'])
|
||||
),
|
||||
server_port=dict(
|
||||
type='int',
|
||||
default=443,
|
||||
fallback=(env_fallback, ['F5_SERVER_PORT'])
|
||||
),
|
||||
state=dict(
|
||||
type='str',
|
||||
default='present',
|
||||
choices=['present', 'absent']
|
||||
),
|
||||
partition=dict(
|
||||
type='str',
|
||||
default='Common',
|
||||
fallback=(env_fallback, ['F5_PARTITION'])
|
||||
)
|
||||
)
|
||||
|
||||
|
||||
def f5_parse_arguments(module):
|
||||
if not bigsuds_found:
|
||||
module.fail_json(msg="the python bigsuds module is required")
|
||||
|
||||
if module.params['validate_certs']:
|
||||
import ssl
|
||||
if not hasattr(ssl, 'SSLContext'):
|
||||
module.fail_json(
|
||||
msg="bigsuds does not support verifying certificates with python < 2.7.9."
|
||||
"Either update python or set validate_certs=False on the task'")
|
||||
|
||||
return (
|
||||
module.params['server'],
|
||||
module.params['user'],
|
||||
module.params['password'],
|
||||
module.params['state'],
|
||||
module.params['partition'],
|
||||
module.params['validate_certs'],
|
||||
module.params['server_port']
|
||||
)
|
||||
|
||||
|
||||
def bigip_api(bigip, user, password, validate_certs, port=443):
|
||||
try:
|
||||
if bigsuds.__version__ >= '1.0.4':
|
||||
api = bigsuds.BIGIP(hostname=bigip, username=user, password=password, verify=validate_certs, port=port)
|
||||
elif bigsuds.__version__ == '1.0.3':
|
||||
api = bigsuds.BIGIP(hostname=bigip, username=user, password=password, verify=validate_certs)
|
||||
else:
|
||||
api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
|
||||
except TypeError:
|
||||
# bigsuds < 1.0.3, no verify param
|
||||
if validate_certs:
|
||||
# Note: verified we have SSLContext when we parsed params
|
||||
api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
|
||||
else:
|
||||
import ssl
|
||||
if hasattr(ssl, 'SSLContext'):
|
||||
# Really, you should never do this. It disables certificate
|
||||
# verification *globally*. But since older bigip libraries
|
||||
# don't give us a way to toggle verification we need to
|
||||
# disable it at the global level.
|
||||
# From https://www.python.org/dev/peps/pep-0476/#id29
|
||||
ssl._create_default_https_context = ssl._create_unverified_context
|
||||
api = bigsuds.BIGIP(hostname=bigip, username=user, password=password)
|
||||
|
||||
return api
|
||||
|
||||
|
||||
# Fully Qualified name (with the partition)
|
||||
def fq_name(partition, name):
|
||||
if name is not None and not name.startswith('/'):
|
||||
return '/%s/%s' % (partition, name)
|
||||
return name
|
||||
|
||||
|
||||
# Fully Qualified name (with partition) for a list
|
||||
def fq_list_names(partition, list_names):
|
||||
if list_names is None:
|
||||
return None
|
||||
return map(lambda x: fq_name(partition, x), list_names)
|
122
plugins/module_utils/network/f5/urls.py
Normal file
122
plugins/module_utils/network/f5/urls.py
Normal file
|
@ -0,0 +1,122 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
#
|
||||
# Copyright (c) 2017, 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
|
||||
__metaclass__ = type
|
||||
|
||||
|
||||
import re
|
||||
|
||||
try:
|
||||
from library.module_utils.network.f5.common import F5ModuleError
|
||||
except ImportError:
|
||||
from ansible_collections.f5networks.f5_modules.plugins.module_utils.network.f5.common import F5ModuleError
|
||||
|
||||
_CLEAN_HEADER_REGEX_BYTE = re.compile(b'^\\S[^\\r\\n]*$|^$')
|
||||
_CLEAN_HEADER_REGEX_STR = re.compile(r'^\S[^\r\n]*$|^$')
|
||||
|
||||
|
||||
def check_header_validity(header):
|
||||
"""Verifies that header value is a string which doesn't contain
|
||||
leading whitespace or return characters.
|
||||
|
||||
NOTE: This is a slightly modified version of the original function
|
||||
taken from the requests library:
|
||||
http://docs.python-requests.org/en/master/_modules/requests/utils/
|
||||
|
||||
:param header: string containing ':'.
|
||||
"""
|
||||
try:
|
||||
name, value = header.split(':')
|
||||
except ValueError:
|
||||
raise F5ModuleError('Invalid header format: {0}'.format(header))
|
||||
if name == '':
|
||||
raise F5ModuleError('Invalid header format: {0}'.format(header))
|
||||
|
||||
if isinstance(value, bytes):
|
||||
pat = _CLEAN_HEADER_REGEX_BYTE
|
||||
else:
|
||||
pat = _CLEAN_HEADER_REGEX_STR
|
||||
try:
|
||||
if not pat.match(value):
|
||||
raise F5ModuleError("Invalid return character or leading space in header: %s" % name)
|
||||
except TypeError:
|
||||
raise F5ModuleError("Value for header {%s: %s} must be of type str or "
|
||||
"bytes, not %s" % (name, value, type(value)))
|
||||
|
||||
|
||||
def build_service_uri(base_uri, partition, name):
|
||||
"""Build the proper uri for a service resource.
|
||||
This follows the scheme:
|
||||
<base_uri>/~<partition>~<<name>.app>~<name>
|
||||
:param base_uri: str -- base uri of the REST endpoint
|
||||
:param partition: str -- partition for the service
|
||||
:param name: str -- name of the service
|
||||
:returns: str -- uri to access the service
|
||||
"""
|
||||
name = name.replace('/', '~')
|
||||
return '%s~%s~%s.app~%s' % (base_uri, partition, name, name)
|
||||
|
||||
|
||||
def parseStats(entry):
|
||||
if 'description' in entry:
|
||||
return entry['description']
|
||||
elif 'value' in entry:
|
||||
return entry['value']
|
||||
elif 'entries' in entry or 'nestedStats' in entry and 'entries' in entry['nestedStats']:
|
||||
if 'entries' in entry:
|
||||
entries = entry['entries']
|
||||
else:
|
||||
entries = entry['nestedStats']['entries']
|
||||
result = None
|
||||
|
||||
for name in entries:
|
||||
entry = entries[name]
|
||||
if 'https://localhost' in name:
|
||||
name = name.split('/')
|
||||
name = name[-1]
|
||||
if result and isinstance(result, list):
|
||||
result.append(parseStats(entry))
|
||||
elif result and isinstance(result, dict):
|
||||
result[name] = parseStats(entry)
|
||||
else:
|
||||
try:
|
||||
int(name)
|
||||
result = list()
|
||||
result.append(parseStats(entry))
|
||||
except ValueError:
|
||||
result = dict()
|
||||
result[name] = parseStats(entry)
|
||||
else:
|
||||
if '.' in name:
|
||||
names = name.split('.')
|
||||
key = names[0]
|
||||
value = names[1]
|
||||
if result is None:
|
||||
# result can be None if this branch is reached first
|
||||
#
|
||||
# For example, the mgmt/tm/net/trunk/NAME/stats API
|
||||
# returns counters.bitsIn before anything else.
|
||||
result = dict()
|
||||
result[key] = dict()
|
||||
elif key not in result:
|
||||
result[key] = dict()
|
||||
elif result[key] is None:
|
||||
result[key] = dict()
|
||||
result[key][value] = parseStats(entry)
|
||||
else:
|
||||
if result and isinstance(result, list):
|
||||
result.append(parseStats(entry))
|
||||
elif result and isinstance(result, dict):
|
||||
result[name] = parseStats(entry)
|
||||
else:
|
||||
try:
|
||||
int(name)
|
||||
result = list()
|
||||
result.append(parseStats(entry))
|
||||
except ValueError:
|
||||
result = dict()
|
||||
result[name] = parseStats(entry)
|
||||
return result
|
Loading…
Add table
Add a link
Reference in a new issue