Renames the security_address_list module (#44348)

Renames module and includes a symlink with the old name so that it
will still work, though will be deprecated too.
This commit is contained in:
Tim Rupp 2018-08-18 14:29:25 -04:00 committed by GitHub
parent adf3ab5e72
commit b65f05f9c0
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
3 changed files with 180 additions and 32 deletions

View file

@ -0,0 +1 @@
bigip_firewall_address_list.py

View file

@ -14,7 +14,7 @@ ANSIBLE_METADATA = {'metadata_version': '1.1',
DOCUMENTATION = r''' DOCUMENTATION = r'''
--- ---
module: bigip_security_address_list module: bigip_firewall_address_list
short_description: Manage address lists on BIG-IP AFM short_description: Manage address lists on BIG-IP AFM
description: description:
- Manages the AFM address lists on a BIG-IP. This module can be used to add - Manages the AFM address lists on a BIG-IP. This module can be used to add
@ -92,7 +92,7 @@ author:
EXAMPLES = r''' EXAMPLES = r'''
- name: Create an address list - name: Create an address list
bigip_security_address_list: bigip_firewall_address_list:
name: foo name: foo
addresses: addresses:
- 3.3.3.3 - 3.3.3.3
@ -161,6 +161,11 @@ try:
from library.module_utils.network.f5.common import cleanup_tokens 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 fq_name
from library.module_utils.network.f5.common import f5_argument_spec from library.module_utils.network.f5.common import f5_argument_spec
from library.module_utils.compat.ipaddress import ip_address
from library.module_utils.compat.ipaddress import ip_interface
from library.module_utils.network.f5.ipaddress import is_valid_ip
from library.module_utils.network.f5.ipaddress import is_valid_ip_interface
from library.module_utils.network.f5.ipaddress import is_valid_ip_network
try: try:
from library.module_utils.network.f5.common import iControlUnexpectedHTTPError from library.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
@ -173,17 +178,16 @@ except ImportError:
from ansible.module_utils.network.f5.common import cleanup_tokens 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 fq_name
from ansible.module_utils.network.f5.common import f5_argument_spec from ansible.module_utils.network.f5.common import f5_argument_spec
from ansible.module_utils.compat.ipaddress import ip_address
from ansible.module_utils.compat.ipaddress import ip_interface
from ansible.module_utils.network.f5.ipaddress import is_valid_ip
from ansible.module_utils.network.f5.ipaddress import is_valid_ip_interface
from ansible.module_utils.network.f5.ipaddress import is_valid_ip_network
try: try:
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
except ImportError: except ImportError:
HAS_F5SDK = False HAS_F5SDK = False
try:
import netaddr
HAS_NETADDR = True
except ImportError:
HAS_NETADDR = False
class Parameters(AnsibleF5Parameters): class Parameters(AnsibleF5Parameters):
api_map = { api_map = {
@ -192,17 +196,29 @@ class Parameters(AnsibleF5Parameters):
} }
api_attributes = [ api_attributes = [
'addressLists', 'addresses', 'description', 'fqdns', 'geo' 'addressLists',
'addresses',
'description',
'fqdns',
'geo',
] ]
returnables = [ returnables = [
'addresses', 'address_ranges', 'address_lists', 'description', 'addresses',
'fqdns', 'geo_locations' 'address_ranges',
'address_lists',
'description',
'fqdns',
'geo_locations',
] ]
updatables = [ updatables = [
'addresses', 'address_ranges', 'address_lists', 'description', 'addresses',
'fqdns', 'geo_locations' 'address_ranges',
'address_lists',
'description',
'fqdns',
'geo_locations',
] ]
def to_return(self): def to_return(self):
@ -524,21 +540,16 @@ class ModuleParameters(Parameters):
def addresses(self): def addresses(self):
if self._values['addresses'] is None: if self._values['addresses'] is None:
return None return None
result = []
for x in self._values['addresses']: for x in self._values['addresses']:
try: if is_valid_ip(x):
netaddr.IPAddress(x) result.append(str(ip_address(u'{0}'.format(x))))
except netaddr.core.AddrFormatError: elif is_valid_ip_interface(x):
result.append(str(ip_interface(u'{0}'.format(x))))
else:
raise F5ModuleError( raise F5ModuleError(
"Address {0} must be either an IPv4 or IPv6 address or network.".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) result = sorted(result)
return result return result
@ -552,13 +563,13 @@ class ModuleParameters(Parameters):
start = start.strip() start = start.strip()
stop = stop.strip() stop = stop.strip()
start = netaddr.IPAddress(start) start = ip_address(u'{0}'.format(start))
stop = netaddr.IPAddress(stop) stop = ip_address(u'{0}'.format(stop))
if start.version != stop.version: if start.version != stop.version:
raise F5ModuleError( raise F5ModuleError(
"When specifying a range, IP addresses must be of the same type; IPv4 or IPv6." "When specifying a range, IP addresses must be of the same type; IPv4 or IPv6."
) )
if start > stop: if int(start) > int(stop):
stop, start = start, stop stop, start = start, stop
item = '{0}-{1}'.format(str(start), str(stop)) item = '{0}-{1}'.format(str(start), str(stop))
result.append(item) result.append(item)
@ -638,13 +649,13 @@ class ReportableChanges(Changes):
start = start.strip() start = start.strip()
stop = stop.strip() stop = stop.strip()
start = netaddr.IPAddress(start) start = ip_address(u'{0}'.format(start))
stop = netaddr.IPAddress(stop) stop = ip_address(u'{0}'.format(stop))
if start.version != stop.version: if start.version != stop.version:
raise F5ModuleError( raise F5ModuleError(
"When specifying a range, IP addresses must be of the same type; IPv4 or IPv6." "When specifying a range, IP addresses must be of the same type; IPv4 or IPv6."
) )
if start > stop: if int(start) > int(stop):
stop, start = start, stop stop, start = start, stop
item = '{0}-{1}'.format(str(start), str(stop)) item = '{0}-{1}'.format(str(start), str(stop))
result.append(item) result.append(item)
@ -924,8 +935,6 @@ def main():
) )
if not HAS_F5SDK: if not HAS_F5SDK:
module.fail_json(msg="The python f5-sdk module is required") module.fail_json(msg="The python f5-sdk module is required")
if not HAS_NETADDR:
module.fail_json(msg="The python netaddr module is required")
try: try:
client = F5Client(**module.params) client = F5Client(**module.params)

View file

@ -0,0 +1,138 @@
# -*- 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 os
import json
import pytest
import sys
from nose.plugins.skip import SkipTest
if sys.version_info < (2, 7):
raise SkipTest("F5 Ansible modules require Python >= 2.7")
from ansible.compat.tests import unittest
from ansible.compat.tests.mock import Mock
from ansible.compat.tests.mock import patch
from ansible.module_utils.basic import AnsibleModule
try:
from library.modules.bigip_firewall_address_list import ApiParameters
from library.modules.bigip_firewall_address_list import ModuleParameters
from library.modules.bigip_firewall_address_list import ModuleManager
from library.modules.bigip_firewall_address_list import ArgumentSpec
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
except ImportError:
try:
from ansible.modules.network.f5.bigip_firewall_address_list import ApiParameters
from ansible.modules.network.f5.bigip_firewall_address_list import ModuleParameters
from ansible.modules.network.f5.bigip_firewall_address_list import ModuleManager
from ansible.modules.network.f5.bigip_firewall_address_list import ArgumentSpec
from ansible.module_utils.network.f5.common import F5ModuleError
from ansible.module_utils.network.f5.common import iControlUnexpectedHTTPError
from units.modules.utils import set_module_args
except ImportError:
raise SkipTest("F5 Ansible modules require the f5-sdk Python library")
fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures')
fixture_data = {}
def load_fixture(name):
path = os.path.join(fixture_path, name)
if path in fixture_data:
return fixture_data[path]
with open(path) as f:
data = f.read()
try:
data = json.loads(data)
except Exception:
pass
fixture_data[path] = data
return data
class TestParameters(unittest.TestCase):
def test_module_parameters(self):
args = dict(
name='foo',
description='this is a description',
addresses=['1.1.1.1', '2.2.2.2'],
address_ranges=['3.3.3.3-4.4.4.4', '5.5.5.5-6.6.6.6'],
address_lists=['/Common/foo', 'foo']
)
p = ModuleParameters(params=args)
assert p.name == 'foo'
assert p.description == 'this is a description'
assert len(p.addresses) == 2
assert len(p.address_ranges) == 2
assert len(p.address_lists) == 2
def test_api_parameters(self):
args = load_fixture('load_security_address_list_1.json')
p = ApiParameters(params=args)
assert len(p.addresses) == 2
assert len(p.address_ranges) == 2
assert len(p.address_lists) == 1
assert len(p.fqdns) == 1
assert len(p.geo_locations) == 5
assert sorted(p.addresses) == ['1.1.1.1', '2700:bc00:1f10:101::6']
assert sorted(p.address_ranges) == ['2.2.2.2-3.3.3.3', '5.5.5.5-6.6.6.6']
assert p.address_lists[0] == '/Common/foo'
class TestManager(unittest.TestCase):
def setUp(self):
self.spec = ArgumentSpec()
def test_create(self, *args):
set_module_args(dict(
name='foo',
description='this is a description',
addresses=['1.1.1.1', '2.2.2.2'],
address_ranges=['3.3.3.3-4.4.4.4', '5.5.5.5-6.6.6.6'],
address_lists=['/Common/foo', 'foo'],
geo_locations=[
dict(country='US', region='Los Angeles'),
dict(country='China'),
dict(country='EU')
],
fqdns=['google.com', 'mit.edu'],
password='password',
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(return_value=False)
mm.create_on_device = Mock(return_value=True)
results = mm.exec_module()
assert results['changed'] is True
assert 'addresses' in results
assert 'address_lists' in results
assert 'address_ranges' in results
assert len(results['addresses']) == 2
assert len(results['address_ranges']) == 2
assert len(results['address_lists']) == 2
assert results['description'] == 'this is a description'