From 1e4dab822bf2087d37d4fbfac8db3fe94f8bb6c2 Mon Sep 17 00:00:00 2001 From: Wojciech Wypior Date: Tue, 19 Mar 2019 07:13:06 +0100 Subject: [PATCH] BIGIP: Bugfix.bigiqapplication (#53986) * adds function to do version checks for bigiq * adds version limitation to bigiq application modules Refactors main() function and module manager in multiple modules in line with recent changes Adds variable types to docs Refactors unit tests to remove deprecated parameters --- .../network/f5/bigiq_application_fasthttp.py | 40 ++++++--- .../f5/bigiq_application_fastl4_tcp.py | 39 ++++++--- .../f5/bigiq_application_fastl4_udp.py | 39 ++++++--- .../network/f5/bigiq_application_http.py | 40 ++++++--- .../f5/bigiq_application_https_offload.py | 52 +++++++++--- .../network/f5/bigiq_application_https_waf.py | 55 +++++++++--- .../f5/test_bigiq_application_fasthttp.py | 80 +++++++++++++++++- .../f5/test_bigiq_application_fastl4_tcp.py | 73 +++++++++++++++- .../f5/test_bigiq_application_fastl4_udp.py | 73 +++++++++++++++- .../network/f5/test_bigiq_application_http.py | 80 +++++++++++++++++- .../test_bigiq_application_https_offload.py | 84 ++++++++++++++++++- .../f5/test_bigiq_application_https_waf.py | 84 ++++++++++++++++++- 12 files changed, 659 insertions(+), 80 deletions(-) diff --git a/lib/ansible/modules/network/f5/bigiq_application_fasthttp.py b/lib/ansible/modules/network/f5/bigiq_application_fasthttp.py index 8c3ba0e9af..3211b1abfc 100644 --- a/lib/ansible/modules/network/f5/bigiq_application_fasthttp.py +++ b/lib/ansible/modules/network/f5/bigiq_application_fasthttp.py @@ -24,10 +24,12 @@ options: name: description: - Name of the new application. + type: str required: True description: description: - Description of the application. + type: str servers: description: - A list of servers that the application is hosted on. @@ -38,13 +40,16 @@ options: address: description: - The IP address of the server. + type: str required: True port: description: - The port of the server. - When creating a new application and specifying a server, if this parameter is not provided, the default of C(80) will be used. + type: str default: 80 + type: list inbound_virtual: description: - Settings to configure the virtual which will receive the inbound connection. @@ -55,18 +60,22 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str required: True netmask: description: - Specifies the netmask to associate with the given C(destination). - This parameter is required when creating a new application. + type: str required: True port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(80) will be used. + type: str default: 80 + type: dict service_environment: description: - Specifies the name of service environment that the application will be @@ -75,6 +84,7 @@ options: - The service environment type will be discovered by this module automatically. Therefore, it is crucial that you maintain unique names for items in the different service environment types (at this time, SSGs and BIGIPs). + type: str add_analytics: description: - Collects statistics of the BIG-IP that the application is deployed to. @@ -87,10 +97,11 @@ options: - The state of the resource on the system. - When C(present), guarantees that the resource exists with the provided attributes. - When C(absent), removes the resource from the system. - default: present + type: str choices: - absent - present + default: present wait: description: - If the module should wait for the application to be created, deleted or updated. @@ -101,7 +112,7 @@ notes: - This module does not support updating of your application (whether deployed or not). If you need to update the application, the recommended practice is to remove and re-create. - - Requires BIG-IQ version 6.0 or greater. + - This module will not work on BIGIQ version 6.1.x or greater. author: - Tim Rupp (@caphrim007) ''' @@ -176,6 +187,7 @@ servers: import time +from distutils.version import LooseVersion from ansible.module_utils.basic import AnsibleModule try: @@ -183,17 +195,15 @@ try: 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 f5_argument_spec - from library.module_utils.network.f5.common import exit_json - from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.ipaddress import is_valid_ip + from library.module_utils.network.f5.icontrol import bigiq_version except ImportError: from ansible.module_utils.network.f5.bigiq import F5RestClient 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 f5_argument_spec - from ansible.module_utils.network.f5.common import exit_json - from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.ipaddress import is_valid_ip + from ansible.module_utils.network.f5.icontrol import bigiq_version class Parameters(AnsibleF5Parameters): @@ -483,7 +493,7 @@ class Difference(object): class ModuleManager(object): def __init__(self, *args, **kwargs): self.module = kwargs.get('module', None) - self.client = kwargs.get('client', None) + self.client = F5RestClient(**self.module.params) self.want = ModuleParameters(params=self.module.params) self.want.client = self.client self.have = ApiParameters() @@ -521,7 +531,15 @@ class ModuleManager(object): return True return False + def check_bigiq_version(self): + version = bigiq_version(self.client) + if LooseVersion(version) >= LooseVersion('6.1.0'): + raise F5ModuleError( + 'Module supports only BIGIQ version 6.0.x or lower.' + ) + def exec_module(self): + self.check_bigiq_version() changed = False result = dict() state = self.want.state @@ -726,14 +744,12 @@ def main(): supports_check_mode=spec.supports_check_mode ) - client = F5RestClient(**module.params) - try: - mm = ModuleManager(module=module, client=client) + mm = ModuleManager(module=module) results = mm.exec_module() - exit_json(module, results, client) + module.exit_json(**results) except F5ModuleError as ex: - fail_json(module, ex, client) + module.fail_json(msg=str(ex)) if __name__ == '__main__': diff --git a/lib/ansible/modules/network/f5/bigiq_application_fastl4_tcp.py b/lib/ansible/modules/network/f5/bigiq_application_fastl4_tcp.py index 4119067d0a..aa176d8e06 100644 --- a/lib/ansible/modules/network/f5/bigiq_application_fastl4_tcp.py +++ b/lib/ansible/modules/network/f5/bigiq_application_fastl4_tcp.py @@ -24,10 +24,12 @@ options: name: description: - Name of the new application. + type: str required: True description: description: - Description of the application. + type: str servers: description: - A list of servers that the application is hosted on. @@ -38,13 +40,16 @@ options: address: description: - The IP address of the server. + type: str required: True port: description: - The port of the server. - When creating a new application and specifying a server, if this parameter is not provided, the default of C(8000) will be used. + type: str default: 8000 + type: list inbound_virtual: description: - Settings to configure the virtual which will receive the inbound connection. @@ -54,11 +59,13 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str required: True netmask: description: - Specifies the netmask to associate with the given C(destination). - This parameter is required when creating a new application. + type: str required: True port: description: @@ -66,6 +73,7 @@ options: - When creating a new application, if this parameter is not specified, the default value of C(8080) will be used. default: 8080 + type: dict service_environment: description: - Specifies the name of service environment that the application will be @@ -75,6 +83,7 @@ options: Therefore, it is crucial that you maintain unique names for items in the different service environment types. - SSGs are not supported for this type of application. + type: str add_analytics: description: - Collects statistics of the BIG-IP that the application is deployed to. @@ -87,10 +96,11 @@ options: - The state of the resource on the system. - When C(present), guarantees that the resource exists with the provided attributes. - When C(absent), removes the resource from the system. - default: present + type: str choices: - absent - present + default: present wait: description: - If the module should wait for the application to be created, deleted or updated. @@ -101,7 +111,7 @@ notes: - This module does not support updating of your application (whether deployed or not). If you need to update the application, the recommended practice is to remove and re-create. - - Requires BIG-IQ version 6.0 or greater. + - This module will not work on BIGIQ version 6.1.x or greater. author: - Tim Rupp (@caphrim007) ''' @@ -176,6 +186,7 @@ servers: import time +from distutils.version import LooseVersion from ansible.module_utils.basic import AnsibleModule try: @@ -183,17 +194,15 @@ try: 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 f5_argument_spec - from library.module_utils.network.f5.common import exit_json - from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.ipaddress import is_valid_ip + from library.module_utils.network.f5.icontrol import bigiq_version except ImportError: from ansible.module_utils.network.f5.bigiq import F5RestClient 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 f5_argument_spec - from ansible.module_utils.network.f5.common import exit_json - from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.ipaddress import is_valid_ip + from ansible.module_utils.network.f5.icontrol import bigiq_version class Parameters(AnsibleF5Parameters): @@ -440,7 +449,7 @@ class Difference(object): class ModuleManager(object): def __init__(self, *args, **kwargs): self.module = kwargs.get('module', None) - self.client = kwargs.get('client', None) + self.client = F5RestClient(**self.module.params) self.want = ModuleParameters(params=self.module.params) self.want.client = self.client self.have = ApiParameters() @@ -478,7 +487,15 @@ class ModuleManager(object): return True return False + def check_bigiq_version(self): + version = bigiq_version(self.client) + if LooseVersion(version) >= LooseVersion('6.1.0'): + raise F5ModuleError( + 'Module supports only BIGIQ version 6.0.x or lower.' + ) + def exec_module(self): + self.check_bigiq_version() changed = False result = dict() state = self.want.state @@ -672,14 +689,12 @@ def main(): supports_check_mode=spec.supports_check_mode ) - client = F5RestClient(**module.params) - try: - mm = ModuleManager(module=module, client=client) + mm = ModuleManager(module=module) results = mm.exec_module() - exit_json(module, results, client) + module.exit_json(**results) except F5ModuleError as ex: - fail_json(module, ex, client) + module.fail_json(msg=str(ex)) if __name__ == '__main__': diff --git a/lib/ansible/modules/network/f5/bigiq_application_fastl4_udp.py b/lib/ansible/modules/network/f5/bigiq_application_fastl4_udp.py index c148e2d965..ff0d78963b 100644 --- a/lib/ansible/modules/network/f5/bigiq_application_fastl4_udp.py +++ b/lib/ansible/modules/network/f5/bigiq_application_fastl4_udp.py @@ -24,10 +24,12 @@ options: name: description: - Name of the new application. + type: str required: True description: description: - Description of the application. + type: str servers: description: - A list of servers that the application is hosted on. @@ -38,13 +40,16 @@ options: address: description: - The IP address of the server. + type: str required: True port: description: - The port of the server. - When creating a new application and specifying a server, if this parameter is not provided, the default of C(8000) will be used. + type: str default: 8000 + type: list inbound_virtual: description: - Settings to configure the virtual which will receive the inbound connection. @@ -54,17 +59,20 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str required: True netmask: description: - Specifies the netmask to associate with the given C(destination). - This parameter is required when creating a new application. + type: str required: True port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(53) will be used. + type: str default: 53 service_environment: description: @@ -75,6 +83,7 @@ options: Therefore, it is crucial that you maintain unique names for items in the different service environment types. - SSGs are not supported for this type of application. + type: str add_analytics: description: - Collects statistics of the BIG-IP that the application is deployed to. @@ -87,10 +96,11 @@ options: - The state of the resource on the system. - When C(present), guarantees that the resource exists with the provided attributes. - When C(absent), removes the resource from the system. - default: present + type: str choices: - absent - present + default: present wait: description: - If the module should wait for the application to be created, deleted or updated. @@ -101,7 +111,7 @@ notes: - This module does not support updating of your application (whether deployed or not). If you need to update the application, the recommended practice is to remove and re-create. - - Requires BIG-IQ version 6.0 or greater. + - This module will not work on BIGIQ version 6.1.x or greater. author: - Tim Rupp (@caphrim007) ''' @@ -176,6 +186,7 @@ servers: import time +from distutils.version import LooseVersion from ansible.module_utils.basic import AnsibleModule try: @@ -183,17 +194,15 @@ try: 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 f5_argument_spec - from library.module_utils.network.f5.common import exit_json - from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.ipaddress import is_valid_ip + from library.module_utils.network.f5.icontrol import bigiq_version except ImportError: from ansible.module_utils.network.f5.bigiq import F5RestClient 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 f5_argument_spec - from ansible.module_utils.network.f5.common import exit_json - from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.ipaddress import is_valid_ip + from ansible.module_utils.network.f5.icontrol import bigiq_version class Parameters(AnsibleF5Parameters): @@ -440,7 +449,7 @@ class Difference(object): class ModuleManager(object): def __init__(self, *args, **kwargs): self.module = kwargs.get('module', None) - self.client = kwargs.get('client', None) + self.client = F5RestClient(**self.module.params) self.want = ModuleParameters(params=self.module.params) self.want.client = self.client self.have = ApiParameters() @@ -478,7 +487,15 @@ class ModuleManager(object): return True return False + def check_bigiq_version(self): + version = bigiq_version(self.client) + if LooseVersion(version) >= LooseVersion('6.1.0'): + raise F5ModuleError( + 'Module supports only BIGIQ version 6.0.x or lower.' + ) + def exec_module(self): + self.check_bigiq_version() changed = False result = dict() state = self.want.state @@ -672,14 +689,12 @@ def main(): supports_check_mode=spec.supports_check_mode ) - client = F5RestClient(**module.params) - try: - mm = ModuleManager(module=module, client=client) + mm = ModuleManager(module=module) results = mm.exec_module() - exit_json(module, results, client) + module.exit_json(**results) except F5ModuleError as ex: - fail_json(module, ex, client) + module.fail_json(msg=str(ex)) if __name__ == '__main__': diff --git a/lib/ansible/modules/network/f5/bigiq_application_http.py b/lib/ansible/modules/network/f5/bigiq_application_http.py index 0de6293c16..edb56145e7 100644 --- a/lib/ansible/modules/network/f5/bigiq_application_http.py +++ b/lib/ansible/modules/network/f5/bigiq_application_http.py @@ -24,10 +24,12 @@ options: name: description: - Name of the new application. + type: str required: True description: description: - Description of the application. + type: str servers: description: - A list of servers that the application is hosted on. @@ -38,13 +40,16 @@ options: address: description: - The IP address of the server. + type: str required: True port: description: - The port of the server. - When creating a new application and specifying a server, if this parameter is not provided, the default of C(80) will be used. + type: str default: 80 + type: list inbound_virtual: description: - Settings to configure the virtual which will receive the inbound connection. @@ -55,18 +60,22 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str required: True netmask: description: - Specifies the netmask to associate with the given C(destination). - This parameter is required when creating a new application. + type: str required: True port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(80) will be used. + type: str default: 80 + type: dict service_environment: description: - Specifies the name of service environment that the application will be @@ -75,6 +84,7 @@ options: - The service environment type will be discovered by this module automatically. Therefore, it is crucial that you maintain unique names for items in the different service environment types (at this time, SSGs and BIGIPs). + type: str add_analytics: description: - Collects statistics of the BIG-IP that the application is deployed to. @@ -87,10 +97,11 @@ options: - The state of the resource on the system. - When C(present), guarantees that the resource exists with the provided attributes. - When C(absent), removes the resource from the system. - default: present + type: str choices: - absent - present + default: present wait: description: - If the module should wait for the application to be created, deleted or updated. @@ -101,7 +112,7 @@ notes: - This module does not support updating of your application (whether deployed or not). If you need to update the application, the recommended practice is to remove and re-create. - - Requires BIG-IQ version 6.0 or greater. + - This module will not work on BIGIQ version 6.1.x or greater. author: - Tim Rupp (@caphrim007) ''' @@ -176,6 +187,7 @@ servers: import time +from distutils.version import LooseVersion from ansible.module_utils.basic import AnsibleModule try: @@ -183,17 +195,15 @@ try: 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 f5_argument_spec - from library.module_utils.network.f5.common import exit_json - from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.ipaddress import is_valid_ip + from library.module_utils.network.f5.icontrol import bigiq_version except ImportError: from ansible.module_utils.network.f5.bigiq import F5RestClient 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 f5_argument_spec - from ansible.module_utils.network.f5.common import exit_json - from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.ipaddress import is_valid_ip + from ansible.module_utils.network.f5.icontrol import bigiq_version class Parameters(AnsibleF5Parameters): @@ -482,7 +492,7 @@ class Difference(object): class ModuleManager(object): def __init__(self, *args, **kwargs): self.module = kwargs.get('module', None) - self.client = kwargs.get('client', None) + self.client = F5RestClient(**self.module.params) self.want = ModuleParameters(params=self.module.params) self.want.client = self.client self.have = ApiParameters() @@ -520,7 +530,15 @@ class ModuleManager(object): return True return False + def check_bigiq_version(self): + version = bigiq_version(self.client) + if LooseVersion(version) >= LooseVersion('6.1.0'): + raise F5ModuleError( + 'Module supports only BIGIQ version 6.0.x or lower.' + ) + def exec_module(self): + self.check_bigiq_version() changed = False result = dict() state = self.want.state @@ -725,14 +743,12 @@ def main(): supports_check_mode=spec.supports_check_mode ) - client = F5RestClient(**module.params) - try: - mm = ModuleManager(module=module, client=client) + mm = ModuleManager(module=module) results = mm.exec_module() - exit_json(module, results, client) + module.exit_json(**results) except F5ModuleError as ex: - fail_json(module, ex, client) + module.fail_json(msg=str(ex)) if __name__ == '__main__': diff --git a/lib/ansible/modules/network/f5/bigiq_application_https_offload.py b/lib/ansible/modules/network/f5/bigiq_application_https_offload.py index 1470f1d6f4..9f623f8a7c 100644 --- a/lib/ansible/modules/network/f5/bigiq_application_https_offload.py +++ b/lib/ansible/modules/network/f5/bigiq_application_https_offload.py @@ -24,10 +24,12 @@ options: name: description: - Name of the new application. + type: str required: True description: description: - Description of the application. + type: str servers: description: - A list of servers that the application is hosted on. @@ -38,10 +40,13 @@ options: address: description: - The IP address of the server. + type: str port: description: - The port of the server. + type: str default: 80 + type: list inbound_virtual: description: - Settings to configure the virtual which will receive the inbound connection. @@ -54,16 +59,20 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str netmask: description: - Specifies the netmask to associate with the given C(address). - This parameter is required when creating a new application. + type: str port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(443) will be used. + type: str default: 443 + type: dict redirect_virtual: description: - Settings to configure the virtual which will receive the connection to be @@ -78,16 +87,20 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str netmask: description: - Specifies the netmask to associate with the given C(address). - This parameter is required when creating a new application. + type: str port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(80) will be used. + type: str default: 80 + type: dict client_ssl_profile: description: - Specifies the SSL profile for managing client-side SSL traffic. @@ -114,20 +127,26 @@ options: cert: description: - Specifies a cert name for use. + type: str required: True key: description: - Specifies a key name. + type: str required: True chain: description: - Specifies a certificate chain that is relevant to the certificate and key mentioned earlier. - This key is optional. + type: str passphrase: description: - Contains the passphrase of the key file, should it require one. - Passphrases are encrypted on the remote BIG-IP device. + type: str + type: raw + type: dict service_environment: description: - Specifies the name of service environment or the hostname of the BIG-IP that @@ -145,16 +164,19 @@ options: - The state of the resource on the system. - When C(present), guarantees that the resource exists with the provided attributes. - When C(absent), removes the resource from the system. - default: present + type: str choices: - absent - present + default: present wait: description: - If the module should wait for the application to be created, deleted or updated. type: bool default: yes extends_documentation_fragment: f5 +notes: + - This module will not work on BIGIQ version 6.1.x or greater. author: - Tim Rupp (@caphrim007) ''' @@ -232,6 +254,7 @@ servers: import time +from distutils.version import LooseVersion from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import string_types @@ -240,19 +263,17 @@ try: 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 f5_argument_spec - from library.module_utils.network.f5.common import exit_json - from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.common import fq_name from library.module_utils.network.f5.ipaddress import is_valid_ip + from library.module_utils.network.f5.icontrol import bigiq_version except ImportError: from ansible.module_utils.network.f5.bigiq import F5RestClient 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 f5_argument_spec - from ansible.module_utils.network.f5.common import exit_json - from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.common import fq_name from ansible.module_utils.network.f5.ipaddress import is_valid_ip + from ansible.module_utils.network.f5.icontrol import bigiq_version class Parameters(AnsibleF5Parameters): @@ -699,7 +720,7 @@ class Difference(object): class ModuleManager(object): def __init__(self, *args, **kwargs): self.module = kwargs.get('module', None) - self.client = kwargs.get('client', None) + self.client = F5RestClient(**self.module.params) self.want = ModuleParameters(params=self.module.params) self.want.client = self.client self.have = ApiParameters() @@ -739,7 +760,15 @@ class ModuleManager(object): return True return False + def check_bigiq_version(self): + version = bigiq_version(self.client) + if LooseVersion(version) >= LooseVersion('6.1.0'): + raise F5ModuleError( + 'Module supports only BIGIQ version 6.0.x or lower.' + ) + def exec_module(self): + self.check_bigiq_version() changed = False result = dict() state = self.want.state @@ -965,17 +994,16 @@ def main(): module = AnsibleModule( argument_spec=spec.argument_spec, - supports_check_mode=spec.supports_check_mode + supports_check_mode=spec.supports_check_mode, + mutually_exclusive=spec.mutually_exclusive ) - client = F5RestClient(**module.params) - try: - mm = ModuleManager(module=module, client=client) + mm = ModuleManager(module=module) results = mm.exec_module() - exit_json(module, results, client) + module.exit_json(**results) except F5ModuleError as ex: - fail_json(module, ex, client) + module.fail_json(msg=str(ex)) if __name__ == '__main__': diff --git a/lib/ansible/modules/network/f5/bigiq_application_https_waf.py b/lib/ansible/modules/network/f5/bigiq_application_https_waf.py index ec3a857c18..a4e18ea20d 100644 --- a/lib/ansible/modules/network/f5/bigiq_application_https_waf.py +++ b/lib/ansible/modules/network/f5/bigiq_application_https_waf.py @@ -24,10 +24,12 @@ options: name: description: - Name of the new application. + type: str required: True description: description: - Description of the application. + type: str servers: description: - A list of servers that the application is hosted on. @@ -38,10 +40,13 @@ options: address: description: - The IP address of the server. + type: str port: description: - The port of the server. + type: str default: 80 + type: list inbound_virtual: description: - Settings to configure the virtual which will receive the inbound connection. @@ -54,16 +59,20 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str netmask: description: - Specifies the netmask to associate with the given C(destination). - This parameter is required when creating a new application. + type: str port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(443) will be used. + type: str default: 443 + type: dict redirect_virtual: description: - Settings to configure the virtual which will receive the connection to be @@ -78,16 +87,20 @@ options: - Specifies destination IP address information to which the virtual server sends traffic. - This parameter is required when creating a new application. + type: str netmask: description: - Specifies the netmask to associate with the given C(destination). - This parameter is required when creating a new application. + type: str port: description: - The port that the virtual listens for connections on. - When creating a new application, if this parameter is not specified, the default value of C(80) will be used. + type: str default: 80 + type: dict client_ssl_profile: description: - Specifies the SSL profile for managing client-side SSL traffic. @@ -97,6 +110,7 @@ options: - The name of the client SSL profile to created and used. - When creating a new application, if this value is not specified, the default value of C(clientssl) will be used. + type: str cert_key_chain: description: - One or more certificates and keys to associate with the SSL profile. @@ -114,25 +128,32 @@ options: cert: description: - Specifies a cert name for use. + type: str required: True key: description: - Specifies a key name. + type: str required: True chain: description: - Specifies a certificate chain that is relevant to the certificate and key mentioned earlier. - This key is optional. + type: str passphrase: description: - Contains the passphrase of the key file, should it require one. - Passphrases are encrypted on the remote BIG-IP device. + type: str + type: raw + type: dict service_environment: description: - Specifies the name of service environment that the application will be deployed to. - When creating a new application, this parameter is required. + type: str add_analytics: description: - Collects statistics of the BIG-IP that the application is deployed to. @@ -145,21 +166,25 @@ options: - Specifies host names that are used to access the web application that this security policy protects. - When creating a new application, this parameter is required. + type: list state: description: - The state of the resource on the system. - When C(present), guarantees that the resource exists with the provided attributes. - When C(absent), removes the resource from the system. - default: present + type: str choices: - absent - present + default: present wait: description: - If the module should wait for the application to be created, deleted or updated. type: bool default: yes extends_documentation_fragment: f5 +notes: + - This module will not work on BIGIQ version 6.1.x or greater. author: - Tim Rupp (@caphrim007) ''' @@ -237,6 +262,7 @@ servers: import time +from distutils.version import LooseVersion from ansible.module_utils.basic import AnsibleModule from ansible.module_utils.six import string_types @@ -245,19 +271,17 @@ try: 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 f5_argument_spec - from library.module_utils.network.f5.common import exit_json - from library.module_utils.network.f5.common import fail_json from library.module_utils.network.f5.common import fq_name from library.module_utils.network.f5.ipaddress import is_valid_ip + from library.module_utils.network.f5.icontrol import bigiq_version except ImportError: from ansible.module_utils.network.f5.bigiq import F5RestClient 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 f5_argument_spec - from ansible.module_utils.network.f5.common import exit_json - from ansible.module_utils.network.f5.common import fail_json from ansible.module_utils.network.f5.common import fq_name from ansible.module_utils.network.f5.ipaddress import is_valid_ip + from ansible.module_utils.network.f5.icontrol import bigiq_version class Parameters(AnsibleF5Parameters): @@ -719,7 +743,7 @@ class Difference(object): class ModuleManager(object): def __init__(self, *args, **kwargs): self.module = kwargs.get('module', None) - self.client = kwargs.get('client', None) + self.client = F5RestClient(**self.module.params) self.want = ModuleParameters(params=self.module.params) self.want.client = self.client self.have = ApiParameters() @@ -759,7 +783,15 @@ class ModuleManager(object): return True return False + def check_bigiq_version(self): + version = bigiq_version(self.client) + if LooseVersion(version) >= LooseVersion('6.1.0'): + raise F5ModuleError( + 'Module supports only BIGIQ version 6.0.x or lower.' + ) + def exec_module(self): + self.check_bigiq_version() changed = False result = dict() state = self.want.state @@ -990,17 +1022,16 @@ def main(): module = AnsibleModule( argument_spec=spec.argument_spec, - supports_check_mode=spec.supports_check_mode + supports_check_mode=spec.supports_check_mode, + mutually_exclusive=spec.mutually_exclusive ) - client = F5RestClient(**module.params) - try: - mm = ModuleManager(module=module, client=client) + mm = ModuleManager(module=module) results = mm.exec_module() - exit_json(module, results, client) + module.exit_json(**results) except F5ModuleError as ex: - fail_json(module, ex, client) + module.fail_json(msg=str(ex)) if __name__ == '__main__': diff --git a/test/units/modules/network/f5/test_bigiq_application_fasthttp.py b/test/units/modules/network/f5/test_bigiq_application_fasthttp.py index c98925318a..acaad34f26 100644 --- a/test/units/modules/network/f5/test_bigiq_application_fasthttp.py +++ b/test/units/modules/network/f5/test_bigiq_application_fasthttp.py @@ -21,6 +21,7 @@ try: from library.modules.bigiq_application_fasthttp import ModuleParameters from library.modules.bigiq_application_fasthttp import ModuleManager from library.modules.bigiq_application_fasthttp import ArgumentSpec + from library.module_utils.network.f5.common import F5ModuleError # In Ansible 2.8, Ansible changed import paths. from test.units.compat import unittest @@ -33,6 +34,7 @@ except ImportError: from ansible.modules.network.f5.bigiq_application_fasthttp import ModuleParameters from ansible.modules.network.f5.bigiq_application_fasthttp import ModuleManager from ansible.modules.network.f5.bigiq_application_fasthttp import ArgumentSpec + from ansible.module_utils.network.f5.common import F5ModuleError # Ansible 2.8 imports from units.compat import unittest @@ -111,14 +113,49 @@ class TestParameters(unittest.TestCase): class TestManager(unittest.TestCase): - def setUp(self): self.spec = ArgumentSpec() self.patcher1 = patch('time.sleep') self.patcher1.start() + try: + self.p1 = patch('library.modules.bigiq_application_fasthttp.bigiq_version') + self.p2 = patch('library.modules.bigiq_application_fasthttp.ModuleParameters.template_reference') + self.p3 = patch('library.modules.bigiq_application_fasthttp.ModuleParameters.ssg_reference') + self.p4 = patch('library.modules.bigiq_application_fasthttp.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + + except Exception: + self.p1 = patch('ansible.modules.network.f5.bigiq_application_fasthttp.bigiq_version') + self.p2 = patch('ansible.modules.network.f5.bigiq_application_fasthttp.ModuleParameters.template_reference') + self.p3 = patch('ansible.modules.network.f5.bigiq_application_fasthttp.ModuleParameters.ssg_reference') + self.p4 = patch('ansible.modules.network.f5.bigiq_application_fasthttp.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + def tearDown(self): self.patcher1.stop() + self.p1.stop() + self.p2.stop() + self.p3.stop() + self.p4.stop() def test_create(self, *args): set_module_args(dict( @@ -154,6 +191,7 @@ class TestManager(unittest.TestCase): # Override methods to force specific logic in the module to happen mm = ModuleManager(module=module) + mm.check_bigiq_version = Mock(return_value=True) mm.has_no_service_environment = Mock(return_value=False) mm.wait_for_apply_template_task = Mock(return_value=True) @@ -164,3 +202,43 @@ class TestManager(unittest.TestCase): assert results['changed'] is True assert results['description'] == 'my description' + + def test_bigiq_version_raises(self): + set_module_args(dict( + name='foo', + description='my description', + service_environment='bar', + servers=[ + dict( + address='1.2.3.4', + port=8080 + ), + dict( + address='5.6.7.8', + port=8000 + ) + ], + inbound_virtual=dict( + address='2.2.2.2', + netmask='255.255.255.255', + port=80 + ), + provider=dict( + server='localhost', + password='password', + user='admin' + ) + )) + + module = AnsibleModule( + argument_spec=self.spec.argument_spec, + supports_check_mode=self.spec.supports_check_mode + ) + + msg = 'Module supports only BIGIQ version 6.0.x or lower.' + # Override methods to force specific logic in the module to happen + mm = ModuleManager(module=module) + + with pytest.raises(F5ModuleError) as err: + mm.exec_module() + assert str(err.value) == msg diff --git a/test/units/modules/network/f5/test_bigiq_application_fastl4_tcp.py b/test/units/modules/network/f5/test_bigiq_application_fastl4_tcp.py index 85ee753b42..4e2f13edeb 100644 --- a/test/units/modules/network/f5/test_bigiq_application_fastl4_tcp.py +++ b/test/units/modules/network/f5/test_bigiq_application_fastl4_tcp.py @@ -21,6 +21,7 @@ try: from library.modules.bigiq_application_fastl4_tcp import ModuleParameters from library.modules.bigiq_application_fastl4_tcp import ModuleManager from library.modules.bigiq_application_fastl4_tcp import ArgumentSpec + from library.module_utils.network.f5.common import F5ModuleError # In Ansible 2.8, Ansible changed import paths. from test.units.compat import unittest @@ -33,6 +34,7 @@ except ImportError: from ansible.modules.network.f5.bigiq_application_fastl4_tcp import ModuleParameters from ansible.modules.network.f5.bigiq_application_fastl4_tcp import ModuleManager from ansible.modules.network.f5.bigiq_application_fastl4_tcp import ArgumentSpec + from ansible.module_utils.network.f5.common import F5ModuleError # Ansible 2.8 imports from units.compat import unittest @@ -111,14 +113,42 @@ class TestParameters(unittest.TestCase): class TestManager(unittest.TestCase): - def setUp(self): self.spec = ArgumentSpec() self.patcher1 = patch('time.sleep') self.patcher1.start() + try: + self.p1 = patch('library.modules.bigiq_application_fastl4_tcp.bigiq_version') + self.p2 = patch('library.modules.bigiq_application_fastl4_tcp.ModuleParameters.template_reference') + self.p3 = patch('library.modules.bigiq_application_fastl4_tcp.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + + except Exception: + self.p1 = patch('ansible.modules.network.f5.bigiq_application_fastl4_tcp.bigiq_version') + self.p2 = patch('ansible.modules.network.f5.bigiq_application_fastl4_tcp.ModuleParameters.template_reference') + self.p3 = patch('ansible.modules.network.f5.bigiq_application_fastl4_tcp.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + def tearDown(self): self.patcher1.stop() + self.p1.stop() + self.p2.stop() + self.p3.stop() def test_create(self, *args): set_module_args(dict( @@ -154,6 +184,7 @@ class TestManager(unittest.TestCase): # Override methods to force specific logic in the module to happen mm = ModuleManager(module=module) + mm.check_bigiq_version = Mock(return_value=True) mm.has_no_service_environment = Mock(return_value=False) mm.wait_for_apply_template_task = Mock(return_value=True) @@ -164,3 +195,43 @@ class TestManager(unittest.TestCase): assert results['changed'] is True assert results['description'] == 'my description' + + def test_bigiq_version_raises(self): + set_module_args(dict( + name='foo', + description='my description', + service_environment='bar', + servers=[ + dict( + address='1.2.3.4', + port=8080 + ), + dict( + address='5.6.7.8', + port=8000 + ) + ], + inbound_virtual=dict( + address='2.2.2.2', + netmask='255.255.255.255', + port=80 + ), + provider=dict( + server='localhost', + password='password', + user='admin' + ) + )) + + module = AnsibleModule( + argument_spec=self.spec.argument_spec, + supports_check_mode=self.spec.supports_check_mode + ) + + msg = 'Module supports only BIGIQ version 6.0.x or lower.' + # Override methods to force specific logic in the module to happen + mm = ModuleManager(module=module) + + with pytest.raises(F5ModuleError) as err: + mm.exec_module() + assert str(err.value) == msg diff --git a/test/units/modules/network/f5/test_bigiq_application_fastl4_udp.py b/test/units/modules/network/f5/test_bigiq_application_fastl4_udp.py index 885609722b..b091cd8e9f 100644 --- a/test/units/modules/network/f5/test_bigiq_application_fastl4_udp.py +++ b/test/units/modules/network/f5/test_bigiq_application_fastl4_udp.py @@ -21,6 +21,7 @@ try: from library.modules.bigiq_application_fastl4_udp import ModuleParameters from library.modules.bigiq_application_fastl4_udp import ModuleManager from library.modules.bigiq_application_fastl4_udp import ArgumentSpec + from library.module_utils.network.f5.common import F5ModuleError # In Ansible 2.8, Ansible changed import paths. from test.units.compat import unittest @@ -33,6 +34,7 @@ except ImportError: from ansible.modules.network.f5.bigiq_application_fastl4_udp import ModuleParameters from ansible.modules.network.f5.bigiq_application_fastl4_udp import ModuleManager from ansible.modules.network.f5.bigiq_application_fastl4_udp import ArgumentSpec + from ansible.module_utils.network.f5.common import F5ModuleError # Ansible 2.8 imports from units.compat import unittest @@ -111,14 +113,42 @@ class TestParameters(unittest.TestCase): class TestManager(unittest.TestCase): - def setUp(self): self.spec = ArgumentSpec() self.patcher1 = patch('time.sleep') self.patcher1.start() + try: + self.p1 = patch('library.modules.bigiq_application_fastl4_udp.bigiq_version') + self.p2 = patch('library.modules.bigiq_application_fastl4_udp.ModuleParameters.template_reference') + self.p3 = patch('library.modules.bigiq_application_fastl4_udp.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + + except Exception: + self.p1 = patch('ansible.modules.network.f5.bigiq_application_fastl4_udp.bigiq_version') + self.p2 = patch('ansible.modules.network.f5.bigiq_application_fastl4_udp.ModuleParameters.template_reference') + self.p3 = patch('ansible.modules.network.f5.bigiq_application_fastl4_udp.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + def tearDown(self): self.patcher1.stop() + self.p1.stop() + self.p2.stop() + self.p3.stop() def test_create(self, *args): set_module_args(dict( @@ -154,6 +184,7 @@ class TestManager(unittest.TestCase): # Override methods to force specific logic in the module to happen mm = ModuleManager(module=module) + mm.check_bigiq_version = Mock(return_value=True) mm.has_no_service_environment = Mock(return_value=False) mm.wait_for_apply_template_task = Mock(return_value=True) @@ -164,3 +195,43 @@ class TestManager(unittest.TestCase): assert results['changed'] is True assert results['description'] == 'my description' + + def test_bigiq_version_raises(self): + set_module_args(dict( + name='foo', + description='my description', + service_environment='bar', + servers=[ + dict( + address='1.2.3.4', + port=8080 + ), + dict( + address='5.6.7.8', + port=8000 + ) + ], + inbound_virtual=dict( + address='2.2.2.2', + netmask='255.255.255.255', + port=80 + ), + provider=dict( + server='localhost', + password='password', + user='admin' + ) + )) + + module = AnsibleModule( + argument_spec=self.spec.argument_spec, + supports_check_mode=self.spec.supports_check_mode + ) + + msg = 'Module supports only BIGIQ version 6.0.x or lower.' + # Override methods to force specific logic in the module to happen + mm = ModuleManager(module=module) + + with pytest.raises(F5ModuleError) as err: + mm.exec_module() + assert str(err.value) == msg diff --git a/test/units/modules/network/f5/test_bigiq_application_http.py b/test/units/modules/network/f5/test_bigiq_application_http.py index 8d604aa75a..b2ac95dd8f 100644 --- a/test/units/modules/network/f5/test_bigiq_application_http.py +++ b/test/units/modules/network/f5/test_bigiq_application_http.py @@ -21,6 +21,7 @@ try: from library.modules.bigiq_application_http import ModuleParameters from library.modules.bigiq_application_http import ModuleManager from library.modules.bigiq_application_http import ArgumentSpec + from library.module_utils.network.f5.common import F5ModuleError # In Ansible 2.8, Ansible changed import paths. from test.units.compat import unittest @@ -33,6 +34,7 @@ except ImportError: from ansible.modules.network.f5.bigiq_application_http import ModuleParameters from ansible.modules.network.f5.bigiq_application_http import ModuleManager from ansible.modules.network.f5.bigiq_application_http import ArgumentSpec + from ansible.module_utils.network.f5.common import F5ModuleError # Ansible 2.8 imports from units.compat import unittest @@ -111,14 +113,49 @@ class TestParameters(unittest.TestCase): class TestManager(unittest.TestCase): - def setUp(self): self.spec = ArgumentSpec() self.patcher1 = patch('time.sleep') self.patcher1.start() + try: + self.p1 = patch('library.modules.bigiq_application_http.bigiq_version') + self.p2 = patch('library.modules.bigiq_application_http.ModuleParameters.template_reference') + self.p3 = patch('library.modules.bigiq_application_http.ModuleParameters.ssg_reference') + self.p4 = patch('library.modules.bigiq_application_http.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + + except Exception: + self.p1 = patch('ansible.modules.network.f5.bigiq_application_http.bigiq_version') + self.p2 = patch('ansible.modules.network.f5.bigiq_application_http.ModuleParameters.template_reference') + self.p3 = patch('ansible.modules.network.f5.bigiq_application_http.ModuleParameters.ssg_reference') + self.p4 = patch('ansible.modules.network.f5.bigiq_application_http.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + def tearDown(self): self.patcher1.stop() + self.p1.stop() + self.p2.stop() + self.p3.stop() + self.p4.stop() def test_create(self, *args): set_module_args(dict( @@ -154,6 +191,7 @@ class TestManager(unittest.TestCase): # Override methods to force specific logic in the module to happen mm = ModuleManager(module=module) + mm.check_bigiq_version = Mock(return_value=True) mm.has_no_service_environment = Mock(return_value=False) mm.wait_for_apply_template_task = Mock(return_value=True) @@ -164,3 +202,43 @@ class TestManager(unittest.TestCase): assert results['changed'] is True assert results['description'] == 'my description' + + def test_bigiq_version_raises(self): + set_module_args(dict( + name='foo', + description='my description', + service_environment='bar', + servers=[ + dict( + address='1.2.3.4', + port=8080 + ), + dict( + address='5.6.7.8', + port=8000 + ) + ], + inbound_virtual=dict( + address='2.2.2.2', + netmask='255.255.255.255', + port=80 + ), + provider=dict( + server='localhost', + password='password', + user='admin' + ) + )) + + module = AnsibleModule( + argument_spec=self.spec.argument_spec, + supports_check_mode=self.spec.supports_check_mode + ) + + msg = 'Module supports only BIGIQ version 6.0.x or lower.' + # Override methods to force specific logic in the module to happen + mm = ModuleManager(module=module) + + with pytest.raises(F5ModuleError) as err: + mm.exec_module() + assert str(err.value) == msg diff --git a/test/units/modules/network/f5/test_bigiq_application_https_offload.py b/test/units/modules/network/f5/test_bigiq_application_https_offload.py index 7b246e25fc..ef35aac786 100644 --- a/test/units/modules/network/f5/test_bigiq_application_https_offload.py +++ b/test/units/modules/network/f5/test_bigiq_application_https_offload.py @@ -21,6 +21,7 @@ try: from library.modules.bigiq_application_https_offload import ModuleParameters from library.modules.bigiq_application_https_offload import ModuleManager from library.modules.bigiq_application_https_offload import ArgumentSpec + from library.module_utils.network.f5.common import F5ModuleError # In Ansible 2.8, Ansible changed import paths. from test.units.compat import unittest @@ -33,6 +34,7 @@ except ImportError: from ansible.modules.network.f5.bigiq_application_https_offload import ModuleParameters from ansible.modules.network.f5.bigiq_application_https_offload import ModuleManager from ansible.modules.network.f5.bigiq_application_https_offload import ArgumentSpec + from ansible.module_utils.network.f5.common import F5ModuleError # Ansible 2.8 imports from units.compat import unittest @@ -122,14 +124,49 @@ class TestParameters(unittest.TestCase): class TestManager(unittest.TestCase): - def setUp(self): self.spec = ArgumentSpec() self.patcher1 = patch('time.sleep') self.patcher1.start() + try: + self.p1 = patch('library.modules.bigiq_application_https_offload.bigiq_version') + self.p2 = patch('library.modules.bigiq_application_https_offload.ModuleParameters.template_reference') + self.p3 = patch('library.modules.bigiq_application_https_offload.ModuleParameters.ssg_reference') + self.p4 = patch('library.modules.bigiq_application_https_offload.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + + except Exception: + self.p1 = patch('ansible.modules.network.f5.bigiq_application_https_offload.bigiq_version') + self.p2 = patch('ansible.modules.network.f5.bigiq_application_https_offload.ModuleParameters.template_reference') + self.p3 = patch('ansible.modules.network.f5.bigiq_application_https_offload.ModuleParameters.ssg_reference') + self.p4 = patch('ansible.modules.network.f5.bigiq_application_https_offload.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + def tearDown(self): self.patcher1.stop() + self.p1.stop() + self.p2.stop() + self.p3.stop() + self.p4.stop() def test_create(self, *args): set_module_args(dict( @@ -165,11 +202,13 @@ class TestManager(unittest.TestCase): module = AnsibleModule( argument_spec=self.spec.argument_spec, - supports_check_mode=self.spec.supports_check_mode + supports_check_mode=self.spec.supports_check_mode, + mutually_exclusive=self.spec.mutually_exclusive ) # Override methods to force specific logic in the module to happen mm = ModuleManager(module=module) + mm.check_bigiq_version = Mock(return_value=True) mm.has_no_service_environment = Mock(return_value=False) mm.wait_for_apply_template_task = Mock(return_value=True) @@ -180,3 +219,44 @@ class TestManager(unittest.TestCase): assert results['changed'] is True assert results['description'] == 'my description' + + def test_bigiq_version_raises(self): + set_module_args(dict( + name='foo', + description='my description', + service_environment='bar', + servers=[ + dict( + address='1.2.3.4', + port=8080 + ), + dict( + address='5.6.7.8', + port=8000 + ) + ], + inbound_virtual=dict( + address='2.2.2.2', + netmask='255.255.255.255', + port=80 + ), + provider=dict( + server='localhost', + password='password', + user='admin' + ) + )) + + module = AnsibleModule( + argument_spec=self.spec.argument_spec, + supports_check_mode=self.spec.supports_check_mode, + mutually_exclusive=self.spec.mutually_exclusive + ) + + msg = 'Module supports only BIGIQ version 6.0.x or lower.' + # Override methods to force specific logic in the module to happen + mm = ModuleManager(module=module) + + with pytest.raises(F5ModuleError) as err: + mm.exec_module() + assert str(err.value) == msg diff --git a/test/units/modules/network/f5/test_bigiq_application_https_waf.py b/test/units/modules/network/f5/test_bigiq_application_https_waf.py index 11bd8d62af..9d99f47374 100644 --- a/test/units/modules/network/f5/test_bigiq_application_https_waf.py +++ b/test/units/modules/network/f5/test_bigiq_application_https_waf.py @@ -21,6 +21,7 @@ try: from library.modules.bigiq_application_https_waf import ModuleParameters from library.modules.bigiq_application_https_waf import ModuleManager from library.modules.bigiq_application_https_waf import ArgumentSpec + from library.module_utils.network.f5.common import F5ModuleError # In Ansible 2.8, Ansible changed import paths. from test.units.compat import unittest @@ -33,6 +34,7 @@ except ImportError: from ansible.modules.network.f5.bigiq_application_https_waf import ModuleParameters from ansible.modules.network.f5.bigiq_application_https_waf import ModuleManager from ansible.modules.network.f5.bigiq_application_https_waf import ArgumentSpec + from ansible.module_utils.network.f5.common import F5ModuleError # Ansible 2.8 imports from units.compat import unittest @@ -126,14 +128,49 @@ class TestParameters(unittest.TestCase): class TestManager(unittest.TestCase): - def setUp(self): self.spec = ArgumentSpec() self.patcher1 = patch('time.sleep') self.patcher1.start() + try: + self.p1 = patch('library.modules.bigiq_application_https_waf.bigiq_version') + self.p2 = patch('library.modules.bigiq_application_https_waf.ModuleParameters.template_reference') + self.p3 = patch('library.modules.bigiq_application_https_waf.ModuleParameters.ssg_reference') + self.p4 = patch('library.modules.bigiq_application_https_waf.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + + except Exception: + self.p1 = patch('ansible.modules.network.f5.bigiq_application_https_waf.bigiq_version') + self.p2 = patch('ansible.modules.network.f5.bigiq_application_https_waf.ModuleParameters.template_reference') + self.p3 = patch('ansible.modules.network.f5.bigiq_application_https_waf.ModuleParameters.ssg_reference') + self.p4 = patch('ansible.modules.network.f5.bigiq_application_https_waf.ModuleParameters.default_device_reference') + + self.m1 = self.p1.start() + self.m2 = self.p2.start() + self.m3 = self.p3.start() + self.m4 = self.p4.start() + + self.m1.return_value = '6.1.0' + self.m2.return_value = Mock(return_value='https://localhost/mgmt/foobar1') + self.m3.return_value = Mock(return_value='https://localhost/mgmt/foobar2') + self.m4.return_value = Mock(return_value='https://localhost/mgmt/foobar3') + def tearDown(self): self.patcher1.stop() + self.p1.stop() + self.p2.stop() + self.p3.stop() + self.p4.stop() def test_create(self, *args): set_module_args(dict( @@ -173,11 +210,13 @@ class TestManager(unittest.TestCase): module = AnsibleModule( argument_spec=self.spec.argument_spec, - supports_check_mode=self.spec.supports_check_mode + supports_check_mode=self.spec.supports_check_mode, + mutually_exclusive=self.spec.mutually_exclusive ) # Override methods to force specific logic in the module to happen mm = ModuleManager(module=module) + mm.check_bigiq_version = Mock(return_value=True) mm.has_no_service_environment = Mock(return_value=False) mm.wait_for_apply_template_task = Mock(return_value=True) @@ -188,3 +227,44 @@ class TestManager(unittest.TestCase): assert results['changed'] is True assert results['description'] == 'my description' + + def test_bigiq_version_raises(self): + set_module_args(dict( + name='foo', + description='my description', + service_environment='bar', + servers=[ + dict( + address='1.2.3.4', + port=8080 + ), + dict( + address='5.6.7.8', + port=8000 + ) + ], + inbound_virtual=dict( + address='2.2.2.2', + netmask='255.255.255.255', + port=80 + ), + provider=dict( + server='localhost', + password='password', + user='admin' + ) + )) + + module = AnsibleModule( + argument_spec=self.spec.argument_spec, + supports_check_mode=self.spec.supports_check_mode, + mutually_exclusive=self.spec.mutually_exclusive + ) + + msg = 'Module supports only BIGIQ version 6.0.x or lower.' + # Override methods to force specific logic in the module to happen + mm = ModuleManager(module=module) + + with pytest.raises(F5ModuleError) as err: + mm.exec_module() + assert str(err.value) == msg