summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTim Rupp <caphrim007@gmail.com>2018-04-24 19:49:52 -0700
committerGitHub <noreply@github.com>2018-04-24 19:49:52 -0700
commit256b5535ece70b76948962113c64615a9bc581d5 (patch)
treecd58bb2509dde6c86fc890ac0dbf06c3c8914891 /lib
parent39ca41eb1bf2f6c0f02df8ba19e26ca2adc414de (diff)
downloadansible-256b5535ece70b76948962113c64615a9bc581d5.tar.gz
Various fixes to F5 modules (#39255)
* Adds gnat provisioning to bigip_provision * Adds special handling for AFM in bigip_provision * Add device rebooting for provisioning as necessary * Refactored route domain module to be inline with current f5 conventions * Minor refactors across modules
Diffstat (limited to 'lib')
-rw-r--r--lib/ansible/modules/network/f5/bigip_provision.py273
-rw-r--r--lib/ansible/modules/network/f5/bigip_qkview.py16
-rw-r--r--lib/ansible/modules/network/f5/bigip_remote_syslog.py8
-rw-r--r--lib/ansible/modules/network/f5/bigip_routedomain.py762
-rw-r--r--lib/ansible/modules/network/f5/bigip_security_address_list.py28
-rw-r--r--lib/ansible/modules/network/f5/bigip_security_port_list.py20
6 files changed, 657 insertions, 450 deletions
diff --git a/lib/ansible/modules/network/f5/bigip_provision.py b/lib/ansible/modules/network/f5/bigip_provision.py
index 2a3cb350f5..23662848b0 100644
--- a/lib/ansible/modules/network/f5/bigip_provision.py
+++ b/lib/ansible/modules/network/f5/bigip_provision.py
@@ -19,9 +19,9 @@ short_description: Manage BIG-IP module provisioning
description:
- Manage BIG-IP module provisioning. This module will only provision at the
standard levels of Dedicated, Nominal, and Minimum.
-version_added: "2.4"
+version_added: 2.4
options:
- name:
+ module:
description:
- The module to provision in BIG-IP.
required: true
@@ -31,6 +31,7 @@ options:
- apm
- asm
- avr
+ - cgnat
- fps
- gtm
- ilx
@@ -41,7 +42,7 @@ options:
- swg
- vcmp
aliases:
- - module
+ - name
level:
description:
- Sets the provisioning level for the requested modules. Changing the
@@ -49,6 +50,8 @@ options:
For example, changing one module to C(dedicated) requires setting all
others to C(none). Setting the level of a module to C(none) means that
the module is not activated.
+ - This parameter is not relevant to C(cgnat) and will not be applied to the
+ C(cgnat) module.
default: nominal
choices:
- dedicated
@@ -104,49 +107,40 @@ import time
from ansible.module_utils.basic import AnsibleModule
-HAS_DEVEL_IMPORTS = False
-
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 f5_argument_spec
try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
+ from f5.bigip.contexts import TransactionContextManager
+ from f5.sdk_exception import LazyAttributesRequired
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 f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
+ from f5.bigip.contexts import TransactionContextManager
+ from f5.sdk_exception import LazyAttributesRequired
except ImportError:
HAS_F5SDK = False
-try:
- from f5.bigip.contexts import TransactionContextManager
- from f5.sdk_exception import LazyAttributesRequired
-except ImportError:
- HAS_F5SDK = False
-
class Parameters(AnsibleF5Parameters):
api_attributes = ['level']
returnables = ['level']
- updatables = ['level']
+ updatables = ['level', 'cgnat']
def to_return(self):
result = {}
@@ -162,27 +156,85 @@ class Parameters(AnsibleF5Parameters):
def level(self):
if self._values['level'] is None:
return None
+ if self.state == 'absent':
+ return 'none'
return str(self._values['level'])
+class ApiParameters(Parameters):
+ pass
+
+
+class ModuleParameters(Parameters):
+ pass
+
+
+class Changes(Parameters):
+ pass
+
+
+class UsableChanges(Parameters):
+ pass
+
+
+class ReportableChanges(Parameters):
+ 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:
+ result = self.__default(param)
+ return result
+
+ 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 cgnat(self):
+ if self.want.module == 'cgnat':
+ if self.want.state == 'absent' and self.have.enabled is True:
+ return True
+ if self.want.state == 'present' and self.have.disabled is True:
+ return True
+
+
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 = Parameters()
+ self.want = ModuleParameters(params=self.module.params)
+ self.changes = UsableChanges()
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
+ 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 = Parameters(params=changed)
+ self.changes = UsableChanges(params=changed)
return True
return False
@@ -196,7 +248,7 @@ class ModuleManager(object):
try:
if state == "present":
- changed = self.update()
+ changed = self.present()
elif state == "absent":
changed = self.absent()
except iControlUnexpectedHTTPError as e:
@@ -207,14 +259,36 @@ class ModuleManager(object):
result.update(dict(changed=changed))
return result
- def exists(self):
- provision = self.client.api.tm.sys.provision
- resource = getattr(provision, self.want.module)
- resource = resource.load()
- result = resource.attrs
- if str(result['level']) == 'none':
+ def present(self):
+ if self.exists():
return False
- return True
+ return self.update()
+
+ def exists(self):
+ if self.want.module == 'cgnat':
+ resource = self.client.api.tm.sys.feature_module.cgnat.load()
+ if resource.disabled is True:
+ return False
+ elif resource.enabled is True:
+ return True
+
+ try:
+ for x in range(0, 5):
+ provision = self.client.api.tm.sys.provision
+ resource = getattr(provision, self.want.module)
+ resource = resource.load()
+ result = resource.attrs
+ if str(result['level']) != 'none' and self.want.level == 'none':
+ return True
+ if str(result['level']) == 'none' and self.want.level == 'none':
+ return False
+ if str(result['level']) == self.want.level:
+ return True
+ return False
+ except Exception as ex:
+ if 'not registered' in str(ex):
+ return False
+ time.sleep(1)
def update(self):
self.have = self.read_current_from_device()
@@ -223,7 +297,10 @@ class ModuleManager(object):
if self.module.check_mode:
return True
- self.update_on_device()
+ result = self.update_on_device()
+ if self.want.module == 'cgnat':
+ return result
+
self._wait_for_module_provisioning()
if self.want.module == 'vcmp':
@@ -232,8 +309,55 @@ class ModuleManager(object):
if self.want.module == 'asm':
self._wait_for_asm_ready()
+ if self.want.module == 'afm':
+ self._wait_for_afm_ready()
return True
+ def should_reboot(self):
+ for x in range(0, 24):
+ try:
+ resource = self.client.api.tm.sys.dbs.db.load(name='provision.action')
+ if resource.value == 'reboot':
+ return True
+ elif resource.value == 'none':
+ time.sleep(5)
+ except Exception:
+ time.sleep(5)
+ return False
+
+ def reboot_device(self):
+ nops = 0
+ last_reboot = self._get_last_reboot()
+
+ try:
+ output = self.client.api.tm.util.bash.exec_cmd(
+ 'run',
+ utilCmdArgs='-c "/sbin/reboot"'
+ )
+ if hasattr(output, 'commandResult'):
+ return str(output.commandResult)
+ except Exception:
+ pass
+
+ # Sleep a little to let rebooting take effect
+ time.sleep(20)
+
+ while nops < 6:
+ try:
+ self.client.reconnect()
+ next_reboot = self._get_last_reboot()
+ if next_reboot is None:
+ nops = 0
+ if next_reboot == last_reboot:
+ nops = 0
+ else:
+ nops += 1
+ except Exception as ex:
+ # This can be caused by restjavad restarting.
+ pass
+ time.sleep(10)
+ return None
+
def should_update(self):
result = self._update_changed_options()
if result:
@@ -241,11 +365,22 @@ class ModuleManager(object):
return False
def update_on_device(self):
- if self.want.level == 'dedicated':
+ if self.want.module == 'cgnat':
+ if self.changes.cgnat:
+ return self.provision_cgnat_on_device()
+ return False
+ elif self.want.level == 'dedicated':
self.provision_dedicated_on_device()
else:
self.provision_non_dedicated_on_device()
+ def provision_cgnat_on_device(self):
+ resource = self.client.api.tm.sys.feature_module.cgnat.load()
+ resource.modify(
+ enabled=True
+ )
+ return True
+
def provision_dedicated_on_device(self):
params = self.want.api_params()
tx = self.client.api.tm.transactions.transaction
@@ -269,11 +404,15 @@ class ModuleManager(object):
resource.update(**params)
def read_current_from_device(self):
- provision = self.client.api.tm.sys.provision
- resource = getattr(provision, str(self.want.module))
- resource = resource.load()
- result = resource.attrs
- return Parameters(params=result)
+ if self.want.module == 'cgnat':
+ resource = self.client.api.tm.sys.feature_module.cgnat.load()
+ result = resource.attrs
+ else:
+ provision = self.client.api.tm.sys.provision
+ resource = getattr(provision, str(self.want.module))
+ resource = resource.load()
+ result = resource.attrs
+ return ApiParameters(params=result)
def absent(self):
if self.exists():
@@ -283,7 +422,9 @@ class ModuleManager(object):
def remove(self):
if self.module.check_mode:
return True
- self.remove_from_device()
+ result = self.remove_from_device()
+ if self.want.module == 'cgnat':
+ return result
self._wait_for_module_provisioning()
# For vCMP, because it has to reboot, we also wait for mcpd to become available
@@ -293,16 +434,40 @@ class ModuleManager(object):
self._wait_for_reboot()
self._wait_for_module_provisioning()
+ if self.should_reboot():
+ self.save_on_device()
+ self.reboot_device()
+ self._wait_for_module_provisioning()
+
if self.exists():
raise F5ModuleError("Failed to de-provision the module")
return True
+ def save_on_device(self):
+ command = 'tmsh save sys config'
+ self.client.api.tm.util.bash.exec_cmd(
+ 'run',
+ utilCmdArgs='-c "{0}"'.format(command)
+ )
+
def remove_from_device(self):
+ if self.want.module == 'cgnat':
+ if self.changes.cgnat:
+ return self.deprovision_cgnat_on_device()
+ return False
+
provision = self.client.api.tm.sys.provision
resource = getattr(provision, self.want.module)
resource = resource.load()
resource.update(level='none')
+ def deprovision_cgnat_on_device(self):
+ resource = self.client.api.tm.sys.feature_module.cgnat.load()
+ resource.modify(
+ disabled=True
+ )
+ return True
+
def _wait_for_module_provisioning(self):
# To prevent things from running forever, the hack is to check
# for mprov's status twice. If mprov is finished, then in most
@@ -370,6 +535,26 @@ class ModuleManager(object):
restarted_asm = True
time.sleep(5)
+ def _wait_for_afm_ready(self):
+ """Waits specifically for AFM
+
+ AFM can take longer to actually start up than all the previous checks take.
+ This check here is specifically waiting for the Security API to stop raising
+ errors.
+ :return:
+ """
+ nops = 0
+ while nops < 3:
+ try:
+ security = self.client.api.tm.security.get_collection()
+ if len(security) >= 0:
+ nops += 1
+ else:
+ nops = 0
+ except Exception as ex:
+ pass
+ time.sleep(5)
+
def _restart_asm(self):
try:
self.client.api.tm.util.bash.exec_cmd(
@@ -427,7 +612,7 @@ class ArgumentSpec(object):
choices=[
'afm', 'am', 'sam', 'asm', 'avr', 'fps',
'gtm', 'lc', 'ltm', 'pem', 'swg', 'ilx',
- 'apm', 'vcmp'
+ 'apm', 'vcmp', 'cgnat'
],
aliases=['name']
),
diff --git a/lib/ansible/modules/network/f5/bigip_qkview.py b/lib/ansible/modules/network/f5/bigip_qkview.py
index acce31c8c3..bfcd35640a 100644
--- a/lib/ansible/modules/network/f5/bigip_qkview.py
+++ b/lib/ansible/modules/network/f5/bigip_qkview.py
@@ -22,7 +22,7 @@ description:
when dealing with F5 support. It may be required that you upload this
qkview to the supported channels during resolution of an SRs that you
may have opened.
-version_added: "2.4"
+version_added: 2.4
options:
filename:
description:
@@ -46,7 +46,7 @@ options:
complete_information:
description:
- Include complete information in the qkview.
- default: yes
+ default: no
type: bool
exclude_core:
description:
@@ -105,30 +105,23 @@ from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import string_types
from distutils.version import LooseVersion
-HAS_DEVEL_IMPORTS = False
-
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 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 f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@@ -434,7 +427,10 @@ class ArgumentSpec(object):
type='bool'
),
exclude=dict(
- type='list'
+ type='list',
+ choices=[
+ 'all', 'audit', 'secure', 'bash_history'
+ ]
),
dest=dict(
type='path',
diff --git a/lib/ansible/modules/network/f5/bigip_remote_syslog.py b/lib/ansible/modules/network/f5/bigip_remote_syslog.py
index fac67ba99c..6f189bcdc0 100644
--- a/lib/ansible/modules/network/f5/bigip_remote_syslog.py
+++ b/lib/ansible/modules/network/f5/bigip_remote_syslog.py
@@ -13,6 +13,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
'supported_by': 'community'}
DOCUMENTATION = r'''
+---
module: bigip_remote_syslog
short_description: Manipulate remote syslog settings on a BIG-IP
description:
@@ -93,30 +94,23 @@ import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.six import iteritems
-HAS_DEVEL_IMPORTS = False
-
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 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 f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
diff --git a/lib/ansible/modules/network/f5/bigip_routedomain.py b/lib/ansible/modules/network/f5/bigip_routedomain.py
index 9274bbe60d..2f19cd51bc 100644
--- a/lib/ansible/modules/network/f5/bigip_routedomain.py
+++ b/lib/ansible/modules/network/f5/bigip_routedomain.py
@@ -18,13 +18,11 @@ module: bigip_routedomain
short_description: Manage route domains on a BIG-IP
description:
- Manage route domains on a BIG-IP.
-version_added: "2.2"
+version_added: 2.2
options:
name:
description:
- The name of the route domain.
- - When creating a new route domain, if this value is not specified, then the
- value of C(id) will be used for it.
version_added: 2.5
bwc_policy:
description:
@@ -51,8 +49,8 @@ options:
become a required parameter.
parent:
description:
- Specifies the route domain the system searches when it cannot
- find a route in the configured domain.
+ - Specifies the route domain the system searches when it cannot
+ find a route in the configured domain.
partition:
description:
- Partition to create the route domain on. Partitions cannot be updated
@@ -83,14 +81,11 @@ options:
- absent
strict:
description:
- - Specifies whether the system enforces cross-routing restrictions
- or not.
- choices:
- - enabled
- - disabled
+ - Specifies whether the system enforces cross-routing restrictions or not.
+ type: bool
vlans:
description:
- - VLANs for the system to use in the route domain
+ - VLANs for the system to use in the route domain.
extends_documentation_fragment: f5
author:
- Tim Rupp (@caphrim007)
@@ -122,82 +117,79 @@ EXAMPLES = r'''
RETURN = r'''
id:
- description: The ID of the route domain that was changed
+ description: The ID of the route domain that was changed.
returned: changed
type: int
sample: 2
description:
- description: The description of the route domain
+ description: The description of the route domain.
returned: changed
type: string
sample: route domain foo
strict:
- description: The new strict isolation setting
+ description: The new strict isolation setting.
returned: changed
type: string
sample: enabled
parent:
- description: The new parent route domain
+ description: The new parent route domain.
returned: changed
type: int
sample: 0
vlans:
- description: List of new VLANs the route domain is applied to
+ description: List of new VLANs the route domain is applied to.
returned: changed
type: list
sample: ['/Common/http-tunnel', '/Common/socks-tunnel']
routing_protocol:
- description: List of routing protocols applied to the route domain
+ description: List of routing protocols applied to the route domain.
returned: changed
type: list
sample: ['bfd', 'bgp']
bwc_policy:
- description: The new bandwidth controller
+ description: The new bandwidth controller.
returned: changed
type: string
sample: /Common/foo
connection_limit:
- description: The new connection limit for the route domain
+ description: The new connection limit for the route domain.
returned: changed
type: int
sample: 100
flow_eviction_policy:
- description: The new eviction policy to use with this route domain
+ description: The new eviction policy to use with this route domain.
returned: changed
type: string
sample: /Common/default-eviction-policy
service_policy:
- description: The new service policy to use with this route domain
+ description: The new service policy to use with this route domain.
returned: changed
type: string
sample: /Common-my-service-policy
'''
-try:
- from f5.bigip import ManagementRoot
-except ImportError:
- pass # Handled via f5_utils.HAS_F5SDK
-
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
-from ansible.module_utils.ec2 import camel_dict_to_snake_dict
-
-HAS_DEVEL_IMPORTS = False
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 fq_name
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 fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@@ -205,375 +197,429 @@ except ImportError:
HAS_F5SDK = False
-PROTOCOLS = [
- 'BFD', 'BGP', 'IS-IS', 'OSPFv2', 'OSPFv3', 'PIM', 'RIP', 'RIPng'
-]
+class Parameters(AnsibleF5Parameters):
+ api_map = {
+ 'connectionLimit': 'connection_limit',
+ 'servicePolicy': 'service_policy',
+ 'bwcPolicy': 'bwc_policy',
+ 'flowEvictionPolicy': 'flow_eviction_policy',
+ 'routingProtocol': 'routing_protocol'
+ }
+
+ api_attributes = [
+ 'connectionLimit',
+ 'description',
+ 'strict',
+ 'parent',
+ 'servicePolicy',
+ 'bwcPolicy',
+ 'flowEvictionPolicy',
+ 'routingProtocol',
+ 'vlans',
+ 'id'
+ ]
+
+ returnables = [
+ 'description',
+ 'strict',
+ 'parent',
+ 'service_policy',
+ 'bwc_policy',
+ 'flow_eviction_policy',
+ 'routing_protocol',
+ 'vlans',
+ 'connection_limit',
+ 'id'
+ ]
+
+ updatables = [
+ 'description',
+ 'strict',
+ 'parent',
+ 'service_policy',
+ 'bwc_policy',
+ 'flow_eviction_policy',
+ 'routing_protocol',
+ 'vlans',
+ 'connection_limit',
+ 'id'
+ ]
+
+ @property
+ def connection_limit(self):
+ if self._values['connection_limit'] is None:
+ return None
+ return int(self._values['connection_limit'])
+
+ @property
+ def id(self):
+ if self._values['id'] is None:
+ return None
+ return int(self._values['id'])
+
+
+class ApiParameters(Parameters):
+ @property
+ def strict(self):
+ if self._values['strict'] is None:
+ return None
+ if self._values['strict'] == 'enabled':
+ return True
+ return False
-STRICTS = ['enabled', 'disabled']
+ @property
+ def domains(self):
+ domains = self.read_domains_from_device()
+ result = [x.fullPath for x in domains]
+ return result
+ def read_domains_from_device(self):
+ collection = self.client.api.tm.net.route_domains.get_collection()
+ return collection
+
+
+class ModuleParameters(Parameters):
+ @property
+ def bwc_policy(self):
+ if self._values['bwc_policy'] is None:
+ return None
+ return fq_name(self.partition, self._values['bwc_policy'])
+
+ @property
+ def flow_eviction_policy(self):
+ if self._values['flow_eviction_policy'] is None:
+ return None
+ return fq_name(self.partition, self._values['flow_eviction_policy'])
+
+ @property
+ def service_policy(self):
+ if self._values['service_policy'] is None:
+ return None
+ return fq_name(self.partition, self._values['service_policy'])
+
+ @property
+ def parent(self):
+ if self._values['parent'] is None:
+ return None
+ result = fq_name(self.partition, self._values['parent'])
+ return result
-class BigIpRouteDomain(object):
- def __init__(self, *args, **kwargs):
- if not HAS_F5SDK:
- raise F5ModuleError("The python f5-sdk module is required")
+ @property
+ def vlans(self):
+ if self._values['vlans'] is None:
+ return None
+ if len(self._values['vlans']) == 1 and self._values['vlans'][0] == '':
+ return ''
+ return [fq_name(self.partition, x) for x in self._values['vlans']]
+
+ @property
+ def name(self):
+ if self._values['name'] is None:
+ return str(self.id)
+ return self._values['name']
+
+ @property
+ def routing_protocol(self):
+ if self._values['routing_protocol'] is None:
+ return None
+ if len(self._values['routing_protocol']) == 1 and self._values['routing_protocol'][0] == '':
+ return ''
+ return self._values['routing_protocol']
+
+
+class Changes(Parameters):
+ def to_return(self):
+ result = {}
+ try:
+ for returnable in self.returnables:
+ result[returnable] = getattr(self, returnable)
+ result = self._filter_params(result)
+ except Exception:
+ pass
+ return result
- # The params that change in the module
- self.cparams = dict()
- # Stores the params that are sent to the module
- self.params = kwargs
- self.api = ManagementRoot(kwargs['server'],
- kwargs['user'],
- kwargs['password'],
- port=kwargs['server_port'],
- token=True)
+class UsableChanges(Changes):
+ @property
+ def strict(self):
+ if self._values['strict'] is None:
+ return None
+ if self._values['strict']:
+ return 'enabled'
+ return 'disabled'
- def absent(self):
- if not self.exists():
- return False
- if self.params['check_mode']:
- return True
+class ReportableChanges(Changes):
+ @property
+ def strict(self):
+ if self._values['strict'] is None:
+ return None
+ if self._values['strict'] == 'enabled':
+ return 'yes'
+ return 'no'
- if self.params['name'] is None:
- self.params['name'] = str(self.params['id'])
- rd = self.api.tm.net.route_domains.route_domain.load(
- name=self.params['name'],
- partition=self.params['partition']
- )
- rd.delete()
+class Difference(object):
+ def __init__(self, want, have=None):
+ self.want = want
+ self.have = have
- if self.exists():
- raise F5ModuleError("Failed to delete the route domain")
- else:
+ 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 routing_protocol(self):
+ if self.want.routing_protocol is None:
+ return None
+ if self.want.routing_protocol == '' and self.have.routing_protocol is None:
+ return None
+ if self.want.routing_protocol == '' and len(self.have.routing_protocol) > 0:
+ return []
+ if self.have.routing_protocol is None:
+ return self.want.routing_protocol
+ want = set(self.want.routing_protocol)
+ have = set(self.have.routing_protocol)
+ if want != have:
+ return list(want)
+
+ @property
+ def vlans(self):
+ if self.want.vlans is None:
+ return None
+ if self.want.vlans == '' and self.have.vlans is None:
+ return None
+ if self.want.vlans == '' and len(self.have.vlans) > 0:
+ return []
+ if self.have.vlans is None:
+ return self.want.vlans
+ want = set(self.want.vlans)
+ have = set(self.have.vlans)
+ if want != have:
+ return list(want)
+
+
+class ModuleManager(object):
+ def __init__(self, *args, **kwargs):
+ self.module = kwargs.get('module', None)
+ self.client = kwargs.get('client', None)
+ self.want = ModuleParameters(params=self.module.params, client=self.client)
+ self.have = ApiParameters(client=self.client)
+ self.changes = UsableChanges()
+
+ def _set_changed_options(self):
+ changed = {}
+ for key in Parameters.returnables:
+ if getattr(self.want, key) is not None:
+ changed[key] = getattr(self.want, key)
+ if changed:
+ self.changes = UsableChanges(params=changed)
+
+ def _update_changed_options(self):
+ 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 = UsableChanges(params=changed)
return True
+ return False
+
+ def should_update(self):
+ result = self._update_changed_options()
+ if result:
+ return True
+ return False
+
+ def exec_module(self):
+ changed = False
+ result = dict()
+ state = self.want.state
+
+ try:
+ if state == "present":
+ changed = self.present()
+ elif state == "absent":
+ changed = self.absent()
+ except iControlUnexpectedHTTPError as e:
+ raise F5ModuleError(str(e))
+
+ 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 _announce_deprecations(self, result):
+ warnings = result.pop('__warnings', [])
+ for warning in warnings:
+ self.client.module.deprecate(
+ msg=warning['msg'],
+ version=warning['version']
+ )
def present(self):
if self.exists():
return self.update()
else:
- if self.params['check_mode']:
- return True
return self.create()
- def read(self):
- """Read information and transform it
-
- The values that are returned by BIG-IP in the f5-sdk can have encoding
- attached to them as well as be completely missing in some cases.
-
- Therefore, this method will transform the data from the BIG-IP into a
- format that is more easily consumable by the rest of the class and the
- parameters that are supported by the module.
- """
- p = dict()
-
- if self.params['name'] is None:
- self.params['name'] = str(self.params['id'])
-
- r = self.api.tm.net.route_domains.route_domain.load(
- name=self.params['name'],
- partition=self.params['partition']
+ def exists(self):
+ result = self.client.api.tm.net.route_domains.route_domain.exists(
+ name=self.want.name,
+ partition=self.want.partition
)
+ return result
- p['id'] = int(r.id)
- p['name'] = str(r.name)
-
- if hasattr(r, 'connectionLimit'):
- p['connection_limit'] = int(r.connectionLimit)
- if hasattr(r, 'description'):
- p['description'] = str(r.description)
- if hasattr(r, 'strict'):
- p['strict'] = str(r.strict)
- if hasattr(r, 'parent'):
- p['parent'] = r.parent
- if hasattr(r, 'vlans'):
- p['vlans'] = list(set([str(x) for x in r.vlans]))
- if hasattr(r, 'routingProtocol'):
- p['routing_protocol'] = list(set([str(x) for x in r.routingProtocol]))
- if hasattr(r, 'flowEvictionPolicy'):
- p['flow_eviction_policy'] = str(r.flowEvictionPolicy)
- if hasattr(r, 'bwcPolicy'):
- p['bwc_policy'] = str(r.bwcPolicy)
- if hasattr(r, 'servicePolicy'):
- p['service_policy'] = str(r.servicePolicy)
- return p
+ def update(self):
+ self.have = self.read_current_from_device()
+ if not self.should_update():
+ return False
+ if self.want.parent and self.want.parent not in self.have.domains:
+ raise F5ModuleError(
+ "The parent route domain was not found."
+ )
+ if self.module.check_mode:
+ return True
+ self.update_on_device()
+ return True
- def domains(self):
- result = []
-
- domains = self.api.tm.net.route_domains.get_collection()
- for domain in domains:
- # Just checking for the addition of the partition here for
- # different versions of BIG-IP
- if '/' + self.params['partition'] + '/' in domain.name:
- result.append(domain.name)
- else:
- full_name = '/%s/%s' % (self.params['partition'], domain.name)
- result.append(full_name)
- return result
+ def remove(self):
+ if self.module.check_mode:
+ return True
+ self.remove_from_device()
+ if self.exists():
+ raise F5ModuleError("Failed to delete the resource.")
+ return True
def create(self):
- params = dict()
- params['id'] = self.params['id']
- params['name'] = self.params['name']
- params['partition'] = self.params['partition']
-
- if params['name'] is None:
- self.params['name'] = str(self.params['id'])
- elif params['id'] is None:
+ if self.want.id is None:
raise F5ModuleError(
"The 'id' parameter is required when creating new route domains."
)
-
- partition = self.params['partition']
- description = self.params['description']
- strict = self.params['strict']
- parent = self.params['parent']
- bwc_policy = self.params['bwc_policy']
- vlans = self.params['vlans']
- routing_protocol = self.params['routing_protocol']
- connection_limit = self.params['connection_limit']
- flow_eviction_policy = self.params['flow_eviction_policy']
- service_policy = self.params['service_policy']
-
- if description is not None:
- params['description'] = description
-
- if strict is not None:
- params['strict'] = strict
-
- if parent is not None:
- parent = '/%s/%s' % (partition, parent)
- if parent in self.domains():
- params['parent'] = parent
- else:
- raise F5ModuleError(
- "The parent route domain was not found"
- )
-
- if bwc_policy is not None:
- policy = '/%s/%s' % (partition, bwc_policy)
- params['bwcPolicy'] = policy
-
- if vlans is not None:
- params['vlans'] = []
- for vlan in vlans:
- vname = '/%s/%s' % (partition, vlan)
- params['vlans'].append(vname)
-
- if routing_protocol is not None:
- params['routingProtocol'] = []
- for protocol in routing_protocol:
- if protocol in PROTOCOLS:
- params['routingProtocol'].append(protocol)
- else:
- raise F5ModuleError(
- "routing_protocol must be one of: %s" % (PROTOCOLS)
- )
-
- if connection_limit is not None:
- params['connectionLimit'] = connection_limit
-
- if flow_eviction_policy is not None:
- policy = '/%s/%s' % (partition, flow_eviction_policy)
- params['flowEvictionPolicy'] = policy
-
- if service_policy is not None:
- policy = '/%s/%s' % (partition, service_policy)
- params['servicePolicy'] = policy
-
- self.api.tm.net.route_domains.route_domain.create(**params)
- exists = self.api.tm.net.route_domains.route_domain.exists(
- name=self.params['name'],
- partition=self.params['partition']
- )
-
- if exists:
- return True
- else:
+ if self.want.parent and self.want.parent not in self.have.domains:
raise F5ModuleError(
- "An error occurred while creating the route domain"
+ "The parent route domain was not found."
)
+ self._set_changed_options()
+ if self.module.check_mode:
+ return True
+ self.create_on_device()
+ return True
- def update(self):
- changed = False
- params = dict()
- current = self.read()
-
- if self.params['name'] is None:
- self.params['name'] = str(self.params['id'])
-
- check_mode = self.params['check_mode']
- partition = self.params['partition']
- description = self.params['description']
- strict = self.params['strict']
- parent = self.params['parent']
- bwc_policy = self.params['bwc_policy']
- vlans = self.params['vlans']
- routing_protocol = self.params['routing_protocol']
- connection_limit = self.params['connection_limit']
- flow_eviction_policy = self.params['flow_eviction_policy']
- service_policy = self.params['service_policy']
-
- if description is not None:
- if 'description' in current:
- if description != current['description']:
- params['description'] = description
- else:
- params['description'] = description
-
- if strict is not None:
- if strict != current['strict']:
- params['strict'] = strict
-
- if parent is not None:
- parent = '/%s/%s' % (partition, parent)
- if 'parent' in current:
- if parent != current['parent']:
- params['parent'] = parent
- else:
- params['parent'] = parent
-
- if bwc_policy is not None:
- policy = '/%s/%s' % (partition, bwc_policy)
- if 'bwc_policy' in current:
- if policy != current['bwc_policy']:
- params['bwcPolicy'] = policy
- else:
- params['bwcPolicy'] = policy
-
- if vlans is not None:
- tmp = set()
- for vlan in vlans:
- vname = '/%s/%s' % (partition, vlan)
- tmp.add(vname)
- tmp = list(tmp)
- if 'vlans' in current:
- if tmp != current['vlans']:
- params['vlans'] = tmp
- else:
- params['vlans'] = tmp
-
- if routing_protocol is not None:
- tmp = set()
- for protocol in routing_protocol:
- if protocol in PROTOCOLS:
- tmp.add(protocol)
- else:
- raise F5ModuleError(
- "routing_protocol must be one of: %s" % (PROTOCOLS)
- )
- tmp = list(tmp)
- if 'routing_protocol' in current:
- if tmp != current['routing_protocol']:
- params['routingProtocol'] = tmp
- else:
- params['routingProtocol'] = tmp
-
- if connection_limit is not None:
- if connection_limit != current['connection_limit']:
- params['connectionLimit'] = connection_limit
+ def create_on_device(self):
+ params = self.changes.api_params()
+ self.client.api.tm.net.route_domains.route_domain.create(
+ name=self.want.name,
+ partition=self.want.partition,
+ **params
+ )
- if flow_eviction_policy is not None:
- policy = '/%s/%s' % (partition, flow_eviction_policy)
- if 'flow_eviction_policy' in current:
- if policy != current['flow_eviction_policy']:
- params['flowEvictionPolicy'] = policy
- else:
- params['flowEvictionPolicy'] = policy
+ def update_on_device(self):
+ params = self.changes.api_params()
+ resource = self.client.api.tm.net.route_domains.route_domain.load(
+ name=self.want.name,
+ partition=self.want.partition
+ )
+ resource.modify(**params)
- if service_policy is not None:
- policy = '/%s/%s' % (partition, service_policy)
- if 'service_policy' in current:
- if policy != current['service_policy']:
- params['servicePolicy'] = policy
- else:
- params['servicePolicy'] = policy
+ def absent(self):
+ if self.exists():
+ return self.remove()
+ return False
- if params:
- changed = True
- self.cparams = camel_dict_to_snake_dict(params)
- if check_mode:
- return changed
- else:
- return changed
+ def remove_from_device(self):
+ resource = self.client.api.tm.net.route_domains.route_domain.load(
+ name=self.want.name,
+ partition=self.want.partition
+ )
+ if resource:
+ resource.delete()
- try:
- rd = self.api.tm.net.route_domains.route_domain.load(
- name=self.params['name'],
- partition=self.params['partition']
+ def read_current_from_device(self):
+ resource = self.client.api.tm.net.route_domains.route_domain.load(
+ name=self.want.name,
+ partition=self.want.partition
+ )
+ result = resource.attrs
+ return ApiParameters(params=result, client=self.client)
+
+
+class ArgumentSpec(object):
+ def __init__(self):
+ self.supports_check_mode = True
+ argument_spec = dict(
+ name=dict(),
+ id=dict(type='int'),
+ description=dict(),
+ strict=dict(type='bool'),
+ parent=dict(type='int'),
+ vlans=dict(type='list'),
+ routing_protocol=dict(
+ type='list',
+ choices=['BFD', 'BGP', 'IS-IS', 'OSPFv2', 'OSPFv3', 'PIM', 'RIP', 'RIPng']
+ ),
+ bwc_policy=dict(),
+ connection_limit=dict(type='int'),
+ flow_eviction_policy=dict(),
+ service_policy=dict(),
+ partition=dict(
+ default='Common',
+ fallback=(env_fallback, ['F5_PARTITION'])
+ ),
+ state=dict(
+ default='present',
+ choices=['present', 'absent']
)
- rd.update(**params)
- rd.refresh()
- except iControlUnexpectedHTTPError as e:
- raise F5ModuleError(e)
-
- return True
-
- def exists(self):
- if self.params['name'] is None:
- self.params['name'] = str(self.params['id'])
- return self.api.tm.net.route_domains.route_domain.exists(
- name=self.params['name'],
- partition=self.params['partition']
)
-
- def exec_module(self):
- result = dict()
- state = self.params['state']
-
- if state == "present":
- changed = self.present()
- current = self.read()
- result.update(current)
- elif state == "absent":
- changed = self.absent()
-
- result.update(dict(changed=changed))
- return result
+ self.argument_spec = {}
+ self.argument_spec.update(f5_argument_spec)
+ self.argument_spec.update(argument_spec)
+ self.required_one_of = [
+ ['name', 'id']
+ ]
def main():
- argument_spec = f5_argument_spec
-
- meta_args = dict(
- name=dict(),
- id=dict(type='int'),
- description=dict(),
- strict=dict(choices=STRICTS),
- parent=dict(type='int'),
- vlans=dict(type='list'),
- routing_protocol=dict(type='list'),
- bwc_policy=dict(),
- connection_limit=dict(type='int',),
- flow_eviction_policy=dict(),
- service_policy=dict(),
- partition=dict(
- default='Common',
- fallback=(env_fallback, ['F5_PARTITION'])
- ),
- state=dict(
- default='present',
- choices=['present', 'absent']
- )
- )
- argument_spec.update(meta_args)
+ spec = ArgumentSpec()
module = AnsibleModule(
- argument_spec=argument_spec,
- supports_check_mode=True,
- required_one_of=[['name', 'id']]
+ 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")
try:
- obj = BigIpRouteDomain(check_mode=module.check_mode, **module.params)
- result = obj.exec_module()
-
- module.exit_json(**result)
- except F5ModuleError as e:
- module.fail_json(msg=str(e))
+ client = F5Client(**module.params)
+ mm = ModuleManager(module=module, client=client)
+ results = mm.exec_module()
+ cleanup_tokens(client)
+ module.exit_json(**results)
+ except F5ModuleError as ex:
+ cleanup_tokens(client)
+ module.fail_json(msg=str(ex))
if __name__ == '__main__':
diff --git a/lib/ansible/modules/network/f5/bigip_security_address_list.py b/lib/ansible/modules/network/f5/bigip_security_address_list.py
index 020c2b6620..123a554a86 100644
--- a/lib/ansible/modules/network/f5/bigip_security_address_list.py
+++ b/lib/ansible/modules/network/f5/bigip_security_address_list.py
@@ -19,7 +19,7 @@ short_description: Manage address lists on BIG-IP AFM
description:
- Manages the AFM address lists on a BIG-IP. This module can be used to add
and remove address list entries.
-version_added: "2.5"
+version_added: 2.5
options:
name:
description:
@@ -54,6 +54,7 @@ options:
- Individual addresses that you want to add to the list. These addresses differ
from ranges, and lists of lists such as what can be used in C(address_ranges)
and C(address_lists) respectively.
+ - This list can also include networks that have CIDR notation.
address_ranges:
description:
- A list of address ranges where the range starts with a port number, is followed
@@ -152,30 +153,25 @@ import re
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
-HAS_DEVEL_IMPORTS = False
-
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 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 f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@@ -219,11 +215,6 @@ class Parameters(AnsibleF5Parameters):
pass
return result
- def _fqdn_name(self, value):
- if value is not None and not value.startswith('/'):
- return '/{0}/{1}'.format(self.partition, value)
- return value
-
class ApiParameters(Parameters):
@property
@@ -538,8 +529,15 @@ class ModuleParameters(Parameters):
netaddr.IPAddress(x)
except netaddr.core.AddrFormatError:
raise F5ModuleError(
- "Address {0} must be either an IPv4 or IPv6 address".format(x)
+ "Address {0} must be either an IPv4 or IPv6 address or network.".format(x)
)
+ except ValueError:
+ try:
+ netaddr.IPNetwork(x)
+ except netaddr.core.AddrFormatError:
+ raise F5ModuleError(
+ "Address {0} must be either an IPv4 or IPv6 address or network.".format(x)
+ )
result = [str(x) for x in self._values['addresses']]
result = sorted(result)
return result
@@ -573,7 +571,7 @@ class ModuleParameters(Parameters):
return None
result = []
for x in self._values['address_lists']:
- item = self._fqdn_name(x)
+ item = fq_name(self.partition, x)
result.append(item)
result = sorted(result)
return result
diff --git a/lib/ansible/modules/network/f5/bigip_security_port_list.py b/lib/ansible/modules/network/f5/bigip_security_port_list.py
index 395d768825..30e26c44c4 100644
--- a/lib/ansible/modules/network/f5/bigip_security_port_list.py
+++ b/lib/ansible/modules/network/f5/bigip_security_port_list.py
@@ -19,7 +19,7 @@ short_description: Manage port lists on BIG-IP AFM
description:
- Manages the AFM port lists on a BIG-IP. This module can be used to add
and remove port list entries.
-version_added: "2.5"
+version_added: 2.5
options:
name:
description:
@@ -29,7 +29,6 @@ options:
description:
- Device partition to manage resources on.
default: Common
- version_added: 2.5
description:
description:
- Description of the port list
@@ -56,7 +55,6 @@ options:
choices:
- present
- absent
- version_added: 2.5
extends_documentation_fragment: f5
author:
- Tim Rupp (@caphrim007)
@@ -163,30 +161,25 @@ port_lists:
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.basic import env_fallback
-HAS_DEVEL_IMPORTS = False
-
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 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 f5_argument_spec
try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
@@ -211,11 +204,6 @@ class Parameters(AnsibleF5Parameters):
'description', 'ports', 'port_ranges', 'port_lists'
]
- def _fqdn_name(self, value):
- if value is not None and not value.startswith('/'):
- return '/{0}/{1}'.format(self.partition, value)
- return value
-
class ApiParameters(Parameters):
@property
@@ -296,7 +284,7 @@ class ModuleParameters(Parameters):
return None
result = []
for x in self._values['port_lists']:
- item = self._fqdn_name(x)
+ item = fq_name(self.partition, x)
result.append(item)
return result