Adds remaining fqdn params to bigip_node (#40427)

This patch adds params for auto_populate, address type, up interval
and down interval params to bigip node
This commit is contained in:
Tim Rupp 2018-05-18 19:14:07 -07:00 committed by GitHub
parent 8b5f34e110
commit 510995bd83
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 307 additions and 14 deletions

View file

@ -87,6 +87,51 @@ options:
aliases:
- hostname
version_added: 2.5
fqdn_address_type:
description:
- Specifies whether the FQDN of the node resolves to an IPv4 or IPv6 address.
- When creating a new node, if this parameter is not specified and C(fqdn) is
specified, this parameter will default to C(ipv4).
- This parameter cannot be changed after it has been set.
choices:
- ipv4
- ipv6
- all
version_added: 2.6
fqdn_auto_populate:
description:
- Specifies whether the system automatically creates ephemeral nodes using
the IP addresses returned by the resolution of a DNS query for a node defined
by an FQDN.
- When C(yes), the system generates an ephemeral node for each IP address
returned in response to a DNS query for the FQDN of the node. Additionally,
when a DNS response indicates the IP address of an ephemeral node no longer
exists, the system deletes the ephemeral node.
- When C(no), the system resolves a DNS query for the FQDN of the node with the
single IP address associated with the FQDN.
- When creating a new node, if this parameter is not specified and C(fqdn) is
specified, this parameter will default to C(yes).
- This parameter cannot be changed after it has been set.
type: bool
version_added: 2.6
fqdn_up_interval:
description:
- Specifies the interval in which a query occurs, when the DNS server is up.
The associated monitor attempts to probe three times, and marks the server
down if it there is no response within the span of three times the interval
value, in seconds.
- This parameter accepts a value of C(ttl) to query based off of the TTL of
the FQDN. The default TTL interval is akin to specifying C(3600).
- When creating a new node, if this parameter is not specified and C(fqdn) is
specified, this parameter will default to C(3600).
version_added: 2.6
fqdn_down_interval:
description:
- Specifies the interval in which a query occurs, when the DNS server is down.
The associated monitor continues polling as long as the DNS server is down.
- When creating a new node, if this parameter is not specified and C(fqdn) is
specified, this parameter will default to C(5).
version_added: 2.6
description:
description:
- Specifies descriptive text that identifies the node.
@ -217,6 +262,8 @@ import time
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
from ansible.module_utils.parsing.convert_bool import BOOLEANS_FALSE
from ansible.module_utils.parsing.convert_bool import BOOLEANS_TRUE
try:
from library.module_utils.network.f5.bigip import HAS_F5SDK
@ -271,11 +318,15 @@ class Parameters(AnsibleF5Parameters):
]
returnables = [
'monitor_type', 'quorum', 'monitors', 'description', 'fqdn', 'session', 'state'
'monitor_type', 'quorum', 'monitors', 'description', 'fqdn', 'session', 'state',
'fqdn_auto_populate', 'fqdn_address_type', 'fqdn_up_interval',
'fqdn_down_interval', 'fqdn_name'
]
updatables = [
'monitor_type', 'quorum', 'monitors', 'description', 'state'
'monitor_type', 'quorum', 'monitors', 'description', 'state',
'fqdn_up_interval', 'fqdn_down_interval', 'tmName', 'fqdn_auto_populate',
'fqdn_address_type'
]
def to_return(self):
@ -348,21 +399,102 @@ class Parameters(AnsibleF5Parameters):
return None
return self._values['monitor_type']
class Changes(Parameters):
pass
class UsableChanges(Changes):
@property
def fqdn(self):
result = dict()
if self._values['fqdn_up_interval'] is not None:
result['interval'] = self._values['fqdn_up_interval']
if self._values['fqdn_down_interval'] is not None:
result['downInterval'] = self._values['fqdn_down_interval']
if self._values['fqdn_auto_populate'] is not None:
result['autopopulate'] = self._values['fqdn_auto_populate']
if self._values['fqdn_name'] is not None:
result['tmName'] = self._values['fqdn_name']
return result
class ReportableChanges(Changes):
pass
class ModuleParameters(Parameters):
@property
def fqdn_up_interval(self):
if self._values['fqdn_up_interval'] is None:
return None
return str(self._values['fqdn_up_interval'])
@property
def fqdn_down_interval(self):
if self._values['fqdn_down_interval'] is None:
return None
return str(self._values['fqdn_down_interval'])
@property
def fqdn_auto_populate(self):
auto_populate = self._values.get('fqdn_auto_populate', None)
if auto_populate in BOOLEANS_TRUE:
return 'enabled'
elif auto_populate in BOOLEANS_FALSE:
return 'disabled'
@property
def fqdn_name(self):
return self._values.get('fqdn', None)
@property
def fqdn(self):
if self._values['fqdn'] is None:
return None
result = dict(
addressFamily='ipv4',
autopopulate='disabled',
downInterval=3600,
tmName=self._values['fqdn']
addressFamily=self._values.get('fqdn_address_type', None),
downInterval=self._values.get('fqdn_down_interval', None),
interval=self._values.get('fqdn_up_interval', None),
autopopulate=None,
tmName=self._values.get('fqdn', None)
)
auto_populate = self._values.get('fqdn_auto_populate', None)
if auto_populate in BOOLEANS_TRUE:
result['autopopulate'] = 'enabled'
elif auto_populate in BOOLEANS_FALSE:
result['autopopulate'] = 'disabled'
return result
class Changes(Parameters):
pass
class ApiParameters(Parameters):
@property
def fqdn_up_interval(self):
if self._values['fqdn'] is None:
return None
if 'interval' in self._values['fqdn']:
return str(self._values['fqdn']['interval'])
@property
def fqdn_down_interval(self):
if self._values['fqdn'] is None:
return None
if 'downInterval' in self._values['fqdn']:
return str(self._values['fqdn']['downInterval'])
@property
def fqdn_address_type(self):
if self._values['fqdn'] is None:
return None
if 'addressFamily' in self._values['fqdn']:
return str(self._values['fqdn']['addressFamily'])
@property
def fqdn_auto_populate(self):
if self._values['fqdn'] is None:
return None
if 'autopopulate' in self._values['fqdn']:
return str(self._values['fqdn']['autopopulate'])
class Difference(object):
@ -454,14 +586,36 @@ class Difference(object):
)
return result
@property
def fqdn_auto_populate(self):
if self.want.fqdn_auto_populate is None:
return None
if self.want.fqdn_auto_populate != self.have.fqdn_auto_populate:
raise F5ModuleError(
"The 'fqdn_auto_populate' parameter cannot be changed."
)
@property
def fqdn_address_type(self):
if self.want.fqdn_address_type is None:
return None
if self.want.fqdn_address_type != self.have.fqdn_address_type:
raise F5ModuleError(
"The 'fqdn_address_type' parameter cannot be changed."
)
@property
def fqdn(self):
return None
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.want = ModuleParameters(params=self.module.params)
self.changes = UsableChanges()
def _set_changed_options(self):
changed = {}
@ -469,7 +623,7 @@ class ModuleManager(object):
if getattr(self.want, key) is not None:
changed[key] = getattr(self.want, key)
if changed:
self.changes = Changes(params=changed)
self.changes = UsableChanges(params=changed)
def _update_changed_options(self):
diff = Difference(self.want, self.have)
@ -485,7 +639,7 @@ class ModuleManager(object):
else:
changed[k] = change
if changed:
self.changes = Changes(params=changed)
self.changes = UsableChanges(params=changed)
return True
return False
@ -573,9 +727,20 @@ class ModuleManager(object):
def create(self):
self._check_required_creation_vars()
self._munge_creation_state_for_device()
if self.want.fqdn_auto_populate is None:
self.want.update({'fqdn_auto_populate': True})
if self.want.fqdn_address_type is None:
self.want.update({'fqdn_address_type': 'ipv4'})
if self.want.fqdn_up_interval is None:
self.want.update({'fqdn_up_interval': 3600})
if self.want.fqdn_down_interval is None:
self.want.update({'fqdn_down_interval': 5})
self._set_changed_options()
if self.module.check_mode:
return True
self.create_on_device()
if not self.exists():
raise F5ModuleError("Failed to create the node")
@ -597,6 +762,7 @@ class ModuleManager(object):
return False
if self.module.check_mode:
return True
self.update_on_device()
if self.want.state == 'offline':
self.update_node_offline_on_device()
@ -621,7 +787,7 @@ class ModuleManager(object):
partition=self.want.partition
)
result = resource.attrs
return Parameters(params=result)
return ApiParameters(params=result)
def exists(self):
result = self.client.api.tm.ltm.nodes.node.exists(
@ -701,7 +867,13 @@ class ArgumentSpec(object):
partition=dict(
default='Common',
fallback=(env_fallback, ['F5_PARTITION'])
)
),
fqdn_address_type=dict(
choices=['ipv4', 'ipv6', 'all']
),
fqdn_auto_populate=dict(type='bool'),
fqdn_up_interval=dict(),
fqdn_down_interval=dict(type='int')
)
self.argument_spec = {}
self.argument_spec.update(f5_argument_spec)

View file

@ -0,0 +1,26 @@
{
"kind": "tm:ltm:node:nodestate",
"name": "fqdn-foo",
"partition": "Common",
"fullPath": "/Common/fqdn-foo",
"generation": 161,
"selfLink": "https://localhost/mgmt/tm/ltm/node/~Common~fqdn-foo?ver=13.0.0",
"address": "any6",
"connectionLimit": 0,
"description": "another node but with fqdn",
"dynamicRatio": 1,
"ephemeral": "false",
"fqdn": {
"addressFamily": "ipv4",
"autopopulate": "disabled",
"downInterval": 5,
"interval": "3600",
"tmName": "google.com"
},
"logging": "disabled",
"monitor": "/Common/icmp and /Common/tcp_echo ",
"rateLimit": "disabled",
"ratio": 1,
"session": "user-enabled",
"state": "fqdn-up"
}

View file

@ -21,6 +21,8 @@ from ansible.module_utils.basic import AnsibleModule
try:
from library.modules.bigip_node import Parameters
from library.modules.bigip_node import ModuleParameters
from library.modules.bigip_node import ApiParameters
from library.modules.bigip_node import ModuleManager
from library.modules.bigip_node import ArgumentSpec
from library.module_utils.network.f5.common import F5ModuleError
@ -29,6 +31,8 @@ try:
except ImportError:
try:
from ansible.modules.network.f5.bigip_node import Parameters
from ansible.modules.network.f5.bigip_node import ModuleParameters
from ansible.modules.network.f5.bigip_node import ApiParameters
from ansible.modules.network.f5.bigip_node import ModuleManager
from ansible.modules.network.f5.bigip_node import ArgumentSpec
from ansible.module_utils.network.f5.common import F5ModuleError
@ -139,3 +143,94 @@ class TestManager(unittest.TestCase):
results = mm.exec_module()
assert results['changed'] is False
def test_create_node_fqdn(self, *args):
set_module_args(dict(
fqdn='foo.bar',
name='mytestserver',
monitors=[
'/Common/icmp'
],
partition='Common',
state='present',
password='passsword',
server='localhost',
user='admin'
))
module = AnsibleModule(
argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode
)
mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[False, True])
mm.create_on_device = Mock(return_value=True)
results = mm.exec_module()
assert results['changed'] is True
def test_update_node_fqdn_up_interval(self, *args):
set_module_args(dict(
fqdn='foo.bar',
fqdn_up_interval=100,
name='mytestserver',
monitors=[
'/Common/icmp'
],
partition='Common',
state='present',
password='passsword',
server='localhost',
user='admin'
))
current = ApiParameters(params=load_fixture('load_ltm_node_2.json'))
module = AnsibleModule(
argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode
)
mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[True, True])
mm.update_on_device = Mock(return_value=True)
mm.read_current_from_device = Mock(return_value=current)
results = mm.exec_module()
assert results['changed'] is True
def test_update_node_fqdn_up_interval_idempotent(self, *args):
set_module_args(dict(
fqdn='google.com',
fqdn_up_interval=3600,
name='fqdn-foo',
monitors=[
'icmp',
'tcp_echo'
],
partition='Common',
state='present',
password='passsword',
server='localhost',
user='admin'
))
current = ApiParameters(params=load_fixture('load_ltm_node_2.json'))
module = AnsibleModule(
argument_spec=self.spec.argument_spec,
supports_check_mode=self.spec.supports_check_mode
)
mm = ModuleManager(module=module)
# Override methods to force specific logic in the module to happen
mm.exists = Mock(side_effect=[True, True])
mm.update_on_device = Mock(return_value=True)
mm.read_current_from_device = Mock(return_value=current)
results = mm.exec_module()
assert results['changed'] is not True