FortiOS modules for 2.9 - 9 (#61320)

* FortiOS modules for 2.9 - 9

* Undo ignore file

* Remove non valid identifiers

* Leave fortios_switch_controller_lldp_profile and fortios_switch_controller_managed_switch out of this PR

* Updated fortios_switch_controller_lldp_profile and fortios_switch_controller_managed_switch
pull/61368/head
Miguel Angel Muñoz González 5 years ago committed by Nilashish Chakraborty
parent 0074fa5672
commit e62fb1e2f9

@ -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_spamfilter_profile
short_description: Configure AntiSpam 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 spamfilter 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)
@ -44,87 +41,110 @@ 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
spamfilter_profile:
description:
- Configure AntiSpam profiles.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
comment:
description:
- Comment.
type: str
external:
description:
- Enable/disable external Email inspection.
type: str
choices:
- enable
- disable
flow-based:
flow_based:
description:
- Enable/disable flow-based spam filtering.
type: str
choices:
- enable
- disable
gmail:
description:
- Gmail.
type: dict
suboptions:
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
imap:
description:
- IMAP.
type: dict
suboptions:
action:
description:
- Action for spam email.
type: str
choices:
- pass
- tag
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
tag-msg:
tag_msg:
description:
- Subject text or header added to spam email.
tag-type:
type: str
tag_type:
description:
- Tag subject or header for spam email.
type: list
choices:
- subject
- header
@ -132,26 +152,31 @@ options:
mapi:
description:
- MAPI.
type: dict
suboptions:
action:
description:
- Action for spam email.
type: str
choices:
- pass
- discard
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
msn-hotmail:
msn_hotmail:
description:
- MSN Hotmail.
type: dict
suboptions:
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
@ -159,9 +184,11 @@ options:
description:
- Profile name.
required: true
type: str
options:
description:
- Options.
type: list
choices:
- bannedword
- spambwl
@ -177,39 +204,47 @@ options:
pop3:
description:
- POP3.
type: dict
suboptions:
action:
description:
- Action for spam email.
type: str
choices:
- pass
- tag
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
tag-msg:
tag_msg:
description:
- Subject text or header added to spam email.
tag-type:
type: str
tag_type:
description:
- Tag subject or header for spam email.
type: list
choices:
- subject
- header
- spaminfo
replacemsg-group:
replacemsg_group:
description:
- Replacement message group. Source system.replacemsg-group.name.
type: str
smtp:
description:
- SMTP.
type: dict
suboptions:
action:
description:
- Action for spam email.
type: str
choices:
- pass
- tag
@ -217,74 +252,90 @@ options:
hdrip:
description:
- Enable/disable SMTP email header IP checks for spamfsip, spamrbl and spambwl filters.
type: str
choices:
- disable
- enable
local-override:
local_override:
description:
- Enable/disable local filter to override SMTP remote check result.
type: str
choices:
- disable
- enable
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
tag-msg:
tag_msg:
description:
- Subject text or header added to spam email.
tag-type:
type: str
tag_type:
description:
- Tag subject or header for spam email.
type: list
choices:
- subject
- header
- spaminfo
spam-bwl-table:
spam_bwl_table:
description:
- Anti-spam black/white list table ID. Source spamfilter.bwl.id.
spam-bword-table:
type: int
spam_bword_table:
description:
- Anti-spam banned word table ID. Source spamfilter.bword.id.
spam-bword-threshold:
type: int
spam_bword_threshold:
description:
- Spam banned word threshold.
spam-filtering:
type: int
spam_filtering:
description:
- Enable/disable spam filtering.
type: str
choices:
- enable
- disable
spam-iptrust-table:
spam_iptrust_table:
description:
- Anti-spam IP trust table ID. Source spamfilter.iptrust.id.
spam-log:
type: int
spam_log:
description:
- Enable/disable spam logging for email filtering.
type: str
choices:
- disable
- enable
spam-log-fortiguard-response:
spam_log_fortiguard_response:
description:
- Enable/disable logging FortiGuard spam response.
type: str
choices:
- disable
- enable
spam-mheader-table:
spam_mheader_table:
description:
- Anti-spam MIME header table ID. Source spamfilter.mheader.id.
spam-rbl-table:
type: int
spam_rbl_table:
description:
- Anti-spam DNSBL table ID. Source spamfilter.dnsbl.id.
yahoo-mail:
type: int
yahoo_mail:
description:
- Yahoo! Mail.
type: dict
suboptions:
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
@ -297,6 +348,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure AntiSpam profiles.
fortios_spamfilter_profile:
@ -305,48 +357,48 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
spamfilter_profile:
state: "present"
comment: "Comment."
external: "enable"
flow-based: "enable"
flow_based: "enable"
gmail:
log: "enable"
imap:
action: "pass"
log: "enable"
tag-msg: "<your_own_value>"
tag-type: "subject"
tag_msg: "<your_own_value>"
tag_type: "subject"
mapi:
action: "pass"
log: "enable"
msn-hotmail:
msn_hotmail:
log: "enable"
name: "default_name_18"
options: "bannedword"
pop3:
action: "pass"
log: "enable"
tag-msg: "<your_own_value>"
tag-type: "subject"
replacemsg-group: "<your_own_value> (source system.replacemsg-group.name)"
tag_msg: "<your_own_value>"
tag_type: "subject"
replacemsg_group: "<your_own_value> (source system.replacemsg-group.name)"
smtp:
action: "pass"
hdrip: "disable"
local-override: "disable"
local_override: "disable"
log: "enable"
tag-msg: "<your_own_value>"
tag-type: "subject"
spam-bwl-table: "33 (source spamfilter.bwl.id)"
spam-bword-table: "34 (source spamfilter.bword.id)"
spam-bword-threshold: "35"
spam-filtering: "enable"
spam-iptrust-table: "37 (source spamfilter.iptrust.id)"
spam-log: "disable"
spam-log-fortiguard-response: "disable"
spam-mheader-table: "40 (source spamfilter.mheader.id)"
spam-rbl-table: "41 (source spamfilter.dnsbl.id)"
yahoo-mail:
tag_msg: "<your_own_value>"
tag_type: "subject"
spam_bwl_table: "33 (source spamfilter.bwl.id)"
spam_bword_table: "34 (source spamfilter.bword.id)"
spam_bword_threshold: "35"
spam_filtering: "enable"
spam_iptrust_table: "37 (source spamfilter.iptrust.id)"
spam_log: "disable"
spam_log_fortiguard_response: "disable"
spam_mheader_table: "40 (source spamfilter.mheader.id)"
spam_rbl_table: "41 (source spamfilter.dnsbl.id)"
yahoo_mail:
log: "enable"
'''
@ -410,14 +462,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']:
@ -425,18 +479,18 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_spamfilter_profile_data(json):
option_list = ['comment', 'external', 'flow-based',
option_list = ['comment', 'external', 'flow_based',
'gmail', 'imap', 'mapi',
'msn-hotmail', 'name', 'options',
'pop3', 'replacemsg-group', 'smtp',
'spam-bwl-table', 'spam-bword-table', 'spam-bword-threshold',
'spam-filtering', 'spam-iptrust-table', 'spam-log',
'spam-log-fortiguard-response', 'spam-mheader-table', 'spam-rbl-table',
'yahoo-mail']
'msn_hotmail', 'name', 'options',
'pop3', 'replacemsg_group', 'smtp',
'spam_bwl_table', 'spam_bword_table', 'spam_bword_threshold',
'spam_filtering', 'spam_iptrust_table', 'spam_log',
'spam_log_fortiguard_response', 'spam_mheader_table', 'spam_rbl_table',
'yahoo_mail']
dictionary = {}
for attribute in option_list:
@ -447,7 +501,7 @@ def filter_spamfilter_profile_data(json):
def flatten_multilists_attributes(data):
multilist_attrs = [[u'options'], [u'imap', u'tag-type'], [u'pop3', u'tag-type'], [u'smtp', u'tag-type']]
multilist_attrs = [[u'options'], [u'imap', u'tag_type'], [u'pop3', u'tag_type'], [u'smtp', u'tag_type']]
for attr in multilist_attrs:
try:
@ -461,50 +515,71 @@ def flatten_multilists_attributes(data):
return data
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 spamfilter_profile(data, fos):
vdom = data['vdom']
state = data['state']
spamfilter_profile_data = data['spamfilter_profile']
flattened_data = flatten_multilists_attributes(spamfilter_profile_data)
filtered_data = filter_spamfilter_profile_data(flattened_data)
if spamfilter_profile_data['state'] == "present":
spamfilter_profile_data = flatten_multilists_attributes(spamfilter_profile_data)
filtered_data = underscore_to_hyphen(filter_spamfilter_profile_data(spamfilter_profile_data))
if state == "present":
return fos.set('spamfilter',
'profile',
data=filtered_data,
vdom=vdom)
elif spamfilter_profile_data['state'] == "absent":
elif state == "absent":
return fos.delete('spamfilter',
'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_spamfilter(data, fos):
login(data)
if data['spamfilter_profile']:
resp = spamfilter_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"]},
"spamfilter_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"},
"external": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"flow-based": {"required": False, "type": "str",
"flow_based": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"gmail": {"required": False, "type": "dict",
"options": {
@ -517,8 +592,8 @@ def main():
"choices": ["pass", "tag"]},
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"tag-msg": {"required": False, "type": "str"},
"tag-type": {"required": False, "type": "list",
"tag_msg": {"required": False, "type": "str"},
"tag_type": {"required": False, "type": "list",
"choices": ["subject", "header", "spaminfo"]}
}},
"mapi": {"required": False, "type": "dict",
@ -528,7 +603,7 @@ def main():
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}},
"msn-hotmail": {"required": False, "type": "dict",
"msn_hotmail": {"required": False, "type": "dict",
"options": {
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
@ -545,38 +620,38 @@ def main():
"choices": ["pass", "tag"]},
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"tag-msg": {"required": False, "type": "str"},
"tag-type": {"required": False, "type": "list",
"tag_msg": {"required": False, "type": "str"},
"tag_type": {"required": False, "type": "list",
"choices": ["subject", "header", "spaminfo"]}
}},
"replacemsg-group": {"required": False, "type": "str"},
"replacemsg_group": {"required": False, "type": "str"},
"smtp": {"required": False, "type": "dict",
"options": {
"action": {"required": False, "type": "str",
"choices": ["pass", "tag", "discard"]},
"hdrip": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"local-override": {"required": False, "type": "str",
"local_override": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"tag-msg": {"required": False, "type": "str"},
"tag-type": {"required": False, "type": "list",
"tag_msg": {"required": False, "type": "str"},
"tag_type": {"required": False, "type": "list",
"choices": ["subject", "header", "spaminfo"]}
}},
"spam-bwl-table": {"required": False, "type": "int"},
"spam-bword-table": {"required": False, "type": "int"},
"spam-bword-threshold": {"required": False, "type": "int"},
"spam-filtering": {"required": False, "type": "str",
"spam_bwl_table": {"required": False, "type": "int"},
"spam_bword_table": {"required": False, "type": "int"},
"spam_bword_threshold": {"required": False, "type": "int"},
"spam_filtering": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"spam-iptrust-table": {"required": False, "type": "int"},
"spam-log": {"required": False, "type": "str",
"spam_iptrust_table": {"required": False, "type": "int"},
"spam_log": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"spam-log-fortiguard-response": {"required": False, "type": "str",
"spam_log_fortiguard_response": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"spam-mheader-table": {"required": False, "type": "int"},
"spam-rbl-table": {"required": False, "type": "int"},
"yahoo-mail": {"required": False, "type": "dict",
"spam_mheader_table": {"required": False, "type": "int"},
"spam_rbl_table": {"required": False, "type": "int"},
"yahoo_mail": {"required": False, "type": "dict",
"options": {
"log": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
@ -588,15 +663,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_spamfilter(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_spamfilter(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_spamfilter(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_ssh_filter_profile
short_description: SSH filter 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 ssh_filter 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)
@ -44,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
ssh_filter_profile:
description:
- SSH filter profile.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
block:
description:
- SSH blocking options.
type: str
choices:
- x11
- shell
@ -89,15 +100,17 @@ options:
- tun-forward
- sftp
- unknown
default-command-log:
default_command_log:
description:
- Enable/disable logging unmatched shell commands.
type: str
choices:
- enable
- disable
log:
description:
- SSH logging options.
type: str
choices:
- x11
- shell
@ -110,19 +123,23 @@ options:
description:
- SSH filter profile name.
required: true
shell-commands:
type: str
shell_commands:
description:
- SSH command filter.
type: list
suboptions:
action:
description:
- Action to take for URL filter matches.
type: str
choices:
- block
- allow
alert:
description:
- Enable/disable alert.
type: str
choices:
- enable
- disable
@ -130,18 +147,22 @@ options:
description:
- Id.
required: true
type: int
log:
description:
- Enable/disable logging.
type: str
choices:
- enable
- disable
pattern:
description:
- SSH shell command pattern.
type: str
severity:
description:
- Log severity.
type: str
choices:
- low
- medium
@ -150,6 +171,7 @@ options:
type:
description:
- Matching type.
type: str
choices:
- simple
- regex
@ -162,6 +184,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: SSH filter profile.
fortios_ssh_filter_profile:
@ -170,13 +193,13 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
ssh_filter_profile:
state: "present"
block: "x11"
default-command-log: "enable"
default_command_log: "enable"
log: "x11"
name: "default_name_6"
shell-commands:
shell_commands:
-
action: "block"
alert: "enable"
@ -247,14 +270,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']:
@ -262,12 +287,12 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_ssh_filter_profile_data(json):
option_list = ['block', 'default-command-log', 'log',
'name', 'shell-commands']
option_list = ['block', 'default_command_log', 'log',
'name', 'shell_commands']
dictionary = {}
for attribute in option_list:
@ -277,73 +302,78 @@ def filter_ssh_filter_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 ssh_filter_profile(data, fos):
vdom = data['vdom']
state = data['state']
ssh_filter_profile_data = data['ssh_filter_profile']
flattened_data = flatten_multilists_attributes(ssh_filter_profile_data)
filtered_data = filter_ssh_filter_profile_data(flattened_data)
if ssh_filter_profile_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_ssh_filter_profile_data(ssh_filter_profile_data))
if state == "present":
return fos.set('ssh-filter',
'profile',
data=filtered_data,
vdom=vdom)
elif ssh_filter_profile_data['state'] == "absent":
elif state == "absent":
return fos.delete('ssh-filter',
'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_ssh_filter(data, fos):
login(data)
if data['ssh_filter_profile']:
resp = ssh_filter_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"]},
"ssh_filter_profile": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"block": {"required": False, "type": "str",
"choices": ["x11", "shell", "exec",
"port-forward", "tun-forward", "sftp",
"unknown"]},
"default-command-log": {"required": False, "type": "str",
"default_command_log": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"log": {"required": False, "type": "str",
"choices": ["x11", "shell", "exec",
"port-forward", "tun-forward", "sftp",
"unknown"]},
"name": {"required": True, "type": "str"},
"shell-commands": {"required": False, "type": "list",
"shell_commands": {"required": False, "type": "list",
"options": {
"action": {"required": False, "type": "str",
"choices": ["block", "allow"]},
@ -366,15 +396,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_ssh_filter(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_ssh_filter(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_ssh_filter(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_switch_controller_global
short_description: Configure FortiSwitch 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 switch_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)
@ -44,72 +41,91 @@ 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
switch_controller_global:
description:
- Configure FortiSwitch global settings.
default: null
type: dict
suboptions:
allow-multiple-interfaces:
allow_multiple_interfaces:
description:
- Enable/disable multiple FortiLink interfaces for redundant connections between a managed FortiSwitch and FortiGate.
type: str
choices:
- enable
- disable
default-virtual-switch-vlan:
default_virtual_switch_vlan:
description:
- Default VLAN for ports when added to the virtual-switch. Source system.interface.name.
disable-discovery:
type: str
disable_discovery:
description:
- Prevent this FortiSwitch from discovering.
type: list
suboptions:
name:
description:
- Managed device ID.
required: true
https-image-push:
type: str
https_image_push:
description:
- Enable/disable image push to FortiSwitch using HTTPS.
type: str
choices:
- enable
- disable
log-mac-limit-violations:
log_mac_limit_violations:
description:
- Enable/disable logs for Learning Limit Violations.
type: str
choices:
- enable
- disable
mac-aging-interval:
mac_aging_interval:
description:
- Time after which an inactive MAC is aged out (10 - 1000000 sec, default = 300, 0 = disable).
mac-retention-period:
- Time after which an inactive MAC is aged out (10 - 1000000 sec).
type: int
mac_retention_period:
description:
- Time in hours after which an inactive MAC is removed from client DB.
mac-violation-timer:
type: int
mac_violation_timer:
description:
- Set timeout for Learning Limit Violations (0 = disabled).
type: int
'''
EXAMPLES = '''
@ -119,6 +135,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure FortiSwitch global settings.
fortios_switch_controller_global:
@ -128,16 +145,16 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
switch_controller_global:
allow-multiple-interfaces: "enable"
default-virtual-switch-vlan: "<your_own_value> (source system.interface.name)"
disable-discovery:
allow_multiple_interfaces: "enable"
default_virtual_switch_vlan: "<your_own_value> (source system.interface.name)"
disable_discovery:
-
name: "default_name_6"
https-image-push: "enable"
log-mac-limit-violations: "enable"
mac-aging-interval: "9"
mac-retention-period: "10"
mac-violation-timer: "11"
https_image_push: "enable"
log_mac_limit_violations: "enable"
mac_aging_interval: "9"
mac_retention_period: "10"
mac_violation_timer: "11"
'''
RETURN = '''
@ -200,14 +217,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']:
@ -215,13 +234,13 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_switch_controller_global_data(json):
option_list = ['allow-multiple-interfaces', 'default-virtual-switch-vlan', 'disable-discovery',
'https-image-push', 'log-mac-limit-violations', 'mac-aging-interval',
'mac-retention-period', 'mac-violation-timer']
option_list = ['allow_multiple_interfaces', 'default_virtual_switch_vlan', 'disable_discovery',
'https_image_push', 'log_mac_limit_violations', 'mac_aging_interval',
'mac_retention_period', 'mac_violation_timer']
dictionary = {}
for attribute in option_list:
@ -231,17 +250,15 @@ def filter_switch_controller_global_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
@ -249,48 +266,54 @@ def flatten_multilists_attributes(data):
def switch_controller_global(data, fos):
vdom = data['vdom']
switch_controller_global_data = data['switch_controller_global']
flattened_data = flatten_multilists_attributes(switch_controller_global_data)
filtered_data = filter_switch_controller_global_data(flattened_data)
filtered_data = underscore_to_hyphen(filter_switch_controller_global_data(switch_controller_global_data))
return fos.set('switch-controller',
'global',
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_switch_controller(data, fos):
login(data)
if data['switch_controller_global']:
resp = switch_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},
"switch_controller_global": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"allow-multiple-interfaces": {"required": False, "type": "str",
"allow_multiple_interfaces": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"default-virtual-switch-vlan": {"required": False, "type": "str"},
"disable-discovery": {"required": False, "type": "list",
"default_virtual_switch_vlan": {"required": False, "type": "str"},
"disable_discovery": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
"https-image-push": {"required": False, "type": "str",
"https_image_push": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"log-mac-limit-violations": {"required": False, "type": "str",
"log_mac_limit_violations": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"mac-aging-interval": {"required": False, "type": "int"},
"mac-retention-period": {"required": False, "type": "int"},
"mac-violation-timer": {"required": False, "type": "int"}
"mac_aging_interval": {"required": False, "type": "int"},
"mac_retention_period": {"required": False, "type": "int"},
"mac_violation_timer": {"required": False, "type": "int"}
}
}
@ -298,15 +321,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_switch_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_switch_controller(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_switch_controller(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_switch_controller_lldp_profile
short_description: Configure FortiSwitch LLDP 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 switch_controller feature and lldp_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)
@ -44,109 +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
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
switch_controller_lldp_profile:
description:
- Configure FortiSwitch LLDP profiles.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
802.1-tlvs:
802.1_tlvs:
description:
- Transmitted IEEE 802.1 TLVs.
type: str
choices:
- port-vlan-id
802.3-tlvs:
802.3_tlvs:
description:
- Transmitted IEEE 802.3 TLVs.
type: str
choices:
- max-frame-size
auto-isl:
auto_isl:
description:
- Enable/disable auto inter-switch LAG.
type: str
choices:
- disable
- enable
auto-isl-hello-timer:
auto_isl_hello_timer:
description:
- Auto inter-switch LAG hello timer duration (1 - 30 sec, default = 3).
auto-isl-port-group:
- Auto inter-switch LAG hello timer duration (1 - 30 sec).
type: int
auto_isl_port_group:
description:
- Auto inter-switch LAG port group ID (0 - 9).
auto-isl-receive-timeout:
type: int
auto_isl_receive_timeout:
description:
- Auto inter-switch LAG timeout if no response is received (3 - 90 sec, default = 9).
custom-tlvs:
- Auto inter-switch LAG timeout if no response is received (3 - 90 sec).
type: int
custom_tlvs:
description:
- Configuration method to edit custom TLV entries.
type: list
suboptions:
information-string:
information_string:
description:
- Organizationally defined information string (0 - 507 hexadecimal bytes).
type: str
name:
description:
- TLV name (not sent).
required: true
type: str
oui:
description:
- Organizationally unique identifier (OUI), a 3-byte hexadecimal number, for this TLV.
type: str
subtype:
description:
- Organizationally defined subtype (0 - 255).
med-network-policy:
type: int
med_network_policy:
description:
- Configuration method to edit Media Endpoint Discovery (MED) network policy type-length-value (TLV) categories.
type: list
suboptions:
dscp:
description:
- Advertised Differentiated Services Code Point (DSCP) value, a packet header value indicating the level of service requested for
traffic, such as high priority or best effort delivery.
type: int
name:
description:
- Policy type name.
required: true
type: str
priority:
description:
- Advertised Layer 2 priority (0 - 7; from lowest to highest priority).
type: int
status:
description:
- Enable or disable this TLV.
type: str
choices:
- disable
- enable
vlan:
description:
- ID of VLAN to advertise, if configured on port (0 - 4094, 0 = priority tag).
med-tlvs:
type: int
med_tlvs:
description:
- "Transmitted LLDP-MED TLVs (type-length-value descriptions): inventory management TLV and/or network policy TLV."
type: str
choices:
- inventory-management
- network-policy
@ -154,6 +182,7 @@ options:
description:
- Profile name.
required: true
type: str
'''
EXAMPLES = '''
@ -163,6 +192,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure FortiSwitch LLDP profiles.
fortios_switch_controller_lldp_profile:
@ -171,28 +201,28 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
switch_controller_lldp_profile:
state: "present"
802.1-tlvs: "port-vlan-id"
802.3-tlvs: "max-frame-size"
auto-isl: "disable"
auto-isl-hello-timer: "6"
auto-isl-port-group: "7"
auto-isl-receive-timeout: "8"
custom-tlvs:
802.1_tlvs: "port-vlan-id"
802.3_tlvs: "max-frame-size"
auto_isl: "disable"
auto_isl_hello_timer: "6"
auto_isl_port_group: "7"
auto_isl_receive_timeout: "8"
custom_tlvs:
-
information-string: "<your_own_value>"
information_string: "<your_own_value>"
name: "default_name_11"
oui: "<your_own_value>"
subtype: "13"
med-network-policy:
med_network_policy:
-
dscp: "15"
name: "default_name_16"
priority: "17"
status: "disable"
vlan: "19"
med-tlvs: "inventory-management"
med_tlvs: "inventory-management"
name: "default_name_21"
'''
@ -256,14 +286,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']:
@ -271,13 +303,13 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_switch_controller_lldp_profile_data(json):
option_list = ['802.1-tlvs', '802.3-tlvs', 'auto-isl',
'auto-isl-hello-timer', 'auto-isl-port-group', 'auto-isl-receive-timeout',
'custom-tlvs', 'med-network-policy', 'med-tlvs',
option_list = ['802.1_tlvs', '802.3_tlvs', 'auto_isl',
'auto_isl_hello_timer', 'auto_isl_port_group', 'auto_isl_receive_timeout',
'custom_tlvs', 'med_network_policy', 'med_tlvs',
'name']
dictionary = {}
@ -288,78 +320,83 @@ def filter_switch_controller_lldp_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 switch_controller_lldp_profile(data, fos):
vdom = data['vdom']
state = data['state']
switch_controller_lldp_profile_data = data['switch_controller_lldp_profile']
flattened_data = flatten_multilists_attributes(switch_controller_lldp_profile_data)
filtered_data = filter_switch_controller_lldp_profile_data(flattened_data)
if switch_controller_lldp_profile_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_switch_controller_lldp_profile_data(switch_controller_lldp_profile_data))
if state == "present":
return fos.set('switch-controller',
'lldp-profile',
data=filtered_data,
vdom=vdom)
elif switch_controller_lldp_profile_data['state'] == "absent":
elif state == "absent":
return fos.delete('switch-controller',
'lldp-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_switch_controller(data, fos):
login(data)
if data['switch_controller_lldp_profile']:
resp = switch_controller_lldp_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"]},
"switch_controller_lldp_profile": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"802.1-tlvs": {"required": False, "type": "str",
"802.1_tlvs": {"required": False, "type": "str",
"choices": ["port-vlan-id"]},
"802.3-tlvs": {"required": False, "type": "str",
"802.3_tlvs": {"required": False, "type": "str",
"choices": ["max-frame-size"]},
"auto-isl": {"required": False, "type": "str",
"auto_isl": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"auto-isl-hello-timer": {"required": False, "type": "int"},
"auto-isl-port-group": {"required": False, "type": "int"},
"auto-isl-receive-timeout": {"required": False, "type": "int"},
"custom-tlvs": {"required": False, "type": "list",
"auto_isl_hello_timer": {"required": False, "type": "int"},
"auto_isl_port_group": {"required": False, "type": "int"},
"auto_isl_receive_timeout": {"required": False, "type": "int"},
"custom_tlvs": {"required": False, "type": "list",
"options": {
"information-string": {"required": False, "type": "str"},
"information_string": {"required": False, "type": "str"},
"name": {"required": True, "type": "str"},
"oui": {"required": False, "type": "str"},
"subtype": {"required": False, "type": "int"}
}},
"med-network-policy": {"required": False, "type": "list",
"med_network_policy": {"required": False, "type": "list",
"options": {
"dscp": {"required": False, "type": "int"},
"name": {"required": True, "type": "str"},
@ -368,7 +405,7 @@ def main():
"choices": ["disable", "enable"]},
"vlan": {"required": False, "type": "int"}
}},
"med-tlvs": {"required": False, "type": "str",
"med_tlvs": {"required": False, "type": "str",
"choices": ["inventory-management", "network-policy"]},
"name": {"required": True, "type": "str"}
@ -378,15 +415,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_switch_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_switch_controller(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_switch_controller(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_switch_controller_lldp_settings
short_description: Configure FortiSwitch LLDP 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 switch_controller feature and lldp_settings 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)
@ -44,56 +41,70 @@ 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
switch_controller_lldp_settings:
description:
- Configure FortiSwitch LLDP settings.
default: null
type: dict
suboptions:
fast-start-interval:
fast_start_interval:
description:
- Frequency of LLDP PDU transmission from FortiSwitch for the first 4 packets when the link is up (2 - 5 sec, default = 2, 0 = disable
fast start).
management-interface:
- Frequency of LLDP PDU transmission from FortiSwitch for the first 4 packets when the link is up (2 - 5 sec).
type: int
management_interface:
description:
- Primary management interface to be advertised in LLDP and CDP PDUs.
type: str
choices:
- internal
- mgmt
status:
description:
- Enable/disable LLDP global settings.
type: str
choices:
- enable
- disable
tx-hold:
tx_hold:
description:
- Number of tx-intervals before local LLDP data expires (1 - 16, default = 4). Packet TTL is tx-hold * tx-interval.
tx-interval:
- Number of tx-intervals before local LLDP data expires (1 - 16). Packet TTL is tx-hold * tx-interval.
type: int
tx_interval:
description:
- Frequency of LLDP PDU transmission from FortiSwitch (5 - 4095 sec, default = 30). Packet TTL is tx-hold * tx-interval.
- Frequency of LLDP PDU transmission from FortiSwitch (5 - 4095 sec). Packet TTL is tx-hold * tx-interval.
type: int
'''
EXAMPLES = '''
@ -103,6 +114,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure FortiSwitch LLDP settings.
fortios_switch_controller_lldp_settings:
@ -112,11 +124,11 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
switch_controller_lldp_settings:
fast-start-interval: "3"
management-interface: "internal"
fast_start_interval: "3"
management_interface: "internal"
status: "enable"
tx-hold: "6"
tx-interval: "7"
tx_hold: "6"
tx_interval: "7"
'''
RETURN = '''
@ -179,14 +191,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']:
@ -194,12 +208,12 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_switch_controller_lldp_settings_data(json):
option_list = ['fast-start-interval', 'management-interface', 'status',
'tx-hold', 'tx-interval']
option_list = ['fast_start_interval', 'management_interface', 'status',
'tx_hold', 'tx_interval']
dictionary = {}
for attribute in option_list:
@ -209,17 +223,15 @@ def filter_switch_controller_lldp_settings_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
@ -227,41 +239,47 @@ def flatten_multilists_attributes(data):
def switch_controller_lldp_settings(data, fos):
vdom = data['vdom']
switch_controller_lldp_settings_data = data['switch_controller_lldp_settings']
flattened_data = flatten_multilists_attributes(switch_controller_lldp_settings_data)
filtered_data = filter_switch_controller_lldp_settings_data(flattened_data)
filtered_data = underscore_to_hyphen(filter_switch_controller_lldp_settings_data(switch_controller_lldp_settings_data))
return fos.set('switch-controller',
'lldp-settings',
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_switch_controller(data, fos):
login(data)
if data['switch_controller_lldp_settings']:
resp = switch_controller_lldp_settings(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},
"switch_controller_lldp_settings": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"fast-start-interval": {"required": False, "type": "int"},
"management-interface": {"required": False, "type": "str",
"fast_start_interval": {"required": False, "type": "int"},
"management_interface": {"required": False, "type": "str",
"choices": ["internal", "mgmt"]},
"status": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"tx-hold": {"required": False, "type": "int"},
"tx-interval": {"required": False, "type": "int"}
"tx_hold": {"required": False, "type": "int"},
"tx_interval": {"required": False, "type": "int"}
}
}
@ -269,15 +287,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_switch_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_switch_controller(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_switch_controller(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -26,10 +26,10 @@ DOCUMENTATION = '''
module: fortios_switch_controller_mac_sync_settings
short_description: Configure global MAC synchronization 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 switch_controller feature and mac_sync_settings 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,37 +41,48 @@ 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
switch_controller_mac_sync_settings:
description:
- Configure global MAC synchronization settings.
default: null
type: dict
suboptions:
mac-sync-interval:
mac_sync_interval:
description:
- Time interval between MAC synchronizations (30 - 1800 sec, default = 60, 0 = disable MAC synchronization).
- Time interval between MAC synchronizations (30 - 1800 sec).
type: int
'''
EXAMPLES = '''
@ -81,6 +92,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure global MAC synchronization settings.
fortios_switch_controller_mac_sync_settings:
@ -90,7 +102,7 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
switch_controller_mac_sync_settings:
mac-sync-interval: "3"
mac_sync_interval: "3"
'''
RETURN = '''
@ -153,14 +165,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']:
@ -168,11 +182,11 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_switch_controller_mac_sync_settings_data(json):
option_list = ['mac-sync-interval']
option_list = ['mac_sync_interval']
dictionary = {}
for attribute in option_list:
@ -182,17 +196,15 @@ def filter_switch_controller_mac_sync_settings_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
@ -200,35 +212,41 @@ def flatten_multilists_attributes(data):
def switch_controller_mac_sync_settings(data, fos):
vdom = data['vdom']
switch_controller_mac_sync_settings_data = data['switch_controller_mac_sync_settings']
flattened_data = flatten_multilists_attributes(switch_controller_mac_sync_settings_data)
filtered_data = filter_switch_controller_mac_sync_settings_data(flattened_data)
filtered_data = underscore_to_hyphen(filter_switch_controller_mac_sync_settings_data(switch_controller_mac_sync_settings_data))
return fos.set('switch-controller',
'mac-sync-settings',
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_switch_controller(data, fos):
login(data)
if data['switch_controller_mac_sync_settings']:
resp = switch_controller_mac_sync_settings(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},
"switch_controller_mac_sync_settings": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"mac-sync-interval": {"required": False, "type": "int"}
"mac_sync_interval": {"required": False, "type": "int"}
}
}
@ -236,15 +254,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_switch_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_switch_controller(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_switch_controller(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_switch_controller_network_monitor_settings
short_description: Configure network monitor 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 switch_controller feature and network_monitor_settings 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)
@ -44,37 +41,48 @@ 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
switch_controller_network_monitor_settings:
description:
- Configure network monitor settings.
default: null
type: dict
suboptions:
network-monitoring:
network_monitoring:
description:
- Enable/disable passive gathering of information by FortiSwitch units concerning other network devices.
type: str
choices:
- enable
- disable
@ -87,6 +95,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure network monitor settings.
fortios_switch_controller_network_monitor_settings:
@ -96,7 +105,7 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
switch_controller_network_monitor_settings:
network-monitoring: "enable"
network_monitoring: "enable"
'''
RETURN = '''
@ -159,14 +168,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']:
@ -174,11 +185,11 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_switch_controller_network_monitor_settings_data(json):
option_list = ['network-monitoring']
option_list = ['network_monitoring']
dictionary = {}
for attribute in option_list:
@ -188,17 +199,15 @@ def filter_switch_controller_network_monitor_settings_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
@ -206,35 +215,41 @@ def flatten_multilists_attributes(data):
def switch_controller_network_monitor_settings(data, fos):
vdom = data['vdom']
switch_controller_network_monitor_settings_data = data['switch_controller_network_monitor_settings']
flattened_data = flatten_multilists_attributes(switch_controller_network_monitor_settings_data)
filtered_data = filter_switch_controller_network_monitor_settings_data(flattened_data)
filtered_data = underscore_to_hyphen(filter_switch_controller_network_monitor_settings_data(switch_controller_network_monitor_settings_data))
return fos.set('switch-controller',
'network-monitor-settings',
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_switch_controller(data, fos):
login(data)
if data['switch_controller_network_monitor_settings']:
resp = switch_controller_network_monitor_settings(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},
"switch_controller_network_monitor_settings": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"network-monitoring": {"required": False, "type": "str",
"network_monitoring": {"required": False, "type": "str",
"choices": ["enable", "disable"]}
}
@ -243,15 +258,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_switch_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_switch_controller(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_switch_controller(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_system_accprofile
short_description: Configure access profiles for system administrators 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 system feature and accprofile 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)
@ -44,52 +41,68 @@ 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
system_accprofile:
description:
- Configure access profiles for system administrators.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
admintimeout:
description:
- Administrator timeout for this access profile (0 - 480 min, default = 10, 0 means never timeout).
admintimeout-override:
- Administrator timeout for this access profile (0 - 480 min).
type: int
admintimeout_override:
description:
- Enable/disable overriding the global administrator idle timeout.
type: str
choices:
- enable
- disable
authgrp:
description:
- Administrator access to Users and Devices.
type: str
choices:
- none
- read
@ -97,9 +110,11 @@ options:
comments:
description:
- Comment.
type: str
ftviewgrp:
description:
- FortiView.
type: str
choices:
- none
- read
@ -107,18 +122,21 @@ options:
fwgrp:
description:
- Administrator access to the Firewall configuration.
type: str
choices:
- none
- read
- read-write
- custom
fwgrp-permission:
fwgrp_permission:
description:
- Custom firewall permission.
type: dict
suboptions:
address:
description:
- Address Configuration.
type: str
choices:
- none
- read
@ -126,6 +144,7 @@ options:
policy:
description:
- Policy Configuration.
type: str
choices:
- none
- read
@ -133,6 +152,7 @@ options:
schedule:
description:
- Schedule Configuration.
type: str
choices:
- none
- read
@ -140,6 +160,7 @@ options:
service:
description:
- Service Configuration.
type: str
choices:
- none
- read
@ -147,39 +168,45 @@ options:
loggrp:
description:
- Administrator access to Logging and Reporting including viewing log messages.
type: str
choices:
- none
- read
- read-write
- custom
loggrp-permission:
loggrp_permission:
description:
- Custom Log & Report permission.
type: dict
suboptions:
config:
description:
- Log & Report configuration.
type: str
choices:
- none
- read
- read-write
data-access:
data_access:
description:
- Log & Report Data Access.
type: str
choices:
- none
- read
- read-write
report-access:
report_access:
description:
- Log & Report Report Access.
type: str
choices:
- none
- read
- read-write
threat-weight:
threat_weight:
description:
- Log & Report Threat Weight.
type: str
choices:
- none
- read
@ -188,35 +215,41 @@ options:
description:
- Profile name.
required: true
type: str
netgrp:
description:
- Network Configuration.
type: str
choices:
- none
- read
- read-write
- custom
netgrp-permission:
netgrp_permission:
description:
- Custom network permission.
type: dict
suboptions:
cfg:
description:
- Network Configuration.
type: str
choices:
- none
- read
- read-write
packet-capture:
packet_capture:
description:
- Packet Capture Configuration.
type: str
choices:
- none
- read
- read-write
route-cfg:
route_cfg:
description:
- Router Configuration.
type: str
choices:
- none
- read
@ -224,12 +257,14 @@ options:
scope:
description:
- "Scope of admin access: global or specific VDOM(s)."
type: str
choices:
- vdom
- global
secfabgrp:
description:
- Security Fabric.
type: str
choices:
- none
- read
@ -237,18 +272,21 @@ options:
sysgrp:
description:
- System Configuration.
type: str
choices:
- none
- read
- read-write
- custom
sysgrp-permission:
sysgrp_permission:
description:
- Custom system permission.
type: dict
suboptions:
admin:
description:
- Administrator Users.
type: str
choices:
- none
- read
@ -256,6 +294,7 @@ options:
cfg:
description:
- System Configuration.
type: str
choices:
- none
- read
@ -263,6 +302,7 @@ options:
mnt:
description:
- Maintenance.
type: str
choices:
- none
- read
@ -270,6 +310,7 @@ options:
upd:
description:
- FortiGuard Updates.
type: str
choices:
- none
- read
@ -277,32 +318,37 @@ options:
utmgrp:
description:
- Administrator access to Security Profiles.
type: str
choices:
- none
- read
- read-write
- custom
utmgrp-permission:
utmgrp_permission:
description:
- Custom Security Profile permissions.
type: dict
suboptions:
antivirus:
description:
- Antivirus profiles and settings.
type: str
choices:
- none
- read
- read-write
application-control:
application_control:
description:
- Application Control profiles and settings.
type: str
choices:
- none
- read
- read-write
data-loss-prevention:
data_loss_prevention:
description:
- DLP profiles and settings.
type: str
choices:
- none
- read
@ -310,13 +356,15 @@ options:
dnsfilter:
description:
- DNS Filter profiles and settings.
type: str
choices:
- none
- read
- read-write
endpoint-control:
endpoint_control:
description:
- FortiClient Profiles.
type: str
choices:
- none
- read
@ -324,6 +372,7 @@ options:
icap:
description:
- ICAP profiles and settings.
type: str
choices:
- none
- read
@ -331,6 +380,7 @@ options:
ips:
description:
- IPS profiles and settings.
type: str
choices:
- none
- read
@ -338,6 +388,7 @@ options:
spamfilter:
description:
- AntiSpam filter and settings.
type: str
choices:
- none
- read
@ -345,6 +396,7 @@ options:
voip:
description:
- VoIP profiles and settings.
type: str
choices:
- none
- read
@ -352,6 +404,7 @@ options:
waf:
description:
- Web Application Firewall profiles and settings.
type: str
choices:
- none
- read
@ -359,6 +412,7 @@ options:
webfilter:
description:
- Web Filter profiles and settings.
type: str
choices:
- none
- read
@ -366,6 +420,7 @@ options:
vpngrp:
description:
- Administrator access to IPsec, SSL, PPTP, and L2TP VPN.
type: str
choices:
- none
- read
@ -373,6 +428,7 @@ options:
wanoptgrp:
description:
- Administrator access to WAN Opt & Cache.
type: str
choices:
- none
- read
@ -380,6 +436,7 @@ options:
wifi:
description:
- Administrator access to the WiFi controller and Switch controller.
type: str
choices:
- none
- read
@ -393,6 +450,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure access profiles for system administrators.
fortios_system_accprofile:
@ -401,46 +459,46 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
system_accprofile:
state: "present"
admintimeout: "3"
admintimeout-override: "enable"
admintimeout_override: "enable"
authgrp: "none"
comments: "<your_own_value>"
ftviewgrp: "none"
fwgrp: "none"
fwgrp-permission:
fwgrp_permission:
address: "none"
policy: "none"
schedule: "none"
service: "none"
loggrp: "none"
loggrp-permission:
loggrp_permission:
config: "none"
data-access: "none"
report-access: "none"
threat-weight: "none"
data_access: "none"
report_access: "none"
threat_weight: "none"
name: "default_name_20"
netgrp: "none"
netgrp-permission:
netgrp_permission:
cfg: "none"
packet-capture: "none"
route-cfg: "none"
packet_capture: "none"
route_cfg: "none"
scope: "vdom"
secfabgrp: "none"
sysgrp: "none"
sysgrp-permission:
sysgrp_permission:
admin: "none"
cfg: "none"
mnt: "none"
upd: "none"
utmgrp: "none"
utmgrp-permission:
utmgrp_permission:
antivirus: "none"
application-control: "none"
data-loss-prevention: "none"
application_control: "none"
data_loss_prevention: "none"
dnsfilter: "none"
endpoint-control: "none"
endpoint_control: "none"
icap: "none"
ips: "none"
spamfilter: "none"
@ -512,14 +570,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']:
@ -527,16 +587,16 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_accprofile_data(json):
option_list = ['admintimeout', 'admintimeout-override', 'authgrp',
option_list = ['admintimeout', 'admintimeout_override', 'authgrp',
'comments', 'ftviewgrp', 'fwgrp',
'fwgrp-permission', 'loggrp', 'loggrp-permission',
'name', 'netgrp', 'netgrp-permission',
'fwgrp_permission', 'loggrp', 'loggrp_permission',
'name', 'netgrp', 'netgrp_permission',
'scope', 'secfabgrp', 'sysgrp',
'sysgrp-permission', 'utmgrp', 'utmgrp-permission',
'sysgrp_permission', 'utmgrp', 'utmgrp_permission',
'vpngrp', 'wanoptgrp', 'wifi']
dictionary = {}
@ -547,63 +607,68 @@ def filter_system_accprofile_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 system_accprofile(data, fos):
vdom = data['vdom']
state = data['state']
system_accprofile_data = data['system_accprofile']
flattened_data = flatten_multilists_attributes(system_accprofile_data)
filtered_data = filter_system_accprofile_data(flattened_data)
if system_accprofile_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_system_accprofile_data(system_accprofile_data))
if state == "present":
return fos.set('system',
'accprofile',
data=filtered_data,
vdom=vdom)
elif system_accprofile_data['state'] == "absent":
elif state == "absent":
return fos.delete('system',
'accprofile',
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_system(data, fos):
login(data)
if data['system_accprofile']:
resp = system_accprofile(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"]},
"system_accprofile": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"admintimeout": {"required": False, "type": "int"},
"admintimeout-override": {"required": False, "type": "str",
"admintimeout_override": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"authgrp": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
@ -613,7 +678,7 @@ def main():
"fwgrp": {"required": False, "type": "str",
"choices": ["none", "read", "read-write",
"custom"]},
"fwgrp-permission": {"required": False, "type": "dict",
"fwgrp_permission": {"required": False, "type": "dict",
"options": {
"address": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
@ -627,28 +692,28 @@ def main():
"loggrp": {"required": False, "type": "str",
"choices": ["none", "read", "read-write",
"custom"]},
"loggrp-permission": {"required": False, "type": "dict",
"loggrp_permission": {"required": False, "type": "dict",
"options": {
"config": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"data-access": {"required": False, "type": "str",
"data_access": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"report-access": {"required": False, "type": "str",
"report_access": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"threat-weight": {"required": False, "type": "str",
"threat_weight": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]}
}},
"name": {"required": True, "type": "str"},
"netgrp": {"required": False, "type": "str",
"choices": ["none", "read", "read-write",
"custom"]},
"netgrp-permission": {"required": False, "type": "dict",
"netgrp_permission": {"required": False, "type": "dict",
"options": {
"cfg": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"packet-capture": {"required": False, "type": "str",
"packet_capture": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"route-cfg": {"required": False, "type": "str",
"route_cfg": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]}
}},
"scope": {"required": False, "type": "str",
@ -658,7 +723,7 @@ def main():
"sysgrp": {"required": False, "type": "str",
"choices": ["none", "read", "read-write",
"custom"]},
"sysgrp-permission": {"required": False, "type": "dict",
"sysgrp_permission": {"required": False, "type": "dict",
"options": {
"admin": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
@ -672,17 +737,17 @@ def main():
"utmgrp": {"required": False, "type": "str",
"choices": ["none", "read", "read-write",
"custom"]},
"utmgrp-permission": {"required": False, "type": "dict",
"utmgrp_permission": {"required": False, "type": "dict",
"options": {
"antivirus": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"application-control": {"required": False, "type": "str",
"application_control": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"data-loss-prevention": {"required": False, "type": "str",
"data_loss_prevention": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"dnsfilter": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"endpoint-control": {"required": False, "type": "str",
"endpoint_control": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
"icap": {"required": False, "type": "str",
"choices": ["none", "read", "read-write"]},
@ -710,15 +775,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_system(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_system(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

File diff suppressed because it is too large Load Diff

@ -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_system_api_user
short_description: Configure API users 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 system feature and api_user 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)
@ -44,96 +41,124 @@ 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
system_api_user:
description:
- Configure API users.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
accprofile:
description:
- Admin user access profile. Source system.accprofile.name.
api-key:
type: str
api_key:
description:
- Admin user password.
type: str
comments:
description:
- Comment.
cors-allow-origin:
type: str
cors_allow_origin:
description:
- Value for Access-Control-Allow-Origin on API responses. Avoid using '*' if possible.
type: str
name:
description:
- User name.
required: true
peer-auth:
type: str
peer_auth:
description:
- Enable/disable peer authentication.
type: str
choices:
- enable
- disable
peer-group:
peer_group:
description:
- Peer group name.
type: str
schedule:
description:
- Schedule name.
type: str
trusthost:
description:
- Trusthost.
type: list
suboptions:
id:
description:
- Table ID.
required: true
ipv4-trusthost:
type: int
ipv4_trusthost:
description:
- IPv4 trusted host address.
ipv6-trusthost:
type: str
ipv6_trusthost:
description:
- IPv6 trusted host address.
type: str
type:
description:
- Trusthost type.
type: str
choices:
- ipv4-trusthost
- ipv6-trusthost
vdom:
description:
- Virtual domains.
type: list
suboptions:
name:
description:
- Virtual domain name. Source system.vdom.name.
required: true
type: str
'''
EXAMPLES = '''
@ -143,6 +168,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure API users.
fortios_system_api_user:
@ -151,21 +177,21 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
system_api_user:
state: "present"
accprofile: "<your_own_value> (source system.accprofile.name)"
api-key: "<your_own_value>"
api_key: "<your_own_value>"
comments: "<your_own_value>"
cors-allow-origin: "<your_own_value>"
cors_allow_origin: "<your_own_value>"
name: "default_name_7"
peer-auth: "enable"
peer-group: "<your_own_value>"
peer_auth: "enable"
peer_group: "<your_own_value>"
schedule: "<your_own_value>"
trusthost:
-
id: "12"
ipv4-trusthost: "<your_own_value>"
ipv6-trusthost: "<your_own_value>"
ipv4_trusthost: "<your_own_value>"
ipv6_trusthost: "<your_own_value>"
type: "ipv4-trusthost"
vdom:
-
@ -232,14 +258,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']:
@ -247,13 +275,13 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_api_user_data(json):
option_list = ['accprofile', 'api-key', 'comments',
'cors-allow-origin', 'name', 'peer-auth',
'peer-group', 'schedule', 'trusthost',
option_list = ['accprofile', 'api_key', 'comments',
'cors_allow_origin', 'name', 'peer_auth',
'peer_group', 'schedule', 'trusthost',
'vdom']
dictionary = {}
@ -264,75 +292,80 @@ def filter_system_api_user_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 system_api_user(data, fos):
vdom = data['vdom']
state = data['state']
system_api_user_data = data['system_api_user']
flattened_data = flatten_multilists_attributes(system_api_user_data)
filtered_data = filter_system_api_user_data(flattened_data)
if system_api_user_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_system_api_user_data(system_api_user_data))
if state == "present":
return fos.set('system',
'api-user',
data=filtered_data,
vdom=vdom)
elif system_api_user_data['state'] == "absent":
elif state == "absent":
return fos.delete('system',
'api-user',
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_system(data, fos):
login(data)
if data['system_api_user']:
resp = system_api_user(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"]},
"system_api_user": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"accprofile": {"required": False, "type": "str"},
"api-key": {"required": False, "type": "str"},
"api_key": {"required": False, "type": "str"},
"comments": {"required": False, "type": "str"},
"cors-allow-origin": {"required": False, "type": "str"},
"cors_allow_origin": {"required": False, "type": "str"},
"name": {"required": True, "type": "str"},
"peer-auth": {"required": False, "type": "str",
"peer_auth": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"peer-group": {"required": False, "type": "str"},
"peer_group": {"required": False, "type": "str"},
"schedule": {"required": False, "type": "str"},
"trusthost": {"required": False, "type": "list",
"options": {
"id": {"required": True, "type": "int"},
"ipv4-trusthost": {"required": False, "type": "str"},
"ipv6-trusthost": {"required": False, "type": "str"},
"ipv4_trusthost": {"required": False, "type": "str"},
"ipv6_trusthost": {"required": False, "type": "str"},
"type": {"required": False, "type": "str",
"choices": ["ipv4-trusthost", "ipv6-trusthost"]}
}},
@ -347,15 +380,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_system(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_system(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_system_central_management
short_description: Configure central management.
short_description: Configure central management in Fortinet's FortiOS and FortiGate.
description:
- This module is able to configure a FortiGate or FortiOS by
allowing the user to configure system feature and central_management 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 system feature and central_management 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,61 +41,76 @@ 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
system_central_management:
description:
- Configure central management.
default: null
type: dict
suboptions:
allow-monitor:
allow_monitor:
description:
- Enable/disable allowing the central management server to remotely monitor this FortiGate
type: str
choices:
- enable
- disable
allow-push-configuration:
allow_push_configuration:
description:
- Enable/disable allowing the central management server to push configuration changes to this FortiGate.
type: str
choices:
- enable
- disable
allow-push-firmware:
allow_push_firmware:
description:
- Enable/disable allowing the central management server to push firmware updates to this FortiGate.
type: str
choices:
- enable
- disable
allow-remote-firmware-upgrade:
allow_remote_firmware_upgrade:
description:
- Enable/disable remotely upgrading the firmware on this FortiGate from the central management server.
type: str
choices:
- enable
- disable
enc-algorithm:
enc_algorithm:
description:
- Encryption strength for communications between the FortiGate and central management.
type: str
choices:
- default
- high
@ -106,47 +118,57 @@ options:
fmg:
description:
- IP address or FQDN of the FortiManager.
fmg-source-ip:
type: str
fmg_source_ip:
description:
- IPv4 source address that this FortiGate uses when communicating with FortiManager.
fmg-source-ip6:
type: str
fmg_source_ip6:
description:
- IPv6 source address that this FortiGate uses when communicating with FortiManager.
include-default-servers:
type: str
include_default_servers:
description:
- Enable/disable inclusion of public FortiGuard servers in the override server list.
type: str
choices:
- enable
- disable
mode:
description:
- Central management mode.
type: str
choices:
- normal
- backup
schedule-config-restore:
schedule_config_restore:
description:
- Enable/disable allowing the central management server to restore the configuration of this FortiGate.
type: str
choices:
- enable
- disable
schedule-script-restore:
schedule_script_restore:
description:
- Enable/disable allowing the central management server to restore the scripts stored on this FortiGate.
type: str
choices:
- enable
- disable
serial-number:
serial_number:
description:
- Serial number.
server-list:
type: str
server_list:
description:
- Additional severs that the FortiGate can use for updates (for AV, IPS, updates) and ratings (for web filter and antispam ratings)
servers.
type: list
suboptions:
addr-type:
addr_type:
description:
- Indicate whether the FortiGate communicates with the override server using an IPv4 address, an IPv6 address or a FQDN.
type: str
choices:
- ipv4
- ipv6
@ -154,25 +176,31 @@ options:
fqdn:
description:
- FQDN address of override server.
type: str
id:
description:
- ID.
required: true
server-address:
type: int
server_address:
description:
- IPv4 address of override server.
server-address6:
type: str
server_address6:
description:
- IPv6 address of override server.
server-type:
type: str
server_type:
description:
- FortiGuard service type.
type: str
choices:
- update
- rating
type:
description:
- Central management type.
type: str
choices:
- fortimanager
- fortiguard
@ -180,6 +208,7 @@ options:
vdom:
description:
- Virtual domain (VDOM) name to use when communicating with FortiManager. Source system.vdom.name.
type: str
'''
EXAMPLES = '''
@ -189,35 +218,37 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure central management.
fortios_system_central_management:
host: "{{ host }}"
host: "{{ host }}"
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
vdom: "{{ vdom }}"
https: "False"
system_central_management:
allow-monitor: "enable"
allow-push-configuration: "enable"
allow-push-firmware: "enable"
allow-remote-firmware-upgrade: "enable"
enc-algorithm: "default"
allow_monitor: "enable"
allow_push_configuration: "enable"
allow_push_firmware: "enable"
allow_remote_firmware_upgrade: "enable"
enc_algorithm: "default"
fmg: "<your_own_value>"
fmg-source-ip: "<your_own_value>"
fmg-source-ip6: "<your_own_value>"
include-default-servers: "enable"
fmg_source_ip: "<your_own_value>"
fmg_source_ip6: "<your_own_value>"
include_default_servers: "enable"
mode: "normal"
schedule-config-restore: "enable"
schedule-script-restore: "enable"
serial-number: "<your_own_value>"
server-list:
schedule_config_restore: "enable"
schedule_script_restore: "enable"
serial_number: "<your_own_value>"
server_list:
-
addr-type: "ipv4"
addr_type: "ipv4"
fqdn: "<your_own_value>"
id: "19"
server-address: "<your_own_value>"
server-address6: "<your_own_value>"
server-type: "update"
server_address: "<your_own_value>"
server_address6: "<your_own_value>"
server_type: "update"
type: "fortimanager"
vdom: "<your_own_value> (source system.vdom.name)"
'''
@ -242,7 +273,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
@ -282,14 +313,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']:
@ -297,90 +330,106 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_central_management_data(json):
option_list = ['allow-monitor', 'allow-push-configuration', 'allow-push-firmware',
'allow-remote-firmware-upgrade', 'enc-algorithm', 'fmg',
'fmg-source-ip', 'fmg-source-ip6', 'include-default-servers',
'mode', 'schedule-config-restore', 'schedule-script-restore',
'serial-number', 'server-list', 'type',
option_list = ['allow_monitor', 'allow_push_configuration', 'allow_push_firmware',
'allow_remote_firmware_upgrade', 'enc_algorithm', 'fmg',
'fmg_source_ip', 'fmg_source_ip6', 'include_default_servers',
'mode', 'schedule_config_restore', 'schedule_script_restore',
'serial_number', 'server_list', 'type',
'vdom']
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 system_central_management(data, fos):
vdom = data['vdom']
system_central_management_data = data['system_central_management']
filtered_data = filter_system_central_management_data(
system_central_management_data)
filtered_data = underscore_to_hyphen(filter_system_central_management_data(system_central_management_data))
return fos.set('system',
'central-management',
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_system(data, fos):
login(data)
methodlist = ['system_central_management']
for method in methodlist:
if data[method]:
resp = eval(method)(data, fos)
break
if data['system_central_management']:
resp = system_central_management(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},
"system_central_management": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"allow-monitor": {"required": False, "type": "str",
"allow_monitor": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"allow-push-configuration": {"required": False, "type": "str",
"allow_push_configuration": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"allow-push-firmware": {"required": False, "type": "str",
"allow_push_firmware": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"allow-remote-firmware-upgrade": {"required": False, "type": "str",
"allow_remote_firmware_upgrade": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"enc-algorithm": {"required": False, "type": "str",
"enc_algorithm": {"required": False, "type": "str",
"choices": ["default", "high", "low"]},
"fmg": {"required": False, "type": "str"},
"fmg-source-ip": {"required": False, "type": "str"},
"fmg-source-ip6": {"required": False, "type": "str"},
"include-default-servers": {"required": False, "type": "str",
"fmg_source_ip": {"required": False, "type": "str"},
"fmg_source_ip6": {"required": False, "type": "str"},
"include_default_servers": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"mode": {"required": False, "type": "str",
"choices": ["normal", "backup"]},
"schedule-config-restore": {"required": False, "type": "str",
"schedule_config_restore": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"schedule-script-restore": {"required": False, "type": "str",
"schedule_script_restore": {"required": False, "type": "str",
"choices": ["enable", "disable"]},
"serial-number": {"required": False, "type": "str"},
"server-list": {"required": False, "type": "list",
"serial_number": {"required": False, "type": "str"},
"server_list": {"required": False, "type": "list",
"options": {
"addr-type": {"required": False, "type": "str",
"addr_type": {"required": False, "type": "str",
"choices": ["ipv4", "ipv6", "fqdn"]},
"fqdn": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"},
"server-address": {"required": False, "type": "str"},
"server-address6": {"required": False, "type": "str"},
"server-type": {"required": False, "type": "str",
"server_address": {"required": False, "type": "str"},
"server_address6": {"required": False, "type": "str"},
"server_type": {"required": False, "type": "str",
"choices": ["update", "rating"]}
}},
"type": {"required": False, "type": "str",
@ -393,15 +442,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_system(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_system(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_system_dhcp_server
short_description: Configure DHCP servers 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 system_dhcp feature and server 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)
@ -44,97 +41,125 @@ 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
system_dhcp_server:
description:
- Configure DHCP servers.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
auto-configuration:
auto_configuration:
description:
- Enable/disable auto configuration.
type: str
choices:
- disable
- enable
conflicted-ip-timeout:
conflicted_ip_timeout:
description:
- Time in seconds to wait after a conflicted IP address is removed from the DHCP range before it can be reused.
ddns-auth:
type: int
ddns_auth:
description:
- DDNS authentication mode.
type: str
choices:
- disable
- tsig
ddns-key:
ddns_key:
description:
- DDNS update key (base 64 encoding).
ddns-keyname:
type: str
ddns_keyname:
description:
- DDNS update key name.
ddns-server-ip:
type: str
ddns_server_ip:
description:
- DDNS server IP.
ddns-ttl:
type: str
ddns_ttl:
description:
- TTL.
ddns-update:
type: int
ddns_update:
description:
- Enable/disable DDNS update for DHCP.
type: str
choices:
- disable
- enable
ddns-update-override:
ddns_update_override:
description:
- Enable/disable DDNS update override for DHCP.
type: str
choices:
- disable
- enable
ddns-zone:
ddns_zone:
description:
- Zone of your domain name (ex. DDNS.com).
default-gateway:
type: str
default_gateway:
description:
- Default gateway IP address assigned by the DHCP server.
dns-server1:
type: str
dns_server1:
description:
- DNS server 1.
dns-server2:
type: str
dns_server2:
description:
- DNS server 2.
dns-server3:
type: str
dns_server3:
description:
- DNS server 3.
dns-service:
type: str
dns_service:
description:
- Options for assigning DNS servers to DHCP clients.
type: str
choices:
- local
- default
@ -142,26 +167,33 @@ options:
domain:
description:
- Domain name suffix for the IP addresses that the DHCP server assigns to clients.
exclude-range:
type: str
exclude_range:
description:
- Exclude one or more ranges of IP addresses from being assigned to clients.
type: list
suboptions:
end-ip:
end_ip:
description:
- End of IP range.
type: str
id:
description:
- ID.
required: true
start-ip:
type: int
start_ip:
description:
- Start of IP range.
type: str
filename:
description:
- Name of the boot file on the TFTP server.
forticlient-on-net-status:
type: str
forticlient_on_net_status:
description:
- Enable/disable FortiClient-On-Net service for this DHCP server.
type: str
choices:
- disable
- enable
@ -169,59 +201,75 @@ options:
description:
- ID.
required: true
type: int
interface:
description:
- DHCP server can assign IP configurations to clients connected to this interface. Source system.interface.name.
ip-mode:
type: str
ip_mode:
description:
- Method used to assign client IP.
type: str
choices:
- range
- usrgrp
ip-range:
ip_range:
description:
- DHCP IP range configuration.
type: list
suboptions:
end-ip:
end_ip:
description:
- End of IP range.
type: str
id:
description:
- ID.
required: true
start-ip:
type: int
start_ip:
description:
- Start of IP range.
ipsec-lease-hold:
type: str
ipsec_lease_hold:
description:
- DHCP over IPsec leases expire this many seconds after tunnel down (0 to disable forced-expiry).
lease-time:
type: int
lease_time:
description:
- Lease time in seconds, 0 means unlimited.
mac-acl-default-action:
type: int
mac_acl_default_action:
description:
- MAC access control default action (allow or block assigning IP settings).
type: str
choices:
- assign
- block
netmask:
description:
- Netmask assigned by the DHCP server.
next-server:
type: str
next_server:
description:
- IP address of a server (for example, a TFTP sever) that DHCP clients can download a boot file from.
ntp-server1:
type: str
ntp_server1:
description:
- NTP server 1.
ntp-server2:
type: str
ntp_server2:
description:
- NTP server 2.
ntp-server3:
type: str
ntp_server3:
description:
- NTP server 3.
ntp-service:
type: str
ntp_service:
description:
- Options for assigning Network Time Protocol (NTP) servers to DHCP clients.
type: str
choices:
- local
- default
@ -229,34 +277,43 @@ options:
options:
description:
- DHCP options.
type: list
suboptions:
code:
description:
- DHCP option code.
type: int
id:
description:
- ID.
required: true
type: int
ip:
description:
- DHCP option IPs.
type: str
type:
description:
- DHCP option type.
type: str
choices:
- hex
- string
- ip
- fqdn
value:
description:
- DHCP option value.
reserved-address:
type: str
reserved_address:
description:
- Options for the DHCP server to assign IP settings to specific MAC addresses.
type: list
suboptions:
action:
description:
- Options for the DHCP server to configure the client with the reserved MAC address.
type: str
choices:
- assign
- block
@ -264,39 +321,47 @@ options:
description:
description:
- Description.
type: str
id:
description:
- ID.
required: true
type: int
ip:
description:
- IP address to be reserved for the MAC address.
type: str
mac:
description:
- MAC address of the client that will get the reserved IP address.
server-type:
type: str
server_type:
description:
- DHCP server can be a normal DHCP server or an IPsec DHCP server.
type: str
choices:
- regular
- ipsec
status:
description:
- Enable/disable this DHCP configuration.
type: str
choices:
- disable
- enable
tftp-server:
tftp_server:
description:
- One or more hostnames or IP addresses of the TFTP servers in quotes separated by spaces.
type: list
suboptions:
tftp-server:
tftp_server:
description:
- TFTP server.
required: true
type: str
timezone:
description:
- Select the time zone to be assigned to DHCP clients.
type: str
choices:
- 01
- 02
@ -386,42 +451,50 @@ options:
- 73
- 86
- 76
timezone-option:
timezone_option:
description:
- Options for the DHCP server to set the client's time zone.
type: str
choices:
- disable
- default
- specify
vci-match:
vci_match:
description:
- Enable/disable vendor class identifier (VCI) matching. When enabled only DHCP requests with a matching VCI are served.
type: str
choices:
- disable
- enable
vci-string:
vci_string:
description:
- One or more VCI strings in quotes separated by spaces.
type: list
suboptions:
vci-string:
vci_string:
description:
- VCI strings.
required: true
wifi-ac1:
type: str
wifi_ac1:
description:
- WiFi Access Controller 1 IP address (DHCP option 138, RFC 5417).
wifi-ac2:
type: str
wifi_ac2:
description:
- WiFi Access Controller 2 IP address (DHCP option 138, RFC 5417).
wifi-ac3:
type: str
wifi_ac3:
description:
- WiFi Access Controller 3 IP address (DHCP option 138, RFC 5417).
wins-server1:
type: str
wins_server1:
description:
- WINS server 1.
wins-server2:
type: str
wins_server2:
description:
- WINS server 2.
type: str
'''
EXAMPLES = '''
@ -431,6 +504,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure DHCP servers.
fortios_system_dhcp_server:
@ -439,48 +513,48 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
system_dhcp_server:
state: "present"
auto-configuration: "disable"
conflicted-ip-timeout: "4"
ddns-auth: "disable"
ddns-key: "<your_own_value>"
ddns-keyname: "<your_own_value>"
ddns-server-ip: "<your_own_value>"
ddns-ttl: "9"
ddns-update: "disable"
ddns-update-override: "disable"
ddns-zone: "<your_own_value>"
default-gateway: "<your_own_value>"
dns-server1: "<your_own_value>"
dns-server2: "<your_own_value>"
dns-server3: "<your_own_value>"
dns-service: "local"
auto_configuration: "disable"
conflicted_ip_timeout: "4"
ddns_auth: "disable"
ddns_key: "<your_own_value>"
ddns_keyname: "<your_own_value>"
ddns_server_ip: "<your_own_value>"
ddns_ttl: "9"
ddns_update: "disable"
ddns_update_override: "disable"
ddns_zone: "<your_own_value>"
default_gateway: "<your_own_value>"
dns_server1: "<your_own_value>"
dns_server2: "<your_own_value>"
dns_server3: "<your_own_value>"
dns_service: "local"
domain: "<your_own_value>"
exclude-range:
exclude_range:
-
end-ip: "<your_own_value>"
end_ip: "<your_own_value>"
id: "21"
start-ip: "<your_own_value>"
start_ip: "<your_own_value>"
filename: "<your_own_value>"
forticlient-on-net-status: "disable"
forticlient_on_net_status: "disable"
id: "25"
interface: "<your_own_value> (source system.interface.name)"
ip-mode: "range"
ip-range:
ip_mode: "range"
ip_range:
-
end-ip: "<your_own_value>"
end_ip: "<your_own_value>"
id: "30"
start-ip: "<your_own_value>"
ipsec-lease-hold: "32"
lease-time: "33"
mac-acl-default-action: "assign"
start_ip: "<your_own_value>"
ipsec_lease_hold: "32"
lease_time: "33"
mac_acl_default_action: "assign"
netmask: "<your_own_value>"
next-server: "<your_own_value>"
ntp-server1: "<your_own_value>"
ntp-server2: "<your_own_value>"
ntp-server3: "<your_own_value>"
ntp-service: "local"
next_server: "<your_own_value>"
ntp_server1: "<your_own_value>"
ntp_server2: "<your_own_value>"
ntp_server3: "<your_own_value>"
ntp_service: "local"
options:
-
code: "42"
@ -488,29 +562,29 @@ EXAMPLES = '''
ip: "<your_own_value>"
type: "hex"
value: "<your_own_value>"
reserved-address:
reserved_address:
-
action: "assign"
description: "<your_own_value>"
id: "50"
ip: "<your_own_value>"
mac: "<your_own_value>"
server-type: "regular"
server_type: "regular"
status: "disable"
tftp-server:
tftp_server:
-
tftp-server: "<your_own_value>"
tftp_server: "<your_own_value>"
timezone: "01"
timezone-option: "disable"
vci-match: "disable"
vci-string:
timezone_option: "disable"
vci_match: "disable"
vci_string:
-
vci-string: "<your_own_value>"
wifi-ac1: "<your_own_value>"
wifi-ac2: "<your_own_value>"
wifi-ac3: "<your_own_value>"
wins-server1: "<your_own_value>"
wins-server2: "<your_own_value>"
vci_string: "<your_own_value>"
wifi_ac1: "<your_own_value>"
wifi_ac2: "<your_own_value>"
wifi_ac3: "<your_own_value>"
wins_server1: "<your_own_value>"
wins_server2: "<your_own_value>"
'''
RETURN = '''
@ -573,14 +647,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']:
@ -588,26 +664,26 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_dhcp_server_data(json):
option_list = ['auto-configuration', 'conflicted-ip-timeout', 'ddns-auth',
'ddns-key', 'ddns-keyname', 'ddns-server-ip',
'ddns-ttl', 'ddns-update', 'ddns-update-override',
'ddns-zone', 'default-gateway', 'dns-server1',
'dns-server2', 'dns-server3', 'dns-service',
'domain', 'exclude-range', 'filename',
'forticlient-on-net-status', 'id', 'interface',
'ip-mode', 'ip-range', 'ipsec-lease-hold',
'lease-time', 'mac-acl-default-action', 'netmask',
'next-server', 'ntp-server1', 'ntp-server2',
'ntp-server3', 'ntp-service', 'options',
'reserved-address', 'server-type', 'status',
'tftp-server', 'timezone', 'timezone-option',
'vci-match', 'vci-string', 'wifi-ac1',
'wifi-ac2', 'wifi-ac3', 'wins-server1',
'wins-server2']
option_list = ['auto_configuration', 'conflicted_ip_timeout', 'ddns_auth',
'ddns_key', 'ddns_keyname', 'ddns_server_ip',
'ddns_ttl', 'ddns_update', 'ddns_update_override',
'ddns_zone', 'default_gateway', 'dns_server1',
'dns_server2', 'dns_server3', 'dns_service',
'domain', 'exclude_range', 'filename',
'forticlient_on_net_status', 'id', 'interface',
'ip_mode', 'ip_range', 'ipsec_lease_hold',
'lease_time', 'mac_acl_default_action', 'netmask',
'next_server', 'ntp_server1', 'ntp_server2',
'ntp_server3', 'ntp_service', 'options',
'reserved_address', 'server_type', 'status',
'tftp_server', 'timezone', 'timezone_option',
'vci_match', 'vci_string', 'wifi_ac1',
'wifi_ac2', 'wifi_ac3', 'wins_server1',
'wins_server2']
dictionary = {}
for attribute in option_list:
@ -617,111 +693,116 @@ def filter_system_dhcp_server_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 system_dhcp_server(data, fos):
vdom = data['vdom']
state = data['state']
system_dhcp_server_data = data['system_dhcp_server']
flattened_data = flatten_multilists_attributes(system_dhcp_server_data)
filtered_data = filter_system_dhcp_server_data(flattened_data)
if system_dhcp_server_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_system_dhcp_server_data(system_dhcp_server_data))
if state == "present":
return fos.set('system.dhcp',
'server',
data=filtered_data,
vdom=vdom)
elif system_dhcp_server_data['state'] == "absent":
elif state == "absent":
return fos.delete('system.dhcp',
'server',
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_system_dhcp(data, fos):
login(data)
if data['system_dhcp_server']:
resp = system_dhcp_server(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"]},
"system_dhcp_server": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"auto-configuration": {"required": False, "type": "str",
"auto_configuration": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"conflicted-ip-timeout": {"required": False, "type": "int"},
"ddns-auth": {"required": False, "type": "str",
"conflicted_ip_timeout": {"required": False, "type": "int"},
"ddns_auth": {"required": False, "type": "str",
"choices": ["disable", "tsig"]},
"ddns-key": {"required": False, "type": "str"},
"ddns-keyname": {"required": False, "type": "str"},
"ddns-server-ip": {"required": False, "type": "str"},
"ddns-ttl": {"required": False, "type": "int"},
"ddns-update": {"required": False, "type": "str",
"ddns_key": {"required": False, "type": "str"},
"ddns_keyname": {"required": False, "type": "str"},
"ddns_server_ip": {"required": False, "type": "str"},
"ddns_ttl": {"required": False, "type": "int"},
"ddns_update": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"ddns-update-override": {"required": False, "type": "str",
"ddns_update_override": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"ddns-zone": {"required": False, "type": "str"},
"default-gateway": {"required": False, "type": "str"},
"dns-server1": {"required": False, "type": "str"},
"dns-server2": {"required": False, "type": "str"},
"dns-server3": {"required": False, "type": "str"},
"dns-service": {"required": False, "type": "str",
"ddns_zone": {"required": False, "type": "str"},
"default_gateway": {"required": False, "type": "str"},
"dns_server1": {"required": False, "type": "str"},
"dns_server2": {"required": False, "type": "str"},
"dns_server3": {"required": False, "type": "str"},
"dns_service": {"required": False, "type": "str",
"choices": ["local", "default", "specify"]},
"domain": {"required": False, "type": "str"},
"exclude-range": {"required": False, "type": "list",
"exclude_range": {"required": False, "type": "list",
"options": {
"end-ip": {"required": False, "type": "str"},
"end_ip": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"},
"start-ip": {"required": False, "type": "str"}
"start_ip": {"required": False, "type": "str"}
}},
"filename": {"required": False, "type": "str"},
"forticlient-on-net-status": {"required": False, "type": "str",
"forticlient_on_net_status": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"id": {"required": True, "type": "int"},
"interface": {"required": False, "type": "str"},
"ip-mode": {"required": False, "type": "str",
"ip_mode": {"required": False, "type": "str",
"choices": ["range", "usrgrp"]},
"ip-range": {"required": False, "type": "list",
"ip_range": {"required": False, "type": "list",
"options": {
"end-ip": {"required": False, "type": "str"},
"end_ip": {"required": False, "type": "str"},
"id": {"required": True, "type": "int"},
"start-ip": {"required": False, "type": "str"}
"start_ip": {"required": False, "type": "str"}
}},
"ipsec-lease-hold": {"required": False, "type": "int"},
"lease-time": {"required": False, "type": "int"},
"mac-acl-default-action": {"required": False, "type": "str",
"ipsec_lease_hold": {"required": False, "type": "int"},
"lease_time": {"required": False, "type": "int"},
"mac_acl_default_action": {"required": False, "type": "str",
"choices": ["assign", "block"]},
"netmask": {"required": False, "type": "str"},
"next-server": {"required": False, "type": "str"},
"ntp-server1": {"required": False, "type": "str"},
"ntp-server2": {"required": False, "type": "str"},
"ntp-server3": {"required": False, "type": "str"},
"ntp-service": {"required": False, "type": "str",
"next_server": {"required": False, "type": "str"},
"ntp_server1": {"required": False, "type": "str"},
"ntp_server2": {"required": False, "type": "str"},
"ntp_server3": {"required": False, "type": "str"},
"ntp_service": {"required": False, "type": "str",
"choices": ["local", "default", "specify"]},
"options": {"required": False, "type": "list",
"options": {
@ -729,10 +810,11 @@ def main():
"id": {"required": True, "type": "int"},
"ip": {"required": False, "type": "str"},
"type": {"required": False, "type": "str",
"choices": ["hex", "string", "ip"]},
"choices": ["hex", "string", "ip",
"fqdn"]},
"value": {"required": False, "type": "str"}
}},
"reserved-address": {"required": False, "type": "list",
"reserved_address": {"required": False, "type": "list",
"options": {
"action": {"required": False, "type": "str",
"choices": ["assign", "block", "reserved"]},
@ -741,13 +823,13 @@ def main():
"ip": {"required": False, "type": "str"},
"mac": {"required": False, "type": "str"}
}},
"server-type": {"required": False, "type": "str",
"server_type": {"required": False, "type": "str",
"choices": ["regular", "ipsec"]},
"status": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"tftp-server": {"required": False, "type": "list",
"tftp_server": {"required": False, "type": "list",
"options": {
"tftp-server": {"required": True, "type": "str"}
"tftp_server": {"required": False, "type": "str"}
}},
"timezone": {"required": False, "type": "str",
"choices": ["01", "02", "03",
@ -780,19 +862,19 @@ def main():
"71", "72", "00",
"82", "73", "86",
"76"]},
"timezone-option": {"required": False, "type": "str",
"timezone_option": {"required": False, "type": "str",
"choices": ["disable", "default", "specify"]},
"vci-match": {"required": False, "type": "str",
"vci_match": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"vci-string": {"required": False, "type": "list",
"vci_string": {"required": False, "type": "list",
"options": {
"vci-string": {"required": True, "type": "str"}
"vci_string": {"required": False, "type": "str"}
}},
"wifi-ac1": {"required": False, "type": "str"},
"wifi-ac2": {"required": False, "type": "str"},
"wifi-ac3": {"required": False, "type": "str"},
"wins-server1": {"required": False, "type": "str"},
"wins-server2": {"required": False, "type": "str"}
"wifi_ac1": {"required": False, "type": "str"},
"wifi_ac2": {"required": False, "type": "str"},
"wifi_ac3": {"required": False, "type": "str"},
"wins_server1": {"required": False, "type": "str"},
"wins_server2": {"required": False, "type": "str"}
}
}
@ -800,15 +882,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_system_dhcp(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_system_dhcp(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system_dhcp(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -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_system_dns
short_description: Configure DNS 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 system feature and dns 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)
@ -44,64 +41,97 @@ 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
system_dns:
description:
- Configure DNS.
default: null
type: dict
suboptions:
cache-notfound-responses:
cache_notfound_responses:
description:
- Enable/disable response from the DNS server when a record is not in cache.
type: str
choices:
- disable
- enable
dns-cache-limit:
dns_cache_limit:
description:
- Maximum number of records in the DNS cache.
dns-cache-ttl:
type: int
dns_cache_ttl:
description:
- Duration in seconds that the DNS cache retains information.
type: int
domain:
description:
- Domain name suffix for the IP addresses of the DNS server.
ip6-primary:
- Search suffix list for hostname lookup.
type: list
suboptions:
domain:
description:
- DNS search domain list separated by space (maximum 8 domains)
required: true
type: str
ip6_primary:
description:
- Primary DNS server IPv6 address.
ip6-secondary:
type: str
ip6_secondary:
description:
- Secondary DNS server IPv6 address.
type: str
primary:
description:
- Primary DNS server IP address, default is FortiGuard server at 208.81.112.53.
- Primary DNS server IP address.
type: str
retry:
description:
- Number of times to retry (0 - 5).
type: int
secondary:
description:
- Secondary DNS server IP address, default is FortiGuard server at 208.81.112.52.
source-ip:
- Secondary DNS server IP address.
type: str
source_ip:
description:
- IP address used by the DNS server as its source IP.
type: str
timeout:
description:
- DNS query timeout interval in seconds (1 - 10).
type: int
'''
EXAMPLES = '''
@ -111,6 +141,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure DNS.
fortios_system_dns:
@ -120,15 +151,19 @@ EXAMPLES = '''
vdom: "{{ vdom }}"
https: "False"
system_dns:
cache-notfound-responses: "disable"
dns-cache-limit: "4"
dns-cache-ttl: "5"
domain: "<your_own_value>"
ip6-primary: "<your_own_value>"
ip6-secondary: "<your_own_value>"
cache_notfound_responses: "disable"
dns_cache_limit: "4"
dns_cache_ttl: "5"
domain:
-
domain: "<your_own_value>"
ip6_primary: "<your_own_value>"
ip6_secondary: "<your_own_value>"
primary: "<your_own_value>"
retry: "11"
secondary: "<your_own_value>"
source-ip: "84.230.14.43"
source_ip: "84.230.14.43"
timeout: "14"
'''
RETURN = '''
@ -191,14 +226,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']:
@ -206,13 +243,14 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_dns_data(json):
option_list = ['cache-notfound-responses', 'dns-cache-limit', 'dns-cache-ttl',
'domain', 'ip6-primary', 'ip6-secondary',
'primary', 'secondary', 'source-ip']
option_list = ['cache_notfound_responses', 'dns_cache_limit', 'dns_cache_ttl',
'domain', 'ip6_primary', 'ip6_secondary',
'primary', 'retry', 'secondary',
'source_ip', 'timeout']
dictionary = {}
for attribute in option_list:
@ -222,17 +260,15 @@ def filter_system_dns_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
@ -240,44 +276,55 @@ def flatten_multilists_attributes(data):
def system_dns(data, fos):
vdom = data['vdom']
system_dns_data = data['system_dns']
flattened_data = flatten_multilists_attributes(system_dns_data)
filtered_data = filter_system_dns_data(flattened_data)
filtered_data = underscore_to_hyphen(filter_system_dns_data(system_dns_data))
return fos.set('system',
'dns',
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_system(data, fos):
login(data)
if data['system_dns']:
resp = system_dns(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},
"system_dns": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"cache-notfound-responses": {"required": False, "type": "str",
"cache_notfound_responses": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"dns-cache-limit": {"required": False, "type": "int"},
"dns-cache-ttl": {"required": False, "type": "int"},
"domain": {"required": False, "type": "str"},
"ip6-primary": {"required": False, "type": "str"},
"ip6-secondary": {"required": False, "type": "str"},
"dns_cache_limit": {"required": False, "type": "int"},
"dns_cache_ttl": {"required": False, "type": "int"},
"domain": {"required": False, "type": "list",
"options": {
"domain": {"required": True, "type": "str"}
}},
"ip6_primary": {"required": False, "type": "str"},
"ip6_secondary": {"required": False, "type": "str"},
"primary": {"required": False, "type": "str"},
"retry": {"required": False, "type": "int"},
"secondary": {"required": False, "type": "str"},
"source-ip": {"required": False, "type": "str"}
"source_ip": {"required": False, "type": "str"},
"timeout": {"required": False, "type": "int"}
}
}
@ -285,15 +332,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_system(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_system(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

File diff suppressed because it is too large Load Diff

@ -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_system_sdn_connector
short_description: Configure connection to SDN Connector.
short_description: Configure connection to SDN Connector in Fortinet's FortiOS and FortiGate.
description:
- This module is able to configure a FortiGate or FortiOS by
allowing the user to configure system feature and sdn_connector 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 system feature and sdn_connector 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,106 +41,142 @@ 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
state:
description:
- Indicates whether to create or remove the object.
type: str
required: true
choices:
- present
- absent
version_added: 2.9
system_sdn_connector:
description:
- Configure connection to SDN Connector.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
access-key:
access_key:
description:
- AWS access key ID.
azure-region:
type: str
azure_region:
description:
- Azure server region.
type: str
choices:
- global
- china
- germany
- usgov
client-id:
- local
client_id:
description:
- Azure client ID (application ID).
client-secret:
type: str
client_secret:
description:
- Azure client secret (application key).
compartment-id:
type: str
compartment_id:
description:
- Compartment ID.
external-ip:
type: str
external_ip:
description:
- Configure GCP external IP.
type: list
suboptions:
name:
description:
- External IP name.
required: true
gcp-project:
type: str
gcp_project:
description:
- GCP project name.
key-passwd:
type: str
key_passwd:
description:
- Private key password.
type: str
login_endpoint:
description:
- Azure Stack login enpoint.
type: str
name:
description:
- SDN connector name.
required: true
type: str
nic:
description:
- Configure Azure network interface.
type: list
suboptions:
ip:
description:
- Configure IP configuration.
type: list
suboptions:
name:
description:
- IP configuration name.
required: true
public-ip:
type: str
public_ip:
description:
- Public IP name.
type: str
name:
description:
- Network interface name.
required: true
oci-cert:
type: str
oci_cert:
description:
- OCI certificate. Source certificate.local.name.
oci-fingerprint:
type: str
oci_fingerprint:
description:
- OCI pubkey fingerprint.
oci-region:
type: str
oci_region:
description:
- OCI server region.
type: str
choices:
- phoenix
- ashburn
@ -152,95 +185,124 @@ options:
password:
description:
- Password of the remote SDN connector as login credentials.
private-key:
type: str
private_key:
description:
- Private key of GCP service account.
type: str
region:
description:
- AWS region name.
resource-group:
type: str
resource_group:
description:
- Azure resource group.
type: str
resource_url:
description:
- Azure Stack resource URL.
type: str
route:
description:
- Configure GCP route.
type: list
suboptions:
name:
description:
- Route name.
required: true
route-table:
type: str
route_table:
description:
- Configure Azure route table.
type: list
suboptions:
name:
description:
- Route table name.
required: true
type: str
route:
description:
- Configure Azure route.
type: list
suboptions:
name:
description:
- Route name.
required: true
next-hop:
type: str
next_hop:
description:
- Next hop address.
secret-key:
type: str
secret_key:
description:
- AWS secret access key.
type: str
server:
description:
- Server address of the remote SDN connector.
server-port:
type: str
server_port:
description:
- Port number of the remote SDN connector.
service-account:
type: int
service_account:
description:
- GCP service account email.
type: str
status:
description:
- Enable/disable connection to the remote SDN connector.
type: str
choices:
- disable
- enable
subscription-id:
subscription_id:
description:
- Azure subscription ID.
tenant-id:
type: str
tenant_id:
description:
- Tenant ID (directory ID).
type: str
type:
description:
- Type of SDN connector.
type: str
choices:
- aci
- aws
- azure
- gcp
- nsx
- nuage
- oci
- gcp
update-interval:
- openstack
update_interval:
description:
- Dynamic object update interval (0 - 3600 sec, 0 means disabled, default = 60).
use-metadata-iam:
- Dynamic object update interval (0 - 3600 sec, 0 means disabled).
type: int
use_metadata_iam:
description:
- Enable/disable using IAM role from metadata to call API.
type: str
choices:
- disable
- enable
user-id:
user_id:
description:
- User ID.
type: str
username:
description:
- Username of the remote SDN connector as login credentials.
vpc-id:
type: str
vpc_id:
description:
- AWS VPC ID.
type: str
'''
EXAMPLES = '''
@ -250,63 +312,67 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure connection to SDN Connector.
fortios_system_sdn_connector:
host: "{{ host }}"
host: "{{ host }}"
username: "{{ username }}"
password: "{{ password }}"
vdom: "{{ vdom }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
system_sdn_connector:
state: "present"
access-key: "<your_own_value>"
azure-region: "global"
client-id: "<your_own_value>"
client-secret: "<your_own_value>"
compartment-id: "<your_own_value>"
external-ip:
access_key: "<your_own_value>"
azure_region: "global"
client_id: "<your_own_value>"
client_secret: "<your_own_value>"
compartment_id: "<your_own_value>"
external_ip:
-
name: "default_name_9"
gcp-project: "<your_own_value>"
key-passwd: "<your_own_value>"
name: "default_name_12"
gcp_project: "<your_own_value>"
key_passwd: "<your_own_value>"
login_endpoint: "<your_own_value>"
name: "default_name_13"
nic:
-
ip:
-
name: "default_name_15"
public-ip: "<your_own_value>"
name: "default_name_17"
oci-cert: "<your_own_value> (source certificate.local.name)"
oci-fingerprint: "<your_own_value>"
oci-region: "phoenix"
name: "default_name_16"
public_ip: "<your_own_value>"
name: "default_name_18"
oci_cert: "<your_own_value> (source certificate.local.name)"
oci_fingerprint: "<your_own_value>"
oci_region: "phoenix"
password: "<your_own_value>"
private-key: "<your_own_value>"
private_key: "<your_own_value>"
region: "<your_own_value>"
resource-group: "<your_own_value>"
resource_group: "<your_own_value>"
resource_url: "<your_own_value>"
route:
-
name: "default_name_26"
route-table:
-
name: "default_name_28"
route_table:
-
name: "default_name_30"
route:
-
name: "default_name_30"
next-hop: "<your_own_value>"
secret-key: "<your_own_value>"
name: "default_name_32"
next_hop: "<your_own_value>"
secret_key: "<your_own_value>"
server: "192.168.100.40"
server-port: "34"
service-account: "<your_own_value>"
server_port: "36"
service_account: "<your_own_value>"
status: "disable"
subscription-id: "<your_own_value>"
tenant-id: "<your_own_value>"
subscription_id: "<your_own_value>"
tenant_id: "<your_own_value>"
type: "aci"
update-interval: "40"
use-metadata-iam: "disable"
user-id: "<your_own_value>"
update_interval: "42"
use_metadata_iam: "disable"
user_id: "<your_own_value>"
username: "<your_own_value>"
vpc-id: "<your_own_value>"
vpc_id: "<your_own_value>"
'''
RETURN = '''
@ -329,7 +395,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
@ -369,14 +435,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']:
@ -384,135 +452,156 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_sdn_connector_data(json):
option_list = ['access-key', 'azure-region', 'client-id',
'client-secret', 'compartment-id', 'external-ip',
'gcp-project', 'key-passwd', 'name',
'nic', 'oci-cert', 'oci-fingerprint',
'oci-region', 'password', 'private-key',
'region', 'resource-group', 'route',
'route-table', 'secret-key', 'server',
'server-port', 'service-account', 'status',
'subscription-id', 'tenant-id', 'type',
'update-interval', 'use-metadata-iam', 'user-id',
'username', 'vpc-id']
option_list = ['access_key', 'azure_region', 'client_id',
'client_secret', 'compartment_id', 'external_ip',
'gcp_project', 'key_passwd', 'login_endpoint',
'name', 'nic', 'oci_cert',
'oci_fingerprint', 'oci_region', 'password',
'private_key', 'region', 'resource_group',
'resource_url', 'route', 'route_table',
'secret_key', 'server', 'server_port',
'service_account', 'status', 'subscription_id',
'tenant_id', 'type', 'update_interval',
'use_metadata_iam', 'user_id', 'username',
'vpc_id']
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 system_sdn_connector(data, fos):
vdom = data['vdom']
state = data['state']
system_sdn_connector_data = data['system_sdn_connector']
filtered_data = filter_system_sdn_connector_data(system_sdn_connector_data)
if system_sdn_connector_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_system_sdn_connector_data(system_sdn_connector_data))
if state == "present":
return fos.set('system',
'sdn-connector',
data=filtered_data,
vdom=vdom)
elif system_sdn_connector_data['state'] == "absent":
elif state == "absent":
return fos.delete('system',
'sdn-connector',
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_system(data, fos):
login(data)
methodlist = ['system_sdn_connector']
for method in methodlist:
if data[method]:
resp = eval(method)(data, fos)
break
if data['system_sdn_connector']:
resp = system_sdn_connector(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"]},
"system_sdn_connector": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"access-key": {"required": False, "type": "str"},
"azure-region": {"required": False, "type": "str",
"access_key": {"required": False, "type": "str"},
"azure_region": {"required": False, "type": "str",
"choices": ["global", "china", "germany",
"usgov"]},
"client-id": {"required": False, "type": "str"},
"client-secret": {"required": False, "type": "str"},
"compartment-id": {"required": False, "type": "str"},
"external-ip": {"required": False, "type": "list",
"usgov", "local"]},
"client_id": {"required": False, "type": "str"},
"client_secret": {"required": False, "type": "str"},
"compartment_id": {"required": False, "type": "str"},
"external_ip": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
"gcp-project": {"required": False, "type": "str"},
"key-passwd": {"required": False, "type": "str"},
"gcp_project": {"required": False, "type": "str"},
"key_passwd": {"required": False, "type": "str"},
"login_endpoint": {"required": False, "type": "str"},
"name": {"required": True, "type": "str"},
"nic": {"required": False, "type": "list",
"options": {
"ip": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"},
"public-ip": {"required": False, "type": "str"}
"public_ip": {"required": False, "type": "str"}
}},
"name": {"required": True, "type": "str"}
}},
"oci-cert": {"required": False, "type": "str"},
"oci-fingerprint": {"required": False, "type": "str"},
"oci-region": {"required": False, "type": "str",
"oci_cert": {"required": False, "type": "str"},
"oci_fingerprint": {"required": False, "type": "str"},
"oci_region": {"required": False, "type": "str",
"choices": ["phoenix", "ashburn", "frankfurt",
"london"]},
"password": {"required": False, "type": "str"},
"private-key": {"required": False, "type": "str"},
"private_key": {"required": False, "type": "str"},
"region": {"required": False, "type": "str"},
"resource-group": {"required": False, "type": "str"},
"resource_group": {"required": False, "type": "str"},
"resource_url": {"required": False, "type": "str"},
"route": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"}
}},
"route-table": {"required": False, "type": "list",
"route_table": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"},
"route": {"required": False, "type": "list",
"options": {
"name": {"required": True, "type": "str"},
"next-hop": {"required": False, "type": "str"}
"next_hop": {"required": False, "type": "str"}
}}
}},
"secret-key": {"required": False, "type": "str"},
"secret_key": {"required": False, "type": "str"},
"server": {"required": False, "type": "str"},
"server-port": {"required": False, "type": "int"},
"service-account": {"required": False, "type": "str"},
"server_port": {"required": False, "type": "int"},
"service_account": {"required": False, "type": "str"},
"status": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"subscription-id": {"required": False, "type": "str"},
"tenant-id": {"required": False, "type": "str"},
"subscription_id": {"required": False, "type": "str"},
"tenant_id": {"required": False, "type": "str"},
"type": {"required": False, "type": "str",
"choices": ["aci", "aws", "azure",
"nsx", "nuage", "oci",
"gcp"]},
"update-interval": {"required": False, "type": "int"},
"use-metadata-iam": {"required": False, "type": "str",
"gcp", "nsx", "nuage",
"oci", "openstack"]},
"update_interval": {"required": False, "type": "int"},
"use_metadata_iam": {"required": False, "type": "str",
"choices": ["disable", "enable"]},
"user-id": {"required": False, "type": "str"},
"user_id": {"required": False, "type": "str"},
"username": {"required": False, "type": "str"},
"vpc-id": {"required": False, "type": "str"}
"vpc_id": {"required": False, "type": "str"}
}
}
@ -520,15 +609,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_system(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_system(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -130,11 +130,11 @@ options:
- disable
bfd_desired_min_tx:
description:
- BFD desired minimal transmit interval (1 - 100000 ms, default = 50).
- BFD desired minimal transmit interval (1 - 100000 ms).
type: int
bfd_detect_mult:
description:
- BFD detection multiplier (1 - 50, default = 3).
- BFD detection multiplier (1 - 50).
type: int
bfd_dont_enforce_src_port:
description:
@ -145,7 +145,7 @@ options:
- disable
bfd_required_min_rx:
description:
- BFD required minimal receive interval (1 - 100000 ms, default = 50).
- BFD required minimal receive interval (1 - 100000 ms).
type: int
block_land_attack:
description:
@ -207,11 +207,11 @@ options:
type: str
discovered_device_timeout:
description:
- Timeout for discovered devices (1 - 365 days, default = 28).
- Timeout for discovered devices (1 - 365 days).
type: int
ecmp_max_paths:
description:
- Maximum number of Equal Cost Multi-Path (ECMP) next-hops. Set to 1 to disable ECMP routing (1 - 100, default = 10).
- Maximum number of Equal Cost Multi-Path (ECMP) next-hops. Set to 1 to disable ECMP routing (1 - 100).
type: int
email_portal_check_dns:
description:
@ -649,7 +649,7 @@ options:
- global
mac_ttl:
description:
- Duration of MAC addresses in Transparent mode (300 - 8640000 sec, default = 300).
- Duration of MAC addresses in Transparent mode (300 - 8640000 sec).
type: int
manageip:
description:
@ -703,7 +703,7 @@ options:
- disable
sccp_port:
description:
- TCP port the SCCP proxy monitors for SCCP traffic (0 - 65535, default = 2000).
- TCP port the SCCP proxy monitors for SCCP traffic (0 - 65535).
type: int
ses_denied_traffic:
description:
@ -729,15 +729,15 @@ options:
- disable
sip_ssl_port:
description:
- TCP port the SIP proxy monitors for SIP SSL/TLS traffic (0 - 65535, default = 5061).
- TCP port the SIP proxy monitors for SIP SSL/TLS traffic (0 - 65535).
type: int
sip_tcp_port:
description:
- TCP port the SIP proxy monitors for SIP traffic (0 - 65535, default = 5060).
- TCP port the SIP proxy monitors for SIP traffic (0 - 65535).
type: int
sip_udp_port:
description:
- UDP port the SIP proxy monitors for SIP traffic (0 - 65535, default = 5060).
- UDP port the SIP proxy monitors for SIP traffic (0 - 65535).
type: int
snat_hairpin_traffic:
description:

@ -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_system_vdom
short_description: Configure virtual domain 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 system feature and vdom 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)
@ -44,53 +41,70 @@ 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
system_vdom:
description:
- Configure virtual domain.
default: null
type: dict
suboptions:
state:
description:
- Indicates whether to create or remove the object
choices:
- present
- absent
name:
description:
- VDOM name.
required: true
short-name:
type: str
short_name:
description:
- VDOM short name.
type: str
temporary:
description:
- Temporary.
vcluster-id:
type: int
vcluster_id:
description:
- Virtual cluster ID (0 - 4294967295).
type: int
'''
EXAMPLES = '''
@ -100,6 +114,7 @@ EXAMPLES = '''
username: "admin"
password: ""
vdom: "root"
ssl_verify: "False"
tasks:
- name: Configure virtual domain.
fortios_system_vdom:
@ -108,12 +123,12 @@ EXAMPLES = '''
password: "{{ password }}"
vdom: "{{ vdom }}"
https: "False"
state: "present"
system_vdom:
state: "present"
name: "default_name_3"
short-name: "<your_own_value>"
short_name: "<your_own_value>"
temporary: "5"
vcluster-id: "6"
vcluster_id: "6"
'''
RETURN = '''
@ -176,14 +191,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']:
@ -191,12 +208,12 @@ def login(data):
else:
fos.https('on')
fos.login(host, username, password)
fos.login(host, username, password, verify=ssl_verify)
def filter_system_vdom_data(json):
option_list = ['name', 'short-name', 'temporary',
'vcluster-id']
option_list = ['name', 'short_name', 'temporary',
'vcluster_id']
dictionary = {}
for attribute in option_list:
@ -206,65 +223,70 @@ def filter_system_vdom_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 system_vdom(data, fos):
vdom = data['vdom']
state = data['state']
system_vdom_data = data['system_vdom']
flattened_data = flatten_multilists_attributes(system_vdom_data)
filtered_data = filter_system_vdom_data(flattened_data)
if system_vdom_data['state'] == "present":
filtered_data = underscore_to_hyphen(filter_system_vdom_data(system_vdom_data))
if state == "present":
return fos.set('system',
'vdom',
data=filtered_data,
vdom=vdom)
elif system_vdom_data['state'] == "absent":
elif state == "absent":
return fos.delete('system',
'vdom',
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_system(data, fos):
login(data)
if data['system_vdom']:
resp = system_vdom(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"]},
"system_vdom": {
"required": False, "type": "dict",
"required": False, "type": "dict", "default": None,
"options": {
"state": {"required": True, "type": "str",
"choices": ["present", "absent"]},
"name": {"required": True, "type": "str"},
"short-name": {"required": False, "type": "str"},
"short_name": {"required": False, "type": "str"},
"temporary": {"required": False, "type": "int"},
"vcluster-id": {"required": False, "type": "int"}
"vcluster_id": {"required": False, "type": "int"}
}
}
@ -272,15 +294,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_system(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_system(module.params, fos)
login(module.params, fos)
is_error, has_changed, result = fortios_system(module.params, fos)
fos.logout()
if not is_error:
module.exit_json(changed=has_changed, meta=result)

@ -3693,46 +3693,10 @@ lib/ansible/modules/network/fortios/fortios_firewall_sniffer.py validate-modules
lib/ansible/modules/network/fortios/fortios_ipv4_policy.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ipv4_policy.py validate-modules:E338
lib/ansible/modules/network/fortios/fortios_report_chart.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_spamfilter_profile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_spamfilter_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_ssh_filter_profile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_ssh_filter_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_switch_controller_global.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_switch_controller_global.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_switch_controller_lldp_profile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_switch_controller_lldp_profile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_switch_controller_lldp_settings.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_switch_controller_lldp_settings.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_switch_controller_mac_sync_settings.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_switch_controller_mac_sync_settings.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_switch_controller_managed_switch.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_switch_controller_managed_switch.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_switch_controller_network_monitor_settings.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_switch_controller_network_monitor_settings.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_accprofile.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_accprofile.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_admin.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_admin.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_api_user.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_api_user.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_central_management.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_central_management.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_dhcp_server.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_system_dhcp_server.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_dhcp_server.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_dns.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_dns.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_global.py validate-modules:E326
lib/ansible/modules/network/fortios/fortios_system_global.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_global.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_interface.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_interface.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_sdn_connector.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_sdn_connector.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_vdom.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_vdom.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_system_virtual_wan_link.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_system_virtual_wan_link.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_user_adgrp.py validate-modules:E336
lib/ansible/modules/network/fortios/fortios_user_adgrp.py validate-modules:E337
lib/ansible/modules/network/fortios/fortios_user_device.py validate-modules:E337

@ -0,0 +1,339 @@
# 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_spamfilter_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_spamfilter_profile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_spamfilter_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',
'spamfilter_profile': {
'comment': 'Comment.',
'external': 'enable',
'flow_based': 'enable',
'name': 'default_name_6',
'replacemsg_group': 'test_value_7',
'spam_bwl_table': '8',
'spam_bword_table': '9',
'spam_bword_threshold': '10',
'spam_filtering': 'enable',
'spam_iptrust_table': '12',
'spam_log': 'disable',
'spam_log_fortiguard_response': 'disable',
'spam_mheader_table': '15',
'spam_rbl_table': '16',
},
'vdom': 'root'}
is_error, changed, response = fortios_spamfilter_profile.fortios_spamfilter(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'external': 'enable',
'flow-based': 'enable',
'name': 'default_name_6',
'replacemsg-group': 'test_value_7',
'spam-bwl-table': '8',
'spam-bword-table': '9',
'spam-bword-threshold': '10',
'spam-filtering': 'enable',
'spam-iptrust-table': '12',
'spam-log': 'disable',
'spam-log-fortiguard-response': 'disable',
'spam-mheader-table': '15',
'spam-rbl-table': '16',
}
set_method_mock.assert_called_with('spamfilter', '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_spamfilter_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',
'spamfilter_profile': {
'comment': 'Comment.',
'external': 'enable',
'flow_based': 'enable',
'name': 'default_name_6',
'replacemsg_group': 'test_value_7',
'spam_bwl_table': '8',
'spam_bword_table': '9',
'spam_bword_threshold': '10',
'spam_filtering': 'enable',
'spam_iptrust_table': '12',
'spam_log': 'disable',
'spam_log_fortiguard_response': 'disable',
'spam_mheader_table': '15',
'spam_rbl_table': '16',
},
'vdom': 'root'}
is_error, changed, response = fortios_spamfilter_profile.fortios_spamfilter(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'external': 'enable',
'flow-based': 'enable',
'name': 'default_name_6',
'replacemsg-group': 'test_value_7',
'spam-bwl-table': '8',
'spam-bword-table': '9',
'spam-bword-threshold': '10',
'spam-filtering': 'enable',
'spam-iptrust-table': '12',
'spam-log': 'disable',
'spam-log-fortiguard-response': 'disable',
'spam-mheader-table': '15',
'spam-rbl-table': '16',
}
set_method_mock.assert_called_with('spamfilter', '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_spamfilter_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',
'spamfilter_profile': {
'comment': 'Comment.',
'external': 'enable',
'flow_based': 'enable',
'name': 'default_name_6',
'replacemsg_group': 'test_value_7',
'spam_bwl_table': '8',
'spam_bword_table': '9',
'spam_bword_threshold': '10',
'spam_filtering': 'enable',
'spam_iptrust_table': '12',
'spam_log': 'disable',
'spam_log_fortiguard_response': 'disable',
'spam_mheader_table': '15',
'spam_rbl_table': '16',
},
'vdom': 'root'}
is_error, changed, response = fortios_spamfilter_profile.fortios_spamfilter(input_data, fos_instance)
delete_method_mock.assert_called_with('spamfilter', '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_spamfilter_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',
'spamfilter_profile': {
'comment': 'Comment.',
'external': 'enable',
'flow_based': 'enable',
'name': 'default_name_6',
'replacemsg_group': 'test_value_7',
'spam_bwl_table': '8',
'spam_bword_table': '9',
'spam_bword_threshold': '10',
'spam_filtering': 'enable',
'spam_iptrust_table': '12',
'spam_log': 'disable',
'spam_log_fortiguard_response': 'disable',
'spam_mheader_table': '15',
'spam_rbl_table': '16',
},
'vdom': 'root'}
is_error, changed, response = fortios_spamfilter_profile.fortios_spamfilter(input_data, fos_instance)
delete_method_mock.assert_called_with('spamfilter', '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_spamfilter_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',
'spamfilter_profile': {
'comment': 'Comment.',
'external': 'enable',
'flow_based': 'enable',
'name': 'default_name_6',
'replacemsg_group': 'test_value_7',
'spam_bwl_table': '8',
'spam_bword_table': '9',
'spam_bword_threshold': '10',
'spam_filtering': 'enable',
'spam_iptrust_table': '12',
'spam_log': 'disable',
'spam_log_fortiguard_response': 'disable',
'spam_mheader_table': '15',
'spam_rbl_table': '16',
},
'vdom': 'root'}
is_error, changed, response = fortios_spamfilter_profile.fortios_spamfilter(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'external': 'enable',
'flow-based': 'enable',
'name': 'default_name_6',
'replacemsg-group': 'test_value_7',
'spam-bwl-table': '8',
'spam-bword-table': '9',
'spam-bword-threshold': '10',
'spam-filtering': 'enable',
'spam-iptrust-table': '12',
'spam-log': 'disable',
'spam-log-fortiguard-response': 'disable',
'spam-mheader-table': '15',
'spam-rbl-table': '16',
}
set_method_mock.assert_called_with('spamfilter', '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_spamfilter_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',
'spamfilter_profile': {
'random_attribute_not_valid': 'tag',
'comment': 'Comment.',
'external': 'enable',
'flow_based': 'enable',
'name': 'default_name_6',
'replacemsg_group': 'test_value_7',
'spam_bwl_table': '8',
'spam_bword_table': '9',
'spam_bword_threshold': '10',
'spam_filtering': 'enable',
'spam_iptrust_table': '12',
'spam_log': 'disable',
'spam_log_fortiguard_response': 'disable',
'spam_mheader_table': '15',
'spam_rbl_table': '16',
},
'vdom': 'root'}
is_error, changed, response = fortios_spamfilter_profile.fortios_spamfilter(input_data, fos_instance)
expected_data = {
'comment': 'Comment.',
'external': 'enable',
'flow-based': 'enable',
'name': 'default_name_6',
'replacemsg-group': 'test_value_7',
'spam-bwl-table': '8',
'spam-bword-table': '9',
'spam-bword-threshold': '10',
'spam-filtering': 'enable',
'spam-iptrust-table': '12',
'spam-log': 'disable',
'spam-log-fortiguard-response': 'disable',
'spam-mheader-table': '15',
'spam-rbl-table': '16',
}
set_method_mock.assert_called_with('spamfilter', '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

@ -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_ssh_filter_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_ssh_filter_profile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_ssh_filter_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',
'ssh_filter_profile': {
'block': 'x11',
'default_command_log': 'enable',
'log': 'x11',
'name': 'default_name_6',
},
'vdom': 'root'}
is_error, changed, response = fortios_ssh_filter_profile.fortios_ssh_filter(input_data, fos_instance)
expected_data = {
'block': 'x11',
'default-command-log': 'enable',
'log': 'x11',
'name': 'default_name_6',
}
set_method_mock.assert_called_with('ssh-filter', '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_ssh_filter_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',
'ssh_filter_profile': {
'block': 'x11',
'default_command_log': 'enable',
'log': 'x11',
'name': 'default_name_6',
},
'vdom': 'root'}
is_error, changed, response = fortios_ssh_filter_profile.fortios_ssh_filter(input_data, fos_instance)
expected_data = {
'block': 'x11',
'default-command-log': 'enable',
'log': 'x11',
'name': 'default_name_6',
}
set_method_mock.assert_called_with('ssh-filter', '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_ssh_filter_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',
'ssh_filter_profile': {
'block': 'x11',
'default_command_log': 'enable',
'log': 'x11',
'name': 'default_name_6',
},
'vdom': 'root'}
is_error, changed, response = fortios_ssh_filter_profile.fortios_ssh_filter(input_data, fos_instance)
delete_method_mock.assert_called_with('ssh-filter', '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_ssh_filter_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',
'ssh_filter_profile': {
'block': 'x11',
'default_command_log': 'enable',
'log': 'x11',
'name': 'default_name_6',
},
'vdom': 'root'}
is_error, changed, response = fortios_ssh_filter_profile.fortios_ssh_filter(input_data, fos_instance)
delete_method_mock.assert_called_with('ssh-filter', '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_ssh_filter_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',
'ssh_filter_profile': {
'block': 'x11',
'default_command_log': 'enable',
'log': 'x11',
'name': 'default_name_6',
},
'vdom': 'root'}
is_error, changed, response = fortios_ssh_filter_profile.fortios_ssh_filter(input_data, fos_instance)
expected_data = {
'block': 'x11',
'default-command-log': 'enable',
'log': 'x11',
'name': 'default_name_6',
}
set_method_mock.assert_called_with('ssh-filter', '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_ssh_filter_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',
'ssh_filter_profile': {
'random_attribute_not_valid': 'tag',
'block': 'x11',
'default_command_log': 'enable',
'log': 'x11',
'name': 'default_name_6',
},
'vdom': 'root'}
is_error, changed, response = fortios_ssh_filter_profile.fortios_ssh_filter(input_data, fos_instance)
expected_data = {
'block': 'x11',
'default-command-log': 'enable',
'log': 'x11',
'name': 'default_name_6',
}
set_method_mock.assert_called_with('ssh-filter', '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

@ -0,0 +1,199 @@
# 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_switch_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_switch_controller_global.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_switch_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',
'switch_controller_global': {
'allow_multiple_interfaces': 'enable',
'default_virtual_switch_vlan': 'test_value_4',
'https_image_push': 'enable',
'log_mac_limit_violations': 'enable',
'mac_aging_interval': '7',
'mac_retention_period': '8',
'mac_violation_timer': '9'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_global.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'allow-multiple-interfaces': 'enable',
'default-virtual-switch-vlan': 'test_value_4',
'https-image-push': 'enable',
'log-mac-limit-violations': 'enable',
'mac-aging-interval': '7',
'mac-retention-period': '8',
'mac-violation-timer': '9'
}
set_method_mock.assert_called_with('switch-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_switch_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',
'switch_controller_global': {
'allow_multiple_interfaces': 'enable',
'default_virtual_switch_vlan': 'test_value_4',
'https_image_push': 'enable',
'log_mac_limit_violations': 'enable',
'mac_aging_interval': '7',
'mac_retention_period': '8',
'mac_violation_timer': '9'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_global.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'allow-multiple-interfaces': 'enable',
'default-virtual-switch-vlan': 'test_value_4',
'https-image-push': 'enable',
'log-mac-limit-violations': 'enable',
'mac-aging-interval': '7',
'mac-retention-period': '8',
'mac-violation-timer': '9'
}
set_method_mock.assert_called_with('switch-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_switch_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',
'switch_controller_global': {
'allow_multiple_interfaces': 'enable',
'default_virtual_switch_vlan': 'test_value_4',
'https_image_push': 'enable',
'log_mac_limit_violations': 'enable',
'mac_aging_interval': '7',
'mac_retention_period': '8',
'mac_violation_timer': '9'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_global.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'allow-multiple-interfaces': 'enable',
'default-virtual-switch-vlan': 'test_value_4',
'https-image-push': 'enable',
'log-mac-limit-violations': 'enable',
'mac-aging-interval': '7',
'mac-retention-period': '8',
'mac-violation-timer': '9'
}
set_method_mock.assert_called_with('switch-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_switch_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',
'switch_controller_global': {
'random_attribute_not_valid': 'tag',
'allow_multiple_interfaces': 'enable',
'default_virtual_switch_vlan': 'test_value_4',
'https_image_push': 'enable',
'log_mac_limit_violations': 'enable',
'mac_aging_interval': '7',
'mac_retention_period': '8',
'mac_violation_timer': '9'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_global.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'allow-multiple-interfaces': 'enable',
'default-virtual-switch-vlan': 'test_value_4',
'https-image-push': 'enable',
'log-mac-limit-violations': 'enable',
'mac-aging-interval': '7',
'mac-retention-period': '8',
'mac-violation-timer': '9'
}
set_method_mock.assert_called_with('switch-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

@ -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_switch_controller_lldp_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_switch_controller_lldp_profile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_switch_controller_lldp_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',
'switch_controller_lldp_profile': {
'802.1_tlvs': 'port-vlan-id',
'802.3_tlvs': 'max-frame-size',
'auto_isl': 'disable',
'auto_isl_hello_timer': '6',
'auto_isl_port_group': '7',
'auto_isl_receive_timeout': '8',
'med_tlvs': 'inventory-management',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_profile.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'802.1-tlvs': 'port-vlan-id',
'802.3-tlvs': 'max-frame-size',
'auto-isl': 'disable',
'auto-isl-hello-timer': '6',
'auto-isl-port-group': '7',
'auto-isl-receive-timeout': '8',
'med-tlvs': 'inventory-management',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-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_switch_controller_lldp_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',
'switch_controller_lldp_profile': {
'802.1_tlvs': 'port-vlan-id',
'802.3_tlvs': 'max-frame-size',
'auto_isl': 'disable',
'auto_isl_hello_timer': '6',
'auto_isl_port_group': '7',
'auto_isl_receive_timeout': '8',
'med_tlvs': 'inventory-management',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_profile.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'802.1-tlvs': 'port-vlan-id',
'802.3-tlvs': 'max-frame-size',
'auto-isl': 'disable',
'auto-isl-hello-timer': '6',
'auto-isl-port-group': '7',
'auto-isl-receive-timeout': '8',
'med-tlvs': 'inventory-management',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-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_switch_controller_lldp_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',
'switch_controller_lldp_profile': {
'802.1_tlvs': 'port-vlan-id',
'802.3_tlvs': 'max-frame-size',
'auto_isl': 'disable',
'auto_isl_hello_timer': '6',
'auto_isl_port_group': '7',
'auto_isl_receive_timeout': '8',
'med_tlvs': 'inventory-management',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_profile.fortios_switch_controller(input_data, fos_instance)
delete_method_mock.assert_called_with('switch-controller', 'lldp-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_switch_controller_lldp_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',
'switch_controller_lldp_profile': {
'802.1_tlvs': 'port-vlan-id',
'802.3_tlvs': 'max-frame-size',
'auto_isl': 'disable',
'auto_isl_hello_timer': '6',
'auto_isl_port_group': '7',
'auto_isl_receive_timeout': '8',
'med_tlvs': 'inventory-management',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_profile.fortios_switch_controller(input_data, fos_instance)
delete_method_mock.assert_called_with('switch-controller', 'lldp-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_switch_controller_lldp_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',
'switch_controller_lldp_profile': {
'802.1_tlvs': 'port-vlan-id',
'802.3_tlvs': 'max-frame-size',
'auto_isl': 'disable',
'auto_isl_hello_timer': '6',
'auto_isl_port_group': '7',
'auto_isl_receive_timeout': '8',
'med_tlvs': 'inventory-management',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_profile.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'802.1-tlvs': 'port-vlan-id',
'802.3-tlvs': 'max-frame-size',
'auto-isl': 'disable',
'auto-isl-hello-timer': '6',
'auto-isl-port-group': '7',
'auto-isl-receive-timeout': '8',
'med-tlvs': 'inventory-management',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-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_switch_controller_lldp_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',
'switch_controller_lldp_profile': {
'random_attribute_not_valid': 'tag',
'802.1_tlvs': 'port-vlan-id',
'802.3_tlvs': 'max-frame-size',
'auto_isl': 'disable',
'auto_isl_hello_timer': '6',
'auto_isl_port_group': '7',
'auto_isl_receive_timeout': '8',
'med_tlvs': 'inventory-management',
'name': 'default_name_10'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_profile.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'802.1-tlvs': 'port-vlan-id',
'802.3-tlvs': 'max-frame-size',
'auto-isl': 'disable',
'auto-isl-hello-timer': '6',
'auto-isl-port-group': '7',
'auto-isl-receive-timeout': '8',
'med-tlvs': 'inventory-management',
'name': 'default_name_10'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-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

@ -0,0 +1,183 @@
# 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_switch_controller_lldp_settings
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_switch_controller_lldp_settings.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_switch_controller_lldp_settings_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',
'switch_controller_lldp_settings': {
'fast_start_interval': '3',
'management_interface': 'internal',
'status': 'enable',
'tx_hold': '6',
'tx_interval': '7'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'fast-start-interval': '3',
'management-interface': 'internal',
'status': 'enable',
'tx-hold': '6',
'tx-interval': '7'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-settings', 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_switch_controller_lldp_settings_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',
'switch_controller_lldp_settings': {
'fast_start_interval': '3',
'management_interface': 'internal',
'status': 'enable',
'tx_hold': '6',
'tx_interval': '7'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'fast-start-interval': '3',
'management-interface': 'internal',
'status': 'enable',
'tx-hold': '6',
'tx-interval': '7'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-settings', 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_switch_controller_lldp_settings_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',
'switch_controller_lldp_settings': {
'fast_start_interval': '3',
'management_interface': 'internal',
'status': 'enable',
'tx_hold': '6',
'tx_interval': '7'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'fast-start-interval': '3',
'management-interface': 'internal',
'status': 'enable',
'tx-hold': '6',
'tx-interval': '7'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-settings', 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_switch_controller_lldp_settings_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',
'switch_controller_lldp_settings': {
'random_attribute_not_valid': 'tag',
'fast_start_interval': '3',
'management_interface': 'internal',
'status': 'enable',
'tx_hold': '6',
'tx_interval': '7'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_lldp_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'fast-start-interval': '3',
'management-interface': 'internal',
'status': 'enable',
'tx-hold': '6',
'tx-interval': '7'
}
set_method_mock.assert_called_with('switch-controller', 'lldp-settings', 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

@ -0,0 +1,151 @@
# 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_switch_controller_mac_sync_settings
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_switch_controller_mac_sync_settings.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_switch_controller_mac_sync_settings_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',
'switch_controller_mac_sync_settings': {
'mac_sync_interval': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_mac_sync_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'mac-sync-interval': '3'
}
set_method_mock.assert_called_with('switch-controller', 'mac-sync-settings', 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_switch_controller_mac_sync_settings_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',
'switch_controller_mac_sync_settings': {
'mac_sync_interval': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_mac_sync_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'mac-sync-interval': '3'
}
set_method_mock.assert_called_with('switch-controller', 'mac-sync-settings', 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_switch_controller_mac_sync_settings_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',
'switch_controller_mac_sync_settings': {
'mac_sync_interval': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_mac_sync_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'mac-sync-interval': '3'
}
set_method_mock.assert_called_with('switch-controller', 'mac-sync-settings', 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_switch_controller_mac_sync_settings_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',
'switch_controller_mac_sync_settings': {
'random_attribute_not_valid': 'tag',
'mac_sync_interval': '3'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_mac_sync_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'mac-sync-interval': '3'
}
set_method_mock.assert_called_with('switch-controller', 'mac-sync-settings', 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

@ -0,0 +1,389 @@
# 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_switch_controller_managed_switch
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_switch_controller_managed_switch.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_switch_controller_managed_switch_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',
'switch_controller_managed_switch': {'delayed_restart_trigger': '3',
'description': 'test_value_4',
'directly_connected': '5',
'dynamic_capability': '6',
'dynamically_discovered': '7',
'fsw_wan1_admin': 'discovered',
'fsw_wan1_peer': 'test_value_9',
'fsw_wan2_admin': 'discovered',
'fsw_wan2_peer': 'test_value_11',
'max_allowed_trunk_members': '12',
'name': 'default_name_13',
'owner_vdom': 'test_value_14',
'poe_detection_type': '15',
'poe_pre_standard_detection': 'enable',
'pre_provisioned': '17',
'staged_image_version': 'test_value_18',
'switch_device_tag': 'test_value_19',
'switch_id': 'test_value_20',
'switch_profile': 'test_value_21',
'type': 'virtual',
'version': '23'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_managed_switch.fortios_switch_controller(input_data, fos_instance)
expected_data = {'delayed-restart-trigger': '3',
'description': 'test_value_4',
'directly-connected': '5',
'dynamic-capability': '6',
'dynamically-discovered': '7',
'fsw-wan1-admin': 'discovered',
'fsw-wan1-peer': 'test_value_9',
'fsw-wan2-admin': 'discovered',
'fsw-wan2-peer': 'test_value_11',
'max-allowed-trunk-members': '12',
'name': 'default_name_13',
'owner-vdom': 'test_value_14',
'poe-detection-type': '15',
'poe-pre-standard-detection': 'enable',
'pre-provisioned': '17',
'staged-image-version': 'test_value_18',
'switch-device-tag': 'test_value_19',
'switch-id': 'test_value_20',
'switch-profile': 'test_value_21',
'type': 'virtual',
'version': '23'
}
set_method_mock.assert_called_with('switch-controller', 'managed-switch', 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_switch_controller_managed_switch_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',
'switch_controller_managed_switch': {'delayed_restart_trigger': '3',
'description': 'test_value_4',
'directly_connected': '5',
'dynamic_capability': '6',
'dynamically_discovered': '7',
'fsw_wan1_admin': 'discovered',
'fsw_wan1_peer': 'test_value_9',
'fsw_wan2_admin': 'discovered',
'fsw_wan2_peer': 'test_value_11',
'max_allowed_trunk_members': '12',
'name': 'default_name_13',
'owner_vdom': 'test_value_14',
'poe_detection_type': '15',
'poe_pre_standard_detection': 'enable',
'pre_provisioned': '17',
'staged_image_version': 'test_value_18',
'switch_device_tag': 'test_value_19',
'switch_id': 'test_value_20',
'switch_profile': 'test_value_21',
'type': 'virtual',
'version': '23'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_managed_switch.fortios_switch_controller(input_data, fos_instance)
expected_data = {'delayed-restart-trigger': '3',
'description': 'test_value_4',
'directly-connected': '5',
'dynamic-capability': '6',
'dynamically-discovered': '7',
'fsw-wan1-admin': 'discovered',
'fsw-wan1-peer': 'test_value_9',
'fsw-wan2-admin': 'discovered',
'fsw-wan2-peer': 'test_value_11',
'max-allowed-trunk-members': '12',
'name': 'default_name_13',
'owner-vdom': 'test_value_14',
'poe-detection-type': '15',
'poe-pre-standard-detection': 'enable',
'pre-provisioned': '17',
'staged-image-version': 'test_value_18',
'switch-device-tag': 'test_value_19',
'switch-id': 'test_value_20',
'switch-profile': 'test_value_21',
'type': 'virtual',
'version': '23'
}
set_method_mock.assert_called_with('switch-controller', 'managed-switch', 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_switch_controller_managed_switch_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',
'switch_controller_managed_switch': {'delayed_restart_trigger': '3',
'description': 'test_value_4',
'directly_connected': '5',
'dynamic_capability': '6',
'dynamically_discovered': '7',
'fsw_wan1_admin': 'discovered',
'fsw_wan1_peer': 'test_value_9',
'fsw_wan2_admin': 'discovered',
'fsw_wan2_peer': 'test_value_11',
'max_allowed_trunk_members': '12',
'name': 'default_name_13',
'owner_vdom': 'test_value_14',
'poe_detection_type': '15',
'poe_pre_standard_detection': 'enable',
'pre_provisioned': '17',
'staged_image_version': 'test_value_18',
'switch_device_tag': 'test_value_19',
'switch_id': 'test_value_20',
'switch_profile': 'test_value_21',
'type': 'virtual',
'version': '23'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_managed_switch.fortios_switch_controller(input_data, fos_instance)
delete_method_mock.assert_called_with('switch-controller', 'managed-switch', 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_switch_controller_managed_switch_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',
'switch_controller_managed_switch': {'delayed_restart_trigger': '3',
'description': 'test_value_4',
'directly_connected': '5',
'dynamic_capability': '6',
'dynamically_discovered': '7',
'fsw_wan1_admin': 'discovered',
'fsw_wan1_peer': 'test_value_9',
'fsw_wan2_admin': 'discovered',
'fsw_wan2_peer': 'test_value_11',
'max_allowed_trunk_members': '12',
'name': 'default_name_13',
'owner_vdom': 'test_value_14',
'poe_detection_type': '15',
'poe_pre_standard_detection': 'enable',
'pre_provisioned': '17',
'staged_image_version': 'test_value_18',
'switch_device_tag': 'test_value_19',
'switch_id': 'test_value_20',
'switch_profile': 'test_value_21',
'type': 'virtual',
'version': '23'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_managed_switch.fortios_switch_controller(input_data, fos_instance)
delete_method_mock.assert_called_with('switch-controller', 'managed-switch', 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_switch_controller_managed_switch_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',
'switch_controller_managed_switch': {'delayed_restart_trigger': '3',
'description': 'test_value_4',
'directly_connected': '5',
'dynamic_capability': '6',
'dynamically_discovered': '7',
'fsw_wan1_admin': 'discovered',
'fsw_wan1_peer': 'test_value_9',
'fsw_wan2_admin': 'discovered',
'fsw_wan2_peer': 'test_value_11',
'max_allowed_trunk_members': '12',
'name': 'default_name_13',
'owner_vdom': 'test_value_14',
'poe_detection_type': '15',
'poe_pre_standard_detection': 'enable',
'pre_provisioned': '17',
'staged_image_version': 'test_value_18',
'switch_device_tag': 'test_value_19',
'switch_id': 'test_value_20',
'switch_profile': 'test_value_21',
'type': 'virtual',
'version': '23'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_managed_switch.fortios_switch_controller(input_data, fos_instance)
expected_data = {'delayed-restart-trigger': '3',
'description': 'test_value_4',
'directly-connected': '5',
'dynamic-capability': '6',
'dynamically-discovered': '7',
'fsw-wan1-admin': 'discovered',
'fsw-wan1-peer': 'test_value_9',
'fsw-wan2-admin': 'discovered',
'fsw-wan2-peer': 'test_value_11',
'max-allowed-trunk-members': '12',
'name': 'default_name_13',
'owner-vdom': 'test_value_14',
'poe-detection-type': '15',
'poe-pre-standard-detection': 'enable',
'pre-provisioned': '17',
'staged-image-version': 'test_value_18',
'switch-device-tag': 'test_value_19',
'switch-id': 'test_value_20',
'switch-profile': 'test_value_21',
'type': 'virtual',
'version': '23'
}
set_method_mock.assert_called_with('switch-controller', 'managed-switch', 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_switch_controller_managed_switch_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',
'switch_controller_managed_switch': {
'random_attribute_not_valid': 'tag', 'delayed_restart_trigger': '3',
'description': 'test_value_4',
'directly_connected': '5',
'dynamic_capability': '6',
'dynamically_discovered': '7',
'fsw_wan1_admin': 'discovered',
'fsw_wan1_peer': 'test_value_9',
'fsw_wan2_admin': 'discovered',
'fsw_wan2_peer': 'test_value_11',
'max_allowed_trunk_members': '12',
'name': 'default_name_13',
'owner_vdom': 'test_value_14',
'poe_detection_type': '15',
'poe_pre_standard_detection': 'enable',
'pre_provisioned': '17',
'staged_image_version': 'test_value_18',
'switch_device_tag': 'test_value_19',
'switch_id': 'test_value_20',
'switch_profile': 'test_value_21',
'type': 'virtual',
'version': '23'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_managed_switch.fortios_switch_controller(input_data, fos_instance)
expected_data = {'delayed-restart-trigger': '3',
'description': 'test_value_4',
'directly-connected': '5',
'dynamic-capability': '6',
'dynamically-discovered': '7',
'fsw-wan1-admin': 'discovered',
'fsw-wan1-peer': 'test_value_9',
'fsw-wan2-admin': 'discovered',
'fsw-wan2-peer': 'test_value_11',
'max-allowed-trunk-members': '12',
'name': 'default_name_13',
'owner-vdom': 'test_value_14',
'poe-detection-type': '15',
'poe-pre-standard-detection': 'enable',
'pre-provisioned': '17',
'staged-image-version': 'test_value_18',
'switch-device-tag': 'test_value_19',
'switch-id': 'test_value_20',
'switch-profile': 'test_value_21',
'type': 'virtual',
'version': '23'
}
set_method_mock.assert_called_with('switch-controller', 'managed-switch', 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

@ -0,0 +1,151 @@
# 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_switch_controller_network_monitor_settings
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_switch_controller_network_monitor_settings.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_switch_controller_network_monitor_settings_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',
'switch_controller_network_monitor_settings': {
'network_monitoring': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_network_monitor_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'network-monitoring': 'enable'
}
set_method_mock.assert_called_with('switch-controller', 'network-monitor-settings', 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_switch_controller_network_monitor_settings_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',
'switch_controller_network_monitor_settings': {
'network_monitoring': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_network_monitor_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'network-monitoring': 'enable'
}
set_method_mock.assert_called_with('switch-controller', 'network-monitor-settings', 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_switch_controller_network_monitor_settings_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',
'switch_controller_network_monitor_settings': {
'network_monitoring': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_network_monitor_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'network-monitoring': 'enable'
}
set_method_mock.assert_called_with('switch-controller', 'network-monitor-settings', 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_switch_controller_network_monitor_settings_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',
'switch_controller_network_monitor_settings': {
'random_attribute_not_valid': 'tag',
'network_monitoring': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_switch_controller_network_monitor_settings.fortios_switch_controller(input_data, fos_instance)
expected_data = {
'network-monitoring': 'enable'
}
set_method_mock.assert_called_with('switch-controller', 'network-monitor-settings', 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

@ -0,0 +1,349 @@
# 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_system_accprofile
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_system_accprofile.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_accprofile_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',
'system_accprofile': {
'admintimeout': '3',
'admintimeout_override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_accprofile.fortios_system(input_data, fos_instance)
expected_data = {
'admintimeout': '3',
'admintimeout-override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
}
set_method_mock.assert_called_with('system', 'accprofile', 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_system_accprofile_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',
'system_accprofile': {
'admintimeout': '3',
'admintimeout_override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_accprofile.fortios_system(input_data, fos_instance)
expected_data = {
'admintimeout': '3',
'admintimeout-override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
}
set_method_mock.assert_called_with('system', 'accprofile', 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_system_accprofile_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',
'system_accprofile': {
'admintimeout': '3',
'admintimeout_override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_accprofile.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'accprofile', 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_system_accprofile_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',
'system_accprofile': {
'admintimeout': '3',
'admintimeout_override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_accprofile.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'accprofile', 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_system_accprofile_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',
'system_accprofile': {
'admintimeout': '3',
'admintimeout_override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_accprofile.fortios_system(input_data, fos_instance)
expected_data = {
'admintimeout': '3',
'admintimeout-override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
}
set_method_mock.assert_called_with('system', 'accprofile', 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_system_accprofile_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',
'system_accprofile': {
'random_attribute_not_valid': 'tag',
'admintimeout': '3',
'admintimeout_override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_accprofile.fortios_system(input_data, fos_instance)
expected_data = {
'admintimeout': '3',
'admintimeout-override': 'enable',
'authgrp': 'none',
'comments': 'test_value_6',
'ftviewgrp': 'none',
'fwgrp': 'none',
'loggrp': 'none',
'name': 'default_name_10',
'netgrp': 'none',
'scope': 'vdom',
'secfabgrp': 'none',
'sysgrp': 'none',
'utmgrp': 'none',
'vpngrp': 'none',
'wanoptgrp': 'none',
'wifi': 'none'
}
set_method_mock.assert_called_with('system', 'accprofile', 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

@ -0,0 +1,689 @@
# 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_system_admin
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_system_admin.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_admin_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',
'system_admin': {
'accprofile': 'test_value_3',
'accprofile_override': 'enable',
'allow_remove_admin_session': 'enable',
'comments': 'test_value_6',
'email_to': 'test_value_7',
'force_password_change': 'enable',
'fortitoken': 'test_value_9',
'guest_auth': 'disable',
'guest_lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6_trusthost1': 'test_value_15',
'ip6_trusthost10': 'test_value_16',
'ip6_trusthost2': 'test_value_17',
'ip6_trusthost3': 'test_value_18',
'ip6_trusthost4': 'test_value_19',
'ip6_trusthost5': 'test_value_20',
'ip6_trusthost6': 'test_value_21',
'ip6_trusthost7': 'test_value_22',
'ip6_trusthost8': 'test_value_23',
'ip6_trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password_expire': 'test_value_27',
'peer_auth': 'enable',
'peer_group': 'test_value_29',
'radius_vdom_override': 'enable',
'remote_auth': 'enable',
'remote_group': 'test_value_32',
'schedule': 'test_value_33',
'sms_custom_server': 'test_value_34',
'sms_phone': 'test_value_35',
'sms_server': 'fortiguard',
'ssh_certificate': 'test_value_37',
'ssh_public_key1': 'test_value_38',
'ssh_public_key2': 'test_value_39',
'ssh_public_key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two_factor': 'disable',
'wildcard': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_admin.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'accprofile-override': 'enable',
'allow-remove-admin-session': 'enable',
'comments': 'test_value_6',
'email-to': 'test_value_7',
'force-password-change': 'enable',
'fortitoken': 'test_value_9',
'guest-auth': 'disable',
'guest-lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6-trusthost1': 'test_value_15',
'ip6-trusthost10': 'test_value_16',
'ip6-trusthost2': 'test_value_17',
'ip6-trusthost3': 'test_value_18',
'ip6-trusthost4': 'test_value_19',
'ip6-trusthost5': 'test_value_20',
'ip6-trusthost6': 'test_value_21',
'ip6-trusthost7': 'test_value_22',
'ip6-trusthost8': 'test_value_23',
'ip6-trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password-expire': 'test_value_27',
'peer-auth': 'enable',
'peer-group': 'test_value_29',
'radius-vdom-override': 'enable',
'remote-auth': 'enable',
'remote-group': 'test_value_32',
'schedule': 'test_value_33',
'sms-custom-server': 'test_value_34',
'sms-phone': 'test_value_35',
'sms-server': 'fortiguard',
'ssh-certificate': 'test_value_37',
'ssh-public-key1': 'test_value_38',
'ssh-public-key2': 'test_value_39',
'ssh-public-key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two-factor': 'disable',
'wildcard': 'enable'
}
set_method_mock.assert_called_with('system', 'admin', 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_system_admin_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',
'system_admin': {
'accprofile': 'test_value_3',
'accprofile_override': 'enable',
'allow_remove_admin_session': 'enable',
'comments': 'test_value_6',
'email_to': 'test_value_7',
'force_password_change': 'enable',
'fortitoken': 'test_value_9',
'guest_auth': 'disable',
'guest_lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6_trusthost1': 'test_value_15',
'ip6_trusthost10': 'test_value_16',
'ip6_trusthost2': 'test_value_17',
'ip6_trusthost3': 'test_value_18',
'ip6_trusthost4': 'test_value_19',
'ip6_trusthost5': 'test_value_20',
'ip6_trusthost6': 'test_value_21',
'ip6_trusthost7': 'test_value_22',
'ip6_trusthost8': 'test_value_23',
'ip6_trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password_expire': 'test_value_27',
'peer_auth': 'enable',
'peer_group': 'test_value_29',
'radius_vdom_override': 'enable',
'remote_auth': 'enable',
'remote_group': 'test_value_32',
'schedule': 'test_value_33',
'sms_custom_server': 'test_value_34',
'sms_phone': 'test_value_35',
'sms_server': 'fortiguard',
'ssh_certificate': 'test_value_37',
'ssh_public_key1': 'test_value_38',
'ssh_public_key2': 'test_value_39',
'ssh_public_key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two_factor': 'disable',
'wildcard': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_admin.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'accprofile-override': 'enable',
'allow-remove-admin-session': 'enable',
'comments': 'test_value_6',
'email-to': 'test_value_7',
'force-password-change': 'enable',
'fortitoken': 'test_value_9',
'guest-auth': 'disable',
'guest-lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6-trusthost1': 'test_value_15',
'ip6-trusthost10': 'test_value_16',
'ip6-trusthost2': 'test_value_17',
'ip6-trusthost3': 'test_value_18',
'ip6-trusthost4': 'test_value_19',
'ip6-trusthost5': 'test_value_20',
'ip6-trusthost6': 'test_value_21',
'ip6-trusthost7': 'test_value_22',
'ip6-trusthost8': 'test_value_23',
'ip6-trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password-expire': 'test_value_27',
'peer-auth': 'enable',
'peer-group': 'test_value_29',
'radius-vdom-override': 'enable',
'remote-auth': 'enable',
'remote-group': 'test_value_32',
'schedule': 'test_value_33',
'sms-custom-server': 'test_value_34',
'sms-phone': 'test_value_35',
'sms-server': 'fortiguard',
'ssh-certificate': 'test_value_37',
'ssh-public-key1': 'test_value_38',
'ssh-public-key2': 'test_value_39',
'ssh-public-key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two-factor': 'disable',
'wildcard': 'enable'
}
set_method_mock.assert_called_with('system', 'admin', 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_system_admin_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',
'system_admin': {
'accprofile': 'test_value_3',
'accprofile_override': 'enable',
'allow_remove_admin_session': 'enable',
'comments': 'test_value_6',
'email_to': 'test_value_7',
'force_password_change': 'enable',
'fortitoken': 'test_value_9',
'guest_auth': 'disable',
'guest_lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6_trusthost1': 'test_value_15',
'ip6_trusthost10': 'test_value_16',
'ip6_trusthost2': 'test_value_17',
'ip6_trusthost3': 'test_value_18',
'ip6_trusthost4': 'test_value_19',
'ip6_trusthost5': 'test_value_20',
'ip6_trusthost6': 'test_value_21',
'ip6_trusthost7': 'test_value_22',
'ip6_trusthost8': 'test_value_23',
'ip6_trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password_expire': 'test_value_27',
'peer_auth': 'enable',
'peer_group': 'test_value_29',
'radius_vdom_override': 'enable',
'remote_auth': 'enable',
'remote_group': 'test_value_32',
'schedule': 'test_value_33',
'sms_custom_server': 'test_value_34',
'sms_phone': 'test_value_35',
'sms_server': 'fortiguard',
'ssh_certificate': 'test_value_37',
'ssh_public_key1': 'test_value_38',
'ssh_public_key2': 'test_value_39',
'ssh_public_key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two_factor': 'disable',
'wildcard': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_admin.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'admin', 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_system_admin_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',
'system_admin': {
'accprofile': 'test_value_3',
'accprofile_override': 'enable',
'allow_remove_admin_session': 'enable',
'comments': 'test_value_6',
'email_to': 'test_value_7',
'force_password_change': 'enable',
'fortitoken': 'test_value_9',
'guest_auth': 'disable',
'guest_lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6_trusthost1': 'test_value_15',
'ip6_trusthost10': 'test_value_16',
'ip6_trusthost2': 'test_value_17',
'ip6_trusthost3': 'test_value_18',
'ip6_trusthost4': 'test_value_19',
'ip6_trusthost5': 'test_value_20',
'ip6_trusthost6': 'test_value_21',
'ip6_trusthost7': 'test_value_22',
'ip6_trusthost8': 'test_value_23',
'ip6_trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password_expire': 'test_value_27',
'peer_auth': 'enable',
'peer_group': 'test_value_29',
'radius_vdom_override': 'enable',
'remote_auth': 'enable',
'remote_group': 'test_value_32',
'schedule': 'test_value_33',
'sms_custom_server': 'test_value_34',
'sms_phone': 'test_value_35',
'sms_server': 'fortiguard',
'ssh_certificate': 'test_value_37',
'ssh_public_key1': 'test_value_38',
'ssh_public_key2': 'test_value_39',
'ssh_public_key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two_factor': 'disable',
'wildcard': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_admin.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'admin', 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_system_admin_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',
'system_admin': {
'accprofile': 'test_value_3',
'accprofile_override': 'enable',
'allow_remove_admin_session': 'enable',
'comments': 'test_value_6',
'email_to': 'test_value_7',
'force_password_change': 'enable',
'fortitoken': 'test_value_9',
'guest_auth': 'disable',
'guest_lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6_trusthost1': 'test_value_15',
'ip6_trusthost10': 'test_value_16',
'ip6_trusthost2': 'test_value_17',
'ip6_trusthost3': 'test_value_18',
'ip6_trusthost4': 'test_value_19',
'ip6_trusthost5': 'test_value_20',
'ip6_trusthost6': 'test_value_21',
'ip6_trusthost7': 'test_value_22',
'ip6_trusthost8': 'test_value_23',
'ip6_trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password_expire': 'test_value_27',
'peer_auth': 'enable',
'peer_group': 'test_value_29',
'radius_vdom_override': 'enable',
'remote_auth': 'enable',
'remote_group': 'test_value_32',
'schedule': 'test_value_33',
'sms_custom_server': 'test_value_34',
'sms_phone': 'test_value_35',
'sms_server': 'fortiguard',
'ssh_certificate': 'test_value_37',
'ssh_public_key1': 'test_value_38',
'ssh_public_key2': 'test_value_39',
'ssh_public_key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two_factor': 'disable',
'wildcard': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_admin.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'accprofile-override': 'enable',
'allow-remove-admin-session': 'enable',
'comments': 'test_value_6',
'email-to': 'test_value_7',
'force-password-change': 'enable',
'fortitoken': 'test_value_9',
'guest-auth': 'disable',
'guest-lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6-trusthost1': 'test_value_15',
'ip6-trusthost10': 'test_value_16',
'ip6-trusthost2': 'test_value_17',
'ip6-trusthost3': 'test_value_18',
'ip6-trusthost4': 'test_value_19',
'ip6-trusthost5': 'test_value_20',
'ip6-trusthost6': 'test_value_21',
'ip6-trusthost7': 'test_value_22',
'ip6-trusthost8': 'test_value_23',
'ip6-trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password-expire': 'test_value_27',
'peer-auth': 'enable',
'peer-group': 'test_value_29',
'radius-vdom-override': 'enable',
'remote-auth': 'enable',
'remote-group': 'test_value_32',
'schedule': 'test_value_33',
'sms-custom-server': 'test_value_34',
'sms-phone': 'test_value_35',
'sms-server': 'fortiguard',
'ssh-certificate': 'test_value_37',
'ssh-public-key1': 'test_value_38',
'ssh-public-key2': 'test_value_39',
'ssh-public-key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two-factor': 'disable',
'wildcard': 'enable'
}
set_method_mock.assert_called_with('system', 'admin', 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_system_admin_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',
'system_admin': {
'random_attribute_not_valid': 'tag',
'accprofile': 'test_value_3',
'accprofile_override': 'enable',
'allow_remove_admin_session': 'enable',
'comments': 'test_value_6',
'email_to': 'test_value_7',
'force_password_change': 'enable',
'fortitoken': 'test_value_9',
'guest_auth': 'disable',
'guest_lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6_trusthost1': 'test_value_15',
'ip6_trusthost10': 'test_value_16',
'ip6_trusthost2': 'test_value_17',
'ip6_trusthost3': 'test_value_18',
'ip6_trusthost4': 'test_value_19',
'ip6_trusthost5': 'test_value_20',
'ip6_trusthost6': 'test_value_21',
'ip6_trusthost7': 'test_value_22',
'ip6_trusthost8': 'test_value_23',
'ip6_trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password_expire': 'test_value_27',
'peer_auth': 'enable',
'peer_group': 'test_value_29',
'radius_vdom_override': 'enable',
'remote_auth': 'enable',
'remote_group': 'test_value_32',
'schedule': 'test_value_33',
'sms_custom_server': 'test_value_34',
'sms_phone': 'test_value_35',
'sms_server': 'fortiguard',
'ssh_certificate': 'test_value_37',
'ssh_public_key1': 'test_value_38',
'ssh_public_key2': 'test_value_39',
'ssh_public_key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two_factor': 'disable',
'wildcard': 'enable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_admin.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'accprofile-override': 'enable',
'allow-remove-admin-session': 'enable',
'comments': 'test_value_6',
'email-to': 'test_value_7',
'force-password-change': 'enable',
'fortitoken': 'test_value_9',
'guest-auth': 'disable',
'guest-lang': 'test_value_11',
'hidden': '12',
'history0': 'test_value_13',
'history1': 'test_value_14',
'ip6-trusthost1': 'test_value_15',
'ip6-trusthost10': 'test_value_16',
'ip6-trusthost2': 'test_value_17',
'ip6-trusthost3': 'test_value_18',
'ip6-trusthost4': 'test_value_19',
'ip6-trusthost5': 'test_value_20',
'ip6-trusthost6': 'test_value_21',
'ip6-trusthost7': 'test_value_22',
'ip6-trusthost8': 'test_value_23',
'ip6-trusthost9': 'test_value_24',
'name': 'default_name_25',
'password': 'test_value_26',
'password-expire': 'test_value_27',
'peer-auth': 'enable',
'peer-group': 'test_value_29',
'radius-vdom-override': 'enable',
'remote-auth': 'enable',
'remote-group': 'test_value_32',
'schedule': 'test_value_33',
'sms-custom-server': 'test_value_34',
'sms-phone': 'test_value_35',
'sms-server': 'fortiguard',
'ssh-certificate': 'test_value_37',
'ssh-public-key1': 'test_value_38',
'ssh-public-key2': 'test_value_39',
'ssh-public-key3': 'test_value_40',
'trusthost1': 'test_value_41',
'trusthost10': 'test_value_42',
'trusthost2': 'test_value_43',
'trusthost3': 'test_value_44',
'trusthost4': 'test_value_45',
'trusthost5': 'test_value_46',
'trusthost6': 'test_value_47',
'trusthost7': 'test_value_48',
'trusthost8': 'test_value_49',
'trusthost9': 'test_value_50',
'two-factor': 'disable',
'wildcard': 'enable'
}
set_method_mock.assert_called_with('system', 'admin', 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

@ -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_system_api_user
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_system_api_user.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_api_user_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',
'system_api_user': {
'accprofile': 'test_value_3',
'api_key': 'test_value_4',
'comments': 'test_value_5',
'cors_allow_origin': 'test_value_6',
'name': 'default_name_7',
'peer_auth': 'enable',
'peer_group': 'test_value_9',
'schedule': 'test_value_10',
},
'vdom': 'root'}
is_error, changed, response = fortios_system_api_user.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'api-key': 'test_value_4',
'comments': 'test_value_5',
'cors-allow-origin': 'test_value_6',
'name': 'default_name_7',
'peer-auth': 'enable',
'peer-group': 'test_value_9',
'schedule': 'test_value_10',
}
set_method_mock.assert_called_with('system', 'api-user', 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_system_api_user_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',
'system_api_user': {
'accprofile': 'test_value_3',
'api_key': 'test_value_4',
'comments': 'test_value_5',
'cors_allow_origin': 'test_value_6',
'name': 'default_name_7',
'peer_auth': 'enable',
'peer_group': 'test_value_9',
'schedule': 'test_value_10',
},
'vdom': 'root'}
is_error, changed, response = fortios_system_api_user.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'api-key': 'test_value_4',
'comments': 'test_value_5',
'cors-allow-origin': 'test_value_6',
'name': 'default_name_7',
'peer-auth': 'enable',
'peer-group': 'test_value_9',
'schedule': 'test_value_10',
}
set_method_mock.assert_called_with('system', 'api-user', 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_system_api_user_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',
'system_api_user': {
'accprofile': 'test_value_3',
'api_key': 'test_value_4',
'comments': 'test_value_5',
'cors_allow_origin': 'test_value_6',
'name': 'default_name_7',
'peer_auth': 'enable',
'peer_group': 'test_value_9',
'schedule': 'test_value_10',
},
'vdom': 'root'}
is_error, changed, response = fortios_system_api_user.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'api-user', 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_system_api_user_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',
'system_api_user': {
'accprofile': 'test_value_3',
'api_key': 'test_value_4',
'comments': 'test_value_5',
'cors_allow_origin': 'test_value_6',
'name': 'default_name_7',
'peer_auth': 'enable',
'peer_group': 'test_value_9',
'schedule': 'test_value_10',
},
'vdom': 'root'}
is_error, changed, response = fortios_system_api_user.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'api-user', 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_system_api_user_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',
'system_api_user': {
'accprofile': 'test_value_3',
'api_key': 'test_value_4',
'comments': 'test_value_5',
'cors_allow_origin': 'test_value_6',
'name': 'default_name_7',
'peer_auth': 'enable',
'peer_group': 'test_value_9',
'schedule': 'test_value_10',
},
'vdom': 'root'}
is_error, changed, response = fortios_system_api_user.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'api-key': 'test_value_4',
'comments': 'test_value_5',
'cors-allow-origin': 'test_value_6',
'name': 'default_name_7',
'peer-auth': 'enable',
'peer-group': 'test_value_9',
'schedule': 'test_value_10',
}
set_method_mock.assert_called_with('system', 'api-user', 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_system_api_user_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',
'system_api_user': {
'random_attribute_not_valid': 'tag',
'accprofile': 'test_value_3',
'api_key': 'test_value_4',
'comments': 'test_value_5',
'cors_allow_origin': 'test_value_6',
'name': 'default_name_7',
'peer_auth': 'enable',
'peer_group': 'test_value_9',
'schedule': 'test_value_10',
},
'vdom': 'root'}
is_error, changed, response = fortios_system_api_user.fortios_system(input_data, fos_instance)
expected_data = {
'accprofile': 'test_value_3',
'api-key': 'test_value_4',
'comments': 'test_value_5',
'cors-allow-origin': 'test_value_6',
'name': 'default_name_7',
'peer-auth': 'enable',
'peer-group': 'test_value_9',
'schedule': 'test_value_10',
}
set_method_mock.assert_called_with('system', 'api-user', 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

@ -0,0 +1,263 @@
# 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_system_central_management
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_system_central_management.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_central_management_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',
'system_central_management': {
'allow_monitor': 'enable',
'allow_push_configuration': 'enable',
'allow_push_firmware': 'enable',
'allow_remote_firmware_upgrade': 'enable',
'enc_algorithm': 'default',
'fmg': 'test_value_8',
'fmg_source_ip': 'test_value_9',
'fmg_source_ip6': 'test_value_10',
'include_default_servers': 'enable',
'mode': 'normal',
'schedule_config_restore': 'enable',
'schedule_script_restore': 'enable',
'serial_number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_central_management.fortios_system(input_data, fos_instance)
expected_data = {
'allow-monitor': 'enable',
'allow-push-configuration': 'enable',
'allow-push-firmware': 'enable',
'allow-remote-firmware-upgrade': 'enable',
'enc-algorithm': 'default',
'fmg': 'test_value_8',
'fmg-source-ip': 'test_value_9',
'fmg-source-ip6': 'test_value_10',
'include-default-servers': 'enable',
'mode': 'normal',
'schedule-config-restore': 'enable',
'schedule-script-restore': 'enable',
'serial-number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
}
set_method_mock.assert_called_with('system', 'central-management', 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_system_central_management_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',
'system_central_management': {
'allow_monitor': 'enable',
'allow_push_configuration': 'enable',
'allow_push_firmware': 'enable',
'allow_remote_firmware_upgrade': 'enable',
'enc_algorithm': 'default',
'fmg': 'test_value_8',
'fmg_source_ip': 'test_value_9',
'fmg_source_ip6': 'test_value_10',
'include_default_servers': 'enable',
'mode': 'normal',
'schedule_config_restore': 'enable',
'schedule_script_restore': 'enable',
'serial_number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_central_management.fortios_system(input_data, fos_instance)
expected_data = {
'allow-monitor': 'enable',
'allow-push-configuration': 'enable',
'allow-push-firmware': 'enable',
'allow-remote-firmware-upgrade': 'enable',
'enc-algorithm': 'default',
'fmg': 'test_value_8',
'fmg-source-ip': 'test_value_9',
'fmg-source-ip6': 'test_value_10',
'include-default-servers': 'enable',
'mode': 'normal',
'schedule-config-restore': 'enable',
'schedule-script-restore': 'enable',
'serial-number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
}
set_method_mock.assert_called_with('system', 'central-management', 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_system_central_management_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',
'system_central_management': {
'allow_monitor': 'enable',
'allow_push_configuration': 'enable',
'allow_push_firmware': 'enable',
'allow_remote_firmware_upgrade': 'enable',
'enc_algorithm': 'default',
'fmg': 'test_value_8',
'fmg_source_ip': 'test_value_9',
'fmg_source_ip6': 'test_value_10',
'include_default_servers': 'enable',
'mode': 'normal',
'schedule_config_restore': 'enable',
'schedule_script_restore': 'enable',
'serial_number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_central_management.fortios_system(input_data, fos_instance)
expected_data = {
'allow-monitor': 'enable',
'allow-push-configuration': 'enable',
'allow-push-firmware': 'enable',
'allow-remote-firmware-upgrade': 'enable',
'enc-algorithm': 'default',
'fmg': 'test_value_8',
'fmg-source-ip': 'test_value_9',
'fmg-source-ip6': 'test_value_10',
'include-default-servers': 'enable',
'mode': 'normal',
'schedule-config-restore': 'enable',
'schedule-script-restore': 'enable',
'serial-number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
}
set_method_mock.assert_called_with('system', 'central-management', 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_system_central_management_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',
'system_central_management': {
'random_attribute_not_valid': 'tag',
'allow_monitor': 'enable',
'allow_push_configuration': 'enable',
'allow_push_firmware': 'enable',
'allow_remote_firmware_upgrade': 'enable',
'enc_algorithm': 'default',
'fmg': 'test_value_8',
'fmg_source_ip': 'test_value_9',
'fmg_source_ip6': 'test_value_10',
'include_default_servers': 'enable',
'mode': 'normal',
'schedule_config_restore': 'enable',
'schedule_script_restore': 'enable',
'serial_number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_central_management.fortios_system(input_data, fos_instance)
expected_data = {
'allow-monitor': 'enable',
'allow-push-configuration': 'enable',
'allow-push-firmware': 'enable',
'allow-remote-firmware-upgrade': 'enable',
'enc-algorithm': 'default',
'fmg': 'test_value_8',
'fmg-source-ip': 'test_value_9',
'fmg-source-ip6': 'test_value_10',
'include-default-servers': 'enable',
'mode': 'normal',
'schedule-config-restore': 'enable',
'schedule-script-restore': 'enable',
'serial-number': 'test_value_15',
'type': 'fortimanager',
'vdom': 'test_value_17'
}
set_method_mock.assert_called_with('system', 'central-management', 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

@ -0,0 +1,589 @@
# 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_system_dhcp_server
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_system_dhcp_server.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_dhcp_server_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',
'system_dhcp_server': {
'auto_configuration': 'disable',
'conflicted_ip_timeout': '4',
'ddns_auth': 'disable',
'ddns_key': 'test_value_6',
'ddns_keyname': 'test_value_7',
'ddns_server_ip': 'test_value_8',
'ddns_ttl': '9',
'ddns_update': 'disable',
'ddns_update_override': 'disable',
'ddns_zone': 'test_value_12',
'default_gateway': 'test_value_13',
'dns_server1': 'test_value_14',
'dns_server2': 'test_value_15',
'dns_server3': 'test_value_16',
'dns_service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient_on_net_status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip_mode': 'range',
'ipsec_lease_hold': '24',
'lease_time': '25',
'mac_acl_default_action': 'assign',
'netmask': 'test_value_27',
'next_server': 'test_value_28',
'ntp_server1': 'test_value_29',
'ntp_server2': 'test_value_30',
'ntp_server3': 'test_value_31',
'ntp_service': 'local',
'server_type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone_option': 'disable',
'vci_match': 'disable',
'wifi_ac1': 'test_value_38',
'wifi_ac2': 'test_value_39',
'wifi_ac3': 'test_value_40',
'wins_server1': 'test_value_41',
'wins_server2': 'test_value_42'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dhcp_server.fortios_system_dhcp(input_data, fos_instance)
expected_data = {
'auto-configuration': 'disable',
'conflicted-ip-timeout': '4',
'ddns-auth': 'disable',
'ddns-key': 'test_value_6',
'ddns-keyname': 'test_value_7',
'ddns-server-ip': 'test_value_8',
'ddns-ttl': '9',
'ddns-update': 'disable',
'ddns-update-override': 'disable',
'ddns-zone': 'test_value_12',
'default-gateway': 'test_value_13',
'dns-server1': 'test_value_14',
'dns-server2': 'test_value_15',
'dns-server3': 'test_value_16',
'dns-service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient-on-net-status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip-mode': 'range',
'ipsec-lease-hold': '24',
'lease-time': '25',
'mac-acl-default-action': 'assign',
'netmask': 'test_value_27',
'next-server': 'test_value_28',
'ntp-server1': 'test_value_29',
'ntp-server2': 'test_value_30',
'ntp-server3': 'test_value_31',
'ntp-service': 'local',
'server-type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone-option': 'disable',
'vci-match': 'disable',
'wifi-ac1': 'test_value_38',
'wifi-ac2': 'test_value_39',
'wifi-ac3': 'test_value_40',
'wins-server1': 'test_value_41',
'wins-server2': 'test_value_42'
}
set_method_mock.assert_called_with('system.dhcp', 'server', 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_system_dhcp_server_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',
'system_dhcp_server': {
'auto_configuration': 'disable',
'conflicted_ip_timeout': '4',
'ddns_auth': 'disable',
'ddns_key': 'test_value_6',
'ddns_keyname': 'test_value_7',
'ddns_server_ip': 'test_value_8',
'ddns_ttl': '9',
'ddns_update': 'disable',
'ddns_update_override': 'disable',
'ddns_zone': 'test_value_12',
'default_gateway': 'test_value_13',
'dns_server1': 'test_value_14',
'dns_server2': 'test_value_15',
'dns_server3': 'test_value_16',
'dns_service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient_on_net_status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip_mode': 'range',
'ipsec_lease_hold': '24',
'lease_time': '25',
'mac_acl_default_action': 'assign',
'netmask': 'test_value_27',
'next_server': 'test_value_28',
'ntp_server1': 'test_value_29',
'ntp_server2': 'test_value_30',
'ntp_server3': 'test_value_31',
'ntp_service': 'local',
'server_type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone_option': 'disable',
'vci_match': 'disable',
'wifi_ac1': 'test_value_38',
'wifi_ac2': 'test_value_39',
'wifi_ac3': 'test_value_40',
'wins_server1': 'test_value_41',
'wins_server2': 'test_value_42'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dhcp_server.fortios_system_dhcp(input_data, fos_instance)
expected_data = {
'auto-configuration': 'disable',
'conflicted-ip-timeout': '4',
'ddns-auth': 'disable',
'ddns-key': 'test_value_6',
'ddns-keyname': 'test_value_7',
'ddns-server-ip': 'test_value_8',
'ddns-ttl': '9',
'ddns-update': 'disable',
'ddns-update-override': 'disable',
'ddns-zone': 'test_value_12',
'default-gateway': 'test_value_13',
'dns-server1': 'test_value_14',
'dns-server2': 'test_value_15',
'dns-server3': 'test_value_16',
'dns-service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient-on-net-status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip-mode': 'range',
'ipsec-lease-hold': '24',
'lease-time': '25',
'mac-acl-default-action': 'assign',
'netmask': 'test_value_27',
'next-server': 'test_value_28',
'ntp-server1': 'test_value_29',
'ntp-server2': 'test_value_30',
'ntp-server3': 'test_value_31',
'ntp-service': 'local',
'server-type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone-option': 'disable',
'vci-match': 'disable',
'wifi-ac1': 'test_value_38',
'wifi-ac2': 'test_value_39',
'wifi-ac3': 'test_value_40',
'wins-server1': 'test_value_41',
'wins-server2': 'test_value_42'
}
set_method_mock.assert_called_with('system.dhcp', 'server', 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_system_dhcp_server_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',
'system_dhcp_server': {
'auto_configuration': 'disable',
'conflicted_ip_timeout': '4',
'ddns_auth': 'disable',
'ddns_key': 'test_value_6',
'ddns_keyname': 'test_value_7',
'ddns_server_ip': 'test_value_8',
'ddns_ttl': '9',
'ddns_update': 'disable',
'ddns_update_override': 'disable',
'ddns_zone': 'test_value_12',
'default_gateway': 'test_value_13',
'dns_server1': 'test_value_14',
'dns_server2': 'test_value_15',
'dns_server3': 'test_value_16',
'dns_service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient_on_net_status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip_mode': 'range',
'ipsec_lease_hold': '24',
'lease_time': '25',
'mac_acl_default_action': 'assign',
'netmask': 'test_value_27',
'next_server': 'test_value_28',
'ntp_server1': 'test_value_29',
'ntp_server2': 'test_value_30',
'ntp_server3': 'test_value_31',
'ntp_service': 'local',
'server_type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone_option': 'disable',
'vci_match': 'disable',
'wifi_ac1': 'test_value_38',
'wifi_ac2': 'test_value_39',
'wifi_ac3': 'test_value_40',
'wins_server1': 'test_value_41',
'wins_server2': 'test_value_42'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dhcp_server.fortios_system_dhcp(input_data, fos_instance)
delete_method_mock.assert_called_with('system.dhcp', 'server', 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_system_dhcp_server_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',
'system_dhcp_server': {
'auto_configuration': 'disable',
'conflicted_ip_timeout': '4',
'ddns_auth': 'disable',
'ddns_key': 'test_value_6',
'ddns_keyname': 'test_value_7',
'ddns_server_ip': 'test_value_8',
'ddns_ttl': '9',
'ddns_update': 'disable',
'ddns_update_override': 'disable',
'ddns_zone': 'test_value_12',
'default_gateway': 'test_value_13',
'dns_server1': 'test_value_14',
'dns_server2': 'test_value_15',
'dns_server3': 'test_value_16',
'dns_service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient_on_net_status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip_mode': 'range',
'ipsec_lease_hold': '24',
'lease_time': '25',
'mac_acl_default_action': 'assign',
'netmask': 'test_value_27',
'next_server': 'test_value_28',
'ntp_server1': 'test_value_29',
'ntp_server2': 'test_value_30',
'ntp_server3': 'test_value_31',
'ntp_service': 'local',
'server_type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone_option': 'disable',
'vci_match': 'disable',
'wifi_ac1': 'test_value_38',
'wifi_ac2': 'test_value_39',
'wifi_ac3': 'test_value_40',
'wins_server1': 'test_value_41',
'wins_server2': 'test_value_42'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dhcp_server.fortios_system_dhcp(input_data, fos_instance)
delete_method_mock.assert_called_with('system.dhcp', 'server', 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_system_dhcp_server_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',
'system_dhcp_server': {
'auto_configuration': 'disable',
'conflicted_ip_timeout': '4',
'ddns_auth': 'disable',
'ddns_key': 'test_value_6',
'ddns_keyname': 'test_value_7',
'ddns_server_ip': 'test_value_8',
'ddns_ttl': '9',
'ddns_update': 'disable',
'ddns_update_override': 'disable',
'ddns_zone': 'test_value_12',
'default_gateway': 'test_value_13',
'dns_server1': 'test_value_14',
'dns_server2': 'test_value_15',
'dns_server3': 'test_value_16',
'dns_service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient_on_net_status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip_mode': 'range',
'ipsec_lease_hold': '24',
'lease_time': '25',
'mac_acl_default_action': 'assign',
'netmask': 'test_value_27',
'next_server': 'test_value_28',
'ntp_server1': 'test_value_29',
'ntp_server2': 'test_value_30',
'ntp_server3': 'test_value_31',
'ntp_service': 'local',
'server_type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone_option': 'disable',
'vci_match': 'disable',
'wifi_ac1': 'test_value_38',
'wifi_ac2': 'test_value_39',
'wifi_ac3': 'test_value_40',
'wins_server1': 'test_value_41',
'wins_server2': 'test_value_42'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dhcp_server.fortios_system_dhcp(input_data, fos_instance)
expected_data = {
'auto-configuration': 'disable',
'conflicted-ip-timeout': '4',
'ddns-auth': 'disable',
'ddns-key': 'test_value_6',
'ddns-keyname': 'test_value_7',
'ddns-server-ip': 'test_value_8',
'ddns-ttl': '9',
'ddns-update': 'disable',
'ddns-update-override': 'disable',
'ddns-zone': 'test_value_12',
'default-gateway': 'test_value_13',
'dns-server1': 'test_value_14',
'dns-server2': 'test_value_15',
'dns-server3': 'test_value_16',
'dns-service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient-on-net-status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip-mode': 'range',
'ipsec-lease-hold': '24',
'lease-time': '25',
'mac-acl-default-action': 'assign',
'netmask': 'test_value_27',
'next-server': 'test_value_28',
'ntp-server1': 'test_value_29',
'ntp-server2': 'test_value_30',
'ntp-server3': 'test_value_31',
'ntp-service': 'local',
'server-type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone-option': 'disable',
'vci-match': 'disable',
'wifi-ac1': 'test_value_38',
'wifi-ac2': 'test_value_39',
'wifi-ac3': 'test_value_40',
'wins-server1': 'test_value_41',
'wins-server2': 'test_value_42'
}
set_method_mock.assert_called_with('system.dhcp', 'server', 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_system_dhcp_server_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',
'system_dhcp_server': {
'random_attribute_not_valid': 'tag',
'auto_configuration': 'disable',
'conflicted_ip_timeout': '4',
'ddns_auth': 'disable',
'ddns_key': 'test_value_6',
'ddns_keyname': 'test_value_7',
'ddns_server_ip': 'test_value_8',
'ddns_ttl': '9',
'ddns_update': 'disable',
'ddns_update_override': 'disable',
'ddns_zone': 'test_value_12',
'default_gateway': 'test_value_13',
'dns_server1': 'test_value_14',
'dns_server2': 'test_value_15',
'dns_server3': 'test_value_16',
'dns_service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient_on_net_status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip_mode': 'range',
'ipsec_lease_hold': '24',
'lease_time': '25',
'mac_acl_default_action': 'assign',
'netmask': 'test_value_27',
'next_server': 'test_value_28',
'ntp_server1': 'test_value_29',
'ntp_server2': 'test_value_30',
'ntp_server3': 'test_value_31',
'ntp_service': 'local',
'server_type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone_option': 'disable',
'vci_match': 'disable',
'wifi_ac1': 'test_value_38',
'wifi_ac2': 'test_value_39',
'wifi_ac3': 'test_value_40',
'wins_server1': 'test_value_41',
'wins_server2': 'test_value_42'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dhcp_server.fortios_system_dhcp(input_data, fos_instance)
expected_data = {
'auto-configuration': 'disable',
'conflicted-ip-timeout': '4',
'ddns-auth': 'disable',
'ddns-key': 'test_value_6',
'ddns-keyname': 'test_value_7',
'ddns-server-ip': 'test_value_8',
'ddns-ttl': '9',
'ddns-update': 'disable',
'ddns-update-override': 'disable',
'ddns-zone': 'test_value_12',
'default-gateway': 'test_value_13',
'dns-server1': 'test_value_14',
'dns-server2': 'test_value_15',
'dns-server3': 'test_value_16',
'dns-service': 'local',
'domain': 'test_value_18',
'filename': 'test_value_19',
'forticlient-on-net-status': 'disable',
'id': '21',
'interface': 'test_value_22',
'ip-mode': 'range',
'ipsec-lease-hold': '24',
'lease-time': '25',
'mac-acl-default-action': 'assign',
'netmask': 'test_value_27',
'next-server': 'test_value_28',
'ntp-server1': 'test_value_29',
'ntp-server2': 'test_value_30',
'ntp-server3': 'test_value_31',
'ntp-service': 'local',
'server-type': 'regular',
'status': 'disable',
'timezone': '01',
'timezone-option': 'disable',
'vci-match': 'disable',
'wifi-ac1': 'test_value_38',
'wifi-ac2': 'test_value_39',
'wifi-ac3': 'test_value_40',
'wins-server1': 'test_value_41',
'wins-server2': 'test_value_42'
}
set_method_mock.assert_called_with('system.dhcp', 'server', 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

@ -0,0 +1,223 @@
# 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_system_dns
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_system_dns.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_dns_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',
'system_dns': {
'cache_notfound_responses': 'disable',
'dns_cache_limit': '4',
'dns_cache_ttl': '5',
'ip6_primary': 'test_value_6',
'ip6_secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source_ip': '84.230.14.11',
'timeout': '12'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dns.fortios_system(input_data, fos_instance)
expected_data = {
'cache-notfound-responses': 'disable',
'dns-cache-limit': '4',
'dns-cache-ttl': '5',
'ip6-primary': 'test_value_6',
'ip6-secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source-ip': '84.230.14.11',
'timeout': '12'
}
set_method_mock.assert_called_with('system', 'dns', 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_system_dns_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',
'system_dns': {
'cache_notfound_responses': 'disable',
'dns_cache_limit': '4',
'dns_cache_ttl': '5',
'ip6_primary': 'test_value_6',
'ip6_secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source_ip': '84.230.14.11',
'timeout': '12'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dns.fortios_system(input_data, fos_instance)
expected_data = {
'cache-notfound-responses': 'disable',
'dns-cache-limit': '4',
'dns-cache-ttl': '5',
'ip6-primary': 'test_value_6',
'ip6-secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source-ip': '84.230.14.11',
'timeout': '12'
}
set_method_mock.assert_called_with('system', 'dns', 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_system_dns_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',
'system_dns': {
'cache_notfound_responses': 'disable',
'dns_cache_limit': '4',
'dns_cache_ttl': '5',
'ip6_primary': 'test_value_6',
'ip6_secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source_ip': '84.230.14.11',
'timeout': '12'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dns.fortios_system(input_data, fos_instance)
expected_data = {
'cache-notfound-responses': 'disable',
'dns-cache-limit': '4',
'dns-cache-ttl': '5',
'ip6-primary': 'test_value_6',
'ip6-secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source-ip': '84.230.14.11',
'timeout': '12'
}
set_method_mock.assert_called_with('system', 'dns', 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_system_dns_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',
'system_dns': {
'random_attribute_not_valid': 'tag',
'cache_notfound_responses': 'disable',
'dns_cache_limit': '4',
'dns_cache_ttl': '5',
'ip6_primary': 'test_value_6',
'ip6_secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source_ip': '84.230.14.11',
'timeout': '12'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_dns.fortios_system(input_data, fos_instance)
expected_data = {
'cache-notfound-responses': 'disable',
'dns-cache-limit': '4',
'dns-cache-ttl': '5',
'ip6-primary': 'test_value_6',
'ip6-secondary': 'test_value_7',
'primary': 'test_value_8',
'retry': '9',
'secondary': 'test_value_10',
'source-ip': '84.230.14.11',
'timeout': '12'
}
set_method_mock.assert_called_with('system', 'dns', 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

@ -0,0 +1,489 @@
# 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_system_sdn_connector
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_system_sdn_connector.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_sdn_connector_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',
'system_sdn_connector': {
'access_key': 'test_value_3',
'azure_region': 'global',
'client_id': 'test_value_5',
'client_secret': 'test_value_6',
'compartment_id': 'test_value_7',
'gcp_project': 'test_value_8',
'key_passwd': 'test_value_9',
'login_endpoint': 'test_value_10',
'name': 'default_name_11',
'oci_cert': 'test_value_12',
'oci_fingerprint': 'test_value_13',
'oci_region': 'phoenix',
'password': 'test_value_15',
'private_key': 'test_value_16',
'region': 'test_value_17',
'resource_group': 'test_value_18',
'resource_url': 'test_value_19',
'secret_key': 'test_value_20',
'server': '192.168.100.21',
'server_port': '22',
'service_account': 'test_value_23',
'status': 'disable',
'subscription_id': 'test_value_25',
'tenant_id': 'test_value_26',
'type': 'aci',
'update_interval': '28',
'use_metadata_iam': 'disable',
'user_id': 'test_value_30',
'username': 'test_value_31',
'vpc_id': 'test_value_32'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_sdn_connector.fortios_system(input_data, fos_instance)
expected_data = {
'access-key': 'test_value_3',
'azure-region': 'global',
'client-id': 'test_value_5',
'client-secret': 'test_value_6',
'compartment-id': 'test_value_7',
'gcp-project': 'test_value_8',
'key-passwd': 'test_value_9',
'login-endpoint': 'test_value_10',
'name': 'default_name_11',
'oci-cert': 'test_value_12',
'oci-fingerprint': 'test_value_13',
'oci-region': 'phoenix',
'password': 'test_value_15',
'private-key': 'test_value_16',
'region': 'test_value_17',
'resource-group': 'test_value_18',
'resource-url': 'test_value_19',
'secret-key': 'test_value_20',
'server': '192.168.100.21',
'server-port': '22',
'service-account': 'test_value_23',
'status': 'disable',
'subscription-id': 'test_value_25',
'tenant-id': 'test_value_26',
'type': 'aci',
'update-interval': '28',
'use-metadata-iam': 'disable',
'user-id': 'test_value_30',
'username': 'test_value_31',
'vpc-id': 'test_value_32'
}
set_method_mock.assert_called_with('system', 'sdn-connector', 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_system_sdn_connector_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',
'system_sdn_connector': {
'access_key': 'test_value_3',
'azure_region': 'global',
'client_id': 'test_value_5',
'client_secret': 'test_value_6',
'compartment_id': 'test_value_7',
'gcp_project': 'test_value_8',
'key_passwd': 'test_value_9',
'login_endpoint': 'test_value_10',
'name': 'default_name_11',
'oci_cert': 'test_value_12',
'oci_fingerprint': 'test_value_13',
'oci_region': 'phoenix',
'password': 'test_value_15',
'private_key': 'test_value_16',
'region': 'test_value_17',
'resource_group': 'test_value_18',
'resource_url': 'test_value_19',
'secret_key': 'test_value_20',
'server': '192.168.100.21',
'server_port': '22',
'service_account': 'test_value_23',
'status': 'disable',
'subscription_id': 'test_value_25',
'tenant_id': 'test_value_26',
'type': 'aci',
'update_interval': '28',
'use_metadata_iam': 'disable',
'user_id': 'test_value_30',
'username': 'test_value_31',
'vpc_id': 'test_value_32'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_sdn_connector.fortios_system(input_data, fos_instance)
expected_data = {
'access-key': 'test_value_3',
'azure-region': 'global',
'client-id': 'test_value_5',
'client-secret': 'test_value_6',
'compartment-id': 'test_value_7',
'gcp-project': 'test_value_8',
'key-passwd': 'test_value_9',
'login-endpoint': 'test_value_10',
'name': 'default_name_11',
'oci-cert': 'test_value_12',
'oci-fingerprint': 'test_value_13',
'oci-region': 'phoenix',
'password': 'test_value_15',
'private-key': 'test_value_16',
'region': 'test_value_17',
'resource-group': 'test_value_18',
'resource-url': 'test_value_19',
'secret-key': 'test_value_20',
'server': '192.168.100.21',
'server-port': '22',
'service-account': 'test_value_23',
'status': 'disable',
'subscription-id': 'test_value_25',
'tenant-id': 'test_value_26',
'type': 'aci',
'update-interval': '28',
'use-metadata-iam': 'disable',
'user-id': 'test_value_30',
'username': 'test_value_31',
'vpc-id': 'test_value_32'
}
set_method_mock.assert_called_with('system', 'sdn-connector', 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_system_sdn_connector_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',
'system_sdn_connector': {
'access_key': 'test_value_3',
'azure_region': 'global',
'client_id': 'test_value_5',
'client_secret': 'test_value_6',
'compartment_id': 'test_value_7',
'gcp_project': 'test_value_8',
'key_passwd': 'test_value_9',
'login_endpoint': 'test_value_10',
'name': 'default_name_11',
'oci_cert': 'test_value_12',
'oci_fingerprint': 'test_value_13',
'oci_region': 'phoenix',
'password': 'test_value_15',
'private_key': 'test_value_16',
'region': 'test_value_17',
'resource_group': 'test_value_18',
'resource_url': 'test_value_19',
'secret_key': 'test_value_20',
'server': '192.168.100.21',
'server_port': '22',
'service_account': 'test_value_23',
'status': 'disable',
'subscription_id': 'test_value_25',
'tenant_id': 'test_value_26',
'type': 'aci',
'update_interval': '28',
'use_metadata_iam': 'disable',
'user_id': 'test_value_30',
'username': 'test_value_31',
'vpc_id': 'test_value_32'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_sdn_connector.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'sdn-connector', 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_system_sdn_connector_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',
'system_sdn_connector': {
'access_key': 'test_value_3',
'azure_region': 'global',
'client_id': 'test_value_5',
'client_secret': 'test_value_6',
'compartment_id': 'test_value_7',
'gcp_project': 'test_value_8',
'key_passwd': 'test_value_9',
'login_endpoint': 'test_value_10',
'name': 'default_name_11',
'oci_cert': 'test_value_12',
'oci_fingerprint': 'test_value_13',
'oci_region': 'phoenix',
'password': 'test_value_15',
'private_key': 'test_value_16',
'region': 'test_value_17',
'resource_group': 'test_value_18',
'resource_url': 'test_value_19',
'secret_key': 'test_value_20',
'server': '192.168.100.21',
'server_port': '22',
'service_account': 'test_value_23',
'status': 'disable',
'subscription_id': 'test_value_25',
'tenant_id': 'test_value_26',
'type': 'aci',
'update_interval': '28',
'use_metadata_iam': 'disable',
'user_id': 'test_value_30',
'username': 'test_value_31',
'vpc_id': 'test_value_32'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_sdn_connector.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'sdn-connector', 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_system_sdn_connector_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',
'system_sdn_connector': {
'access_key': 'test_value_3',
'azure_region': 'global',
'client_id': 'test_value_5',
'client_secret': 'test_value_6',
'compartment_id': 'test_value_7',
'gcp_project': 'test_value_8',
'key_passwd': 'test_value_9',
'login_endpoint': 'test_value_10',
'name': 'default_name_11',
'oci_cert': 'test_value_12',
'oci_fingerprint': 'test_value_13',
'oci_region': 'phoenix',
'password': 'test_value_15',
'private_key': 'test_value_16',
'region': 'test_value_17',
'resource_group': 'test_value_18',
'resource_url': 'test_value_19',
'secret_key': 'test_value_20',
'server': '192.168.100.21',
'server_port': '22',
'service_account': 'test_value_23',
'status': 'disable',
'subscription_id': 'test_value_25',
'tenant_id': 'test_value_26',
'type': 'aci',
'update_interval': '28',
'use_metadata_iam': 'disable',
'user_id': 'test_value_30',
'username': 'test_value_31',
'vpc_id': 'test_value_32'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_sdn_connector.fortios_system(input_data, fos_instance)
expected_data = {
'access-key': 'test_value_3',
'azure-region': 'global',
'client-id': 'test_value_5',
'client-secret': 'test_value_6',
'compartment-id': 'test_value_7',
'gcp-project': 'test_value_8',
'key-passwd': 'test_value_9',
'login-endpoint': 'test_value_10',
'name': 'default_name_11',
'oci-cert': 'test_value_12',
'oci-fingerprint': 'test_value_13',
'oci-region': 'phoenix',
'password': 'test_value_15',
'private-key': 'test_value_16',
'region': 'test_value_17',
'resource-group': 'test_value_18',
'resource-url': 'test_value_19',
'secret-key': 'test_value_20',
'server': '192.168.100.21',
'server-port': '22',
'service-account': 'test_value_23',
'status': 'disable',
'subscription-id': 'test_value_25',
'tenant-id': 'test_value_26',
'type': 'aci',
'update-interval': '28',
'use-metadata-iam': 'disable',
'user-id': 'test_value_30',
'username': 'test_value_31',
'vpc-id': 'test_value_32'
}
set_method_mock.assert_called_with('system', 'sdn-connector', 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_system_sdn_connector_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',
'system_sdn_connector': {
'random_attribute_not_valid': 'tag',
'access_key': 'test_value_3',
'azure_region': 'global',
'client_id': 'test_value_5',
'client_secret': 'test_value_6',
'compartment_id': 'test_value_7',
'gcp_project': 'test_value_8',
'key_passwd': 'test_value_9',
'login_endpoint': 'test_value_10',
'name': 'default_name_11',
'oci_cert': 'test_value_12',
'oci_fingerprint': 'test_value_13',
'oci_region': 'phoenix',
'password': 'test_value_15',
'private_key': 'test_value_16',
'region': 'test_value_17',
'resource_group': 'test_value_18',
'resource_url': 'test_value_19',
'secret_key': 'test_value_20',
'server': '192.168.100.21',
'server_port': '22',
'service_account': 'test_value_23',
'status': 'disable',
'subscription_id': 'test_value_25',
'tenant_id': 'test_value_26',
'type': 'aci',
'update_interval': '28',
'use_metadata_iam': 'disable',
'user_id': 'test_value_30',
'username': 'test_value_31',
'vpc_id': 'test_value_32'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_sdn_connector.fortios_system(input_data, fos_instance)
expected_data = {
'access-key': 'test_value_3',
'azure-region': 'global',
'client-id': 'test_value_5',
'client-secret': 'test_value_6',
'compartment-id': 'test_value_7',
'gcp-project': 'test_value_8',
'key-passwd': 'test_value_9',
'login-endpoint': 'test_value_10',
'name': 'default_name_11',
'oci-cert': 'test_value_12',
'oci-fingerprint': 'test_value_13',
'oci-region': 'phoenix',
'password': 'test_value_15',
'private-key': 'test_value_16',
'region': 'test_value_17',
'resource-group': 'test_value_18',
'resource-url': 'test_value_19',
'secret-key': 'test_value_20',
'server': '192.168.100.21',
'server-port': '22',
'service-account': 'test_value_23',
'status': 'disable',
'subscription-id': 'test_value_25',
'tenant-id': 'test_value_26',
'type': 'aci',
'update-interval': '28',
'use-metadata-iam': 'disable',
'user-id': 'test_value_30',
'username': 'test_value_31',
'vpc-id': 'test_value_32'
}
set_method_mock.assert_called_with('system', 'sdn-connector', 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

@ -0,0 +1,229 @@
# 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_system_vdom
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_system_vdom.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_vdom_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',
'system_vdom': {
'name': 'default_name_3',
'short_name': 'test_value_4',
'temporary': '5',
'vcluster_id': '6'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_vdom.fortios_system(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'short-name': 'test_value_4',
'temporary': '5',
'vcluster-id': '6'
}
set_method_mock.assert_called_with('system', 'vdom', 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_system_vdom_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',
'system_vdom': {
'name': 'default_name_3',
'short_name': 'test_value_4',
'temporary': '5',
'vcluster_id': '6'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_vdom.fortios_system(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'short-name': 'test_value_4',
'temporary': '5',
'vcluster-id': '6'
}
set_method_mock.assert_called_with('system', 'vdom', 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_system_vdom_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',
'system_vdom': {
'name': 'default_name_3',
'short_name': 'test_value_4',
'temporary': '5',
'vcluster_id': '6'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_vdom.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'vdom', 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_system_vdom_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',
'system_vdom': {
'name': 'default_name_3',
'short_name': 'test_value_4',
'temporary': '5',
'vcluster_id': '6'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_vdom.fortios_system(input_data, fos_instance)
delete_method_mock.assert_called_with('system', 'vdom', 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_system_vdom_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',
'system_vdom': {
'name': 'default_name_3',
'short_name': 'test_value_4',
'temporary': '5',
'vcluster_id': '6'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_vdom.fortios_system(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'short-name': 'test_value_4',
'temporary': '5',
'vcluster-id': '6'
}
set_method_mock.assert_called_with('system', 'vdom', 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_system_vdom_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',
'system_vdom': {
'random_attribute_not_valid': 'tag',
'name': 'default_name_3',
'short_name': 'test_value_4',
'temporary': '5',
'vcluster_id': '6'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_vdom.fortios_system(input_data, fos_instance)
expected_data = {
'name': 'default_name_3',
'short-name': 'test_value_4',
'temporary': '5',
'vcluster-id': '6'
}
set_method_mock.assert_called_with('system', 'vdom', 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

@ -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_system_virtual_wan_link
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_system_virtual_wan_link.Connection')
return connection_class_mock
fos_instance = FortiOSHandler(connection_mock)
def test_system_virtual_wan_link_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',
'system_virtual_wan_link': {'fail_detect': 'enable',
'load_balance_mode': 'source-ip-based',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_virtual_wan_link.fortios_system(input_data, fos_instance)
expected_data = {'fail-detect': 'enable',
'load-balance-mode': 'source-ip-based',
'status': 'disable'
}
set_method_mock.assert_called_with('system', 'virtual-wan-link', 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_system_virtual_wan_link_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',
'system_virtual_wan_link': {'fail_detect': 'enable',
'load_balance_mode': 'source-ip-based',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_virtual_wan_link.fortios_system(input_data, fos_instance)
expected_data = {'fail-detect': 'enable',
'load-balance-mode': 'source-ip-based',
'status': 'disable'
}
set_method_mock.assert_called_with('system', 'virtual-wan-link', 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_system_virtual_wan_link_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',
'system_virtual_wan_link': {'fail_detect': 'enable',
'load_balance_mode': 'source-ip-based',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_virtual_wan_link.fortios_system(input_data, fos_instance)
expected_data = {'fail-detect': 'enable',
'load-balance-mode': 'source-ip-based',
'status': 'disable'
}
set_method_mock.assert_called_with('system', 'virtual-wan-link', 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_system_virtual_wan_link_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',
'system_virtual_wan_link': {
'random_attribute_not_valid': 'tag', 'fail_detect': 'enable',
'load_balance_mode': 'source-ip-based',
'status': 'disable'
},
'vdom': 'root'}
is_error, changed, response = fortios_system_virtual_wan_link.fortios_system(input_data, fos_instance)
expected_data = {'fail-detect': 'enable',
'load-balance-mode': 'source-ip-based',
'status': 'disable'
}
set_method_mock.assert_called_with('system', 'virtual-wan-link', 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
Loading…
Cancel
Save