summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMiguel Angel Muñoz González <magonzalez@fortinet.com>2019-08-28 09:55:00 +0200
committerNilashish Chakraborty <nilashishchakraborty8@gmail.com>2019-08-28 13:24:59 +0530
commitda762018e874bd4abcac1d060d08ae2be4e31126 (patch)
treeef8a51e5a073af91c3dddea2e879c9448d425949
parentf5d829392a17e20d0ba02c30e5a377a43cf70cfd (diff)
downloadansible-da762018e874bd4abcac1d060d08ae2be4e31126.tar.gz
FortiOS modules for 2.9 - 11 (#61387)
-rw-r--r--lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py322
-rw-r--r--lib/ansible/modules/network/fortios/fortios_web_proxy_global.py224
-rw-r--r--lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py200
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py222
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_cat.py160
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_rating.py160
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py145
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py141
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py141
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_override.py189
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_profile.py600
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py178
-rw-r--r--lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py197
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py236
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py132
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py186
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py913
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py551
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py707
-rw-r--r--lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py1240
-rw-r--r--test/sanity/ignore.txt38
-rw-r--r--test/units/modules/network/fortios/test_fortios_web_proxy_explicit.py351
-rw-r--r--test/units/modules/network/fortios/test_fortios_web_proxy_global.py247
-rw-r--r--test/units/modules/network/fortios/test_fortios_web_proxy_profile.py289
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_fortiguard.py231
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_cat.py219
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_rating.py219
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_cache_setting.py159
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting.py175
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting6.py175
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_override.py299
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_profile.py479
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_search_engine.py259
-rw-r--r--test/units/modules/network/fortios/test_fortios_webfilter_urlfilter.py239
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_global.py279
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_setting.py175
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_utm_profile.py269
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_vap.py1109
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_wids_profile.py679
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_wtp.py509
-rw-r--r--test/units/modules/network/fortios/test_fortios_wireless_controller_wtp_profile.py439
41 files changed, 11006 insertions, 2676 deletions
diff --git a/lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py b/lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py
index af1033c305..fa545cb980 100644
--- a/lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py
+++ b/lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_web_proxy_explicit
short_description: Configure explicit Web proxy settings in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify web_proxy feature and explicit category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,195 +41,242 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
web_proxy_explicit:
description:
- Configure explicit Web proxy settings.
default: null
+ type: dict
suboptions:
- ftp-incoming-port:
+ ftp_incoming_port:
description:
- - Accept incoming FTP-over-HTTP requests on one or more ports (0 - 65535, default = 0; use the same as HTTP).
- ftp-over-http:
+ - Accept incoming FTP-over-HTTP requests on one or more ports (0 - 65535).
+ type: str
+ ftp_over_http:
description:
- Enable to proxy FTP-over-HTTP sessions sent from a web browser.
+ type: str
choices:
- enable
- disable
- http-incoming-port:
+ http_incoming_port:
description:
- - Accept incoming HTTP requests on one or more ports (0 - 65535, default = 8080).
- https-incoming-port:
+ - Accept incoming HTTP requests on one or more ports (0 - 65535).
+ type: str
+ https_incoming_port:
description:
- - Accept incoming HTTPS requests on one or more ports (0 - 65535, default = 0, use the same as HTTP).
- https-replacement-message:
+ - Accept incoming HTTPS requests on one or more ports (0 - 65535).
+ type: str
+ https_replacement_message:
description:
- Enable/disable sending the client a replacement message for HTTPS requests.
+ type: str
choices:
- enable
- disable
- incoming-ip:
+ incoming_ip:
description:
- Restrict the explicit HTTP proxy to only accept sessions from this IP address. An interface must have this IP address.
- incoming-ip6:
+ type: str
+ incoming_ip6:
description:
- Restrict the explicit web proxy to only accept sessions from this IPv6 address. An interface must have this IPv6 address.
- ipv6-status:
+ type: str
+ ipv6_status:
description:
- Enable/disable allowing an IPv6 web proxy destination in policies and all IPv6 related entries in this command.
+ type: str
choices:
- enable
- disable
- message-upon-server-error:
+ message_upon_server_error:
description:
- Enable/disable displaying a replacement message when a server error is detected.
+ type: str
choices:
- enable
- disable
- outgoing-ip:
+ outgoing_ip:
description:
- Outgoing HTTP requests will have this IP address as their source address. An interface must have this IP address.
- outgoing-ip6:
+ type: str
+ outgoing_ip6:
description:
- Outgoing HTTP requests will leave this IPv6. Multiple interfaces can be specified. Interfaces must have these IPv6 addresses.
- pac-file-data:
+ type: str
+ pac_file_data:
description:
- PAC file contents enclosed in quotes (maximum of 256K bytes).
- pac-file-name:
+ type: str
+ pac_file_name:
description:
- Pac file name.
- pac-file-server-port:
+ type: str
+ pac_file_server_port:
description:
- - Port number that PAC traffic from client web browsers uses to connect to the explicit web proxy (0 - 65535, default = 0; use the same as
- HTTP).
- pac-file-server-status:
+ - Port number that PAC traffic from client web browsers uses to connect to the explicit web proxy (0 - 65535).
+ type: str
+ pac_file_server_status:
description:
- Enable/disable Proxy Auto-Configuration (PAC) for users of this explicit proxy profile.
+ type: str
choices:
- enable
- disable
- pac-file-url:
+ pac_file_url:
description:
- PAC file access URL.
- pac-policy:
+ type: str
+ pac_policy:
description:
- PAC policies.
+ type: list
suboptions:
comments:
description:
- Optional comments.
+ type: str
dstaddr:
description:
- Destination address objects.
+ type: list
suboptions:
name:
description:
- Address name. Source firewall.address.name firewall.addrgrp.name.
required: true
- pac-file-data:
+ type: str
+ pac_file_data:
description:
- PAC file contents enclosed in quotes (maximum of 256K bytes).
- pac-file-name:
+ type: str
+ pac_file_name:
description:
- Pac file name.
+ type: str
policyid:
description:
- Policy ID.
required: true
+ type: int
srcaddr:
description:
- Source address objects.
+ type: list
suboptions:
name:
description:
- Address name. Source firewall.address.name firewall.addrgrp.name firewall.proxy-address.name firewall.proxy-addrgrp.name.
required: true
+ type: str
srcaddr6:
description:
- Source address6 objects.
+ type: list
suboptions:
name:
description:
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
required: true
+ type: str
status:
description:
- Enable/disable policy.
+ type: str
choices:
- enable
- disable
- pref-dns-result:
+ pref_dns_result:
description:
- - Prefer resolving addresses using the configured IPv4 or IPv6 DNS server (default = ipv4).
+ - Prefer resolving addresses using the configured IPv4 or IPv6 DNS server .
+ type: str
choices:
- ipv4
- ipv6
realm:
description:
- Authentication realm used to identify the explicit web proxy (maximum of 63 characters).
- sec-default-action:
+ type: str
+ sec_default_action:
description:
- Accept or deny explicit web proxy sessions when no web proxy firewall policy exists.
+ type: str
choices:
- accept
- deny
socks:
description:
- Enable/disable the SOCKS proxy.
+ type: str
choices:
- enable
- disable
- socks-incoming-port:
+ socks_incoming_port:
description:
- - Accept incoming SOCKS proxy requests on one or more ports (0 - 65535, default = 0; use the same as HTTP).
- ssl-algorithm:
+ - Accept incoming SOCKS proxy requests on one or more ports (0 - 65535).
+ type: str
+ ssl_algorithm:
description:
- "Relative strength of encryption algorithms accepted in HTTPS deep scan: high, medium, or low."
+ type: str
choices:
- low
status:
description:
- Enable/disable the explicit Web proxy for HTTP and HTTPS session.
+ type: str
choices:
- enable
- disable
- strict-guest:
+ strict_guest:
description:
- Enable/disable strict guest user checking by the explicit web proxy.
+ type: str
choices:
- enable
- disable
- trace-auth-no-rsp:
+ trace_auth_no_rsp:
description:
- Enable/disable logging timed-out authentication requests.
+ type: str
choices:
- enable
- disable
- unknown-http-version:
+ unknown_http_version:
description:
- Either reject unknown HTTP traffic as malformed or handle unknown HTTP traffic as best as the proxy server can.
+ type: str
choices:
- reject
- best-effort
@@ -242,6 +289,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure explicit Web proxy settings.
fortios_web_proxy_explicit:
@@ -251,30 +299,30 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
web_proxy_explicit:
- ftp-incoming-port: "<your_own_value>"
- ftp-over-http: "enable"
- http-incoming-port: "<your_own_value>"
- https-incoming-port: "<your_own_value>"
- https-replacement-message: "enable"
- incoming-ip: "<your_own_value>"
- incoming-ip6: "<your_own_value>"
- ipv6-status: "enable"
- message-upon-server-error: "enable"
- outgoing-ip: "<your_own_value>"
- outgoing-ip6: "<your_own_value>"
- pac-file-data: "<your_own_value>"
- pac-file-name: "<your_own_value>"
- pac-file-server-port: "<your_own_value>"
- pac-file-server-status: "enable"
- pac-file-url: "<your_own_value>"
- pac-policy:
+ ftp_incoming_port: "<your_own_value>"
+ ftp_over_http: "enable"
+ http_incoming_port: "<your_own_value>"
+ https_incoming_port: "<your_own_value>"
+ https_replacement_message: "enable"
+ incoming_ip: "<your_own_value>"
+ incoming_ip6: "<your_own_value>"
+ ipv6_status: "enable"
+ message_upon_server_error: "enable"
+ outgoing_ip: "<your_own_value>"
+ outgoing_ip6: "<your_own_value>"
+ pac_file_data: "<your_own_value>"
+ pac_file_name: "<your_own_value>"
+ pac_file_server_port: "<your_own_value>"
+ pac_file_server_status: "enable"
+ pac_file_url: "<your_own_value>"
+ pac_policy:
-
comments: "<your_own_value>"
dstaddr:
-
name: "default_name_22 (source firewall.address.name firewall.addrgrp.name)"
- pac-file-data: "<your_own_value>"
- pac-file-name: "<your_own_value>"
+ pac_file_data: "<your_own_value>"
+ pac_file_name: "<your_own_value>"
policyid: "25"
srcaddr:
-
@@ -283,16 +331,16 @@ EXAMPLES = '''
-
name: "default_name_29 (source firewall.address6.name firewall.addrgrp6.name)"
status: "enable"
- pref-dns-result: "ipv4"
+ pref_dns_result: "ipv4"
realm: "<your_own_value>"
- sec-default-action: "accept"
+ sec_default_action: "accept"
socks: "enable"
- socks-incoming-port: "<your_own_value>"
- ssl-algorithm: "low"
+ socks_incoming_port: "<your_own_value>"
+ ssl_algorithm: "low"
status: "enable"
- strict-guest: "enable"
- trace-auth-no-rsp: "enable"
- unknown-http-version: "reject"
+ strict_guest: "enable"
+ trace_auth_no_rsp: "enable"
+ unknown_http_version: "reject"
'''
RETURN = '''
@@ -355,12 +403,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -368,19 +420,19 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_web_proxy_explicit_data(json):
- option_list = ['ftp-incoming-port', 'ftp-over-http', 'http-incoming-port',
- 'https-incoming-port', 'https-replacement-message', 'incoming-ip',
- 'incoming-ip6', 'ipv6-status', 'message-upon-server-error',
- 'outgoing-ip', 'outgoing-ip6', 'pac-file-data',
- 'pac-file-name', 'pac-file-server-port', 'pac-file-server-status',
- 'pac-file-url', 'pac-policy', 'pref-dns-result',
- 'realm', 'sec-default-action', 'socks',
- 'socks-incoming-port', 'ssl-algorithm', 'status',
- 'strict-guest', 'trace-auth-no-rsp', 'unknown-http-version']
+ option_list = ['ftp_incoming_port', 'ftp_over_http', 'http_incoming_port',
+ 'https_incoming_port', 'https_replacement_message', 'incoming_ip',
+ 'incoming_ip6', 'ipv6_status', 'message_upon_server_error',
+ 'outgoing_ip', 'outgoing_ip6', 'pac_file_data',
+ 'pac_file_name', 'pac_file_server_port', 'pac_file_server_status',
+ 'pac_file_url', 'pac_policy', 'pref_dns_result',
+ 'realm', 'sec_default_action', 'socks',
+ 'socks_incoming_port', 'ssl_algorithm', 'status',
+ 'strict_guest', 'trace_auth_no_rsp', 'unknown_http_version']
dictionary = {}
for attribute in option_list:
@@ -390,10 +442,23 @@ def filter_web_proxy_explicit_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def web_proxy_explicit(data, fos):
vdom = data['vdom']
web_proxy_explicit_data = data['web_proxy_explicit']
- filtered_data = filter_web_proxy_explicit_data(web_proxy_explicit_data)
+ filtered_data = underscore_to_hyphen(filter_web_proxy_explicit_data(web_proxy_explicit_data))
return fos.set('web-proxy',
'explicit',
@@ -401,56 +466,62 @@ def web_proxy_explicit(data, fos):
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_web_proxy(data, fos):
- login(data, fos)
if data['web_proxy_explicit']:
resp = web_proxy_explicit(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"web_proxy_explicit": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "ftp-incoming-port": {"required": False, "type": "str"},
- "ftp-over-http": {"required": False, "type": "str",
+ "ftp_incoming_port": {"required": False, "type": "str"},
+ "ftp_over_http": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "http-incoming-port": {"required": False, "type": "str"},
- "https-incoming-port": {"required": False, "type": "str"},
- "https-replacement-message": {"required": False, "type": "str",
+ "http_incoming_port": {"required": False, "type": "str"},
+ "https_incoming_port": {"required": False, "type": "str"},
+ "https_replacement_message": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "incoming-ip": {"required": False, "type": "str"},
- "incoming-ip6": {"required": False, "type": "str"},
- "ipv6-status": {"required": False, "type": "str",
+ "incoming_ip": {"required": False, "type": "str"},
+ "incoming_ip6": {"required": False, "type": "str"},
+ "ipv6_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "message-upon-server-error": {"required": False, "type": "str",
+ "message_upon_server_error": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "outgoing-ip": {"required": False, "type": "str"},
- "outgoing-ip6": {"required": False, "type": "str"},
- "pac-file-data": {"required": False, "type": "str"},
- "pac-file-name": {"required": False, "type": "str"},
- "pac-file-server-port": {"required": False, "type": "str"},
- "pac-file-server-status": {"required": False, "type": "str",
+ "outgoing_ip": {"required": False, "type": "str"},
+ "outgoing_ip6": {"required": False, "type": "str"},
+ "pac_file_data": {"required": False, "type": "str"},
+ "pac_file_name": {"required": False, "type": "str"},
+ "pac_file_server_port": {"required": False, "type": "str"},
+ "pac_file_server_status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "pac-file-url": {"required": False, "type": "str"},
- "pac-policy": {"required": False, "type": "list",
+ "pac_file_url": {"required": False, "type": "str"},
+ "pac_policy": {"required": False, "type": "list",
"options": {
"comments": {"required": False, "type": "str"},
"dstaddr": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "pac-file-data": {"required": False, "type": "str"},
- "pac-file-name": {"required": False, "type": "str"},
+ "pac_file_data": {"required": False, "type": "str"},
+ "pac_file_name": {"required": False, "type": "str"},
"policyid": {"required": True, "type": "int"},
"srcaddr": {"required": False, "type": "list",
"options": {
@@ -463,23 +534,23 @@ def main():
"status": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}},
- "pref-dns-result": {"required": False, "type": "str",
+ "pref_dns_result": {"required": False, "type": "str",
"choices": ["ipv4", "ipv6"]},
"realm": {"required": False, "type": "str"},
- "sec-default-action": {"required": False, "type": "str",
+ "sec_default_action": {"required": False, "type": "str",
"choices": ["accept", "deny"]},
"socks": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "socks-incoming-port": {"required": False, "type": "str"},
- "ssl-algorithm": {"required": False, "type": "str",
+ "socks_incoming_port": {"required": False, "type": "str"},
+ "ssl_algorithm": {"required": False, "type": "str",
"choices": ["low"]},
"status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "strict-guest": {"required": False, "type": "str",
+ "strict_guest": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "trace-auth-no-rsp": {"required": False, "type": "str",
+ "trace_auth_no_rsp": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "unknown-http-version": {"required": False, "type": "str",
+ "unknown_http_version": {"required": False, "type": "str",
"choices": ["reject", "best-effort"]}
}
@@ -488,14 +559,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_web_proxy_global.py b/lib/ansible/modules/network/fortios/fortios_web_proxy_global.py
index 92bd84e294..a8721bcc00 100644
--- a/lib/ansible/modules/network/fortios/fortios_web_proxy_global.py
+++ b/lib/ansible/modules/network/fortios/fortios_web_proxy_global.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_web_proxy_global
short_description: Configure Web proxy global settings in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify web_proxy feature and global category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,113 +41,140 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
web_proxy_global:
description:
- Configure Web proxy global settings.
default: null
+ type: dict
suboptions:
- fast-policy-match:
+ fast_policy_match:
description:
- Enable/disable fast matching algorithm for explicit and transparent proxy policy.
+ type: str
choices:
- enable
- disable
- forward-proxy-auth:
+ forward_proxy_auth:
description:
- Enable/disable forwarding proxy authentication headers.
+ type: str
choices:
- enable
- disable
- forward-server-affinity-timeout:
+ forward_server_affinity_timeout:
description:
- - Period of time before the source IP's traffic is no longer assigned to the forwarding server (6 - 60 min, default = 30).
- learn-client-ip:
+ - Period of time before the source IP's traffic is no longer assigned to the forwarding server (6 - 60 min).
+ type: int
+ learn_client_ip:
description:
- Enable/disable learning the client's IP address from headers.
+ type: str
choices:
- enable
- disable
- learn-client-ip-from-header:
+ learn_client_ip_from_header:
description:
- Learn client IP address from the specified headers.
+ type: str
choices:
- true-client-ip
- x-real-ip
- x-forwarded-for
- learn-client-ip-srcaddr:
+ learn_client_ip_srcaddr:
description:
- Source address name (srcaddr or srcaddr6 must be set).
+ type: list
suboptions:
name:
description:
- Address name. Source firewall.address.name firewall.addrgrp.name.
required: true
- learn-client-ip-srcaddr6:
+ type: str
+ learn_client_ip_srcaddr6:
description:
- IPv6 Source address name (srcaddr or srcaddr6 must be set).
+ type: list
suboptions:
name:
description:
- Address name. Source firewall.address6.name firewall.addrgrp6.name.
required: true
- max-message-length:
+ type: str
+ max_message_length:
description:
- - Maximum length of HTTP message, not including body (16 - 256 Kbytes, default = 32).
- max-request-length:
+ - Maximum length of HTTP message, not including body (16 - 256 Kbytes).
+ type: int
+ max_request_length:
description:
- - Maximum length of HTTP request line (2 - 64 Kbytes, default = 4).
- max-waf-body-cache-length:
+ - Maximum length of HTTP request line (2 - 64 Kbytes).
+ type: int
+ max_waf_body_cache_length:
description:
- - Maximum length of HTTP messages processed by Web Application Firewall (WAF) (10 - 1024 Kbytes, default = 32).
- proxy-fqdn:
+ - Maximum length of HTTP messages processed by Web Application Firewall (WAF) (10 - 1024 Kbytes).
+ type: int
+ proxy_fqdn:
description:
- - Fully Qualified Domain Name (FQDN) that clients connect to (default = default.fqdn) to connect to the explicit web proxy.
- strict-web-check:
+ - Fully Qualified Domain Name (FQDN) that clients connect to to connect to the explicit web proxy.
+ type: str
+ strict_web_check:
description:
- Enable/disable strict web checking to block web sites that send incorrect headers that don't conform to HTTP 1.1.
+ type: str
choices:
- enable
- disable
- tunnel-non-http:
+ tunnel_non_http:
description:
- Enable/disable allowing non-HTTP traffic. Allowed non-HTTP traffic is tunneled.
+ type: str
choices:
- enable
- disable
- unknown-http-version:
+ unknown_http_version:
description:
- "Action to take when an unknown version of HTTP is encountered: reject, allow (tunnel), or proceed with best-effort."
+ type: str
choices:
- reject
- tunnel
- best-effort
- webproxy-profile:
+ webproxy_profile:
description:
- Name of the web proxy profile to apply when explicit proxy traffic is allowed by default and traffic is accepted that does not match an
explicit proxy policy. Source web-proxy.profile.name.
+ type: str
'''
EXAMPLES = '''
@@ -157,6 +184,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure Web proxy global settings.
fortios_web_proxy_global:
@@ -166,25 +194,25 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
web_proxy_global:
- fast-policy-match: "enable"
- forward-proxy-auth: "enable"
- forward-server-affinity-timeout: "5"
- learn-client-ip: "enable"
- learn-client-ip-from-header: "true-client-ip"
- learn-client-ip-srcaddr:
+ fast_policy_match: "enable"
+ forward_proxy_auth: "enable"
+ forward_server_affinity_timeout: "5"
+ learn_client_ip: "enable"
+ learn_client_ip_from_header: "true-client-ip"
+ learn_client_ip_srcaddr:
-
name: "default_name_9 (source firewall.address.name firewall.addrgrp.name)"
- learn-client-ip-srcaddr6:
+ learn_client_ip_srcaddr6:
-
name: "default_name_11 (source firewall.address6.name firewall.addrgrp6.name)"
- max-message-length: "12"
- max-request-length: "13"
- max-waf-body-cache-length: "14"
- proxy-fqdn: "<your_own_value>"
- strict-web-check: "enable"
- tunnel-non-http: "enable"
- unknown-http-version: "reject"
- webproxy-profile: "<your_own_value> (source web-proxy.profile.name)"
+ max_message_length: "12"
+ max_request_length: "13"
+ max_waf_body_cache_length: "14"
+ proxy_fqdn: "<your_own_value>"
+ strict_web_check: "enable"
+ tunnel_non_http: "enable"
+ unknown_http_version: "reject"
+ webproxy_profile: "<your_own_value> (source web-proxy.profile.name)"
'''
RETURN = '''
@@ -247,12 +275,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -260,15 +292,15 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_web_proxy_global_data(json):
- option_list = ['fast-policy-match', 'forward-proxy-auth', 'forward-server-affinity-timeout',
- 'learn-client-ip', 'learn-client-ip-from-header', 'learn-client-ip-srcaddr',
- 'learn-client-ip-srcaddr6', 'max-message-length', 'max-request-length',
- 'max-waf-body-cache-length', 'proxy-fqdn', 'strict-web-check',
- 'tunnel-non-http', 'unknown-http-version', 'webproxy-profile']
+ option_list = ['fast_policy_match', 'forward_proxy_auth', 'forward_server_affinity_timeout',
+ 'learn_client_ip', 'learn_client_ip_from_header', 'learn_client_ip_srcaddr',
+ 'learn_client_ip_srcaddr6', 'max_message_length', 'max_request_length',
+ 'max_waf_body_cache_length', 'proxy_fqdn', 'strict_web_check',
+ 'tunnel_non_http', 'unknown_http_version', 'webproxy_profile']
dictionary = {}
for attribute in option_list:
@@ -278,10 +310,23 @@ def filter_web_proxy_global_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def web_proxy_global(data, fos):
vdom = data['vdom']
web_proxy_global_data = data['web_proxy_global']
- filtered_data = filter_web_proxy_global_data(web_proxy_global_data)
+ filtered_data = underscore_to_hyphen(filter_web_proxy_global_data(web_proxy_global_data))
return fos.set('web-proxy',
'global',
@@ -289,54 +334,60 @@ def web_proxy_global(data, fos):
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_web_proxy(data, fos):
- login(data, fos)
if data['web_proxy_global']:
resp = web_proxy_global(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"web_proxy_global": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "fast-policy-match": {"required": False, "type": "str",
+ "fast_policy_match": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "forward-proxy-auth": {"required": False, "type": "str",
+ "forward_proxy_auth": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "forward-server-affinity-timeout": {"required": False, "type": "int"},
- "learn-client-ip": {"required": False, "type": "str",
+ "forward_server_affinity_timeout": {"required": False, "type": "int"},
+ "learn_client_ip": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "learn-client-ip-from-header": {"required": False, "type": "str",
+ "learn_client_ip_from_header": {"required": False, "type": "str",
"choices": ["true-client-ip", "x-real-ip", "x-forwarded-for"]},
- "learn-client-ip-srcaddr": {"required": False, "type": "list",
+ "learn_client_ip_srcaddr": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "learn-client-ip-srcaddr6": {"required": False, "type": "list",
+ "learn_client_ip_srcaddr6": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "max-message-length": {"required": False, "type": "int"},
- "max-request-length": {"required": False, "type": "int"},
- "max-waf-body-cache-length": {"required": False, "type": "int"},
- "proxy-fqdn": {"required": False, "type": "str"},
- "strict-web-check": {"required": False, "type": "str",
+ "max_message_length": {"required": False, "type": "int"},
+ "max_request_length": {"required": False, "type": "int"},
+ "max_waf_body_cache_length": {"required": False, "type": "int"},
+ "proxy_fqdn": {"required": False, "type": "str"},
+ "strict_web_check": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "tunnel-non-http": {"required": False, "type": "str",
+ "tunnel_non_http": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "unknown-http-version": {"required": False, "type": "str",
+ "unknown_http_version": {"required": False, "type": "str",
"choices": ["reject", "tunnel", "best-effort"]},
- "webproxy-profile": {"required": False, "type": "str"}
+ "webproxy_profile": {"required": False, "type": "str"}
}
}
@@ -344,14 +395,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py b/lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py
index 6f397316aa..8c12d33baf 100644
--- a/lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py
+++ b/lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_web_proxy_profile
short_description: Configure web proxy profiles in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify web_proxy feature and profile category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,85 +41,105 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
web_proxy_profile:
description:
- Configure web proxy profiles.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
- header-client-ip:
+ header_client_ip:
description:
- "Action to take on the HTTP client-IP header in forwarded requests: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
- remove
- header-front-end-https:
+ header_front_end_https:
description:
- "Action to take on the HTTP front-end-HTTPS header in forwarded requests: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
- remove
- header-via-request:
+ header_via_request:
description:
- "Action to take on the HTTP via header in forwarded requests: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
- remove
- header-via-response:
+ header_via_response:
description:
- "Action to take on the HTTP via header in forwarded responses: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
- remove
- header-x-authenticated-groups:
+ header_x_authenticated_groups:
description:
- "Action to take on the HTTP x-authenticated-groups header in forwarded requests: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
- remove
- header-x-authenticated-user:
+ header_x_authenticated_user:
description:
- "Action to take on the HTTP x-authenticated-user header in forwarded requests: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
- remove
- header-x-forwarded-for:
+ header_x_forwarded_for:
description:
- "Action to take on the HTTP x-forwarded-for header in forwarded requests: forwards (pass), adds, or removes the HTTP header."
+ type: str
choices:
- pass
- add
@@ -127,10 +147,12 @@ options:
headers:
description:
- Configure HTTP forwarded requests headers.
+ type: list
suboptions:
action:
description:
- Action when HTTP the header forwarded.
+ type: str
choices:
- add-to-request
- add-to-response
@@ -139,16 +161,20 @@ options:
content:
description:
- HTTP header's content.
+ type: str
id:
description:
- HTTP forwarded header id.
required: true
+ type: int
name:
description:
- HTTP forwarded header name.
- log-header-change:
+ type: str
+ log_header_change:
description:
- Enable/disable logging HTTP header changes.
+ type: str
choices:
- enable
- disable
@@ -156,9 +182,11 @@ options:
description:
- Profile name.
required: true
- strip-encoding:
+ type: str
+ strip_encoding:
description:
- Enable/disable stripping unsupported encoding from the request header.
+ type: str
choices:
- enable
- disable
@@ -171,6 +199,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure web proxy profiles.
fortios_web_proxy_profile:
@@ -179,24 +208,24 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
+ state: "present"
web_proxy_profile:
- state: "present"
- header-client-ip: "pass"
- header-front-end-https: "pass"
- header-via-request: "pass"
- header-via-response: "pass"
- header-x-authenticated-groups: "pass"
- header-x-authenticated-user: "pass"
- header-x-forwarded-for: "pass"
+ header_client_ip: "pass"
+ header_front_end_https: "pass"
+ header_via_request: "pass"
+ header_via_response: "pass"
+ header_x_authenticated_groups: "pass"
+ header_x_authenticated_user: "pass"
+ header_x_forwarded_for: "pass"
headers:
-
action: "add-to-request"
content: "<your_own_value>"
id: "13"
name: "default_name_14"
- log-header-change: "enable"
+ log_header_change: "enable"
name: "default_name_16"
- strip-encoding: "enable"
+ strip_encoding: "enable"
'''
RETURN = '''
@@ -259,12 +288,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -272,14 +305,14 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_web_proxy_profile_data(json):
- option_list = ['header-client-ip', 'header-front-end-https', 'header-via-request',
- 'header-via-response', 'header-x-authenticated-groups', 'header-x-authenticated-user',
- 'header-x-forwarded-for', 'headers', 'log-header-change',
- 'name', 'strip-encoding']
+ option_list = ['header_client_ip', 'header_front_end_https', 'header_via_request',
+ 'header_via_response', 'header_x_authenticated_groups', 'header_x_authenticated_user',
+ 'header_x_forwarded_for', 'headers', 'log_header_change',
+ 'name', 'strip_encoding']
dictionary = {}
for attribute in option_list:
@@ -289,59 +322,79 @@ def filter_web_proxy_profile_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def web_proxy_profile(data, fos):
vdom = data['vdom']
+ state = data['state']
web_proxy_profile_data = data['web_proxy_profile']
- filtered_data = filter_web_proxy_profile_data(web_proxy_profile_data)
+ filtered_data = underscore_to_hyphen(filter_web_proxy_profile_data(web_proxy_profile_data))
- if web_proxy_profile_data['state'] == "present":
+ if state == "present":
return fos.set('web-proxy',
'profile',
data=filtered_data,
vdom=vdom)
- elif web_proxy_profile_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('web-proxy',
'profile',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_web_proxy(data, fos):
- login(data, fos)
if data['web_proxy_profile']:
resp = web_proxy_profile(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"web_proxy_profile": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
- "header-client-ip": {"required": False, "type": "str",
+ "header_client_ip": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
- "header-front-end-https": {"required": False, "type": "str",
+ "header_front_end_https": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
- "header-via-request": {"required": False, "type": "str",
+ "header_via_request": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
- "header-via-response": {"required": False, "type": "str",
+ "header_via_response": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
- "header-x-authenticated-groups": {"required": False, "type": "str",
+ "header_x_authenticated_groups": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
- "header-x-authenticated-user": {"required": False, "type": "str",
+ "header_x_authenticated_user": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
- "header-x-forwarded-for": {"required": False, "type": "str",
+ "header_x_forwarded_for": {"required": False, "type": "str",
"choices": ["pass", "add", "remove"]},
"headers": {"required": False, "type": "list",
"options": {
@@ -352,10 +405,10 @@ def main():
"id": {"required": True, "type": "int"},
"name": {"required": False, "type": "str"}
}},
- "log-header-change": {"required": False, "type": "str",
+ "log_header_change": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"name": {"required": True, "type": "str"},
- "strip-encoding": {"required": False, "type": "str",
+ "strip_encoding": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@@ -364,14 +417,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_web_proxy(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py b/lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py
index 5f8d2d5a4e..0f2ff208ef 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_fortiguard
-short_description: Configure FortiGuard Web Filter service.
+short_description: Configure FortiGuard Web Filter service in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and fortiguard category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and fortiguard category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,79 +41,100 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
type: bool
- default: false
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
+ type: bool
+ default: true
+ version_added: 2.9
webfilter_fortiguard:
description:
- Configure FortiGuard Web Filter service.
default: null
+ type: dict
suboptions:
- cache-mem-percent:
+ cache_mem_percent:
description:
- Maximum percentage of available memory allocated to caching (1 - 15%).
- cache-mode:
+ type: int
+ cache_mode:
description:
- Cache entry expiration mode.
+ type: str
choices:
- ttl
- db-ver
- cache-prefix-match:
+ cache_prefix_match:
description:
- Enable/disable prefix matching in the cache.
+ type: str
choices:
- enable
- disable
- close-ports:
+ close_ports:
description:
- Close ports used for HTTP/HTTPS override authentication and disable user overrides.
+ type: str
choices:
- enable
- disable
- ovrd-auth-https:
+ ovrd_auth_https:
description:
- Enable/disable use of HTTPS for override authentication.
+ type: str
choices:
- enable
- disable
- ovrd-auth-port:
+ ovrd_auth_port:
description:
- Port to use for FortiGuard Web Filter override authentication.
- ovrd-auth-port-http:
+ type: int
+ ovrd_auth_port_http:
description:
- Port to use for FortiGuard Web Filter HTTP override authentication
- ovrd-auth-port-https:
+ type: int
+ ovrd_auth_port_https:
description:
- Port to use for FortiGuard Web Filter HTTPS override authentication.
- ovrd-auth-port-warning:
+ type: int
+ ovrd_auth_port_warning:
description:
- Port to use for FortiGuard Web Filter Warning override authentication.
- request-packet-size-limit:
+ type: int
+ request_packet_size_limit:
description:
- Limit size of URL request packets sent to FortiGuard server (0 for default).
- warn-auth-https:
+ type: int
+ warn_auth_https:
description:
- Enable/disable use of HTTPS for warning and authentication.
+ type: str
choices:
- enable
- disable
@@ -129,25 +147,27 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure FortiGuard Web Filter service.
fortios_webfilter_fortiguard:
- host: "{{ host }}"
+ host: "{{ host }}"
username: "{{ username }}"
password: "{{ password }}"
- vdom: "{{ vdom }}"
+ vdom: "{{ vdom }}"
+ https: "False"
webfilter_fortiguard:
- cache-mem-percent: "3"
- cache-mode: "ttl"
- cache-prefix-match: "enable"
- close-ports: "enable"
- ovrd-auth-https: "enable"
- ovrd-auth-port: "8"
- ovrd-auth-port-http: "9"
- ovrd-auth-port-https: "10"
- ovrd-auth-port-warning: "11"
- request-packet-size-limit: "12"
- warn-auth-https: "enable"
+ cache_mem_percent: "3"
+ cache_mode: "ttl"
+ cache_prefix_match: "enable"
+ close_ports: "enable"
+ ovrd_auth_https: "enable"
+ ovrd_auth_port: "8"
+ ovrd_auth_port_http: "9"
+ ovrd_auth_port_https: "10"
+ ovrd_auth_port_warning: "11"
+ request_packet_size_limit: "12"
+ warn_auth_https: "enable"
'''
RETURN = '''
@@ -170,7 +190,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -210,14 +230,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -225,75 +247,88 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_fortiguard_data(json):
- option_list = ['cache-mem-percent', 'cache-mode', 'cache-prefix-match',
- 'close-ports', 'ovrd-auth-https', 'ovrd-auth-port',
- 'ovrd-auth-port-http', 'ovrd-auth-port-https', 'ovrd-auth-port-warning',
- 'request-packet-size-limit', 'warn-auth-https']
+ option_list = ['cache_mem_percent', 'cache_mode', 'cache_prefix_match',
+ 'close_ports', 'ovrd_auth_https', 'ovrd_auth_port',
+ 'ovrd_auth_port_http', 'ovrd_auth_port_https', 'ovrd_auth_port_warning',
+ 'request_packet_size_limit', 'warn_auth_https']
dictionary = {}
for attribute in option_list:
- if attribute in json:
+ if attribute in json and json[attribute] is not None:
dictionary[attribute] = json[attribute]
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_fortiguard(data, fos):
vdom = data['vdom']
webfilter_fortiguard_data = data['webfilter_fortiguard']
- filtered_data = filter_webfilter_fortiguard_data(webfilter_fortiguard_data)
+ filtered_data = underscore_to_hyphen(filter_webfilter_fortiguard_data(webfilter_fortiguard_data))
+
return fos.set('webfilter',
'fortiguard',
data=filtered_data,
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- host = data['host']
- username = data['username']
- password = data['password']
- fos.https('off')
- fos.login(host, username, password)
- methodlist = ['webfilter_fortiguard']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_fortiguard']:
+ resp = webfilter_fortiguard(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"webfilter_fortiguard": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "cache-mem-percent": {"required": False, "type": "int"},
- "cache-mode": {"required": False, "type": "str",
+ "cache_mem_percent": {"required": False, "type": "int"},
+ "cache_mode": {"required": False, "type": "str",
"choices": ["ttl", "db-ver"]},
- "cache-prefix-match": {"required": False, "type": "str",
+ "cache_prefix_match": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "close-ports": {"required": False, "type": "str",
+ "close_ports": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ovrd-auth-https": {"required": False, "type": "str",
+ "ovrd_auth_https": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ovrd-auth-port": {"required": False, "type": "int"},
- "ovrd-auth-port-http": {"required": False, "type": "int"},
- "ovrd-auth-port-https": {"required": False, "type": "int"},
- "ovrd-auth-port-warning": {"required": False, "type": "int"},
- "request-packet-size-limit": {"required": False, "type": "int"},
- "warn-auth-https": {"required": False, "type": "str",
+ "ovrd_auth_port": {"required": False, "type": "int"},
+ "ovrd_auth_port_http": {"required": False, "type": "int"},
+ "ovrd_auth_port_https": {"required": False, "type": "int"},
+ "ovrd_auth_port_warning": {"required": False, "type": "int"},
+ "request_packet_size_limit": {"required": False, "type": "int"},
+ "warn_auth_https": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@@ -302,14 +337,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_cat.py b/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_cat.py
index 0642c7c88c..e862a3be4d 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_cat.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_cat.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_ftgd_local_cat
-short_description: Configure FortiGuard Web Filter local categories.
+short_description: Configure FortiGuard Web Filter local categories in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and ftgd_local_cat category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and ftgd_local_cat category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,50 +41,66 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
webfilter_ftgd_local_cat:
description:
- Configure FortiGuard Web Filter local categories.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
desc:
description:
- Local category description.
required: true
+ type: str
id:
description:
- Local category ID.
+ type: int
status:
description:
- Enable/disable the local category.
+ type: str
choices:
- enable
- disable
@@ -100,6 +113,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure FortiGuard Web Filter local categories.
fortios_webfilter_ftgd_local_cat:
@@ -107,8 +121,9 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
+ state: "present"
webfilter_ftgd_local_cat:
- state: "present"
desc: "<your_own_value>"
id: "4"
status: "enable"
@@ -134,7 +149,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -174,14 +189,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -189,7 +206,7 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_ftgd_local_cat_data(json):
@@ -197,55 +214,72 @@ def filter_webfilter_ftgd_local_cat_data(json):
dictionary = {}
for attribute in option_list:
- if attribute in json:
+ if attribute in json and json[attribute] is not None:
dictionary[attribute] = json[attribute]
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_ftgd_local_cat(data, fos):
vdom = data['vdom']
+ state = data['state']
webfilter_ftgd_local_cat_data = data['webfilter_ftgd_local_cat']
- filtered_data = filter_webfilter_ftgd_local_cat_data(
- webfilter_ftgd_local_cat_data)
- if webfilter_ftgd_local_cat_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_webfilter_ftgd_local_cat_data(webfilter_ftgd_local_cat_data))
+
+ if state == "present":
return fos.set('webfilter',
'ftgd-local-cat',
data=filtered_data,
vdom=vdom)
- elif webfilter_ftgd_local_cat_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('webfilter',
'ftgd-local-cat',
mkey=filtered_data['desc'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_ftgd_local_cat']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_ftgd_local_cat']:
+ resp = webfilter_ftgd_local_cat(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"webfilter_ftgd_local_cat": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"desc": {"required": True, "type": "str"},
"id": {"required": False, "type": "int"},
"status": {"required": False, "type": "str",
@@ -257,15 +291,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_rating.py b/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_rating.py
index 379ba5e903..b44d0efb6a 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_rating.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_rating.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_ftgd_local_rating
-short_description: Configure local FortiGuard Web Filter local ratings.
+short_description: Configure local FortiGuard Web Filter local ratings in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and ftgd_local_rating category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and ftgd_local_rating category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,46 +41,61 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
webfilter_ftgd_local_rating:
description:
- Configure local FortiGuard Web Filter local ratings.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
rating:
description:
- Local rating.
+ type: str
status:
description:
- Enable/disable local rating.
+ type: str
choices:
- enable
- disable
@@ -91,6 +103,7 @@ options:
description:
- URL to rate locally.
required: true
+ type: str
'''
EXAMPLES = '''
@@ -100,6 +113,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure local FortiGuard Web Filter local ratings.
fortios_webfilter_ftgd_local_rating:
@@ -107,8 +121,9 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
+ state: "present"
webfilter_ftgd_local_rating:
- state: "present"
rating: "<your_own_value>"
status: "enable"
url: "myurl.com"
@@ -134,7 +149,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -174,14 +189,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -189,7 +206,7 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_ftgd_local_rating_data(json):
@@ -197,55 +214,72 @@ def filter_webfilter_ftgd_local_rating_data(json):
dictionary = {}
for attribute in option_list:
- if attribute in json:
+ if attribute in json and json[attribute] is not None:
dictionary[attribute] = json[attribute]
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_ftgd_local_rating(data, fos):
vdom = data['vdom']
+ state = data['state']
webfilter_ftgd_local_rating_data = data['webfilter_ftgd_local_rating']
- filtered_data = filter_webfilter_ftgd_local_rating_data(
- webfilter_ftgd_local_rating_data)
- if webfilter_ftgd_local_rating_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_webfilter_ftgd_local_rating_data(webfilter_ftgd_local_rating_data))
+
+ if state == "present":
return fos.set('webfilter',
'ftgd-local-rating',
data=filtered_data,
vdom=vdom)
- elif webfilter_ftgd_local_rating_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('webfilter',
'ftgd-local-rating',
mkey=filtered_data['url'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_ftgd_local_rating']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_ftgd_local_rating']:
+ resp = webfilter_ftgd_local_rating(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"webfilter_ftgd_local_rating": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"rating": {"required": False, "type": "str"},
"status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
@@ -257,15 +291,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py b/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py
index 69dbbcc06a..baf72727ec 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_ips_urlfilter_cache_setting
-short_description: Configure IPS URL filter cache settings.
+short_description: Configure IPS URL filter cache settings in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and ips_urlfilter_cache_setting category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and ips_urlfilter_cache_setting category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,40 +41,52 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
webfilter_ips_urlfilter_cache_setting:
description:
- Configure IPS URL filter cache settings.
default: null
+ type: dict
suboptions:
- dns-retry-interval:
+ dns_retry_interval:
description:
- Retry interval. Refresh DNS faster than TTL to capture multiple IPs for hosts. 0 means use DNS server's TTL only.
- extended-ttl:
+ type: int
+ extended_ttl:
description:
- Extend time to live beyond reported by DNS. 0 means use DNS server's TTL
+ type: int
'''
EXAMPLES = '''
@@ -87,6 +96,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure IPS URL filter cache settings.
fortios_webfilter_ips_urlfilter_cache_setting:
@@ -94,9 +104,10 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
webfilter_ips_urlfilter_cache_setting:
- dns-retry-interval: "3"
- extended-ttl: "4"
+ dns_retry_interval: "3"
+ extended_ttl: "4"
'''
RETURN = '''
@@ -119,7 +130,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -159,14 +170,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-fos = None
-
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -174,11 +187,11 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_ips_urlfilter_cache_setting_data(json):
- option_list = ['dns-retry-interval', 'extended-ttl']
+ option_list = ['dns_retry_interval', 'extended_ttl']
dictionary = {}
for attribute in option_list:
@@ -188,42 +201,58 @@ def filter_webfilter_ips_urlfilter_cache_setting_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_ips_urlfilter_cache_setting(data, fos):
vdom = data['vdom']
webfilter_ips_urlfilter_cache_setting_data = data['webfilter_ips_urlfilter_cache_setting']
- filtered_data = filter_webfilter_ips_urlfilter_cache_setting_data(
- webfilter_ips_urlfilter_cache_setting_data)
+ filtered_data = underscore_to_hyphen(filter_webfilter_ips_urlfilter_cache_setting_data(webfilter_ips_urlfilter_cache_setting_data))
+
return fos.set('webfilter',
'ips-urlfilter-cache-setting',
data=filtered_data,
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_ips_urlfilter_cache_setting']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_ips_urlfilter_cache_setting']:
+ resp = webfilter_ips_urlfilter_cache_setting(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"webfilter_ips_urlfilter_cache_setting": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "dns-retry-interval": {"required": False, "type": "int"},
- "extended-ttl": {"required": False, "type": "int"}
+ "dns_retry_interval": {"required": False, "type": "int"},
+ "extended_ttl": {"required": False, "type": "int"}
}
}
@@ -231,15 +260,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py b/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py
index d05b42141a..aa4c9b2167 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_ips_urlfilter_setting
-short_description: Configure IPS URL filter settings.
+short_description: Configure IPS URL filter settings in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and ips_urlfilter_setting category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and ips_urlfilter_setting category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,46 +41,60 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
webfilter_ips_urlfilter_setting:
description:
- Configure IPS URL filter settings.
default: null
+ type: dict
suboptions:
device:
description:
- Interface for this route. Source system.interface.name.
+ type: str
distance:
description:
- Administrative distance (1 - 255) for this route.
+ type: int
gateway:
description:
- Gateway IP address for this route.
- geo-filter:
+ type: str
+ geo_filter:
description:
- Filter based on geographical location. Route will NOT be installed if the resolved IP address belongs to the country in the filter.
+ type: str
'''
EXAMPLES = '''
@@ -93,6 +104,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure IPS URL filter settings.
fortios_webfilter_ips_urlfilter_setting:
@@ -100,11 +112,12 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
webfilter_ips_urlfilter_setting:
device: "<your_own_value> (source system.interface.name)"
distance: "4"
gateway: "<your_own_value>"
- geo-filter: "<your_own_value>"
+ geo_filter: "<your_own_value>"
'''
RETURN = '''
@@ -127,7 +140,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -167,14 +180,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-fos = None
-
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -182,12 +197,12 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_ips_urlfilter_setting_data(json):
option_list = ['device', 'distance', 'gateway',
- 'geo-filter']
+ 'geo_filter']
dictionary = {}
for attribute in option_list:
@@ -197,44 +212,60 @@ def filter_webfilter_ips_urlfilter_setting_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_ips_urlfilter_setting(data, fos):
vdom = data['vdom']
webfilter_ips_urlfilter_setting_data = data['webfilter_ips_urlfilter_setting']
- filtered_data = filter_webfilter_ips_urlfilter_setting_data(
- webfilter_ips_urlfilter_setting_data)
+ filtered_data = underscore_to_hyphen(filter_webfilter_ips_urlfilter_setting_data(webfilter_ips_urlfilter_setting_data))
+
return fos.set('webfilter',
'ips-urlfilter-setting',
data=filtered_data,
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_ips_urlfilter_setting']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_ips_urlfilter_setting']:
+ resp = webfilter_ips_urlfilter_setting(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"webfilter_ips_urlfilter_setting": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
"device": {"required": False, "type": "str"},
"distance": {"required": False, "type": "int"},
"gateway": {"required": False, "type": "str"},
- "geo-filter": {"required": False, "type": "str"}
+ "geo_filter": {"required": False, "type": "str"}
}
}
@@ -242,15 +273,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py b/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py
index 3334403134..102b583dcc 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_ips_urlfilter_setting6
-short_description: Configure IPS URL filter settings for IPv6.
+short_description: Configure IPS URL filter settings for IPv6 in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and ips_urlfilter_setting6 category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and ips_urlfilter_setting6 category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,46 +41,60 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
webfilter_ips_urlfilter_setting6:
description:
- Configure IPS URL filter settings for IPv6.
default: null
+ type: dict
suboptions:
device:
description:
- Interface for this route. Source system.interface.name.
+ type: str
distance:
description:
- Administrative distance (1 - 255) for this route.
+ type: int
gateway6:
description:
- Gateway IPv6 address for this route.
- geo-filter:
+ type: str
+ geo_filter:
description:
- Filter based on geographical location. Route will NOT be installed if the resolved IPv6 address belongs to the country in the filter.
+ type: str
'''
EXAMPLES = '''
@@ -93,6 +104,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure IPS URL filter settings for IPv6.
fortios_webfilter_ips_urlfilter_setting6:
@@ -100,11 +112,12 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
webfilter_ips_urlfilter_setting6:
device: "<your_own_value> (source system.interface.name)"
distance: "4"
gateway6: "<your_own_value>"
- geo-filter: "<your_own_value>"
+ geo_filter: "<your_own_value>"
'''
RETURN = '''
@@ -127,7 +140,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -167,14 +180,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-fos = None
-
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -182,12 +197,12 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_ips_urlfilter_setting6_data(json):
option_list = ['device', 'distance', 'gateway6',
- 'geo-filter']
+ 'geo_filter']
dictionary = {}
for attribute in option_list:
@@ -197,44 +212,60 @@ def filter_webfilter_ips_urlfilter_setting6_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_ips_urlfilter_setting6(data, fos):
vdom = data['vdom']
webfilter_ips_urlfilter_setting6_data = data['webfilter_ips_urlfilter_setting6']
- filtered_data = filter_webfilter_ips_urlfilter_setting6_data(
- webfilter_ips_urlfilter_setting6_data)
+ filtered_data = underscore_to_hyphen(filter_webfilter_ips_urlfilter_setting6_data(webfilter_ips_urlfilter_setting6_data))
+
return fos.set('webfilter',
'ips-urlfilter-setting6',
data=filtered_data,
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_ips_urlfilter_setting6']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_ips_urlfilter_setting6']:
+ resp = webfilter_ips_urlfilter_setting6(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"webfilter_ips_urlfilter_setting6": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
"device": {"required": False, "type": "str"},
"distance": {"required": False, "type": "int"},
"gateway6": {"required": False, "type": "str"},
- "geo-filter": {"required": False, "type": "str"}
+ "geo_filter": {"required": False, "type": "str"}
}
}
@@ -242,15 +273,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_override.py b/lib/ansible/modules/network/fortios/fortios_webfilter_override.py
index fa962b1292..42233c95f9 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_override.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_override.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_override
-short_description: Configure FortiGuard Web Filter administrative overrides.
+short_description: Configure FortiGuard Web Filter administrative overrides in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and override category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and override category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,65 +41,86 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
webfilter_override:
description:
- Configure FortiGuard Web Filter administrative overrides.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
expires:
description:
- "Override expiration date and time, from 5 minutes to 365 from now (format: yyyy/mm/dd hh:mm:ss)."
+ type: str
id:
description:
- Override rule ID.
required: true
+ type: int
initiator:
description:
- Initiating user of override (read-only setting).
+ type: str
ip:
description:
- IPv4 address which the override applies.
+ type: str
ip6:
description:
- IPv6 address which the override applies.
- new-profile:
+ type: str
+ new_profile:
description:
- Name of the new web filter profile used by the override. Source webfilter.profile.name.
- old-profile:
+ type: str
+ old_profile:
description:
- Name of the web filter profile which the override applies. Source webfilter.profile.name.
+ type: str
scope:
description:
- Override either the specific user, user group, IPv4 address, or IPv6 address.
+ type: str
choices:
- user
- user-group
@@ -111,15 +129,18 @@ options:
status:
description:
- Enable/disable override rule.
+ type: str
choices:
- enable
- disable
user:
description:
- Name of the user which the override applies.
- user-group:
+ type: str
+ user_group:
description:
- Specify the user group for which the override applies. Source user.group.name.
+ type: str
'''
EXAMPLES = '''
@@ -129,6 +150,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure FortiGuard Web Filter administrative overrides.
fortios_webfilter_override:
@@ -136,19 +158,20 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
+ state: "present"
webfilter_override:
- state: "present"
expires: "<your_own_value>"
id: "4"
initiator: "<your_own_value>"
ip: "<your_own_value>"
ip6: "<your_own_value>"
- new-profile: "<your_own_value> (source webfilter.profile.name)"
- old-profile: "<your_own_value> (source webfilter.profile.name)"
+ new_profile: "<your_own_value> (source webfilter.profile.name)"
+ old_profile: "<your_own_value> (source webfilter.profile.name)"
scope: "user"
status: "enable"
user: "<your_own_value>"
- user-group: "<your_own_value> (source user.group.name)"
+ user_group: "<your_own_value> (source user.group.name)"
'''
RETURN = '''
@@ -171,7 +194,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -211,14 +234,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -226,14 +251,14 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_override_data(json):
option_list = ['expires', 'id', 'initiator',
- 'ip', 'ip6', 'new-profile',
- 'old-profile', 'scope', 'status',
- 'user', 'user-group']
+ 'ip', 'ip6', 'new_profile',
+ 'old_profile', 'scope', 'status',
+ 'user', 'user_group']
dictionary = {}
for attribute in option_list:
@@ -243,62 +268,80 @@ def filter_webfilter_override_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_override(data, fos):
vdom = data['vdom']
+ state = data['state']
webfilter_override_data = data['webfilter_override']
- filtered_data = filter_webfilter_override_data(webfilter_override_data)
- if webfilter_override_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_webfilter_override_data(webfilter_override_data))
+
+ if state == "present":
return fos.set('webfilter',
'override',
data=filtered_data,
vdom=vdom)
- elif webfilter_override_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('webfilter',
'override',
mkey=filtered_data['id'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_override']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_override']:
+ resp = webfilter_override(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"webfilter_override": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"expires": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"},
"initiator": {"required": False, "type": "str"},
"ip": {"required": False, "type": "str"},
"ip6": {"required": False, "type": "str"},
- "new-profile": {"required": False, "type": "str"},
- "old-profile": {"required": False, "type": "str"},
+ "new_profile": {"required": False, "type": "str"},
+ "old_profile": {"required": False, "type": "str"},
"scope": {"required": False, "type": "str",
"choices": ["user", "user-group", "ip",
"ip6"]},
"status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"user": {"required": False, "type": "str"},
- "user-group": {"required": False, "type": "str"}
+ "user_group": {"required": False, "type": "str"}
}
}
@@ -306,15 +349,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_profile.py b/lib/ansible/modules/network/fortios/fortios_webfilter_profile.py
index 8fc7b6c1a7..7bb2df36c2 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_profile.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_profile.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_profile
-short_description: Configure Web filter profiles.
+short_description: Configure Web filter profiles in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and profile category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and profile category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,113 +41,143 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
webfilter_profile:
description:
- Configure Web filter profiles.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
comment:
description:
- Optional comments.
- extended-log:
+ type: str
+ extended_log:
description:
- Enable/disable extended logging for web filtering.
+ type: str
choices:
- enable
- disable
- ftgd-wf:
+ ftgd_wf:
description:
- FortiGuard Web Filter settings.
+ type: dict
suboptions:
- exempt-quota:
+ exempt_quota:
description:
- Do not stop quota for these categories.
+ type: str
filters:
description:
- FortiGuard filters.
+ type: list
suboptions:
action:
description:
- Action to take for matches.
+ type: str
choices:
- block
- authenticate
- monitor
- warning
- auth-usr-grp:
+ auth_usr_grp:
description:
- Groups with permission to authenticate.
+ type: str
suboptions:
name:
description:
- User group name. Source user.group.name.
required: true
+ type: str
category:
description:
- Categories and groups the filter examines.
+ type: int
id:
description:
- ID number.
required: true
+ type: int
log:
description:
- Enable/disable logging.
+ type: str
choices:
- enable
- disable
- override-replacemsg:
+ override_replacemsg:
description:
- Override replacement message.
- warn-duration:
+ type: str
+ warn_duration:
description:
- Duration of warnings.
- warning-duration-type:
+ type: str
+ warning_duration_type:
description:
- Re-display warning after closing browser or after a timeout.
+ type: str
choices:
- session
- timeout
- warning-prompt:
+ warning_prompt:
description:
- Warning prompts in each category or each domain.
+ type: str
choices:
- per-domain
- per-category
- max-quota-timeout:
+ max_quota_timeout:
description:
- Maximum FortiGuard quota used by single page view in seconds (excludes streams).
+ type: int
options:
description:
- Options for FortiGuard Web Filter.
+ type: str
choices:
- error-allow
- rate-server-ip
@@ -159,32 +186,40 @@ options:
ovrd:
description:
- Allow web filter profile overrides.
+ type: str
quota:
description:
- FortiGuard traffic quota settings.
+ type: list
suboptions:
category:
description:
- FortiGuard categories to apply quota to (category action must be set to monitor).
+ type: str
duration:
description:
- Duration of quota.
+ type: str
id:
description:
- ID number.
required: true
- override-replacemsg:
+ type: int
+ override_replacemsg:
description:
- Override replacement message.
+ type: str
type:
description:
- Quota type.
+ type: str
choices:
- time
- traffic
unit:
description:
- Traffic quota unit of measurement.
+ type: str
choices:
- B
- KB
@@ -193,45 +228,53 @@ options:
value:
description:
- Traffic quota value.
- rate-crl-urls:
+ type: int
+ rate_crl_urls:
description:
- Enable/disable rating CRL by URL.
+ type: str
choices:
- disable
- enable
- rate-css-urls:
+ rate_css_urls:
description:
- Enable/disable rating CSS by URL.
+ type: str
choices:
- disable
- enable
- rate-image-urls:
+ rate_image_urls:
description:
- Enable/disable rating images by URL.
+ type: str
choices:
- disable
- enable
- rate-javascript-urls:
+ rate_javascript_urls:
description:
- Enable/disable rating JavaScript by URL.
+ type: str
choices:
- disable
- enable
- https-replacemsg:
+ https_replacemsg:
description:
- Enable replacement messages for HTTPS.
+ type: str
choices:
- enable
- disable
- inspection-mode:
+ inspection_mode:
description:
- Web filtering inspection mode.
+ type: str
choices:
- proxy
- flow-based
- log-all-url:
+ log_all_url:
description:
- Enable/disable logging all URLs visited.
+ type: str
choices:
- enable
- disable
@@ -239,9 +282,11 @@ options:
description:
- Profile name.
required: true
+ type: str
options:
description:
- Options.
+ type: str
choices:
- activexfilter
- cookiefilter
@@ -258,50 +303,60 @@ options:
override:
description:
- Web Filter override settings.
+ type: dict
suboptions:
- ovrd-cookie:
+ ovrd_cookie:
description:
- Allow/deny browser-based (cookie) overrides.
+ type: str
choices:
- allow
- deny
- ovrd-dur:
+ ovrd_dur:
description:
- Override duration.
- ovrd-dur-mode:
+ type: str
+ ovrd_dur_mode:
description:
- Override duration mode.
+ type: str
choices:
- constant
- ask
- ovrd-scope:
+ ovrd_scope:
description:
- Override scope.
+ type: str
choices:
- user
- user-group
- ip
- browser
- ask
- ovrd-user-group:
+ ovrd_user_group:
description:
- User groups with permission to use the override.
+ type: str
suboptions:
name:
description:
- User group name. Source user.group.name.
required: true
+ type: str
profile:
description:
- Web filter profile with permission to create overrides.
+ type: list
suboptions:
name:
description:
- Web profile. Source webfilter.profile.name.
required: true
- profile-attribute:
+ type: str
+ profile_attribute:
description:
- Profile attribute to retrieve from the RADIUS server.
+ type: str
choices:
- User-Name
- NAS-IP-Address
@@ -325,74 +380,89 @@ options:
- Framed-AppleTalk-Zone
- Acct-Session-Id
- Acct-Multi-Session-Id
- profile-type:
+ profile_type:
description:
- Override profile type.
+ type: str
choices:
- list
- radius
- ovrd-perm:
+ ovrd_perm:
description:
- Permitted override types.
+ type: str
choices:
- bannedword-override
- urlfilter-override
- fortiguard-wf-override
- contenttype-check-override
- post-action:
+ post_action:
description:
- Action taken for HTTP POST traffic.
+ type: str
choices:
- normal
- block
- replacemsg-group:
+ replacemsg_group:
description:
- Replacement message group. Source system.replacemsg-group.name.
+ type: str
web:
description:
- Web content filtering settings.
+ type: dict
suboptions:
blacklist:
description:
- Enable/disable automatic addition of URLs detected by FortiSandbox to blacklist.
+ type: str
choices:
- enable
- disable
- bword-table:
+ bword_table:
description:
- Banned word table ID. Source webfilter.content.id.
- bword-threshold:
+ type: int
+ bword_threshold:
description:
- Banned word score threshold.
- content-header-list:
+ type: int
+ content_header_list:
description:
- Content header list. Source webfilter.content-header.id.
- keyword-match:
+ type: int
+ keyword_match:
description:
- Search keywords to log when match is found.
+ type: str
suboptions:
pattern:
description:
- Pattern/keyword to search for.
required: true
- log-search:
+ type: str
+ log_search:
description:
- Enable/disable logging all search phrases.
+ type: str
choices:
- enable
- disable
- safe-search:
+ safe_search:
description:
- Safe search type.
+ type: str
choices:
- url
- header
- urlfilter-table:
+ urlfilter_table:
description:
- URL filter table ID. Source webfilter.urlfilter.id.
+ type: int
whitelist:
description:
- FortiGuard whitelist settings.
+ type: str
choices:
- exempt-av
- exempt-webcontent
@@ -400,147 +470,173 @@ options:
- exempt-dlp
- exempt-rangeblock
- extended-log-others
- youtube-restrict:
+ youtube_restrict:
description:
- YouTube EDU filter level.
+ type: str
choices:
- none
- strict
- moderate
- web-content-log:
+ web_content_log:
description:
- Enable/disable logging logging blocked web content.
+ type: str
choices:
- enable
- disable
- web-extended-all-action-log:
+ web_extended_all_action_log:
description:
- Enable/disable extended any filter action logging for web filtering.
+ type: str
choices:
- enable
- disable
- web-filter-activex-log:
+ web_filter_activex_log:
description:
- Enable/disable logging ActiveX.
+ type: str
choices:
- enable
- disable
- web-filter-applet-log:
+ web_filter_applet_log:
description:
- Enable/disable logging Java applets.
+ type: str
choices:
- enable
- disable
- web-filter-command-block-log:
+ web_filter_command_block_log:
description:
- Enable/disable logging blocked commands.
+ type: str
choices:
- enable
- disable
- web-filter-cookie-log:
+ web_filter_cookie_log:
description:
- Enable/disable logging cookie filtering.
+ type: str
choices:
- enable
- disable
- web-filter-cookie-removal-log:
+ web_filter_cookie_removal_log:
description:
- Enable/disable logging blocked cookies.
+ type: str
choices:
- enable
- disable
- web-filter-js-log:
+ web_filter_js_log:
description:
- Enable/disable logging Java scripts.
+ type: str
choices:
- enable
- disable
- web-filter-jscript-log:
+ web_filter_jscript_log:
description:
- Enable/disable logging JScripts.
+ type: str
choices:
- enable
- disable
- web-filter-referer-log:
+ web_filter_referer_log:
description:
- Enable/disable logging referrers.
+ type: str
choices:
- enable
- disable
- web-filter-unknown-log:
+ web_filter_unknown_log:
description:
- Enable/disable logging unknown scripts.
+ type: str
choices:
- enable
- disable
- web-filter-vbs-log:
+ web_filter_vbs_log:
description:
- Enable/disable logging VBS scripts.
+ type: str
choices:
- enable
- disable
- web-ftgd-err-log:
+ web_ftgd_err_log:
description:
- Enable/disable logging rating errors.
+ type: str
choices:
- enable
- disable
- web-ftgd-quota-usage:
+ web_ftgd_quota_usage:
description:
- Enable/disable logging daily quota usage.
+ type: str
choices:
- enable
- disable
- web-invalid-domain-log:
+ web_invalid_domain_log:
description:
- Enable/disable logging invalid domain names.
+ type: str
choices:
- enable
- disable
- web-url-log:
+ web_url_log:
description:
- Enable/disable logging URL filtering.
+ type: str
choices:
- enable
- disable
wisp:
description:
- Enable/disable web proxy WISP.
+ type: str
choices:
- enable
- disable
- wisp-algorithm:
+ wisp_algorithm:
description:
- WISP server selection algorithm.
+ type: str
choices:
- primary-secondary
- round-robin
- auto-learning
- wisp-servers:
+ wisp_servers:
description:
- WISP servers.
+ type: list
suboptions:
name:
description:
- Server name. Source web-proxy.wisp.name.
required: true
- youtube-channel-filter:
+ type: str
+ youtube_channel_filter:
description:
- YouTube channel filter.
+ type: list
suboptions:
- channel-id:
+ channel_id:
description:
- YouTube channel ID to be filtered.
+ type: str
comment:
description:
- Comment.
+ type: str
id:
description:
- ID.
required: true
- youtube-channel-status:
+ type: int
+ youtube_channel_status:
description:
- YouTube channel filter status.
+ type: str
choices:
- disable
- blacklist
@@ -554,6 +650,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure Web filter profiles.
fortios_webfilter_profile:
@@ -561,26 +658,27 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
+ state: "present"
webfilter_profile:
- state: "present"
comment: "Optional comments."
- extended-log: "enable"
- ftgd-wf:
- exempt-quota: "<your_own_value>"
+ extended_log: "enable"
+ ftgd_wf:
+ exempt_quota: "<your_own_value>"
filters:
-
action: "block"
- auth-usr-grp:
+ auth_usr_grp:
-
name: "default_name_10 (source user.group.name)"
category: "11"
id: "12"
log: "enable"
- override-replacemsg: "<your_own_value>"
- warn-duration: "<your_own_value>"
- warning-duration-type: "session"
- warning-prompt: "per-domain"
- max-quota-timeout: "18"
+ override_replacemsg: "<your_own_value>"
+ warn_duration: "<your_own_value>"
+ warning_duration_type: "session"
+ warning_prompt: "per-domain"
+ max_quota_timeout: "18"
options: "error-allow"
ovrd: "<your_own_value>"
quota:
@@ -588,75 +686,75 @@ EXAMPLES = '''
category: "<your_own_value>"
duration: "<your_own_value>"
id: "24"
- override-replacemsg: "<your_own_value>"
+ override_replacemsg: "<your_own_value>"
type: "time"
unit: "B"
value: "28"
- rate-crl-urls: "disable"
- rate-css-urls: "disable"
- rate-image-urls: "disable"
- rate-javascript-urls: "disable"
- https-replacemsg: "enable"
- inspection-mode: "proxy"
- log-all-url: "enable"
+ rate_crl_urls: "disable"
+ rate_css_urls: "disable"
+ rate_image_urls: "disable"
+ rate_javascript_urls: "disable"
+ https_replacemsg: "enable"
+ inspection_mode: "proxy"
+ log_all_url: "enable"
name: "default_name_36"
options: "activexfilter"
override:
- ovrd-cookie: "allow"
- ovrd-dur: "<your_own_value>"
- ovrd-dur-mode: "constant"
- ovrd-scope: "user"
- ovrd-user-group:
+ ovrd_cookie: "allow"
+ ovrd_dur: "<your_own_value>"
+ ovrd_dur_mode: "constant"
+ ovrd_scope: "user"
+ ovrd_user_group:
-
name: "default_name_44 (source user.group.name)"
profile:
-
name: "default_name_46 (source webfilter.profile.name)"
- profile-attribute: "User-Name"
- profile-type: "list"
- ovrd-perm: "bannedword-override"
- post-action: "normal"
- replacemsg-group: "<your_own_value> (source system.replacemsg-group.name)"
+ profile_attribute: "User-Name"
+ profile_type: "list"
+ ovrd_perm: "bannedword-override"
+ post_action: "normal"
+ replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)"
web:
blacklist: "enable"
- bword-table: "54 (source webfilter.content.id)"
- bword-threshold: "55"
- content-header-list: "56 (source webfilter.content-header.id)"
- keyword-match:
+ bword_table: "54 (source webfilter.content.id)"
+ bword_threshold: "55"
+ content_header_list: "56 (source webfilter.content-header.id)"
+ keyword_match:
-
pattern: "<your_own_value>"
- log-search: "enable"
- safe-search: "url"
- urlfilter-table: "61 (source webfilter.urlfilter.id)"
+ log_search: "enable"
+ safe_search: "url"
+ urlfilter_table: "61 (source webfilter.urlfilter.id)"
whitelist: "exempt-av"
- youtube-restrict: "none"
- web-content-log: "enable"
- web-extended-all-action-log: "enable"
- web-filter-activex-log: "enable"
- web-filter-applet-log: "enable"
- web-filter-command-block-log: "enable"
- web-filter-cookie-log: "enable"
- web-filter-cookie-removal-log: "enable"
- web-filter-js-log: "enable"
- web-filter-jscript-log: "enable"
- web-filter-referer-log: "enable"
- web-filter-unknown-log: "enable"
- web-filter-vbs-log: "enable"
- web-ftgd-err-log: "enable"
- web-ftgd-quota-usage: "enable"
- web-invalid-domain-log: "enable"
- web-url-log: "enable"
+ youtube_restrict: "none"
+ web_content_log: "enable"
+ web_extended_all_action_log: "enable"
+ web_filter_activex_log: "enable"
+ web_filter_applet_log: "enable"
+ web_filter_command_block_log: "enable"
+ web_filter_cookie_log: "enable"
+ web_filter_cookie_removal_log: "enable"
+ web_filter_js_log: "enable"
+ web_filter_jscript_log: "enable"
+ web_filter_referer_log: "enable"
+ web_filter_unknown_log: "enable"
+ web_filter_vbs_log: "enable"
+ web_ftgd_err_log: "enable"
+ web_ftgd_quota_usage: "enable"
+ web_invalid_domain_log: "enable"
+ web_url_log: "enable"
wisp: "enable"
- wisp-algorithm: "primary-secondary"
- wisp-servers:
+ wisp_algorithm: "primary-secondary"
+ wisp_servers:
-
name: "default_name_83 (source web-proxy.wisp.name)"
- youtube-channel-filter:
+ youtube_channel_filter:
-
- channel-id: "<your_own_value>"
+ channel_id: "<your_own_value>"
comment: "Comment."
id: "87"
- youtube-channel-status: "disable"
+ youtube_channel_status: "disable"
'''
RETURN = '''
@@ -679,7 +777,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -719,14 +817,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -734,85 +834,103 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_profile_data(json):
- option_list = ['comment', 'extended-log', 'ftgd-wf',
- 'https-replacemsg', 'inspection-mode', 'log-all-url',
+ option_list = ['comment', 'extended_log', 'ftgd_wf',
+ 'https_replacemsg', 'inspection_mode', 'log_all_url',
'name', 'options', 'override',
- 'ovrd-perm', 'post-action', 'replacemsg-group',
- 'web', 'web-content-log', 'web-extended-all-action-log',
- 'web-filter-activex-log', 'web-filter-applet-log', 'web-filter-command-block-log',
- 'web-filter-cookie-log', 'web-filter-cookie-removal-log', 'web-filter-js-log',
- 'web-filter-jscript-log', 'web-filter-referer-log', 'web-filter-unknown-log',
- 'web-filter-vbs-log', 'web-ftgd-err-log', 'web-ftgd-quota-usage',
- 'web-invalid-domain-log', 'web-url-log', 'wisp',
- 'wisp-algorithm', 'wisp-servers', 'youtube-channel-filter',
- 'youtube-channel-status']
+ 'ovrd_perm', 'post_action', 'replacemsg_group',
+ 'web', 'web_content_log', 'web_extended_all_action_log',
+ 'web_filter_activex_log', 'web_filter_applet_log', 'web_filter_command_block_log',
+ 'web_filter_cookie_log', 'web_filter_cookie_removal_log', 'web_filter_js_log',
+ 'web_filter_jscript_log', 'web_filter_referer_log', 'web_filter_unknown_log',
+ 'web_filter_vbs_log', 'web_ftgd_err_log', 'web_ftgd_quota_usage',
+ 'web_invalid_domain_log', 'web_url_log', 'wisp',
+ 'wisp_algorithm', 'wisp_servers', 'youtube_channel_filter',
+ 'youtube_channel_status']
dictionary = {}
for attribute in option_list:
- if attribute in json:
+ if attribute in json and json[attribute] is not None:
dictionary[attribute] = json[attribute]
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_profile(data, fos):
vdom = data['vdom']
+ state = data['state']
webfilter_profile_data = data['webfilter_profile']
- filtered_data = filter_webfilter_profile_data(webfilter_profile_data)
- if webfilter_profile_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_webfilter_profile_data(webfilter_profile_data))
+
+ if state == "present":
return fos.set('webfilter',
'profile',
data=filtered_data,
vdom=vdom)
- elif webfilter_profile_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('webfilter',
'profile',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_profile']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_profile']:
+ resp = webfilter_profile(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"webfilter_profile": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"comment": {"required": False, "type": "str"},
- "extended-log": {"required": False, "type": "str",
+ "extended_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ftgd-wf": {"required": False, "type": "dict",
+ "ftgd_wf": {"required": False, "type": "dict",
"options": {
- "exempt-quota": {"required": False, "type": "str"},
+ "exempt_quota": {"required": False, "type": "str"},
"filters": {"required": False, "type": "list",
"options": {
"action": {"required": False, "type": "str",
"choices": ["block", "authenticate", "monitor",
"warning"]},
- "auth-usr-grp": {"required": False, "type": "str",
+ "auth_usr_grp": {"required": False, "type": "str",
"options": {
"name": {"required": True, "type": "str"}
}},
@@ -820,14 +938,14 @@ def main():
"id": {"required": True, "type": "int"},
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-replacemsg": {"required": False, "type": "str"},
- "warn-duration": {"required": False, "type": "str"},
- "warning-duration-type": {"required": False, "type": "str",
+ "override_replacemsg": {"required": False, "type": "str"},
+ "warn_duration": {"required": False, "type": "str"},
+ "warning_duration_type": {"required": False, "type": "str",
"choices": ["session", "timeout"]},
- "warning-prompt": {"required": False, "type": "str",
+ "warning_prompt": {"required": False, "type": "str",
"choices": ["per-domain", "per-category"]}
}},
- "max-quota-timeout": {"required": False, "type": "int"},
+ "max_quota_timeout": {"required": False, "type": "int"},
"options": {"required": False, "type": "str",
"choices": ["error-allow", "rate-server-ip", "connect-request-bypass",
"ftgd-disable"]},
@@ -837,7 +955,7 @@ def main():
"category": {"required": False, "type": "str"},
"duration": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"},
- "override-replacemsg": {"required": False, "type": "str"},
+ "override_replacemsg": {"required": False, "type": "str"},
"type": {"required": False, "type": "str",
"choices": ["time", "traffic"]},
"unit": {"required": False, "type": "str",
@@ -845,20 +963,20 @@ def main():
"GB"]},
"value": {"required": False, "type": "int"}
}},
- "rate-crl-urls": {"required": False, "type": "str",
+ "rate_crl_urls": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
- "rate-css-urls": {"required": False, "type": "str",
+ "rate_css_urls": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
- "rate-image-urls": {"required": False, "type": "str",
+ "rate_image_urls": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
- "rate-javascript-urls": {"required": False, "type": "str",
+ "rate_javascript_urls": {"required": False, "type": "str",
"choices": ["disable", "enable"]}
}},
- "https-replacemsg": {"required": False, "type": "str",
+ "https_replacemsg": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "inspection-mode": {"required": False, "type": "str",
+ "inspection_mode": {"required": False, "type": "str",
"choices": ["proxy", "flow-based"]},
- "log-all-url": {"required": False, "type": "str",
+ "log_all_url": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"name": {"required": True, "type": "str"},
"options": {"required": False, "type": "str",
@@ -868,15 +986,15 @@ def main():
"wf-referer", "wf-cookie", "per-user-bwl"]},
"override": {"required": False, "type": "dict",
"options": {
- "ovrd-cookie": {"required": False, "type": "str",
+ "ovrd_cookie": {"required": False, "type": "str",
"choices": ["allow", "deny"]},
- "ovrd-dur": {"required": False, "type": "str"},
- "ovrd-dur-mode": {"required": False, "type": "str",
+ "ovrd_dur": {"required": False, "type": "str"},
+ "ovrd_dur_mode": {"required": False, "type": "str",
"choices": ["constant", "ask"]},
- "ovrd-scope": {"required": False, "type": "str",
+ "ovrd_scope": {"required": False, "type": "str",
"choices": ["user", "user-group", "ip",
"browser", "ask"]},
- "ovrd-user-group": {"required": False, "type": "str",
+ "ovrd_user_group": {"required": False, "type": "str",
"options": {
"name": {"required": True, "type": "str"}
}},
@@ -884,7 +1002,7 @@ def main():
"options": {
"name": {"required": True, "type": "str"}
}},
- "profile-attribute": {"required": False, "type": "str",
+ "profile_attribute": {"required": False, "type": "str",
"choices": ["User-Name", "NAS-IP-Address", "Framed-IP-Address",
"Framed-IP-Netmask", "Filter-Id", "Login-IP-Host",
"Reply-Message", "Callback-Number", "Callback-Id",
@@ -893,84 +1011,84 @@ def main():
"Proxy-State", "Login-LAT-Service", "Login-LAT-Node",
"Login-LAT-Group", "Framed-AppleTalk-Zone", "Acct-Session-Id",
"Acct-Multi-Session-Id"]},
- "profile-type": {"required": False, "type": "str",
+ "profile_type": {"required": False, "type": "str",
"choices": ["list", "radius"]}
}},
- "ovrd-perm": {"required": False, "type": "str",
+ "ovrd_perm": {"required": False, "type": "str",
"choices": ["bannedword-override", "urlfilter-override", "fortiguard-wf-override",
"contenttype-check-override"]},
- "post-action": {"required": False, "type": "str",
+ "post_action": {"required": False, "type": "str",
"choices": ["normal", "block"]},
- "replacemsg-group": {"required": False, "type": "str"},
+ "replacemsg_group": {"required": False, "type": "str"},
"web": {"required": False, "type": "dict",
"options": {
"blacklist": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "bword-table": {"required": False, "type": "int"},
- "bword-threshold": {"required": False, "type": "int"},
- "content-header-list": {"required": False, "type": "int"},
- "keyword-match": {"required": False, "type": "str",
+ "bword_table": {"required": False, "type": "int"},
+ "bword_threshold": {"required": False, "type": "int"},
+ "content_header_list": {"required": False, "type": "int"},
+ "keyword_match": {"required": False, "type": "str",
"options": {
"pattern": {"required": True, "type": "str"}
}},
- "log-search": {"required": False, "type": "str",
+ "log_search": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "safe-search": {"required": False, "type": "str",
+ "safe_search": {"required": False, "type": "str",
"choices": ["url", "header"]},
- "urlfilter-table": {"required": False, "type": "int"},
+ "urlfilter_table": {"required": False, "type": "int"},
"whitelist": {"required": False, "type": "str",
"choices": ["exempt-av", "exempt-webcontent", "exempt-activex-java-cookie",
"exempt-dlp", "exempt-rangeblock", "extended-log-others"]},
- "youtube-restrict": {"required": False, "type": "str",
+ "youtube_restrict": {"required": False, "type": "str",
"choices": ["none", "strict", "moderate"]}
}},
- "web-content-log": {"required": False, "type": "str",
+ "web_content_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-extended-all-action-log": {"required": False, "type": "str",
+ "web_extended_all_action_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-activex-log": {"required": False, "type": "str",
+ "web_filter_activex_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-applet-log": {"required": False, "type": "str",
+ "web_filter_applet_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-command-block-log": {"required": False, "type": "str",
+ "web_filter_command_block_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-cookie-log": {"required": False, "type": "str",
+ "web_filter_cookie_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-cookie-removal-log": {"required": False, "type": "str",
+ "web_filter_cookie_removal_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-js-log": {"required": False, "type": "str",
+ "web_filter_js_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-jscript-log": {"required": False, "type": "str",
+ "web_filter_jscript_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-referer-log": {"required": False, "type": "str",
+ "web_filter_referer_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-unknown-log": {"required": False, "type": "str",
+ "web_filter_unknown_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-filter-vbs-log": {"required": False, "type": "str",
+ "web_filter_vbs_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-ftgd-err-log": {"required": False, "type": "str",
+ "web_ftgd_err_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-ftgd-quota-usage": {"required": False, "type": "str",
+ "web_ftgd_quota_usage": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-invalid-domain-log": {"required": False, "type": "str",
+ "web_invalid_domain_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "web-url-log": {"required": False, "type": "str",
+ "web_url_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"wisp": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "wisp-algorithm": {"required": False, "type": "str",
+ "wisp_algorithm": {"required": False, "type": "str",
"choices": ["primary-secondary", "round-robin", "auto-learning"]},
- "wisp-servers": {"required": False, "type": "list",
+ "wisp_servers": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "youtube-channel-filter": {"required": False, "type": "list",
+ "youtube_channel_filter": {"required": False, "type": "list",
"options": {
- "channel-id": {"required": False, "type": "str"},
+ "channel_id": {"required": False, "type": "str"},
"comment": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"}
}},
- "youtube-channel-status": {"required": False, "type": "str",
+ "youtube_channel_status": {"required": False, "type": "str",
"choices": ["disable", "blacklist", "whitelist"]}
}
@@ -979,15 +1097,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py b/lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py
index ca0b680b55..0af1b01422 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -27,12 +24,12 @@ ANSIBLE_METADATA = {'status': ['preview'],
DOCUMENTATION = '''
---
module: fortios_webfilter_search_engine
-short_description: Configure web filter search engines.
+short_description: Configure web filter search engines in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and search_engine category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and search_engine category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,69 +41,89 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
webfilter_search_engine:
description:
- Configure web filter search engines.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
charset:
description:
- Search engine charset.
+ type: str
choices:
- utf-8
- gb2312
hostname:
description:
- Hostname (regular expression).
+ type: str
name:
description:
- Search engine name.
required: true
+ type: str
query:
description:
- Code used to prefix a query (must end with an equals character).
+ type: str
safesearch:
description:
- Safe search method. You can disable safe search, add the safe search string to URLs, or insert a safe search header.
+ type: str
choices:
- disable
- url
- header
- safesearch-str:
+ safesearch_str:
description:
- Safe search parameter used in the URL.
+ type: str
url:
description:
- URL (regular expression).
+ type: str
'''
EXAMPLES = '''
@@ -116,22 +133,24 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure web filter search engines.
fortios_webfilter_search_engine:
- host: "{{ host }}"
+ host: "{{ host }}"
username: "{{ username }}"
password: "{{ password }}"
- vdom: "{{ vdom }}"
+ vdom: "{{ vdom }}"
+ https: "False"
+ state: "present"
webfilter_search_engine:
- state: "present"
charset: "utf-8"
hostname: "myhostname"
name: "default_name_5"
query: "<your_own_value>"
safesearch: "disable"
- safesearch-str: "<your_own_value>"
- url: "http://myurl.com"
+ safesearch_str: "<your_own_value>"
+ url: "myurl.com"
'''
RETURN = '''
@@ -154,7 +173,7 @@ mkey:
description: Master key (id) used in the last call to FortiGate
returned: success
type: str
- sample: "key1"
+ sample: "id"
name:
description: Name of the table used to fulfill the request
returned: always
@@ -194,14 +213,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -209,65 +230,82 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_search_engine_data(json):
option_list = ['charset', 'hostname', 'name',
- 'query', 'safesearch', 'safesearch-str',
+ 'query', 'safesearch', 'safesearch_str',
'url']
dictionary = {}
for attribute in option_list:
- if attribute in json:
+ if attribute in json and json[attribute] is not None:
dictionary[attribute] = json[attribute]
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_search_engine(data, fos):
vdom = data['vdom']
+ state = data['state']
webfilter_search_engine_data = data['webfilter_search_engine']
- filtered_data = filter_webfilter_search_engine_data(
- webfilter_search_engine_data)
- if webfilter_search_engine_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_webfilter_search_engine_data(webfilter_search_engine_data))
+
+ if state == "present":
return fos.set('webfilter',
'search-engine',
data=filtered_data,
vdom=vdom)
- elif webfilter_search_engine_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('webfilter',
'search-engine',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_search_engine']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_search_engine']:
+ resp = webfilter_search_engine(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"webfilter_search_engine": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"charset": {"required": False, "type": "str",
"choices": ["utf-8", "gb2312"]},
"hostname": {"required": False, "type": "str"},
@@ -275,7 +313,7 @@ def main():
"query": {"required": False, "type": "str"},
"safesearch": {"required": False, "type": "str",
"choices": ["disable", "url", "header"]},
- "safesearch-str": {"required": False, "type": "str"},
+ "safesearch_str": {"required": False, "type": "str"},
"url": {"required": False, "type": "str"}
}
@@ -284,15 +322,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py b/lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py
index 63d10a0c19..9f4c59a9ec 100644
--- a/lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py
+++ b/lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py
@@ -1,6 +1,6 @@
#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
-# Copyright 2018 Fortinet, Inc.
+# Copyright 2019 Fortinet, Inc.
#
# This program is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -14,9 +14,6 @@ from __future__ import (absolute_import, division, print_function)
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see <https://www.gnu.org/licenses/>.
-#
-# the lib use python logging can get it if the following is set in your
-# Ansible config.
__metaclass__ = type
@@ -29,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_webfilter_urlfilter
short_description: Configure URL filter lists in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by
- allowing the user to configure webfilter feature and urlfilter category.
- Examples includes all options and need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
+ user to set and modify webfilter feature and urlfilter category.
+ Examples include all parameters and values need to be adjusted to datasources before usage.
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -44,58 +41,75 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
- default: false
+ default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
webfilter_urlfilter:
description:
- Configure URL filter lists.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
comment:
description:
- Optional comments.
+ type: str
entries:
description:
- URL filter entries.
+ type: list
suboptions:
action:
description:
- Action to take for URL filter matches.
+ type: str
choices:
- exempt
- block
- allow
- monitor
- dns-address-family:
+ dns_address_family:
description:
- Resolve IPv4 address, IPv6 address, or both from DNS server.
+ type: str
choices:
- ipv4
- ipv6
@@ -103,6 +117,7 @@ options:
exempt:
description:
- If action is set to exempt, select the security profile operations that exempt URLs skip. Separate multiple options with a space.
+ type: str
choices:
- av
- web-content
@@ -116,18 +131,22 @@ options:
description:
- Id.
required: true
- referrer-host:
+ type: int
+ referrer_host:
description:
- Referrer host name.
+ type: str
status:
description:
- Enable/disable this URL filter.
+ type: str
choices:
- enable
- disable
type:
description:
- Filter type (simple, regex, or wildcard).
+ type: str
choices:
- simple
- regex
@@ -135,25 +154,31 @@ options:
url:
description:
- URL to be filtered.
- web-proxy-profile:
+ type: str
+ web_proxy_profile:
description:
- Web proxy profile. Source web-proxy.profile.name.
+ type: str
id:
description:
- ID.
required: true
- ip-addr-block:
+ type: int
+ ip_addr_block:
description:
- Enable/disable blocking URLs when the hostname appears as an IP address.
+ type: str
choices:
- enable
- disable
name:
description:
- Name of URL filter list.
- one-arm-ips-urlfilter:
+ type: str
+ one_arm_ips_urlfilter:
description:
- Enable/disable DNS resolver for one-arm IPS URL filter operation.
+ type: str
choices:
- enable
- disable
@@ -166,6 +191,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure URL filter lists.
fortios_webfilter_urlfilter:
@@ -173,24 +199,25 @@ EXAMPLES = '''
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
+ https: "False"
+ state: "present"
webfilter_urlfilter:
- state: "present"
comment: "Optional comments."
entries:
-
action: "exempt"
- dns-address-family: "ipv4"
+ dns_address_family: "ipv4"
exempt: "av"
id: "8"
- referrer-host: "myhostname"
+ referrer_host: "myhostname"
status: "enable"
type: "simple"
url: "myurl.com"
- web-proxy-profile: "<your_own_value> (source web-proxy.profile.name)"
+ web_proxy_profile: "<your_own_value> (source web-proxy.profile.name)"
id: "14"
- ip-addr-block: "enable"
+ ip_addr_block: "enable"
name: "default_name_16"
- one-arm-ips-urlfilter: "enable"
+ one_arm_ips_urlfilter: "enable"
'''
RETURN = '''
@@ -253,14 +280,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
-
-fos = None
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
-def login(data):
+def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -268,12 +297,12 @@ def login(data):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_webfilter_urlfilter_data(json):
option_list = ['comment', 'entries', 'id',
- 'ip-addr-block', 'name', 'one-arm-ips-urlfilter']
+ 'ip_addr_block', 'name', 'one_arm_ips_urlfilter']
dictionary = {}
for attribute in option_list:
@@ -283,74 +312,92 @@ def filter_webfilter_urlfilter_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def webfilter_urlfilter(data, fos):
vdom = data['vdom']
+ state = data['state']
webfilter_urlfilter_data = data['webfilter_urlfilter']
- filtered_data = filter_webfilter_urlfilter_data(webfilter_urlfilter_data)
- if webfilter_urlfilter_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_webfilter_urlfilter_data(webfilter_urlfilter_data))
+
+ if state == "present":
return fos.set('webfilter',
'urlfilter',
data=filtered_data,
vdom=vdom)
- elif webfilter_urlfilter_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('webfilter',
'urlfilter',
mkey=filtered_data['id'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_webfilter(data, fos):
- login(data)
- methodlist = ['webfilter_urlfilter']
- for method in methodlist:
- if data[method]:
- resp = eval(method)(data, fos)
- break
+ if data['webfilter_urlfilter']:
+ resp = webfilter_urlfilter(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
- "https": {"required": False, "type": "bool", "default": "False"},
+ "https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"webfilter_urlfilter": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"comment": {"required": False, "type": "str"},
"entries": {"required": False, "type": "list",
"options": {
"action": {"required": False, "type": "str",
"choices": ["exempt", "block", "allow",
"monitor"]},
- "dns-address-family": {"required": False, "type": "str",
+ "dns_address_family": {"required": False, "type": "str",
"choices": ["ipv4", "ipv6", "both"]},
"exempt": {"required": False, "type": "str",
"choices": ["av", "web-content", "activex-java-cookie",
"dlp", "fortiguard", "range-block",
"pass", "all"]},
"id": {"required": True, "type": "int"},
- "referrer-host": {"required": False, "type": "str"},
+ "referrer_host": {"required": False, "type": "str"},
"status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"type": {"required": False, "type": "str",
"choices": ["simple", "regex", "wildcard"]},
"url": {"required": False, "type": "str"},
- "web-proxy-profile": {"required": False, "type": "str"}
+ "web_proxy_profile": {"required": False, "type": "str"}
}},
"id": {"required": True, "type": "int"},
- "ip-addr-block": {"required": False, "type": "str",
+ "ip_addr_block": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"name": {"required": False, "type": "str"},
- "one-arm-ips-urlfilter": {"required": False, "type": "str",
+ "one_arm_ips_urlfilter": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@@ -359,15 +406,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- global fos
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_webfilter(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py
index 308b89af4d..ec7d93b774 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_global
short_description: Configure wireless controller global settings in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and global category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,49 +41,63 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
wireless_controller_global:
description:
- Configure wireless controller global settings.
default: null
+ type: dict
suboptions:
- ap-log-server:
+ ap_log_server:
description:
- - Enable/disable configuring APs or FortiAPs to send log messages to a syslog server (default = disable).
+ - Enable/disable configuring APs or FortiAPs to send log messages to a syslog server .
+ type: str
choices:
- enable
- disable
- ap-log-server-ip:
+ ap_log_server_ip:
description:
- IP address that APs or FortiAPs send log messages to.
- ap-log-server-port:
+ type: str
+ ap_log_server_port:
description:
- Port that APs or FortiAPs send log messages to.
- control-message-offload:
+ type: int
+ control_message_offload:
description:
- Configure CAPWAP control message data channel offload.
+ type: str
choices:
- ebp-frame
- aeroscout-tag
@@ -92,54 +106,67 @@ options:
- sta-cap-list
- stats
- aeroscout-mu
- data-ethernet-II:
+ data_ethernet_II:
description:
- - Configure the wireless controller to use Ethernet II or 802.3 frames with 802.3 data tunnel mode (default = disable).
+ - Configure the wireless controller to use Ethernet II or 802.3 frames with 802.3 data tunnel mode .
+ type: str
choices:
- enable
- disable
- discovery-mc-addr:
+ discovery_mc_addr:
description:
- - Multicast IP address for AP discovery (default = 244.0.1.140).
- fiapp-eth-type:
+ - Multicast IP address for AP discovery .
+ type: str
+ fiapp_eth_type:
description:
- - Ethernet type for Fortinet Inter-Access Point Protocol (IAPP), or IEEE 802.11f, packets (0 - 65535, default = 5252).
- image-download:
+ - Ethernet type for Fortinet Inter-Access Point Protocol (IAPP), or IEEE 802.11f, packets (0 - 65535).
+ type: int
+ image_download:
description:
- Enable/disable WTP image download at join time.
+ type: str
choices:
- enable
- disable
- ipsec-base-ip:
+ ipsec_base_ip:
description:
- - Base IP address for IPsec VPN tunnels between the access points and the wireless controller (default = 169.254.0.1).
- link-aggregation:
+ - Base IP address for IPsec VPN tunnels between the access points and the wireless controller .
+ type: str
+ link_aggregation:
description:
- - Enable/disable calculating the CAPWAP transmit hash to load balance sessions to link aggregation nodes (default = disable).
+ - Enable/disable calculating the CAPWAP transmit hash to load balance sessions to link aggregation nodes .
+ type: str
choices:
- enable
- disable
location:
description:
- Description of the location of the wireless controller.
- max-clients:
+ type: str
+ max_clients:
description:
- - Maximum number of clients that can connect simultaneously (default = 0, meaning no limitation).
- max-retransmit:
+ - Maximum number of clients that can connect simultaneously .
+ type: int
+ max_retransmit:
description:
- - Maximum number of tunnel packet retransmissions (0 - 64, default = 3).
- mesh-eth-type:
+ - Maximum number of tunnel packet retransmissions (0 - 64).
+ type: int
+ mesh_eth_type:
description:
- - Mesh Ethernet identifier included in backhaul packets (0 - 65535, default = 8755).
+ - Mesh Ethernet identifier included in backhaul packets (0 - 65535).
+ type: int
name:
description:
- Name of the wireless controller.
- rogue-scan-mac-adjacency:
+ type: str
+ rogue_scan_mac_adjacency:
description:
- - Maximum numerical difference between an AP's Ethernet and wireless MAC values to match for rogue detection (0 - 31, default = 7).
- wtp-share:
+ - Maximum numerical difference between an AP's Ethernet and wireless MAC values to match for rogue detection (0 - 31).
+ type: int
+ wtp_share:
description:
- Enable/disable sharing of WTPs between VDOMs.
+ type: str
choices:
- enable
- disable
@@ -152,6 +179,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure wireless controller global settings.
fortios_wireless_controller_global:
@@ -161,23 +189,23 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
wireless_controller_global:
- ap-log-server: "enable"
- ap-log-server-ip: "<your_own_value>"
- ap-log-server-port: "5"
- control-message-offload: "ebp-frame"
- data-ethernet-II: "enable"
- discovery-mc-addr: "<your_own_value>"
- fiapp-eth-type: "9"
- image-download: "enable"
- ipsec-base-ip: "<your_own_value>"
- link-aggregation: "enable"
+ ap_log_server: "enable"
+ ap_log_server_ip: "<your_own_value>"
+ ap_log_server_port: "5"
+ control_message_offload: "ebp-frame"
+ data_ethernet_II: "enable"
+ discovery_mc_addr: "<your_own_value>"
+ fiapp_eth_type: "9"
+ image_download: "enable"
+ ipsec_base_ip: "<your_own_value>"
+ link_aggregation: "enable"
location: "<your_own_value>"
- max-clients: "14"
- max-retransmit: "15"
- mesh-eth-type: "16"
+ max_clients: "14"
+ max_retransmit: "15"
+ mesh_eth_type: "16"
name: "default_name_17"
- rogue-scan-mac-adjacency: "18"
- wtp-share: "enable"
+ rogue_scan_mac_adjacency: "18"
+ wtp_share: "enable"
'''
RETURN = '''
@@ -240,12 +268,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -253,16 +285,16 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_global_data(json):
- option_list = ['ap-log-server', 'ap-log-server-ip', 'ap-log-server-port',
- 'control-message-offload', 'data-ethernet-II', 'discovery-mc-addr',
- 'fiapp-eth-type', 'image-download', 'ipsec-base-ip',
- 'link-aggregation', 'location', 'max-clients',
- 'max-retransmit', 'mesh-eth-type', 'name',
- 'rogue-scan-mac-adjacency', 'wtp-share']
+ option_list = ['ap_log_server', 'ap_log_server_ip', 'ap_log_server_port',
+ 'control_message_offload', 'data_ethernet_II', 'discovery_mc_addr',
+ 'fiapp_eth_type', 'image_download', 'ipsec_base_ip',
+ 'link_aggregation', 'location', 'max_clients',
+ 'max_retransmit', 'mesh_eth_type', 'name',
+ 'rogue_scan_mac_adjacency', 'wtp_share']
dictionary = {}
for attribute in option_list:
@@ -272,10 +304,23 @@ def filter_wireless_controller_global_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def wireless_controller_global(data, fos):
vdom = data['vdom']
wireless_controller_global_data = data['wireless_controller_global']
- filtered_data = filter_wireless_controller_global_data(wireless_controller_global_data)
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_global_data(wireless_controller_global_data))
return fos.set('wireless-controller',
'global',
@@ -283,50 +328,56 @@ def wireless_controller_global(data, fos):
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_global']:
resp = wireless_controller_global(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"wireless_controller_global": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "ap-log-server": {"required": False, "type": "str",
+ "ap_log_server": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-log-server-ip": {"required": False, "type": "str"},
- "ap-log-server-port": {"required": False, "type": "int"},
- "control-message-offload": {"required": False, "type": "str",
+ "ap_log_server_ip": {"required": False, "type": "str"},
+ "ap_log_server_port": {"required": False, "type": "int"},
+ "control_message_offload": {"required": False, "type": "str",
"choices": ["ebp-frame", "aeroscout-tag", "ap-list",
"sta-list", "sta-cap-list", "stats",
"aeroscout-mu"]},
- "data-ethernet-II": {"required": False, "type": "str",
+ "data_ethernet_II": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "discovery-mc-addr": {"required": False, "type": "ipv4-address-multicast"},
- "fiapp-eth-type": {"required": False, "type": "int"},
- "image-download": {"required": False, "type": "str",
+ "discovery_mc_addr": {"required": False, "type": "str"},
+ "fiapp_eth_type": {"required": False, "type": "int"},
+ "image_download": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ipsec-base-ip": {"required": False, "type": "str"},
- "link-aggregation": {"required": False, "type": "str",
+ "ipsec_base_ip": {"required": False, "type": "str"},
+ "link_aggregation": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"location": {"required": False, "type": "str"},
- "max-clients": {"required": False, "type": "int"},
- "max-retransmit": {"required": False, "type": "int"},
- "mesh-eth-type": {"required": False, "type": "int"},
+ "max_clients": {"required": False, "type": "int"},
+ "max_retransmit": {"required": False, "type": "int"},
+ "mesh_eth_type": {"required": False, "type": "int"},
"name": {"required": False, "type": "str"},
- "rogue-scan-mac-adjacency": {"required": False, "type": "int"},
- "wtp-share": {"required": False, "type": "str",
+ "rogue_scan_mac_adjacency": {"required": False, "type": "int"},
+ "wtp_share": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@@ -335,14 +386,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py
index 6daa745f3c..038746265c 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_setting
short_description: VDOM wireless controller configuration in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and setting category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,40 +41,52 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
wireless_controller_setting:
description:
- VDOM wireless controller configuration.
default: null
+ type: dict
suboptions:
- account-id:
+ account_id:
description:
- FortiCloud customer account ID.
+ type: str
country:
description:
- Country or region in which the FortiGate is located. The country determines the 802.11 bands and channels that are available.
+ type: str
choices:
- NA
- AL
@@ -204,15 +216,17 @@ options:
- ZW
- JP
- CA
- duplicate-ssid:
+ duplicate_ssid:
description:
- Enable/disable allowing Virtual Access Points (VAPs) to use the same SSID name in the same VDOM.
+ type: str
choices:
- enable
- disable
- fapc-compatibility:
+ fapc_compatibility:
description:
- Enable/disable FAP-C series compatibility.
+ type: str
choices:
- enable
- disable
@@ -225,6 +239,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: VDOM wireless controller configuration.
fortios_wireless_controller_setting:
@@ -234,10 +249,10 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
wireless_controller_setting:
- account-id: "<your_own_value>"
+ account_id: "<your_own_value>"
country: "NA"
- duplicate-ssid: "enable"
- fapc-compatibility: "enable"
+ duplicate_ssid: "enable"
+ fapc_compatibility: "enable"
'''
RETURN = '''
@@ -300,12 +315,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -313,12 +332,12 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_setting_data(json):
- option_list = ['account-id', 'country', 'duplicate-ssid',
- 'fapc-compatibility']
+ option_list = ['account_id', 'country', 'duplicate_ssid',
+ 'fapc_compatibility']
dictionary = {}
for attribute in option_list:
@@ -328,17 +347,15 @@ def filter_wireless_controller_setting_data(json):
return dictionary
-def flatten_multilists_attributes(data):
- multilist_attrs = []
-
- for attr in multilist_attrs:
- try:
- path = "data['" + "']['".join(elem for elem in attr) + "']"
- current_val = eval(path)
- flattened_val = ' '.join(elem for elem in current_val)
- exec(path + '= flattened_val')
- except BaseException:
- pass
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
return data
@@ -346,35 +363,41 @@ def flatten_multilists_attributes(data):
def wireless_controller_setting(data, fos):
vdom = data['vdom']
wireless_controller_setting_data = data['wireless_controller_setting']
- flattened_data = flatten_multilists_attributes(wireless_controller_setting_data)
- filtered_data = filter_wireless_controller_setting_data(flattened_data)
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_setting_data(wireless_controller_setting_data))
+
return fos.set('wireless-controller',
'setting',
data=filtered_data,
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_setting']:
resp = wireless_controller_setting(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
"wireless_controller_setting": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "account-id": {"required": False, "type": "str"},
+ "account_id": {"required": False, "type": "str"},
"country": {"required": False, "type": "str",
"choices": ["NA", "AL", "DZ",
"AO", "AR", "AM",
@@ -419,9 +442,9 @@ def main():
"UZ", "VE", "VN",
"YE", "ZB", "ZW",
"JP", "CA"]},
- "duplicate-ssid": {"required": False, "type": "str",
+ "duplicate_ssid": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "fapc-compatibility": {"required": False, "type": "str",
+ "fapc_compatibility": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@@ -430,14 +453,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py
index 5298c7f956..aef19b7b8d 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_utm_profile
short_description: Configure UTM (Unified Threat Management) profile in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and utm_profile category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,72 +41,93 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
wireless_controller_utm_profile:
description:
- Configure UTM (Unified Threat Management) profile.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
- antivirus-profile:
+ antivirus_profile:
description:
- AntiVirus profile name. Source antivirus.profile.name.
- application-list:
+ type: str
+ application_list:
description:
- Application control list name. Source application.list.name.
+ type: str
comment:
description:
- Comment.
- ips-sensor:
+ type: str
+ ips_sensor:
description:
- IPS sensor name. Source ips.sensor.name.
+ type: str
name:
description:
- UTM profile name.
required: true
- scan-botnet-connections:
+ type: str
+ scan_botnet_connections:
description:
- Block or monitor connections to Botnet servers or disable Botnet scanning.
+ type: str
choices:
- disable
- - block
- monitor
- utm-log:
+ - block
+ utm_log:
description:
- Enable/disable UTM logging.
+ type: str
choices:
- enable
- disable
- webfilter-profile:
+ webfilter_profile:
description:
- WebFilter profile name. Source webfilter.profile.name.
+ type: str
'''
EXAMPLES = '''
@@ -116,6 +137,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure UTM (Unified Threat Management) profile.
fortios_wireless_controller_utm_profile:
@@ -124,16 +146,16 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
+ state: "present"
wireless_controller_utm_profile:
- state: "present"
- antivirus-profile: "<your_own_value> (source antivirus.profile.name)"
- application-list: "<your_own_value> (source application.list.name)"
+ antivirus_profile: "<your_own_value> (source antivirus.profile.name)"
+ application_list: "<your_own_value> (source application.list.name)"
comment: "Comment."
- ips-sensor: "<your_own_value> (source ips.sensor.name)"
+ ips_sensor: "<your_own_value> (source ips.sensor.name)"
name: "default_name_7"
- scan-botnet-connections: "disable"
- utm-log: "enable"
- webfilter-profile: "<your_own_value> (source webfilter.profile.name)"
+ scan_botnet_connections: "disable"
+ utm_log: "enable"
+ webfilter_profile: "<your_own_value> (source webfilter.profile.name)"
'''
RETURN = '''
@@ -196,12 +218,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -209,13 +235,13 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_utm_profile_data(json):
- option_list = ['antivirus-profile', 'application-list', 'comment',
- 'ips-sensor', 'name', 'scan-botnet-connections',
- 'utm-log', 'webfilter-profile']
+ option_list = ['antivirus_profile', 'application_list', 'comment',
+ 'ips_sensor', 'name', 'scan_botnet_connections',
+ 'utm_log', 'webfilter_profile']
dictionary = {}
for attribute in option_list:
@@ -225,71 +251,76 @@ def filter_wireless_controller_utm_profile_data(json):
return dictionary
-def flatten_multilists_attributes(data):
- multilist_attrs = []
-
- for attr in multilist_attrs:
- try:
- path = "data['" + "']['".join(elem for elem in attr) + "']"
- current_val = eval(path)
- flattened_val = ' '.join(elem for elem in current_val)
- exec(path + '= flattened_val')
- except BaseException:
- pass
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
return data
def wireless_controller_utm_profile(data, fos):
vdom = data['vdom']
+ state = data['state']
wireless_controller_utm_profile_data = data['wireless_controller_utm_profile']
- flattened_data = flatten_multilists_attributes(wireless_controller_utm_profile_data)
- filtered_data = filter_wireless_controller_utm_profile_data(flattened_data)
- if wireless_controller_utm_profile_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_utm_profile_data(wireless_controller_utm_profile_data))
+
+ if state == "present":
return fos.set('wireless-controller',
'utm-profile',
data=filtered_data,
vdom=vdom)
- elif wireless_controller_utm_profile_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('wireless-controller',
'utm-profile',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_utm_profile']:
resp = wireless_controller_utm_profile(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"wireless_controller_utm_profile": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
- "antivirus-profile": {"required": False, "type": "str"},
- "application-list": {"required": False, "type": "str"},
+ "antivirus_profile": {"required": False, "type": "str"},
+ "application_list": {"required": False, "type": "str"},
"comment": {"required": False, "type": "str"},
- "ips-sensor": {"required": False, "type": "str"},
+ "ips_sensor": {"required": False, "type": "str"},
"name": {"required": True, "type": "str"},
- "scan-botnet-connections": {"required": False, "type": "str",
- "choices": ["disable", "block", "monitor"]},
- "utm-log": {"required": False, "type": "str",
+ "scan_botnet_connections": {"required": False, "type": "str",
+ "choices": ["disable", "monitor", "block"]},
+ "utm_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "webfilter-profile": {"required": False, "type": "str"}
+ "webfilter_profile": {"required": False, "type": "str"}
}
}
@@ -297,14 +328,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py
index 3168b7ca30..52a3972e85 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_vap
short_description: Configure Virtual Access Points (VAPs) in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and vap category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,63 +41,81 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
wireless_controller_vap:
description:
- Configure Virtual Access Points (VAPs).
default: null
+ type: dict
suboptions:
- state:
+ acct_interim_interval:
description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
- acct-interim-interval:
- description:
- - WiFi RADIUS accounting interim interval (60 - 86400 sec, default = 0).
+ - WiFi RADIUS accounting interim interval (60 - 86400 sec).
+ type: int
alias:
description:
- Alias.
+ type: str
auth:
description:
- Authentication protocol.
+ type: str
choices:
- psk
- radius
- usergroup
- broadcast-ssid:
+ broadcast_ssid:
description:
- - Enable/disable broadcasting the SSID (default = enable).
+ - Enable/disable broadcasting the SSID .
+ type: str
choices:
- enable
- disable
- broadcast-suppression:
+ broadcast_suppression:
description:
- Optional suppression of broadcast messages. For example, you can keep DHCP messages, ARP broadcasts, and so on off of the wireless
network.
+ type: str
choices:
- dhcp-up
- dhcp-down
@@ -112,261 +130,315 @@ options:
- ipv6
- all-other-mc
- all-other-bc
- captive-portal-ac-name:
+ captive_portal_ac_name:
description:
- Local-bridging captive portal ac-name.
- captive-portal-macauth-radius-secret:
+ type: str
+ captive_portal_macauth_radius_secret:
description:
- Secret key to access the macauth RADIUS server.
- captive-portal-macauth-radius-server:
+ type: str
+ captive_portal_macauth_radius_server:
description:
- Captive portal external RADIUS server domain name or IP address.
- captive-portal-radius-secret:
+ type: str
+ captive_portal_radius_secret:
description:
- Secret key to access the RADIUS server.
- captive-portal-radius-server:
+ type: str
+ captive_portal_radius_server:
description:
- Captive portal RADIUS server domain name or IP address.
- captive-portal-session-timeout-interval:
+ type: str
+ captive_portal_session_timeout_interval:
description:
- - Session timeout interval (0 - 864000 sec, default = 0).
- dhcp-lease-time:
+ - Session timeout interval (0 - 864000 sec).
+ type: int
+ dhcp_lease_time:
description:
- DHCP lease time in seconds for NAT IP address.
- dhcp-option82-circuit-id-insertion:
+ type: int
+ dhcp_option82_circuit_id_insertion:
description:
- - Enable/disable DHCP option 82 circuit-id insert (default = disable).
+ - Enable/disable DHCP option 82 circuit-id insert .
+ type: str
choices:
- style-1
- style-2
- disable
- dhcp-option82-insertion:
+ dhcp_option82_insertion:
description:
- - Enable/disable DHCP option 82 insert (default = disable).
+ - Enable/disable DHCP option 82 insert .
+ type: str
choices:
- enable
- disable
- dhcp-option82-remote-id-insertion:
+ dhcp_option82_remote_id_insertion:
description:
- - Enable/disable DHCP option 82 remote-id insert (default = disable).
+ - Enable/disable DHCP option 82 remote-id insert .
+ type: str
choices:
- style-1
- disable
- dynamic-vlan:
+ dynamic_vlan:
description:
- Enable/disable dynamic VLAN assignment.
+ type: str
choices:
- enable
- disable
- eap-reauth:
+ eap_reauth:
description:
- Enable/disable EAP re-authentication for WPA-Enterprise security.
+ type: str
choices:
- enable
- disable
- eap-reauth-intv:
+ eap_reauth_intv:
description:
- - EAP re-authentication interval (1800 - 864000 sec, default = 86400).
- eapol-key-retries:
+ - EAP re-authentication interval (1800 - 864000 sec).
+ type: int
+ eapol_key_retries:
description:
- - Enable/disable retransmission of EAPOL-Key frames (message 3/4 and group message 1/2) (default = enable).
+ - Enable/disable retransmission of EAPOL-Key frames (message 3/4 and group message 1/2) .
+ type: str
choices:
- disable
- enable
encrypt:
description:
- Encryption protocol to use (only available when security is set to a WPA type).
+ type: str
choices:
- TKIP
- AES
- TKIP-AES
- external-fast-roaming:
+ external_fast_roaming:
description:
- - Enable/disable fast roaming or pre-authentication with external APs not managed by the FortiGate (default = disable).
+ - Enable/disable fast roaming or pre-authentication with external APs not managed by the FortiGate .
+ type: str
choices:
- enable
- disable
- external-logout:
+ external_logout:
description:
- URL of external authentication logout server.
- external-web:
+ type: str
+ external_web:
description:
- URL of external authentication web server.
- fast-bss-transition:
+ type: str
+ fast_bss_transition:
description:
- - Enable/disable 802.11r Fast BSS Transition (FT) (default = disable).
+ - Enable/disable 802.11r Fast BSS Transition (FT) .
+ type: str
choices:
- disable
- enable
- fast-roaming:
+ fast_roaming:
description:
- - Enable/disable fast-roaming, or pre-authentication, where supported by clients (default = disable).
+ - Enable/disable fast-roaming, or pre-authentication, where supported by clients .
+ type: str
choices:
- enable
- disable
- ft-mobility-domain:
+ ft_mobility_domain:
description:
- - Mobility domain identifier in FT (1 - 65535, default = 1000).
- ft-over-ds:
+ - Mobility domain identifier in FT (1 - 65535).
+ type: int
+ ft_over_ds:
description:
- Enable/disable FT over the Distribution System (DS).
+ type: str
choices:
- disable
- enable
- ft-r0-key-lifetime:
+ ft_r0_key_lifetime:
description:
- Lifetime of the PMK-R0 key in FT, 1-65535 minutes.
- gtk-rekey:
+ type: int
+ gtk_rekey:
description:
- Enable/disable GTK rekey for WPA security.
+ type: str
choices:
- enable
- disable
- gtk-rekey-intv:
+ gtk_rekey_intv:
description:
- - GTK rekey interval (1800 - 864000 sec, default = 86400).
- hotspot20-profile:
+ - GTK rekey interval (1800 - 864000 sec).
+ type: int
+ hotspot20_profile:
description:
- Hotspot 2.0 profile name.
- intra-vap-privacy:
+ type: str
+ intra_vap_privacy:
description:
- - Enable/disable blocking communication between clients on the same SSID (called intra-SSID privacy) (default = disable).
+ - Enable/disable blocking communication between clients on the same SSID (called intra-SSID privacy) .
+ type: str
choices:
- enable
- disable
ip:
description:
- IP address and subnet mask for the local standalone NAT subnet.
+ type: str
key:
description:
- WEP Key.
+ type: str
keyindex:
description:
- WEP key index (1 - 4).
+ type: int
ldpc:
description:
- VAP low-density parity-check (LDPC) coding configuration.
+ type: str
choices:
- disable
- rx
- tx
- rxtx
- local-authentication:
+ local_authentication:
description:
- Enable/disable AP local authentication.
+ type: str
choices:
- enable
- disable
- local-bridging:
+ local_bridging:
description:
- - Enable/disable bridging of wireless and Ethernet interfaces on the FortiAP (default = disable).
+ - Enable/disable bridging of wireless and Ethernet interfaces on the FortiAP .
+ type: str
choices:
- enable
- disable
- local-lan:
+ local_lan:
description:
- - Allow/deny traffic destined for a Class A, B, or C private IP address (default = allow).
+ - Allow/deny traffic destined for a Class A, B, or C private IP address .
+ type: str
choices:
- allow
- deny
- local-standalone:
+ local_standalone:
description:
- - Enable/disable AP local standalone (default = disable).
+ - Enable/disable AP local standalone .
+ type: str
choices:
- enable
- disable
- local-standalone-nat:
+ local_standalone_nat:
description:
- Enable/disable AP local standalone NAT mode.
+ type: str
choices:
- enable
- disable
- mac-auth-bypass:
+ mac_auth_bypass:
description:
- Enable/disable MAC authentication bypass.
+ type: str
choices:
- enable
- disable
- mac-filter:
+ mac_filter:
description:
- Enable/disable MAC filtering to block wireless clients by mac address.
+ type: str
choices:
- enable
- disable
- mac-filter-list:
+ mac_filter_list:
description:
- Create a list of MAC addresses for MAC address filtering.
+ type: list
suboptions:
id:
description:
- ID.
required: true
+ type: int
mac:
description:
- MAC address.
- mac-filter-policy:
+ type: str
+ mac_filter_policy:
description:
- Deny or allow the client with this MAC address.
+ type: str
choices:
- allow
- deny
- mac-filter-policy-other:
+ mac_filter_policy_other:
description:
- Allow or block clients with MAC addresses that are not in the filter list.
+ type: str
choices:
- allow
- deny
- max-clients:
+ max_clients:
description:
- - Maximum number of clients that can connect simultaneously to the VAP (default = 0, meaning no limitation).
- max-clients-ap:
+ - Maximum number of clients that can connect simultaneously to the VAP .
+ type: int
+ max_clients_ap:
description:
- - Maximum number of clients that can connect simultaneously to each radio (default = 0, meaning no limitation).
- me-disable-thresh:
+ - Maximum number of clients that can connect simultaneously to each radio .
+ type: int
+ me_disable_thresh:
description:
- Disable multicast enhancement when this many clients are receiving multicast traffic.
- mesh-backhaul:
+ type: int
+ mesh_backhaul:
description:
- - Enable/disable using this VAP as a WiFi mesh backhaul (default = disable). This entry is only available when security is set to a WPA
- type or open.
+ - Enable/disable using this VAP as a WiFi mesh backhaul . This entry is only available when security is set to a WPA type or open.
+ type: str
choices:
- enable
- disable
mpsk:
description:
- Enable/disable multiple pre-shared keys (PSKs.)
+ type: str
choices:
- enable
- disable
- mpsk-concurrent-clients:
+ mpsk_concurrent_clients:
description:
- Number of pre-shared keys (PSKs) to allow if multiple pre-shared keys are enabled.
- mpsk-key:
+ type: int
+ mpsk_key:
description:
- Pre-shared keys that can be used to connect to this virtual access point.
+ type: list
suboptions:
comment:
description:
- Comment.
- concurrent-clients:
+ type: str
+ concurrent_clients:
description:
- Number of clients that can connect using this pre-shared key.
- key-name:
+ type: str
+ key_name:
description:
- Pre-shared key name.
- required: true
+ type: str
passphrase:
description:
- WPA Pre-shared key.
- multicast-enhance:
+ type: str
+ multicast_enhance:
description:
- - Enable/disable converting multicast to unicast to improve performance (default = disable).
+ - Enable/disable converting multicast to unicast to improve performance .
+ type: str
choices:
- enable
- disable
- multicast-rate:
+ multicast_rate:
description:
- - Multicast rate (0, 6000, 12000, or 24000 kbps, default = 0).
+ - Multicast rate (0, 6000, 12000, or 24000 kbps).
+ type: str
choices:
- 0
- 6000
@@ -376,50 +448,63 @@ options:
description:
- Virtual AP name.
required: true
+ type: str
okc:
description:
- - Enable/disable Opportunistic Key Caching (OKC) (default = enable).
+ - Enable/disable Opportunistic Key Caching (OKC) .
+ type: str
choices:
- disable
- enable
passphrase:
description:
- WPA pre-shard key (PSK) to be used to authenticate WiFi users.
+ type: str
pmf:
description:
- - Protected Management Frames (PMF) support (default = disable).
+ - Protected Management Frames (PMF) support .
+ type: str
choices:
- disable
- enable
- optional
- pmf-assoc-comeback-timeout:
+ pmf_assoc_comeback_timeout:
description:
- Protected Management Frames (PMF) comeback maximum timeout (1-20 sec).
- pmf-sa-query-retry-timeout:
+ type: int
+ pmf_sa_query_retry_timeout:
description:
- Protected Management Frames (PMF) SA query retry timeout interval (1 - 5 100s of msec).
- portal-message-override-group:
+ type: int
+ portal_message_override_group:
description:
- Replacement message group for this VAP (only available when security is set to a captive portal type).
- portal-message-overrides:
+ type: str
+ portal_message_overrides:
description:
- Individual message overrides.
+ type: dict
suboptions:
- auth-disclaimer-page:
+ auth_disclaimer_page:
description:
- Override auth-disclaimer-page message with message from portal-message-overrides group.
- auth-login-failed-page:
+ type: str
+ auth_login_failed_page:
description:
- Override auth-login-failed-page message with message from portal-message-overrides group.
- auth-login-page:
+ type: str
+ auth_login_page:
description:
- Override auth-login-page message with message from portal-message-overrides group.
- auth-reject-page:
+ type: str
+ auth_reject_page:
description:
- Override auth-reject-page message with message from portal-message-overrides group.
- portal-type:
+ type: str
+ portal_type:
description:
- Captive portal functionality. Configure how the captive portal authenticates users and whether it includes a disclaimer.
+ type: str
choices:
- auth
- auth+disclaimer
@@ -428,68 +513,83 @@ options:
- cmcc
- cmcc-macauth
- auth-mac
- probe-resp-suppression:
+ probe_resp_suppression:
description:
- - Enable/disable probe response suppression (to ignore weak signals) (default = disable).
+ - Enable/disable probe response suppression (to ignore weak signals) .
+ type: str
choices:
- enable
- disable
- probe-resp-threshold:
+ probe_resp_threshold:
description:
- - Minimum signal level/threshold in dBm required for the AP response to probe requests (-95 to -20, default = -80).
- ptk-rekey:
+ - Minimum signal level/threshold in dBm required for the AP response to probe requests (-95 to -20).
+ type: str
+ ptk_rekey:
description:
- Enable/disable PTK rekey for WPA-Enterprise security.
+ type: str
choices:
- enable
- disable
- ptk-rekey-intv:
+ ptk_rekey_intv:
description:
- - PTK rekey interval (1800 - 864000 sec, default = 86400).
- qos-profile:
+ - PTK rekey interval (1800 - 864000 sec).
+ type: int
+ qos_profile:
description:
- Quality of service profile name.
+ type: str
quarantine:
description:
- - Enable/disable station quarantine (default = enable).
+ - Enable/disable station quarantine .
+ type: str
choices:
- enable
- disable
- radio-2g-threshold:
+ radio_2g_threshold:
description:
- - Minimum signal level/threshold in dBm required for the AP response to receive a packet in 2.4G band (-95 to -20, default = -79).
- radio-5g-threshold:
+ - Minimum signal level/threshold in dBm required for the AP response to receive a packet in 2.4G band (-95 to -20).
+ type: str
+ radio_5g_threshold:
description:
- - Minimum signal level/threshold in dBm required for the AP response to receive a packet in 5G band(-95 to -20, default = -76).
- radio-sensitivity:
+ - Minimum signal level/threshold in dBm required for the AP response to receive a packet in 5G band(-95 to -20).
+ type: str
+ radio_sensitivity:
description:
- - Enable/disable software radio sensitivity (to ignore weak signals) (default = disable).
+ - Enable/disable software radio sensitivity (to ignore weak signals) .
+ type: str
choices:
- enable
- disable
- radius-mac-auth:
+ radius_mac_auth:
description:
- - Enable/disable RADIUS-based MAC authentication of clients (default = disable).
+ - Enable/disable RADIUS-based MAC authentication of clients .
+ type: str
choices:
- enable
- disable
- radius-mac-auth-server:
+ radius_mac_auth_server:
description:
- RADIUS-based MAC authentication server.
- radius-mac-auth-usergroups:
+ type: str
+ radius_mac_auth_usergroups:
description:
- Selective user groups that are permitted for RADIUS mac authentication.
+ type: list
suboptions:
name:
description:
- User group name.
required: true
- radius-server:
+ type: str
+ radius_server:
description:
- RADIUS server to be used to authenticate WiFi users.
- rates-11a:
+ type: str
+ rates_11a:
description:
- Allowed data rates for 802.11a.
+ type: str
choices:
- 1
- 1-basic
@@ -515,9 +615,10 @@ options:
- 48-basic
- 54
- 54-basic
- rates-11ac-ss12:
+ rates_11ac_ss12:
description:
- Allowed data rates for 802.11ac with 1 or 2 spatial streams.
+ type: str
choices:
- mcs0/1
- mcs1/1
@@ -543,9 +644,10 @@ options:
- mcs9/2
- mcs10/2
- mcs11/2
- rates-11ac-ss34:
+ rates_11ac_ss34:
description:
- Allowed data rates for 802.11ac with 3 or 4 spatial streams.
+ type: str
choices:
- mcs0/3
- mcs1/3
@@ -571,9 +673,10 @@ options:
- mcs9/4
- mcs10/4
- mcs11/4
- rates-11bg:
+ rates_11bg:
description:
- Allowed data rates for 802.11b/g.
+ type: str
choices:
- 1
- 1-basic
@@ -599,9 +702,10 @@ options:
- 48-basic
- 54
- 54-basic
- rates-11n-ss12:
+ rates_11n_ss12:
description:
- Allowed data rates for 802.11n with 1 or 2 spatial streams.
+ type: str
choices:
- mcs0/1
- mcs1/1
@@ -619,9 +723,10 @@ options:
- mcs13/2
- mcs14/2
- mcs15/2
- rates-11n-ss34:
+ rates_11n_ss34:
description:
- Allowed data rates for 802.11n with 3 or 4 spatial streams.
+ type: str
choices:
- mcs16/3
- mcs17/3
@@ -642,9 +747,11 @@ options:
schedule:
description:
- VAP schedule name.
+ type: str
security:
description:
- - Security mode for the wireless interface (default = wpa2-only-personal).
+ - Security mode for the wireless interface .
+ type: str
choices:
- open
- captive-portal
@@ -660,29 +767,35 @@ options:
- wpa2-only-personal+captive-portal
- wpa2-only-enterprise
- osen
- security-exempt-list:
+ security_exempt_list:
description:
- Optional security exempt list for captive portal authentication.
- security-obsolete-option:
+ type: str
+ security_obsolete_option:
description:
- Enable/disable obsolete security options.
+ type: str
choices:
- enable
- disable
- security-redirect-url:
+ security_redirect_url:
description:
- Optional URL for redirecting users after they pass captive portal authentication.
- selected-usergroups:
+ type: str
+ selected_usergroups:
description:
- Selective user groups that are permitted to authenticate.
+ type: list
suboptions:
name:
description:
- User group name.
required: true
- split-tunneling:
+ type: str
+ split_tunneling:
description:
- - Enable/disable split tunneling (default = disable).
+ - Enable/disable split tunneling .
+ type: str
choices:
- enable
- disable
@@ -690,47 +803,58 @@ options:
description:
- IEEE 802.11 service set identifier (SSID) for the wireless interface. Users who wish to use the wireless network must configure their
computers to access this SSID name.
- tkip-counter-measure:
+ type: str
+ tkip_counter_measure:
description:
- Enable/disable TKIP counter measure.
+ type: str
choices:
- enable
- disable
usergroup:
description:
- Firewall user group to be used to authenticate WiFi users.
+ type: list
suboptions:
name:
description:
- User group name.
required: true
- utm-profile:
+ type: str
+ utm_profile:
description:
- UTM profile name.
+ type: str
vdom:
description:
- Name of the VDOM that the Virtual AP has been added to. Source system.vdom.name.
- vlan-auto:
+ type: str
+ vlan_auto:
description:
- Enable/disable automatic management of SSID VLAN interface.
+ type: str
choices:
- enable
- disable
- vlan-pool:
+ vlan_pool:
description:
- VLAN pool.
+ type: list
suboptions:
id:
description:
- ID.
required: true
- wtp-group:
+ type: int
+ wtp_group:
description:
- WTP group name.
- vlan-pooling:
+ type: str
+ vlan_pooling:
description:
- - Enable/disable VLAN pooling, to allow grouping of multiple wireless controller VLANs into VLAN pools (default = disable). When set to
- wtp-group, VLAN pooling occurs with VLAN assignment by wtp-group.
+ - Enable/disable VLAN pooling, to allow grouping of multiple wireless controller VLANs into VLAN pools . When set to wtp-group, VLAN
+ pooling occurs with VLAN assignment by wtp-group.
+ type: str
choices:
- wtp-group
- round-robin
@@ -739,9 +863,11 @@ options:
vlanid:
description:
- Optional VLAN ID.
- voice-enterprise:
+ type: int
+ voice_enterprise:
description:
- - Enable/disable 802.11k and 802.11v assisted Voice-Enterprise roaming (default = disable).
+ - Enable/disable 802.11k and 802.11v assisted Voice-Enterprise roaming .
+ type: str
choices:
- disable
- enable
@@ -754,6 +880,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure Virtual Access Points (VAPs).
fortios_wireless_controller_vap:
@@ -762,129 +889,129 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
+ state: "present"
wireless_controller_vap:
- state: "present"
- acct-interim-interval: "3"
+ acct_interim_interval: "3"
alias: "<your_own_value>"
auth: "psk"
- broadcast-ssid: "enable"
- broadcast-suppression: "dhcp-up"
- captive-portal-ac-name: "<your_own_value>"
- captive-portal-macauth-radius-secret: "<your_own_value>"
- captive-portal-macauth-radius-server: "<your_own_value>"
- captive-portal-radius-secret: "<your_own_value>"
- captive-portal-radius-server: "<your_own_value>"
- captive-portal-session-timeout-interval: "13"
- dhcp-lease-time: "14"
- dhcp-option82-circuit-id-insertion: "style-1"
- dhcp-option82-insertion: "enable"
- dhcp-option82-remote-id-insertion: "style-1"
- dynamic-vlan: "enable"
- eap-reauth: "enable"
- eap-reauth-intv: "20"
- eapol-key-retries: "disable"
+ broadcast_ssid: "enable"
+ broadcast_suppression: "dhcp-up"
+ captive_portal_ac_name: "<your_own_value>"
+ captive_portal_macauth_radius_secret: "<your_own_value>"
+ captive_portal_macauth_radius_server: "<your_own_value>"
+ captive_portal_radius_secret: "<your_own_value>"
+ captive_portal_radius_server: "<your_own_value>"
+ captive_portal_session_timeout_interval: "13"
+ dhcp_lease_time: "14"
+ dhcp_option82_circuit_id_insertion: "style-1"
+ dhcp_option82_insertion: "enable"
+ dhcp_option82_remote_id_insertion: "style-1"
+ dynamic_vlan: "enable"
+ eap_reauth: "enable"
+ eap_reauth_intv: "20"
+ eapol_key_retries: "disable"
encrypt: "TKIP"
- external-fast-roaming: "enable"
- external-logout: "<your_own_value>"
- external-web: "<your_own_value>"
- fast-bss-transition: "disable"
- fast-roaming: "enable"
- ft-mobility-domain: "28"
- ft-over-ds: "disable"
- ft-r0-key-lifetime: "30"
- gtk-rekey: "enable"
- gtk-rekey-intv: "32"
- hotspot20-profile: "<your_own_value>"
- intra-vap-privacy: "enable"
+ external_fast_roaming: "enable"
+ external_logout: "<your_own_value>"
+ external_web: "<your_own_value>"
+ fast_bss_transition: "disable"
+ fast_roaming: "enable"
+ ft_mobility_domain: "28"
+ ft_over_ds: "disable"
+ ft_r0_key_lifetime: "30"
+ gtk_rekey: "enable"
+ gtk_rekey_intv: "32"
+ hotspot20_profile: "<your_own_value>"
+ intra_vap_privacy: "enable"
ip: "<your_own_value>"
key: "<your_own_value>"
keyindex: "37"
ldpc: "disable"
- local-authentication: "enable"
- local-bridging: "enable"
- local-lan: "allow"
- local-standalone: "enable"
- local-standalone-nat: "enable"
- mac-auth-bypass: "enable"
- mac-filter: "enable"
- mac-filter-list:
+ local_authentication: "enable"
+ local_bridging: "enable"
+ local_lan: "allow"
+ local_standalone: "enable"
+ local_standalone_nat: "enable"
+ mac_auth_bypass: "enable"
+ mac_filter: "enable"
+ mac_filter_list:
-
id: "47"
mac: "<your_own_value>"
- mac-filter-policy: "allow"
- mac-filter-policy-other: "allow"
- max-clients: "51"
- max-clients-ap: "52"
- me-disable-thresh: "53"
- mesh-backhaul: "enable"
+ mac_filter_policy: "allow"
+ mac_filter_policy_other: "allow"
+ max_clients: "51"
+ max_clients_ap: "52"
+ me_disable_thresh: "53"
+ mesh_backhaul: "enable"
mpsk: "enable"
- mpsk-concurrent-clients: "56"
- mpsk-key:
+ mpsk_concurrent_clients: "56"
+ mpsk_key:
-
comment: "Comment."
- concurrent-clients: "<your_own_value>"
- key-name: "<your_own_value>"
+ concurrent_clients: "<your_own_value>"
+ key_name: "<your_own_value>"
passphrase: "<your_own_value>"
- multicast-enhance: "enable"
- multicast-rate: "0"
+ multicast_enhance: "enable"
+ multicast_rate: "0"
name: "default_name_64"
okc: "disable"
passphrase: "<your_own_value>"
pmf: "disable"
- pmf-assoc-comeback-timeout: "68"
- pmf-sa-query-retry-timeout: "69"
- portal-message-override-group: "<your_own_value>"
- portal-message-overrides:
- auth-disclaimer-page: "<your_own_value>"
- auth-login-failed-page: "<your_own_value>"
- auth-login-page: "<your_own_value>"
- auth-reject-page: "<your_own_value>"
- portal-type: "auth"
- probe-resp-suppression: "enable"
- probe-resp-threshold: "<your_own_value>"
- ptk-rekey: "enable"
- ptk-rekey-intv: "80"
- qos-profile: "<your_own_value>"
+ pmf_assoc_comeback_timeout: "68"
+ pmf_sa_query_retry_timeout: "69"
+ portal_message_override_group: "<your_own_value>"
+ portal_message_overrides:
+ auth_disclaimer_page: "<your_own_value>"
+ auth_login_failed_page: "<your_own_value>"
+ auth_login_page: "<your_own_value>"
+ auth_reject_page: "<your_own_value>"
+ portal_type: "auth"
+ probe_resp_suppression: "enable"
+ probe_resp_threshold: "<your_own_value>"
+ ptk_rekey: "enable"
+ ptk_rekey_intv: "80"
+ qos_profile: "<your_own_value>"
quarantine: "enable"
- radio-2g-threshold: "<your_own_value>"
- radio-5g-threshold: "<your_own_value>"
- radio-sensitivity: "enable"
- radius-mac-auth: "enable"
- radius-mac-auth-server: "<your_own_value>"
- radius-mac-auth-usergroups:
+ radio_2g_threshold: "<your_own_value>"
+ radio_5g_threshold: "<your_own_value>"
+ radio_sensitivity: "enable"
+ radius_mac_auth: "enable"
+ radius_mac_auth_server: "<your_own_value>"
+ radius_mac_auth_usergroups:
-
name: "default_name_89"
- radius-server: "<your_own_value>"
- rates-11a: "1"
- rates-11ac-ss12: "mcs0/1"
- rates-11ac-ss34: "mcs0/3"
- rates-11bg: "1"
- rates-11n-ss12: "mcs0/1"
- rates-11n-ss34: "mcs16/3"
+ radius_server: "<your_own_value>"
+ rates_11a: "1"
+ rates_11ac_ss12: "mcs0/1"
+ rates_11ac_ss34: "mcs0/3"
+ rates_11bg: "1"
+ rates_11n_ss12: "mcs0/1"
+ rates_11n_ss34: "mcs16/3"
schedule: "<your_own_value>"
security: "open"
- security-exempt-list: "<your_own_value>"
- security-obsolete-option: "enable"
- security-redirect-url: "<your_own_value>"
- selected-usergroups:
+ security_exempt_list: "<your_own_value>"
+ security_obsolete_option: "enable"
+ security_redirect_url: "<your_own_value>"
+ selected_usergroups:
-
name: "default_name_103"
- split-tunneling: "enable"
+ split_tunneling: "enable"
ssid: "<your_own_value>"
- tkip-counter-measure: "enable"
+ tkip_counter_measure: "enable"
usergroup:
-
name: "default_name_108"
- utm-profile: "<your_own_value>"
+ utm_profile: "<your_own_value>"
vdom: "<your_own_value> (source system.vdom.name)"
- vlan-auto: "enable"
- vlan-pool:
+ vlan_auto: "enable"
+ vlan_pool:
-
id: "113"
- wtp-group: "<your_own_value>"
- vlan-pooling: "wtp-group"
+ wtp_group: "<your_own_value>"
+ vlan_pooling: "wtp-group"
vlanid: "116"
- voice-enterprise: "disable"
+ voice_enterprise: "disable"
'''
RETURN = '''
@@ -947,12 +1074,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -960,43 +1091,43 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_vap_data(json):
- option_list = ['acct-interim-interval', 'alias', 'auth',
- 'broadcast-ssid', 'broadcast-suppression', 'captive-portal-ac-name',
- 'captive-portal-macauth-radius-secret', 'captive-portal-macauth-radius-server', 'captive-portal-radius-secret',
- 'captive-portal-radius-server', 'captive-portal-session-timeout-interval', 'dhcp-lease-time',
- 'dhcp-option82-circuit-id-insertion', 'dhcp-option82-insertion', 'dhcp-option82-remote-id-insertion',
- 'dynamic-vlan', 'eap-reauth', 'eap-reauth-intv',
- 'eapol-key-retries', 'encrypt', 'external-fast-roaming',
- 'external-logout', 'external-web', 'fast-bss-transition',
- 'fast-roaming', 'ft-mobility-domain', 'ft-over-ds',
- 'ft-r0-key-lifetime', 'gtk-rekey', 'gtk-rekey-intv',
- 'hotspot20-profile', 'intra-vap-privacy', 'ip',
+ option_list = ['acct_interim_interval', 'alias', 'auth',
+ 'broadcast_ssid', 'broadcast_suppression', 'captive_portal_ac_name',
+ 'captive_portal_macauth_radius_secret', 'captive_portal_macauth_radius_server', 'captive_portal_radius_secret',
+ 'captive_portal_radius_server', 'captive_portal_session_timeout_interval', 'dhcp_lease_time',
+ 'dhcp_option82_circuit_id_insertion', 'dhcp_option82_insertion', 'dhcp_option82_remote_id_insertion',
+ 'dynamic_vlan', 'eap_reauth', 'eap_reauth_intv',
+ 'eapol_key_retries', 'encrypt', 'external_fast_roaming',
+ 'external_logout', 'external_web', 'fast_bss_transition',
+ 'fast_roaming', 'ft_mobility_domain', 'ft_over_ds',
+ 'ft_r0_key_lifetime', 'gtk_rekey', 'gtk_rekey_intv',
+ 'hotspot20_profile', 'intra_vap_privacy', 'ip',
'key', 'keyindex', 'ldpc',
- 'local-authentication', 'local-bridging', 'local-lan',
- 'local-standalone', 'local-standalone-nat', 'mac-auth-bypass',
- 'mac-filter', 'mac-filter-list', 'mac-filter-policy-other',
- 'max-clients', 'max-clients-ap', 'me-disable-thresh',
- 'mesh-backhaul', 'mpsk', 'mpsk-concurrent-clients',
- 'mpsk-key', 'multicast-enhance', 'multicast-rate',
+ 'local_authentication', 'local_bridging', 'local_lan',
+ 'local_standalone', 'local_standalone_nat', 'mac_auth_bypass',
+ 'mac_filter', 'mac_filter_list', 'mac_filter_policy_other',
+ 'max_clients', 'max_clients_ap', 'me_disable_thresh',
+ 'mesh_backhaul', 'mpsk', 'mpsk_concurrent_clients',
+ 'mpsk_key', 'multicast_enhance', 'multicast_rate',
'name', 'okc', 'passphrase',
- 'pmf', 'pmf-assoc-comeback-timeout', 'pmf-sa-query-retry-timeout',
- 'portal-message-override-group', 'portal-message-overrides', 'portal-type',
- 'probe-resp-suppression', 'probe-resp-threshold', 'ptk-rekey',
- 'ptk-rekey-intv', 'qos-profile', 'quarantine',
- 'radio-2g-threshold', 'radio-5g-threshold', 'radio-sensitivity',
- 'radius-mac-auth', 'radius-mac-auth-server', 'radius-mac-auth-usergroups',
- 'radius-server', 'rates-11a', 'rates-11ac-ss12',
- 'rates-11ac-ss34', 'rates-11bg', 'rates-11n-ss12',
- 'rates-11n-ss34', 'schedule', 'security',
- 'security-exempt-list', 'security-obsolete-option', 'security-redirect-url',
- 'selected-usergroups', 'split-tunneling', 'ssid',
- 'tkip-counter-measure', 'usergroup', 'utm-profile',
- 'vdom', 'vlan-auto', 'vlan-pool',
- 'vlan-pooling', 'vlanid', 'voice-enterprise']
+ 'pmf', 'pmf_assoc_comeback_timeout', 'pmf_sa_query_retry_timeout',
+ 'portal_message_override_group', 'portal_message_overrides', 'portal_type',
+ 'probe_resp_suppression', 'probe_resp_threshold', 'ptk_rekey',
+ 'ptk_rekey_intv', 'qos_profile', 'quarantine',
+ 'radio_2g_threshold', 'radio_5g_threshold', 'radio_sensitivity',
+ 'radius_mac_auth', 'radius_mac_auth_server', 'radius_mac_auth_usergroups',
+ 'radius_server', 'rates_11a', 'rates_11ac_ss12',
+ 'rates_11ac_ss34', 'rates_11bg', 'rates_11n_ss12',
+ 'rates_11n_ss34', 'schedule', 'security',
+ 'security_exempt_list', 'security_obsolete_option', 'security_redirect_url',
+ 'selected_usergroups', 'split_tunneling', 'ssid',
+ 'tkip_counter_measure', 'usergroup', 'utm_profile',
+ 'vdom', 'vlan_auto', 'vlan_pool',
+ 'vlan_pooling', 'vlanid', 'voice_enterprise']
dictionary = {}
for attribute in option_list:
@@ -1006,112 +1137,117 @@ def filter_wireless_controller_vap_data(json):
return dictionary
-def flatten_multilists_attributes(data):
- multilist_attrs = []
-
- for attr in multilist_attrs:
- try:
- path = "data['" + "']['".join(elem for elem in attr) + "']"
- current_val = eval(path)
- flattened_val = ' '.join(elem for elem in current_val)
- exec(path + '= flattened_val')
- except BaseException:
- pass
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
return data
def wireless_controller_vap(data, fos):
vdom = data['vdom']
+ state = data['state']
wireless_controller_vap_data = data['wireless_controller_vap']
- flattened_data = flatten_multilists_attributes(wireless_controller_vap_data)
- filtered_data = filter_wireless_controller_vap_data(flattened_data)
- if wireless_controller_vap_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_vap_data(wireless_controller_vap_data))
+
+ if state == "present":
return fos.set('wireless-controller',
'vap',
data=filtered_data,
vdom=vdom)
- elif wireless_controller_vap_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('wireless-controller',
'vap',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_vap']:
resp = wireless_controller_vap(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"wireless_controller_vap": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
- "acct-interim-interval": {"required": False, "type": "int"},
+ "acct_interim_interval": {"required": False, "type": "int"},
"alias": {"required": False, "type": "str"},
"auth": {"required": False, "type": "str",
"choices": ["psk", "radius", "usergroup"]},
- "broadcast-ssid": {"required": False, "type": "str",
+ "broadcast_ssid": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "broadcast-suppression": {"required": False, "type": "str",
+ "broadcast_suppression": {"required": False, "type": "str",
"choices": ["dhcp-up", "dhcp-down", "dhcp-starvation",
"arp-known", "arp-unknown", "arp-reply",
"arp-poison", "arp-proxy", "netbios-ns",
"netbios-ds", "ipv6", "all-other-mc",
"all-other-bc"]},
- "captive-portal-ac-name": {"required": False, "type": "str"},
- "captive-portal-macauth-radius-secret": {"required": False, "type": "str"},
- "captive-portal-macauth-radius-server": {"required": False, "type": "str"},
- "captive-portal-radius-secret": {"required": False, "type": "str"},
- "captive-portal-radius-server": {"required": False, "type": "str"},
- "captive-portal-session-timeout-interval": {"required": False, "type": "int"},
- "dhcp-lease-time": {"required": False, "type": "int"},
- "dhcp-option82-circuit-id-insertion": {"required": False, "type": "str",
+ "captive_portal_ac_name": {"required": False, "type": "str"},
+ "captive_portal_macauth_radius_secret": {"required": False, "type": "str"},
+ "captive_portal_macauth_radius_server": {"required": False, "type": "str"},
+ "captive_portal_radius_secret": {"required": False, "type": "str"},
+ "captive_portal_radius_server": {"required": False, "type": "str"},
+ "captive_portal_session_timeout_interval": {"required": False, "type": "int"},
+ "dhcp_lease_time": {"required": False, "type": "int"},
+ "dhcp_option82_circuit_id_insertion": {"required": False, "type": "str",
"choices": ["style-1", "style-2", "disable"]},
- "dhcp-option82-insertion": {"required": False, "type": "str",
+ "dhcp_option82_insertion": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "dhcp-option82-remote-id-insertion": {"required": False, "type": "str",
+ "dhcp_option82_remote_id_insertion": {"required": False, "type": "str",
"choices": ["style-1", "disable"]},
- "dynamic-vlan": {"required": False, "type": "str",
+ "dynamic_vlan": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eap-reauth": {"required": False, "type": "str",
+ "eap_reauth": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eap-reauth-intv": {"required": False, "type": "int"},
- "eapol-key-retries": {"required": False, "type": "str",
+ "eap_reauth_intv": {"required": False, "type": "int"},
+ "eapol_key_retries": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"encrypt": {"required": False, "type": "str",
"choices": ["TKIP", "AES", "TKIP-AES"]},
- "external-fast-roaming": {"required": False, "type": "str",
+ "external_fast_roaming": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "external-logout": {"required": False, "type": "str"},
- "external-web": {"required": False, "type": "str"},
- "fast-bss-transition": {"required": False, "type": "str",
+ "external_logout": {"required": False, "type": "str"},
+ "external_web": {"required": False, "type": "str"},
+ "fast_bss_transition": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
- "fast-roaming": {"required": False, "type": "str",
+ "fast_roaming": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ft-mobility-domain": {"required": False, "type": "int"},
- "ft-over-ds": {"required": False, "type": "str",
+ "ft_mobility_domain": {"required": False, "type": "int"},
+ "ft_over_ds": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
- "ft-r0-key-lifetime": {"required": False, "type": "int"},
- "gtk-rekey": {"required": False, "type": "str",
+ "ft_r0_key_lifetime": {"required": False, "type": "int"},
+ "gtk_rekey": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "gtk-rekey-intv": {"required": False, "type": "int"},
- "hotspot20-profile": {"required": False, "type": "str"},
- "intra-vap-privacy": {"required": False, "type": "str",
+ "gtk_rekey_intv": {"required": False, "type": "int"},
+ "hotspot20_profile": {"required": False, "type": "str"},
+ "intra_vap_privacy": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"ip": {"required": False, "type": "str"},
"key": {"required": False, "type": "str"},
@@ -1119,47 +1255,47 @@ def main():
"ldpc": {"required": False, "type": "str",
"choices": ["disable", "rx", "tx",
"rxtx"]},
- "local-authentication": {"required": False, "type": "str",
+ "local_authentication": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "local-bridging": {"required": False, "type": "str",
+ "local_bridging": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "local-lan": {"required": False, "type": "str",
+ "local_lan": {"required": False, "type": "str",
"choices": ["allow", "deny"]},
- "local-standalone": {"required": False, "type": "str",
+ "local_standalone": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "local-standalone-nat": {"required": False, "type": "str",
+ "local_standalone_nat": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "mac-auth-bypass": {"required": False, "type": "str",
+ "mac_auth_bypass": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "mac-filter": {"required": False, "type": "str",
+ "mac_filter": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "mac-filter-list": {"required": False, "type": "list",
+ "mac_filter_list": {"required": False, "type": "list",
"options": {
"id": {"required": True, "type": "int"},
"mac": {"required": False, "type": "str"},
- "mac-filter-policy": {"required": False, "type": "str",
+ "mac_filter_policy": {"required": False, "type": "str",
"choices": ["allow", "deny"]}
}},
- "mac-filter-policy-other": {"required": False, "type": "str",
+ "mac_filter_policy_other": {"required": False, "type": "str",
"choices": ["allow", "deny"]},
- "max-clients": {"required": False, "type": "int"},
- "max-clients-ap": {"required": False, "type": "int"},
- "me-disable-thresh": {"required": False, "type": "int"},
- "mesh-backhaul": {"required": False, "type": "str",
+ "max_clients": {"required": False, "type": "int"},
+ "max_clients_ap": {"required": False, "type": "int"},
+ "me_disable_thresh": {"required": False, "type": "int"},
+ "mesh_backhaul": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"mpsk": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "mpsk-concurrent-clients": {"required": False, "type": "int"},
- "mpsk-key": {"required": False, "type": "list",
+ "mpsk_concurrent_clients": {"required": False, "type": "int"},
+ "mpsk_key": {"required": False, "type": "list",
"options": {
"comment": {"required": False, "type": "str"},
- "concurrent-clients": {"required": False, "type": "str"},
- "key-name": {"required": True, "type": "str"},
+ "concurrent_clients": {"required": False, "type": "str"},
+ "key_name": {"required": False, "type": "str"},
"passphrase": {"required": False, "type": "str"}
}},
- "multicast-enhance": {"required": False, "type": "str",
+ "multicast_enhance": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "multicast-rate": {"required": False, "type": "str",
+ "multicast_rate": {"required": False, "type": "str",
"choices": ["0", "6000", "12000",
"24000"]},
"name": {"required": True, "type": "str"},
@@ -1168,42 +1304,42 @@ def main():
"passphrase": {"required": False, "type": "str"},
"pmf": {"required": False, "type": "str",
"choices": ["disable", "enable", "optional"]},
- "pmf-assoc-comeback-timeout": {"required": False, "type": "int"},
- "pmf-sa-query-retry-timeout": {"required": False, "type": "int"},
- "portal-message-override-group": {"required": False, "type": "str"},
- "portal-message-overrides": {"required": False, "type": "dict",
+ "pmf_assoc_comeback_timeout": {"required": False, "type": "int"},
+ "pmf_sa_query_retry_timeout": {"required": False, "type": "int"},
+ "portal_message_override_group": {"required": False, "type": "str"},
+ "portal_message_overrides": {"required": False, "type": "dict",
"options": {
- "auth-disclaimer-page": {"required": False, "type": "str"},
- "auth-login-failed-page": {"required": False, "type": "str"},
- "auth-login-page": {"required": False, "type": "str"},
- "auth-reject-page": {"required": False, "type": "str"}
+ "auth_disclaimer_page": {"required": False, "type": "str"},
+ "auth_login_failed_page": {"required": False, "type": "str"},
+ "auth_login_page": {"required": False, "type": "str"},
+ "auth_reject_page": {"required": False, "type": "str"}
}},
- "portal-type": {"required": False, "type": "str",
+ "portal_type": {"required": False, "type": "str",
"choices": ["auth", "auth+disclaimer", "disclaimer",
"email-collect", "cmcc", "cmcc-macauth",
"auth-mac"]},
- "probe-resp-suppression": {"required": False, "type": "str",
+ "probe_resp_suppression": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "probe-resp-threshold": {"required": False, "type": "str"},
- "ptk-rekey": {"required": False, "type": "str",
+ "probe_resp_threshold": {"required": False, "type": "str"},
+ "ptk_rekey": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ptk-rekey-intv": {"required": False, "type": "int"},
- "qos-profile": {"required": False, "type": "str"},
+ "ptk_rekey_intv": {"required": False, "type": "int"},
+ "qos_profile": {"required": False, "type": "str"},
"quarantine": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "radio-2g-threshold": {"required": False, "type": "str"},
- "radio-5g-threshold": {"required": False, "type": "str"},
- "radio-sensitivity": {"required": False, "type": "str",
+ "radio_2g_threshold": {"required": False, "type": "str"},
+ "radio_5g_threshold": {"required": False, "type": "str"},
+ "radio_sensitivity": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "radius-mac-auth": {"required": False, "type": "str",
+ "radius_mac_auth": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "radius-mac-auth-server": {"required": False, "type": "str"},
- "radius-mac-auth-usergroups": {"required": False, "type": "list",
+ "radius_mac_auth_server": {"required": False, "type": "str"},
+ "radius_mac_auth_usergroups": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "radius-server": {"required": False, "type": "str"},
- "rates-11a": {"required": False, "type": "str",
+ "radius_server": {"required": False, "type": "str"},
+ "rates_11a": {"required": False, "type": "str",
"choices": ["1", "1-basic", "2",
"2-basic", "5.5", "5.5-basic",
"11", "11-basic", "6",
@@ -1212,7 +1348,7 @@ def main():
"18-basic", "24", "24-basic",
"36", "36-basic", "48",
"48-basic", "54", "54-basic"]},
- "rates-11ac-ss12": {"required": False, "type": "str",
+ "rates_11ac_ss12": {"required": False, "type": "str",
"choices": ["mcs0/1", "mcs1/1", "mcs2/1",
"mcs3/1", "mcs4/1", "mcs5/1",
"mcs6/1", "mcs7/1", "mcs8/1",
@@ -1221,7 +1357,7 @@ def main():
"mcs3/2", "mcs4/2", "mcs5/2",
"mcs6/2", "mcs7/2", "mcs8/2",
"mcs9/2", "mcs10/2", "mcs11/2"]},
- "rates-11ac-ss34": {"required": False, "type": "str",
+ "rates_11ac_ss34": {"required": False, "type": "str",
"choices": ["mcs0/3", "mcs1/3", "mcs2/3",
"mcs3/3", "mcs4/3", "mcs5/3",
"mcs6/3", "mcs7/3", "mcs8/3",
@@ -1230,7 +1366,7 @@ def main():
"mcs3/4", "mcs4/4", "mcs5/4",
"mcs6/4", "mcs7/4", "mcs8/4",
"mcs9/4", "mcs10/4", "mcs11/4"]},
- "rates-11bg": {"required": False, "type": "str",
+ "rates_11bg": {"required": False, "type": "str",
"choices": ["1", "1-basic", "2",
"2-basic", "5.5", "5.5-basic",
"11", "11-basic", "6",
@@ -1239,14 +1375,14 @@ def main():
"18-basic", "24", "24-basic",
"36", "36-basic", "48",
"48-basic", "54", "54-basic"]},
- "rates-11n-ss12": {"required": False, "type": "str",
+ "rates_11n_ss12": {"required": False, "type": "str",
"choices": ["mcs0/1", "mcs1/1", "mcs2/1",
"mcs3/1", "mcs4/1", "mcs5/1",
"mcs6/1", "mcs7/1", "mcs8/2",
"mcs9/2", "mcs10/2", "mcs11/2",
"mcs12/2", "mcs13/2", "mcs14/2",
"mcs15/2"]},
- "rates-11n-ss34": {"required": False, "type": "str",
+ "rates_11n_ss34": {"required": False, "type": "str",
"choices": ["mcs16/3", "mcs17/3", "mcs18/3",
"mcs19/3", "mcs20/3", "mcs21/3",
"mcs22/3", "mcs23/3", "mcs24/4",
@@ -1260,37 +1396,37 @@ def main():
"wpa-enterprise", "wpa-only-personal", "wpa-only-personal+captive-portal",
"wpa-only-enterprise", "wpa2-only-personal", "wpa2-only-personal+captive-portal",
"wpa2-only-enterprise", "osen"]},
- "security-exempt-list": {"required": False, "type": "str"},
- "security-obsolete-option": {"required": False, "type": "str",
+ "security_exempt_list": {"required": False, "type": "str"},
+ "security_obsolete_option": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "security-redirect-url": {"required": False, "type": "str"},
- "selected-usergroups": {"required": False, "type": "list",
+ "security_redirect_url": {"required": False, "type": "str"},
+ "selected_usergroups": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "split-tunneling": {"required": False, "type": "str",
+ "split_tunneling": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"ssid": {"required": False, "type": "str"},
- "tkip-counter-measure": {"required": False, "type": "str",
+ "tkip_counter_measure": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"usergroup": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "utm-profile": {"required": False, "type": "str"},
+ "utm_profile": {"required": False, "type": "str"},
"vdom": {"required": False, "type": "str"},
- "vlan-auto": {"required": False, "type": "str",
+ "vlan_auto": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "vlan-pool": {"required": False, "type": "list",
+ "vlan_pool": {"required": False, "type": "list",
"options": {
"id": {"required": True, "type": "int"},
- "wtp-group": {"required": False, "type": "str"}
+ "wtp_group": {"required": False, "type": "str"}
}},
- "vlan-pooling": {"required": False, "type": "str",
+ "vlan_pooling": {"required": False, "type": "str",
"choices": ["wtp-group", "round-robin", "hash",
"disable"]},
"vlanid": {"required": False, "type": "int"},
- "voice-enterprise": {"required": False, "type": "str",
+ "voice_enterprise": {"required": False, "type": "str",
"choices": ["disable", "enable"]}
}
@@ -1299,14 +1435,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py
index f0b67a3f34..f643128cdf 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_wids_profile
short_description: Configure wireless intrusion detection system (WIDS) profiles in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and wids_profile category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,49 +41,64 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
wireless_controller_wids_profile:
description:
- Configure wireless intrusion detection system (WIDS) profiles.
default: null
+ type: dict
suboptions:
- state:
+ ap_auto_suppress:
description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
- ap-auto-suppress:
- description:
- - Enable/disable on-wire rogue AP auto-suppression (default = disable).
+ - Enable/disable on-wire rogue AP auto-suppression .
+ type: str
choices:
- enable
- disable
- ap-bgscan-disable-day:
+ ap_bgscan_disable_day:
description:
- Optionally turn off scanning for one or more days of the week. Separate the days with a space. By default, no days are set.
+ type: str
choices:
- sunday
- monday
@@ -92,203 +107,250 @@ options:
- thursday
- friday
- saturday
- ap-bgscan-disable-end:
+ ap_bgscan_disable_end:
description:
- - "End time, using a 24-hour clock in the format of hh:mm, for disabling background scanning (default = 00:00)."
- ap-bgscan-disable-start:
+ - "End time, using a 24-hour clock in the format of hh:mm, for disabling background scanning ."
+ type: str
+ ap_bgscan_disable_start:
description:
- - "Start time, using a 24-hour clock in the format of hh:mm, for disabling background scanning (default = 00:00)."
- ap-bgscan-duration:
+ - "Start time, using a 24-hour clock in the format of hh:mm, for disabling background scanning ."
+ type: str
+ ap_bgscan_duration:
description:
- - Listening time on a scanning channel (10 - 1000 msec, default = 20).
- ap-bgscan-idle:
+ - Listening time on a scanning channel (10 - 1000 msec).
+ type: int
+ ap_bgscan_idle:
description:
- - Waiting time for channel inactivity before scanning this channel (0 - 1000 msec, default = 0).
- ap-bgscan-intv:
+ - Waiting time for channel inactivity before scanning this channel (0 - 1000 msec).
+ type: int
+ ap_bgscan_intv:
description:
- - Period of time between scanning two channels (1 - 600 sec, default = 1).
- ap-bgscan-period:
+ - Period of time between scanning two channels (1 - 600 sec).
+ type: int
+ ap_bgscan_period:
description:
- - Period of time between background scans (60 - 3600 sec, default = 600).
- ap-bgscan-report-intv:
+ - Period of time between background scans (60 - 3600 sec).
+ type: int
+ ap_bgscan_report_intv:
description:
- - Period of time between background scan reports (15 - 600 sec, default = 30).
- ap-fgscan-report-intv:
+ - Period of time between background scan reports (15 - 600 sec).
+ type: int
+ ap_fgscan_report_intv:
description:
- - Period of time between foreground scan reports (15 - 600 sec, default = 15).
- ap-scan:
+ - Period of time between foreground scan reports (15 - 600 sec).
+ type: int
+ ap_scan:
description:
- Enable/disable rogue AP detection.
+ type: str
choices:
- disable
- enable
- ap-scan-passive:
+ ap_scan_passive:
description:
- - Enable/disable passive scanning. Enable means do not send probe request on any channels (default = disable).
+ - Enable/disable passive scanning. Enable means do not send probe request on any channels .
+ type: str
choices:
- enable
- disable
- asleap-attack:
+ asleap_attack:
description:
- - Enable/disable asleap attack detection (default = disable).
+ - Enable/disable asleap attack detection .
+ type: str
choices:
- enable
- disable
- assoc-flood-thresh:
+ assoc_flood_thresh:
description:
- The threshold value for association frame flooding.
- assoc-flood-time:
+ type: int
+ assoc_flood_time:
description:
- Number of seconds after which a station is considered not connected.
- assoc-frame-flood:
+ type: int
+ assoc_frame_flood:
description:
- - Enable/disable association frame flooding detection (default = disable).
+ - Enable/disable association frame flooding detection .
+ type: str
choices:
- enable
- disable
- auth-flood-thresh:
+ auth_flood_thresh:
description:
- The threshold value for authentication frame flooding.
- auth-flood-time:
+ type: int
+ auth_flood_time:
description:
- Number of seconds after which a station is considered not connected.
- auth-frame-flood:
+ type: int
+ auth_frame_flood:
description:
- - Enable/disable authentication frame flooding detection (default = disable).
+ - Enable/disable authentication frame flooding detection .
+ type: str
choices:
- enable
- disable
comment:
description:
- Comment.
- deauth-broadcast:
+ type: str
+ deauth_broadcast:
description:
- - Enable/disable broadcasting de-authentication detection (default = disable).
+ - Enable/disable broadcasting de-authentication detection .
+ type: str
choices:
- enable
- disable
- deauth-unknown-src-thresh:
+ deauth_unknown_src_thresh:
description:
- "Threshold value per second to deauth unknown src for DoS attack (0: no limit)."
- eapol-fail-flood:
+ type: int
+ eapol_fail_flood:
description:
- - Enable/disable EAPOL-Failure flooding (to AP) detection (default = disable).
+ - Enable/disable EAPOL-Failure flooding (to AP) detection .
+ type: str
choices:
- enable
- disable
- eapol-fail-intv:
+ eapol_fail_intv:
description:
- The detection interval for EAPOL-Failure flooding (1 - 3600 sec).
- eapol-fail-thresh:
+ type: int
+ eapol_fail_thresh:
description:
- The threshold value for EAPOL-Failure flooding in specified interval.
- eapol-logoff-flood:
+ type: int
+ eapol_logoff_flood:
description:
- - Enable/disable EAPOL-Logoff flooding (to AP) detection (default = disable).
+ - Enable/disable EAPOL-Logoff flooding (to AP) detection .
+ type: str
choices:
- enable
- disable
- eapol-logoff-intv:
+ eapol_logoff_intv:
description:
- The detection interval for EAPOL-Logoff flooding (1 - 3600 sec).
- eapol-logoff-thresh:
+ type: int
+ eapol_logoff_thresh:
description:
- The threshold value for EAPOL-Logoff flooding in specified interval.
- eapol-pre-fail-flood:
+ type: int
+ eapol_pre_fail_flood:
description:
- - Enable/disable premature EAPOL-Failure flooding (to STA) detection (default = disable).
+ - Enable/disable premature EAPOL-Failure flooding (to STA) detection .
+ type: str
choices:
- enable
- disable
- eapol-pre-fail-intv:
+ eapol_pre_fail_intv:
description:
- The detection interval for premature EAPOL-Failure flooding (1 - 3600 sec).
- eapol-pre-fail-thresh:
+ type: int
+ eapol_pre_fail_thresh:
description:
- The threshold value for premature EAPOL-Failure flooding in specified interval.
- eapol-pre-succ-flood:
+ type: int
+ eapol_pre_succ_flood:
description:
- - Enable/disable premature EAPOL-Success flooding (to STA) detection (default = disable).
+ - Enable/disable premature EAPOL-Success flooding (to STA) detection .
+ type: str
choices:
- enable
- disable
- eapol-pre-succ-intv:
+ eapol_pre_succ_intv:
description:
- The detection interval for premature EAPOL-Success flooding (1 - 3600 sec).
- eapol-pre-succ-thresh:
+ type: int
+ eapol_pre_succ_thresh:
description:
- The threshold value for premature EAPOL-Success flooding in specified interval.
- eapol-start-flood:
+ type: int
+ eapol_start_flood:
description:
- - Enable/disable EAPOL-Start flooding (to AP) detection (default = disable).
+ - Enable/disable EAPOL-Start flooding (to AP) detection .
+ type: str
choices:
- enable
- disable
- eapol-start-intv:
+ eapol_start_intv:
description:
- The detection interval for EAPOL-Start flooding (1 - 3600 sec).
- eapol-start-thresh:
+ type: int
+ eapol_start_thresh:
description:
- The threshold value for EAPOL-Start flooding in specified interval.
- eapol-succ-flood:
+ type: int
+ eapol_succ_flood:
description:
- - Enable/disable EAPOL-Success flooding (to AP) detection (default = disable).
+ - Enable/disable EAPOL-Success flooding (to AP) detection .
+ type: str
choices:
- enable
- disable
- eapol-succ-intv:
+ eapol_succ_intv:
description:
- The detection interval for EAPOL-Success flooding (1 - 3600 sec).
- eapol-succ-thresh:
+ type: int
+ eapol_succ_thresh:
description:
- The threshold value for EAPOL-Success flooding in specified interval.
- invalid-mac-oui:
+ type: int
+ invalid_mac_oui:
description:
- Enable/disable invalid MAC OUI detection.
+ type: str
choices:
- enable
- disable
- long-duration-attack:
+ long_duration_attack:
description:
- - Enable/disable long duration attack detection based on user configured threshold (default = disable).
+ - Enable/disable long duration attack detection based on user configured threshold .
+ type: str
choices:
- enable
- disable
- long-duration-thresh:
+ long_duration_thresh:
description:
- - Threshold value for long duration attack detection (1000 - 32767 usec, default = 8200).
+ - Threshold value for long duration attack detection (1000 - 32767 usec).
+ type: int
name:
description:
- WIDS profile name.
required: true
- null-ssid-probe-resp:
+ type: str
+ null_ssid_probe_resp:
description:
- - Enable/disable null SSID probe response detection (default = disable).
+ - Enable/disable null SSID probe response detection .
+ type: str
choices:
- enable
- disable
- sensor-mode:
+ sensor_mode:
description:
- - Scan WiFi nearby stations (default = disable).
+ - Scan WiFi nearby stations .
+ type: str
choices:
- disable
- foreign
- both
- spoofed-deauth:
+ spoofed_deauth:
description:
- - Enable/disable spoofed de-authentication attack detection (default = disable).
+ - Enable/disable spoofed de-authentication attack detection .
+ type: str
choices:
- enable
- disable
- weak-wep-iv:
+ weak_wep_iv:
description:
- - Enable/disable weak WEP IV (Initialization Vector) detection (default = disable).
+ - Enable/disable weak WEP IV (Initialization Vector) detection .
+ type: str
choices:
- enable
- disable
- wireless-bridge:
+ wireless_bridge:
description:
- - Enable/disable wireless bridge detection (default = disable).
+ - Enable/disable wireless bridge detection .
+ type: str
choices:
- enable
- disable
@@ -301,6 +363,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure wireless intrusion detection system (WIDS) profiles.
fortios_wireless_controller_wids_profile:
@@ -309,57 +372,57 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
+ state: "present"
wireless_controller_wids_profile:
- state: "present"
- ap-auto-suppress: "enable"
- ap-bgscan-disable-day: "sunday"
- ap-bgscan-disable-end: "<your_own_value>"
- ap-bgscan-disable-start: "<your_own_value>"
- ap-bgscan-duration: "7"
- ap-bgscan-idle: "8"
- ap-bgscan-intv: "9"
- ap-bgscan-period: "10"
- ap-bgscan-report-intv: "11"
- ap-fgscan-report-intv: "12"
- ap-scan: "disable"
- ap-scan-passive: "enable"
- asleap-attack: "enable"
- assoc-flood-thresh: "16"
- assoc-flood-time: "17"
- assoc-frame-flood: "enable"
- auth-flood-thresh: "19"
- auth-flood-time: "20"
- auth-frame-flood: "enable"
+ ap_auto_suppress: "enable"
+ ap_bgscan_disable_day: "sunday"
+ ap_bgscan_disable_end: "<your_own_value>"
+ ap_bgscan_disable_start: "<your_own_value>"
+ ap_bgscan_duration: "7"
+ ap_bgscan_idle: "8"
+ ap_bgscan_intv: "9"
+ ap_bgscan_period: "10"
+ ap_bgscan_report_intv: "11"
+ ap_fgscan_report_intv: "12"
+ ap_scan: "disable"
+ ap_scan_passive: "enable"
+ asleap_attack: "enable"
+ assoc_flood_thresh: "16"
+ assoc_flood_time: "17"
+ assoc_frame_flood: "enable"
+ auth_flood_thresh: "19"
+ auth_flood_time: "20"
+ auth_frame_flood: "enable"
comment: "Comment."
- deauth-broadcast: "enable"
- deauth-unknown-src-thresh: "24"
- eapol-fail-flood: "enable"
- eapol-fail-intv: "26"
- eapol-fail-thresh: "27"
- eapol-logoff-flood: "enable"
- eapol-logoff-intv: "29"
- eapol-logoff-thresh: "30"
- eapol-pre-fail-flood: "enable"
- eapol-pre-fail-intv: "32"
- eapol-pre-fail-thresh: "33"
- eapol-pre-succ-flood: "enable"
- eapol-pre-succ-intv: "35"
- eapol-pre-succ-thresh: "36"
- eapol-start-flood: "enable"
- eapol-start-intv: "38"
- eapol-start-thresh: "39"
- eapol-succ-flood: "enable"
- eapol-succ-intv: "41"
- eapol-succ-thresh: "42"
- invalid-mac-oui: "enable"
- long-duration-attack: "enable"
- long-duration-thresh: "45"
+ deauth_broadcast: "enable"
+ deauth_unknown_src_thresh: "24"
+ eapol_fail_flood: "enable"
+ eapol_fail_intv: "26"
+ eapol_fail_thresh: "27"
+ eapol_logoff_flood: "enable"
+ eapol_logoff_intv: "29"
+ eapol_logoff_thresh: "30"
+ eapol_pre_fail_flood: "enable"
+ eapol_pre_fail_intv: "32"
+ eapol_pre_fail_thresh: "33"
+ eapol_pre_succ_flood: "enable"
+ eapol_pre_succ_intv: "35"
+ eapol_pre_succ_thresh: "36"
+ eapol_start_flood: "enable"
+ eapol_start_intv: "38"
+ eapol_start_thresh: "39"
+ eapol_succ_flood: "enable"
+ eapol_succ_intv: "41"
+ eapol_succ_thresh: "42"
+ invalid_mac_oui: "enable"
+ long_duration_attack: "enable"
+ long_duration_thresh: "45"
name: "default_name_46"
- null-ssid-probe-resp: "enable"
- sensor-mode: "disable"
- spoofed-deauth: "enable"
- weak-wep-iv: "enable"
- wireless-bridge: "enable"
+ null_ssid_probe_resp: "enable"
+ sensor_mode: "disable"
+ spoofed_deauth: "enable"
+ weak_wep_iv: "enable"
+ wireless_bridge: "enable"
'''
RETURN = '''
@@ -422,12 +485,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -435,27 +502,27 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_wids_profile_data(json):
- option_list = ['ap-auto-suppress', 'ap-bgscan-disable-day', 'ap-bgscan-disable-end',
- 'ap-bgscan-disable-start', 'ap-bgscan-duration', 'ap-bgscan-idle',
- 'ap-bgscan-intv', 'ap-bgscan-period', 'ap-bgscan-report-intv',
- 'ap-fgscan-report-intv', 'ap-scan', 'ap-scan-passive',
- 'asleap-attack', 'assoc-flood-thresh', 'assoc-flood-time',
- 'assoc-frame-flood', 'auth-flood-thresh', 'auth-flood-time',
- 'auth-frame-flood', 'comment', 'deauth-broadcast',
- 'deauth-unknown-src-thresh', 'eapol-fail-flood', 'eapol-fail-intv',
- 'eapol-fail-thresh', 'eapol-logoff-flood', 'eapol-logoff-intv',
- 'eapol-logoff-thresh', 'eapol-pre-fail-flood', 'eapol-pre-fail-intv',
- 'eapol-pre-fail-thresh', 'eapol-pre-succ-flood', 'eapol-pre-succ-intv',
- 'eapol-pre-succ-thresh', 'eapol-start-flood', 'eapol-start-intv',
- 'eapol-start-thresh', 'eapol-succ-flood', 'eapol-succ-intv',
- 'eapol-succ-thresh', 'invalid-mac-oui', 'long-duration-attack',
- 'long-duration-thresh', 'name', 'null-ssid-probe-resp',
- 'sensor-mode', 'spoofed-deauth', 'weak-wep-iv',
- 'wireless-bridge']
+ option_list = ['ap_auto_suppress', 'ap_bgscan_disable_day', 'ap_bgscan_disable_end',
+ 'ap_bgscan_disable_start', 'ap_bgscan_duration', 'ap_bgscan_idle',
+ 'ap_bgscan_intv', 'ap_bgscan_period', 'ap_bgscan_report_intv',
+ 'ap_fgscan_report_intv', 'ap_scan', 'ap_scan_passive',
+ 'asleap_attack', 'assoc_flood_thresh', 'assoc_flood_time',
+ 'assoc_frame_flood', 'auth_flood_thresh', 'auth_flood_time',
+ 'auth_frame_flood', 'comment', 'deauth_broadcast',
+ 'deauth_unknown_src_thresh', 'eapol_fail_flood', 'eapol_fail_intv',
+ 'eapol_fail_thresh', 'eapol_logoff_flood', 'eapol_logoff_intv',
+ 'eapol_logoff_thresh', 'eapol_pre_fail_flood', 'eapol_pre_fail_intv',
+ 'eapol_pre_fail_thresh', 'eapol_pre_succ_flood', 'eapol_pre_succ_intv',
+ 'eapol_pre_succ_thresh', 'eapol_start_flood', 'eapol_start_intv',
+ 'eapol_start_thresh', 'eapol_succ_flood', 'eapol_succ_intv',
+ 'eapol_succ_thresh', 'invalid_mac_oui', 'long_duration_attack',
+ 'long_duration_thresh', 'name', 'null_ssid_probe_resp',
+ 'sensor_mode', 'spoofed_deauth', 'weak_wep_iv',
+ 'wireless_bridge']
dictionary = {}
for attribute in option_list:
@@ -465,132 +532,137 @@ def filter_wireless_controller_wids_profile_data(json):
return dictionary
-def flatten_multilists_attributes(data):
- multilist_attrs = []
-
- for attr in multilist_attrs:
- try:
- path = "data['" + "']['".join(elem for elem in attr) + "']"
- current_val = eval(path)
- flattened_val = ' '.join(elem for elem in current_val)
- exec(path + '= flattened_val')
- except BaseException:
- pass
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
return data
def wireless_controller_wids_profile(data, fos):
vdom = data['vdom']
+ state = data['state']
wireless_controller_wids_profile_data = data['wireless_controller_wids_profile']
- flattened_data = flatten_multilists_attributes(wireless_controller_wids_profile_data)
- filtered_data = filter_wireless_controller_wids_profile_data(flattened_data)
- if wireless_controller_wids_profile_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_wids_profile_data(wireless_controller_wids_profile_data))
+
+ if state == "present":
return fos.set('wireless-controller',
'wids-profile',
data=filtered_data,
vdom=vdom)
- elif wireless_controller_wids_profile_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('wireless-controller',
'wids-profile',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_wids_profile']:
resp = wireless_controller_wids_profile(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"wireless_controller_wids_profile": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
- "ap-auto-suppress": {"required": False, "type": "str",
+ "ap_auto_suppress": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-bgscan-disable-day": {"required": False, "type": "str",
+ "ap_bgscan_disable_day": {"required": False, "type": "str",
"choices": ["sunday", "monday", "tuesday",
"wednesday", "thursday", "friday",
"saturday"]},
- "ap-bgscan-disable-end": {"required": False, "type": "str"},
- "ap-bgscan-disable-start": {"required": False, "type": "str"},
- "ap-bgscan-duration": {"required": False, "type": "int"},
- "ap-bgscan-idle": {"required": False, "type": "int"},
- "ap-bgscan-intv": {"required": False, "type": "int"},
- "ap-bgscan-period": {"required": False, "type": "int"},
- "ap-bgscan-report-intv": {"required": False, "type": "int"},
- "ap-fgscan-report-intv": {"required": False, "type": "int"},
- "ap-scan": {"required": False, "type": "str",
+ "ap_bgscan_disable_end": {"required": False, "type": "str"},
+ "ap_bgscan_disable_start": {"required": False, "type": "str"},
+ "ap_bgscan_duration": {"required": False, "type": "int"},
+ "ap_bgscan_idle": {"required": False, "type": "int"},
+ "ap_bgscan_intv": {"required": False, "type": "int"},
+ "ap_bgscan_period": {"required": False, "type": "int"},
+ "ap_bgscan_report_intv": {"required": False, "type": "int"},
+ "ap_fgscan_report_intv": {"required": False, "type": "int"},
+ "ap_scan": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
- "ap-scan-passive": {"required": False, "type": "str",
+ "ap_scan_passive": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "asleap-attack": {"required": False, "type": "str",
+ "asleap_attack": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "assoc-flood-thresh": {"required": False, "type": "int"},
- "assoc-flood-time": {"required": False, "type": "int"},
- "assoc-frame-flood": {"required": False, "type": "str",
+ "assoc_flood_thresh": {"required": False, "type": "int"},
+ "assoc_flood_time": {"required": False, "type": "int"},
+ "assoc_frame_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auth-flood-thresh": {"required": False, "type": "int"},
- "auth-flood-time": {"required": False, "type": "int"},
- "auth-frame-flood": {"required": False, "type": "str",
+ "auth_flood_thresh": {"required": False, "type": "int"},
+ "auth_flood_time": {"required": False, "type": "int"},
+ "auth_frame_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"comment": {"required": False, "type": "str"},
- "deauth-broadcast": {"required": False, "type": "str",
+ "deauth_broadcast": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "deauth-unknown-src-thresh": {"required": False, "type": "int"},
- "eapol-fail-flood": {"required": False, "type": "str",
+ "deauth_unknown_src_thresh": {"required": False, "type": "int"},
+ "eapol_fail_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eapol-fail-intv": {"required": False, "type": "int"},
- "eapol-fail-thresh": {"required": False, "type": "int"},
- "eapol-logoff-flood": {"required": False, "type": "str",
+ "eapol_fail_intv": {"required": False, "type": "int"},
+ "eapol_fail_thresh": {"required": False, "type": "int"},
+ "eapol_logoff_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eapol-logoff-intv": {"required": False, "type": "int"},
- "eapol-logoff-thresh": {"required": False, "type": "int"},
- "eapol-pre-fail-flood": {"required": False, "type": "str",
+ "eapol_logoff_intv": {"required": False, "type": "int"},
+ "eapol_logoff_thresh": {"required": False, "type": "int"},
+ "eapol_pre_fail_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eapol-pre-fail-intv": {"required": False, "type": "int"},
- "eapol-pre-fail-thresh": {"required": False, "type": "int"},
- "eapol-pre-succ-flood": {"required": False, "type": "str",
+ "eapol_pre_fail_intv": {"required": False, "type": "int"},
+ "eapol_pre_fail_thresh": {"required": False, "type": "int"},
+ "eapol_pre_succ_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eapol-pre-succ-intv": {"required": False, "type": "int"},
- "eapol-pre-succ-thresh": {"required": False, "type": "int"},
- "eapol-start-flood": {"required": False, "type": "str",
+ "eapol_pre_succ_intv": {"required": False, "type": "int"},
+ "eapol_pre_succ_thresh": {"required": False, "type": "int"},
+ "eapol_start_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eapol-start-intv": {"required": False, "type": "int"},
- "eapol-start-thresh": {"required": False, "type": "int"},
- "eapol-succ-flood": {"required": False, "type": "str",
+ "eapol_start_intv": {"required": False, "type": "int"},
+ "eapol_start_thresh": {"required": False, "type": "int"},
+ "eapol_succ_flood": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "eapol-succ-intv": {"required": False, "type": "int"},
- "eapol-succ-thresh": {"required": False, "type": "int"},
- "invalid-mac-oui": {"required": False, "type": "str",
+ "eapol_succ_intv": {"required": False, "type": "int"},
+ "eapol_succ_thresh": {"required": False, "type": "int"},
+ "invalid_mac_oui": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "long-duration-attack": {"required": False, "type": "str",
+ "long_duration_attack": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "long-duration-thresh": {"required": False, "type": "int"},
+ "long_duration_thresh": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"},
- "null-ssid-probe-resp": {"required": False, "type": "str",
+ "null_ssid_probe_resp": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "sensor-mode": {"required": False, "type": "str",
+ "sensor_mode": {"required": False, "type": "str",
"choices": ["disable", "foreign", "both"]},
- "spoofed-deauth": {"required": False, "type": "str",
+ "spoofed_deauth": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "weak-wep-iv": {"required": False, "type": "str",
+ "weak_wep_iv": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "wireless-bridge": {"required": False, "type": "str",
+ "wireless_bridge": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@@ -599,14 +671,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py
index 6844efa8c2..e19fed3870 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_wtp
short_description: Configure Wireless Termination Points (WTPs), that is, FortiAPs or APs to be managed by FortiGate in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and wtp category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,43 +41,57 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
wireless_controller_wtp:
description:
- Configure Wireless Termination Points (WTPs), that is, FortiAPs or APs to be managed by FortiGate.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
admin:
description:
- Configure how the FortiGate operating as a wireless controller discovers and manages this WTP, AP or FortiAP.
+ type: str
choices:
- discovered
- disable
@@ -85,173 +99,207 @@ options:
allowaccess:
description:
- Control management access to the managed WTP, FortiAP, or AP. Separate entries with a space.
+ type: str
choices:
- telnet
- http
- https
- ssh
- bonjour-profile:
+ bonjour_profile:
description:
- Bonjour profile name. Source wireless-controller.bonjour-profile.name.
- coordinate-enable:
+ type: str
+ coordinate_enable:
description:
- Enable/disable WTP coordinates (X,Y axis).
+ type: str
choices:
- enable
- disable
- coordinate-latitude:
+ coordinate_latitude:
description:
- WTP latitude coordinate.
- coordinate-longitude:
+ type: str
+ coordinate_longitude:
description:
- WTP longitude coordinate.
- coordinate-x:
+ type: str
+ coordinate_x:
description:
- X axis coordinate.
- coordinate-y:
+ type: str
+ coordinate_y:
description:
- Y axis coordinate.
- image-download:
+ type: str
+ image_download:
description:
- Enable/disable WTP image download.
+ type: str
choices:
- enable
- disable
index:
description:
- Index (0 - 4294967295).
- ip-fragment-preventing:
+ type: int
+ ip_fragment_preventing:
description:
- - Method by which IP fragmentation is prevented for CAPWAP tunneled control and data packets (default = tcp-mss-adjust).
+ - Method by which IP fragmentation is prevented for CAPWAP tunneled control and data packets .
+ type: str
choices:
- tcp-mss-adjust
- icmp-unreachable
lan:
description:
- WTP LAN port mapping.
+ type: dict
suboptions:
- port-mode:
+ port_mode:
description:
- LAN port mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port-ssid:
+ port_ssid:
description:
- Bridge LAN port to SSID. Source wireless-controller.vap.name.
- port1-mode:
+ type: str
+ port1_mode:
description:
- LAN port 1 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port1-ssid:
+ port1_ssid:
description:
- Bridge LAN port 1 to SSID. Source wireless-controller.vap.name.
- port2-mode:
+ type: str
+ port2_mode:
description:
- LAN port 2 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port2-ssid:
+ port2_ssid:
description:
- Bridge LAN port 2 to SSID. Source wireless-controller.vap.name.
- port3-mode:
+ type: str
+ port3_mode:
description:
- LAN port 3 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port3-ssid:
+ port3_ssid:
description:
- Bridge LAN port 3 to SSID. Source wireless-controller.vap.name.
- port4-mode:
+ type: str
+ port4_mode:
description:
- LAN port 4 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port4-ssid:
+ port4_ssid:
description:
- Bridge LAN port 4 to SSID. Source wireless-controller.vap.name.
- port5-mode:
+ type: str
+ port5_mode:
description:
- LAN port 5 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port5-ssid:
+ port5_ssid:
description:
- Bridge LAN port 5 to SSID. Source wireless-controller.vap.name.
- port6-mode:
+ type: str
+ port6_mode:
description:
- LAN port 6 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port6-ssid:
+ port6_ssid:
description:
- Bridge LAN port 6 to SSID. Source wireless-controller.vap.name.
- port7-mode:
+ type: str
+ port7_mode:
description:
- LAN port 7 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port7-ssid:
+ port7_ssid:
description:
- Bridge LAN port 7 to SSID. Source wireless-controller.vap.name.
- port8-mode:
+ type: str
+ port8_mode:
description:
- LAN port 8 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port8-ssid:
+ port8_ssid:
description:
- Bridge LAN port 8 to SSID. Source wireless-controller.vap.name.
- led-state:
+ type: str
+ led_state:
description:
- Enable to allow the FortiAPs LEDs to light. Disable to keep the LEDs off. You may want to keep the LEDs off so they are not distracting
in low light areas etc.
+ type: str
choices:
- enable
- disable
location:
description:
- Field for describing the physical location of the WTP, AP or FortiAP.
- login-passwd:
+ type: str
+ login_passwd:
description:
- Set the managed WTP, FortiAP, or AP's administrator password.
- login-passwd-change:
+ type: str
+ login_passwd_change:
description:
- - Change or reset the administrator password of a managed WTP, FortiAP or AP (yes, default, or no, default = no).
+ - Change or reset the administrator password of a managed WTP, FortiAP or AP (yes, default, or no).
+ type: str
choices:
- yes
- default
- no
- mesh-bridge-enable:
+ mesh_bridge_enable:
description:
- Enable/disable mesh Ethernet bridge when WTP is configured as a mesh branch/leaf AP.
+ type: str
choices:
- default
- enable
@@ -259,69 +307,82 @@ options:
name:
description:
- WTP, AP or FortiAP configuration name.
- override-allowaccess:
+ type: str
+ override_allowaccess:
description:
- Enable to override the WTP profile management access configuration.
+ type: str
choices:
- enable
- disable
- override-ip-fragment:
+ override_ip_fragment:
description:
- Enable/disable overriding the WTP profile IP fragment prevention setting.
+ type: str
choices:
- enable
- disable
- override-lan:
+ override_lan:
description:
- Enable to override the WTP profile LAN port setting.
+ type: str
choices:
- enable
- disable
- override-led-state:
+ override_led_state:
description:
- Enable to override the profile LED state setting for this FortiAP. You must enable this option to use the led-state command to turn off
the FortiAP's LEDs.
+ type: str
choices:
- enable
- disable
- override-login-passwd-change:
+ override_login_passwd_change:
description:
- Enable to override the WTP profile login-password (administrator password) setting.
+ type: str
choices:
- enable
- disable
- override-split-tunnel:
+ override_split_tunnel:
description:
- Enable/disable overriding the WTP profile split tunneling setting.
+ type: str
choices:
- enable
- disable
- override-wan-port-mode:
+ override_wan_port_mode:
description:
- Enable/disable overriding the wan-port-mode in the WTP profile.
+ type: str
choices:
- enable
- disable
- radio-1:
+ radio_1:
description:
- Configuration options for radio 1.
+ type: dict
suboptions:
- auto-power-high:
+ auto_power_high:
description:
- Automatic transmission power high limit in decibels (dB) of the measured power referenced to one milliwatt (mW), or dBm (10 - 17
- dBm, default = 17).
- auto-power-level:
+ dBm).
+ type: int
+ auto_power_level:
description:
- - Enable/disable automatic power-level adjustment to prevent co-channel interference (default = enable).
+ - Enable/disable automatic power-level adjustment to prevent co-channel interference .
+ type: str
choices:
- enable
- disable
- auto-power-low:
+ auto_power_low:
description:
- Automatic transmission power low limit in dBm (the actual range of transmit power depends on the AP platform type).
+ type: int
band:
description:
- WiFi band that Radio 1 operates on.
+ type: str
choices:
- 802.11a
- 802.11b
@@ -338,87 +399,105 @@ options:
channel:
description:
- Selected list of wireless radio channels.
+ type: list
suboptions:
chan:
description:
- Channel number.
required: true
- override-analysis:
+ type: str
+ override_analysis:
description:
- Enable to override the WTP profile spectrum analysis configuration.
+ type: str
choices:
- enable
- disable
- override-band:
+ override_band:
description:
- Enable to override the WTP profile band setting.
+ type: str
choices:
- enable
- disable
- override-channel:
+ override_channel:
description:
- Enable to override WTP profile channel settings.
+ type: str
choices:
- enable
- disable
- override-txpower:
+ override_txpower:
description:
- Enable to override the WTP profile power level configuration.
+ type: str
choices:
- enable
- disable
- override-vaps:
+ override_vaps:
description:
- Enable to override WTP profile Virtual Access Point (VAP) settings.
+ type: str
choices:
- enable
- disable
- power-level:
+ power_level:
description:
- - Radio power level as a percentage of the maximum transmit power (0 - 100, default = 100).
- radio-id:
+ - Radio power level as a percentage of the maximum transmit power (0 - 100).
+ type: int
+ radio_id:
description:
- radio-id
- spectrum-analysis:
+ type: int
+ spectrum_analysis:
description:
- Enable/disable spectrum analysis to find interference that would negatively impact wireless performance.
+ type: str
choices:
- enable
- disable
- vap-all:
+ vap_all:
description:
- - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) (default = enable).
+ - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) .
+ type: str
choices:
- enable
- disable
vaps:
description:
- Manually selected list of Virtual Access Points (VAPs).
+ type: list
suboptions:
name:
description:
- Virtual Access Point (VAP) name. Source wireless-controller.vap-group.name wireless-controller.vap.name.
required: true
- radio-2:
+ type: str
+ radio_2:
description:
- Configuration options for radio 2.
+ type: dict
suboptions:
- auto-power-high:
+ auto_power_high:
description:
- Automatic transmission power high limit in decibels (dB) of the measured power referenced to one milliwatt (mW), or dBm (10 - 17
- dBm, default = 17).
- auto-power-level:
+ dBm).
+ type: int
+ auto_power_level:
description:
- - Enable/disable automatic power-level adjustment to prevent co-channel interference (default = enable).
+ - Enable/disable automatic power-level adjustment to prevent co-channel interference .
+ type: str
choices:
- enable
- disable
- auto-power-low:
+ auto_power_low:
description:
- Automatic transmission power low limit in dBm (the actual range of transmit power depends on the AP platform type).
+ type: int
band:
description:
- WiFi band that Radio 1 operates on.
+ type: str
choices:
- 802.11a
- 802.11b
@@ -435,116 +514,139 @@ options:
channel:
description:
- Selected list of wireless radio channels.
+ type: list
suboptions:
chan:
description:
- Channel number.
required: true
- override-analysis:
+ type: str
+ override_analysis:
description:
- Enable to override the WTP profile spectrum analysis configuration.
+ type: str
choices:
- enable
- disable
- override-band:
+ override_band:
description:
- Enable to override the WTP profile band setting.
+ type: str
choices:
- enable
- disable
- override-channel:
+ override_channel:
description:
- Enable to override WTP profile channel settings.
+ type: str
choices:
- enable
- disable
- override-txpower:
+ override_txpower:
description:
- Enable to override the WTP profile power level configuration.
+ type: str
choices:
- enable
- disable
- override-vaps:
+ override_vaps:
description:
- Enable to override WTP profile Virtual Access Point (VAP) settings.
+ type: str
choices:
- enable
- disable
- power-level:
+ power_level:
description:
- - Radio power level as a percentage of the maximum transmit power (0 - 100, default = 100).
- radio-id:
+ - Radio power level as a percentage of the maximum transmit power (0 - 100).
+ type: int
+ radio_id:
description:
- radio-id
- spectrum-analysis:
+ type: int
+ spectrum_analysis:
description:
- Enable/disable spectrum analysis to find interference that would negatively impact wireless performance.
+ type: str
choices:
- enable
- disable
- vap-all:
+ vap_all:
description:
- - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) (default = enable).
+ - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) .
+ type: str
choices:
- enable
- disable
vaps:
description:
- Manually selected list of Virtual Access Points (VAPs).
+ type: list
suboptions:
name:
description:
- Virtual Access Point (VAP) name. Source wireless-controller.vap-group.name wireless-controller.vap.name.
required: true
- split-tunneling-acl:
+ type: str
+ split_tunneling_acl:
description:
- Split tunneling ACL filter list.
+ type: list
suboptions:
- dest-ip:
+ dest_ip:
description:
- Destination IP and mask for the split-tunneling subnet.
+ type: str
id:
description:
- ID.
required: true
- split-tunneling-acl-local-ap-subnet:
+ type: int
+ split_tunneling_acl_local_ap_subnet:
description:
- - Enable/disable automatically adding local subnetwork of FortiAP to split-tunneling ACL (default = disable).
+ - Enable/disable automatically adding local subnetwork of FortiAP to split-tunneling ACL .
+ type: str
choices:
- enable
- disable
- split-tunneling-acl-path:
+ split_tunneling_acl_path:
description:
- Split tunneling ACL path is local/tunnel.
+ type: str
choices:
- tunnel
- local
- tun-mtu-downlink:
+ tun_mtu_downlink:
description:
- Downlink tunnel MTU in octets. Set the value to either 0 (by default), 576, or 1500.
- tun-mtu-uplink:
+ type: int
+ tun_mtu_uplink:
description:
- Uplink tunnel maximum transmission unit (MTU) in octets (eight-bit bytes). Set the value to either 0 (by default), 576, or 1500.
- wan-port-mode:
+ type: int
+ wan_port_mode:
description:
- Enable/disable using the FortiAP WAN port as a LAN port.
+ type: str
choices:
- wan-lan
- wan-only
- wtp-id:
+ wtp_id:
description:
- WTP ID.
- required: true
- wtp-mode:
+ type: str
+ wtp_mode:
description:
- WTP, AP, or FortiAP operating mode; normal (by default) or remote. A tunnel mode SSID can be assigned to an AP in normal mode but not
remote mode, while a local-bridge mode SSID can be assigned to an AP in either normal mode or remote mode.
+ type: str
choices:
- normal
- remote
- wtp-profile:
+ wtp_profile:
description:
- WTP profile name to apply to this WTP, AP or FortiAP. Source wireless-controller.wtp-profile.name.
+ type: str
'''
EXAMPLES = '''
@@ -554,6 +656,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure Wireless Termination Points (WTPs), that is, FortiAPs or APs to be managed by FortiGate.
fortios_wireless_controller_wtp:
@@ -562,103 +665,103 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
+ state: "present"
wireless_controller_wtp:
- state: "present"
admin: "discovered"
allowaccess: "telnet"
- bonjour-profile: "<your_own_value> (source wireless-controller.bonjour-profile.name)"
- coordinate-enable: "enable"
- coordinate-latitude: "<your_own_value>"
- coordinate-longitude: "<your_own_value>"
- coordinate-x: "<your_own_value>"
- coordinate-y: "<your_own_value>"
- image-download: "enable"
+ bonjour_profile: "<your_own_value> (source wireless-controller.bonjour-profile.name)"
+ coordinate_enable: "enable"
+ coordinate_latitude: "<your_own_value>"
+ coordinate_longitude: "<your_own_value>"
+ coordinate_x: "<your_own_value>"
+ coordinate_y: "<your_own_value>"
+ image_download: "enable"
index: "12"
- ip-fragment-preventing: "tcp-mss-adjust"
+ ip_fragment_preventing: "tcp-mss-adjust"
lan:
- port-mode: "offline"
- port-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port1-mode: "offline"
- port1-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port2-mode: "offline"
- port2-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port3-mode: "offline"
- port3-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port4-mode: "offline"
- port4-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port5-mode: "offline"
- port5-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port6-mode: "offline"
- port6-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port7-mode: "offline"
- port7-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port8-mode: "offline"
- port8-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- led-state: "enable"
+ port_mode: "offline"
+ port_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port1_mode: "offline"
+ port1_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port2_mode: "offline"
+ port2_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port3_mode: "offline"
+ port3_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port4_mode: "offline"
+ port4_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port5_mode: "offline"
+ port5_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port6_mode: "offline"
+ port6_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port7_mode: "offline"
+ port7_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port8_mode: "offline"
+ port8_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ led_state: "enable"
location: "<your_own_value>"
- login-passwd: "<your_own_value>"
- login-passwd-change: "yes"
- mesh-bridge-enable: "default"
+ login_passwd: "<your_own_value>"
+ login_passwd_change: "yes"
+ mesh_bridge_enable: "default"
name: "default_name_38"
- override-allowaccess: "enable"
- override-ip-fragment: "enable"
- override-lan: "enable"
- override-led-state: "enable"
- override-login-passwd-change: "enable"
- override-split-tunnel: "enable"
- override-wan-port-mode: "enable"
- radio-1:
- auto-power-high: "47"
- auto-power-level: "enable"
- auto-power-low: "49"
+ override_allowaccess: "enable"
+ override_ip_fragment: "enable"
+ override_lan: "enable"
+ override_led_state: "enable"
+ override_login_passwd_change: "enable"
+ override_split_tunnel: "enable"
+ override_wan_port_mode: "enable"
+ radio_1:
+ auto_power_high: "47"
+ auto_power_level: "enable"
+ auto_power_low: "49"
band: "802.11a"
channel:
-
chan: "<your_own_value>"
- override-analysis: "enable"
- override-band: "enable"
- override-channel: "enable"
- override-txpower: "enable"
- override-vaps: "enable"
- power-level: "58"
- radio-id: "59"
- spectrum-analysis: "enable"
- vap-all: "enable"
+ override_analysis: "enable"
+ override_band: "enable"
+ override_channel: "enable"
+ override_txpower: "enable"
+ override_vaps: "enable"
+ power_level: "58"
+ radio_id: "59"
+ spectrum_analysis: "enable"
+ vap_all: "enable"
vaps:
-
name: "default_name_63 (source wireless-controller.vap-group.name wireless-controller.vap.name)"
- radio-2:
- auto-power-high: "65"
- auto-power-level: "enable"
- auto-power-low: "67"
+ radio_2:
+ auto_power_high: "65"
+ auto_power_level: "enable"
+ auto_power_low: "67"
band: "802.11a"
channel:
-
chan: "<your_own_value>"
- override-analysis: "enable"
- override-band: "enable"
- override-channel: "enable"
- override-txpower: "enable"
- override-vaps: "enable"
- power-level: "76"
- radio-id: "77"
- spectrum-analysis: "enable"
- vap-all: "enable"
+ override_analysis: "enable"
+ override_band: "enable"
+ override_channel: "enable"
+ override_txpower: "enable"
+ override_vaps: "enable"
+ power_level: "76"
+ radio_id: "77"
+ spectrum_analysis: "enable"
+ vap_all: "enable"
vaps:
-
name: "default_name_81 (source wireless-controller.vap-group.name wireless-controller.vap.name)"
- split-tunneling-acl:
+ split_tunneling_acl:
-
- dest-ip: "<your_own_value>"
+ dest_ip: "<your_own_value>"
id: "84"
- split-tunneling-acl-local-ap-subnet: "enable"
- split-tunneling-acl-path: "tunnel"
- tun-mtu-downlink: "87"
- tun-mtu-uplink: "88"
- wan-port-mode: "wan-lan"
- wtp-id: "<your_own_value>"
- wtp-mode: "normal"
- wtp-profile: "<your_own_value> (source wireless-controller.wtp-profile.name)"
+ split_tunneling_acl_local_ap_subnet: "enable"
+ split_tunneling_acl_path: "tunnel"
+ tun_mtu_downlink: "87"
+ tun_mtu_uplink: "88"
+ wan_port_mode: "wan-lan"
+ wtp_id: "<your_own_value>"
+ wtp_mode: "normal"
+ wtp_profile: "<your_own_value> (source wireless-controller.wtp-profile.name)"
'''
RETURN = '''
@@ -721,12 +824,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -734,22 +841,22 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_wtp_data(json):
- option_list = ['admin', 'allowaccess', 'bonjour-profile',
- 'coordinate-enable', 'coordinate-latitude', 'coordinate-longitude',
- 'coordinate-x', 'coordinate-y', 'image-download',
- 'index', 'ip-fragment-preventing', 'lan',
- 'led-state', 'location', 'login-passwd',
- 'login-passwd-change', 'mesh-bridge-enable', 'name',
- 'override-allowaccess', 'override-ip-fragment', 'override-lan',
- 'override-led-state', 'override-login-passwd-change', 'override-split-tunnel',
- 'override-wan-port-mode', 'radio-1', 'radio-2',
- 'split-tunneling-acl', 'split-tunneling-acl-local-ap-subnet', 'split-tunneling-acl-path',
- 'tun-mtu-downlink', 'tun-mtu-uplink', 'wan-port-mode',
- 'wtp-id', 'wtp-mode', 'wtp-profile']
+ option_list = ['admin', 'allowaccess', 'bonjour_profile',
+ 'coordinate_enable', 'coordinate_latitude', 'coordinate_longitude',
+ 'coordinate_x', 'coordinate_y', 'image_download',
+ 'index', 'ip_fragment_preventing', 'lan',
+ 'led_state', 'location', 'login_passwd',
+ 'login_passwd_change', 'mesh_bridge_enable', 'name',
+ 'override_allowaccess', 'override_ip_fragment', 'override_lan',
+ 'override_led_state', 'override_login_passwd_change', 'override_split_tunnel',
+ 'override_wan_port_mode', 'radio_1', 'radio_2',
+ 'split_tunneling_acl', 'split_tunneling_acl_local_ap_subnet', 'split_tunneling_acl_path',
+ 'tun_mtu_downlink', 'tun_mtu_uplink', 'wan_port_mode',
+ 'wtp_id', 'wtp_mode', 'wtp_profile']
dictionary = {}
for attribute in option_list:
@@ -759,146 +866,151 @@ def filter_wireless_controller_wtp_data(json):
return dictionary
-def flatten_multilists_attributes(data):
- multilist_attrs = []
-
- for attr in multilist_attrs:
- try:
- path = "data['" + "']['".join(elem for elem in attr) + "']"
- current_val = eval(path)
- flattened_val = ' '.join(elem for elem in current_val)
- exec(path + '= flattened_val')
- except BaseException:
- pass
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
return data
def wireless_controller_wtp(data, fos):
vdom = data['vdom']
+ state = data['state']
wireless_controller_wtp_data = data['wireless_controller_wtp']
- flattened_data = flatten_multilists_attributes(wireless_controller_wtp_data)
- filtered_data = filter_wireless_controller_wtp_data(flattened_data)
- if wireless_controller_wtp_data['state'] == "present":
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_wtp_data(wireless_controller_wtp_data))
+
+ if state == "present":
return fos.set('wireless-controller',
'wtp',
data=filtered_data,
vdom=vdom)
- elif wireless_controller_wtp_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('wireless-controller',
'wtp',
mkey=filtered_data['wtp-id'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_wtp']:
resp = wireless_controller_wtp(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"wireless_controller_wtp": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"admin": {"required": False, "type": "str",
"choices": ["discovered", "disable", "enable"]},
"allowaccess": {"required": False, "type": "str",
"choices": ["telnet", "http", "https",
"ssh"]},
- "bonjour-profile": {"required": False, "type": "str"},
- "coordinate-enable": {"required": False, "type": "str",
+ "bonjour_profile": {"required": False, "type": "str"},
+ "coordinate_enable": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "coordinate-latitude": {"required": False, "type": "str"},
- "coordinate-longitude": {"required": False, "type": "str"},
- "coordinate-x": {"required": False, "type": "str"},
- "coordinate-y": {"required": False, "type": "str"},
- "image-download": {"required": False, "type": "str",
+ "coordinate_latitude": {"required": False, "type": "str"},
+ "coordinate_longitude": {"required": False, "type": "str"},
+ "coordinate_x": {"required": False, "type": "str"},
+ "coordinate_y": {"required": False, "type": "str"},
+ "image_download": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"index": {"required": False, "type": "int"},
- "ip-fragment-preventing": {"required": False, "type": "str",
+ "ip_fragment_preventing": {"required": False, "type": "str",
"choices": ["tcp-mss-adjust", "icmp-unreachable"]},
"lan": {"required": False, "type": "dict",
"options": {
- "port-mode": {"required": False, "type": "str",
+ "port_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port-ssid": {"required": False, "type": "str"},
- "port1-mode": {"required": False, "type": "str",
+ "port_ssid": {"required": False, "type": "str"},
+ "port1_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port1-ssid": {"required": False, "type": "str"},
- "port2-mode": {"required": False, "type": "str",
+ "port1_ssid": {"required": False, "type": "str"},
+ "port2_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port2-ssid": {"required": False, "type": "str"},
- "port3-mode": {"required": False, "type": "str",
+ "port2_ssid": {"required": False, "type": "str"},
+ "port3_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port3-ssid": {"required": False, "type": "str"},
- "port4-mode": {"required": False, "type": "str",
+ "port3_ssid": {"required": False, "type": "str"},
+ "port4_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port4-ssid": {"required": False, "type": "str"},
- "port5-mode": {"required": False, "type": "str",
+ "port4_ssid": {"required": False, "type": "str"},
+ "port5_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port5-ssid": {"required": False, "type": "str"},
- "port6-mode": {"required": False, "type": "str",
+ "port5_ssid": {"required": False, "type": "str"},
+ "port6_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port6-ssid": {"required": False, "type": "str"},
- "port7-mode": {"required": False, "type": "str",
+ "port6_ssid": {"required": False, "type": "str"},
+ "port7_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port7-ssid": {"required": False, "type": "str"},
- "port8-mode": {"required": False, "type": "str",
+ "port7_ssid": {"required": False, "type": "str"},
+ "port8_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port8-ssid": {"required": False, "type": "str"}
+ "port8_ssid": {"required": False, "type": "str"}
}},
- "led-state": {"required": False, "type": "str",
+ "led_state": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"location": {"required": False, "type": "str"},
- "login-passwd": {"required": False, "type": "str"},
- "login-passwd-change": {"required": False, "type": "str",
+ "login_passwd": {"required": False, "type": "str"},
+ "login_passwd_change": {"required": False, "type": "str",
"choices": ["yes", "default", "no"]},
- "mesh-bridge-enable": {"required": False, "type": "str",
+ "mesh_bridge_enable": {"required": False, "type": "str",
"choices": ["default", "enable", "disable"]},
"name": {"required": False, "type": "str"},
- "override-allowaccess": {"required": False, "type": "str",
+ "override_allowaccess": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-ip-fragment": {"required": False, "type": "str",
+ "override_ip_fragment": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-lan": {"required": False, "type": "str",
+ "override_lan": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-led-state": {"required": False, "type": "str",
+ "override_led_state": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-login-passwd-change": {"required": False, "type": "str",
+ "override_login_passwd_change": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-split-tunnel": {"required": False, "type": "str",
+ "override_split_tunnel": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-wan-port-mode": {"required": False, "type": "str",
+ "override_wan_port_mode": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "radio-1": {"required": False, "type": "dict",
+ "radio_1": {"required": False, "type": "dict",
"options": {
- "auto-power-high": {"required": False, "type": "int"},
- "auto-power-level": {"required": False, "type": "str",
+ "auto_power_high": {"required": False, "type": "int"},
+ "auto_power_level": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auto-power-low": {"required": False, "type": "int"},
+ "auto_power_low": {"required": False, "type": "int"},
"band": {"required": False, "type": "str",
"choices": ["802.11a", "802.11b", "802.11g",
"802.11n", "802.11n-5G", "802.11n,g-only",
@@ -908,33 +1020,33 @@ def main():
"options": {
"chan": {"required": True, "type": "str"}
}},
- "override-analysis": {"required": False, "type": "str",
+ "override_analysis": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-band": {"required": False, "type": "str",
+ "override_band": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-channel": {"required": False, "type": "str",
+ "override_channel": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-txpower": {"required": False, "type": "str",
+ "override_txpower": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-vaps": {"required": False, "type": "str",
+ "override_vaps": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "power-level": {"required": False, "type": "int"},
- "radio-id": {"required": False, "type": "int"},
- "spectrum-analysis": {"required": False, "type": "str",
+ "power_level": {"required": False, "type": "int"},
+ "radio_id": {"required": False, "type": "int"},
+ "spectrum_analysis": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "vap-all": {"required": False, "type": "str",
+ "vap_all": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"vaps": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}}
}},
- "radio-2": {"required": False, "type": "dict",
+ "radio_2": {"required": False, "type": "dict",
"options": {
- "auto-power-high": {"required": False, "type": "int"},
- "auto-power-level": {"required": False, "type": "str",
+ "auto_power_high": {"required": False, "type": "int"},
+ "auto_power_level": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auto-power-low": {"required": False, "type": "int"},
+ "auto_power_low": {"required": False, "type": "int"},
"band": {"required": False, "type": "str",
"choices": ["802.11a", "802.11b", "802.11g",
"802.11n", "802.11n-5G", "802.11n,g-only",
@@ -944,44 +1056,44 @@ def main():
"options": {
"chan": {"required": True, "type": "str"}
}},
- "override-analysis": {"required": False, "type": "str",
+ "override_analysis": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-band": {"required": False, "type": "str",
+ "override_band": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-channel": {"required": False, "type": "str",
+ "override_channel": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-txpower": {"required": False, "type": "str",
+ "override_txpower": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "override-vaps": {"required": False, "type": "str",
+ "override_vaps": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "power-level": {"required": False, "type": "int"},
- "radio-id": {"required": False, "type": "int"},
- "spectrum-analysis": {"required": False, "type": "str",
+ "power_level": {"required": False, "type": "int"},
+ "radio_id": {"required": False, "type": "int"},
+ "spectrum_analysis": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "vap-all": {"required": False, "type": "str",
+ "vap_all": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"vaps": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}}
}},
- "split-tunneling-acl": {"required": False, "type": "list",
+ "split_tunneling_acl": {"required": False, "type": "list",
"options": {
- "dest-ip": {"required": False, "type": "str"},
+ "dest_ip": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"}
}},
- "split-tunneling-acl-local-ap-subnet": {"required": False, "type": "str",
+ "split_tunneling_acl_local_ap_subnet": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "split-tunneling-acl-path": {"required": False, "type": "str",
+ "split_tunneling_acl_path": {"required": False, "type": "str",
"choices": ["tunnel", "local"]},
- "tun-mtu-downlink": {"required": False, "type": "int"},
- "tun-mtu-uplink": {"required": False, "type": "int"},
- "wan-port-mode": {"required": False, "type": "str",
+ "tun_mtu_downlink": {"required": False, "type": "int"},
+ "tun_mtu_uplink": {"required": False, "type": "int"},
+ "wan_port_mode": {"required": False, "type": "str",
"choices": ["wan-lan", "wan-only"]},
- "wtp-id": {"required": True, "type": "str"},
- "wtp-mode": {"required": False, "type": "str",
+ "wtp_id": {"required": False, "type": "str"},
+ "wtp_mode": {"required": False, "type": "str",
"choices": ["normal", "remote"]},
- "wtp-profile": {"required": False, "type": "str"}
+ "wtp_profile": {"required": False, "type": "str"}
}
}
@@ -989,14 +1101,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py b/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py
index d84f0d38c4..d5a9ac1e17 100644
--- a/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py
+++ b/lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py
@@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_wireless_controller_wtp_profile
short_description: Configure WTP profiles or FortiAP profiles that define radio settings for manageable FortiAP platforms in Fortinet's FortiOS and FortiGate.
description:
- - This module is able to configure a FortiGate or FortiOS by allowing the
+ - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
user to set and modify wireless_controller feature and wtp_profile category.
Examples include all parameters and values need to be adjusted to datasources before usage.
- Tested with FOS v6.0.2
+ Tested with FOS v6.0.5
version_added: "2.8"
author:
- Miguel Angel Munoz (@mamunozgonzalez)
@@ -41,51 +41,66 @@ requirements:
- fortiosapi>=0.9.8
options:
host:
- description:
- - FortiOS or FortiGate ip address.
- required: true
+ description:
+ - FortiOS or FortiGate IP address.
+ type: str
+ required: false
username:
description:
- FortiOS or FortiGate username.
- required: true
+ type: str
+ required: false
password:
description:
- FortiOS or FortiGate password.
+ type: str
default: ""
vdom:
description:
- Virtual domain, among those defined previously. A vdom is a
virtual instance of the FortiGate that can be configured and
used as a different unit.
+ type: str
default: root
https:
description:
- - Indicates if the requests towards FortiGate must use HTTPS
- protocol
+ - Indicates if the requests towards FortiGate must use HTTPS protocol.
+ type: bool
+ default: true
+ ssl_verify:
+ description:
+ - Ensures FortiGate certificate must be verified by a proper CA.
type: bool
default: true
+ version_added: 2.9
+ state:
+ description:
+ - Indicates whether to create or remove the object.
+ type: str
+ required: true
+ choices:
+ - present
+ - absent
+ version_added: 2.9
wireless_controller_wtp_profile:
description:
- Configure WTP profiles or FortiAP profiles that define radio settings for manageable FortiAP platforms.
default: null
+ type: dict
suboptions:
- state:
- description:
- - Indicates whether to create or remove the object
- choices:
- - present
- - absent
allowaccess:
description:
- Control management access to the managed WTP, FortiAP, or AP. Separate entries with a space.
+ type: str
choices:
- telnet
- http
- https
- ssh
- ap-country:
+ ap_country:
description:
- - Country in which this WTP, FortiAP or AP will operate (default = US).
+ - Country in which this WTP, FortiAP or AP will operate .
+ type: str
choices:
- NA
- AL
@@ -215,15 +230,18 @@ options:
- ZW
- JP
- CA
- ble-profile:
+ ble_profile:
description:
- Bluetooth Low Energy profile name. Source wireless-controller.ble-profile.name.
+ type: str
comment:
description:
- Comment.
- control-message-offload:
+ type: str
+ control_message_offload:
description:
- Enable/disable CAPWAP control message data channel offload.
+ type: str
choices:
- ebp-frame
- aeroscout-tag
@@ -232,306 +250,367 @@ options:
- sta-cap-list
- stats
- aeroscout-mu
- deny-mac-list:
+ deny_mac_list:
description:
- List of MAC addresses that are denied access to this WTP, FortiAP, or AP.
+ type: list
suboptions:
id:
description:
- ID.
required: true
+ type: int
mac:
description:
- A WiFi device with this MAC address is denied access to this WTP, FortiAP or AP.
- dtls-in-kernel:
+ type: str
+ dtls_in_kernel:
description:
- Enable/disable data channel DTLS in kernel.
+ type: str
choices:
- enable
- disable
- dtls-policy:
+ dtls_policy:
description:
- - WTP data channel DTLS policy (default = clear-text).
+ - WTP data channel DTLS policy .
+ type: str
choices:
- clear-text
- dtls-enabled
- ipsec-vpn
- energy-efficient-ethernet:
+ energy_efficient_ethernet:
description:
- Enable/disable use of energy efficient Ethernet on WTP.
+ type: str
choices:
- enable
- disable
- ext-info-enable:
+ ext_info_enable:
description:
- Enable/disable station/VAP/radio extension information.
+ type: str
choices:
- enable
- disable
- handoff-roaming:
+ handoff_roaming:
description:
- - Enable/disable client load balancing during roaming to avoid roaming delay (default = disable).
+ - Enable/disable client load balancing during roaming to avoid roaming delay .
+ type: str
choices:
- enable
- disable
- handoff-rssi:
+ handoff_rssi:
description:
- - Minimum received signal strength indicator (RSSI) value for handoff (20 - 30, default = 25).
- handoff-sta-thresh:
+ - Minimum received signal strength indicator (RSSI) value for handoff (20 - 30).
+ type: int
+ handoff_sta_thresh:
description:
- - Threshold value for AP handoff (5 - 35, default = 30).
- ip-fragment-preventing:
+ - Threshold value for AP handoff.
+ type: int
+ ip_fragment_preventing:
description:
- - Select how to prevent IP fragmentation for CAPWAP tunneled control and data packets (default = tcp-mss-adjust).
+ - Select how to prevent IP fragmentation for CAPWAP tunneled control and data packets .
+ type: str
choices:
- tcp-mss-adjust
- icmp-unreachable
lan:
description:
- WTP LAN port mapping.
+ type: dict
suboptions:
- port-mode:
+ port_mode:
description:
- LAN port mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port-ssid:
+ port_ssid:
description:
- Bridge LAN port to SSID. Source wireless-controller.vap.name.
- port1-mode:
+ type: str
+ port1_mode:
description:
- LAN port 1 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port1-ssid:
+ port1_ssid:
description:
- Bridge LAN port 1 to SSID. Source wireless-controller.vap.name.
- port2-mode:
+ type: str
+ port2_mode:
description:
- LAN port 2 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port2-ssid:
+ port2_ssid:
description:
- Bridge LAN port 2 to SSID. Source wireless-controller.vap.name.
- port3-mode:
+ type: str
+ port3_mode:
description:
- LAN port 3 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port3-ssid:
+ port3_ssid:
description:
- Bridge LAN port 3 to SSID. Source wireless-controller.vap.name.
- port4-mode:
+ type: str
+ port4_mode:
description:
- LAN port 4 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port4-ssid:
+ port4_ssid:
description:
- Bridge LAN port 4 to SSID. Source wireless-controller.vap.name.
- port5-mode:
+ type: str
+ port5_mode:
description:
- LAN port 5 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port5-ssid:
+ port5_ssid:
description:
- Bridge LAN port 5 to SSID. Source wireless-controller.vap.name.
- port6-mode:
+ type: str
+ port6_mode:
description:
- LAN port 6 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port6-ssid:
+ port6_ssid:
description:
- Bridge LAN port 6 to SSID. Source wireless-controller.vap.name.
- port7-mode:
+ type: str
+ port7_mode:
description:
- LAN port 7 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port7-ssid:
+ port7_ssid:
description:
- Bridge LAN port 7 to SSID. Source wireless-controller.vap.name.
- port8-mode:
+ type: str
+ port8_mode:
description:
- LAN port 8 mode.
+ type: str
choices:
- offline
- nat-to-wan
- bridge-to-wan
- bridge-to-ssid
- port8-ssid:
+ port8_ssid:
description:
- Bridge LAN port 8 to SSID. Source wireless-controller.vap.name.
+ type: str
lbs:
description:
- Set various location based service (LBS) options.
+ type: dict
suboptions:
aeroscout:
description:
- - Enable/disable AeroScout Real Time Location Service (RTLS) support.
+ - Enable/disable AeroScout Real Time Location Service (RTLS) support .
+ type: str
choices:
- enable
- disable
- aeroscout-ap-mac:
+ aeroscout_ap_mac:
description:
- - Use BSSID or board MAC address as AP MAC address in the Aeroscout AP message.
+ - Use BSSID or board MAC address as AP MAC address in AeroScout AP messages .
+ type: str
choices:
- bssid
- board-mac
- aeroscout-mmu-report:
+ aeroscout_mmu_report:
description:
- - Enable/disable MU compounded report.
+ - Enable/disable compounded AeroScout tag and MU report .
+ type: str
choices:
- enable
- disable
- aeroscout-mu:
+ aeroscout_mu:
description:
- - Enable/disable AeroScout support.
+ - Enable/disable AeroScout Mobile Unit (MU) support .
+ type: str
choices:
- enable
- disable
- aeroscout-mu-factor:
+ aeroscout_mu_factor:
description:
- - AeroScout Mobile Unit (MU) mode dilution factor (default = 20).
- aeroscout-mu-timeout:
+ - AeroScout MU mode dilution factor .
+ type: int
+ aeroscout_mu_timeout:
description:
- - AeroScout MU mode timeout (0 - 65535 sec, default = 5).
- aeroscout-server-ip:
+ - AeroScout MU mode timeout (0 - 65535 sec).
+ type: int
+ aeroscout_server_ip:
description:
- IP address of AeroScout server.
- aeroscout-server-port:
+ type: str
+ aeroscout_server_port:
description:
- AeroScout server UDP listening port.
- ekahau-blink-mode:
+ type: int
+ ekahau_blink_mode:
description:
- - Enable/disable Ekahua blink mode (also called AiRISTA Flow Blink Mode) to find the location of devices connected to a wireless
- LAN (default = disable).
+ - Enable/disable Ekahau blink mode (now known as AiRISTA Flow) to track and locate WiFi tags .
+ type: str
choices:
- enable
- disable
- ekahau-tag:
+ ekahau_tag:
description:
- WiFi frame MAC address or WiFi Tag.
- erc-server-ip:
+ type: str
+ erc_server_ip:
description:
- - IP address of Ekahua RTLS Controller (ERC).
- erc-server-port:
+ - IP address of Ekahau RTLS Controller (ERC).
+ type: str
+ erc_server_port:
description:
- - Ekahua RTLS Controller (ERC) UDP listening port.
+ - Ekahau RTLS Controller (ERC) UDP listening port.
+ type: int
fortipresence:
description:
- Enable/disable FortiPresence to monitor the location and activity of WiFi clients even if they don't connect to this WiFi
- network (default = disable).
+ network .
+ type: str
choices:
- foreign
- both
- disable
- fortipresence-frequency:
+ fortipresence_frequency:
description:
- - FortiPresence report transmit frequency (5 - 65535 sec, default = 30).
- fortipresence-port:
+ - FortiPresence report transmit frequency (5 - 65535 sec).
+ type: int
+ fortipresence_port:
description:
- - FortiPresence server UDP listening port (default = 3000).
- fortipresence-project:
+ - FortiPresence server UDP listening port .
+ type: int
+ fortipresence_project:
description:
- - FortiPresence project name (max. 16 characters, default = fortipresence).
- fortipresence-rogue:
+ - FortiPresence project name (max. 16 characters).
+ type: str
+ fortipresence_rogue:
description:
- Enable/disable FortiPresence finding and reporting rogue APs.
+ type: str
choices:
- enable
- disable
- fortipresence-secret:
+ fortipresence_secret:
description:
- FortiPresence secret password (max. 16 characters).
- fortipresence-server:
+ type: str
+ fortipresence_server:
description:
- FortiPresence server IP address.
- fortipresence-unassoc:
+ type: str
+ fortipresence_unassoc:
description:
- Enable/disable FortiPresence finding and reporting unassociated stations.
+ type: str
choices:
- enable
- disable
- station-locate:
+ station_locate:
description:
- - Enable/disable client station locating services for all clients, whether associated or not (default = disable).
+ - Enable/disable client station locating services for all clients, whether associated or not .
+ type: str
choices:
- enable
- disable
- led-schedules:
+ led_schedules:
description:
- Recurring firewall schedules for illuminating LEDs on the FortiAP. If led-state is enabled, LEDs will be visible when at least one of
the schedules is valid. Separate multiple schedule names with a space.
+ type: list
suboptions:
name:
description:
- LED schedule name. Source firewall.schedule.group.name firewall.schedule.recurring.name.
required: true
- led-state:
+ type: str
+ led_state:
description:
- - Enable/disable use of LEDs on WTP (default = disable).
+ - Enable/disable use of LEDs on WTP .
+ type: str
choices:
- enable
- disable
lldp:
description:
- - Enable/disable Link Layer Discovery Protocol (LLDP) for the WTP, FortiAP, or AP (default = disable).
+ - Enable/disable Link Layer Discovery Protocol (LLDP) for the WTP, FortiAP, or AP .
+ type: str
choices:
- enable
- disable
- login-passwd:
+ login_passwd:
description:
- Set the managed WTP, FortiAP, or AP's administrator password.
- login-passwd-change:
+ type: str
+ login_passwd_change:
description:
- - Change or reset the administrator password of a managed WTP, FortiAP or AP (yes, default, or no, default = no).
+ - Change or reset the administrator password of a managed WTP, FortiAP or AP (yes, default, or no).
+ type: str
choices:
- yes
- default
- no
- max-clients:
+ max_clients:
description:
- - Maximum number of stations (STAs) supported by the WTP (default = 0, meaning no client limitation).
+ - Maximum number of stations (STAs) supported by the WTP .
+ type: int
name:
description:
- WTP (or FortiAP or AP) profile name.
required: true
+ type: str
platform:
description:
- WTP, FortiAP, or AP platform.
+ type: dict
suboptions:
type:
description:
- WTP, FortiAP or AP platform type. There are built-in WTP profiles for all supported FortiAP models. You can select a built-in
profile and customize it or create a new profile.
+ type: str
choices:
- AP-11N
- 220B
@@ -585,84 +664,100 @@ options:
- U24JEV
- U321EV
- U323EV
- poe-mode:
+ poe_mode:
description:
- Set the WTP, FortiAP, or AP's PoE mode.
+ type: str
choices:
- auto
- 8023af
- 8023at
- power-adapter
- radio-1:
+ radio_1:
description:
- Configuration options for radio 1.
+ type: dict
suboptions:
amsdu:
description:
- - Enable/disable 802.11n AMSDU support. AMSDU can improve performance if supported by your WiFi clients (default = enable).
+ - Enable/disable 802.11n AMSDU support. AMSDU can improve performance if supported by your WiFi clients .
+ type: str
choices:
- enable
- disable
- ap-handoff:
+ ap_handoff:
description:
- - Enable/disable AP handoff of clients to other APs (default = disable).
+ - Enable/disable AP handoff of clients to other APs .
+ type: str
choices:
- enable
- disable
- ap-sniffer-addr:
+ ap_sniffer_addr:
description:
- MAC address to monitor.
- ap-sniffer-bufsize:
+ type: str
+ ap_sniffer_bufsize:
description:
- - Sniffer buffer size (1 - 32 MB, default = 16).
- ap-sniffer-chan:
+ - Sniffer buffer size (1 - 32 MB).
+ type: int
+ ap_sniffer_chan:
description:
- - Channel on which to operate the sniffer (default = 6).
- ap-sniffer-ctl:
+ - Channel on which to operate the sniffer .
+ type: int
+ ap_sniffer_ctl:
description:
- - Enable/disable sniffer on WiFi control frame (default = enable).
+ - Enable/disable sniffer on WiFi control frame .
+ type: str
choices:
- enable
- disable
- ap-sniffer-data:
+ ap_sniffer_data:
description:
- - Enable/disable sniffer on WiFi data frame (default = enable).
+ - Enable/disable sniffer on WiFi data frame .
+ type: str
choices:
- enable
- disable
- ap-sniffer-mgmt-beacon:
+ ap_sniffer_mgmt_beacon:
description:
- - Enable/disable sniffer on WiFi management Beacon frames (default = enable).
+ - Enable/disable sniffer on WiFi management Beacon frames .
+ type: str
choices:
- enable
- disable
- ap-sniffer-mgmt-other:
+ ap_sniffer_mgmt_other:
description:
- - Enable/disable sniffer on WiFi management other frames (default = enable).
+ - Enable/disable sniffer on WiFi management other frames .
+ type: str
choices:
- enable
- disable
- ap-sniffer-mgmt-probe:
+ ap_sniffer_mgmt_probe:
description:
- - Enable/disable sniffer on WiFi management probe frames (default = enable).
+ - Enable/disable sniffer on WiFi management probe frames .
+ type: str
choices:
- enable
- disable
- auto-power-high:
+ auto_power_high:
description:
- Automatic transmit power high limit in dBm (the actual range of transmit power depends on the AP platform type).
- auto-power-level:
+ type: int
+ auto_power_level:
description:
- - Enable/disable automatic power-level adjustment to prevent co-channel interference (default = disable).
+ - Enable/disable automatic power-level adjustment to prevent co-channel interference .
+ type: str
choices:
- enable
- disable
- auto-power-low:
+ auto_power_low:
description:
- Automatic transmission power low limit in dBm (the actual range of transmit power depends on the AP platform type).
+ type: int
band:
description:
- WiFi band that Radio 1 operates on.
+ type: str
choices:
- 802.11a
- 802.11b
@@ -676,226 +771,268 @@ options:
- 802.11n-5G-only
- 802.11ac,n-only
- 802.11ac-only
- bandwidth-admission-control:
+ bandwidth_admission_control:
description:
- Enable/disable WiFi multimedia (WMM) bandwidth admission control to optimize WiFi bandwidth use. A request to join the wireless
network is only allowed if the access point has enough bandwidth to support it.
+ type: str
choices:
- enable
- disable
- bandwidth-capacity:
+ bandwidth_capacity:
description:
- - Maximum bandwidth capacity allowed (1 - 600000 Kbps, default = 2000).
- beacon-interval:
+ - Maximum bandwidth capacity allowed (1 - 600000 Kbps).
+ type: int
+ beacon_interval:
description:
- - Beacon interval. The time between beacon frames in msec (the actual range of beacon interval depends on the AP platform type,
- default = 100).
- call-admission-control:
+ - Beacon interval. The time between beacon frames in msec (the actual range of beacon interval depends on the AP platform type).
+ type: int
+ call_admission_control:
description:
- Enable/disable WiFi multimedia (WMM) call admission control to optimize WiFi bandwidth use for VoIP calls. New VoIP calls are
only accepted if there is enough bandwidth available to support them.
+ type: str
choices:
- enable
- disable
- call-capacity:
+ call_capacity:
description:
- - Maximum number of Voice over WLAN (VoWLAN) phones supported by the radio (0 - 60, default = 10).
+ - Maximum number of Voice over WLAN (VoWLAN) phones supported by the radio (0 - 60).
+ type: int
channel:
description:
- Selected list of wireless radio channels.
+ type: list
suboptions:
chan:
description:
- Channel number.
required: true
- channel-bonding:
+ type: str
+ channel_bonding:
description:
- "Channel bandwidth: 80, 40, or 20MHz. Channels may use both 20 and 40 by enabling coexistence."
+ type: str
choices:
- 80MHz
- 40MHz
- 20MHz
- channel-utilization:
+ channel_utilization:
description:
- Enable/disable measuring channel utilization.
+ type: str
choices:
- enable
- disable
coexistence:
description:
- - Enable/disable allowing both HT20 and HT40 on the same radio (default = enable).
+ - Enable/disable allowing both HT20 and HT40 on the same radio .
+ type: str
choices:
- enable
- disable
darrp:
description:
- Enable/disable Distributed Automatic Radio Resource Provisioning (DARRP) to make sure the radio is always using the most optimal
- channel (default = disable).
+ channel .
+ type: str
choices:
- enable
- disable
dtim:
description:
- - DTIM interval. The frequency to transmit Delivery Traffic Indication Message (or Map) (DTIM) messages (1 - 255, default = 1).
- Set higher to save client battery life.
- frag-threshold:
+ - DTIM interval. The frequency to transmit Delivery Traffic Indication Message (or Map) (DTIM) messages (1 - 255). Set higher to
+ save client battery life.
+ type: int
+ frag_threshold:
description:
- - Maximum packet size that can be sent without fragmentation (800 - 2346 bytes, default = 2346).
- frequency-handoff:
+ - Maximum packet size that can be sent without fragmentation (800 - 2346 bytes).
+ type: int
+ frequency_handoff:
description:
- - Enable/disable frequency handoff of clients to other channels (default = disable).
+ - Enable/disable frequency handoff of clients to other channels .
+ type: str
choices:
- enable
- disable
- max-clients:
+ max_clients:
description:
- Maximum number of stations (STAs) or WiFi clients supported by the radio. Range depends on the hardware.
- max-distance:
+ type: int
+ max_distance:
description:
- - Maximum expected distance between the AP and clients (0 - 54000 m, default = 0).
+ - Maximum expected distance between the AP and clients (0 - 54000 m).
+ type: int
mode:
description:
- Mode of radio 1. Radio 1 can be disabled, configured as an access point, a rogue AP monitor, or a sniffer.
+ type: str
choices:
- disabled
- ap
- monitor
- sniffer
- power-level:
+ power_level:
description:
- - Radio power level as a percentage of the maximum transmit power (0 - 100, default = 100).
- powersave-optimize:
+ - Radio power level as a percentage of the maximum transmit power (0 - 100).
+ type: int
+ powersave_optimize:
description:
- Enable client power-saving features such as TIM, AC VO, and OBSS etc.
+ type: str
choices:
- tim
- ac-vo
- no-obss-scan
- no-11b-rate
- client-rate-follow
- protection-mode:
+ protection_mode:
description:
- Enable/disable 802.11g protection modes to support backwards compatibility with older clients (rtscts, ctsonly, disable).
+ type: str
choices:
- rtscts
- ctsonly
- disable
- radio-id:
+ radio_id:
description:
- radio-id
- rts-threshold:
+ type: int
+ rts_threshold:
description:
- - Maximum packet size for RTS transmissions, specifying the maximum size of a data packet before RTS/CTS (256 - 2346 bytes,
- default = 2346).
- short-guard-interval:
+ - Maximum packet size for RTS transmissions, specifying the maximum size of a data packet before RTS/CTS (256 - 2346 bytes).
+ type: int
+ short_guard_interval:
description:
- Use either the short guard interval (Short GI) of 400 ns or the long guard interval (Long GI) of 800 ns.
+ type: str
choices:
- enable
- disable
- spectrum-analysis:
+ spectrum_analysis:
description:
- Enable/disable spectrum analysis to find interference that would negatively impact wireless performance.
+ type: str
choices:
- enable
- disable
- transmit-optimize:
+ transmit_optimize:
description:
- Packet transmission optimization options including power saving, aggregation limiting, retry limiting, etc. All are enabled by
default.
+ type: str
choices:
- disable
- power-save
- aggr-limit
- retry-limit
- send-bar
- vap-all:
+ vap_all:
description:
- - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) (default = enable).
+ - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) .
+ type: str
choices:
- enable
- disable
vaps:
description:
- Manually selected list of Virtual Access Points (VAPs).
+ type: list
suboptions:
name:
description:
- Virtual Access Point (VAP) name. Source wireless-controller.vap-group.name wireless-controller.vap.name.
required: true
- wids-profile:
+ type: str
+ wids_profile:
description:
- Wireless Intrusion Detection System (WIDS) profile name to assign to the radio. Source wireless-controller.wids-profile.name.
- radio-2:
+ type: str
+ radio_2:
description:
- Configuration options for radio 2.
+ type: dict
suboptions:
amsdu:
description:
- - Enable/disable 802.11n AMSDU support. AMSDU can improve performance if supported by your WiFi clients (default = enable).
+ - Enable/disable 802.11n AMSDU support. AMSDU can improve performance if supported by your WiFi clients .
+ type: str
choices:
- enable
- disable
- ap-handoff:
+ ap_handoff:
description:
- - Enable/disable AP handoff of clients to other APs (default = disable).
+ - Enable/disable AP handoff of clients to other APs .
+ type: str
choices:
- enable
- disable
- ap-sniffer-addr:
+ ap_sniffer_addr:
description:
- MAC address to monitor.
- ap-sniffer-bufsize:
+ type: str
+ ap_sniffer_bufsize:
description:
- - Sniffer buffer size (1 - 32 MB, default = 16).
- ap-sniffer-chan:
+ - Sniffer buffer size (1 - 32 MB).
+ type: int
+ ap_sniffer_chan:
description:
- - Channel on which to operate the sniffer (default = 6).
- ap-sniffer-ctl:
+ - Channel on which to operate the sniffer .
+ type: int
+ ap_sniffer_ctl:
description:
- - Enable/disable sniffer on WiFi control frame (default = enable).
+ - Enable/disable sniffer on WiFi control frame .
+ type: str
choices:
- enable
- disable
- ap-sniffer-data:
+ ap_sniffer_data:
description:
- - Enable/disable sniffer on WiFi data frame (default = enable).
+ - Enable/disable sniffer on WiFi data frame .
+ type: str
choices:
- enable
- disable
- ap-sniffer-mgmt-beacon:
+ ap_sniffer_mgmt_beacon:
description:
- - Enable/disable sniffer on WiFi management Beacon frames (default = enable).
+ - Enable/disable sniffer on WiFi management Beacon frames .
+ type: str
choices:
- enable
- disable
- ap-sniffer-mgmt-other:
+ ap_sniffer_mgmt_other:
description:
- - Enable/disable sniffer on WiFi management other frames (default = enable).
+ - Enable/disable sniffer on WiFi management other frames .
+ type: str
choices:
- enable
- disable
- ap-sniffer-mgmt-probe:
+ ap_sniffer_mgmt_probe:
description:
- - Enable/disable sniffer on WiFi management probe frames (default = enable).
+ - Enable/disable sniffer on WiFi management probe frames .
+ type: str
choices:
- enable
- disable
- auto-power-high:
+ auto_power_high:
description:
- Automatic transmit power high limit in dBm (the actual range of transmit power depends on the AP platform type).
- auto-power-level:
+ type: int
+ auto_power_level:
description:
- - Enable/disable automatic power-level adjustment to prevent co-channel interference (default = disable).
+ - Enable/disable automatic power-level adjustment to prevent co-channel interference .
+ type: str
choices:
- enable
- disable
- auto-power-low:
+ auto_power_low:
description:
- Automatic transmission power low limit in dBm (the actual range of transmit power depends on the AP platform type).
+ type: int
band:
description:
- WiFi band that Radio 2 operates on.
+ type: str
choices:
- 802.11a
- 802.11b
@@ -909,188 +1046,223 @@ options:
- 802.11n-5G-only
- 802.11ac,n-only
- 802.11ac-only
- bandwidth-admission-control:
+ bandwidth_admission_control:
description:
- Enable/disable WiFi multimedia (WMM) bandwidth admission control to optimize WiFi bandwidth use. A request to join the wireless
network is only allowed if the access point has enough bandwidth to support it.
+ type: str
choices:
- enable
- disable
- bandwidth-capacity:
+ bandwidth_capacity:
description:
- - Maximum bandwidth capacity allowed (1 - 600000 Kbps, default = 2000).
- beacon-interval:
+ - Maximum bandwidth capacity allowed (1 - 600000 Kbps).
+ type: int
+ beacon_interval:
description:
- - Beacon interval. The time between beacon frames in msec (the actual range of beacon interval depends on the AP platform type,
- default = 100).
- call-admission-control:
+ - Beacon interval. The time between beacon frames in msec (the actual range of beacon interval depends on the AP platform type).
+ type: int
+ call_admission_control:
description:
- Enable/disable WiFi multimedia (WMM) call admission control to optimize WiFi bandwidth use for VoIP calls. New VoIP calls are
only accepted if there is enough bandwidth available to support them.
+ type: str
choices:
- enable
- disable
- call-capacity:
+ call_capacity:
description:
- - Maximum number of Voice over WLAN (VoWLAN) phones supported by the radio (0 - 60, default = 10).
+ - Maximum number of Voice over WLAN (VoWLAN) phones supported by the radio (0 - 60).
+ type: int
channel:
description:
- Selected list of wireless radio channels.
+ type: list
suboptions:
chan:
description:
- Channel number.
required: true
- channel-bonding:
+ type: str
+ channel_bonding:
description:
- "Channel bandwidth: 80, 40, or 20MHz. Channels may use both 20 and 40 by enabling coexistence."
+ type: str
choices:
- 80MHz
- 40MHz
- 20MHz
- channel-utilization:
+ channel_utilization:
description:
- Enable/disable measuring channel utilization.
+ type: str
choices:
- enable
- disable
coexistence:
description:
- - Enable/disable allowing both HT20 and HT40 on the same radio (default = enable).
+ - Enable/disable allowing both HT20 and HT40 on the same radio .
+ type: str
choices:
- enable
- disable
darrp:
description:
- Enable/disable Distributed Automatic Radio Resource Provisioning (DARRP) to make sure the radio is always using the most optimal
- channel (default = disable).
+ channel .
+ type: str
choices:
- enable
- disable
dtim:
description:
- - DTIM interval. The frequency to transmit Delivery Traffic Indication Message (or Map) (DTIM) messages (1 - 255, default = 1).
- Set higher to save client battery life.
- frag-threshold:
+ - DTIM interval. The frequency to transmit Delivery Traffic Indication Message (or Map) (DTIM) messages (1 - 255). Set higher to
+ save client battery life.
+ type: int
+ frag_threshold:
description:
- - Maximum packet size that can be sent without fragmentation (800 - 2346 bytes, default = 2346).
- frequency-handoff:
+ - Maximum packet size that can be sent without fragmentation (800 - 2346 bytes).
+ type: int
+ frequency_handoff:
description:
- - Enable/disable frequency handoff of clients to other channels (default = disable).
+ - Enable/disable frequency handoff of clients to other channels .
+ type: str
choices:
- enable
- disable
- max-clients:
+ max_clients:
description:
- Maximum number of stations (STAs) or WiFi clients supported by the radio. Range depends on the hardware.
- max-distance:
+ type: int
+ max_distance:
description:
- - Maximum expected distance between the AP and clients (0 - 54000 m, default = 0).
+ - Maximum expected distance between the AP and clients (0 - 54000 m).
+ type: int
mode:
description:
- Mode of radio 2. Radio 2 can be disabled, configured as an access point, a rogue AP monitor, or a sniffer.
+ type: str
choices:
- disabled
- ap
- monitor
- sniffer
- power-level:
+ power_level:
description:
- - Radio power level as a percentage of the maximum transmit power (0 - 100, default = 100).
- powersave-optimize:
+ - Radio power level as a percentage of the maximum transmit power (0 - 100).
+ type: int
+ powersave_optimize:
description:
- Enable client power-saving features such as TIM, AC VO, and OBSS etc.
+ type: str
choices:
- tim
- ac-vo
- no-obss-scan
- no-11b-rate
- client-rate-follow
- protection-mode:
+ protection_mode:
description:
- Enable/disable 802.11g protection modes to support backwards compatibility with older clients (rtscts, ctsonly, disable).
+ type: str
choices:
- rtscts
- ctsonly
- disable
- radio-id:
+ radio_id:
description:
- radio-id
- rts-threshold:
+ type: int
+ rts_threshold:
description:
- - Maximum packet size for RTS transmissions, specifying the maximum size of a data packet before RTS/CTS (256 - 2346 bytes,
- default = 2346).
- short-guard-interval:
+ - Maximum packet size for RTS transmissions, specifying the maximum size of a data packet before RTS/CTS (256 - 2346 bytes).
+ type: int
+ short_guard_interval:
description:
- Use either the short guard interval (Short GI) of 400 ns or the long guard interval (Long GI) of 800 ns.
+ type: str
choices:
- enable
- disable
- spectrum-analysis:
+ spectrum_analysis:
description:
- Enable/disable spectrum analysis to find interference that would negatively impact wireless performance.
+ type: str
choices:
- enable
- disable
- transmit-optimize:
+ transmit_optimize:
description:
- Packet transmission optimization options including power saving, aggregation limiting, retry limiting, etc. All are enabled by
default.
+ type: str
choices:
- disable
- power-save
- aggr-limit
- retry-limit
- send-bar
- vap-all:
+ vap_all:
description:
- - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) (default = enable).
+ - Enable/disable the automatic inheritance of all Virtual Access Points (VAPs) .
+ type: str
choices:
- enable
- disable
vaps:
description:
- Manually selected list of Virtual Access Points (VAPs).
+ type: list
suboptions:
name:
description:
- Virtual Access Point (VAP) name. Source wireless-controller.vap-group.name wireless-controller.vap.name.
required: true
- wids-profile:
+ type: str
+ wids_profile:
description:
- Wireless Intrusion Detection System (WIDS) profile name to assign to the radio. Source wireless-controller.wids-profile.name.
- split-tunneling-acl:
+ type: str
+ split_tunneling_acl:
description:
- Split tunneling ACL filter list.
+ type: list
suboptions:
- dest-ip:
+ dest_ip:
description:
- Destination IP and mask for the split-tunneling subnet.
+ type: str
id:
description:
- ID.
required: true
- split-tunneling-acl-local-ap-subnet:
+ type: int
+ split_tunneling_acl_local_ap_subnet:
description:
- - Enable/disable automatically adding local subnetwork of FortiAP to split-tunneling ACL (default = disable).
+ - Enable/disable automatically adding local subnetwork of FortiAP to split-tunneling ACL .
+ type: str
choices:
- enable
- disable
- split-tunneling-acl-path:
+ split_tunneling_acl_path:
description:
- Split tunneling ACL path is local/tunnel.
+ type: str
choices:
- tunnel
- local
- tun-mtu-downlink:
+ tun_mtu_downlink:
description:
- - Downlink CAPWAP tunnel MTU (0, 576, or 1500 bytes, default = 0).
- tun-mtu-uplink:
+ - Downlink CAPWAP tunnel MTU (0, 576, or 1500 bytes).
+ type: int
+ tun_mtu_uplink:
description:
- - Uplink CAPWAP tunnel MTU (0, 576, or 1500 bytes, default = 0).
- wan-port-mode:
+ - Uplink CAPWAP tunnel MTU (0, 576, or 1500 bytes).
+ type: int
+ wan_port_mode:
description:
- Enable/disable using a WAN port as a LAN port.
+ type: str
choices:
- wan-lan
- wan-only
@@ -1103,6 +1275,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
+ ssl_verify: "False"
tasks:
- name: Configure WTP profiles or FortiAP profiles that define radio settings for manageable FortiAP platforms.
fortios_wireless_controller_wtp_profile:
@@ -1111,179 +1284,179 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
+ state: "present"
wireless_controller_wtp_profile:
- state: "present"
allowaccess: "telnet"
- ap-country: "NA"
- ble-profile: "<your_own_value> (source wireless-controller.ble-profile.name)"
+ ap_country: "NA"
+ ble_profile: "<your_own_value> (source wireless-controller.ble-profile.name)"
comment: "Comment."
- control-message-offload: "ebp-frame"
- deny-mac-list:
+ control_message_offload: "ebp-frame"
+ deny_mac_list:
-
id: "9"
mac: "<your_own_value>"
- dtls-in-kernel: "enable"
- dtls-policy: "clear-text"
- energy-efficient-ethernet: "enable"
- ext-info-enable: "enable"
- handoff-roaming: "enable"
- handoff-rssi: "16"
- handoff-sta-thresh: "17"
- ip-fragment-preventing: "tcp-mss-adjust"
+ dtls_in_kernel: "enable"
+ dtls_policy: "clear-text"
+ energy_efficient_ethernet: "enable"
+ ext_info_enable: "enable"
+ handoff_roaming: "enable"
+ handoff_rssi: "16"
+ handoff_sta_thresh: "17"
+ ip_fragment_preventing: "tcp-mss-adjust"
lan:
- port-mode: "offline"
- port-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port1-mode: "offline"
- port1-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port2-mode: "offline"
- port2-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port3-mode: "offline"
- port3-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port4-mode: "offline"
- port4-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port5-mode: "offline"
- port5-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port6-mode: "offline"
- port6-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port7-mode: "offline"
- port7-ssid: "<your_own_value> (source wireless-controller.vap.name)"
- port8-mode: "offline"
- port8-ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port_mode: "offline"
+ port_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port1_mode: "offline"
+ port1_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port2_mode: "offline"
+ port2_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port3_mode: "offline"
+ port3_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port4_mode: "offline"
+ port4_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port5_mode: "offline"
+ port5_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port6_mode: "offline"
+ port6_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port7_mode: "offline"
+ port7_ssid: "<your_own_value> (source wireless-controller.vap.name)"
+ port8_mode: "offline"
+ port8_ssid: "<your_own_value> (source wireless-controller.vap.name)"
lbs:
aeroscout: "enable"
- aeroscout-ap-mac: "bssid"
- aeroscout-mmu-report: "enable"
- aeroscout-mu: "enable"
- aeroscout-mu-factor: "43"
- aeroscout-mu-timeout: "44"
- aeroscout-server-ip: "<your_own_value>"
- aeroscout-server-port: "46"
- ekahau-blink-mode: "enable"
- ekahau-tag: "<your_own_value>"
- erc-server-ip: "<your_own_value>"
- erc-server-port: "50"
+ aeroscout_ap_mac: "bssid"
+ aeroscout_mmu_report: "enable"
+ aeroscout_mu: "enable"
+ aeroscout_mu_factor: "43"
+ aeroscout_mu_timeout: "44"
+ aeroscout_server_ip: "<your_own_value>"
+ aeroscout_server_port: "46"
+ ekahau_blink_mode: "enable"
+ ekahau_tag: "<your_own_value>"
+ erc_server_ip: "<your_own_value>"
+ erc_server_port: "50"
fortipresence: "foreign"
- fortipresence-frequency: "52"
- fortipresence-port: "53"
- fortipresence-project: "<your_own_value>"
- fortipresence-rogue: "enable"
- fortipresence-secret: "<your_own_value>"
- fortipresence-server: "<your_own_value>"
- fortipresence-unassoc: "enable"
- station-locate: "enable"
- led-schedules:
+ fortipresence_frequency: "52"
+ fortipresence_port: "53"
+ fortipresence_project: "<your_own_value>"
+ fortipresence_rogue: "enable"
+ fortipresence_secret: "<your_own_value>"
+ fortipresence_server: "<your_own_value>"
+ fortipresence_unassoc: "enable"
+ station_locate: "enable"
+ led_schedules:
-
name: "default_name_61 (source firewall.schedule.group.name firewall.schedule.recurring.name)"
- led-state: "enable"
+ led_state: "enable"
lldp: "enable"
- login-passwd: "<your_own_value>"
- login-passwd-change: "yes"
- max-clients: "66"
+ login_passwd: "<your_own_value>"
+ login_passwd_change: "yes"
+ max_clients: "66"
name: "default_name_67"
platform:
type: "AP-11N"
- poe-mode: "auto"
- radio-1:
+ poe_mode: "auto"
+ radio_1:
amsdu: "enable"
- ap-handoff: "enable"
- ap-sniffer-addr: "<your_own_value>"
- ap-sniffer-bufsize: "75"
- ap-sniffer-chan: "76"
- ap-sniffer-ctl: "enable"
- ap-sniffer-data: "enable"
- ap-sniffer-mgmt-beacon: "enable"
- ap-sniffer-mgmt-other: "enable"
- ap-sniffer-mgmt-probe: "enable"
- auto-power-high: "82"
- auto-power-level: "enable"
- auto-power-low: "84"
+ ap_handoff: "enable"
+ ap_sniffer_addr: "<your_own_value>"
+ ap_sniffer_bufsize: "75"
+ ap_sniffer_chan: "76"
+ ap_sniffer_ctl: "enable"
+ ap_sniffer_data: "enable"
+ ap_sniffer_mgmt_beacon: "enable"
+ ap_sniffer_mgmt_other: "enable"
+ ap_sniffer_mgmt_probe: "enable"
+ auto_power_high: "82"
+ auto_power_level: "enable"
+ auto_power_low: "84"
band: "802.11a"
- bandwidth-admission-control: "enable"
- bandwidth-capacity: "87"
- beacon-interval: "88"
- call-admission-control: "enable"
- call-capacity: "90"
+ bandwidth_admission_control: "enable"
+ bandwidth_capacity: "87"
+ beacon_interval: "88"
+ call_admission_control: "enable"
+ call_capacity: "90"
channel:
-
chan: "<your_own_value>"
- channel-bonding: "80MHz"
- channel-utilization: "enable"
+ channel_bonding: "80MHz"
+ channel_utilization: "enable"
coexistence: "enable"
darrp: "enable"
dtim: "97"
- frag-threshold: "98"
- frequency-handoff: "enable"
- max-clients: "100"
- max-distance: "101"
+ frag_threshold: "98"
+ frequency_handoff: "enable"
+ max_clients: "100"
+ max_distance: "101"
mode: "disabled"
- power-level: "103"
- powersave-optimize: "tim"
- protection-mode: "rtscts"
- radio-id: "106"
- rts-threshold: "107"
- short-guard-interval: "enable"
- spectrum-analysis: "enable"
- transmit-optimize: "disable"
- vap-all: "enable"
+ power_level: "103"
+ powersave_optimize: "tim"
+ protection_mode: "rtscts"
+ radio_id: "106"
+ rts_threshold: "107"
+ short_guard_interval: "enable"
+ spectrum_analysis: "enable"
+ transmit_optimize: "disable"
+ vap_all: "enable"
vaps:
-
name: "default_name_113 (source wireless-controller.vap-group.name wireless-controller.vap.name)"
- wids-profile: "<your_own_value> (source wireless-controller.wids-profile.name)"
- radio-2:
+ wids_profile: "<your_own_value> (source wireless-controller.wids-profile.name)"
+ radio_2:
amsdu: "enable"
- ap-handoff: "enable"
- ap-sniffer-addr: "<your_own_value>"
- ap-sniffer-bufsize: "119"
- ap-sniffer-chan: "120"
- ap-sniffer-ctl: "enable"
- ap-sniffer-data: "enable"
- ap-sniffer-mgmt-beacon: "enable"
- ap-sniffer-mgmt-other: "enable"
- ap-sniffer-mgmt-probe: "enable"
- auto-power-high: "126"
- auto-power-level: "enable"
- auto-power-low: "128"
+ ap_handoff: "enable"
+ ap_sniffer_addr: "<your_own_value>"
+ ap_sniffer_bufsize: "119"
+ ap_sniffer_chan: "120"
+ ap_sniffer_ctl: "enable"
+ ap_sniffer_data: "enable"
+ ap_sniffer_mgmt_beacon: "enable"
+ ap_sniffer_mgmt_other: "enable"
+ ap_sniffer_mgmt_probe: "enable"
+ auto_power_high: "126"
+ auto_power_level: "enable"
+ auto_power_low: "128"
band: "802.11a"
- bandwidth-admission-control: "enable"
- bandwidth-capacity: "131"
- beacon-interval: "132"
- call-admission-control: "enable"
- call-capacity: "134"
+ bandwidth_admission_control: "enable"
+ bandwidth_capacity: "131"
+ beacon_interval: "132"
+ call_admission_control: "enable"
+ call_capacity: "134"
channel:
-
chan: "<your_own_value>"
- channel-bonding: "80MHz"
- channel-utilization: "enable"
+ channel_bonding: "80MHz"
+ channel_utilization: "enable"
coexistence: "enable"
darrp: "enable"
dtim: "141"
- frag-threshold: "142"
- frequency-handoff: "enable"
- max-clients: "144"
- max-distance: "145"
+ frag_threshold: "142"
+ frequency_handoff: "enable"
+ max_clients: "144"
+ max_distance: "145"
mode: "disabled"
- power-level: "147"
- powersave-optimize: "tim"
- protection-mode: "rtscts"
- radio-id: "150"
- rts-threshold: "151"
- short-guard-interval: "enable"
- spectrum-analysis: "enable"
- transmit-optimize: "disable"
- vap-all: "enable"
+ power_level: "147"
+ powersave_optimize: "tim"
+ protection_mode: "rtscts"
+ radio_id: "150"
+ rts_threshold: "151"
+ short_guard_interval: "enable"
+ spectrum_analysis: "enable"
+ transmit_optimize: "disable"
+ vap_all: "enable"
vaps:
-
name: "default_name_157 (source wireless-controller.vap-group.name wireless-controller.vap.name)"
- wids-profile: "<your_own_value> (source wireless-controller.wids-profile.name)"
- split-tunneling-acl:
+ wids_profile: "<your_own_value> (source wireless-controller.wids-profile.name)"
+ split_tunneling_acl:
-
- dest-ip: "<your_own_value>"
+ dest_ip: "<your_own_value>"
id: "161"
- split-tunneling-acl-local-ap-subnet: "enable"
- split-tunneling-acl-path: "tunnel"
- tun-mtu-downlink: "164"
- tun-mtu-uplink: "165"
- wan-port-mode: "wan-lan"
+ split_tunneling_acl_local_ap_subnet: "enable"
+ split_tunneling_acl_path: "tunnel"
+ tun_mtu_downlink: "164"
+ tun_mtu_uplink: "165"
+ wan_port_mode: "wan-lan"
'''
RETURN = '''
@@ -1346,12 +1519,16 @@ version:
'''
from ansible.module_utils.basic import AnsibleModule
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
def login(data, fos):
host = data['host']
username = data['username']
password = data['password']
+ ssl_verify = data['ssl_verify']
fos.debug('on')
if 'https' in data and not data['https']:
@@ -1359,21 +1536,21 @@ def login(data, fos):
else:
fos.https('on')
- fos.login(host, username, password)
+ fos.login(host, username, password, verify=ssl_verify)
def filter_wireless_controller_wtp_profile_data(json):
- option_list = ['allowaccess', 'ap-country', 'ble-profile',
- 'comment', 'control-message-offload', 'deny-mac-list',
- 'dtls-in-kernel', 'dtls-policy', 'energy-efficient-ethernet',
- 'ext-info-enable', 'handoff-roaming', 'handoff-rssi',
- 'handoff-sta-thresh', 'ip-fragment-preventing', 'lan',
- 'lbs', 'led-schedules', 'led-state',
- 'lldp', 'login-passwd', 'login-passwd-change',
- 'max-clients', 'name', 'platform',
- 'poe-mode', 'radio-1', 'radio-2',
- 'split-tunneling-acl', 'split-tunneling-acl-local-ap-subnet', 'split-tunneling-acl-path',
- 'tun-mtu-downlink', 'tun-mtu-uplink', 'wan-port-mode']
+ option_list = ['allowaccess', 'ap_country', 'ble_profile',
+ 'comment', 'control_message_offload', 'deny_mac_list',
+ 'dtls_in_kernel', 'dtls_policy', 'energy_efficient_ethernet',
+ 'ext_info_enable', 'handoff_roaming', 'handoff_rssi',
+ 'handoff_sta_thresh', 'ip_fragment_preventing', 'lan',
+ 'lbs', 'led_schedules', 'led_state',
+ 'lldp', 'login_passwd', 'login_passwd_change',
+ 'max_clients', 'name', 'platform',
+ 'poe_mode', 'radio_1', 'radio_2',
+ 'split_tunneling_acl', 'split_tunneling_acl_local_ap_subnet', 'split_tunneling_acl_path',
+ 'tun_mtu_downlink', 'tun_mtu_uplink', 'wan_port_mode']
dictionary = {}
for attribute in option_list:
@@ -1383,50 +1560,70 @@ def filter_wireless_controller_wtp_profile_data(json):
return dictionary
+def underscore_to_hyphen(data):
+ if isinstance(data, list):
+ for elem in data:
+ elem = underscore_to_hyphen(elem)
+ elif isinstance(data, dict):
+ new_data = {}
+ for k, v in data.items():
+ new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
+ data = new_data
+
+ return data
+
+
def wireless_controller_wtp_profile(data, fos):
vdom = data['vdom']
+ state = data['state']
wireless_controller_wtp_profile_data = data['wireless_controller_wtp_profile']
- filtered_data = filter_wireless_controller_wtp_profile_data(wireless_controller_wtp_profile_data)
+ filtered_data = underscore_to_hyphen(filter_wireless_controller_wtp_profile_data(wireless_controller_wtp_profile_data))
- if wireless_controller_wtp_profile_data['state'] == "present":
+ if state == "present":
return fos.set('wireless-controller',
'wtp-profile',
data=filtered_data,
vdom=vdom)
- elif wireless_controller_wtp_profile_data['state'] == "absent":
+ elif state == "absent":
return fos.delete('wireless-controller',
'wtp-profile',
mkey=filtered_data['name'],
vdom=vdom)
+def is_successful_status(status):
+ return status['status'] == "success" or \
+ status['http_method'] == "DELETE" and status['http_status'] == 404
+
+
def fortios_wireless_controller(data, fos):
- login(data, fos)
if data['wireless_controller_wtp_profile']:
resp = wireless_controller_wtp_profile(data, fos)
- fos.logout()
- return not resp['status'] == "success", resp['status'] == "success", resp
+ return not is_successful_status(resp), \
+ resp['status'] == "success", \
+ resp
def main():
fields = {
- "host": {"required": True, "type": "str"},
- "username": {"required": True, "type": "str"},
- "password": {"required": False, "type": "str", "no_log": True},
+ "host": {"required": False, "type": "str"},
+ "username": {"required": False, "type": "str"},
+ "password": {"required": False, "type": "str", "default": "", "no_log": True},
"vdom": {"required": False, "type": "str", "default": "root"},
"https": {"required": False, "type": "bool", "default": True},
+ "ssl_verify": {"required": False, "type": "bool", "default": True},
+ "state": {"required": True, "type": "str",
+ "choices": ["present", "absent"]},
"wireless_controller_wtp_profile": {
- "required": False, "type": "dict",
+ "required": False, "type": "dict", "default": None,
"options": {
- "state": {"required": True, "type": "str",
- "choices": ["present", "absent"]},
"allowaccess": {"required": False, "type": "str",
"choices": ["telnet", "http", "https",
"ssh"]},
- "ap-country": {"required": False, "type": "str",
+ "ap_country": {"required": False, "type": "str",
"choices": ["NA", "AL", "DZ",
"AO", "AR", "AM",
"AU", "AT", "AZ",
@@ -1470,115 +1667,115 @@ def main():
"UZ", "VE", "VN",
"YE", "ZB", "ZW",
"JP", "CA"]},
- "ble-profile": {"required": False, "type": "str"},
+ "ble_profile": {"required": False, "type": "str"},
"comment": {"required": False, "type": "str"},
- "control-message-offload": {"required": False, "type": "str",
+ "control_message_offload": {"required": False, "type": "str",
"choices": ["ebp-frame", "aeroscout-tag", "ap-list",
"sta-list", "sta-cap-list", "stats",
"aeroscout-mu"]},
- "deny-mac-list": {"required": False, "type": "list",
+ "deny_mac_list": {"required": False, "type": "list",
"options": {
"id": {"required": True, "type": "int"},
"mac": {"required": False, "type": "str"}
}},
- "dtls-in-kernel": {"required": False, "type": "str",
+ "dtls_in_kernel": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "dtls-policy": {"required": False, "type": "str",
+ "dtls_policy": {"required": False, "type": "str",
"choices": ["clear-text", "dtls-enabled", "ipsec-vpn"]},
- "energy-efficient-ethernet": {"required": False, "type": "str",
+ "energy_efficient_ethernet": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ext-info-enable": {"required": False, "type": "str",
+ "ext_info_enable": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "handoff-roaming": {"required": False, "type": "str",
+ "handoff_roaming": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "handoff-rssi": {"required": False, "type": "int"},
- "handoff-sta-thresh": {"required": False, "type": "int"},
- "ip-fragment-preventing": {"required": False, "type": "str",
+ "handoff_rssi": {"required": False, "type": "int"},
+ "handoff_sta_thresh": {"required": False, "type": "int"},
+ "ip_fragment_preventing": {"required": False, "type": "str",
"choices": ["tcp-mss-adjust", "icmp-unreachable"]},
"lan": {"required": False, "type": "dict",
"options": {
- "port-mode": {"required": False, "type": "str",
+ "port_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port-ssid": {"required": False, "type": "str"},
- "port1-mode": {"required": False, "type": "str",
+ "port_ssid": {"required": False, "type": "str"},
+ "port1_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port1-ssid": {"required": False, "type": "str"},
- "port2-mode": {"required": False, "type": "str",
+ "port1_ssid": {"required": False, "type": "str"},
+ "port2_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port2-ssid": {"required": False, "type": "str"},
- "port3-mode": {"required": False, "type": "str",
+ "port2_ssid": {"required": False, "type": "str"},
+ "port3_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port3-ssid": {"required": False, "type": "str"},
- "port4-mode": {"required": False, "type": "str",
+ "port3_ssid": {"required": False, "type": "str"},
+ "port4_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port4-ssid": {"required": False, "type": "str"},
- "port5-mode": {"required": False, "type": "str",
+ "port4_ssid": {"required": False, "type": "str"},
+ "port5_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port5-ssid": {"required": False, "type": "str"},
- "port6-mode": {"required": False, "type": "str",
+ "port5_ssid": {"required": False, "type": "str"},
+ "port6_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port6-ssid": {"required": False, "type": "str"},
- "port7-mode": {"required": False, "type": "str",
+ "port6_ssid": {"required": False, "type": "str"},
+ "port7_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port7-ssid": {"required": False, "type": "str"},
- "port8-mode": {"required": False, "type": "str",
+ "port7_ssid": {"required": False, "type": "str"},
+ "port8_mode": {"required": False, "type": "str",
"choices": ["offline", "nat-to-wan", "bridge-to-wan",
"bridge-to-ssid"]},
- "port8-ssid": {"required": False, "type": "str"}
+ "port8_ssid": {"required": False, "type": "str"}
}},
"lbs": {"required": False, "type": "dict",
"options": {
"aeroscout": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "aeroscout-ap-mac": {"required": False, "type": "str",
+ "aeroscout_ap_mac": {"required": False, "type": "str",
"choices": ["bssid", "board-mac"]},
- "aeroscout-mmu-report": {"required": False, "type": "str",
+ "aeroscout_mmu_report": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "aeroscout-mu": {"required": False, "type": "str",
+ "aeroscout_mu": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "aeroscout-mu-factor": {"required": False, "type": "int"},
- "aeroscout-mu-timeout": {"required": False, "type": "int"},
- "aeroscout-server-ip": {"required": False, "type": "str"},
- "aeroscout-server-port": {"required": False, "type": "int"},
- "ekahau-blink-mode": {"required": False, "type": "str",
+ "aeroscout_mu_factor": {"required": False, "type": "int"},
+ "aeroscout_mu_timeout": {"required": False, "type": "int"},
+ "aeroscout_server_ip": {"required": False, "type": "str"},
+ "aeroscout_server_port": {"required": False, "type": "int"},
+ "ekahau_blink_mode": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ekahau-tag": {"required": False, "type": "str"},
- "erc-server-ip": {"required": False, "type": "str"},
- "erc-server-port": {"required": False, "type": "int"},
+ "ekahau_tag": {"required": False, "type": "str"},
+ "erc_server_ip": {"required": False, "type": "str"},
+ "erc_server_port": {"required": False, "type": "int"},
"fortipresence": {"required": False, "type": "str",
"choices": ["foreign", "both", "disable"]},
- "fortipresence-frequency": {"required": False, "type": "int"},
- "fortipresence-port": {"required": False, "type": "int"},
- "fortipresence-project": {"required": False, "type": "str"},
- "fortipresence-rogue": {"required": False, "type": "str",
+ "fortipresence_frequency": {"required": False, "type": "int"},
+ "fortipresence_port": {"required": False, "type": "int"},
+ "fortipresence_project": {"required": False, "type": "str"},
+ "fortipresence_rogue": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "fortipresence-secret": {"required": False, "type": "str"},
- "fortipresence-server": {"required": False, "type": "str"},
- "fortipresence-unassoc": {"required": False, "type": "str",
+ "fortipresence_secret": {"required": False, "type": "str"},
+ "fortipresence_server": {"required": False, "type": "str"},
+ "fortipresence_unassoc": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "station-locate": {"required": False, "type": "str",
+ "station_locate": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}},
- "led-schedules": {"required": False, "type": "list",
+ "led_schedules": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "led-state": {"required": False, "type": "str",
+ "led_state": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"lldp": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "login-passwd": {"required": False, "type": "str"},
- "login-passwd-change": {"required": False, "type": "str",
+ "login_passwd": {"required": False, "type": "str"},
+ "login_passwd_change": {"required": False, "type": "str",
"choices": ["yes", "default", "no"]},
- "max-clients": {"required": False, "type": "int"},
+ "max_clients": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"},
"platform": {"required": False, "type": "dict",
"options": {
@@ -1602,179 +1799,179 @@ def main():
"U223EV", "U24JEV", "U321EV",
"U323EV"]}
}},
- "poe-mode": {"required": False, "type": "str",
+ "poe_mode": {"required": False, "type": "str",
"choices": ["auto", "8023af", "8023at",
"power-adapter"]},
- "radio-1": {"required": False, "type": "dict",
+ "radio_1": {"required": False, "type": "dict",
"options": {
"amsdu": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-handoff": {"required": False, "type": "str",
+ "ap_handoff": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-addr": {"required": False, "type": "str"},
- "ap-sniffer-bufsize": {"required": False, "type": "int"},
- "ap-sniffer-chan": {"required": False, "type": "int"},
- "ap-sniffer-ctl": {"required": False, "type": "str",
+ "ap_sniffer_addr": {"required": False, "type": "str"},
+ "ap_sniffer_bufsize": {"required": False, "type": "int"},
+ "ap_sniffer_chan": {"required": False, "type": "int"},
+ "ap_sniffer_ctl": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-data": {"required": False, "type": "str",
+ "ap_sniffer_data": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-mgmt-beacon": {"required": False, "type": "str",
+ "ap_sniffer_mgmt_beacon": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-mgmt-other": {"required": False, "type": "str",
+ "ap_sniffer_mgmt_other": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-mgmt-probe": {"required": False, "type": "str",
+ "ap_sniffer_mgmt_probe": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auto-power-high": {"required": False, "type": "int"},
- "auto-power-level": {"required": False, "type": "str",
+ "auto_power_high": {"required": False, "type": "int"},
+ "auto_power_level": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auto-power-low": {"required": False, "type": "int"},
+ "auto_power_low": {"required": False, "type": "int"},
"band": {"required": False, "type": "str",
"choices": ["802.11a", "802.11b", "802.11g",
"802.11n", "802.11n-5G", "802.11ac",
"802.11n,g-only", "802.11g-only", "802.11n-only",
"802.11n-5G-only", "802.11ac,n-only", "802.11ac-only"]},
- "bandwidth-admission-control": {"required": False, "type": "str",
+ "bandwidth_admission_control": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "bandwidth-capacity": {"required": False, "type": "int"},
- "beacon-interval": {"required": False, "type": "int"},
- "call-admission-control": {"required": False, "type": "str",
+ "bandwidth_capacity": {"required": False, "type": "int"},
+ "beacon_interval": {"required": False, "type": "int"},
+ "call_admission_control": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "call-capacity": {"required": False, "type": "int"},
+ "call_capacity": {"required": False, "type": "int"},
"channel": {"required": False, "type": "list",
"options": {
"chan": {"required": True, "type": "str"}
}},
- "channel-bonding": {"required": False, "type": "str",
+ "channel_bonding": {"required": False, "type": "str",
"choices": ["80MHz", "40MHz", "20MHz"]},
- "channel-utilization": {"required": False, "type": "str",
+ "channel_utilization": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"coexistence": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"darrp": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"dtim": {"required": False, "type": "int"},
- "frag-threshold": {"required": False, "type": "int"},
- "frequency-handoff": {"required": False, "type": "str",
+ "frag_threshold": {"required": False, "type": "int"},
+ "frequency_handoff": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "max-clients": {"required": False, "type": "int"},
- "max-distance": {"required": False, "type": "int"},
+ "max_clients": {"required": False, "type": "int"},
+ "max_distance": {"required": False, "type": "int"},
"mode": {"required": False, "type": "str",
"choices": ["disabled", "ap", "monitor",
"sniffer"]},
- "power-level": {"required": False, "type": "int"},
- "powersave-optimize": {"required": False, "type": "str",
+ "power_level": {"required": False, "type": "int"},
+ "powersave_optimize": {"required": False, "type": "str",
"choices": ["tim", "ac-vo", "no-obss-scan",
"no-11b-rate", "client-rate-follow"]},
- "protection-mode": {"required": False, "type": "str",
+ "protection_mode": {"required": False, "type": "str",
"choices": ["rtscts", "ctsonly", "disable"]},
- "radio-id": {"required": False, "type": "int"},
- "rts-threshold": {"required": False, "type": "int"},
- "short-guard-interval": {"required": False, "type": "str",
+ "radio_id": {"required": False, "type": "int"},
+ "rts_threshold": {"required": False, "type": "int"},
+ "short_guard_interval": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "spectrum-analysis": {"required": False, "type": "str",
+ "spectrum_analysis": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "transmit-optimize": {"required": False, "type": "str",
+ "transmit_optimize": {"required": False, "type": "str",
"choices": ["disable", "power-save", "aggr-limit",
"retry-limit", "send-bar"]},
- "vap-all": {"required": False, "type": "str",
+ "vap_all": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"vaps": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "wids-profile": {"required": False, "type": "str"}
+ "wids_profile": {"required": False, "type": "str"}
}},
- "radio-2": {"required": False, "type": "dict",
+ "radio_2": {"required": False, "type": "dict",
"options": {
"amsdu": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-handoff": {"required": False, "type": "str",
+ "ap_handoff": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-addr": {"required": False, "type": "str"},
- "ap-sniffer-bufsize": {"required": False, "type": "int"},
- "ap-sniffer-chan": {"required": False, "type": "int"},
- "ap-sniffer-ctl": {"required": False, "type": "str",
+ "ap_sniffer_addr": {"required": False, "type": "str"},
+ "ap_sniffer_bufsize": {"required": False, "type": "int"},
+ "ap_sniffer_chan": {"required": False, "type": "int"},
+ "ap_sniffer_ctl": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-data": {"required": False, "type": "str",
+ "ap_sniffer_data": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-mgmt-beacon": {"required": False, "type": "str",
+ "ap_sniffer_mgmt_beacon": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-mgmt-other": {"required": False, "type": "str",
+ "ap_sniffer_mgmt_other": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "ap-sniffer-mgmt-probe": {"required": False, "type": "str",
+ "ap_sniffer_mgmt_probe": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auto-power-high": {"required": False, "type": "int"},
- "auto-power-level": {"required": False, "type": "str",
+ "auto_power_high": {"required": False, "type": "int"},
+ "auto_power_level": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "auto-power-low": {"required": False, "type": "int"},
+ "auto_power_low": {"required": False, "type": "int"},
"band": {"required": False, "type": "str",
"choices": ["802.11a", "802.11b", "802.11g",
"802.11n", "802.11n-5G", "802.11ac",
"802.11n,g-only", "802.11g-only", "802.11n-only",
"802.11n-5G-only", "802.11ac,n-only", "802.11ac-only"]},
- "bandwidth-admission-control": {"required": False, "type": "str",
+ "bandwidth_admission_control": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "bandwidth-capacity": {"required": False, "type": "int"},
- "beacon-interval": {"required": False, "type": "int"},
- "call-admission-control": {"required": False, "type": "str",
+ "bandwidth_capacity": {"required": False, "type": "int"},
+ "beacon_interval": {"required": False, "type": "int"},
+ "call_admission_control": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "call-capacity": {"required": False, "type": "int"},
+ "call_capacity": {"required": False, "type": "int"},
"channel": {"required": False, "type": "list",
"options": {
"chan": {"required": True, "type": "str"}
}},
- "channel-bonding": {"required": False, "type": "str",
+ "channel_bonding": {"required": False, "type": "str",
"choices": ["80MHz", "40MHz", "20MHz"]},
- "channel-utilization": {"required": False, "type": "str",
+ "channel_utilization": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"coexistence": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"darrp": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"dtim": {"required": False, "type": "int"},
- "frag-threshold": {"required": False, "type": "int"},
- "frequency-handoff": {"required": False, "type": "str",
+ "frag_threshold": {"required": False, "type": "int"},
+ "frequency_handoff": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "max-clients": {"required": False, "type": "int"},
- "max-distance": {"required": False, "type": "int"},
+ "max_clients": {"required": False, "type": "int"},
+ "max_distance": {"required": False, "type": "int"},
"mode": {"required": False, "type": "str",
"choices": ["disabled", "ap", "monitor",
"sniffer"]},
- "power-level": {"required": False, "type": "int"},
- "powersave-optimize": {"required": False, "type": "str",
+ "power_level": {"required": False, "type": "int"},
+ "powersave_optimize": {"required": False, "type": "str",
"choices": ["tim", "ac-vo", "no-obss-scan",
"no-11b-rate", "client-rate-follow"]},
- "protection-mode": {"required": False, "type": "str",
+ "protection_mode": {"required": False, "type": "str",
"choices": ["rtscts", "ctsonly", "disable"]},
- "radio-id": {"required": False, "type": "int"},
- "rts-threshold": {"required": False, "type": "int"},
- "short-guard-interval": {"required": False, "type": "str",
+ "radio_id": {"required": False, "type": "int"},
+ "rts_threshold": {"required": False, "type": "int"},
+ "short_guard_interval": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "spectrum-analysis": {"required": False, "type": "str",
+ "spectrum_analysis": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "transmit-optimize": {"required": False, "type": "str",
+ "transmit_optimize": {"required": False, "type": "str",
"choices": ["disable", "power-save", "aggr-limit",
"retry-limit", "send-bar"]},
- "vap-all": {"required": False, "type": "str",
+ "vap_all": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"vaps": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
- "wids-profile": {"required": False, "type": "str"}
+ "wids_profile": {"required": False, "type": "str"}
}},
- "split-tunneling-acl": {"required": False, "type": "list",
+ "split_tunneling_acl": {"required": False, "type": "list",
"options": {
- "dest-ip": {"required": False, "type": "str"},
+ "dest_ip": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"}
}},
- "split-tunneling-acl-local-ap-subnet": {"required": False, "type": "str",
+ "split_tunneling_acl_local_ap_subnet": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
- "split-tunneling-acl-path": {"required": False, "type": "str",
+ "split_tunneling_acl_path": {"required": False, "type": "str",
"choices": ["tunnel", "local"]},
- "tun-mtu-downlink": {"required": False, "type": "int"},
- "tun-mtu-uplink": {"required": False, "type": "int"},
- "wan-port-mode": {"required": False, "type": "str",
+ "tun_mtu_downlink": {"required": False, "type": "int"},
+ "tun_mtu_uplink": {"required": False, "type": "int"},
+ "wan_port_mode": {"required": False, "type": "str",
"choices": ["wan-lan", "wan-only"]}
}
@@ -1783,14 +1980,31 @@ def main():
module = AnsibleModule(argument_spec=fields,
supports_check_mode=False)
- try:
- from fortiosapi import FortiOSAPI
- except ImportError:
- module.fail_json(msg="fortiosapi module is required")
- fos = FortiOSAPI()
+ # legacy_mode refers to using fortiosapi instead of HTTPAPI
+ legacy_mode = 'host' in module.params and module.params['host'] is not None and \
+ 'username' in module.params and module.params['username'] is not None and \
+ 'password' in module.params and module.params['password'] is not None
+
+ if not legacy_mode:
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fos = FortiOSHandler(connection)
+
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+ else:
+ try:
+ from fortiosapi import FortiOSAPI
+ except ImportError:
+ module.fail_json(msg="fortiosapi module is required")
+
+ fos = FortiOSAPI()
- is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ login(module.params, fos)
+ is_error, has_changed, result = fortios_wireless_controller(module.params, fos)
+ fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)
diff --git a/test/sanity/ignore.txt b/test/sanity/ignore.txt
index 652d7af421..3aa414e6cf 100644
--- a/test/sanity/ignore.txt
+++ b/test/sanity/ignore.txt
@@ -3712,51 +3712,13 @@ lib/ansible/modules/network/fortios/fortios_system_global.py validate-modules:E3
lib/ansible/modules/network/fortios/fortios_voip_profile.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_vpn_ipsec_manualkey.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_vpn_ipsec_manualkey_interface.py validate-modules:E326
-lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_web_proxy_explicit.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_web_proxy_global.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_web_proxy_global.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_web_proxy_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_webfilter.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_webfilter.py validate-modules:E328
lib/ansible/modules/network/fortios/fortios_webfilter.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_webfilter.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_fortiguard.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_cat.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_ftgd_local_rating.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_cache_setting.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_ips_urlfilter_setting6.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_override.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_override.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_profile.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_profile.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_search_engine.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_webfilter_urlfilter.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_global.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py validate-modules:E326
-lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_setting.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_utm_profile.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_vap.py validate-modules:E337
-lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_wids_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py validate-modules:E326
-lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py validate-modules:E326
-lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py validate-modules:E336
-lib/ansible/modules/network/fortios/fortios_wireless_controller_wtp_profile.py validate-modules:E337
lib/ansible/modules/network/frr/frr_bgp.py validate-modules:E322
lib/ansible/modules/network/frr/frr_bgp.py validate-modules:E323
lib/ansible/modules/network/frr/frr_bgp.py validate-modules:E337
diff --git a/test/units/modules/network/fortios/test_fortios_web_proxy_explicit.py b/test/units/modules/network/fortios/test_fortios_web_proxy_explicit.py
new file mode 100644
index 0000000000..013fa3a52c
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_web_proxy_explicit.py
@@ -0,0 +1,351 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_web_proxy_explicit
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_web_proxy_explicit.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_web_proxy_explicit_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_explicit': {
+ 'ftp_incoming_port': 'test_value_3',
+ 'ftp_over_http': 'enable',
+ 'http_incoming_port': 'test_value_5',
+ 'https_incoming_port': 'test_value_6',
+ 'https_replacement_message': 'enable',
+ 'incoming_ip': 'test_value_8',
+ 'incoming_ip6': 'test_value_9',
+ 'ipv6_status': 'enable',
+ 'message_upon_server_error': 'enable',
+ 'outgoing_ip': 'test_value_12',
+ 'outgoing_ip6': 'test_value_13',
+ 'pac_file_data': 'test_value_14',
+ 'pac_file_name': 'test_value_15',
+ 'pac_file_server_port': 'test_value_16',
+ 'pac_file_server_status': 'enable',
+ 'pac_file_url': 'test_value_18',
+ 'pref_dns_result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec_default_action': 'accept',
+ 'socks': 'enable',
+ 'socks_incoming_port': 'test_value_23',
+ 'ssl_algorithm': 'low',
+ 'status': 'enable',
+ 'strict_guest': 'enable',
+ 'trace_auth_no_rsp': 'enable',
+ 'unknown_http_version': 'reject'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_explicit.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'ftp-incoming-port': 'test_value_3',
+ 'ftp-over-http': 'enable',
+ 'http-incoming-port': 'test_value_5',
+ 'https-incoming-port': 'test_value_6',
+ 'https-replacement-message': 'enable',
+ 'incoming-ip': 'test_value_8',
+ 'incoming-ip6': 'test_value_9',
+ 'ipv6-status': 'enable',
+ 'message-upon-server-error': 'enable',
+ 'outgoing-ip': 'test_value_12',
+ 'outgoing-ip6': 'test_value_13',
+ 'pac-file-data': 'test_value_14',
+ 'pac-file-name': 'test_value_15',
+ 'pac-file-server-port': 'test_value_16',
+ 'pac-file-server-status': 'enable',
+ 'pac-file-url': 'test_value_18',
+ 'pref-dns-result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec-default-action': 'accept',
+ 'socks': 'enable',
+ 'socks-incoming-port': 'test_value_23',
+ 'ssl-algorithm': 'low',
+ 'status': 'enable',
+ 'strict-guest': 'enable',
+ 'trace-auth-no-rsp': 'enable',
+ 'unknown-http-version': 'reject'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'explicit', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_web_proxy_explicit_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_explicit': {
+ 'ftp_incoming_port': 'test_value_3',
+ 'ftp_over_http': 'enable',
+ 'http_incoming_port': 'test_value_5',
+ 'https_incoming_port': 'test_value_6',
+ 'https_replacement_message': 'enable',
+ 'incoming_ip': 'test_value_8',
+ 'incoming_ip6': 'test_value_9',
+ 'ipv6_status': 'enable',
+ 'message_upon_server_error': 'enable',
+ 'outgoing_ip': 'test_value_12',
+ 'outgoing_ip6': 'test_value_13',
+ 'pac_file_data': 'test_value_14',
+ 'pac_file_name': 'test_value_15',
+ 'pac_file_server_port': 'test_value_16',
+ 'pac_file_server_status': 'enable',
+ 'pac_file_url': 'test_value_18',
+ 'pref_dns_result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec_default_action': 'accept',
+ 'socks': 'enable',
+ 'socks_incoming_port': 'test_value_23',
+ 'ssl_algorithm': 'low',
+ 'status': 'enable',
+ 'strict_guest': 'enable',
+ 'trace_auth_no_rsp': 'enable',
+ 'unknown_http_version': 'reject'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_explicit.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'ftp-incoming-port': 'test_value_3',
+ 'ftp-over-http': 'enable',
+ 'http-incoming-port': 'test_value_5',
+ 'https-incoming-port': 'test_value_6',
+ 'https-replacement-message': 'enable',
+ 'incoming-ip': 'test_value_8',
+ 'incoming-ip6': 'test_value_9',
+ 'ipv6-status': 'enable',
+ 'message-upon-server-error': 'enable',
+ 'outgoing-ip': 'test_value_12',
+ 'outgoing-ip6': 'test_value_13',
+ 'pac-file-data': 'test_value_14',
+ 'pac-file-name': 'test_value_15',
+ 'pac-file-server-port': 'test_value_16',
+ 'pac-file-server-status': 'enable',
+ 'pac-file-url': 'test_value_18',
+ 'pref-dns-result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec-default-action': 'accept',
+ 'socks': 'enable',
+ 'socks-incoming-port': 'test_value_23',
+ 'ssl-algorithm': 'low',
+ 'status': 'enable',
+ 'strict-guest': 'enable',
+ 'trace-auth-no-rsp': 'enable',
+ 'unknown-http-version': 'reject'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'explicit', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_web_proxy_explicit_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_explicit': {
+ 'ftp_incoming_port': 'test_value_3',
+ 'ftp_over_http': 'enable',
+ 'http_incoming_port': 'test_value_5',
+ 'https_incoming_port': 'test_value_6',
+ 'https_replacement_message': 'enable',
+ 'incoming_ip': 'test_value_8',
+ 'incoming_ip6': 'test_value_9',
+ 'ipv6_status': 'enable',
+ 'message_upon_server_error': 'enable',
+ 'outgoing_ip': 'test_value_12',
+ 'outgoing_ip6': 'test_value_13',
+ 'pac_file_data': 'test_value_14',
+ 'pac_file_name': 'test_value_15',
+ 'pac_file_server_port': 'test_value_16',
+ 'pac_file_server_status': 'enable',
+ 'pac_file_url': 'test_value_18',
+ 'pref_dns_result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec_default_action': 'accept',
+ 'socks': 'enable',
+ 'socks_incoming_port': 'test_value_23',
+ 'ssl_algorithm': 'low',
+ 'status': 'enable',
+ 'strict_guest': 'enable',
+ 'trace_auth_no_rsp': 'enable',
+ 'unknown_http_version': 'reject'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_explicit.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'ftp-incoming-port': 'test_value_3',
+ 'ftp-over-http': 'enable',
+ 'http-incoming-port': 'test_value_5',
+ 'https-incoming-port': 'test_value_6',
+ 'https-replacement-message': 'enable',
+ 'incoming-ip': 'test_value_8',
+ 'incoming-ip6': 'test_value_9',
+ 'ipv6-status': 'enable',
+ 'message-upon-server-error': 'enable',
+ 'outgoing-ip': 'test_value_12',
+ 'outgoing-ip6': 'test_value_13',
+ 'pac-file-data': 'test_value_14',
+ 'pac-file-name': 'test_value_15',
+ 'pac-file-server-port': 'test_value_16',
+ 'pac-file-server-status': 'enable',
+ 'pac-file-url': 'test_value_18',
+ 'pref-dns-result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec-default-action': 'accept',
+ 'socks': 'enable',
+ 'socks-incoming-port': 'test_value_23',
+ 'ssl-algorithm': 'low',
+ 'status': 'enable',
+ 'strict-guest': 'enable',
+ 'trace-auth-no-rsp': 'enable',
+ 'unknown-http-version': 'reject'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'explicit', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_web_proxy_explicit_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_explicit': {
+ 'random_attribute_not_valid': 'tag',
+ 'ftp_incoming_port': 'test_value_3',
+ 'ftp_over_http': 'enable',
+ 'http_incoming_port': 'test_value_5',
+ 'https_incoming_port': 'test_value_6',
+ 'https_replacement_message': 'enable',
+ 'incoming_ip': 'test_value_8',
+ 'incoming_ip6': 'test_value_9',
+ 'ipv6_status': 'enable',
+ 'message_upon_server_error': 'enable',
+ 'outgoing_ip': 'test_value_12',
+ 'outgoing_ip6': 'test_value_13',
+ 'pac_file_data': 'test_value_14',
+ 'pac_file_name': 'test_value_15',
+ 'pac_file_server_port': 'test_value_16',
+ 'pac_file_server_status': 'enable',
+ 'pac_file_url': 'test_value_18',
+ 'pref_dns_result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec_default_action': 'accept',
+ 'socks': 'enable',
+ 'socks_incoming_port': 'test_value_23',
+ 'ssl_algorithm': 'low',
+ 'status': 'enable',
+ 'strict_guest': 'enable',
+ 'trace_auth_no_rsp': 'enable',
+ 'unknown_http_version': 'reject'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_explicit.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'ftp-incoming-port': 'test_value_3',
+ 'ftp-over-http': 'enable',
+ 'http-incoming-port': 'test_value_5',
+ 'https-incoming-port': 'test_value_6',
+ 'https-replacement-message': 'enable',
+ 'incoming-ip': 'test_value_8',
+ 'incoming-ip6': 'test_value_9',
+ 'ipv6-status': 'enable',
+ 'message-upon-server-error': 'enable',
+ 'outgoing-ip': 'test_value_12',
+ 'outgoing-ip6': 'test_value_13',
+ 'pac-file-data': 'test_value_14',
+ 'pac-file-name': 'test_value_15',
+ 'pac-file-server-port': 'test_value_16',
+ 'pac-file-server-status': 'enable',
+ 'pac-file-url': 'test_value_18',
+ 'pref-dns-result': 'ipv4',
+ 'realm': 'test_value_20',
+ 'sec-default-action': 'accept',
+ 'socks': 'enable',
+ 'socks-incoming-port': 'test_value_23',
+ 'ssl-algorithm': 'low',
+ 'status': 'enable',
+ 'strict-guest': 'enable',
+ 'trace-auth-no-rsp': 'enable',
+ 'unknown-http-version': 'reject'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'explicit', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_web_proxy_global.py b/test/units/modules/network/fortios/test_fortios_web_proxy_global.py
new file mode 100644
index 0000000000..24d4236eea
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_web_proxy_global.py
@@ -0,0 +1,247 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_web_proxy_global
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_web_proxy_global.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_web_proxy_global_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_global': {
+ 'fast_policy_match': 'enable',
+ 'forward_proxy_auth': 'enable',
+ 'forward_server_affinity_timeout': '5',
+ 'learn_client_ip': 'enable',
+ 'learn_client_ip_from_header': 'true-client-ip',
+ 'max_message_length': '8',
+ 'max_request_length': '9',
+ 'max_waf_body_cache_length': '10',
+ 'proxy_fqdn': 'test_value_11',
+ 'strict_web_check': 'enable',
+ 'tunnel_non_http': 'enable',
+ 'unknown_http_version': 'reject',
+ 'webproxy_profile': 'test_value_15'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_global.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'fast-policy-match': 'enable',
+ 'forward-proxy-auth': 'enable',
+ 'forward-server-affinity-timeout': '5',
+ 'learn-client-ip': 'enable',
+ 'learn-client-ip-from-header': 'true-client-ip',
+ 'max-message-length': '8',
+ 'max-request-length': '9',
+ 'max-waf-body-cache-length': '10',
+ 'proxy-fqdn': 'test_value_11',
+ 'strict-web-check': 'enable',
+ 'tunnel-non-http': 'enable',
+ 'unknown-http-version': 'reject',
+ 'webproxy-profile': 'test_value_15'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_web_proxy_global_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_global': {
+ 'fast_policy_match': 'enable',
+ 'forward_proxy_auth': 'enable',
+ 'forward_server_affinity_timeout': '5',
+ 'learn_client_ip': 'enable',
+ 'learn_client_ip_from_header': 'true-client-ip',
+ 'max_message_length': '8',
+ 'max_request_length': '9',
+ 'max_waf_body_cache_length': '10',
+ 'proxy_fqdn': 'test_value_11',
+ 'strict_web_check': 'enable',
+ 'tunnel_non_http': 'enable',
+ 'unknown_http_version': 'reject',
+ 'webproxy_profile': 'test_value_15'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_global.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'fast-policy-match': 'enable',
+ 'forward-proxy-auth': 'enable',
+ 'forward-server-affinity-timeout': '5',
+ 'learn-client-ip': 'enable',
+ 'learn-client-ip-from-header': 'true-client-ip',
+ 'max-message-length': '8',
+ 'max-request-length': '9',
+ 'max-waf-body-cache-length': '10',
+ 'proxy-fqdn': 'test_value_11',
+ 'strict-web-check': 'enable',
+ 'tunnel-non-http': 'enable',
+ 'unknown-http-version': 'reject',
+ 'webproxy-profile': 'test_value_15'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_web_proxy_global_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_global': {
+ 'fast_policy_match': 'enable',
+ 'forward_proxy_auth': 'enable',
+ 'forward_server_affinity_timeout': '5',
+ 'learn_client_ip': 'enable',
+ 'learn_client_ip_from_header': 'true-client-ip',
+ 'max_message_length': '8',
+ 'max_request_length': '9',
+ 'max_waf_body_cache_length': '10',
+ 'proxy_fqdn': 'test_value_11',
+ 'strict_web_check': 'enable',
+ 'tunnel_non_http': 'enable',
+ 'unknown_http_version': 'reject',
+ 'webproxy_profile': 'test_value_15'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_global.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'fast-policy-match': 'enable',
+ 'forward-proxy-auth': 'enable',
+ 'forward-server-affinity-timeout': '5',
+ 'learn-client-ip': 'enable',
+ 'learn-client-ip-from-header': 'true-client-ip',
+ 'max-message-length': '8',
+ 'max-request-length': '9',
+ 'max-waf-body-cache-length': '10',
+ 'proxy-fqdn': 'test_value_11',
+ 'strict-web-check': 'enable',
+ 'tunnel-non-http': 'enable',
+ 'unknown-http-version': 'reject',
+ 'webproxy-profile': 'test_value_15'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_web_proxy_global_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_global': {
+ 'random_attribute_not_valid': 'tag',
+ 'fast_policy_match': 'enable',
+ 'forward_proxy_auth': 'enable',
+ 'forward_server_affinity_timeout': '5',
+ 'learn_client_ip': 'enable',
+ 'learn_client_ip_from_header': 'true-client-ip',
+ 'max_message_length': '8',
+ 'max_request_length': '9',
+ 'max_waf_body_cache_length': '10',
+ 'proxy_fqdn': 'test_value_11',
+ 'strict_web_check': 'enable',
+ 'tunnel_non_http': 'enable',
+ 'unknown_http_version': 'reject',
+ 'webproxy_profile': 'test_value_15'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_global.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'fast-policy-match': 'enable',
+ 'forward-proxy-auth': 'enable',
+ 'forward-server-affinity-timeout': '5',
+ 'learn-client-ip': 'enable',
+ 'learn-client-ip-from-header': 'true-client-ip',
+ 'max-message-length': '8',
+ 'max-request-length': '9',
+ 'max-waf-body-cache-length': '10',
+ 'proxy-fqdn': 'test_value_11',
+ 'strict-web-check': 'enable',
+ 'tunnel-non-http': 'enable',
+ 'unknown-http-version': 'reject',
+ 'webproxy-profile': 'test_value_15'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_web_proxy_profile.py b/test/units/modules/network/fortios/test_fortios_web_proxy_profile.py
new file mode 100644
index 0000000000..d401b30116
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_web_proxy_profile.py
@@ -0,0 +1,289 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_web_proxy_profile
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_web_proxy_profile.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_web_proxy_profile_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_profile': {
+ 'header_client_ip': 'pass',
+ 'header_front_end_https': 'pass',
+ 'header_via_request': 'pass',
+ 'header_via_response': 'pass',
+ 'header_x_authenticated_groups': 'pass',
+ 'header_x_authenticated_user': 'pass',
+ 'header_x_forwarded_for': 'pass',
+ 'log_header_change': 'enable',
+ 'name': 'default_name_11',
+ 'strip_encoding': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_profile.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'header-client-ip': 'pass',
+ 'header-front-end-https': 'pass',
+ 'header-via-request': 'pass',
+ 'header-via-response': 'pass',
+ 'header-x-authenticated-groups': 'pass',
+ 'header-x-authenticated-user': 'pass',
+ 'header-x-forwarded-for': 'pass',
+ 'log-header-change': 'enable',
+ 'name': 'default_name_11',
+ 'strip-encoding': 'enable'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_web_proxy_profile_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_profile': {
+ 'header_client_ip': 'pass',
+ 'header_front_end_https': 'pass',
+ 'header_via_request': 'pass',
+ 'header_via_response': 'pass',
+ 'header_x_authenticated_groups': 'pass',
+ 'header_x_authenticated_user': 'pass',
+ 'header_x_forwarded_for': 'pass',
+ 'log_header_change': 'enable',
+ 'name': 'default_name_11',
+ 'strip_encoding': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_profile.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'header-client-ip': 'pass',
+ 'header-front-end-https': 'pass',
+ 'header-via-request': 'pass',
+ 'header-via-response': 'pass',
+ 'header-x-authenticated-groups': 'pass',
+ 'header-x-authenticated-user': 'pass',
+ 'header-x-forwarded-for': 'pass',
+ 'log-header-change': 'enable',
+ 'name': 'default_name_11',
+ 'strip-encoding': 'enable'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_web_proxy_profile_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'web_proxy_profile': {
+ 'header_client_ip': 'pass',
+ 'header_front_end_https': 'pass',
+ 'header_via_request': 'pass',
+ 'header_via_response': 'pass',
+ 'header_x_authenticated_groups': 'pass',
+ 'header_x_authenticated_user': 'pass',
+ 'header_x_forwarded_for': 'pass',
+ 'log_header_change': 'enable',
+ 'name': 'default_name_11',
+ 'strip_encoding': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_profile.fortios_web_proxy(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('web-proxy', 'profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_web_proxy_profile_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'web_proxy_profile': {
+ 'header_client_ip': 'pass',
+ 'header_front_end_https': 'pass',
+ 'header_via_request': 'pass',
+ 'header_via_response': 'pass',
+ 'header_x_authenticated_groups': 'pass',
+ 'header_x_authenticated_user': 'pass',
+ 'header_x_forwarded_for': 'pass',
+ 'log_header_change': 'enable',
+ 'name': 'default_name_11',
+ 'strip_encoding': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_profile.fortios_web_proxy(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('web-proxy', 'profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_web_proxy_profile_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_profile': {
+ 'header_client_ip': 'pass',
+ 'header_front_end_https': 'pass',
+ 'header_via_request': 'pass',
+ 'header_via_response': 'pass',
+ 'header_x_authenticated_groups': 'pass',
+ 'header_x_authenticated_user': 'pass',
+ 'header_x_forwarded_for': 'pass',
+ 'log_header_change': 'enable',
+ 'name': 'default_name_11',
+ 'strip_encoding': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_profile.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'header-client-ip': 'pass',
+ 'header-front-end-https': 'pass',
+ 'header-via-request': 'pass',
+ 'header-via-response': 'pass',
+ 'header-x-authenticated-groups': 'pass',
+ 'header-x-authenticated-user': 'pass',
+ 'header-x-forwarded-for': 'pass',
+ 'log-header-change': 'enable',
+ 'name': 'default_name_11',
+ 'strip-encoding': 'enable'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_web_proxy_profile_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'web_proxy_profile': {
+ 'random_attribute_not_valid': 'tag',
+ 'header_client_ip': 'pass',
+ 'header_front_end_https': 'pass',
+ 'header_via_request': 'pass',
+ 'header_via_response': 'pass',
+ 'header_x_authenticated_groups': 'pass',
+ 'header_x_authenticated_user': 'pass',
+ 'header_x_forwarded_for': 'pass',
+ 'log_header_change': 'enable',
+ 'name': 'default_name_11',
+ 'strip_encoding': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_web_proxy_profile.fortios_web_proxy(input_data, fos_instance)
+
+ expected_data = {
+ 'header-client-ip': 'pass',
+ 'header-front-end-https': 'pass',
+ 'header-via-request': 'pass',
+ 'header-via-response': 'pass',
+ 'header-x-authenticated-groups': 'pass',
+ 'header-x-authenticated-user': 'pass',
+ 'header-x-forwarded-for': 'pass',
+ 'log-header-change': 'enable',
+ 'name': 'default_name_11',
+ 'strip-encoding': 'enable'
+ }
+
+ set_method_mock.assert_called_with('web-proxy', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_fortiguard.py b/test/units/modules/network/fortios/test_fortios_webfilter_fortiguard.py
new file mode 100644
index 0000000000..f46455ec2e
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_fortiguard.py
@@ -0,0 +1,231 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_fortiguard
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_fortiguard.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_fortiguard_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_fortiguard': {
+ 'cache_mem_percent': '3',
+ 'cache_mode': 'ttl',
+ 'cache_prefix_match': 'enable',
+ 'close_ports': 'enable',
+ 'ovrd_auth_https': 'enable',
+ 'ovrd_auth_port': '8',
+ 'ovrd_auth_port_http': '9',
+ 'ovrd_auth_port_https': '10',
+ 'ovrd_auth_port_warning': '11',
+ 'request_packet_size_limit': '12',
+ 'warn_auth_https': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_fortiguard.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'cache-mem-percent': '3',
+ 'cache-mode': 'ttl',
+ 'cache-prefix-match': 'enable',
+ 'close-ports': 'enable',
+ 'ovrd-auth-https': 'enable',
+ 'ovrd-auth-port': '8',
+ 'ovrd-auth-port-http': '9',
+ 'ovrd-auth-port-https': '10',
+ 'ovrd-auth-port-warning': '11',
+ 'request-packet-size-limit': '12',
+ 'warn-auth-https': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'fortiguard', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_fortiguard_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_fortiguard': {
+ 'cache_mem_percent': '3',
+ 'cache_mode': 'ttl',
+ 'cache_prefix_match': 'enable',
+ 'close_ports': 'enable',
+ 'ovrd_auth_https': 'enable',
+ 'ovrd_auth_port': '8',
+ 'ovrd_auth_port_http': '9',
+ 'ovrd_auth_port_https': '10',
+ 'ovrd_auth_port_warning': '11',
+ 'request_packet_size_limit': '12',
+ 'warn_auth_https': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_fortiguard.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'cache-mem-percent': '3',
+ 'cache-mode': 'ttl',
+ 'cache-prefix-match': 'enable',
+ 'close-ports': 'enable',
+ 'ovrd-auth-https': 'enable',
+ 'ovrd-auth-port': '8',
+ 'ovrd-auth-port-http': '9',
+ 'ovrd-auth-port-https': '10',
+ 'ovrd-auth-port-warning': '11',
+ 'request-packet-size-limit': '12',
+ 'warn-auth-https': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'fortiguard', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_fortiguard_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_fortiguard': {
+ 'cache_mem_percent': '3',
+ 'cache_mode': 'ttl',
+ 'cache_prefix_match': 'enable',
+ 'close_ports': 'enable',
+ 'ovrd_auth_https': 'enable',
+ 'ovrd_auth_port': '8',
+ 'ovrd_auth_port_http': '9',
+ 'ovrd_auth_port_https': '10',
+ 'ovrd_auth_port_warning': '11',
+ 'request_packet_size_limit': '12',
+ 'warn_auth_https': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_fortiguard.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'cache-mem-percent': '3',
+ 'cache-mode': 'ttl',
+ 'cache-prefix-match': 'enable',
+ 'close-ports': 'enable',
+ 'ovrd-auth-https': 'enable',
+ 'ovrd-auth-port': '8',
+ 'ovrd-auth-port-http': '9',
+ 'ovrd-auth-port-https': '10',
+ 'ovrd-auth-port-warning': '11',
+ 'request-packet-size-limit': '12',
+ 'warn-auth-https': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'fortiguard', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_fortiguard_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_fortiguard': {
+ 'random_attribute_not_valid': 'tag',
+ 'cache_mem_percent': '3',
+ 'cache_mode': 'ttl',
+ 'cache_prefix_match': 'enable',
+ 'close_ports': 'enable',
+ 'ovrd_auth_https': 'enable',
+ 'ovrd_auth_port': '8',
+ 'ovrd_auth_port_http': '9',
+ 'ovrd_auth_port_https': '10',
+ 'ovrd_auth_port_warning': '11',
+ 'request_packet_size_limit': '12',
+ 'warn_auth_https': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_fortiguard.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'cache-mem-percent': '3',
+ 'cache-mode': 'ttl',
+ 'cache-prefix-match': 'enable',
+ 'close-ports': 'enable',
+ 'ovrd-auth-https': 'enable',
+ 'ovrd-auth-port': '8',
+ 'ovrd-auth-port-http': '9',
+ 'ovrd-auth-port-https': '10',
+ 'ovrd-auth-port-warning': '11',
+ 'request-packet-size-limit': '12',
+ 'warn-auth-https': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'fortiguard', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_cat.py b/test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_cat.py
new file mode 100644
index 0000000000..ae1374a400
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_cat.py
@@ -0,0 +1,219 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_ftgd_local_cat
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_ftgd_local_cat.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_ftgd_local_cat_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_cat': {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_cat.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-cat', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ftgd_local_cat_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_cat': {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_cat.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-cat', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ftgd_local_cat_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_ftgd_local_cat': {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_cat.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'ftgd-local-cat', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ftgd_local_cat_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_ftgd_local_cat': {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_cat.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'ftgd-local-cat', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ftgd_local_cat_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_cat': {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_cat.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-cat', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_ftgd_local_cat_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_cat': {
+ 'random_attribute_not_valid': 'tag',
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_cat.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'desc': 'test_value_3',
+ 'id': '4',
+ 'status': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-cat', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_rating.py b/test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_rating.py
new file mode 100644
index 0000000000..377ada0958
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_ftgd_local_rating.py
@@ -0,0 +1,219 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_ftgd_local_rating
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_ftgd_local_rating.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_ftgd_local_rating_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_rating': {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_rating.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-rating', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ftgd_local_rating_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_rating': {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_rating.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-rating', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ftgd_local_rating_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_ftgd_local_rating': {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_rating.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'ftgd-local-rating', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ftgd_local_rating_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_ftgd_local_rating': {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_rating.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'ftgd-local-rating', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ftgd_local_rating_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_rating': {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_rating.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-rating', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_ftgd_local_rating_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ftgd_local_rating': {
+ 'random_attribute_not_valid': 'tag',
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ftgd_local_rating.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'rating': 'test_value_3',
+ 'status': 'enable',
+ 'url': 'myurl_5.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ftgd-local-rating', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_cache_setting.py b/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_cache_setting.py
new file mode 100644
index 0000000000..688afd3edd
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_cache_setting.py
@@ -0,0 +1,159 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_ips_urlfilter_cache_setting
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_ips_urlfilter_cache_setting.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_ips_urlfilter_cache_setting_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_cache_setting': {
+ 'dns_retry_interval': '3',
+ 'extended_ttl': '4'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_cache_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'dns-retry-interval': '3',
+ 'extended-ttl': '4'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-cache-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ips_urlfilter_cache_setting_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_cache_setting': {
+ 'dns_retry_interval': '3',
+ 'extended_ttl': '4'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_cache_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'dns-retry-interval': '3',
+ 'extended-ttl': '4'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-cache-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ips_urlfilter_cache_setting_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_cache_setting': {
+ 'dns_retry_interval': '3',
+ 'extended_ttl': '4'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_cache_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'dns-retry-interval': '3',
+ 'extended-ttl': '4'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-cache-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_ips_urlfilter_cache_setting_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_cache_setting': {
+ 'random_attribute_not_valid': 'tag',
+ 'dns_retry_interval': '3',
+ 'extended_ttl': '4'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_cache_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'dns-retry-interval': '3',
+ 'extended-ttl': '4'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-cache-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting.py b/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting.py
new file mode 100644
index 0000000000..d79a65760c
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting.py
@@ -0,0 +1,175 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_ips_urlfilter_setting
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_ips_urlfilter_setting.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_ips_urlfilter_setting_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting': {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ips_urlfilter_setting_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting': {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ips_urlfilter_setting_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting': {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_ips_urlfilter_setting_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting': {
+ 'random_attribute_not_valid': 'tag',
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting6.py b/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting6.py
new file mode 100644
index 0000000000..32b7006391
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_ips_urlfilter_setting6.py
@@ -0,0 +1,175 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_ips_urlfilter_setting6
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_ips_urlfilter_setting6.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_ips_urlfilter_setting6_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting6': {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting6.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting6', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_ips_urlfilter_setting6_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting6': {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting6.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting6', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_ips_urlfilter_setting6_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting6': {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting6.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting6', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_ips_urlfilter_setting6_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_ips_urlfilter_setting6': {
+ 'random_attribute_not_valid': 'tag',
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo_filter': 'test_value_6'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_ips_urlfilter_setting6.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'device': 'test_value_3',
+ 'distance': '4',
+ 'gateway6': 'test_value_5',
+ 'geo-filter': 'test_value_6'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'ips-urlfilter-setting6', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_override.py b/test/units/modules/network/fortios/test_fortios_webfilter_override.py
new file mode 100644
index 0000000000..0594217dc7
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_override.py
@@ -0,0 +1,299 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_override
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_override.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_override_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_override': {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new_profile': 'test_value_8',
+ 'old_profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user_group': 'test_value_13'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_override.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new-profile': 'test_value_8',
+ 'old-profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user-group': 'test_value_13'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'override', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_override_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_override': {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new_profile': 'test_value_8',
+ 'old_profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user_group': 'test_value_13'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_override.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new-profile': 'test_value_8',
+ 'old-profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user-group': 'test_value_13'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'override', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_override_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_override': {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new_profile': 'test_value_8',
+ 'old_profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user_group': 'test_value_13'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_override.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'override', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_override_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_override': {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new_profile': 'test_value_8',
+ 'old_profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user_group': 'test_value_13'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_override.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'override', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_override_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_override': {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new_profile': 'test_value_8',
+ 'old_profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user_group': 'test_value_13'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_override.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new-profile': 'test_value_8',
+ 'old-profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user-group': 'test_value_13'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'override', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_override_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_override': {
+ 'random_attribute_not_valid': 'tag',
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new_profile': 'test_value_8',
+ 'old_profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user_group': 'test_value_13'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_override.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'expires': 'test_value_3',
+ 'id': '4',
+ 'initiator': 'test_value_5',
+ 'ip': 'test_value_6',
+ 'ip6': 'test_value_7',
+ 'new-profile': 'test_value_8',
+ 'old-profile': 'test_value_9',
+ 'scope': 'user',
+ 'status': 'enable',
+ 'user': 'test_value_12',
+ 'user-group': 'test_value_13'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'override', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_profile.py b/test/units/modules/network/fortios/test_fortios_webfilter_profile.py
new file mode 100644
index 0000000000..07efbfcbd5
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_profile.py
@@ -0,0 +1,479 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_profile
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_profile.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_profile_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_profile': {
+ 'comment': 'Optional comments.',
+ 'extended_log': 'enable',
+ 'https_replacemsg': 'enable',
+ 'inspection_mode': 'proxy',
+ 'log_all_url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd_perm': 'bannedword-override',
+ 'post_action': 'normal',
+ 'replacemsg_group': 'test_value_12',
+ 'web_content_log': 'enable',
+ 'web_extended_all_action_log': 'enable',
+ 'web_filter_activex_log': 'enable',
+ 'web_filter_applet_log': 'enable',
+ 'web_filter_command_block_log': 'enable',
+ 'web_filter_cookie_log': 'enable',
+ 'web_filter_cookie_removal_log': 'enable',
+ 'web_filter_js_log': 'enable',
+ 'web_filter_jscript_log': 'enable',
+ 'web_filter_referer_log': 'enable',
+ 'web_filter_unknown_log': 'enable',
+ 'web_filter_vbs_log': 'enable',
+ 'web_ftgd_err_log': 'enable',
+ 'web_ftgd_quota_usage': 'enable',
+ 'web_invalid_domain_log': 'enable',
+ 'web_url_log': 'enable',
+ 'wisp': 'enable',
+ 'wisp_algorithm': 'primary-secondary',
+ 'youtube_channel_status': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_profile.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'extended-log': 'enable',
+ 'https-replacemsg': 'enable',
+ 'inspection-mode': 'proxy',
+ 'log-all-url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd-perm': 'bannedword-override',
+ 'post-action': 'normal',
+ 'replacemsg-group': 'test_value_12',
+ 'web-content-log': 'enable',
+ 'web-extended-all-action-log': 'enable',
+ 'web-filter-activex-log': 'enable',
+ 'web-filter-applet-log': 'enable',
+ 'web-filter-command-block-log': 'enable',
+ 'web-filter-cookie-log': 'enable',
+ 'web-filter-cookie-removal-log': 'enable',
+ 'web-filter-js-log': 'enable',
+ 'web-filter-jscript-log': 'enable',
+ 'web-filter-referer-log': 'enable',
+ 'web-filter-unknown-log': 'enable',
+ 'web-filter-vbs-log': 'enable',
+ 'web-ftgd-err-log': 'enable',
+ 'web-ftgd-quota-usage': 'enable',
+ 'web-invalid-domain-log': 'enable',
+ 'web-url-log': 'enable',
+ 'wisp': 'enable',
+ 'wisp-algorithm': 'primary-secondary',
+ 'youtube-channel-status': 'disable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_profile_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_profile': {
+ 'comment': 'Optional comments.',
+ 'extended_log': 'enable',
+ 'https_replacemsg': 'enable',
+ 'inspection_mode': 'proxy',
+ 'log_all_url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd_perm': 'bannedword-override',
+ 'post_action': 'normal',
+ 'replacemsg_group': 'test_value_12',
+ 'web_content_log': 'enable',
+ 'web_extended_all_action_log': 'enable',
+ 'web_filter_activex_log': 'enable',
+ 'web_filter_applet_log': 'enable',
+ 'web_filter_command_block_log': 'enable',
+ 'web_filter_cookie_log': 'enable',
+ 'web_filter_cookie_removal_log': 'enable',
+ 'web_filter_js_log': 'enable',
+ 'web_filter_jscript_log': 'enable',
+ 'web_filter_referer_log': 'enable',
+ 'web_filter_unknown_log': 'enable',
+ 'web_filter_vbs_log': 'enable',
+ 'web_ftgd_err_log': 'enable',
+ 'web_ftgd_quota_usage': 'enable',
+ 'web_invalid_domain_log': 'enable',
+ 'web_url_log': 'enable',
+ 'wisp': 'enable',
+ 'wisp_algorithm': 'primary-secondary',
+ 'youtube_channel_status': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_profile.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'extended-log': 'enable',
+ 'https-replacemsg': 'enable',
+ 'inspection-mode': 'proxy',
+ 'log-all-url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd-perm': 'bannedword-override',
+ 'post-action': 'normal',
+ 'replacemsg-group': 'test_value_12',
+ 'web-content-log': 'enable',
+ 'web-extended-all-action-log': 'enable',
+ 'web-filter-activex-log': 'enable',
+ 'web-filter-applet-log': 'enable',
+ 'web-filter-command-block-log': 'enable',
+ 'web-filter-cookie-log': 'enable',
+ 'web-filter-cookie-removal-log': 'enable',
+ 'web-filter-js-log': 'enable',
+ 'web-filter-jscript-log': 'enable',
+ 'web-filter-referer-log': 'enable',
+ 'web-filter-unknown-log': 'enable',
+ 'web-filter-vbs-log': 'enable',
+ 'web-ftgd-err-log': 'enable',
+ 'web-ftgd-quota-usage': 'enable',
+ 'web-invalid-domain-log': 'enable',
+ 'web-url-log': 'enable',
+ 'wisp': 'enable',
+ 'wisp-algorithm': 'primary-secondary',
+ 'youtube-channel-status': 'disable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_profile_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_profile': {
+ 'comment': 'Optional comments.',
+ 'extended_log': 'enable',
+ 'https_replacemsg': 'enable',
+ 'inspection_mode': 'proxy',
+ 'log_all_url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd_perm': 'bannedword-override',
+ 'post_action': 'normal',
+ 'replacemsg_group': 'test_value_12',
+ 'web_content_log': 'enable',
+ 'web_extended_all_action_log': 'enable',
+ 'web_filter_activex_log': 'enable',
+ 'web_filter_applet_log': 'enable',
+ 'web_filter_command_block_log': 'enable',
+ 'web_filter_cookie_log': 'enable',
+ 'web_filter_cookie_removal_log': 'enable',
+ 'web_filter_js_log': 'enable',
+ 'web_filter_jscript_log': 'enable',
+ 'web_filter_referer_log': 'enable',
+ 'web_filter_unknown_log': 'enable',
+ 'web_filter_vbs_log': 'enable',
+ 'web_ftgd_err_log': 'enable',
+ 'web_ftgd_quota_usage': 'enable',
+ 'web_invalid_domain_log': 'enable',
+ 'web_url_log': 'enable',
+ 'wisp': 'enable',
+ 'wisp_algorithm': 'primary-secondary',
+ 'youtube_channel_status': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_profile.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_profile_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_profile': {
+ 'comment': 'Optional comments.',
+ 'extended_log': 'enable',
+ 'https_replacemsg': 'enable',
+ 'inspection_mode': 'proxy',
+ 'log_all_url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd_perm': 'bannedword-override',
+ 'post_action': 'normal',
+ 'replacemsg_group': 'test_value_12',
+ 'web_content_log': 'enable',
+ 'web_extended_all_action_log': 'enable',
+ 'web_filter_activex_log': 'enable',
+ 'web_filter_applet_log': 'enable',
+ 'web_filter_command_block_log': 'enable',
+ 'web_filter_cookie_log': 'enable',
+ 'web_filter_cookie_removal_log': 'enable',
+ 'web_filter_js_log': 'enable',
+ 'web_filter_jscript_log': 'enable',
+ 'web_filter_referer_log': 'enable',
+ 'web_filter_unknown_log': 'enable',
+ 'web_filter_vbs_log': 'enable',
+ 'web_ftgd_err_log': 'enable',
+ 'web_ftgd_quota_usage': 'enable',
+ 'web_invalid_domain_log': 'enable',
+ 'web_url_log': 'enable',
+ 'wisp': 'enable',
+ 'wisp_algorithm': 'primary-secondary',
+ 'youtube_channel_status': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_profile.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_profile_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_profile': {
+ 'comment': 'Optional comments.',
+ 'extended_log': 'enable',
+ 'https_replacemsg': 'enable',
+ 'inspection_mode': 'proxy',
+ 'log_all_url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd_perm': 'bannedword-override',
+ 'post_action': 'normal',
+ 'replacemsg_group': 'test_value_12',
+ 'web_content_log': 'enable',
+ 'web_extended_all_action_log': 'enable',
+ 'web_filter_activex_log': 'enable',
+ 'web_filter_applet_log': 'enable',
+ 'web_filter_command_block_log': 'enable',
+ 'web_filter_cookie_log': 'enable',
+ 'web_filter_cookie_removal_log': 'enable',
+ 'web_filter_js_log': 'enable',
+ 'web_filter_jscript_log': 'enable',
+ 'web_filter_referer_log': 'enable',
+ 'web_filter_unknown_log': 'enable',
+ 'web_filter_vbs_log': 'enable',
+ 'web_ftgd_err_log': 'enable',
+ 'web_ftgd_quota_usage': 'enable',
+ 'web_invalid_domain_log': 'enable',
+ 'web_url_log': 'enable',
+ 'wisp': 'enable',
+ 'wisp_algorithm': 'primary-secondary',
+ 'youtube_channel_status': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_profile.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'extended-log': 'enable',
+ 'https-replacemsg': 'enable',
+ 'inspection-mode': 'proxy',
+ 'log-all-url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd-perm': 'bannedword-override',
+ 'post-action': 'normal',
+ 'replacemsg-group': 'test_value_12',
+ 'web-content-log': 'enable',
+ 'web-extended-all-action-log': 'enable',
+ 'web-filter-activex-log': 'enable',
+ 'web-filter-applet-log': 'enable',
+ 'web-filter-command-block-log': 'enable',
+ 'web-filter-cookie-log': 'enable',
+ 'web-filter-cookie-removal-log': 'enable',
+ 'web-filter-js-log': 'enable',
+ 'web-filter-jscript-log': 'enable',
+ 'web-filter-referer-log': 'enable',
+ 'web-filter-unknown-log': 'enable',
+ 'web-filter-vbs-log': 'enable',
+ 'web-ftgd-err-log': 'enable',
+ 'web-ftgd-quota-usage': 'enable',
+ 'web-invalid-domain-log': 'enable',
+ 'web-url-log': 'enable',
+ 'wisp': 'enable',
+ 'wisp-algorithm': 'primary-secondary',
+ 'youtube-channel-status': 'disable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_profile_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_profile': {
+ 'random_attribute_not_valid': 'tag',
+ 'comment': 'Optional comments.',
+ 'extended_log': 'enable',
+ 'https_replacemsg': 'enable',
+ 'inspection_mode': 'proxy',
+ 'log_all_url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd_perm': 'bannedword-override',
+ 'post_action': 'normal',
+ 'replacemsg_group': 'test_value_12',
+ 'web_content_log': 'enable',
+ 'web_extended_all_action_log': 'enable',
+ 'web_filter_activex_log': 'enable',
+ 'web_filter_applet_log': 'enable',
+ 'web_filter_command_block_log': 'enable',
+ 'web_filter_cookie_log': 'enable',
+ 'web_filter_cookie_removal_log': 'enable',
+ 'web_filter_js_log': 'enable',
+ 'web_filter_jscript_log': 'enable',
+ 'web_filter_referer_log': 'enable',
+ 'web_filter_unknown_log': 'enable',
+ 'web_filter_vbs_log': 'enable',
+ 'web_ftgd_err_log': 'enable',
+ 'web_ftgd_quota_usage': 'enable',
+ 'web_invalid_domain_log': 'enable',
+ 'web_url_log': 'enable',
+ 'wisp': 'enable',
+ 'wisp_algorithm': 'primary-secondary',
+ 'youtube_channel_status': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_profile.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'extended-log': 'enable',
+ 'https-replacemsg': 'enable',
+ 'inspection-mode': 'proxy',
+ 'log-all-url': 'enable',
+ 'name': 'default_name_8',
+ 'options': 'activexfilter',
+ 'ovrd-perm': 'bannedword-override',
+ 'post-action': 'normal',
+ 'replacemsg-group': 'test_value_12',
+ 'web-content-log': 'enable',
+ 'web-extended-all-action-log': 'enable',
+ 'web-filter-activex-log': 'enable',
+ 'web-filter-applet-log': 'enable',
+ 'web-filter-command-block-log': 'enable',
+ 'web-filter-cookie-log': 'enable',
+ 'web-filter-cookie-removal-log': 'enable',
+ 'web-filter-js-log': 'enable',
+ 'web-filter-jscript-log': 'enable',
+ 'web-filter-referer-log': 'enable',
+ 'web-filter-unknown-log': 'enable',
+ 'web-filter-vbs-log': 'enable',
+ 'web-ftgd-err-log': 'enable',
+ 'web-ftgd-quota-usage': 'enable',
+ 'web-invalid-domain-log': 'enable',
+ 'web-url-log': 'enable',
+ 'wisp': 'enable',
+ 'wisp-algorithm': 'primary-secondary',
+ 'youtube-channel-status': 'disable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_search_engine.py b/test/units/modules/network/fortios/test_fortios_webfilter_search_engine.py
new file mode 100644
index 0000000000..ef6cd8a47a
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_search_engine.py
@@ -0,0 +1,259 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_search_engine
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_search_engine.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_search_engine_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_search_engine': {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch_str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_search_engine.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch-str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'search-engine', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_search_engine_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_search_engine': {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch_str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_search_engine.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch-str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'search-engine', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_search_engine_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_search_engine': {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch_str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_search_engine.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'search-engine', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_search_engine_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_search_engine': {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch_str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_search_engine.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'search-engine', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_search_engine_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_search_engine': {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch_str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_search_engine.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch-str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'search-engine', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_search_engine_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_search_engine': {
+ 'random_attribute_not_valid': 'tag',
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch_str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_search_engine.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'charset': 'utf-8',
+ 'hostname': 'myhostname4',
+ 'name': 'default_name_5',
+ 'query': 'test_value_6',
+ 'safesearch': 'disable',
+ 'safesearch-str': 'test_value_8',
+ 'url': 'myurl_9.com'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'search-engine', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_webfilter_urlfilter.py b/test/units/modules/network/fortios/test_fortios_webfilter_urlfilter.py
new file mode 100644
index 0000000000..2272b0af7c
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_webfilter_urlfilter.py
@@ -0,0 +1,239 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_webfilter_urlfilter
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_webfilter_urlfilter.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_webfilter_urlfilter_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_urlfilter': {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip_addr_block': 'enable',
+ 'name': 'default_name_6',
+ 'one_arm_ips_urlfilter': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_urlfilter.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip-addr-block': 'enable',
+ 'name': 'default_name_6',
+ 'one-arm-ips-urlfilter': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'urlfilter', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_urlfilter_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_urlfilter': {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip_addr_block': 'enable',
+ 'name': 'default_name_6',
+ 'one_arm_ips_urlfilter': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_urlfilter.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip-addr-block': 'enable',
+ 'name': 'default_name_6',
+ 'one-arm-ips-urlfilter': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'urlfilter', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_urlfilter_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_urlfilter': {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip_addr_block': 'enable',
+ 'name': 'default_name_6',
+ 'one_arm_ips_urlfilter': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_urlfilter.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'urlfilter', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_webfilter_urlfilter_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'webfilter_urlfilter': {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip_addr_block': 'enable',
+ 'name': 'default_name_6',
+ 'one_arm_ips_urlfilter': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_urlfilter.fortios_webfilter(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('webfilter', 'urlfilter', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_webfilter_urlfilter_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_urlfilter': {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip_addr_block': 'enable',
+ 'name': 'default_name_6',
+ 'one_arm_ips_urlfilter': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_urlfilter.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip-addr-block': 'enable',
+ 'name': 'default_name_6',
+ 'one-arm-ips-urlfilter': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'urlfilter', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_webfilter_urlfilter_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'webfilter_urlfilter': {
+ 'random_attribute_not_valid': 'tag',
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip_addr_block': 'enable',
+ 'name': 'default_name_6',
+ 'one_arm_ips_urlfilter': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_webfilter_urlfilter.fortios_webfilter(input_data, fos_instance)
+
+ expected_data = {
+ 'comment': 'Optional comments.',
+ 'id': '4',
+ 'ip-addr-block': 'enable',
+ 'name': 'default_name_6',
+ 'one-arm-ips-urlfilter': 'enable'
+ }
+
+ set_method_mock.assert_called_with('webfilter', 'urlfilter', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_global.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_global.py
new file mode 100644
index 0000000000..50cc589823
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_global.py
@@ -0,0 +1,279 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_global
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_global.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_global_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_global': {
+ 'ap_log_server': 'enable',
+ 'ap_log_server_ip': 'test_value_4',
+ 'ap_log_server_port': '5',
+ 'control_message_offload': 'ebp-frame',
+ 'data_ethernet_II': 'enable',
+ 'discovery_mc_addr': 'test_value_8',
+ 'fiapp_eth_type': '9',
+ 'image_download': 'enable',
+ 'ipsec_base_ip': 'test_value_11',
+ 'link_aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max_clients': '14',
+ 'max_retransmit': '15',
+ 'mesh_eth_type': '16',
+ 'name': 'default_name_17',
+ 'rogue_scan_mac_adjacency': '18',
+ 'wtp_share': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_global.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-log-server': 'enable',
+ 'ap-log-server-ip': 'test_value_4',
+ 'ap-log-server-port': '5',
+ 'control-message-offload': 'ebp-frame',
+ 'data-ethernet-II': 'enable',
+ 'discovery-mc-addr': 'test_value_8',
+ 'fiapp-eth-type': '9',
+ 'image-download': 'enable',
+ 'ipsec-base-ip': 'test_value_11',
+ 'link-aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max-clients': '14',
+ 'max-retransmit': '15',
+ 'mesh-eth-type': '16',
+ 'name': 'default_name_17',
+ 'rogue-scan-mac-adjacency': '18',
+ 'wtp-share': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_global_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_global': {
+ 'ap_log_server': 'enable',
+ 'ap_log_server_ip': 'test_value_4',
+ 'ap_log_server_port': '5',
+ 'control_message_offload': 'ebp-frame',
+ 'data_ethernet_II': 'enable',
+ 'discovery_mc_addr': 'test_value_8',
+ 'fiapp_eth_type': '9',
+ 'image_download': 'enable',
+ 'ipsec_base_ip': 'test_value_11',
+ 'link_aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max_clients': '14',
+ 'max_retransmit': '15',
+ 'mesh_eth_type': '16',
+ 'name': 'default_name_17',
+ 'rogue_scan_mac_adjacency': '18',
+ 'wtp_share': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_global.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-log-server': 'enable',
+ 'ap-log-server-ip': 'test_value_4',
+ 'ap-log-server-port': '5',
+ 'control-message-offload': 'ebp-frame',
+ 'data-ethernet-II': 'enable',
+ 'discovery-mc-addr': 'test_value_8',
+ 'fiapp-eth-type': '9',
+ 'image-download': 'enable',
+ 'ipsec-base-ip': 'test_value_11',
+ 'link-aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max-clients': '14',
+ 'max-retransmit': '15',
+ 'mesh-eth-type': '16',
+ 'name': 'default_name_17',
+ 'rogue-scan-mac-adjacency': '18',
+ 'wtp-share': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_global_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_global': {
+ 'ap_log_server': 'enable',
+ 'ap_log_server_ip': 'test_value_4',
+ 'ap_log_server_port': '5',
+ 'control_message_offload': 'ebp-frame',
+ 'data_ethernet_II': 'enable',
+ 'discovery_mc_addr': 'test_value_8',
+ 'fiapp_eth_type': '9',
+ 'image_download': 'enable',
+ 'ipsec_base_ip': 'test_value_11',
+ 'link_aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max_clients': '14',
+ 'max_retransmit': '15',
+ 'mesh_eth_type': '16',
+ 'name': 'default_name_17',
+ 'rogue_scan_mac_adjacency': '18',
+ 'wtp_share': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_global.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-log-server': 'enable',
+ 'ap-log-server-ip': 'test_value_4',
+ 'ap-log-server-port': '5',
+ 'control-message-offload': 'ebp-frame',
+ 'data-ethernet-II': 'enable',
+ 'discovery-mc-addr': 'test_value_8',
+ 'fiapp-eth-type': '9',
+ 'image-download': 'enable',
+ 'ipsec-base-ip': 'test_value_11',
+ 'link-aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max-clients': '14',
+ 'max-retransmit': '15',
+ 'mesh-eth-type': '16',
+ 'name': 'default_name_17',
+ 'rogue-scan-mac-adjacency': '18',
+ 'wtp-share': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_global_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_global': {
+ 'random_attribute_not_valid': 'tag',
+ 'ap_log_server': 'enable',
+ 'ap_log_server_ip': 'test_value_4',
+ 'ap_log_server_port': '5',
+ 'control_message_offload': 'ebp-frame',
+ 'data_ethernet_II': 'enable',
+ 'discovery_mc_addr': 'test_value_8',
+ 'fiapp_eth_type': '9',
+ 'image_download': 'enable',
+ 'ipsec_base_ip': 'test_value_11',
+ 'link_aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max_clients': '14',
+ 'max_retransmit': '15',
+ 'mesh_eth_type': '16',
+ 'name': 'default_name_17',
+ 'rogue_scan_mac_adjacency': '18',
+ 'wtp_share': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_global.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-log-server': 'enable',
+ 'ap-log-server-ip': 'test_value_4',
+ 'ap-log-server-port': '5',
+ 'control-message-offload': 'ebp-frame',
+ 'data-ethernet-II': 'enable',
+ 'discovery-mc-addr': 'test_value_8',
+ 'fiapp-eth-type': '9',
+ 'image-download': 'enable',
+ 'ipsec-base-ip': 'test_value_11',
+ 'link-aggregation': 'enable',
+ 'location': 'test_value_13',
+ 'max-clients': '14',
+ 'max-retransmit': '15',
+ 'mesh-eth-type': '16',
+ 'name': 'default_name_17',
+ 'rogue-scan-mac-adjacency': '18',
+ 'wtp-share': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'global', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_setting.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_setting.py
new file mode 100644
index 0000000000..5be01593a2
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_setting.py
@@ -0,0 +1,175 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_setting
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_setting.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_setting_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_setting': {
+ 'account_id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate_ssid': 'enable',
+ 'fapc_compatibility': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_setting.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'account-id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate-ssid': 'enable',
+ 'fapc-compatibility': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_setting_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_setting': {
+ 'account_id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate_ssid': 'enable',
+ 'fapc_compatibility': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_setting.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'account-id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate-ssid': 'enable',
+ 'fapc-compatibility': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_setting_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_setting': {
+ 'account_id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate_ssid': 'enable',
+ 'fapc_compatibility': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_setting.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'account-id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate-ssid': 'enable',
+ 'fapc-compatibility': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_setting_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_setting': {
+ 'random_attribute_not_valid': 'tag',
+ 'account_id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate_ssid': 'enable',
+ 'fapc_compatibility': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_setting.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'account-id': 'test_value_3',
+ 'country': 'NA',
+ 'duplicate-ssid': 'enable',
+ 'fapc-compatibility': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'setting', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_utm_profile.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_utm_profile.py
new file mode 100644
index 0000000000..6af88cad6a
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_utm_profile.py
@@ -0,0 +1,269 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_utm_profile
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_utm_profile.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_utm_profile_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_utm_profile': {
+ 'antivirus_profile': 'test_value_3',
+ 'application_list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips_sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan_botnet_connections': 'disable',
+ 'utm_log': 'enable',
+ 'webfilter_profile': 'test_value_10'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_utm_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'antivirus-profile': 'test_value_3',
+ 'application-list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips-sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan-botnet-connections': 'disable',
+ 'utm-log': 'enable',
+ 'webfilter-profile': 'test_value_10'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'utm-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_utm_profile_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_utm_profile': {
+ 'antivirus_profile': 'test_value_3',
+ 'application_list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips_sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan_botnet_connections': 'disable',
+ 'utm_log': 'enable',
+ 'webfilter_profile': 'test_value_10'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_utm_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'antivirus-profile': 'test_value_3',
+ 'application-list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips-sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan-botnet-connections': 'disable',
+ 'utm-log': 'enable',
+ 'webfilter-profile': 'test_value_10'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'utm-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_utm_profile_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_utm_profile': {
+ 'antivirus_profile': 'test_value_3',
+ 'application_list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips_sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan_botnet_connections': 'disable',
+ 'utm_log': 'enable',
+ 'webfilter_profile': 'test_value_10'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_utm_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'utm-profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_utm_profile_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_utm_profile': {
+ 'antivirus_profile': 'test_value_3',
+ 'application_list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips_sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan_botnet_connections': 'disable',
+ 'utm_log': 'enable',
+ 'webfilter_profile': 'test_value_10'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_utm_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'utm-profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_utm_profile_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_utm_profile': {
+ 'antivirus_profile': 'test_value_3',
+ 'application_list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips_sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan_botnet_connections': 'disable',
+ 'utm_log': 'enable',
+ 'webfilter_profile': 'test_value_10'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_utm_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'antivirus-profile': 'test_value_3',
+ 'application-list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips-sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan-botnet-connections': 'disable',
+ 'utm-log': 'enable',
+ 'webfilter-profile': 'test_value_10'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'utm-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_utm_profile_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_utm_profile': {
+ 'random_attribute_not_valid': 'tag',
+ 'antivirus_profile': 'test_value_3',
+ 'application_list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips_sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan_botnet_connections': 'disable',
+ 'utm_log': 'enable',
+ 'webfilter_profile': 'test_value_10'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_utm_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'antivirus-profile': 'test_value_3',
+ 'application-list': 'test_value_4',
+ 'comment': 'Comment.',
+ 'ips-sensor': 'test_value_6',
+ 'name': 'default_name_7',
+ 'scan-botnet-connections': 'disable',
+ 'utm-log': 'enable',
+ 'webfilter-profile': 'test_value_10'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'utm-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_vap.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_vap.py
new file mode 100644
index 0000000000..fcfc7ce094
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_vap.py
@@ -0,0 +1,1109 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_vap
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_vap.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_vap_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_vap': {
+ 'acct_interim_interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast_ssid': 'enable',
+ 'broadcast_suppression': 'dhcp-up',
+ 'captive_portal_ac_name': 'test_value_8',
+ 'captive_portal_macauth_radius_secret': 'test_value_9',
+ 'captive_portal_macauth_radius_server': 'test_value_10',
+ 'captive_portal_radius_secret': 'test_value_11',
+ 'captive_portal_radius_server': 'test_value_12',
+ 'captive_portal_session_timeout_interval': '13',
+ 'dhcp_lease_time': '14',
+ 'dhcp_option82_circuit_id_insertion': 'style-1',
+ 'dhcp_option82_insertion': 'enable',
+ 'dhcp_option82_remote_id_insertion': 'style-1',
+ 'dynamic_vlan': 'enable',
+ 'eap_reauth': 'enable',
+ 'eap_reauth_intv': '20',
+ 'eapol_key_retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external_fast_roaming': 'enable',
+ 'external_logout': 'test_value_24',
+ 'external_web': 'test_value_25',
+ 'fast_bss_transition': 'disable',
+ 'fast_roaming': 'enable',
+ 'ft_mobility_domain': '28',
+ 'ft_over_ds': 'disable',
+ 'ft_r0_key_lifetime': '30',
+ 'gtk_rekey': 'enable',
+ 'gtk_rekey_intv': '32',
+ 'hotspot20_profile': 'test_value_33',
+ 'intra_vap_privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local_authentication': 'enable',
+ 'local_bridging': 'enable',
+ 'local_lan': 'allow',
+ 'local_standalone': 'enable',
+ 'local_standalone_nat': 'enable',
+ 'mac_auth_bypass': 'enable',
+ 'mac_filter': 'enable',
+ 'mac_filter_policy_other': 'allow',
+ 'max_clients': '47',
+ 'max_clients_ap': '48',
+ 'me_disable_thresh': '49',
+ 'mesh_backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk_concurrent_clients': '52',
+ 'multicast_enhance': 'enable',
+ 'multicast_rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf_assoc_comeback_timeout': '59',
+ 'pmf_sa_query_retry_timeout': '60',
+ 'portal_message_override_group': 'test_value_61',
+ 'portal_type': 'auth',
+ 'probe_resp_suppression': 'enable',
+ 'probe_resp_threshold': 'test_value_64',
+ 'ptk_rekey': 'enable',
+ 'ptk_rekey_intv': '66',
+ 'qos_profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio_2g_threshold': 'test_value_69',
+ 'radio_5g_threshold': 'test_value_70',
+ 'radio_sensitivity': 'enable',
+ 'radius_mac_auth': 'enable',
+ 'radius_mac_auth_server': 'test_value_73',
+ 'radius_server': 'test_value_74',
+ 'rates_11a': '1',
+ 'rates_11ac_ss12': 'mcs0/1',
+ 'rates_11ac_ss34': 'mcs0/3',
+ 'rates_11bg': '1',
+ 'rates_11n_ss12': 'mcs0/1',
+ 'rates_11n_ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security_exempt_list': 'test_value_83',
+ 'security_obsolete_option': 'enable',
+ 'security_redirect_url': 'test_value_85',
+ 'split_tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip_counter_measure': 'enable',
+ 'utm_profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan_auto': 'enable',
+ 'vlan_pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice_enterprise': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_vap.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'acct-interim-interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast-ssid': 'enable',
+ 'broadcast-suppression': 'dhcp-up',
+ 'captive-portal-ac-name': 'test_value_8',
+ 'captive-portal-macauth-radius-secret': 'test_value_9',
+ 'captive-portal-macauth-radius-server': 'test_value_10',
+ 'captive-portal-radius-secret': 'test_value_11',
+ 'captive-portal-radius-server': 'test_value_12',
+ 'captive-portal-session-timeout-interval': '13',
+ 'dhcp-lease-time': '14',
+ 'dhcp-option82-circuit-id-insertion': 'style-1',
+ 'dhcp-option82-insertion': 'enable',
+ 'dhcp-option82-remote-id-insertion': 'style-1',
+ 'dynamic-vlan': 'enable',
+ 'eap-reauth': 'enable',
+ 'eap-reauth-intv': '20',
+ 'eapol-key-retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external-fast-roaming': 'enable',
+ 'external-logout': 'test_value_24',
+ 'external-web': 'test_value_25',
+ 'fast-bss-transition': 'disable',
+ 'fast-roaming': 'enable',
+ 'ft-mobility-domain': '28',
+ 'ft-over-ds': 'disable',
+ 'ft-r0-key-lifetime': '30',
+ 'gtk-rekey': 'enable',
+ 'gtk-rekey-intv': '32',
+ 'hotspot20-profile': 'test_value_33',
+ 'intra-vap-privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local-authentication': 'enable',
+ 'local-bridging': 'enable',
+ 'local-lan': 'allow',
+ 'local-standalone': 'enable',
+ 'local-standalone-nat': 'enable',
+ 'mac-auth-bypass': 'enable',
+ 'mac-filter': 'enable',
+ 'mac-filter-policy-other': 'allow',
+ 'max-clients': '47',
+ 'max-clients-ap': '48',
+ 'me-disable-thresh': '49',
+ 'mesh-backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk-concurrent-clients': '52',
+ 'multicast-enhance': 'enable',
+ 'multicast-rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf-assoc-comeback-timeout': '59',
+ 'pmf-sa-query-retry-timeout': '60',
+ 'portal-message-override-group': 'test_value_61',
+ 'portal-type': 'auth',
+ 'probe-resp-suppression': 'enable',
+ 'probe-resp-threshold': 'test_value_64',
+ 'ptk-rekey': 'enable',
+ 'ptk-rekey-intv': '66',
+ 'qos-profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio-2g-threshold': 'test_value_69',
+ 'radio-5g-threshold': 'test_value_70',
+ 'radio-sensitivity': 'enable',
+ 'radius-mac-auth': 'enable',
+ 'radius-mac-auth-server': 'test_value_73',
+ 'radius-server': 'test_value_74',
+ 'rates-11a': '1',
+ 'rates-11ac-ss12': 'mcs0/1',
+ 'rates-11ac-ss34': 'mcs0/3',
+ 'rates-11bg': '1',
+ 'rates-11n-ss12': 'mcs0/1',
+ 'rates-11n-ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security-exempt-list': 'test_value_83',
+ 'security-obsolete-option': 'enable',
+ 'security-redirect-url': 'test_value_85',
+ 'split-tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip-counter-measure': 'enable',
+ 'utm-profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan-auto': 'enable',
+ 'vlan-pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice-enterprise': 'disable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'vap', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_vap_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_vap': {
+ 'acct_interim_interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast_ssid': 'enable',
+ 'broadcast_suppression': 'dhcp-up',
+ 'captive_portal_ac_name': 'test_value_8',
+ 'captive_portal_macauth_radius_secret': 'test_value_9',
+ 'captive_portal_macauth_radius_server': 'test_value_10',
+ 'captive_portal_radius_secret': 'test_value_11',
+ 'captive_portal_radius_server': 'test_value_12',
+ 'captive_portal_session_timeout_interval': '13',
+ 'dhcp_lease_time': '14',
+ 'dhcp_option82_circuit_id_insertion': 'style-1',
+ 'dhcp_option82_insertion': 'enable',
+ 'dhcp_option82_remote_id_insertion': 'style-1',
+ 'dynamic_vlan': 'enable',
+ 'eap_reauth': 'enable',
+ 'eap_reauth_intv': '20',
+ 'eapol_key_retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external_fast_roaming': 'enable',
+ 'external_logout': 'test_value_24',
+ 'external_web': 'test_value_25',
+ 'fast_bss_transition': 'disable',
+ 'fast_roaming': 'enable',
+ 'ft_mobility_domain': '28',
+ 'ft_over_ds': 'disable',
+ 'ft_r0_key_lifetime': '30',
+ 'gtk_rekey': 'enable',
+ 'gtk_rekey_intv': '32',
+ 'hotspot20_profile': 'test_value_33',
+ 'intra_vap_privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local_authentication': 'enable',
+ 'local_bridging': 'enable',
+ 'local_lan': 'allow',
+ 'local_standalone': 'enable',
+ 'local_standalone_nat': 'enable',
+ 'mac_auth_bypass': 'enable',
+ 'mac_filter': 'enable',
+ 'mac_filter_policy_other': 'allow',
+ 'max_clients': '47',
+ 'max_clients_ap': '48',
+ 'me_disable_thresh': '49',
+ 'mesh_backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk_concurrent_clients': '52',
+ 'multicast_enhance': 'enable',
+ 'multicast_rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf_assoc_comeback_timeout': '59',
+ 'pmf_sa_query_retry_timeout': '60',
+ 'portal_message_override_group': 'test_value_61',
+ 'portal_type': 'auth',
+ 'probe_resp_suppression': 'enable',
+ 'probe_resp_threshold': 'test_value_64',
+ 'ptk_rekey': 'enable',
+ 'ptk_rekey_intv': '66',
+ 'qos_profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio_2g_threshold': 'test_value_69',
+ 'radio_5g_threshold': 'test_value_70',
+ 'radio_sensitivity': 'enable',
+ 'radius_mac_auth': 'enable',
+ 'radius_mac_auth_server': 'test_value_73',
+ 'radius_server': 'test_value_74',
+ 'rates_11a': '1',
+ 'rates_11ac_ss12': 'mcs0/1',
+ 'rates_11ac_ss34': 'mcs0/3',
+ 'rates_11bg': '1',
+ 'rates_11n_ss12': 'mcs0/1',
+ 'rates_11n_ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security_exempt_list': 'test_value_83',
+ 'security_obsolete_option': 'enable',
+ 'security_redirect_url': 'test_value_85',
+ 'split_tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip_counter_measure': 'enable',
+ 'utm_profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan_auto': 'enable',
+ 'vlan_pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice_enterprise': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_vap.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'acct-interim-interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast-ssid': 'enable',
+ 'broadcast-suppression': 'dhcp-up',
+ 'captive-portal-ac-name': 'test_value_8',
+ 'captive-portal-macauth-radius-secret': 'test_value_9',
+ 'captive-portal-macauth-radius-server': 'test_value_10',
+ 'captive-portal-radius-secret': 'test_value_11',
+ 'captive-portal-radius-server': 'test_value_12',
+ 'captive-portal-session-timeout-interval': '13',
+ 'dhcp-lease-time': '14',
+ 'dhcp-option82-circuit-id-insertion': 'style-1',
+ 'dhcp-option82-insertion': 'enable',
+ 'dhcp-option82-remote-id-insertion': 'style-1',
+ 'dynamic-vlan': 'enable',
+ 'eap-reauth': 'enable',
+ 'eap-reauth-intv': '20',
+ 'eapol-key-retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external-fast-roaming': 'enable',
+ 'external-logout': 'test_value_24',
+ 'external-web': 'test_value_25',
+ 'fast-bss-transition': 'disable',
+ 'fast-roaming': 'enable',
+ 'ft-mobility-domain': '28',
+ 'ft-over-ds': 'disable',
+ 'ft-r0-key-lifetime': '30',
+ 'gtk-rekey': 'enable',
+ 'gtk-rekey-intv': '32',
+ 'hotspot20-profile': 'test_value_33',
+ 'intra-vap-privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local-authentication': 'enable',
+ 'local-bridging': 'enable',
+ 'local-lan': 'allow',
+ 'local-standalone': 'enable',
+ 'local-standalone-nat': 'enable',
+ 'mac-auth-bypass': 'enable',
+ 'mac-filter': 'enable',
+ 'mac-filter-policy-other': 'allow',
+ 'max-clients': '47',
+ 'max-clients-ap': '48',
+ 'me-disable-thresh': '49',
+ 'mesh-backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk-concurrent-clients': '52',
+ 'multicast-enhance': 'enable',
+ 'multicast-rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf-assoc-comeback-timeout': '59',
+ 'pmf-sa-query-retry-timeout': '60',
+ 'portal-message-override-group': 'test_value_61',
+ 'portal-type': 'auth',
+ 'probe-resp-suppression': 'enable',
+ 'probe-resp-threshold': 'test_value_64',
+ 'ptk-rekey': 'enable',
+ 'ptk-rekey-intv': '66',
+ 'qos-profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio-2g-threshold': 'test_value_69',
+ 'radio-5g-threshold': 'test_value_70',
+ 'radio-sensitivity': 'enable',
+ 'radius-mac-auth': 'enable',
+ 'radius-mac-auth-server': 'test_value_73',
+ 'radius-server': 'test_value_74',
+ 'rates-11a': '1',
+ 'rates-11ac-ss12': 'mcs0/1',
+ 'rates-11ac-ss34': 'mcs0/3',
+ 'rates-11bg': '1',
+ 'rates-11n-ss12': 'mcs0/1',
+ 'rates-11n-ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security-exempt-list': 'test_value_83',
+ 'security-obsolete-option': 'enable',
+ 'security-redirect-url': 'test_value_85',
+ 'split-tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip-counter-measure': 'enable',
+ 'utm-profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan-auto': 'enable',
+ 'vlan-pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice-enterprise': 'disable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'vap', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_vap_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_vap': {
+ 'acct_interim_interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast_ssid': 'enable',
+ 'broadcast_suppression': 'dhcp-up',
+ 'captive_portal_ac_name': 'test_value_8',
+ 'captive_portal_macauth_radius_secret': 'test_value_9',
+ 'captive_portal_macauth_radius_server': 'test_value_10',
+ 'captive_portal_radius_secret': 'test_value_11',
+ 'captive_portal_radius_server': 'test_value_12',
+ 'captive_portal_session_timeout_interval': '13',
+ 'dhcp_lease_time': '14',
+ 'dhcp_option82_circuit_id_insertion': 'style-1',
+ 'dhcp_option82_insertion': 'enable',
+ 'dhcp_option82_remote_id_insertion': 'style-1',
+ 'dynamic_vlan': 'enable',
+ 'eap_reauth': 'enable',
+ 'eap_reauth_intv': '20',
+ 'eapol_key_retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external_fast_roaming': 'enable',
+ 'external_logout': 'test_value_24',
+ 'external_web': 'test_value_25',
+ 'fast_bss_transition': 'disable',
+ 'fast_roaming': 'enable',
+ 'ft_mobility_domain': '28',
+ 'ft_over_ds': 'disable',
+ 'ft_r0_key_lifetime': '30',
+ 'gtk_rekey': 'enable',
+ 'gtk_rekey_intv': '32',
+ 'hotspot20_profile': 'test_value_33',
+ 'intra_vap_privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local_authentication': 'enable',
+ 'local_bridging': 'enable',
+ 'local_lan': 'allow',
+ 'local_standalone': 'enable',
+ 'local_standalone_nat': 'enable',
+ 'mac_auth_bypass': 'enable',
+ 'mac_filter': 'enable',
+ 'mac_filter_policy_other': 'allow',
+ 'max_clients': '47',
+ 'max_clients_ap': '48',
+ 'me_disable_thresh': '49',
+ 'mesh_backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk_concurrent_clients': '52',
+ 'multicast_enhance': 'enable',
+ 'multicast_rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf_assoc_comeback_timeout': '59',
+ 'pmf_sa_query_retry_timeout': '60',
+ 'portal_message_override_group': 'test_value_61',
+ 'portal_type': 'auth',
+ 'probe_resp_suppression': 'enable',
+ 'probe_resp_threshold': 'test_value_64',
+ 'ptk_rekey': 'enable',
+ 'ptk_rekey_intv': '66',
+ 'qos_profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio_2g_threshold': 'test_value_69',
+ 'radio_5g_threshold': 'test_value_70',
+ 'radio_sensitivity': 'enable',
+ 'radius_mac_auth': 'enable',
+ 'radius_mac_auth_server': 'test_value_73',
+ 'radius_server': 'test_value_74',
+ 'rates_11a': '1',
+ 'rates_11ac_ss12': 'mcs0/1',
+ 'rates_11ac_ss34': 'mcs0/3',
+ 'rates_11bg': '1',
+ 'rates_11n_ss12': 'mcs0/1',
+ 'rates_11n_ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security_exempt_list': 'test_value_83',
+ 'security_obsolete_option': 'enable',
+ 'security_redirect_url': 'test_value_85',
+ 'split_tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip_counter_measure': 'enable',
+ 'utm_profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan_auto': 'enable',
+ 'vlan_pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice_enterprise': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_vap.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'vap', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_vap_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_vap': {
+ 'acct_interim_interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast_ssid': 'enable',
+ 'broadcast_suppression': 'dhcp-up',
+ 'captive_portal_ac_name': 'test_value_8',
+ 'captive_portal_macauth_radius_secret': 'test_value_9',
+ 'captive_portal_macauth_radius_server': 'test_value_10',
+ 'captive_portal_radius_secret': 'test_value_11',
+ 'captive_portal_radius_server': 'test_value_12',
+ 'captive_portal_session_timeout_interval': '13',
+ 'dhcp_lease_time': '14',
+ 'dhcp_option82_circuit_id_insertion': 'style-1',
+ 'dhcp_option82_insertion': 'enable',
+ 'dhcp_option82_remote_id_insertion': 'style-1',
+ 'dynamic_vlan': 'enable',
+ 'eap_reauth': 'enable',
+ 'eap_reauth_intv': '20',
+ 'eapol_key_retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external_fast_roaming': 'enable',
+ 'external_logout': 'test_value_24',
+ 'external_web': 'test_value_25',
+ 'fast_bss_transition': 'disable',
+ 'fast_roaming': 'enable',
+ 'ft_mobility_domain': '28',
+ 'ft_over_ds': 'disable',
+ 'ft_r0_key_lifetime': '30',
+ 'gtk_rekey': 'enable',
+ 'gtk_rekey_intv': '32',
+ 'hotspot20_profile': 'test_value_33',
+ 'intra_vap_privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local_authentication': 'enable',
+ 'local_bridging': 'enable',
+ 'local_lan': 'allow',
+ 'local_standalone': 'enable',
+ 'local_standalone_nat': 'enable',
+ 'mac_auth_bypass': 'enable',
+ 'mac_filter': 'enable',
+ 'mac_filter_policy_other': 'allow',
+ 'max_clients': '47',
+ 'max_clients_ap': '48',
+ 'me_disable_thresh': '49',
+ 'mesh_backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk_concurrent_clients': '52',
+ 'multicast_enhance': 'enable',
+ 'multicast_rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf_assoc_comeback_timeout': '59',
+ 'pmf_sa_query_retry_timeout': '60',
+ 'portal_message_override_group': 'test_value_61',
+ 'portal_type': 'auth',
+ 'probe_resp_suppression': 'enable',
+ 'probe_resp_threshold': 'test_value_64',
+ 'ptk_rekey': 'enable',
+ 'ptk_rekey_intv': '66',
+ 'qos_profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio_2g_threshold': 'test_value_69',
+ 'radio_5g_threshold': 'test_value_70',
+ 'radio_sensitivity': 'enable',
+ 'radius_mac_auth': 'enable',
+ 'radius_mac_auth_server': 'test_value_73',
+ 'radius_server': 'test_value_74',
+ 'rates_11a': '1',
+ 'rates_11ac_ss12': 'mcs0/1',
+ 'rates_11ac_ss34': 'mcs0/3',
+ 'rates_11bg': '1',
+ 'rates_11n_ss12': 'mcs0/1',
+ 'rates_11n_ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security_exempt_list': 'test_value_83',
+ 'security_obsolete_option': 'enable',
+ 'security_redirect_url': 'test_value_85',
+ 'split_tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip_counter_measure': 'enable',
+ 'utm_profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan_auto': 'enable',
+ 'vlan_pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice_enterprise': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_vap.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'vap', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_vap_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_vap': {
+ 'acct_interim_interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast_ssid': 'enable',
+ 'broadcast_suppression': 'dhcp-up',
+ 'captive_portal_ac_name': 'test_value_8',
+ 'captive_portal_macauth_radius_secret': 'test_value_9',
+ 'captive_portal_macauth_radius_server': 'test_value_10',
+ 'captive_portal_radius_secret': 'test_value_11',
+ 'captive_portal_radius_server': 'test_value_12',
+ 'captive_portal_session_timeout_interval': '13',
+ 'dhcp_lease_time': '14',
+ 'dhcp_option82_circuit_id_insertion': 'style-1',
+ 'dhcp_option82_insertion': 'enable',
+ 'dhcp_option82_remote_id_insertion': 'style-1',
+ 'dynamic_vlan': 'enable',
+ 'eap_reauth': 'enable',
+ 'eap_reauth_intv': '20',
+ 'eapol_key_retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external_fast_roaming': 'enable',
+ 'external_logout': 'test_value_24',
+ 'external_web': 'test_value_25',
+ 'fast_bss_transition': 'disable',
+ 'fast_roaming': 'enable',
+ 'ft_mobility_domain': '28',
+ 'ft_over_ds': 'disable',
+ 'ft_r0_key_lifetime': '30',
+ 'gtk_rekey': 'enable',
+ 'gtk_rekey_intv': '32',
+ 'hotspot20_profile': 'test_value_33',
+ 'intra_vap_privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local_authentication': 'enable',
+ 'local_bridging': 'enable',
+ 'local_lan': 'allow',
+ 'local_standalone': 'enable',
+ 'local_standalone_nat': 'enable',
+ 'mac_auth_bypass': 'enable',
+ 'mac_filter': 'enable',
+ 'mac_filter_policy_other': 'allow',
+ 'max_clients': '47',
+ 'max_clients_ap': '48',
+ 'me_disable_thresh': '49',
+ 'mesh_backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk_concurrent_clients': '52',
+ 'multicast_enhance': 'enable',
+ 'multicast_rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf_assoc_comeback_timeout': '59',
+ 'pmf_sa_query_retry_timeout': '60',
+ 'portal_message_override_group': 'test_value_61',
+ 'portal_type': 'auth',
+ 'probe_resp_suppression': 'enable',
+ 'probe_resp_threshold': 'test_value_64',
+ 'ptk_rekey': 'enable',
+ 'ptk_rekey_intv': '66',
+ 'qos_profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio_2g_threshold': 'test_value_69',
+ 'radio_5g_threshold': 'test_value_70',
+ 'radio_sensitivity': 'enable',
+ 'radius_mac_auth': 'enable',
+ 'radius_mac_auth_server': 'test_value_73',
+ 'radius_server': 'test_value_74',
+ 'rates_11a': '1',
+ 'rates_11ac_ss12': 'mcs0/1',
+ 'rates_11ac_ss34': 'mcs0/3',
+ 'rates_11bg': '1',
+ 'rates_11n_ss12': 'mcs0/1',
+ 'rates_11n_ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security_exempt_list': 'test_value_83',
+ 'security_obsolete_option': 'enable',
+ 'security_redirect_url': 'test_value_85',
+ 'split_tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip_counter_measure': 'enable',
+ 'utm_profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan_auto': 'enable',
+ 'vlan_pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice_enterprise': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_vap.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'acct-interim-interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast-ssid': 'enable',
+ 'broadcast-suppression': 'dhcp-up',
+ 'captive-portal-ac-name': 'test_value_8',
+ 'captive-portal-macauth-radius-secret': 'test_value_9',
+ 'captive-portal-macauth-radius-server': 'test_value_10',
+ 'captive-portal-radius-secret': 'test_value_11',
+ 'captive-portal-radius-server': 'test_value_12',
+ 'captive-portal-session-timeout-interval': '13',
+ 'dhcp-lease-time': '14',
+ 'dhcp-option82-circuit-id-insertion': 'style-1',
+ 'dhcp-option82-insertion': 'enable',
+ 'dhcp-option82-remote-id-insertion': 'style-1',
+ 'dynamic-vlan': 'enable',
+ 'eap-reauth': 'enable',
+ 'eap-reauth-intv': '20',
+ 'eapol-key-retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external-fast-roaming': 'enable',
+ 'external-logout': 'test_value_24',
+ 'external-web': 'test_value_25',
+ 'fast-bss-transition': 'disable',
+ 'fast-roaming': 'enable',
+ 'ft-mobility-domain': '28',
+ 'ft-over-ds': 'disable',
+ 'ft-r0-key-lifetime': '30',
+ 'gtk-rekey': 'enable',
+ 'gtk-rekey-intv': '32',
+ 'hotspot20-profile': 'test_value_33',
+ 'intra-vap-privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local-authentication': 'enable',
+ 'local-bridging': 'enable',
+ 'local-lan': 'allow',
+ 'local-standalone': 'enable',
+ 'local-standalone-nat': 'enable',
+ 'mac-auth-bypass': 'enable',
+ 'mac-filter': 'enable',
+ 'mac-filter-policy-other': 'allow',
+ 'max-clients': '47',
+ 'max-clients-ap': '48',
+ 'me-disable-thresh': '49',
+ 'mesh-backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk-concurrent-clients': '52',
+ 'multicast-enhance': 'enable',
+ 'multicast-rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf-assoc-comeback-timeout': '59',
+ 'pmf-sa-query-retry-timeout': '60',
+ 'portal-message-override-group': 'test_value_61',
+ 'portal-type': 'auth',
+ 'probe-resp-suppression': 'enable',
+ 'probe-resp-threshold': 'test_value_64',
+ 'ptk-rekey': 'enable',
+ 'ptk-rekey-intv': '66',
+ 'qos-profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio-2g-threshold': 'test_value_69',
+ 'radio-5g-threshold': 'test_value_70',
+ 'radio-sensitivity': 'enable',
+ 'radius-mac-auth': 'enable',
+ 'radius-mac-auth-server': 'test_value_73',
+ 'radius-server': 'test_value_74',
+ 'rates-11a': '1',
+ 'rates-11ac-ss12': 'mcs0/1',
+ 'rates-11ac-ss34': 'mcs0/3',
+ 'rates-11bg': '1',
+ 'rates-11n-ss12': 'mcs0/1',
+ 'rates-11n-ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security-exempt-list': 'test_value_83',
+ 'security-obsolete-option': 'enable',
+ 'security-redirect-url': 'test_value_85',
+ 'split-tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip-counter-measure': 'enable',
+ 'utm-profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan-auto': 'enable',
+ 'vlan-pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice-enterprise': 'disable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'vap', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_vap_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_vap': {
+ 'random_attribute_not_valid': 'tag',
+ 'acct_interim_interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast_ssid': 'enable',
+ 'broadcast_suppression': 'dhcp-up',
+ 'captive_portal_ac_name': 'test_value_8',
+ 'captive_portal_macauth_radius_secret': 'test_value_9',
+ 'captive_portal_macauth_radius_server': 'test_value_10',
+ 'captive_portal_radius_secret': 'test_value_11',
+ 'captive_portal_radius_server': 'test_value_12',
+ 'captive_portal_session_timeout_interval': '13',
+ 'dhcp_lease_time': '14',
+ 'dhcp_option82_circuit_id_insertion': 'style-1',
+ 'dhcp_option82_insertion': 'enable',
+ 'dhcp_option82_remote_id_insertion': 'style-1',
+ 'dynamic_vlan': 'enable',
+ 'eap_reauth': 'enable',
+ 'eap_reauth_intv': '20',
+ 'eapol_key_retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external_fast_roaming': 'enable',
+ 'external_logout': 'test_value_24',
+ 'external_web': 'test_value_25',
+ 'fast_bss_transition': 'disable',
+ 'fast_roaming': 'enable',
+ 'ft_mobility_domain': '28',
+ 'ft_over_ds': 'disable',
+ 'ft_r0_key_lifetime': '30',
+ 'gtk_rekey': 'enable',
+ 'gtk_rekey_intv': '32',
+ 'hotspot20_profile': 'test_value_33',
+ 'intra_vap_privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local_authentication': 'enable',
+ 'local_bridging': 'enable',
+ 'local_lan': 'allow',
+ 'local_standalone': 'enable',
+ 'local_standalone_nat': 'enable',
+ 'mac_auth_bypass': 'enable',
+ 'mac_filter': 'enable',
+ 'mac_filter_policy_other': 'allow',
+ 'max_clients': '47',
+ 'max_clients_ap': '48',
+ 'me_disable_thresh': '49',
+ 'mesh_backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk_concurrent_clients': '52',
+ 'multicast_enhance': 'enable',
+ 'multicast_rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf_assoc_comeback_timeout': '59',
+ 'pmf_sa_query_retry_timeout': '60',
+ 'portal_message_override_group': 'test_value_61',
+ 'portal_type': 'auth',
+ 'probe_resp_suppression': 'enable',
+ 'probe_resp_threshold': 'test_value_64',
+ 'ptk_rekey': 'enable',
+ 'ptk_rekey_intv': '66',
+ 'qos_profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio_2g_threshold': 'test_value_69',
+ 'radio_5g_threshold': 'test_value_70',
+ 'radio_sensitivity': 'enable',
+ 'radius_mac_auth': 'enable',
+ 'radius_mac_auth_server': 'test_value_73',
+ 'radius_server': 'test_value_74',
+ 'rates_11a': '1',
+ 'rates_11ac_ss12': 'mcs0/1',
+ 'rates_11ac_ss34': 'mcs0/3',
+ 'rates_11bg': '1',
+ 'rates_11n_ss12': 'mcs0/1',
+ 'rates_11n_ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security_exempt_list': 'test_value_83',
+ 'security_obsolete_option': 'enable',
+ 'security_redirect_url': 'test_value_85',
+ 'split_tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip_counter_measure': 'enable',
+ 'utm_profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan_auto': 'enable',
+ 'vlan_pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice_enterprise': 'disable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_vap.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'acct-interim-interval': '3',
+ 'alias': 'test_value_4',
+ 'auth': 'psk',
+ 'broadcast-ssid': 'enable',
+ 'broadcast-suppression': 'dhcp-up',
+ 'captive-portal-ac-name': 'test_value_8',
+ 'captive-portal-macauth-radius-secret': 'test_value_9',
+ 'captive-portal-macauth-radius-server': 'test_value_10',
+ 'captive-portal-radius-secret': 'test_value_11',
+ 'captive-portal-radius-server': 'test_value_12',
+ 'captive-portal-session-timeout-interval': '13',
+ 'dhcp-lease-time': '14',
+ 'dhcp-option82-circuit-id-insertion': 'style-1',
+ 'dhcp-option82-insertion': 'enable',
+ 'dhcp-option82-remote-id-insertion': 'style-1',
+ 'dynamic-vlan': 'enable',
+ 'eap-reauth': 'enable',
+ 'eap-reauth-intv': '20',
+ 'eapol-key-retries': 'disable',
+ 'encrypt': 'TKIP',
+ 'external-fast-roaming': 'enable',
+ 'external-logout': 'test_value_24',
+ 'external-web': 'test_value_25',
+ 'fast-bss-transition': 'disable',
+ 'fast-roaming': 'enable',
+ 'ft-mobility-domain': '28',
+ 'ft-over-ds': 'disable',
+ 'ft-r0-key-lifetime': '30',
+ 'gtk-rekey': 'enable',
+ 'gtk-rekey-intv': '32',
+ 'hotspot20-profile': 'test_value_33',
+ 'intra-vap-privacy': 'enable',
+ 'ip': 'test_value_35',
+ 'key': 'test_value_36',
+ 'keyindex': '37',
+ 'ldpc': 'disable',
+ 'local-authentication': 'enable',
+ 'local-bridging': 'enable',
+ 'local-lan': 'allow',
+ 'local-standalone': 'enable',
+ 'local-standalone-nat': 'enable',
+ 'mac-auth-bypass': 'enable',
+ 'mac-filter': 'enable',
+ 'mac-filter-policy-other': 'allow',
+ 'max-clients': '47',
+ 'max-clients-ap': '48',
+ 'me-disable-thresh': '49',
+ 'mesh-backhaul': 'enable',
+ 'mpsk': 'enable',
+ 'mpsk-concurrent-clients': '52',
+ 'multicast-enhance': 'enable',
+ 'multicast-rate': '0',
+ 'name': 'default_name_55',
+ 'okc': 'disable',
+ 'passphrase': 'test_value_57',
+ 'pmf': 'disable',
+ 'pmf-assoc-comeback-timeout': '59',
+ 'pmf-sa-query-retry-timeout': '60',
+ 'portal-message-override-group': 'test_value_61',
+ 'portal-type': 'auth',
+ 'probe-resp-suppression': 'enable',
+ 'probe-resp-threshold': 'test_value_64',
+ 'ptk-rekey': 'enable',
+ 'ptk-rekey-intv': '66',
+ 'qos-profile': 'test_value_67',
+ 'quarantine': 'enable',
+ 'radio-2g-threshold': 'test_value_69',
+ 'radio-5g-threshold': 'test_value_70',
+ 'radio-sensitivity': 'enable',
+ 'radius-mac-auth': 'enable',
+ 'radius-mac-auth-server': 'test_value_73',
+ 'radius-server': 'test_value_74',
+ 'rates-11a': '1',
+ 'rates-11ac-ss12': 'mcs0/1',
+ 'rates-11ac-ss34': 'mcs0/3',
+ 'rates-11bg': '1',
+ 'rates-11n-ss12': 'mcs0/1',
+ 'rates-11n-ss34': 'mcs16/3',
+ 'schedule': 'test_value_81',
+ 'security': 'open',
+ 'security-exempt-list': 'test_value_83',
+ 'security-obsolete-option': 'enable',
+ 'security-redirect-url': 'test_value_85',
+ 'split-tunneling': 'enable',
+ 'ssid': 'test_value_87',
+ 'tkip-counter-measure': 'enable',
+ 'utm-profile': 'test_value_89',
+ 'vdom': 'test_value_90',
+ 'vlan-auto': 'enable',
+ 'vlan-pooling': 'wtp-group',
+ 'vlanid': '93',
+ 'voice-enterprise': 'disable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'vap', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_wids_profile.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_wids_profile.py
new file mode 100644
index 0000000000..622dbef72e
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_wids_profile.py
@@ -0,0 +1,679 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_wids_profile
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_wids_profile.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_wids_profile_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wids_profile': {
+ 'ap_auto_suppress': 'enable',
+ 'ap_bgscan_disable_day': 'sunday',
+ 'ap_bgscan_disable_end': 'test_value_5',
+ 'ap_bgscan_disable_start': 'test_value_6',
+ 'ap_bgscan_duration': '7',
+ 'ap_bgscan_idle': '8',
+ 'ap_bgscan_intv': '9',
+ 'ap_bgscan_period': '10',
+ 'ap_bgscan_report_intv': '11',
+ 'ap_fgscan_report_intv': '12',
+ 'ap_scan': 'disable',
+ 'ap_scan_passive': 'enable',
+ 'asleap_attack': 'enable',
+ 'assoc_flood_thresh': '16',
+ 'assoc_flood_time': '17',
+ 'assoc_frame_flood': 'enable',
+ 'auth_flood_thresh': '19',
+ 'auth_flood_time': '20',
+ 'auth_frame_flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth_broadcast': 'enable',
+ 'deauth_unknown_src_thresh': '24',
+ 'eapol_fail_flood': 'enable',
+ 'eapol_fail_intv': '26',
+ 'eapol_fail_thresh': '27',
+ 'eapol_logoff_flood': 'enable',
+ 'eapol_logoff_intv': '29',
+ 'eapol_logoff_thresh': '30',
+ 'eapol_pre_fail_flood': 'enable',
+ 'eapol_pre_fail_intv': '32',
+ 'eapol_pre_fail_thresh': '33',
+ 'eapol_pre_succ_flood': 'enable',
+ 'eapol_pre_succ_intv': '35',
+ 'eapol_pre_succ_thresh': '36',
+ 'eapol_start_flood': 'enable',
+ 'eapol_start_intv': '38',
+ 'eapol_start_thresh': '39',
+ 'eapol_succ_flood': 'enable',
+ 'eapol_succ_intv': '41',
+ 'eapol_succ_thresh': '42',
+ 'invalid_mac_oui': 'enable',
+ 'long_duration_attack': 'enable',
+ 'long_duration_thresh': '45',
+ 'name': 'default_name_46',
+ 'null_ssid_probe_resp': 'enable',
+ 'sensor_mode': 'disable',
+ 'spoofed_deauth': 'enable',
+ 'weak_wep_iv': 'enable',
+ 'wireless_bridge': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wids_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-auto-suppress': 'enable',
+ 'ap-bgscan-disable-day': 'sunday',
+ 'ap-bgscan-disable-end': 'test_value_5',
+ 'ap-bgscan-disable-start': 'test_value_6',
+ 'ap-bgscan-duration': '7',
+ 'ap-bgscan-idle': '8',
+ 'ap-bgscan-intv': '9',
+ 'ap-bgscan-period': '10',
+ 'ap-bgscan-report-intv': '11',
+ 'ap-fgscan-report-intv': '12',
+ 'ap-scan': 'disable',
+ 'ap-scan-passive': 'enable',
+ 'asleap-attack': 'enable',
+ 'assoc-flood-thresh': '16',
+ 'assoc-flood-time': '17',
+ 'assoc-frame-flood': 'enable',
+ 'auth-flood-thresh': '19',
+ 'auth-flood-time': '20',
+ 'auth-frame-flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth-broadcast': 'enable',
+ 'deauth-unknown-src-thresh': '24',
+ 'eapol-fail-flood': 'enable',
+ 'eapol-fail-intv': '26',
+ 'eapol-fail-thresh': '27',
+ 'eapol-logoff-flood': 'enable',
+ 'eapol-logoff-intv': '29',
+ 'eapol-logoff-thresh': '30',
+ 'eapol-pre-fail-flood': 'enable',
+ 'eapol-pre-fail-intv': '32',
+ 'eapol-pre-fail-thresh': '33',
+ 'eapol-pre-succ-flood': 'enable',
+ 'eapol-pre-succ-intv': '35',
+ 'eapol-pre-succ-thresh': '36',
+ 'eapol-start-flood': 'enable',
+ 'eapol-start-intv': '38',
+ 'eapol-start-thresh': '39',
+ 'eapol-succ-flood': 'enable',
+ 'eapol-succ-intv': '41',
+ 'eapol-succ-thresh': '42',
+ 'invalid-mac-oui': 'enable',
+ 'long-duration-attack': 'enable',
+ 'long-duration-thresh': '45',
+ 'name': 'default_name_46',
+ 'null-ssid-probe-resp': 'enable',
+ 'sensor-mode': 'disable',
+ 'spoofed-deauth': 'enable',
+ 'weak-wep-iv': 'enable',
+ 'wireless-bridge': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wids-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_wids_profile_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wids_profile': {
+ 'ap_auto_suppress': 'enable',
+ 'ap_bgscan_disable_day': 'sunday',
+ 'ap_bgscan_disable_end': 'test_value_5',
+ 'ap_bgscan_disable_start': 'test_value_6',
+ 'ap_bgscan_duration': '7',
+ 'ap_bgscan_idle': '8',
+ 'ap_bgscan_intv': '9',
+ 'ap_bgscan_period': '10',
+ 'ap_bgscan_report_intv': '11',
+ 'ap_fgscan_report_intv': '12',
+ 'ap_scan': 'disable',
+ 'ap_scan_passive': 'enable',
+ 'asleap_attack': 'enable',
+ 'assoc_flood_thresh': '16',
+ 'assoc_flood_time': '17',
+ 'assoc_frame_flood': 'enable',
+ 'auth_flood_thresh': '19',
+ 'auth_flood_time': '20',
+ 'auth_frame_flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth_broadcast': 'enable',
+ 'deauth_unknown_src_thresh': '24',
+ 'eapol_fail_flood': 'enable',
+ 'eapol_fail_intv': '26',
+ 'eapol_fail_thresh': '27',
+ 'eapol_logoff_flood': 'enable',
+ 'eapol_logoff_intv': '29',
+ 'eapol_logoff_thresh': '30',
+ 'eapol_pre_fail_flood': 'enable',
+ 'eapol_pre_fail_intv': '32',
+ 'eapol_pre_fail_thresh': '33',
+ 'eapol_pre_succ_flood': 'enable',
+ 'eapol_pre_succ_intv': '35',
+ 'eapol_pre_succ_thresh': '36',
+ 'eapol_start_flood': 'enable',
+ 'eapol_start_intv': '38',
+ 'eapol_start_thresh': '39',
+ 'eapol_succ_flood': 'enable',
+ 'eapol_succ_intv': '41',
+ 'eapol_succ_thresh': '42',
+ 'invalid_mac_oui': 'enable',
+ 'long_duration_attack': 'enable',
+ 'long_duration_thresh': '45',
+ 'name': 'default_name_46',
+ 'null_ssid_probe_resp': 'enable',
+ 'sensor_mode': 'disable',
+ 'spoofed_deauth': 'enable',
+ 'weak_wep_iv': 'enable',
+ 'wireless_bridge': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wids_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-auto-suppress': 'enable',
+ 'ap-bgscan-disable-day': 'sunday',
+ 'ap-bgscan-disable-end': 'test_value_5',
+ 'ap-bgscan-disable-start': 'test_value_6',
+ 'ap-bgscan-duration': '7',
+ 'ap-bgscan-idle': '8',
+ 'ap-bgscan-intv': '9',
+ 'ap-bgscan-period': '10',
+ 'ap-bgscan-report-intv': '11',
+ 'ap-fgscan-report-intv': '12',
+ 'ap-scan': 'disable',
+ 'ap-scan-passive': 'enable',
+ 'asleap-attack': 'enable',
+ 'assoc-flood-thresh': '16',
+ 'assoc-flood-time': '17',
+ 'assoc-frame-flood': 'enable',
+ 'auth-flood-thresh': '19',
+ 'auth-flood-time': '20',
+ 'auth-frame-flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth-broadcast': 'enable',
+ 'deauth-unknown-src-thresh': '24',
+ 'eapol-fail-flood': 'enable',
+ 'eapol-fail-intv': '26',
+ 'eapol-fail-thresh': '27',
+ 'eapol-logoff-flood': 'enable',
+ 'eapol-logoff-intv': '29',
+ 'eapol-logoff-thresh': '30',
+ 'eapol-pre-fail-flood': 'enable',
+ 'eapol-pre-fail-intv': '32',
+ 'eapol-pre-fail-thresh': '33',
+ 'eapol-pre-succ-flood': 'enable',
+ 'eapol-pre-succ-intv': '35',
+ 'eapol-pre-succ-thresh': '36',
+ 'eapol-start-flood': 'enable',
+ 'eapol-start-intv': '38',
+ 'eapol-start-thresh': '39',
+ 'eapol-succ-flood': 'enable',
+ 'eapol-succ-intv': '41',
+ 'eapol-succ-thresh': '42',
+ 'invalid-mac-oui': 'enable',
+ 'long-duration-attack': 'enable',
+ 'long-duration-thresh': '45',
+ 'name': 'default_name_46',
+ 'null-ssid-probe-resp': 'enable',
+ 'sensor-mode': 'disable',
+ 'spoofed-deauth': 'enable',
+ 'weak-wep-iv': 'enable',
+ 'wireless-bridge': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wids-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_wids_profile_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_wids_profile': {
+ 'ap_auto_suppress': 'enable',
+ 'ap_bgscan_disable_day': 'sunday',
+ 'ap_bgscan_disable_end': 'test_value_5',
+ 'ap_bgscan_disable_start': 'test_value_6',
+ 'ap_bgscan_duration': '7',
+ 'ap_bgscan_idle': '8',
+ 'ap_bgscan_intv': '9',
+ 'ap_bgscan_period': '10',
+ 'ap_bgscan_report_intv': '11',
+ 'ap_fgscan_report_intv': '12',
+ 'ap_scan': 'disable',
+ 'ap_scan_passive': 'enable',
+ 'asleap_attack': 'enable',
+ 'assoc_flood_thresh': '16',
+ 'assoc_flood_time': '17',
+ 'assoc_frame_flood': 'enable',
+ 'auth_flood_thresh': '19',
+ 'auth_flood_time': '20',
+ 'auth_frame_flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth_broadcast': 'enable',
+ 'deauth_unknown_src_thresh': '24',
+ 'eapol_fail_flood': 'enable',
+ 'eapol_fail_intv': '26',
+ 'eapol_fail_thresh': '27',
+ 'eapol_logoff_flood': 'enable',
+ 'eapol_logoff_intv': '29',
+ 'eapol_logoff_thresh': '30',
+ 'eapol_pre_fail_flood': 'enable',
+ 'eapol_pre_fail_intv': '32',
+ 'eapol_pre_fail_thresh': '33',
+ 'eapol_pre_succ_flood': 'enable',
+ 'eapol_pre_succ_intv': '35',
+ 'eapol_pre_succ_thresh': '36',
+ 'eapol_start_flood': 'enable',
+ 'eapol_start_intv': '38',
+ 'eapol_start_thresh': '39',
+ 'eapol_succ_flood': 'enable',
+ 'eapol_succ_intv': '41',
+ 'eapol_succ_thresh': '42',
+ 'invalid_mac_oui': 'enable',
+ 'long_duration_attack': 'enable',
+ 'long_duration_thresh': '45',
+ 'name': 'default_name_46',
+ 'null_ssid_probe_resp': 'enable',
+ 'sensor_mode': 'disable',
+ 'spoofed_deauth': 'enable',
+ 'weak_wep_iv': 'enable',
+ 'wireless_bridge': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wids_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'wids-profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_wids_profile_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_wids_profile': {
+ 'ap_auto_suppress': 'enable',
+ 'ap_bgscan_disable_day': 'sunday',
+ 'ap_bgscan_disable_end': 'test_value_5',
+ 'ap_bgscan_disable_start': 'test_value_6',
+ 'ap_bgscan_duration': '7',
+ 'ap_bgscan_idle': '8',
+ 'ap_bgscan_intv': '9',
+ 'ap_bgscan_period': '10',
+ 'ap_bgscan_report_intv': '11',
+ 'ap_fgscan_report_intv': '12',
+ 'ap_scan': 'disable',
+ 'ap_scan_passive': 'enable',
+ 'asleap_attack': 'enable',
+ 'assoc_flood_thresh': '16',
+ 'assoc_flood_time': '17',
+ 'assoc_frame_flood': 'enable',
+ 'auth_flood_thresh': '19',
+ 'auth_flood_time': '20',
+ 'auth_frame_flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth_broadcast': 'enable',
+ 'deauth_unknown_src_thresh': '24',
+ 'eapol_fail_flood': 'enable',
+ 'eapol_fail_intv': '26',
+ 'eapol_fail_thresh': '27',
+ 'eapol_logoff_flood': 'enable',
+ 'eapol_logoff_intv': '29',
+ 'eapol_logoff_thresh': '30',
+ 'eapol_pre_fail_flood': 'enable',
+ 'eapol_pre_fail_intv': '32',
+ 'eapol_pre_fail_thresh': '33',
+ 'eapol_pre_succ_flood': 'enable',
+ 'eapol_pre_succ_intv': '35',
+ 'eapol_pre_succ_thresh': '36',
+ 'eapol_start_flood': 'enable',
+ 'eapol_start_intv': '38',
+ 'eapol_start_thresh': '39',
+ 'eapol_succ_flood': 'enable',
+ 'eapol_succ_intv': '41',
+ 'eapol_succ_thresh': '42',
+ 'invalid_mac_oui': 'enable',
+ 'long_duration_attack': 'enable',
+ 'long_duration_thresh': '45',
+ 'name': 'default_name_46',
+ 'null_ssid_probe_resp': 'enable',
+ 'sensor_mode': 'disable',
+ 'spoofed_deauth': 'enable',
+ 'weak_wep_iv': 'enable',
+ 'wireless_bridge': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wids_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'wids-profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_wids_profile_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wids_profile': {
+ 'ap_auto_suppress': 'enable',
+ 'ap_bgscan_disable_day': 'sunday',
+ 'ap_bgscan_disable_end': 'test_value_5',
+ 'ap_bgscan_disable_start': 'test_value_6',
+ 'ap_bgscan_duration': '7',
+ 'ap_bgscan_idle': '8',
+ 'ap_bgscan_intv': '9',
+ 'ap_bgscan_period': '10',
+ 'ap_bgscan_report_intv': '11',
+ 'ap_fgscan_report_intv': '12',
+ 'ap_scan': 'disable',
+ 'ap_scan_passive': 'enable',
+ 'asleap_attack': 'enable',
+ 'assoc_flood_thresh': '16',
+ 'assoc_flood_time': '17',
+ 'assoc_frame_flood': 'enable',
+ 'auth_flood_thresh': '19',
+ 'auth_flood_time': '20',
+ 'auth_frame_flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth_broadcast': 'enable',
+ 'deauth_unknown_src_thresh': '24',
+ 'eapol_fail_flood': 'enable',
+ 'eapol_fail_intv': '26',
+ 'eapol_fail_thresh': '27',
+ 'eapol_logoff_flood': 'enable',
+ 'eapol_logoff_intv': '29',
+ 'eapol_logoff_thresh': '30',
+ 'eapol_pre_fail_flood': 'enable',
+ 'eapol_pre_fail_intv': '32',
+ 'eapol_pre_fail_thresh': '33',
+ 'eapol_pre_succ_flood': 'enable',
+ 'eapol_pre_succ_intv': '35',
+ 'eapol_pre_succ_thresh': '36',
+ 'eapol_start_flood': 'enable',
+ 'eapol_start_intv': '38',
+ 'eapol_start_thresh': '39',
+ 'eapol_succ_flood': 'enable',
+ 'eapol_succ_intv': '41',
+ 'eapol_succ_thresh': '42',
+ 'invalid_mac_oui': 'enable',
+ 'long_duration_attack': 'enable',
+ 'long_duration_thresh': '45',
+ 'name': 'default_name_46',
+ 'null_ssid_probe_resp': 'enable',
+ 'sensor_mode': 'disable',
+ 'spoofed_deauth': 'enable',
+ 'weak_wep_iv': 'enable',
+ 'wireless_bridge': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wids_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-auto-suppress': 'enable',
+ 'ap-bgscan-disable-day': 'sunday',
+ 'ap-bgscan-disable-end': 'test_value_5',
+ 'ap-bgscan-disable-start': 'test_value_6',
+ 'ap-bgscan-duration': '7',
+ 'ap-bgscan-idle': '8',
+ 'ap-bgscan-intv': '9',
+ 'ap-bgscan-period': '10',
+ 'ap-bgscan-report-intv': '11',
+ 'ap-fgscan-report-intv': '12',
+ 'ap-scan': 'disable',
+ 'ap-scan-passive': 'enable',
+ 'asleap-attack': 'enable',
+ 'assoc-flood-thresh': '16',
+ 'assoc-flood-time': '17',
+ 'assoc-frame-flood': 'enable',
+ 'auth-flood-thresh': '19',
+ 'auth-flood-time': '20',
+ 'auth-frame-flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth-broadcast': 'enable',
+ 'deauth-unknown-src-thresh': '24',
+ 'eapol-fail-flood': 'enable',
+ 'eapol-fail-intv': '26',
+ 'eapol-fail-thresh': '27',
+ 'eapol-logoff-flood': 'enable',
+ 'eapol-logoff-intv': '29',
+ 'eapol-logoff-thresh': '30',
+ 'eapol-pre-fail-flood': 'enable',
+ 'eapol-pre-fail-intv': '32',
+ 'eapol-pre-fail-thresh': '33',
+ 'eapol-pre-succ-flood': 'enable',
+ 'eapol-pre-succ-intv': '35',
+ 'eapol-pre-succ-thresh': '36',
+ 'eapol-start-flood': 'enable',
+ 'eapol-start-intv': '38',
+ 'eapol-start-thresh': '39',
+ 'eapol-succ-flood': 'enable',
+ 'eapol-succ-intv': '41',
+ 'eapol-succ-thresh': '42',
+ 'invalid-mac-oui': 'enable',
+ 'long-duration-attack': 'enable',
+ 'long-duration-thresh': '45',
+ 'name': 'default_name_46',
+ 'null-ssid-probe-resp': 'enable',
+ 'sensor-mode': 'disable',
+ 'spoofed-deauth': 'enable',
+ 'weak-wep-iv': 'enable',
+ 'wireless-bridge': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wids-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_wids_profile_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wids_profile': {
+ 'random_attribute_not_valid': 'tag',
+ 'ap_auto_suppress': 'enable',
+ 'ap_bgscan_disable_day': 'sunday',
+ 'ap_bgscan_disable_end': 'test_value_5',
+ 'ap_bgscan_disable_start': 'test_value_6',
+ 'ap_bgscan_duration': '7',
+ 'ap_bgscan_idle': '8',
+ 'ap_bgscan_intv': '9',
+ 'ap_bgscan_period': '10',
+ 'ap_bgscan_report_intv': '11',
+ 'ap_fgscan_report_intv': '12',
+ 'ap_scan': 'disable',
+ 'ap_scan_passive': 'enable',
+ 'asleap_attack': 'enable',
+ 'assoc_flood_thresh': '16',
+ 'assoc_flood_time': '17',
+ 'assoc_frame_flood': 'enable',
+ 'auth_flood_thresh': '19',
+ 'auth_flood_time': '20',
+ 'auth_frame_flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth_broadcast': 'enable',
+ 'deauth_unknown_src_thresh': '24',
+ 'eapol_fail_flood': 'enable',
+ 'eapol_fail_intv': '26',
+ 'eapol_fail_thresh': '27',
+ 'eapol_logoff_flood': 'enable',
+ 'eapol_logoff_intv': '29',
+ 'eapol_logoff_thresh': '30',
+ 'eapol_pre_fail_flood': 'enable',
+ 'eapol_pre_fail_intv': '32',
+ 'eapol_pre_fail_thresh': '33',
+ 'eapol_pre_succ_flood': 'enable',
+ 'eapol_pre_succ_intv': '35',
+ 'eapol_pre_succ_thresh': '36',
+ 'eapol_start_flood': 'enable',
+ 'eapol_start_intv': '38',
+ 'eapol_start_thresh': '39',
+ 'eapol_succ_flood': 'enable',
+ 'eapol_succ_intv': '41',
+ 'eapol_succ_thresh': '42',
+ 'invalid_mac_oui': 'enable',
+ 'long_duration_attack': 'enable',
+ 'long_duration_thresh': '45',
+ 'name': 'default_name_46',
+ 'null_ssid_probe_resp': 'enable',
+ 'sensor_mode': 'disable',
+ 'spoofed_deauth': 'enable',
+ 'weak_wep_iv': 'enable',
+ 'wireless_bridge': 'enable'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wids_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'ap-auto-suppress': 'enable',
+ 'ap-bgscan-disable-day': 'sunday',
+ 'ap-bgscan-disable-end': 'test_value_5',
+ 'ap-bgscan-disable-start': 'test_value_6',
+ 'ap-bgscan-duration': '7',
+ 'ap-bgscan-idle': '8',
+ 'ap-bgscan-intv': '9',
+ 'ap-bgscan-period': '10',
+ 'ap-bgscan-report-intv': '11',
+ 'ap-fgscan-report-intv': '12',
+ 'ap-scan': 'disable',
+ 'ap-scan-passive': 'enable',
+ 'asleap-attack': 'enable',
+ 'assoc-flood-thresh': '16',
+ 'assoc-flood-time': '17',
+ 'assoc-frame-flood': 'enable',
+ 'auth-flood-thresh': '19',
+ 'auth-flood-time': '20',
+ 'auth-frame-flood': 'enable',
+ 'comment': 'Comment.',
+ 'deauth-broadcast': 'enable',
+ 'deauth-unknown-src-thresh': '24',
+ 'eapol-fail-flood': 'enable',
+ 'eapol-fail-intv': '26',
+ 'eapol-fail-thresh': '27',
+ 'eapol-logoff-flood': 'enable',
+ 'eapol-logoff-intv': '29',
+ 'eapol-logoff-thresh': '30',
+ 'eapol-pre-fail-flood': 'enable',
+ 'eapol-pre-fail-intv': '32',
+ 'eapol-pre-fail-thresh': '33',
+ 'eapol-pre-succ-flood': 'enable',
+ 'eapol-pre-succ-intv': '35',
+ 'eapol-pre-succ-thresh': '36',
+ 'eapol-start-flood': 'enable',
+ 'eapol-start-intv': '38',
+ 'eapol-start-thresh': '39',
+ 'eapol-succ-flood': 'enable',
+ 'eapol-succ-intv': '41',
+ 'eapol-succ-thresh': '42',
+ 'invalid-mac-oui': 'enable',
+ 'long-duration-attack': 'enable',
+ 'long-duration-thresh': '45',
+ 'name': 'default_name_46',
+ 'null-ssid-probe-resp': 'enable',
+ 'sensor-mode': 'disable',
+ 'spoofed-deauth': 'enable',
+ 'weak-wep-iv': 'enable',
+ 'wireless-bridge': 'enable'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wids-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_wtp.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_wtp.py
new file mode 100644
index 0000000000..aea02faba5
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_wtp.py
@@ -0,0 +1,509 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_wtp
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_wtp.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_wtp_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp': {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour_profile': 'test_value_5',
+ 'coordinate_enable': 'enable',
+ 'coordinate_latitude': 'test_value_7',
+ 'coordinate_longitude': 'test_value_8',
+ 'coordinate_x': 'test_value_9',
+ 'coordinate_y': 'test_value_10',
+ 'image_download': 'enable',
+ 'index': '12',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'location': 'test_value_15',
+ 'login_passwd': 'test_value_16',
+ 'login_passwd_change': 'yes',
+ 'mesh_bridge_enable': 'default',
+ 'name': 'default_name_19',
+ 'override_allowaccess': 'enable',
+ 'override_ip_fragment': 'enable',
+ 'override_lan': 'enable',
+ 'override_led_state': 'enable',
+ 'override_login_passwd_change': 'enable',
+ 'override_split_tunnel': 'enable',
+ 'override_wan_port_mode': 'enable',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '29',
+ 'tun_mtu_uplink': '30',
+ 'wan_port_mode': 'wan-lan',
+ 'wtp_id': 'test_value_32',
+ 'wtp_mode': 'normal',
+ 'wtp_profile': 'test_value_34'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour-profile': 'test_value_5',
+ 'coordinate-enable': 'enable',
+ 'coordinate-latitude': 'test_value_7',
+ 'coordinate-longitude': 'test_value_8',
+ 'coordinate-x': 'test_value_9',
+ 'coordinate-y': 'test_value_10',
+ 'image-download': 'enable',
+ 'index': '12',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'location': 'test_value_15',
+ 'login-passwd': 'test_value_16',
+ 'login-passwd-change': 'yes',
+ 'mesh-bridge-enable': 'default',
+ 'name': 'default_name_19',
+ 'override-allowaccess': 'enable',
+ 'override-ip-fragment': 'enable',
+ 'override-lan': 'enable',
+ 'override-led-state': 'enable',
+ 'override-login-passwd-change': 'enable',
+ 'override-split-tunnel': 'enable',
+ 'override-wan-port-mode': 'enable',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '29',
+ 'tun-mtu-uplink': '30',
+ 'wan-port-mode': 'wan-lan',
+ 'wtp-id': 'test_value_32',
+ 'wtp-mode': 'normal',
+ 'wtp-profile': 'test_value_34'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_wtp_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp': {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour_profile': 'test_value_5',
+ 'coordinate_enable': 'enable',
+ 'coordinate_latitude': 'test_value_7',
+ 'coordinate_longitude': 'test_value_8',
+ 'coordinate_x': 'test_value_9',
+ 'coordinate_y': 'test_value_10',
+ 'image_download': 'enable',
+ 'index': '12',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'location': 'test_value_15',
+ 'login_passwd': 'test_value_16',
+ 'login_passwd_change': 'yes',
+ 'mesh_bridge_enable': 'default',
+ 'name': 'default_name_19',
+ 'override_allowaccess': 'enable',
+ 'override_ip_fragment': 'enable',
+ 'override_lan': 'enable',
+ 'override_led_state': 'enable',
+ 'override_login_passwd_change': 'enable',
+ 'override_split_tunnel': 'enable',
+ 'override_wan_port_mode': 'enable',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '29',
+ 'tun_mtu_uplink': '30',
+ 'wan_port_mode': 'wan-lan',
+ 'wtp_id': 'test_value_32',
+ 'wtp_mode': 'normal',
+ 'wtp_profile': 'test_value_34'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour-profile': 'test_value_5',
+ 'coordinate-enable': 'enable',
+ 'coordinate-latitude': 'test_value_7',
+ 'coordinate-longitude': 'test_value_8',
+ 'coordinate-x': 'test_value_9',
+ 'coordinate-y': 'test_value_10',
+ 'image-download': 'enable',
+ 'index': '12',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'location': 'test_value_15',
+ 'login-passwd': 'test_value_16',
+ 'login-passwd-change': 'yes',
+ 'mesh-bridge-enable': 'default',
+ 'name': 'default_name_19',
+ 'override-allowaccess': 'enable',
+ 'override-ip-fragment': 'enable',
+ 'override-lan': 'enable',
+ 'override-led-state': 'enable',
+ 'override-login-passwd-change': 'enable',
+ 'override-split-tunnel': 'enable',
+ 'override-wan-port-mode': 'enable',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '29',
+ 'tun-mtu-uplink': '30',
+ 'wan-port-mode': 'wan-lan',
+ 'wtp-id': 'test_value_32',
+ 'wtp-mode': 'normal',
+ 'wtp-profile': 'test_value_34'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_wtp_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_wtp': {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour_profile': 'test_value_5',
+ 'coordinate_enable': 'enable',
+ 'coordinate_latitude': 'test_value_7',
+ 'coordinate_longitude': 'test_value_8',
+ 'coordinate_x': 'test_value_9',
+ 'coordinate_y': 'test_value_10',
+ 'image_download': 'enable',
+ 'index': '12',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'location': 'test_value_15',
+ 'login_passwd': 'test_value_16',
+ 'login_passwd_change': 'yes',
+ 'mesh_bridge_enable': 'default',
+ 'name': 'default_name_19',
+ 'override_allowaccess': 'enable',
+ 'override_ip_fragment': 'enable',
+ 'override_lan': 'enable',
+ 'override_led_state': 'enable',
+ 'override_login_passwd_change': 'enable',
+ 'override_split_tunnel': 'enable',
+ 'override_wan_port_mode': 'enable',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '29',
+ 'tun_mtu_uplink': '30',
+ 'wan_port_mode': 'wan-lan',
+ 'wtp_id': 'test_value_32',
+ 'wtp_mode': 'normal',
+ 'wtp_profile': 'test_value_34'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'wtp', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_wtp_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_wtp': {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour_profile': 'test_value_5',
+ 'coordinate_enable': 'enable',
+ 'coordinate_latitude': 'test_value_7',
+ 'coordinate_longitude': 'test_value_8',
+ 'coordinate_x': 'test_value_9',
+ 'coordinate_y': 'test_value_10',
+ 'image_download': 'enable',
+ 'index': '12',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'location': 'test_value_15',
+ 'login_passwd': 'test_value_16',
+ 'login_passwd_change': 'yes',
+ 'mesh_bridge_enable': 'default',
+ 'name': 'default_name_19',
+ 'override_allowaccess': 'enable',
+ 'override_ip_fragment': 'enable',
+ 'override_lan': 'enable',
+ 'override_led_state': 'enable',
+ 'override_login_passwd_change': 'enable',
+ 'override_split_tunnel': 'enable',
+ 'override_wan_port_mode': 'enable',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '29',
+ 'tun_mtu_uplink': '30',
+ 'wan_port_mode': 'wan-lan',
+ 'wtp_id': 'test_value_32',
+ 'wtp_mode': 'normal',
+ 'wtp_profile': 'test_value_34'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'wtp', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_wtp_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp': {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour_profile': 'test_value_5',
+ 'coordinate_enable': 'enable',
+ 'coordinate_latitude': 'test_value_7',
+ 'coordinate_longitude': 'test_value_8',
+ 'coordinate_x': 'test_value_9',
+ 'coordinate_y': 'test_value_10',
+ 'image_download': 'enable',
+ 'index': '12',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'location': 'test_value_15',
+ 'login_passwd': 'test_value_16',
+ 'login_passwd_change': 'yes',
+ 'mesh_bridge_enable': 'default',
+ 'name': 'default_name_19',
+ 'override_allowaccess': 'enable',
+ 'override_ip_fragment': 'enable',
+ 'override_lan': 'enable',
+ 'override_led_state': 'enable',
+ 'override_login_passwd_change': 'enable',
+ 'override_split_tunnel': 'enable',
+ 'override_wan_port_mode': 'enable',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '29',
+ 'tun_mtu_uplink': '30',
+ 'wan_port_mode': 'wan-lan',
+ 'wtp_id': 'test_value_32',
+ 'wtp_mode': 'normal',
+ 'wtp_profile': 'test_value_34'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour-profile': 'test_value_5',
+ 'coordinate-enable': 'enable',
+ 'coordinate-latitude': 'test_value_7',
+ 'coordinate-longitude': 'test_value_8',
+ 'coordinate-x': 'test_value_9',
+ 'coordinate-y': 'test_value_10',
+ 'image-download': 'enable',
+ 'index': '12',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'location': 'test_value_15',
+ 'login-passwd': 'test_value_16',
+ 'login-passwd-change': 'yes',
+ 'mesh-bridge-enable': 'default',
+ 'name': 'default_name_19',
+ 'override-allowaccess': 'enable',
+ 'override-ip-fragment': 'enable',
+ 'override-lan': 'enable',
+ 'override-led-state': 'enable',
+ 'override-login-passwd-change': 'enable',
+ 'override-split-tunnel': 'enable',
+ 'override-wan-port-mode': 'enable',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '29',
+ 'tun-mtu-uplink': '30',
+ 'wan-port-mode': 'wan-lan',
+ 'wtp-id': 'test_value_32',
+ 'wtp-mode': 'normal',
+ 'wtp-profile': 'test_value_34'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_wtp_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp': {
+ 'random_attribute_not_valid': 'tag',
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour_profile': 'test_value_5',
+ 'coordinate_enable': 'enable',
+ 'coordinate_latitude': 'test_value_7',
+ 'coordinate_longitude': 'test_value_8',
+ 'coordinate_x': 'test_value_9',
+ 'coordinate_y': 'test_value_10',
+ 'image_download': 'enable',
+ 'index': '12',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'location': 'test_value_15',
+ 'login_passwd': 'test_value_16',
+ 'login_passwd_change': 'yes',
+ 'mesh_bridge_enable': 'default',
+ 'name': 'default_name_19',
+ 'override_allowaccess': 'enable',
+ 'override_ip_fragment': 'enable',
+ 'override_lan': 'enable',
+ 'override_led_state': 'enable',
+ 'override_login_passwd_change': 'enable',
+ 'override_split_tunnel': 'enable',
+ 'override_wan_port_mode': 'enable',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '29',
+ 'tun_mtu_uplink': '30',
+ 'wan_port_mode': 'wan-lan',
+ 'wtp_id': 'test_value_32',
+ 'wtp_mode': 'normal',
+ 'wtp_profile': 'test_value_34'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'admin': 'discovered',
+ 'allowaccess': 'telnet',
+ 'bonjour-profile': 'test_value_5',
+ 'coordinate-enable': 'enable',
+ 'coordinate-latitude': 'test_value_7',
+ 'coordinate-longitude': 'test_value_8',
+ 'coordinate-x': 'test_value_9',
+ 'coordinate-y': 'test_value_10',
+ 'image-download': 'enable',
+ 'index': '12',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'location': 'test_value_15',
+ 'login-passwd': 'test_value_16',
+ 'login-passwd-change': 'yes',
+ 'mesh-bridge-enable': 'default',
+ 'name': 'default_name_19',
+ 'override-allowaccess': 'enable',
+ 'override-ip-fragment': 'enable',
+ 'override-lan': 'enable',
+ 'override-led-state': 'enable',
+ 'override-login-passwd-change': 'enable',
+ 'override-split-tunnel': 'enable',
+ 'override-wan-port-mode': 'enable',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '29',
+ 'tun-mtu-uplink': '30',
+ 'wan-port-mode': 'wan-lan',
+ 'wtp-id': 'test_value_32',
+ 'wtp-mode': 'normal',
+ 'wtp-profile': 'test_value_34'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
diff --git a/test/units/modules/network/fortios/test_fortios_wireless_controller_wtp_profile.py b/test/units/modules/network/fortios/test_fortios_wireless_controller_wtp_profile.py
new file mode 100644
index 0000000000..d578db5802
--- /dev/null
+++ b/test/units/modules/network/fortios/test_fortios_wireless_controller_wtp_profile.py
@@ -0,0 +1,439 @@
+# Copyright 2019 Fortinet, Inc.
+#
+# This program is free software: you can redistribute it and/or modify
+# it under the terms of the GNU General Public License as published by
+# the Free Software Foundation, either version 3 of the License, or
+# (at your option) any later version.
+#
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+# GNU General Public License for more details.
+#
+# You should have received a copy of the GNU General Public License
+# along with Ansible. If not, see <https://www.gnu.org/licenses/>.
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+import pytest
+from mock import ANY
+from ansible.module_utils.network.fortios.fortios import FortiOSHandler
+
+try:
+ from ansible.modules.network.fortios import fortios_wireless_controller_wtp_profile
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortios.fortios_wireless_controller_wtp_profile.Connection')
+ return connection_class_mock
+
+
+fos_instance = FortiOSHandler(connection_mock)
+
+
+def test_wireless_controller_wtp_profile_creation(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp_profile': {
+ 'allowaccess': 'telnet',
+ 'ap_country': 'NA',
+ 'ble_profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control_message_offload': 'ebp-frame',
+ 'dtls_in_kernel': 'enable',
+ 'dtls_policy': 'clear-text',
+ 'energy_efficient_ethernet': 'enable',
+ 'ext_info_enable': 'enable',
+ 'handoff_roaming': 'enable',
+ 'handoff_rssi': '13',
+ 'handoff_sta_thresh': '14',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'lldp': 'enable',
+ 'login_passwd': 'test_value_18',
+ 'login_passwd_change': 'yes',
+ 'max_clients': '20',
+ 'name': 'default_name_21',
+ 'poe_mode': 'auto',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '25',
+ 'tun_mtu_uplink': '26',
+ 'wan_port_mode': 'wan-lan'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'allowaccess': 'telnet',
+ 'ap-country': 'NA',
+ 'ble-profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control-message-offload': 'ebp-frame',
+ 'dtls-in-kernel': 'enable',
+ 'dtls-policy': 'clear-text',
+ 'energy-efficient-ethernet': 'enable',
+ 'ext-info-enable': 'enable',
+ 'handoff-roaming': 'enable',
+ 'handoff-rssi': '13',
+ 'handoff-sta-thresh': '14',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'lldp': 'enable',
+ 'login-passwd': 'test_value_18',
+ 'login-passwd-change': 'yes',
+ 'max-clients': '20',
+ 'name': 'default_name_21',
+ 'poe-mode': 'auto',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '25',
+ 'tun-mtu-uplink': '26',
+ 'wan-port-mode': 'wan-lan'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_wtp_profile_creation_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp_profile': {
+ 'allowaccess': 'telnet',
+ 'ap_country': 'NA',
+ 'ble_profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control_message_offload': 'ebp-frame',
+ 'dtls_in_kernel': 'enable',
+ 'dtls_policy': 'clear-text',
+ 'energy_efficient_ethernet': 'enable',
+ 'ext_info_enable': 'enable',
+ 'handoff_roaming': 'enable',
+ 'handoff_rssi': '13',
+ 'handoff_sta_thresh': '14',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'lldp': 'enable',
+ 'login_passwd': 'test_value_18',
+ 'login_passwd_change': 'yes',
+ 'max_clients': '20',
+ 'name': 'default_name_21',
+ 'poe_mode': 'auto',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '25',
+ 'tun_mtu_uplink': '26',
+ 'wan_port_mode': 'wan-lan'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'allowaccess': 'telnet',
+ 'ap-country': 'NA',
+ 'ble-profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control-message-offload': 'ebp-frame',
+ 'dtls-in-kernel': 'enable',
+ 'dtls-policy': 'clear-text',
+ 'energy-efficient-ethernet': 'enable',
+ 'ext-info-enable': 'enable',
+ 'handoff-roaming': 'enable',
+ 'handoff-rssi': '13',
+ 'handoff-sta-thresh': '14',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'lldp': 'enable',
+ 'login-passwd': 'test_value_18',
+ 'login-passwd-change': 'yes',
+ 'max-clients': '20',
+ 'name': 'default_name_21',
+ 'poe-mode': 'auto',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '25',
+ 'tun-mtu-uplink': '26',
+ 'wan-port-mode': 'wan-lan'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_wtp_profile_removal(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_wtp_profile': {
+ 'allowaccess': 'telnet',
+ 'ap_country': 'NA',
+ 'ble_profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control_message_offload': 'ebp-frame',
+ 'dtls_in_kernel': 'enable',
+ 'dtls_policy': 'clear-text',
+ 'energy_efficient_ethernet': 'enable',
+ 'ext_info_enable': 'enable',
+ 'handoff_roaming': 'enable',
+ 'handoff_rssi': '13',
+ 'handoff_sta_thresh': '14',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'lldp': 'enable',
+ 'login_passwd': 'test_value_18',
+ 'login_passwd_change': 'yes',
+ 'max_clients': '20',
+ 'name': 'default_name_21',
+ 'poe_mode': 'auto',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '25',
+ 'tun_mtu_uplink': '26',
+ 'wan_port_mode': 'wan-lan'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'wtp-profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200
+
+
+def test_wireless_controller_wtp_profile_deletion_fails(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ delete_method_result = {'status': 'error', 'http_method': 'POST', 'http_status': 500}
+ delete_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.delete', return_value=delete_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'absent',
+ 'wireless_controller_wtp_profile': {
+ 'allowaccess': 'telnet',
+ 'ap_country': 'NA',
+ 'ble_profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control_message_offload': 'ebp-frame',
+ 'dtls_in_kernel': 'enable',
+ 'dtls_policy': 'clear-text',
+ 'energy_efficient_ethernet': 'enable',
+ 'ext_info_enable': 'enable',
+ 'handoff_roaming': 'enable',
+ 'handoff_rssi': '13',
+ 'handoff_sta_thresh': '14',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'lldp': 'enable',
+ 'login_passwd': 'test_value_18',
+ 'login_passwd_change': 'yes',
+ 'max_clients': '20',
+ 'name': 'default_name_21',
+ 'poe_mode': 'auto',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '25',
+ 'tun_mtu_uplink': '26',
+ 'wan_port_mode': 'wan-lan'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ delete_method_mock.assert_called_with('wireless-controller', 'wtp-profile', mkey=ANY, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 500
+
+
+def test_wireless_controller_wtp_profile_idempotent(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'error', 'http_method': 'DELETE', 'http_status': 404}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp_profile': {
+ 'allowaccess': 'telnet',
+ 'ap_country': 'NA',
+ 'ble_profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control_message_offload': 'ebp-frame',
+ 'dtls_in_kernel': 'enable',
+ 'dtls_policy': 'clear-text',
+ 'energy_efficient_ethernet': 'enable',
+ 'ext_info_enable': 'enable',
+ 'handoff_roaming': 'enable',
+ 'handoff_rssi': '13',
+ 'handoff_sta_thresh': '14',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'lldp': 'enable',
+ 'login_passwd': 'test_value_18',
+ 'login_passwd_change': 'yes',
+ 'max_clients': '20',
+ 'name': 'default_name_21',
+ 'poe_mode': 'auto',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '25',
+ 'tun_mtu_uplink': '26',
+ 'wan_port_mode': 'wan-lan'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'allowaccess': 'telnet',
+ 'ap-country': 'NA',
+ 'ble-profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control-message-offload': 'ebp-frame',
+ 'dtls-in-kernel': 'enable',
+ 'dtls-policy': 'clear-text',
+ 'energy-efficient-ethernet': 'enable',
+ 'ext-info-enable': 'enable',
+ 'handoff-roaming': 'enable',
+ 'handoff-rssi': '13',
+ 'handoff-sta-thresh': '14',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'lldp': 'enable',
+ 'login-passwd': 'test_value_18',
+ 'login-passwd-change': 'yes',
+ 'max-clients': '20',
+ 'name': 'default_name_21',
+ 'poe-mode': 'auto',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '25',
+ 'tun-mtu-uplink': '26',
+ 'wan-port-mode': 'wan-lan'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert not changed
+ assert response['status'] == 'error'
+ assert response['http_status'] == 404
+
+
+def test_wireless_controller_wtp_profile_filter_foreign_attributes(mocker):
+ schema_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.schema')
+
+ set_method_result = {'status': 'success', 'http_method': 'POST', 'http_status': 200}
+ set_method_mock = mocker.patch('ansible.module_utils.network.fortios.fortios.FortiOSHandler.set', return_value=set_method_result)
+
+ input_data = {
+ 'username': 'admin',
+ 'state': 'present',
+ 'wireless_controller_wtp_profile': {
+ 'random_attribute_not_valid': 'tag',
+ 'allowaccess': 'telnet',
+ 'ap_country': 'NA',
+ 'ble_profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control_message_offload': 'ebp-frame',
+ 'dtls_in_kernel': 'enable',
+ 'dtls_policy': 'clear-text',
+ 'energy_efficient_ethernet': 'enable',
+ 'ext_info_enable': 'enable',
+ 'handoff_roaming': 'enable',
+ 'handoff_rssi': '13',
+ 'handoff_sta_thresh': '14',
+ 'ip_fragment_preventing': 'tcp-mss-adjust',
+ 'led_state': 'enable',
+ 'lldp': 'enable',
+ 'login_passwd': 'test_value_18',
+ 'login_passwd_change': 'yes',
+ 'max_clients': '20',
+ 'name': 'default_name_21',
+ 'poe_mode': 'auto',
+ 'split_tunneling_acl_local_ap_subnet': 'enable',
+ 'split_tunneling_acl_path': 'tunnel',
+ 'tun_mtu_downlink': '25',
+ 'tun_mtu_uplink': '26',
+ 'wan_port_mode': 'wan-lan'
+ },
+ 'vdom': 'root'}
+
+ is_error, changed, response = fortios_wireless_controller_wtp_profile.fortios_wireless_controller(input_data, fos_instance)
+
+ expected_data = {
+ 'allowaccess': 'telnet',
+ 'ap-country': 'NA',
+ 'ble-profile': 'test_value_5',
+ 'comment': 'Comment.',
+ 'control-message-offload': 'ebp-frame',
+ 'dtls-in-kernel': 'enable',
+ 'dtls-policy': 'clear-text',
+ 'energy-efficient-ethernet': 'enable',
+ 'ext-info-enable': 'enable',
+ 'handoff-roaming': 'enable',
+ 'handoff-rssi': '13',
+ 'handoff-sta-thresh': '14',
+ 'ip-fragment-preventing': 'tcp-mss-adjust',
+ 'led-state': 'enable',
+ 'lldp': 'enable',
+ 'login-passwd': 'test_value_18',
+ 'login-passwd-change': 'yes',
+ 'max-clients': '20',
+ 'name': 'default_name_21',
+ 'poe-mode': 'auto',
+ 'split-tunneling-acl-local-ap-subnet': 'enable',
+ 'split-tunneling-acl-path': 'tunnel',
+ 'tun-mtu-downlink': '25',
+ 'tun-mtu-uplink': '26',
+ 'wan-port-mode': 'wan-lan'
+ }
+
+ set_method_mock.assert_called_with('wireless-controller', 'wtp-profile', data=expected_data, vdom='root')
+ schema_method_mock.assert_not_called()
+ assert not is_error
+ assert changed
+ assert response['status'] == 'success'
+ assert response['http_status'] == 200