mirror of
https://github.com/ansible-collections/community.general.git
synced 2024-09-14 20:13:21 +02:00
Fixes for bigip_gtm_wide_ip (#39931)
Added the irules parameter. Misc corrections of invalid parameter names and internal behaviors.
This commit is contained in:
parent
1cf07028d4
commit
ad5fdf5eb7
3 changed files with 151 additions and 70 deletions
|
@ -17,13 +17,15 @@ module: bigip_gtm_wide_ip
|
|||
short_description: Manages F5 BIG-IP GTM wide ip
|
||||
description:
|
||||
- Manages F5 BIG-IP GTM wide ip.
|
||||
version_added: "2.0"
|
||||
version_added: 2.0
|
||||
options:
|
||||
pool_lb_method:
|
||||
description:
|
||||
- Specifies the load balancing method used to select a pool in this wide
|
||||
IP. This setting is relevant only when multiple pools are configured
|
||||
for a wide IP.
|
||||
- The C(round_robin) value is deprecated and will be removed in Ansible 2.9.
|
||||
- The C(global_availability) value is deprecated and will be removed in Ansible 2.9.
|
||||
required: True
|
||||
aliases: ['lb_method']
|
||||
choices:
|
||||
|
@ -31,6 +33,8 @@ options:
|
|||
- ratio
|
||||
- topology
|
||||
- global-availability
|
||||
- global_availability
|
||||
- round_robin
|
||||
version_added: 2.5
|
||||
name:
|
||||
description:
|
||||
|
@ -80,13 +84,19 @@ options:
|
|||
suboptions:
|
||||
name:
|
||||
description:
|
||||
- The name of the pool to include
|
||||
required: true
|
||||
- The name of the pool to include.
|
||||
required: True
|
||||
ratio:
|
||||
description:
|
||||
- Ratio for the pool.
|
||||
- The system uses this number with the Ratio load balancing method.
|
||||
version_added: 2.5
|
||||
irules:
|
||||
version_added: 2.6
|
||||
description:
|
||||
- List of rules to be applied.
|
||||
- If you want to remove all existing iRules, specify a single empty value; C("").
|
||||
See the documentation for an example.
|
||||
extends_documentation_fragment: f5
|
||||
author:
|
||||
- Tim Rupp (@caphrim007)
|
||||
|
@ -98,9 +108,54 @@ EXAMPLES = r'''
|
|||
server: lb.mydomain.com
|
||||
user: admin
|
||||
password: secret
|
||||
lb_method: round-robin
|
||||
pool_lb_method: round-robin
|
||||
name: my-wide-ip.example.com
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Add iRules to the Wide IP
|
||||
bigip_gtm_wide_ip:
|
||||
server: lb.mydomain.com
|
||||
user: admin
|
||||
password: secret
|
||||
pool_lb_method: round-robin
|
||||
name: my-wide-ip.example.com
|
||||
irules:
|
||||
- irule1
|
||||
- irule2
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Remove one iRule from the Virtual Server
|
||||
bigip_gtm_wide_ip:
|
||||
server: lb.mydomain.com
|
||||
user: admin
|
||||
password: secret
|
||||
pool_lb_method: round-robin
|
||||
name: my-wide-ip.example.com
|
||||
irules:
|
||||
- irule1
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Remove all iRules from the Virtual Server
|
||||
bigip_gtm_wide_ip:
|
||||
server: lb.mydomain.com
|
||||
user: admin
|
||||
password: secret
|
||||
pool_lb_method: round-robin
|
||||
name: my-wide-ip.example.com
|
||||
irules: ""
|
||||
delegate_to: localhost
|
||||
|
||||
- name: Assign a pool with ratio to the Wide IP
|
||||
bigip_gtm_wide_ip:
|
||||
server: lb.mydomain.com
|
||||
user: admin
|
||||
password: secret
|
||||
pool_lb_method: round-robin
|
||||
name: my-wide-ip.example.com
|
||||
pools:
|
||||
- name: pool1
|
||||
ratio: 100
|
||||
delegate_to: localhost
|
||||
'''
|
||||
|
||||
RETURN = r'''
|
||||
|
@ -114,40 +169,40 @@ state:
|
|||
returned: changed
|
||||
type: string
|
||||
sample: disabled
|
||||
irules:
|
||||
description: iRules set on the Wide IP.
|
||||
returned: changed
|
||||
type: list
|
||||
sample: ['/Common/irule1', '/Common/irule2']
|
||||
'''
|
||||
|
||||
import re
|
||||
|
||||
from ansible.module_utils.six import iteritems
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
from ansible.module_utils.basic import AnsibleModule
|
||||
from ansible.module_utils.basic import env_fallback
|
||||
|
||||
HAS_DEVEL_IMPORTS = False
|
||||
from ansible.module_utils.six import iteritems
|
||||
from distutils.version import LooseVersion
|
||||
|
||||
try:
|
||||
# Sideband repository used for dev
|
||||
from library.module_utils.network.f5.bigip import HAS_F5SDK
|
||||
from library.module_utils.network.f5.bigip import F5Client
|
||||
from library.module_utils.network.f5.common import F5ModuleError
|
||||
from library.module_utils.network.f5.common import AnsibleF5Parameters
|
||||
from library.module_utils.network.f5.common import cleanup_tokens
|
||||
from library.module_utils.network.f5.common import fqdn_name
|
||||
from library.module_utils.network.f5.common import fq_name
|
||||
from library.module_utils.network.f5.common import is_valid_fqdn
|
||||
from library.module_utils.network.f5.common import f5_argument_spec
|
||||
|
||||
try:
|
||||
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
||||
except ImportError:
|
||||
HAS_F5SDK = False
|
||||
HAS_DEVEL_IMPORTS = True
|
||||
except ImportError:
|
||||
# Upstream Ansible
|
||||
from ansible.module_utils.network.f5.bigip import HAS_F5SDK
|
||||
from ansible.module_utils.network.f5.bigip import F5Client
|
||||
from ansible.module_utils.network.f5.common import F5ModuleError
|
||||
from ansible.module_utils.network.f5.common import AnsibleF5Parameters
|
||||
from ansible.module_utils.network.f5.common import cleanup_tokens
|
||||
from ansible.module_utils.network.f5.common import fqdn_name
|
||||
from ansible.module_utils.network.f5.common import fq_name
|
||||
from ansible.module_utils.network.f5.common import is_valid_fqdn
|
||||
from ansible.module_utils.network.f5.common import f5_argument_spec
|
||||
try:
|
||||
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
||||
|
@ -157,16 +212,21 @@ except ImportError:
|
|||
|
||||
class Parameters(AnsibleF5Parameters):
|
||||
api_map = {
|
||||
'poolLbMode': 'pool_lb_method'
|
||||
'poolLbMode': 'pool_lb_method',
|
||||
'rules': 'irules',
|
||||
}
|
||||
updatables = ['pool_lb_method', 'state', 'pools']
|
||||
returnables = ['name', 'pool_lb_method', 'state', 'pools']
|
||||
api_attributes = ['poolLbMode', 'enabled', 'disabled', 'pools']
|
||||
|
||||
def _fqdn_name(self, value):
|
||||
if value is not None and not value.startswith('/'):
|
||||
return '/{0}/{1}'.format(self.partition, value)
|
||||
return value
|
||||
updatables = [
|
||||
'pool_lb_method', 'state', 'pools', 'irules', 'enabled', 'disabled'
|
||||
]
|
||||
|
||||
returnables = [
|
||||
'name', 'pool_lb_method', 'state', 'pools', 'irules'
|
||||
]
|
||||
|
||||
api_attributes = [
|
||||
'poolLbMode', 'enabled', 'disabled', 'pools', 'rules'
|
||||
]
|
||||
|
||||
|
||||
class ApiParameters(Parameters):
|
||||
|
@ -204,25 +264,15 @@ class ApiParameters(Parameters):
|
|||
class ModuleParameters(Parameters):
|
||||
@property
|
||||
def pool_lb_method(self):
|
||||
deprecated = [
|
||||
'return_to_dns', 'null', 'static_persist', 'vs_capacity',
|
||||
'least_conn', 'lowest_rtt', 'lowest_hops', 'packet_rate', 'cpu',
|
||||
'hit_ratio', 'qos', 'bps', 'drop_packet', 'explicit_ip',
|
||||
'connection_rate', 'vs_score'
|
||||
]
|
||||
if self._values['lb_method'] is None:
|
||||
if self._values['pool_lb_method'] is None:
|
||||
return None
|
||||
lb_method = str(self._values['lb_method'])
|
||||
if lb_method in deprecated:
|
||||
raise F5ModuleError(
|
||||
"The provided lb_method is not supported"
|
||||
)
|
||||
elif lb_method == 'global_availability':
|
||||
lb_method = str(self._values['pool_lb_method'])
|
||||
if lb_method == 'global_availability':
|
||||
if self._values['__warnings'] is None:
|
||||
self._values['__warnings'] = []
|
||||
self._values['__warnings'].append(
|
||||
dict(
|
||||
msg='The provided lb_method is deprecated',
|
||||
msg='The provided pool_lb_method is deprecated',
|
||||
version='2.4'
|
||||
)
|
||||
)
|
||||
|
@ -232,7 +282,7 @@ class ModuleParameters(Parameters):
|
|||
self._values['__warnings'] = []
|
||||
self._values['__warnings'].append(
|
||||
dict(
|
||||
msg='The provided lb_method is deprecated',
|
||||
msg='The provided pool_lb_method is deprecated',
|
||||
version='2.4'
|
||||
)
|
||||
)
|
||||
|
@ -249,7 +299,7 @@ class ModuleParameters(Parameters):
|
|||
def name(self):
|
||||
if self._values['name'] is None:
|
||||
return None
|
||||
if not re.search(r'.*\..*\..*', self._values['name']):
|
||||
if not is_valid_fqdn(self._values['name']):
|
||||
raise F5ModuleError(
|
||||
"The provided name must be a valid FQDN"
|
||||
)
|
||||
|
@ -286,12 +336,28 @@ class ModuleParameters(Parameters):
|
|||
return None
|
||||
for item in self._values['pools']:
|
||||
pool = dict()
|
||||
if 'name' not in item:
|
||||
raise F5ModuleError(
|
||||
"'name' is a required key for items in the list of pools."
|
||||
)
|
||||
if 'ratio' in item:
|
||||
pool['ratio'] = item['ratio']
|
||||
pool['name'] = self._fqdn_name(item['name'])
|
||||
pool['name'] = fq_name(self.partition, item['name'])
|
||||
result.append(pool)
|
||||
return result
|
||||
|
||||
@property
|
||||
def irules(self):
|
||||
results = []
|
||||
if self._values['irules'] is None:
|
||||
return None
|
||||
if len(self._values['irules']) == 1 and self._values['irules'][0] == '':
|
||||
return ''
|
||||
for irule in self._values['irules']:
|
||||
result = fq_name(self.partition, irule)
|
||||
results.append(result)
|
||||
return results
|
||||
|
||||
|
||||
class Changes(Parameters):
|
||||
def to_return(self):
|
||||
|
@ -310,7 +376,13 @@ class Changes(Parameters):
|
|||
|
||||
|
||||
class UsableChanges(Changes):
|
||||
pass
|
||||
@property
|
||||
def irules(self):
|
||||
if self._values['irules'] is None:
|
||||
return None
|
||||
if self._values['irules'] == '':
|
||||
return []
|
||||
return self._values['irules']
|
||||
|
||||
|
||||
class ReportableChanges(Changes):
|
||||
|
@ -375,6 +447,17 @@ class Difference(object):
|
|||
result = self._diff_complex_items(self.want.pools, self.have.pools)
|
||||
return result
|
||||
|
||||
@property
|
||||
def irules(self):
|
||||
if self.want.irules is None:
|
||||
return None
|
||||
if self.want.irules == '' and self.have.irules is None:
|
||||
return None
|
||||
if self.want.irules == '' and len(self.have.irules) > 0:
|
||||
return []
|
||||
if sorted(set(self.want.irules)) != sorted(set(self.have.irules)):
|
||||
return self.want.irules
|
||||
|
||||
|
||||
class ModuleManager(object):
|
||||
def __init__(self, *args, **kwargs):
|
||||
|
@ -466,16 +549,16 @@ class BaseManager(object):
|
|||
)
|
||||
|
||||
def present(self):
|
||||
if self.want.lb_method is None:
|
||||
raise F5ModuleError(
|
||||
"The 'lb_method' option is required when state is 'present'"
|
||||
)
|
||||
if self.exists():
|
||||
return self.update()
|
||||
else:
|
||||
return self.create()
|
||||
|
||||
def create(self):
|
||||
if self.want.pool_lb_method is None:
|
||||
raise F5ModuleError(
|
||||
"The 'pool_lb_method' option is required when state is 'present'"
|
||||
)
|
||||
self._set_changed_options()
|
||||
if self.module.check_mode:
|
||||
return True
|
||||
|
@ -519,7 +602,7 @@ class UntypedManager(BaseManager):
|
|||
)
|
||||
|
||||
def update_on_device(self):
|
||||
params = self.want.api_params()
|
||||
params = self.changes.api_params()
|
||||
result = self.client.api.tm.gtm.wideips.wipeip.load(
|
||||
name=self.want.name,
|
||||
partition=self.want.partition
|
||||
|
@ -535,7 +618,7 @@ class UntypedManager(BaseManager):
|
|||
return ApiParameters(params=result)
|
||||
|
||||
def create_on_device(self):
|
||||
params = self.want.api_params()
|
||||
params = self.changes.api_params()
|
||||
self.client.api.tm.gtm.wideips.wideip.create(
|
||||
name=self.want.name,
|
||||
partition=self.want.partition,
|
||||
|
@ -580,7 +663,7 @@ class TypedManager(BaseManager):
|
|||
return result
|
||||
|
||||
def update_on_device(self):
|
||||
params = self.want.api_params()
|
||||
params = self.changes.api_params()
|
||||
wideips = self.client.api.tm.gtm.wideips
|
||||
collection = getattr(wideips, self.collection)
|
||||
resource = getattr(collection, self.want.type)
|
||||
|
@ -602,7 +685,7 @@ class TypedManager(BaseManager):
|
|||
return ApiParameters(params=result)
|
||||
|
||||
def create_on_device(self):
|
||||
params = self.want.api_params()
|
||||
params = self.changes.api_params()
|
||||
wideips = self.client.api.tm.gtm.wideips
|
||||
collection = getattr(wideips, self.collection)
|
||||
resource = getattr(collection, self.want.type)
|
||||
|
@ -626,16 +709,12 @@ class TypedManager(BaseManager):
|
|||
|
||||
class ArgumentSpec(object):
|
||||
def __init__(self):
|
||||
deprecated = [
|
||||
'return_to_dns', 'null', 'round_robin', 'static_persist',
|
||||
'global_availability', 'vs_capacity', 'least_conn', 'lowest_rtt',
|
||||
'lowest_hops', 'packet_rate', 'cpu', 'hit_ratio', 'qos', 'bps',
|
||||
'drop_packet', 'explicit_ip', 'connection_rate', 'vs_score'
|
||||
lb_method_choices = [
|
||||
'round-robin', 'topology', 'ratio', 'global-availability',
|
||||
|
||||
# TODO(Remove in Ansible 2.9)
|
||||
'round_robin', 'global_availability'
|
||||
]
|
||||
supported = [
|
||||
'round-robin', 'topology', 'ratio', 'global-availability'
|
||||
]
|
||||
lb_method_choices = deprecated + supported
|
||||
self.supports_check_mode = True
|
||||
argument_spec = dict(
|
||||
pool_lb_method=dict(
|
||||
|
@ -665,7 +744,10 @@ class ArgumentSpec(object):
|
|||
partition=dict(
|
||||
default='Common',
|
||||
fallback=(env_fallback, ['F5_PARTITION'])
|
||||
)
|
||||
),
|
||||
irules=dict(
|
||||
type='list',
|
||||
),
|
||||
)
|
||||
self.argument_spec = {}
|
||||
self.argument_spec.update(f5_argument_spec)
|
||||
|
|
|
@ -1072,7 +1072,6 @@ lib/ansible/modules/network/f5/bigip_gtm_facts.py E326
|
|||
lib/ansible/modules/network/f5/bigip_gtm_pool.py E324
|
||||
lib/ansible/modules/network/f5/bigip_gtm_pool.py E326
|
||||
lib/ansible/modules/network/f5/bigip_gtm_server.py E326
|
||||
lib/ansible/modules/network/f5/bigip_gtm_wide_ip.py E326
|
||||
lib/ansible/modules/network/f5/bigip_iapp_service.py E324
|
||||
lib/ansible/modules/network/f5/bigip_iapp_service.py E325
|
||||
lib/ansible/modules/network/f5/bigip_monitor_snmp_dca.py E326
|
||||
|
|
|
@ -21,12 +21,12 @@ from ansible.compat.tests.mock import patch
|
|||
from ansible.module_utils.basic import AnsibleModule
|
||||
|
||||
try:
|
||||
from library.bigip_gtm_wide_ip import ApiParameters
|
||||
from library.bigip_gtm_wide_ip import ModuleParameters
|
||||
from library.bigip_gtm_wide_ip import ModuleManager
|
||||
from library.bigip_gtm_wide_ip import ArgumentSpec
|
||||
from library.bigip_gtm_wide_ip import UntypedManager
|
||||
from library.bigip_gtm_wide_ip import TypedManager
|
||||
from library.modules.bigip_gtm_wide_ip import ApiParameters
|
||||
from library.modules.bigip_gtm_wide_ip import ModuleParameters
|
||||
from library.modules.bigip_gtm_wide_ip import ModuleManager
|
||||
from library.modules.bigip_gtm_wide_ip import ArgumentSpec
|
||||
from library.modules.bigip_gtm_wide_ip import UntypedManager
|
||||
from library.modules.bigip_gtm_wide_ip import TypedManager
|
||||
from library.module_utils.network.f5.common import F5ModuleError
|
||||
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
|
||||
from test.unit.modules.utils import set_module_args
|
||||
|
@ -70,7 +70,7 @@ class TestParameters(unittest.TestCase):
|
|||
def test_module_parameters(self):
|
||||
args = dict(
|
||||
name='foo.baz.bar',
|
||||
lb_method='round-robin',
|
||||
pool_lb_method='round-robin',
|
||||
)
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.name == 'foo.baz.bar'
|
||||
|
@ -108,12 +108,12 @@ class TestParameters(unittest.TestCase):
|
|||
|
||||
def test_module_not_fqdn_name(self):
|
||||
args = dict(
|
||||
name='foo.baz',
|
||||
name='foo',
|
||||
lb_method='round-robin'
|
||||
)
|
||||
with pytest.raises(F5ModuleError) as excinfo:
|
||||
p = ModuleParameters(params=args)
|
||||
assert p.name == 'foo.baz'
|
||||
assert p.name == 'foo'
|
||||
assert 'The provided name must be a valid FQDN' in str(excinfo)
|
||||
|
||||
|
||||
|
|
Loading…
Reference in a new issue