#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
# Copyright 2019-2020 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 this program.  If not, see <https://www.gnu.org/licenses/>.

__metaclass__ = type

ANSIBLE_METADATA = {'status': ['preview'],
                    'supported_by': 'community',
                    'metadata_version': '1.1'}

DOCUMENTATION = '''
---
module: fortios_firewall_central_snat_map
short_description: Configure central SNAT policies in Fortinet's FortiOS and FortiGate.
description:
    - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
      user to set and modify firewall feature and central_snat_map category.
      Examples include all parameters and values need to be adjusted to datasources before usage.
      Tested with FOS v6.0.0
version_added: "2.10"
author:
    - <NAME> (@chillancezen)
    - <NAME> (@JieX19)
    - <NAME> (@fgtdev-hblu)
    - <NAME> (@frankshen01)
    - <NAME> (@mamunozgonzalez)
    - <NAME> (@thomnico)
notes:
    - Legacy fortiosapi has been deprecated, httpapi is the preferred way to run playbooks
    - Adjust object order by moving self after(before) another.
    - Only one of [after, before] must be specified when action is moving an object.

requirements:
    - ansible>=2.9.0
options:
    access_token:
        description:
            - Token-based authentication.
              Generated from GUI of Fortigate.
        type: str
        required: false
    enable_log:
        description:
            - Enable/Disable logging for task.
        type: bool
        required: false
        default: false
    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
    member_path:
        type: str
        description:
            - Member attribute path to operate on.
            - Delimited by a slash character if there are more than one attribute.
            - Parameter marked with member_path is legitimate for doing member operation.
    member_state:
        type: str
        description:
            - Add or delete a member under specified attribute path.
            - When member_state is specified, the state option is ignored.
        choices:
            - present
            - absent
    action:
        description:
            - the action indiactor to move an object in the list
        type: str
        choices:
            - move
    self:
        description:
            - mkey of self identifier
        type: str
    after:
        description:
            - mkey of target identifier
        type: str
    before:
        description:
            - mkey of target identifier
        type: str

    state:
        description:
            - Indicates whether to create or remove the object.
        type: str
        required: true
        choices:
            - present
            - absent
    firewall_central_snat_map:
        description:
            - Configure central SNAT policies.
        default: null
        type: dict
        suboptions:
            comments:
                description:
                    - Comment.
                type: str
            dst_addr:
                description:
                    - Destination address name from available addresses.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address.name firewall.addrgrp.name.
                        required: true
                        type: str
            dst_addr6:
                description:
                    - IPv6 Destination address.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address6.name firewall.addrgrp6.name.
                        required: true
                        type: str
            dstintf:
                description:
                    - Destination interface name from available interfaces.
                type: list
                suboptions:
                    name:
                        description:
                            - Interface name. Source system.interface.name system.zone.name.
                        required: true
                        type: str
            nat:
                description:
                    - Enable/disable source NAT.
                type: str
                choices:
                    - disable
                    - enable
            nat_ippool:
                description:
                    - Name of the IP pools to be used to translate addresses from available IP Pools.
                type: list
                suboptions:
                    name:
                        description:
                            - IP pool name. Source firewall.ippool.name.
                        required: true
                        type: str
            nat_ippool6:
                description:
                    - IPv6 pools to be used for source NAT.
                type: list
                suboptions:
                    name:
                        description:
                            - IPv6 pool name. Source firewall.ippool6.name.
                        required: true
                        type: str
            nat_port:
                description:
                    - Translated port or port range (0 to 65535).
                type: str
            nat46:
                description:
                    - Enable/disable NAT46.
                type: str
                choices:
                    - enable
                    - disable
            nat64:
                description:
                    - Enable/disable NAT64.
                type: str
                choices:
                    - enable
                    - disable
            orig_addr:
                description:
                    - Original address.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address.name firewall.addrgrp.name.
                        required: true
                        type: str
            orig_addr6:
                description:
                    - IPv6 Original address.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address6.name firewall.addrgrp6.name.
                        required: true
                        type: str
            orig_port:
                description:
                    - Original TCP port (0 to 65535).
                type: str
            policyid:
                description:
                    - Policy ID.
                required: true
                type: int
            protocol:
                description:
                    - Integer value for the protocol type (0 - 255).
                type: int
            srcintf:
                description:
                    - Source interface name from available interfaces.
                type: list
                suboptions:
                    name:
                        description:
                            - Interface name. Source system.interface.name system.zone.name.
                        required: true
                        type: str
            status:
                description:
                    - Enable/disable the active status of this policy.
                type: str
                choices:
                    - enable
                    - disable
            type:
                description:
                    - IPv4/IPv6 source NAT.
                type: str
                choices:
                    - ipv4
                    - ipv6
            uuid:
                description:
                    - Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
                type: str
'''
EXAMPLES = '''
- collections:
  - fortinet.fortios
  connection: httpapi
  hosts: fortigate01
  vars:
    ansible_httpapi_port: 443
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: false
    vdom: root
  tasks:
  - name: fortios_firewall_central_snat_map
    fortios_firewall_central_snat_map:
      vdom: root
      state: present
      firewall_central_snat_map:
        dst_addr:
        - all
        dstintf:
        - port5
        nat: disable
        nat_port: '0'
        orig_addr:
        - all
        orig_port: '0'
        policyid: 1
        protocol: 33
        srcintf:
        - port2
        status: enable
        type: ipv4

'''

RETURN = '''
build:
  description: Build number of the fortigate image
  returned: always
  type: str
  sample: '1547'
http_method:
  description: Last method used to provision the content into FortiGate
  returned: always
  type: str
  sample: 'PUT'
http_status:
  description: Last result given by FortiGate on last operation applied
  returned: always
  type: str
  sample: "200"
mkey:
  description: Master key (id) used in the last call to FortiGate
  returned: success
  type: str
  sample: "id"
name:
  description: Name of the table used to fulfill the request
  returned: always
  type: str
  sample: "urlfilter"
path:
  description: Path of the table used to fulfill the request
  returned: always
  type: str
  sample: "webfilter"
revision:
  description: Internal revision number
  returned: always
  type: str
  sample: "17.0.2.10658"
serial:
  description: Serial number of the unit
  returned: always
  type: str
  sample: "FGVMEVYYQT3AB5352"
status:
  description: Indication of the operation's result
  returned: always
  type: str
  sample: "success"
vdom:
  description: Virtual domain used
  returned: always
  type: str
  sample: "root"
version:
  description: Version of the FortiGate
  returned: always
  type: str
  sample: "v5.6.3"

'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize


def filter_firewall_central_snat_map_data(json):
    option_list = ['comments', 'dst_addr', 'dst_addr6',
                   'dstintf', 'nat', 'nat_ippool',
                   'nat_ippool6', 'nat_port', 'nat46',
                   'nat64', 'orig_addr', 'orig_addr6',
                   'orig_port', 'policyid', 'protocol',
                   'srcintf', 'status', 'type',
                   'uuid']
    dictionary = {}

    for attribute in option_list:
        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 i, elem in enumerate(data):
            data[i] = 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 firewall_central_snat_map(data, fos, check_mode=False):

    vdom = data['vdom']

    state = data['state']

    firewall_central_snat_map_data = data['firewall_central_snat_map']
    filtered_data = underscore_to_hyphen(filter_firewall_central_snat_map_data(firewall_central_snat_map_data))

    # check_mode starts from here
    if check_mode:
        mkey = fos.get_mkey('firewall', 'central_snat_map', filtered_data, vdom=vdom)
        current_data = fos.get('firewall', 'central_snat_map', vdom=vdom, mkey=mkey)
        is_existed = current_data and current_data.get('http_status') == 200 \
            and isinstance(current_data.get('results'), list) \
            and len(current_data['results']) > 0

        # 2. if it exists and the state is 'present' then compare current settings with desired
        if state == 'present' or state is True:
            if mkey is None:
                return False, True, filtered_data

            # if mkey exists then compare each other
            # record exits and they're matched or not
            if is_existed:
                is_same = is_same_comparison(
                    serialize(current_data['results'][0]), serialize(filtered_data))
                return False, not is_same, filtered_data

            # record does not exist
            return False, True, filtered_data

        if state == 'absent':
            if mkey is None:
                return False, False, filtered_data

            if is_existed:
                return False, True, filtered_data
            return False, False, filtered_data

        return True, False, {'reason: ': 'Must provide state parameter'}

    if state == "present" or state is True:
        return fos.set('firewall',
                       'central-snat-map',
                       data=filtered_data,
                       vdom=vdom)

    elif state == "absent":
        return fos.delete('firewall',
                          'central-snat-map',
                          mkey=filtered_data['policyid'],
                          vdom=vdom)
    else:
        fos._module.fail_json(msg='state must be present or absent!')


def is_successful_status(resp):
    return 'status' in resp and resp['status'] == 'success' or \
        'http_status' in resp and resp['http_status'] == 200 or \
        'http_method' in resp and resp['http_method'] == "DELETE" and resp['http_status'] == 404


def move_fortios_firewall(data, fos):
    if not data['self'] or (not data['after'] and not data['before']):
        fos._module.fail_json(msg='self, after(or before) must not be empty')
    vdom = data['vdom']
    params_set = dict()
    params_set['action'] = 'move'
    if data['after']:
        params_set['after'] = data['after']
    if data['before']:
        params_set['before'] = data['before']
    return fos.set('firewall',
                   'central-snat-map',
                   data=None,
                   mkey=data['self'],
                   vdom=vdom,
                   parameters=params_set)


def fortios_firewall(data, fos, check_mode):

    fos.do_member_operation('firewall_central_snat_map')
    if data['action'] == 'move':
        resp = move_fortios_firewall(data, fos)
    elif data['firewall_central_snat_map']:
        resp = firewall_central_snat_map(data, fos, check_mode)
    else:
        fos._module.fail_json(msg='missing task body: %s' % ('firewall_central_snat_map'))
    if check_mode:
        return resp
    return not is_successful_status(resp), \
        is_successful_status(resp) and \
        (resp['revision_changed'] if 'revision_changed' in resp else True), \
        resp


versioned_schema = {
    "type": "list",
    "children": {
        "status": {
            "type": "string",
            "options": [
                {
                    "value": "enable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                },
                {
                    "value": "disable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            ],
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "dst_addr6": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            },
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "nat": {
            "type": "string",
            "options": [
                {
                    "value": "disable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                },
                {
                    "value": "enable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            ],
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "protocol": {
            "type": "integer",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "uuid": {
            "type": "string",
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "nat_ippool6": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            },
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "nat64": {
            "type": "string",
            "options": [
                {
                    "value": "enable",
                    "revisions": {
                        "v7.0.1": True
                    }
                },
                {
                    "value": "disable",
                    "revisions": {
                        "v7.0.1": True
                    }
                }
            ],
            "revisions": {
                "v7.0.1": True
            }
        },
        "orig_port": {
            "type": "string",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "dstintf": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "nat_port": {
            "type": "string",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "nat46": {
            "type": "string",
            "options": [
                {
                    "value": "enable",
                    "revisions": {
                        "v7.0.1": True
                    }
                },
                {
                    "value": "disable",
                    "revisions": {
                        "v7.0.1": True
                    }
                }
            ],
            "revisions": {
                "v7.0.1": True
            }
        },
        "comments": {
            "type": "string",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "srcintf": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "nat_ippool": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "policyid": {
            "type": "integer",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "orig_addr": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "type": {
            "type": "string",
            "options": [
                {
                    "value": "ipv4",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                },
                {
                    "value": "ipv6",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            ],
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "dst_addr": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "orig_addr6": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            },
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        }
    },
    "revisions": {
        "v6.0.0": True,
        "v7.0.0": True,
        "v6.0.5": True,
        "v6.4.4": True,
        "v7.0.1": True,
        "v6.4.0": True,
        "v6.4.1": True,
        "v6.2.0": True,
        "v6.2.3": True,
        "v6.2.5": True,
        "v6.2.7": True,
        "v6.0.11": True
    }
}


def main():
    module_spec = schema_to_module_spec(versioned_schema)
    mkeyname = 'policyid'
    fields = {
        "access_token": {"required": False, "type": "str", "no_log": True},
        "enable_log": {"required": False, "type": bool},
        "vdom": {"required": False, "type": "str", "default": "root"},
        "member_path": {"required": False, "type": "str"},
        "member_state": {
            "type": "str",
            "required": False,
            "choices": ["present", "absent"]
        },
        "action": {"type": "str", "required": False, "choices": ["move"]},
        "self": {"type": "str", "required": False},
        "before": {"type": "str", "required": False},
        "after": {"type": "str", "required": False},
        "state": {"required": False, "type": "str",
                  "choices": ["present", "absent"]},
        "firewall_central_snat_map": {
            "required": False, "type": "dict", "default": None,
            "options": {
            }
        }
    }
    for attribute_name in module_spec['options']:
        fields["firewall_central_snat_map"]['options'][attribute_name] = module_spec['options'][attribute_name]
        if mkeyname and mkeyname == attribute_name:
            fields["firewall_central_snat_map"]['options'][attribute_name]['required'] = True

    check_legacy_fortiosapi()
    module = AnsibleModule(argument_spec=fields,
                           supports_check_mode=True)

    versions_check_result = None
    if module._socket_path:
        connection = Connection(module._socket_path)
        if 'access_token' in module.params:
            connection.set_option('access_token', module.params['access_token'])

        if 'enable_log' in module.params:
            connection.set_option('enable_log', module.params['enable_log'])
        else:
            connection.set_option('enable_log', False)
        fos = FortiOSHandler(connection, module, mkeyname)
        versions_check_result = check_schema_versioning(fos, versioned_schema, "firewall_central_snat_map")

        is_error, has_changed, result = fortios_firewall(module.params, fos, module.check_mode)

    else:
        module.fail_json(**FAIL_SOCKET_MSG)

    if versions_check_result and versions_check_result['matched'] is False:
        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")

    if not is_error:
        if versions_check_result and versions_check_result['matched'] is False:
            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
        else:
            module.exit_json(changed=has_changed, meta=result)
    else:
        if versions_check_result and versions_check_result['matched'] is False:
            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
        else:
            module.fail_json(msg="Error in repo", meta=result)


if __name__ == '__main__':
    main()

#!/usr/bin/python
from __future__ import (absolute_import, division, print_function)
# Copyright 2019-2020 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 this program.  If not, see <https://www.gnu.org/licenses/>.

__metaclass__ = type

ANSIBLE_METADATA = {'status': ['preview'],
                    'supported_by': 'community',
                    'metadata_version': '1.1'}

DOCUMENTATION = '''
---
module: fortios_firewall_central_snat_map
short_description: Configure central SNAT policies in Fortinet's FortiOS and FortiGate.
description:
    - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
      user to set and modify firewall feature and central_snat_map category.
      Examples include all parameters and values need to be adjusted to datasources before usage.
      Tested with FOS v6.0.0
version_added: "2.10"
author:
    - <NAME> (@chillancezen)
    - <NAME> (@JieX19)
    - <NAME> (@fgtdev-hblu)
    - <NAME> (@frankshen01)
    - <NAME> (@mamunozgonzalez)
    - <NAME> (@thomnico)
notes:
    - Legacy fortiosapi has been deprecated, httpapi is the preferred way to run playbooks
    - Adjust object order by moving self after(before) another.
    - Only one of [after, before] must be specified when action is moving an object.

requirements:
    - ansible>=2.9.0
options:
    access_token:
        description:
            - Token-based authentication.
              Generated from GUI of Fortigate.
        type: str
        required: false
    enable_log:
        description:
            - Enable/Disable logging for task.
        type: bool
        required: false
        default: false
    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
    member_path:
        type: str
        description:
            - Member attribute path to operate on.
            - Delimited by a slash character if there are more than one attribute.
            - Parameter marked with member_path is legitimate for doing member operation.
    member_state:
        type: str
        description:
            - Add or delete a member under specified attribute path.
            - When member_state is specified, the state option is ignored.
        choices:
            - present
            - absent
    action:
        description:
            - the action indiactor to move an object in the list
        type: str
        choices:
            - move
    self:
        description:
            - mkey of self identifier
        type: str
    after:
        description:
            - mkey of target identifier
        type: str
    before:
        description:
            - mkey of target identifier
        type: str

    state:
        description:
            - Indicates whether to create or remove the object.
        type: str
        required: true
        choices:
            - present
            - absent
    firewall_central_snat_map:
        description:
            - Configure central SNAT policies.
        default: null
        type: dict
        suboptions:
            comments:
                description:
                    - Comment.
                type: str
            dst_addr:
                description:
                    - Destination address name from available addresses.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address.name firewall.addrgrp.name.
                        required: true
                        type: str
            dst_addr6:
                description:
                    - IPv6 Destination address.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address6.name firewall.addrgrp6.name.
                        required: true
                        type: str
            dstintf:
                description:
                    - Destination interface name from available interfaces.
                type: list
                suboptions:
                    name:
                        description:
                            - Interface name. Source system.interface.name system.zone.name.
                        required: true
                        type: str
            nat:
                description:
                    - Enable/disable source NAT.
                type: str
                choices:
                    - disable
                    - enable
            nat_ippool:
                description:
                    - Name of the IP pools to be used to translate addresses from available IP Pools.
                type: list
                suboptions:
                    name:
                        description:
                            - IP pool name. Source firewall.ippool.name.
                        required: true
                        type: str
            nat_ippool6:
                description:
                    - IPv6 pools to be used for source NAT.
                type: list
                suboptions:
                    name:
                        description:
                            - IPv6 pool name. Source firewall.ippool6.name.
                        required: true
                        type: str
            nat_port:
                description:
                    - Translated port or port range (0 to 65535).
                type: str
            nat46:
                description:
                    - Enable/disable NAT46.
                type: str
                choices:
                    - enable
                    - disable
            nat64:
                description:
                    - Enable/disable NAT64.
                type: str
                choices:
                    - enable
                    - disable
            orig_addr:
                description:
                    - Original address.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address.name firewall.addrgrp.name.
                        required: true
                        type: str
            orig_addr6:
                description:
                    - IPv6 Original address.
                type: list
                suboptions:
                    name:
                        description:
                            - Address name. Source firewall.address6.name firewall.addrgrp6.name.
                        required: true
                        type: str
            orig_port:
                description:
                    - Original TCP port (0 to 65535).
                type: str
            policyid:
                description:
                    - Policy ID.
                required: true
                type: int
            protocol:
                description:
                    - Integer value for the protocol type (0 - 255).
                type: int
            srcintf:
                description:
                    - Source interface name from available interfaces.
                type: list
                suboptions:
                    name:
                        description:
                            - Interface name. Source system.interface.name system.zone.name.
                        required: true
                        type: str
            status:
                description:
                    - Enable/disable the active status of this policy.
                type: str
                choices:
                    - enable
                    - disable
            type:
                description:
                    - IPv4/IPv6 source NAT.
                type: str
                choices:
                    - ipv4
                    - ipv6
            uuid:
                description:
                    - Universally Unique Identifier (UUID; automatically assigned but can be manually reset).
                type: str
'''
EXAMPLES = '''
- collections:
  - fortinet.fortios
  connection: httpapi
  hosts: fortigate01
  vars:
    ansible_httpapi_port: 443
    ansible_httpapi_use_ssl: true
    ansible_httpapi_validate_certs: false
    vdom: root
  tasks:
  - name: fortios_firewall_central_snat_map
    fortios_firewall_central_snat_map:
      vdom: root
      state: present
      firewall_central_snat_map:
        dst_addr:
        - all
        dstintf:
        - port5
        nat: disable
        nat_port: '0'
        orig_addr:
        - all
        orig_port: '0'
        policyid: 1
        protocol: 33
        srcintf:
        - port2
        status: enable
        type: ipv4

'''

RETURN = '''
build:
  description: Build number of the fortigate image
  returned: always
  type: str
  sample: '1547'
http_method:
  description: Last method used to provision the content into FortiGate
  returned: always
  type: str
  sample: 'PUT'
http_status:
  description: Last result given by FortiGate on last operation applied
  returned: always
  type: str
  sample: "200"
mkey:
  description: Master key (id) used in the last call to FortiGate
  returned: success
  type: str
  sample: "id"
name:
  description: Name of the table used to fulfill the request
  returned: always
  type: str
  sample: "urlfilter"
path:
  description: Path of the table used to fulfill the request
  returned: always
  type: str
  sample: "webfilter"
revision:
  description: Internal revision number
  returned: always
  type: str
  sample: "17.0.2.10658"
serial:
  description: Serial number of the unit
  returned: always
  type: str
  sample: "FGVMEVYYQT3AB5352"
status:
  description: Indication of the operation's result
  returned: always
  type: str
  sample: "success"
vdom:
  description: Virtual domain used
  returned: always
  type: str
  sample: "root"
version:
  description: Version of the FortiGate
  returned: always
  type: str
  sample: "v5.6.3"

'''
from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.connection import Connection
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize


def filter_firewall_central_snat_map_data(json):
    option_list = ['comments', 'dst_addr', 'dst_addr6',
                   'dstintf', 'nat', 'nat_ippool',
                   'nat_ippool6', 'nat_port', 'nat46',
                   'nat64', 'orig_addr', 'orig_addr6',
                   'orig_port', 'policyid', 'protocol',
                   'srcintf', 'status', 'type',
                   'uuid']
    dictionary = {}

    for attribute in option_list:
        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 i, elem in enumerate(data):
            data[i] = 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 firewall_central_snat_map(data, fos, check_mode=False):

    vdom = data['vdom']

    state = data['state']

    firewall_central_snat_map_data = data['firewall_central_snat_map']
    filtered_data = underscore_to_hyphen(filter_firewall_central_snat_map_data(firewall_central_snat_map_data))

    # check_mode starts from here
    if check_mode:
        mkey = fos.get_mkey('firewall', 'central_snat_map', filtered_data, vdom=vdom)
        current_data = fos.get('firewall', 'central_snat_map', vdom=vdom, mkey=mkey)
        is_existed = current_data and current_data.get('http_status') == 200 \
            and isinstance(current_data.get('results'), list) \
            and len(current_data['results']) > 0

        # 2. if it exists and the state is 'present' then compare current settings with desired
        if state == 'present' or state is True:
            if mkey is None:
                return False, True, filtered_data

            # if mkey exists then compare each other
            # record exits and they're matched or not
            if is_existed:
                is_same = is_same_comparison(
                    serialize(current_data['results'][0]), serialize(filtered_data))
                return False, not is_same, filtered_data

            # record does not exist
            return False, True, filtered_data

        if state == 'absent':
            if mkey is None:
                return False, False, filtered_data

            if is_existed:
                return False, True, filtered_data
            return False, False, filtered_data

        return True, False, {'reason: ': 'Must provide state parameter'}

    if state == "present" or state is True:
        return fos.set('firewall',
                       'central-snat-map',
                       data=filtered_data,
                       vdom=vdom)

    elif state == "absent":
        return fos.delete('firewall',
                          'central-snat-map',
                          mkey=filtered_data['policyid'],
                          vdom=vdom)
    else:
        fos._module.fail_json(msg='state must be present or absent!')


def is_successful_status(resp):
    return 'status' in resp and resp['status'] == 'success' or \
        'http_status' in resp and resp['http_status'] == 200 or \
        'http_method' in resp and resp['http_method'] == "DELETE" and resp['http_status'] == 404


def move_fortios_firewall(data, fos):
    if not data['self'] or (not data['after'] and not data['before']):
        fos._module.fail_json(msg='self, after(or before) must not be empty')
    vdom = data['vdom']
    params_set = dict()
    params_set['action'] = 'move'
    if data['after']:
        params_set['after'] = data['after']
    if data['before']:
        params_set['before'] = data['before']
    return fos.set('firewall',
                   'central-snat-map',
                   data=None,
                   mkey=data['self'],
                   vdom=vdom,
                   parameters=params_set)


def fortios_firewall(data, fos, check_mode):

    fos.do_member_operation('firewall_central_snat_map')
    if data['action'] == 'move':
        resp = move_fortios_firewall(data, fos)
    elif data['firewall_central_snat_map']:
        resp = firewall_central_snat_map(data, fos, check_mode)
    else:
        fos._module.fail_json(msg='missing task body: %s' % ('firewall_central_snat_map'))
    if check_mode:
        return resp
    return not is_successful_status(resp), \
        is_successful_status(resp) and \
        (resp['revision_changed'] if 'revision_changed' in resp else True), \
        resp


versioned_schema = {
    "type": "list",
    "children": {
        "status": {
            "type": "string",
            "options": [
                {
                    "value": "enable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                },
                {
                    "value": "disable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            ],
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "dst_addr6": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            },
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "nat": {
            "type": "string",
            "options": [
                {
                    "value": "disable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                },
                {
                    "value": "enable",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            ],
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "protocol": {
            "type": "integer",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "uuid": {
            "type": "string",
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "nat_ippool6": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            },
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "nat64": {
            "type": "string",
            "options": [
                {
                    "value": "enable",
                    "revisions": {
                        "v7.0.1": True
                    }
                },
                {
                    "value": "disable",
                    "revisions": {
                        "v7.0.1": True
                    }
                }
            ],
            "revisions": {
                "v7.0.1": True
            }
        },
        "orig_port": {
            "type": "string",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "dstintf": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "nat_port": {
            "type": "string",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "nat46": {
            "type": "string",
            "options": [
                {
                    "value": "enable",
                    "revisions": {
                        "v7.0.1": True
                    }
                },
                {
                    "value": "disable",
                    "revisions": {
                        "v7.0.1": True
                    }
                }
            ],
            "revisions": {
                "v7.0.1": True
            }
        },
        "comments": {
            "type": "string",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "srcintf": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "nat_ippool": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "policyid": {
            "type": "integer",
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "orig_addr": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "type": {
            "type": "string",
            "options": [
                {
                    "value": "ipv4",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                },
                {
                    "value": "ipv6",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            ],
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        },
        "dst_addr": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.0.0": True,
                        "v7.0.0": True,
                        "v6.0.5": True,
                        "v6.4.4": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True,
                        "v6.2.0": True,
                        "v6.2.3": True,
                        "v6.2.5": True,
                        "v6.2.7": True,
                        "v6.0.11": True
                    }
                }
            },
            "revisions": {
                "v6.0.0": True,
                "v7.0.0": True,
                "v6.0.5": True,
                "v6.4.4": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True,
                "v6.2.0": True,
                "v6.2.3": True,
                "v6.2.5": True,
                "v6.2.7": True,
                "v6.0.11": True
            }
        },
        "orig_addr6": {
            "type": "list",
            "children": {
                "name": {
                    "type": "string",
                    "revisions": {
                        "v6.4.4": True,
                        "v7.0.0": True,
                        "v7.0.1": True,
                        "v6.4.0": True,
                        "v6.4.1": True
                    }
                }
            },
            "revisions": {
                "v6.4.4": True,
                "v7.0.0": True,
                "v7.0.1": True,
                "v6.4.0": True,
                "v6.4.1": True
            }
        }
    },
    "revisions": {
        "v6.0.0": True,
        "v7.0.0": True,
        "v6.0.5": True,
        "v6.4.4": True,
        "v7.0.1": True,
        "v6.4.0": True,
        "v6.4.1": True,
        "v6.2.0": True,
        "v6.2.3": True,
        "v6.2.5": True,
        "v6.2.7": True,
        "v6.0.11": True
    }
}


def main():
    module_spec = schema_to_module_spec(versioned_schema)
    mkeyname = 'policyid'
    fields = {
        "access_token": {"required": False, "type": "str", "no_log": True},
        "enable_log": {"required": False, "type": bool},
        "vdom": {"required": False, "type": "str", "default": "root"},
        "member_path": {"required": False, "type": "str"},
        "member_state": {
            "type": "str",
            "required": False,
            "choices": ["present", "absent"]
        },
        "action": {"type": "str", "required": False, "choices": ["move"]},
        "self": {"type": "str", "required": False},
        "before": {"type": "str", "required": False},
        "after": {"type": "str", "required": False},
        "state": {"required": False, "type": "str",
                  "choices": ["present", "absent"]},
        "firewall_central_snat_map": {
            "required": False, "type": "dict", "default": None,
            "options": {
            }
        }
    }
    for attribute_name in module_spec['options']:
        fields["firewall_central_snat_map"]['options'][attribute_name] = module_spec['options'][attribute_name]
        if mkeyname and mkeyname == attribute_name:
            fields["firewall_central_snat_map"]['options'][attribute_name]['required'] = True

    check_legacy_fortiosapi()
    module = AnsibleModule(argument_spec=fields,
                           supports_check_mode=True)

    versions_check_result = None
    if module._socket_path:
        connection = Connection(module._socket_path)
        if 'access_token' in module.params:
            connection.set_option('access_token', module.params['access_token'])

        if 'enable_log' in module.params:
            connection.set_option('enable_log', module.params['enable_log'])
        else:
            connection.set_option('enable_log', False)
        fos = FortiOSHandler(connection, module, mkeyname)
        versions_check_result = check_schema_versioning(fos, versioned_schema, "firewall_central_snat_map")

        is_error, has_changed, result = fortios_firewall(module.params, fos, module.check_mode)

    else:
        module.fail_json(**FAIL_SOCKET_MSG)

    if versions_check_result and versions_check_result['matched'] is False:
        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")

    if not is_error:
        if versions_check_result and versions_check_result['matched'] is False:
            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
        else:
            module.exit_json(changed=has_changed, meta=result)
    else:
        if versions_check_result and versions_check_result['matched'] is False:
            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
        else:
            module.fail_json(msg="Error in repo", meta=result)


if __name__ == '__main__':
    main()

#!/usr/bin/python # Copyright 2019-2020 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 this program.  If not, see <https://www.gnu.org/licenses/>. --- module: fortios_firewall_central_snat_map short_description: Configure central SNAT policies in Fortinet's FortiOS and FortiGate. description:     - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the       user to set and modify firewall feature and central_snat_map category.       Examples include all parameters and values need to be adjusted to datasources before usage.       Tested with FOS v6.0.0 version_added: "2.10" author:     - <NAME> (@chillancezen)     - <NAME> (@JieX19)     - <NAME> (@fgtdev-hblu)     - <NAME> (@frankshen01)     - <NAME> (@mamunozgonzalez)     - <NAME> (@thomnico) notes:     - Legacy fortiosapi has been deprecated, httpapi is the preferred way to run playbooks     - Adjust object order by moving self after(before) another.     - Only one of [after, before] must be specified when action is moving an object.  requirements:     - ansible>=2.9.0 options:     access_token:         description:             - Token-based authentication.               Generated from GUI of Fortigate.         type: str         required: false     enable_log:         description:             - Enable/Disable logging for task.         type: bool         required: false         default: false     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     member_path:         type: str         description:             - Member attribute path to operate on.             - Delimited by a slash character if there are more than one attribute.             - Parameter marked with member_path is legitimate for doing member operation.     member_state:         type: str         description:             - Add or delete a member under specified attribute path.             - When member_state is specified, the state option is ignored.         choices:             - present             - absent     action:         description:             - the action indiactor to move an object in the list         type: str         choices:             - move     self:         description:             - mkey of self identifier         type: str     after:         description:             - mkey of target identifier         type: str     before:         description:             - mkey of target identifier         type: str      state:         description:             - Indicates whether to create or remove the object.         type: str         required: true         choices:             - present             - absent     firewall_central_snat_map:         description:             - Configure central SNAT policies.         default: null         type: dict         suboptions:             comments:                 description:                     - Comment.                 type: str             dst_addr:                 description:                     - Destination address name from available addresses.                 type: list                 suboptions:                     name:                         description:                             - Address name. Source firewall.address.name firewall.addrgrp.name.                         required: true                         type: str             dst_addr6:                 description:                     - IPv6 Destination address.                 type: list                 suboptions:                     name:                         description:                             - Address name. Source firewall.address6.name firewall.addrgrp6.name.                         required: true                         type: str             dstintf:                 description:                     - Destination interface name from available interfaces.                 type: list                 suboptions:                     name:                         description:                             - Interface name. Source system.interface.name system.zone.name.                         required: true                         type: str             nat:                 description:                     - Enable/disable source NAT.                 type: str                 choices:                     - disable                     - enable             nat_ippool:                 description:                     - Name of the IP pools to be used to translate addresses from available IP Pools.                 type: list                 suboptions:                     name:                         description:                             - IP pool name. Source firewall.ippool.name.                         required: true                         type: str             nat_ippool6:                 description:                     - IPv6 pools to be used for source NAT.                 type: list                 suboptions:                     name:                         description:                             - IPv6 pool name. Source firewall.ippool6.name.                         required: true                         type: str             nat_port:                 description:                     - Translated port or port range (0 to 65535).                 type: str             nat46:                 description:                     - Enable/disable NAT46.                 type: str                 choices:                     - enable                     - disable             nat64:                 description:                     - Enable/disable NAT64.                 type: str                 choices:                     - enable                     - disable             orig_addr:                 description:                     - Original address.                 type: list                 suboptions:                     name:                         description:                             - Address name. Source firewall.address.name firewall.addrgrp.name.                         required: true                         type: str             orig_addr6:                 description:                     - IPv6 Original address.                 type: list                 suboptions:                     name:                         description:                             - Address name. Source firewall.address6.name firewall.addrgrp6.name.                         required: true                         type: str             orig_port:                 description:                     - Original TCP port (0 to 65535).                 type: str             policyid:                 description:                     - Policy ID.                 required: true                 type: int             protocol:                 description:                     - Integer value for the protocol type (0 - 255).                 type: int             srcintf:                 description:                     - Source interface name from available interfaces.                 type: list                 suboptions:                     name:                         description:                             - Interface name. Source system.interface.name system.zone.name.                         required: true                         type: str             status:                 description:                     - Enable/disable the active status of this policy.                 type: str                 choices:                     - enable                     - disable             type:                 description:                     - IPv4/IPv6 source NAT.                 type: str                 choices:                     - ipv4                     - ipv6             uuid:                 description:                     - Universally Unique Identifier (UUID; automatically assigned but can be manually reset).                 type: str - collections:   - fortinet.fortios   connection: httpapi   hosts: fortigate01   vars:     ansible_httpapi_port: 443     ansible_httpapi_use_ssl: true     ansible_httpapi_validate_certs: false     vdom: root   tasks:   - name: fortios_firewall_central_snat_map     fortios_firewall_central_snat_map:       vdom: root       state: present       firewall_central_snat_map:         dst_addr:         - all         dstintf:         - port5         nat: disable         nat_port: '0'         orig_addr:         - all         orig_port: '0'         policyid: 1         protocol: 33         srcintf:         - port2         status: enable         type: ipv4 build:   description: Build number of the fortigate image   returned: always   type: str   sample: '1547' http_method:   description: Last method used to provision the content into FortiGate   returned: always   type: str   sample: 'PUT' http_status:   description: Last result given by FortiGate on last operation applied   returned: always   type: str   sample: "200" mkey:   description: Master key (id) used in the last call to FortiGate   returned: success   type: str   sample: "id" name:   description: Name of the table used to fulfill the request   returned: always   type: str   sample: "urlfilter" path:   description: Path of the table used to fulfill the request   returned: always   type: str   sample: "webfilter" revision:   description: Internal revision number   returned: always   type: str   sample: "17.0.2.10658" serial:   description: Serial number of the unit   returned: always   type: str   sample: "FGVMEVYYQT3AB5352" status:   description: Indication of the operation's result   returned: always   type: str   sample: "success" vdom:   description: Virtual domain used   returned: always   type: str   sample: "root" version:   description: Version of the FortiGate   returned: always   type: str   sample: "v5.6.3" # check_mode starts from here # 2. if it exists and the state is 'present' then compare current settings with desired # if mkey exists then compare each other # record exits and they're matched or not # record does not exist