From e585e948fb019ac02f6b4f268607d191d65dff40 Mon Sep 17 00:00:00 2001
From: ftntcorecse <43451990+ftntcorecse@users.noreply.github.com>
Date: Mon, 4 Mar 2019 06:13:05 -0500
Subject: [PATCH] New FortiManager Module: fmgr_fwobj_service (#53027)
* Auto Commit for: fmgr_fwobj_service
* Auto Commit for: fmgr_fwobj_service
---
.../fortimanager/fmgr_fwobj_service.py | 624 +++++++++++++++
.../fixtures/test_fmgr_fwobj_service.json | 745 ++++++++++++++++++
.../fortimanager/test_fmgr_fwobj_service.py | 123 +++
3 files changed, 1492 insertions(+)
create mode 100644 lib/ansible/modules/network/fortimanager/fmgr_fwobj_service.py
create mode 100644 test/units/modules/network/fortimanager/fixtures/test_fmgr_fwobj_service.json
create mode 100644 test/units/modules/network/fortimanager/test_fmgr_fwobj_service.py
diff --git a/lib/ansible/modules/network/fortimanager/fmgr_fwobj_service.py b/lib/ansible/modules/network/fortimanager/fmgr_fwobj_service.py
new file mode 100644
index 00000000000..9b9302cc2e5
--- /dev/null
+++ b/lib/ansible/modules/network/fortimanager/fmgr_fwobj_service.py
@@ -0,0 +1,624 @@
+#!/usr/bin/python
+#
+# This file is part of Ansible
+#
+# Ansible 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.
+#
+# Ansible 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 .
+#
+
+from __future__ import absolute_import, division, print_function
+
+__metaclass__ = type
+
+ANSIBLE_METADATA = {
+ "metadata_version": "1.1",
+ "status": ["preview"],
+ "supported_by": "community"
+}
+
+DOCUMENTATION = '''
+---
+module: fmgr_fwobj_service
+version_added: "2.8"
+notes:
+ - Full Documentation at U(https://ftnt-ansible-docs.readthedocs.io/en/latest/).
+author:
+ - Luke Weighall (@lweighall)
+ - Andrew Welsh (@Ghilli3)
+ - Jim Huber (@p4r4n0y1ng)
+short_description: Manages FortiManager Firewall Service Objects.
+description:
+ - Manages FortiManager Firewall Service Objects.
+
+options:
+ adom:
+ description:
+ -The ADOM the configuration should belong to.
+ required: false
+ default: root
+
+ app_category:
+ description:
+ - Application category ID.
+ required: false
+
+ app_service_type:
+ description:
+ - Application service type.
+ required: false
+
+ application:
+ description:
+ - Application ID.
+ required: false
+
+ category:
+ description:
+ - Service category.
+ required: false
+
+ check_reset_range:
+ description:
+ - Enable disable RST check.
+ required: false
+
+ color:
+ description:
+ - GUI icon color.
+ required: false
+ default: 22
+
+ comment:
+ description:
+ - Comment.
+ required: false
+
+ custom_type:
+ description:
+ - Tells module what kind of custom service to be added.
+ choices: ['tcp_udp_sctp', 'icmp', 'icmp6', 'ip', 'http', 'ftp', 'connect', 'socks_tcp', 'socks_udp', 'all']
+ default: all
+ required: false
+
+ explicit_proxy:
+ description:
+ - Enable/disable explicit web proxy service.
+ choices: ['enable', 'disable']
+ default: 'disable'
+ required: false
+
+ fqdn:
+ description:
+ - Fully qualified domain name.
+ required: false
+ default: ""
+
+ group_name:
+ description:
+ - Name of the Service Group.
+ required: false
+
+ group_member:
+ description:
+ - Comma-Seperated list of members' names.
+ required: false
+
+ icmp_code:
+ description:
+ - ICMP code.
+ required: false
+
+ icmp_type:
+ description:
+ - ICMP type.
+ required: false
+
+ iprange:
+ description:
+ - Start IP-End IP.
+ required: false
+ default: "0.0.0.0"
+
+ name:
+ description:
+ - Custom service name.
+ required: false
+
+ mode:
+ description:
+ - Sets one of three modes for managing the object.
+ choices: ['add', 'set', 'delete']
+ default: add
+ required: false
+
+ object_type:
+ description:
+ - Tells module if we are adding a custom service, category, or group.
+ choices: ['custom', 'group', 'category']
+ required: false
+
+ protocol:
+ description:
+ - Protocol type.
+ required: false
+
+ protocol_number:
+ description:
+ - IP protocol number.
+ required: false
+
+ sctp_portrange:
+ description:
+ - Multiple SCTP port ranges. Comma separated list of destination ports to add (i.e. '443,80').
+ - Syntax is
+ - If no sourcePort is defined, it assumes all of them.
+ - Ranges can be defined with a hyphen -
+ - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000).
+ - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000').
+ required: false
+
+ session_ttl:
+ description:
+ - Session TTL (300 - 604800, 0 = default).
+ required: false
+ default: 0
+
+ tcp_halfclose_timer:
+ description:
+ - TCP half close timeout (1 - 86400 sec, 0 = default).
+ required: false
+ default: 0
+
+ tcp_halfopen_timer:
+ description:
+ - TCP half close timeout (1 - 86400 sec, 0 = default).
+ required: false
+ default: 0
+
+ tcp_portrange:
+ description:
+ - Comma separated list of destination ports to add (i.e. '443,80').
+ - Syntax is
+ - If no sourcePort is defined, it assumes all of them.
+ - Ranges can be defined with a hyphen -
+ - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000).
+ - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000').
+ required: false
+
+ tcp_timewait_timer:
+ description:
+ - TCP half close timeout (1 - 300 sec, 0 = default).
+ required: false
+ default: 0
+
+ udp_idle_timer:
+ description:
+ - TCP half close timeout (0 - 86400 sec, 0 = default).
+ required: false
+ default: 0
+
+ udp_portrange:
+ description:
+ - Comma separated list of destination ports to add (i.e. '443,80').
+ - Syntax is
+ - If no sourcePort is defined, it assumes all of them.
+ - Ranges can be defined with a hyphen -
+ - Examples -- '443' (destPort 443 only) '443:1000-2000' (destPort 443 from source ports 1000-2000).
+ - String multiple together in same quotes, comma separated. ('443:1000-2000, 80:1000-2000').
+ required: false
+
+ visibility:
+ description:
+ - Enable/disable service visibility.
+ required: false
+ choices: ["enable", "disable"]
+ default: "enable"
+
+'''
+
+EXAMPLES = '''
+- name: ADD A CUSTOM SERVICE FOR TCP/UDP/SCP
+ fmgr_fwobj_service:
+ adom: "ansible"
+ name: "ansible_custom_service"
+ object_type: "custom"
+ custom_type: "tcp_udp_sctp"
+ tcp_portrange: "443"
+ udp_portrange: "51"
+ sctp_portrange: "100"
+
+- name: ADD A CUSTOM SERVICE FOR TCP/UDP/SCP WITH SOURCE RANGES AND MULTIPLES
+ fmgr_fwobj_service:
+ adom: "ansible"
+ name: "ansible_custom_serviceWithSource"
+ object_type: "custom"
+ custom_type: "tcp_udp_sctp"
+ tcp_portrange: "443:2000-1000,80-82:10000-20000"
+ udp_portrange: "51:100-200,162:200-400"
+ sctp_portrange: "100:2000-2500"
+
+- name: ADD A CUSTOM SERVICE FOR ICMP
+ fmgr_fwobj_service:
+ adom: "ansible"
+ name: "ansible_custom_icmp"
+ object_type: "custom"
+ custom_type: "icmp"
+ icmp_type: "8"
+ icmp_code: "3"
+
+- name: ADD A CUSTOM SERVICE FOR ICMP6
+ fmgr_fwobj_service:
+ adom: "ansible"
+ name: "ansible_custom_icmp6"
+ object_type: "custom"
+ custom_type: "icmp6"
+ icmp_type: "5"
+ icmp_code: "1"
+
+- name: ADD A CUSTOM SERVICE FOR IP - GRE
+ fmgr_fwobj_service:
+ adom: "ansible"
+ name: "ansible_custom_icmp6"
+ object_type: "custom"
+ custom_type: "ip"
+ protocol_number: "47"
+
+- name: ADD A CUSTOM PROXY FOR ALL WITH SOURCE RANGES AND MULTIPLES
+ fmgr_fwobj_service:
+ adom: "ansible"
+ name: "ansible_custom_proxy_all"
+ object_type: "custom"
+ custom_type: "all"
+ explicit_proxy: "enable"
+ tcp_portrange: "443:2000-1000,80-82:10000-20000"
+ iprange: "www.ansible.com"
+'''
+
+RETURN = """
+api_result:
+ description: full API response, includes status code and message
+ returned: always
+ type: str
+"""
+
+from ansible.module_utils.basic import AnsibleModule, env_fallback
+from ansible.module_utils.connection import Connection
+from ansible.module_utils.network.fortimanager.fortimanager import FortiManagerHandler
+from ansible.module_utils.network.fortimanager.common import FMGBaseException
+from ansible.module_utils.network.fortimanager.common import FMGRCommon
+from ansible.module_utils.network.fortimanager.common import DEFAULT_RESULT_OBJ
+from ansible.module_utils.network.fortimanager.common import FAIL_SOCKET_MSG
+from ansible.module_utils.network.fortimanager.common import scrub_dict
+
+
+def fmgr_fwobj_service_custom(fmgr, paramgram):
+ """
+ description:
+ - the tcp and udp-portrange parameters are in a list when there are multiple. they are not in a list when they
+ singular or by themselves (only 1 was listed)
+ - the syntax for this is (destPort:sourcePort). Ranges are (xxxx-xxxx) i.e. 443:443, or 443:1000-2000.
+ - if you leave out the second field after the colon (source port) it assumes any source port (which is usual)
+ - multiples would look like ['443:1000-2000','80']
+ - a single would look simple like "443:1000-2000" without the list around it ( a string!)
+ - the protocol parameter is the protocol NUMBER, not the string of it.
+ :param fmgr: The fmgr object instance from fortimanager.py
+ :type fmgr: class object
+ :param paramgram: The formatted dictionary of options to process
+ :type paramgram: dict
+ :return: The response from the FortiManager
+ :rtype: dict
+ """
+ response = DEFAULT_RESULT_OBJ
+ if paramgram["mode"] in ['set', 'add']:
+ # SET THE URL FOR ADD / SET
+ url = '/pm/config/adom/{adom}/obj/firewall/service/custom'.format(adom=paramgram["adom"])
+ # BUILD THE DEFAULT DATAGRAM
+ datagram = {
+ # ADVANCED OPTIONS
+ "app-category": paramgram["app-category"],
+ "app-service-type": paramgram["app-service-type"],
+ "application": paramgram["application"],
+ "category": paramgram["category"],
+ "check-reset-range": paramgram["check-reset-range"],
+ "color": paramgram["color"],
+ "session-ttl": paramgram["session-ttl"],
+ "tcp-halfclose-timer": paramgram["tcp-halfclose-timer"],
+ "tcp-halfopen-timer": paramgram["tcp-halfopen-timer"],
+ "tcp-timewait-timer": paramgram["tcp-timewait-timer"],
+ "udp-idle-timer": paramgram["udp-idle-timer"],
+ "visibility": paramgram["visibility"],
+ "comment": paramgram["comment"],
+ "proxy": paramgram["explicit-proxy"],
+ "name": paramgram["name"]
+ }
+
+ if datagram["proxy"] == "disable":
+ #######################################
+ # object-type = "TCP/UDP/SCTP"
+ #######################################
+ if paramgram["custom_type"] == "tcp_udp_sctp":
+ datagram["protocol"] = "TCP/UDP/SCTP"
+ # PROCESS PORT RANGES TO PUT INTO THE PROPER SYNTAX
+ if paramgram["tcp-portrange"] is not None:
+ tcp_list = []
+ for tcp in paramgram["tcp-portrange"].split(","):
+ tcp = tcp.strip()
+ tcp_list.append(tcp)
+ datagram["tcp-portrange"] = tcp_list
+
+ if paramgram["udp-portrange"] is not None:
+ udp_list = []
+ for udp in paramgram["udp-portrange"].split(","):
+ udp = udp.strip()
+ udp_list.append(udp)
+ datagram["udp-portrange"] = udp_list
+
+ if paramgram["sctp-portrange"] is not None:
+ sctp_list = []
+ for sctp in paramgram["sctp-portrange"].split(","):
+ sctp = sctp.strip()
+ sctp_list.append(sctp)
+ datagram["sctp-portrange"] = sctp_list
+
+ #######################################
+ # object-type = "ICMP"
+ #######################################
+ if paramgram["custom_type"] == "icmp":
+ datagram["icmpcode"] = paramgram["icmp_code"]
+ datagram["icmptype"] = paramgram["icmp_type"]
+ datagram["protocol"] = "ICMP"
+
+ #######################################
+ # object-type = "ICMP6"
+ #######################################
+ if paramgram["custom_type"] == "icmp6":
+ datagram["icmpcode"] = paramgram["icmp_code"]
+ datagram["icmptype"] = paramgram["icmp_type"]
+ datagram["protocol"] = "ICMP6"
+
+ #######################################
+ # object-type = "IP"
+ #######################################
+ if paramgram["custom_type"] == "ip":
+ datagram["protocol"] = "IP"
+ datagram["protocol-number"] = paramgram["protocol-number"]
+
+ #######################################
+ # object-type in any of the explicit proxy options
+ #######################################
+ if datagram["proxy"] == "enable":
+ datagram["protocol"] = paramgram["custom_type"].upper()
+ datagram["iprange"] = paramgram["iprange"]
+
+ # PROCESS PROXY TCP PORT RANGES TO PUT INTO THE PROPER SYNTAX
+ if paramgram["tcp-portrange"] is not None:
+ tcp_list = []
+ for tcp in paramgram["tcp-portrange"].split(","):
+ tcp = tcp.strip()
+ tcp_list.append(tcp)
+ datagram["tcp-portrange"] = tcp_list
+
+ if paramgram["mode"] == "delete":
+ datagram = {
+ "name": paramgram["name"]
+ }
+ # SET DELETE URL
+ url = '/pm/config/adom/{adom}/obj/firewall/service/custom' \
+ '/{name}'.format(adom=paramgram["adom"], name=paramgram["name"])
+
+ datagram = scrub_dict(datagram)
+ response = fmgr.process_request(url, datagram, paramgram["mode"])
+ return response
+
+
+def fmgr_fwobj_service_group(fmgr, paramgram):
+ """
+ :param fmgr: The fmgr object instance from fortimanager.py
+ :type fmgr: class object
+ :param paramgram: The formatted dictionary of options to process
+ :type paramgram: dict
+ :return: The response from the FortiManager
+ :rtype: dict
+ """
+ response = DEFAULT_RESULT_OBJ
+ if paramgram["mode"] in ['set', 'add']:
+ url = '/pm/config/adom/{adom}/obj/firewall/service/group'.format(adom=paramgram["adom"])
+ datagram = {
+ "name": paramgram["group-name"],
+ "comment": paramgram["comment"],
+ "proxy": paramgram["explicit-proxy"],
+ "color": paramgram["color"]
+ }
+
+ members = paramgram["group-member"]
+ member = []
+ for obj in members.split(","):
+ member.append(obj.strip())
+ datagram["member"] = member
+
+ if paramgram["mode"] == "delete":
+ datagram = {
+ "name": paramgram["name"]
+ }
+ # SET DELETE URL
+ url = '/pm/config/adom/{adom}/obj/firewall/service/group' \
+ '/{name}'.format(adom=paramgram["adom"], name=paramgram["group-name"])
+
+ datagram = scrub_dict(datagram)
+ response = fmgr.process_request(url, datagram, paramgram["mode"])
+ return response
+
+
+def fmgr_fwobj_service_category(fmgr, paramgram):
+ """
+ :param fmgr: The fmgr object instance from fortimanager.py
+ :type fmgr: class object
+ :param paramgram: The formatted dictionary of options to process
+ :type paramgram: dict
+ :return: The response from the FortiManager
+ :rtype: dict
+ """
+ response = DEFAULT_RESULT_OBJ
+ if paramgram["mode"] in ['set', 'add']:
+ url = '/pm/config/adom/{adom}/obj/firewall/service/category'.format(adom=paramgram["adom"])
+ # GET RID OF ANY WHITESPACE
+ category = paramgram["category"]
+ category = category.strip()
+
+ datagram = {
+ "name": paramgram["category"],
+ "comment": "Created by Ansible"
+ }
+
+ # IF MODE = DELETE
+ if paramgram["mode"] == "delete":
+ datagram = {
+ "name": paramgram["name"]
+ }
+ # SET DELETE URL
+ url = '/pm/config/adom/{adom}/obj/firewall/service/category' \
+ '/{name}'.format(adom=paramgram["adom"], name=paramgram["category"])
+
+ datagram = scrub_dict(datagram)
+ response = fmgr.process_request(url, datagram, paramgram["mode"])
+ return response
+
+
+def main():
+ argument_spec = dict(
+ adom=dict(required=False, type="str", default="root"),
+ mode=dict(required=False, type="str", choices=['add', 'set', 'delete'], default="add"),
+ app_category=dict(required=False, type="str"),
+ app_service_type=dict(required=False, type="str"),
+ application=dict(required=False, type="str"),
+ category=dict(required=False, type="str"),
+ check_reset_range=dict(required=False, type="str"),
+ color=dict(required=False, type="int", default=22),
+ comment=dict(required=False, type="str"),
+ custom_type=dict(required=False, type="str", choices=['tcp_udp_sctp', 'icmp', 'icmp6', 'ip', 'http', 'ftp',
+ 'connect', 'socks_tcp', 'socks_udp', 'all'],
+ default="all"),
+ explicit_proxy=dict(required=False, type="str", choices=['enable', 'disable'], default="disable"),
+ fqdn=dict(required=False, type="str", default=""),
+ group_name=dict(required=False, type="str"),
+ group_member=dict(required=False, type="str"),
+ icmp_code=dict(required=False, type="int"),
+ icmp_type=dict(required=False, type="int"),
+ iprange=dict(required=False, type="str", default="0.0.0.0"),
+ name=dict(required=False, type="str"),
+ protocol=dict(required=False, type="str"),
+ protocol_number=dict(required=False, type="int"),
+ sctp_portrange=dict(required=False, type="str"),
+ session_ttl=dict(required=False, type="int", default=0),
+ object_type=dict(required=False, type="str", choices=['custom', 'group', 'category']),
+ tcp_halfclose_timer=dict(required=False, type="int", default=0),
+ tcp_halfopen_timer=dict(required=False, type="int", default=0),
+ tcp_portrange=dict(required=False, type="str"),
+ tcp_timewait_timer=dict(required=False, type="int", default=0),
+ udp_idle_timer=dict(required=False, type="int", default=0),
+ udp_portrange=dict(required=False, type="str"),
+ visibility=dict(required=False, type="str", default="enable", choices=["enable", "disable"]),
+
+ )
+
+ module = AnsibleModule(argument_spec=argument_spec, supports_check_mode=False, )
+ # MODULE DATAGRAM
+ paramgram = {
+ "adom": module.params["adom"],
+ "app-category": module.params["app_category"],
+ "app-service-type": module.params["app_service_type"],
+ "application": module.params["application"],
+ "category": module.params["category"],
+ "check-reset-range": module.params["check_reset_range"],
+ "color": module.params["color"],
+ "comment": module.params["comment"],
+ "custom_type": module.params["custom_type"],
+ "explicit-proxy": module.params["explicit_proxy"],
+ "fqdn": module.params["fqdn"],
+ "group-name": module.params["group_name"],
+ "group-member": module.params["group_member"],
+ "icmp_code": module.params["icmp_code"],
+ "icmp_type": module.params["icmp_type"],
+ "iprange": module.params["iprange"],
+ "name": module.params["name"],
+ "mode": module.params["mode"],
+ "protocol": module.params["protocol"],
+ "protocol-number": module.params["protocol_number"],
+ "sctp-portrange": module.params["sctp_portrange"],
+ "object_type": module.params["object_type"],
+ "session-ttl": module.params["session_ttl"],
+ "tcp-halfclose-timer": module.params["tcp_halfclose_timer"],
+ "tcp-halfopen-timer": module.params["tcp_halfopen_timer"],
+ "tcp-portrange": module.params["tcp_portrange"],
+ "tcp-timewait-timer": module.params["tcp_timewait_timer"],
+ "udp-idle-timer": module.params["udp_idle_timer"],
+ "udp-portrange": module.params["udp_portrange"],
+ "visibility": module.params["visibility"],
+ }
+ module.paramgram = paramgram
+ fmgr = None
+ if module._socket_path:
+ connection = Connection(module._socket_path)
+ fmgr = FortiManagerHandler(connection, module)
+ fmgr.tools = FMGRCommon()
+ else:
+ module.fail_json(**FAIL_SOCKET_MSG)
+
+ results = DEFAULT_RESULT_OBJ
+
+ try:
+ # CHECK FOR CATEGORIES TO ADD
+ # THIS IS ONLY WHEN OBJECT_TYPE ISN'T SPECIFICALLY ADDING A CATEGORY!
+ # WE NEED TO ADD THE CATEGORY BEFORE ADDING THE OBJECT
+ # IF ANY category ARE DEFINED AND MODE IS ADD OR SET LETS ADD THOSE
+ # THIS IS A "BLIND ADD" AND THE EXIT CODE FOR OBJECT ALREADY EXISTS IS TREATED AS A PASS
+ if paramgram["category"] is not None and paramgram["mode"] in ['add', 'set'] \
+ and paramgram["object_type"] != "category":
+ category_add = fmgr_fwobj_service_category(fmgr, paramgram)
+ fmgr.govern_response(module=module, results=category_add,
+ ansible_facts=fmgr.construct_ansible_facts(category_add, module.params, paramgram))
+ except Exception as err:
+ raise FMGBaseException(err)
+
+ try:
+ # IF OBJECT_TYPE IS CATEGORY...
+ if paramgram["object_type"] == 'category':
+ results = fmgr_fwobj_service_category(fmgr, paramgram)
+ fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3],
+ ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
+ except Exception as err:
+ raise FMGBaseException(err)
+
+ try:
+ # IF OBJECT_TYPE IS CUSTOM...
+ if paramgram["object_type"] == 'custom':
+ results = fmgr_fwobj_service_custom(fmgr, paramgram)
+ fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3],
+ ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
+ except Exception as err:
+ raise FMGBaseException(err)
+
+ try:
+ # IF OBJECT_TYPE IS GROUP...
+ if paramgram["object_type"] == 'group':
+ results = fmgr_fwobj_service_group(fmgr, paramgram)
+ fmgr.govern_response(module=module, results=results, good_codes=[0, -2, -3],
+ ansible_facts=fmgr.construct_ansible_facts(results, module.params, paramgram))
+ except Exception as err:
+ raise FMGBaseException(err)
+
+ return module.exit_json(**results[1])
+
+
+if __name__ == "__main__":
+ main()
diff --git a/test/units/modules/network/fortimanager/fixtures/test_fmgr_fwobj_service.json b/test/units/modules/network/fortimanager/fixtures/test_fmgr_fwobj_service.json
new file mode 100644
index 00000000000..7909db218a1
--- /dev/null
+++ b/test/units/modules/network/fortimanager/fixtures/test_fmgr_fwobj_service.json
@@ -0,0 +1,745 @@
+{
+ "fmgr_fwobj_service_custom": [
+ {
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom/ansible_custom_service"
+ },
+ "datagram_sent": {
+ "name": "ansible_custom_service"
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_service",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "post_method": "delete"
+ },
+ {
+ "paramgram_used": {
+ "comment": null,
+ "protocol-number": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_icmp",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "datagram_sent": {
+ "name": "ansible_custom_icmp"
+ },
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom/ansible_custom_icmp"
+ },
+ "post_method": "delete"
+ },
+ {
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom/ansible_custom_icmp6"
+ },
+ "datagram_sent": {
+ "name": "ansible_custom_icmp6"
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_icmp6",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "post_method": "delete"
+ },
+ {
+ "paramgram_used": {
+ "comment": null,
+ "protocol-number": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_ip",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "datagram_sent": {
+ "name": "ansible_custom_ip"
+ },
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom/ansible_custom_ip"
+ },
+ "post_method": "delete"
+ },
+ {
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom/ansible_custom_serviceWithSource"
+ },
+ "datagram_sent": {
+ "name": "ansible_custom_serviceWithSource"
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_serviceWithSource",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "post_method": "delete"
+ },
+ {
+ "paramgram_used": {
+ "comment": null,
+ "protocol-number": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_proxy_all",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "datagram_sent": {
+ "name": "ansible_custom_proxy_all"
+ },
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom/ansible_custom_proxy_all"
+ },
+ "post_method": "delete"
+ },
+ {
+ "paramgram_used": {
+ "comment": null,
+ "protocol-number": null,
+ "protocol": null,
+ "custom_type": "tcp_udp_sctp",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": "ansibleCategoryTest",
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": "443",
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_service",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": "51",
+ "sctp-portrange": "100"
+ },
+ "datagram_sent": {
+ "category": "ansibleCategoryTest",
+ "protocol": "TCP/UDP/SCTP",
+ "name": "ansible_custom_service",
+ "color": 22,
+ "visibility": "enable",
+ "proxy": "disable",
+ "sctp-portrange": [
+ "100"
+ ],
+ "udp-portrange": [
+ "51"
+ ],
+ "tcp-portrange": [
+ "443"
+ ]
+ },
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom"
+ },
+ "post_method": "add"
+ },
+ {
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom"
+ },
+ "datagram_sent": {
+ "protocol": "TCP/UDP/SCTP",
+ "name": "ansible_custom_serviceWithSource",
+ "color": 22,
+ "visibility": "enable",
+ "proxy": "disable",
+ "tcp-portrange": [
+ "443:1000-2000",
+ "80-82:10000-20000"
+ ],
+ "udp-portrange": [
+ "51:100-200",
+ "162:200-400"
+ ],
+ "sctp-portrange": [
+ "100:2000-2500"
+ ]
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "tcp_udp_sctp",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": "443:1000-2000,80-82:10000-20000",
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_serviceWithSource",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": "51:100-200,162:200-400",
+ "sctp-portrange": "100:2000-2500"
+ },
+ "post_method": "add"
+ },
+ {
+ "paramgram_used": {
+ "comment": null,
+ "protocol-number": null,
+ "protocol": null,
+ "custom_type": "icmp",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": 8,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": 3,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_icmp",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "datagram_sent": {
+ "protocol": "ICMP",
+ "name": "ansible_custom_icmp",
+ "color": 22,
+ "visibility": "enable",
+ "icmptype": 8,
+ "proxy": "disable",
+ "icmpcode": 3
+ },
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom"
+ },
+ "post_method": "add"
+ },
+ {
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom"
+ },
+ "datagram_sent": {
+ "protocol": "ICMP6",
+ "name": "ansible_custom_icmp6",
+ "color": 22,
+ "visibility": "enable",
+ "icmptype": 5,
+ "proxy": "disable",
+ "icmpcode": 1
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "icmp6",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": 5,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": 1,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_icmp6",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "post_method": "add"
+ },
+ {
+ "paramgram_used": {
+ "comment": null,
+ "protocol-number": 12,
+ "protocol": null,
+ "custom_type": "ip",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_ip",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "datagram_sent": {
+ "protocol-number": 12,
+ "protocol": "IP",
+ "name": "ansible_custom_ip",
+ "color": 22,
+ "visibility": "enable",
+ "proxy": "disable"
+ },
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom"
+ },
+ "post_method": "add"
+ },
+ {
+ "raw_response": {
+ "status": {
+ "message": "OK",
+ "code": 0
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/custom"
+ },
+ "datagram_sent": {
+ "protocol": "ALL",
+ "name": "ansible_custom_proxy_all",
+ "color": 22,
+ "visibility": "enable",
+ "proxy": "enable",
+ "iprange": "www.ansible.com",
+ "tcp-portrange": [
+ "443:1000-2000",
+ "80-82:10000-20000"
+ ]
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "www.ansible.com",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "enable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": "443:1000-2000,80-82:10000-20000",
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_proxy_all",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "post_method": "add"
+ }
+ ],
+ "fmgr_fwobj_service_group": [
+ {
+ "raw_response": {
+ "status": {
+ "message": "Object does not exist",
+ "code": -3
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/group/ansibleTestGroup"
+ },
+ "datagram_sent": {},
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 22,
+ "object_type": "group",
+ "group-name": "ansibleTestGroup",
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": null,
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "delete",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "post_method": "delete"
+ },
+ {
+ "paramgram_used": {
+ "comment": "created by ansible",
+ "protocol-number": null,
+ "protocol": null,
+ "custom_type": "all",
+ "color": 10,
+ "object_type": "group",
+ "group-name": "ansibleTestGroup",
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": null,
+ "explicit-proxy": "disable",
+ "udp-idle-timer": 0,
+ "group-member": "ansible_custom_ip, ansible_custom_icmp, ansible_custom_service",
+ "application": null,
+ "tcp-portrange": null,
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": null,
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": null,
+ "sctp-portrange": null
+ },
+ "datagram_sent": {
+ "comment": "created by ansible",
+ "color": 10,
+ "member": [
+ "ansible_custom_ip",
+ "ansible_custom_icmp",
+ "ansible_custom_service"
+ ],
+ "name": "ansibleTestGroup",
+ "proxy": "disable"
+ },
+ "raw_response": {
+ "status": {
+ "message": "datasrc invalid. object: firewall service group member ansibleTestGroup. detail: ansible_custom_ip. solution: data not exist",
+ "code": -10131
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/group"
+ },
+ "post_method": "add"
+ }
+ ],
+ "fmgr_fwobj_service_category": [
+ {
+ "raw_response": {
+ "status": {
+ "message": "Object already exists",
+ "code": -2
+ },
+ "url": "/pm/config/adom/ansible/obj/firewall/service/category"
+ },
+ "datagram_sent": {
+ "comment": "Created by Ansible",
+ "name": "ansibleCategoryTest"
+ },
+ "paramgram_used": {
+ "comment": null,
+ "protocol": null,
+ "custom_type": "tcp_udp_sctp",
+ "color": 22,
+ "object_type": "custom",
+ "group-name": null,
+ "tcp-halfclose-timer": 0,
+ "icmp_type": null,
+ "iprange": "0.0.0.0",
+ "category": "ansibleCategoryTest",
+ "protocol-number": null,
+ "udp-idle-timer": 0,
+ "explicit-proxy": "disable",
+ "group-member": null,
+ "application": null,
+ "tcp-portrange": "443",
+ "icmp_code": null,
+ "session-ttl": 0,
+ "adom": "ansible",
+ "visibility": "enable",
+ "tcp-timewait-timer": 0,
+ "name": "ansible_custom_service",
+ "app-service-type": null,
+ "fqdn": "",
+ "app-category": null,
+ "check-reset-range": null,
+ "mode": "add",
+ "tcp-halfopen-timer": 0,
+ "udp-portrange": "51",
+ "sctp-portrange": "100"
+ },
+ "post_method": "add"
+ }
+ ]
+}
diff --git a/test/units/modules/network/fortimanager/test_fmgr_fwobj_service.py b/test/units/modules/network/fortimanager/test_fmgr_fwobj_service.py
new file mode 100644
index 00000000000..85bfcc2f539
--- /dev/null
+++ b/test/units/modules/network/fortimanager/test_fmgr_fwobj_service.py
@@ -0,0 +1,123 @@
+# Copyright 2018 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 .
+
+# Make coding more python3-ish
+from __future__ import (absolute_import, division, print_function)
+__metaclass__ = type
+
+import os
+import json
+from ansible.module_utils.network.fortimanager.fortimanager import FortiManagerHandler
+import pytest
+
+try:
+ from ansible.modules.network.fortimanager import fmgr_fwobj_service
+except ImportError:
+ pytest.skip("Could not load required modules for testing", allow_module_level=True)
+
+
+def load_fixtures():
+ fixture_path = os.path.join(os.path.dirname(__file__), 'fixtures') + "/{filename}.json".format(
+ filename=os.path.splitext(os.path.basename(__file__))[0])
+ try:
+ with open(fixture_path, "r") as fixture_file:
+ fixture_data = json.load(fixture_file)
+ except IOError:
+ return []
+ return [fixture_data]
+
+
+@pytest.fixture(autouse=True)
+def module_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.module_utils.basic.AnsibleModule')
+ return connection_class_mock
+
+
+@pytest.fixture(autouse=True)
+def connection_mock(mocker):
+ connection_class_mock = mocker.patch('ansible.modules.network.fortimanager.fmgr_fwobj_service.Connection')
+ return connection_class_mock
+
+
+@pytest.fixture(scope="function", params=load_fixtures())
+def fixture_data(request):
+ func_name = request.function.__name__.replace("test_", "")
+ return request.param.get(func_name, None)
+
+
+fmg_instance = FortiManagerHandler(connection_mock, module_mock)
+
+
+def test_fmgr_fwobj_service_custom(fixture_data, mocker):
+ mocker.patch("ansible.module_utils.network.fortimanager.fortimanager.FortiManagerHandler.process_request",
+ side_effect=fixture_data)
+
+ # Test using fixture 1 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[0]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 2 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[1]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 3 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[2]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 4 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[3]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 5 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[4]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 6 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[5]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 7 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[6]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 8 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[7]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 9 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[8]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 10 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[9]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 11 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[10]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+ # Test using fixture 12 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_custom(fmg_instance, fixture_data[11]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == 0
+
+
+def test_fmgr_fwobj_service_group(fixture_data, mocker):
+ mocker.patch("ansible.module_utils.network.fortimanager.fortimanager.FortiManagerHandler.process_request",
+ side_effect=fixture_data)
+
+ # Test using fixture 1 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_group(fmg_instance, fixture_data[0]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == -3
+ # Test using fixture 2 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_group(fmg_instance, fixture_data[1]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == -10131
+
+
+def test_fmgr_fwobj_service_category(fixture_data, mocker):
+ mocker.patch("ansible.module_utils.network.fortimanager.fortimanager.FortiManagerHandler.process_request",
+ side_effect=fixture_data)
+
+ # Test using fixture 1 #
+ output = fmgr_fwobj_service.fmgr_fwobj_service_category(fmg_instance, fixture_data[0]['paramgram_used'])
+ assert output['raw_response']['status']['code'] == -2