Fixes for bigip_gtm_wide_ip (#39931)

Added the irules parameter. Misc corrections of invalid parameter
names and internal behaviors.
pull/36547/merge
Tim Rupp 6 years ago committed by GitHub
parent 1cf07028d4
commit ad5fdf5eb7
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -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,8 +108,53 @@ 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
'''
@ -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'
]
supported = [
'round-robin', 'topology', 'ratio', 'global-availability'
lb_method_choices = [
'round-robin', 'topology', 'ratio', 'global-availability',
# TODO(Remove in Ansible 2.9)
'round_robin', '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…
Cancel
Save