1#!/usr/local/bin/python3.8
2from __future__ import (absolute_import, division, print_function)
3# Copyright 2019-2020 Fortinet, Inc.
4#
5# This program is free software: you can redistribute it and/or modify
6# it under the terms of the GNU General Public License as published by
7# the Free Software Foundation, either version 3 of the License, or
8# (at your option) any later version.
9#
10# This program is distributed in the hope that it will be useful,
11# but WITHOUT ANY WARRANTY; without even the implied warranty of
12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13# GNU General Public License for more details.
14#
15# You should have received a copy of the GNU General Public License
16# along with this program.  If not, see <https://www.gnu.org/licenses/>.
17
18__metaclass__ = type
19
20ANSIBLE_METADATA = {'status': ['preview'],
21                    'supported_by': 'community',
22                    'metadata_version': '1.1'}
23
24DOCUMENTATION = '''
25---
26module: fortios_router_policy
27short_description: Configure IPv4 routing policies in Fortinet's FortiOS and FortiGate.
28description:
29    - This module is able to configure a FortiGate or FortiOS (FOS) device by allowing the
30      user to set and modify router feature and policy category.
31      Examples include all parameters and values need to be adjusted to datasources before usage.
32      Tested with FOS v6.0.0
33version_added: "2.10"
34author:
35    - Link Zheng (@chillancezen)
36    - Jie Xue (@JieX19)
37    - Hongbin Lu (@fgtdev-hblu)
38    - Frank Shen (@frankshen01)
39    - Miguel Angel Munoz (@mamunozgonzalez)
40    - Nicolas Thomas (@thomnico)
41notes:
42    - Legacy fortiosapi has been deprecated, httpapi is the preferred way to run playbooks
43
44requirements:
45    - ansible>=2.9.0
46options:
47    access_token:
48        description:
49            - Token-based authentication.
50              Generated from GUI of Fortigate.
51        type: str
52        required: false
53    enable_log:
54        description:
55            - Enable/Disable logging for task.
56        type: bool
57        required: false
58        default: false
59    vdom:
60        description:
61            - Virtual domain, among those defined previously. A vdom is a
62              virtual instance of the FortiGate that can be configured and
63              used as a different unit.
64        type: str
65        default: root
66
67    state:
68        description:
69            - Indicates whether to create or remove the object.
70        type: str
71        required: true
72        choices:
73            - present
74            - absent
75    router_policy:
76        description:
77            - Configure IPv4 routing policies.
78        default: null
79        type: dict
80        suboptions:
81            action:
82                description:
83                    - Action of the policy route.
84                type: str
85                choices:
86                    - deny
87                    - permit
88            comments:
89                description:
90                    - Optional comments.
91                type: str
92            dst:
93                description:
94                    - Destination IP and mask (x.x.x.x/x).
95                type: list
96                suboptions:
97                    subnet:
98                        description:
99                            - IP and mask.
100                        required: true
101                        type: str
102            dst_negate:
103                description:
104                    - Enable/disable negating destination address match.
105                type: str
106                choices:
107                    - enable
108                    - disable
109            dstaddr:
110                description:
111                    - Destination address name.
112                type: list
113                suboptions:
114                    name:
115                        description:
116                            - Address/group name. Source firewall.address.name firewall.addrgrp.name.
117                        required: true
118                        type: str
119            end_port:
120                description:
121                    - End destination port number (0 - 65535).
122                type: int
123            end_source_port:
124                description:
125                    - End source port number (0 - 65535).
126                type: int
127            gateway:
128                description:
129                    - IP address of the gateway.
130                type: str
131            input_device:
132                description:
133                    - Incoming interface name.
134                type: list
135                suboptions:
136                    name:
137                        description:
138                            - Interface name. Source system.interface.name.
139                        required: true
140                        type: str
141            input_device_negate:
142                description:
143                    - Enable/disable negation of input device match.
144                type: str
145                choices:
146                    - enable
147                    - disable
148            internet_service_custom:
149                description:
150                    - Custom Destination Internet Service name.
151                type: list
152                suboptions:
153                    name:
154                        description:
155                            - Custom Destination Internet Service name. Source firewall.internet-service-custom.name.
156                        required: true
157                        type: str
158            internet_service_id:
159                description:
160                    - Destination Internet Service ID.
161                type: list
162                suboptions:
163                    id:
164                        description:
165                            - Destination Internet Service ID. Source firewall.internet-service.id.
166                        required: true
167                        type: int
168            output_device:
169                description:
170                    - Outgoing interface name. Source system.interface.name.
171                type: str
172            protocol:
173                description:
174                    - Protocol number (0 - 255).
175                type: int
176            seq_num:
177                description:
178                    - Sequence number.
179                type: int
180            src:
181                description:
182                    - Source IP and mask (x.x.x.x/x).
183                type: list
184                suboptions:
185                    subnet:
186                        description:
187                            - IP and mask.
188                        required: true
189                        type: str
190            src_negate:
191                description:
192                    - Enable/disable negating source address match.
193                type: str
194                choices:
195                    - enable
196                    - disable
197            srcaddr:
198                description:
199                    - Source address name.
200                type: list
201                suboptions:
202                    name:
203                        description:
204                            - Address/group name. Source firewall.address.name firewall.addrgrp.name.
205                        required: true
206                        type: str
207            start_port:
208                description:
209                    - Start destination port number (0 - 65535).
210                type: int
211            start_source_port:
212                description:
213                    - Start source port number (0 - 65535).
214                type: int
215            status:
216                description:
217                    - Enable/disable this policy route.
218                type: str
219                choices:
220                    - enable
221                    - disable
222            tos:
223                description:
224                    - Type of service bit pattern.
225                type: str
226            tos_mask:
227                description:
228                    - Type of service evaluated bits.
229                type: str
230'''
231
232EXAMPLES = '''
233- hosts: fortigates
234  collections:
235    - fortinet.fortios
236  connection: httpapi
237  vars:
238   vdom: "root"
239   ansible_httpapi_use_ssl: yes
240   ansible_httpapi_validate_certs: no
241   ansible_httpapi_port: 443
242  tasks:
243  - name: Configure IPv4 routing policies.
244    fortios_router_policy:
245      vdom:  "{{ vdom }}"
246      state: "present"
247      access_token: "<your_own_value>"
248      router_policy:
249        action: "deny"
250        comments: "<your_own_value>"
251        dst:
252         -
253            subnet: "<your_own_value>"
254        dst_negate: "enable"
255        dstaddr:
256         -
257            name: "default_name_9 (source firewall.address.name firewall.addrgrp.name)"
258        end_port: "10"
259        end_source_port: "11"
260        gateway: "<your_own_value>"
261        input_device:
262         -
263            name: "default_name_14 (source system.interface.name)"
264        input_device_negate: "enable"
265        internet_service_custom:
266         -
267            name: "default_name_17 (source firewall.internet-service-custom.name)"
268        internet_service_id:
269         -
270            id:  "19 (source firewall.internet-service.id)"
271        output_device: "<your_own_value> (source system.interface.name)"
272        protocol: "21"
273        seq_num: "22"
274        src:
275         -
276            subnet: "<your_own_value>"
277        src_negate: "enable"
278        srcaddr:
279         -
280            name: "default_name_27 (source firewall.address.name firewall.addrgrp.name)"
281        start_port: "28"
282        start_source_port: "29"
283        status: "enable"
284        tos: "<your_own_value>"
285        tos_mask: "<your_own_value>"
286
287'''
288
289RETURN = '''
290build:
291  description: Build number of the fortigate image
292  returned: always
293  type: str
294  sample: '1547'
295http_method:
296  description: Last method used to provision the content into FortiGate
297  returned: always
298  type: str
299  sample: 'PUT'
300http_status:
301  description: Last result given by FortiGate on last operation applied
302  returned: always
303  type: str
304  sample: "200"
305mkey:
306  description: Master key (id) used in the last call to FortiGate
307  returned: success
308  type: str
309  sample: "id"
310name:
311  description: Name of the table used to fulfill the request
312  returned: always
313  type: str
314  sample: "urlfilter"
315path:
316  description: Path of the table used to fulfill the request
317  returned: always
318  type: str
319  sample: "webfilter"
320revision:
321  description: Internal revision number
322  returned: always
323  type: str
324  sample: "17.0.2.10658"
325serial:
326  description: Serial number of the unit
327  returned: always
328  type: str
329  sample: "FGVMEVYYQT3AB5352"
330status:
331  description: Indication of the operation's result
332  returned: always
333  type: str
334  sample: "success"
335vdom:
336  description: Virtual domain used
337  returned: always
338  type: str
339  sample: "root"
340version:
341  description: Version of the FortiGate
342  returned: always
343  type: str
344  sample: "v5.6.3"
345
346'''
347from ansible.module_utils.basic import AnsibleModule
348from ansible.module_utils.connection import Connection
349from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
350from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
351from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
352from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
353from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
354from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
355from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize
356
357
358def filter_router_policy_data(json):
359    option_list = ['action', 'comments', 'dst',
360                   'dst_negate', 'dstaddr', 'end_port',
361                   'end_source_port', 'gateway', 'input_device',
362                   'input_device_negate', 'internet_service_custom', 'internet_service_id',
363                   'output_device', 'protocol', 'seq_num',
364                   'src', 'src_negate', 'srcaddr',
365                   'start_port', 'start_source_port', 'status',
366                   'tos', 'tos_mask']
367    dictionary = {}
368
369    for attribute in option_list:
370        if attribute in json and json[attribute] is not None:
371            dictionary[attribute] = json[attribute]
372
373    return dictionary
374
375
376def underscore_to_hyphen(data):
377    if isinstance(data, list):
378        for i, elem in enumerate(data):
379            data[i] = underscore_to_hyphen(elem)
380    elif isinstance(data, dict):
381        new_data = {}
382        for k, v in data.items():
383            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
384        data = new_data
385
386    return data
387
388
389def router_policy(data, fos, check_mode=False):
390
391    vdom = data['vdom']
392
393    state = data['state']
394
395    router_policy_data = data['router_policy']
396    filtered_data = underscore_to_hyphen(filter_router_policy_data(router_policy_data))
397
398    # check_mode starts from here
399    if check_mode:
400        mkey = fos.get_mkey('system', 'interface', filtered_data, vdom=vdom)
401        current_data = fos.get('system', 'interface', vdom=vdom, mkey=mkey)
402        is_existed = current_data and current_data.get('http_status') == 200 \
403            and isinstance(current_data.get('results'), list) \
404            and len(current_data['results']) > 0
405
406        # 2. if it exists and the state is 'present' then compare current settings with desired
407        if state == 'present' or state is True:
408            if mkey is None:
409                return False, True, filtered_data
410
411            # if mkey exists then compare each other
412            # record exits and they're matched or not
413            if is_existed:
414                is_same = is_same_comparison(
415                    serialize(current_data['results'][0]), serialize(filtered_data))
416                return False, not is_same, filtered_data
417
418            # record does not exist
419            return False, True, filtered_data
420
421        if state == 'absent':
422            if mkey is None:
423                return False, False, filtered_data
424
425            if is_existed:
426                return False, True, filtered_data
427            return False, False, filtered_data
428
429        return True, False, {'reason: ': 'Must provide state parameter'}
430
431    if state == "present" or state is True:
432        return fos.set('router',
433                       'policy',
434                       data=filtered_data,
435                       vdom=vdom)
436
437    elif state == "absent":
438        return fos.delete('router',
439                          'policy',
440                          mkey=filtered_data['seq-num'],
441                          vdom=vdom)
442    else:
443        fos._module.fail_json(msg='state must be present or absent!')
444
445
446def is_successful_status(status):
447    return status['status'] == "success" or \
448        status['http_method'] == "DELETE" and status['http_status'] == 404
449
450
451def fortios_router(data, fos, check_mode):
452
453    if data['router_policy']:
454        resp = router_policy(data, fos, check_mode)
455    else:
456        fos._module.fail_json(msg='missing task body: %s' % ('router_policy'))
457    if check_mode:
458        return resp
459    return not is_successful_status(resp), \
460        resp['status'] == "success" and \
461        (resp['revision_changed'] if 'revision_changed' in resp else True), \
462        resp
463
464
465versioned_schema = {
466    "type": "list",
467    "children": {
468        "protocol": {
469            "type": "integer",
470            "revisions": {
471                "v6.0.0": True,
472                "v7.0.0": True,
473                "v6.0.5": True,
474                "v6.4.4": True,
475                "v6.4.0": True,
476                "v6.4.1": True,
477                "v6.2.0": True,
478                "v6.2.3": True,
479                "v6.2.5": True,
480                "v6.2.7": True,
481                "v6.0.11": True
482            }
483        },
484        "end_port": {
485            "type": "integer",
486            "revisions": {
487                "v6.0.0": True,
488                "v7.0.0": True,
489                "v6.0.5": True,
490                "v6.4.4": True,
491                "v6.4.0": True,
492                "v6.4.1": True,
493                "v6.2.0": True,
494                "v6.2.3": True,
495                "v6.2.5": True,
496                "v6.2.7": True,
497                "v6.0.11": True
498            }
499        },
500        "dst_negate": {
501            "type": "string",
502            "options": [
503                {
504                    "value": "enable",
505                    "revisions": {
506                        "v6.0.0": True,
507                        "v7.0.0": True,
508                        "v6.0.5": True,
509                        "v6.4.4": True,
510                        "v6.4.0": True,
511                        "v6.4.1": True,
512                        "v6.2.0": True,
513                        "v6.2.3": True,
514                        "v6.2.5": True,
515                        "v6.2.7": True,
516                        "v6.0.11": True
517                    }
518                },
519                {
520                    "value": "disable",
521                    "revisions": {
522                        "v6.0.0": True,
523                        "v7.0.0": True,
524                        "v6.0.5": True,
525                        "v6.4.4": True,
526                        "v6.4.0": True,
527                        "v6.4.1": True,
528                        "v6.2.0": True,
529                        "v6.2.3": True,
530                        "v6.2.5": True,
531                        "v6.2.7": True,
532                        "v6.0.11": True
533                    }
534                }
535            ],
536            "revisions": {
537                "v6.0.0": True,
538                "v7.0.0": True,
539                "v6.0.5": True,
540                "v6.4.4": True,
541                "v6.4.0": True,
542                "v6.4.1": True,
543                "v6.2.0": True,
544                "v6.2.3": True,
545                "v6.2.5": True,
546                "v6.2.7": True,
547                "v6.0.11": True
548            }
549        },
550        "start_source_port": {
551            "type": "integer",
552            "revisions": {
553                "v6.0.0": True,
554                "v7.0.0": True,
555                "v6.0.5": True,
556                "v6.4.4": True,
557                "v6.4.0": True,
558                "v6.4.1": True,
559                "v6.2.0": True,
560                "v6.2.3": True,
561                "v6.2.5": True,
562                "v6.2.7": True,
563                "v6.0.11": True
564            }
565        },
566        "internet_service_custom": {
567            "type": "list",
568            "children": {
569                "name": {
570                    "type": "string",
571                    "revisions": {
572                        "v7.0.0": True,
573                        "v6.4.4": True,
574                        "v6.4.0": True,
575                        "v6.4.1": True,
576                        "v6.2.0": True,
577                        "v6.2.3": True,
578                        "v6.2.5": True,
579                        "v6.2.7": True
580                    }
581                }
582            },
583            "revisions": {
584                "v7.0.0": True,
585                "v6.4.4": True,
586                "v6.4.0": True,
587                "v6.4.1": True,
588                "v6.2.0": True,
589                "v6.2.3": True,
590                "v6.2.5": True,
591                "v6.2.7": True
592            }
593        },
594        "input_device": {
595            "type": "list",
596            "children": {
597                "name": {
598                    "type": "string",
599                    "revisions": {
600                        "v6.0.0": True,
601                        "v7.0.0": True,
602                        "v6.0.5": True,
603                        "v6.4.4": True,
604                        "v6.4.0": True,
605                        "v6.4.1": True,
606                        "v6.2.0": True,
607                        "v6.2.3": True,
608                        "v6.2.5": True,
609                        "v6.2.7": True,
610                        "v6.0.11": True
611                    }
612                }
613            },
614            "revisions": {
615                "v6.0.0": True,
616                "v7.0.0": True,
617                "v6.0.5": True,
618                "v6.4.4": True,
619                "v6.4.0": True,
620                "v6.4.1": True,
621                "v6.2.0": True,
622                "v6.2.3": True,
623                "v6.2.5": True,
624                "v6.2.7": True,
625                "v6.0.11": True
626            }
627        },
628        "gateway": {
629            "type": "string",
630            "revisions": {
631                "v6.0.0": True,
632                "v7.0.0": True,
633                "v6.0.5": True,
634                "v6.4.4": True,
635                "v6.4.0": True,
636                "v6.4.1": True,
637                "v6.2.0": True,
638                "v6.2.3": True,
639                "v6.2.5": True,
640                "v6.2.7": True,
641                "v6.0.11": True
642            }
643        },
644        "tos": {
645            "type": "string",
646            "revisions": {
647                "v6.0.0": True,
648                "v7.0.0": True,
649                "v6.0.5": True,
650                "v6.4.4": True,
651                "v6.4.0": True,
652                "v6.4.1": True,
653                "v6.2.0": True,
654                "v6.2.3": True,
655                "v6.2.5": True,
656                "v6.2.7": True,
657                "v6.0.11": True
658            }
659        },
660        "dst": {
661            "type": "list",
662            "children": {
663                "subnet": {
664                    "type": "string",
665                    "revisions": {
666                        "v6.0.0": True,
667                        "v7.0.0": True,
668                        "v6.0.5": True,
669                        "v6.4.4": True,
670                        "v6.4.0": True,
671                        "v6.4.1": True,
672                        "v6.2.0": True,
673                        "v6.2.3": True,
674                        "v6.2.5": True,
675                        "v6.2.7": True,
676                        "v6.0.11": True
677                    }
678                }
679            },
680            "revisions": {
681                "v6.0.0": True,
682                "v7.0.0": True,
683                "v6.0.5": True,
684                "v6.4.4": True,
685                "v6.4.0": True,
686                "v6.4.1": True,
687                "v6.2.0": True,
688                "v6.2.3": True,
689                "v6.2.5": True,
690                "v6.2.7": True,
691                "v6.0.11": True
692            }
693        },
694        "input_device_negate": {
695            "type": "string",
696            "options": [
697                {
698                    "value": "enable",
699                    "revisions": {
700                        "v7.0.0": True,
701                        "v6.4.4": True,
702                        "v6.4.0": True,
703                        "v6.4.1": True,
704                        "v6.2.0": True,
705                        "v6.2.3": True,
706                        "v6.2.5": True,
707                        "v6.2.7": True
708                    }
709                },
710                {
711                    "value": "disable",
712                    "revisions": {
713                        "v7.0.0": True,
714                        "v6.4.4": True,
715                        "v6.4.0": True,
716                        "v6.4.1": True,
717                        "v6.2.0": True,
718                        "v6.2.3": True,
719                        "v6.2.5": True,
720                        "v6.2.7": True
721                    }
722                }
723            ],
724            "revisions": {
725                "v7.0.0": True,
726                "v6.4.4": True,
727                "v6.4.0": True,
728                "v6.4.1": True,
729                "v6.2.0": True,
730                "v6.2.3": True,
731                "v6.2.5": True,
732                "v6.2.7": True
733            }
734        },
735        "comments": {
736            "type": "string",
737            "revisions": {
738                "v6.0.0": True,
739                "v7.0.0": True,
740                "v6.0.5": True,
741                "v6.4.4": True,
742                "v6.4.0": True,
743                "v6.4.1": True,
744                "v6.2.0": True,
745                "v6.2.3": True,
746                "v6.2.5": True,
747                "v6.2.7": True,
748                "v6.0.11": True
749            }
750        },
751        "status": {
752            "type": "string",
753            "options": [
754                {
755                    "value": "enable",
756                    "revisions": {
757                        "v6.0.0": True,
758                        "v7.0.0": True,
759                        "v6.0.5": True,
760                        "v6.4.4": True,
761                        "v6.4.0": True,
762                        "v6.4.1": True,
763                        "v6.2.0": True,
764                        "v6.2.3": True,
765                        "v6.2.5": True,
766                        "v6.2.7": True,
767                        "v6.0.11": True
768                    }
769                },
770                {
771                    "value": "disable",
772                    "revisions": {
773                        "v6.0.0": True,
774                        "v7.0.0": True,
775                        "v6.0.5": True,
776                        "v6.4.4": True,
777                        "v6.4.0": True,
778                        "v6.4.1": True,
779                        "v6.2.0": True,
780                        "v6.2.3": True,
781                        "v6.2.5": True,
782                        "v6.2.7": True,
783                        "v6.0.11": True
784                    }
785                }
786            ],
787            "revisions": {
788                "v6.0.0": True,
789                "v7.0.0": True,
790                "v6.0.5": True,
791                "v6.4.4": True,
792                "v6.4.0": True,
793                "v6.4.1": True,
794                "v6.2.0": True,
795                "v6.2.3": True,
796                "v6.2.5": True,
797                "v6.2.7": True,
798                "v6.0.11": True
799            }
800        },
801        "start_port": {
802            "type": "integer",
803            "revisions": {
804                "v6.0.0": True,
805                "v7.0.0": True,
806                "v6.0.5": True,
807                "v6.4.4": True,
808                "v6.4.0": True,
809                "v6.4.1": True,
810                "v6.2.0": True,
811                "v6.2.3": True,
812                "v6.2.5": True,
813                "v6.2.7": True,
814                "v6.0.11": True
815            }
816        },
817        "srcaddr": {
818            "type": "list",
819            "children": {
820                "name": {
821                    "type": "string",
822                    "revisions": {
823                        "v6.0.0": True,
824                        "v7.0.0": True,
825                        "v6.0.5": True,
826                        "v6.4.4": True,
827                        "v6.4.0": True,
828                        "v6.4.1": True,
829                        "v6.2.0": True,
830                        "v6.2.3": True,
831                        "v6.2.5": True,
832                        "v6.2.7": True,
833                        "v6.0.11": True
834                    }
835                }
836            },
837            "revisions": {
838                "v6.0.0": True,
839                "v7.0.0": True,
840                "v6.0.5": True,
841                "v6.4.4": True,
842                "v6.4.0": True,
843                "v6.4.1": True,
844                "v6.2.0": True,
845                "v6.2.3": True,
846                "v6.2.5": True,
847                "v6.2.7": True,
848                "v6.0.11": True
849            }
850        },
851        "tos_mask": {
852            "type": "string",
853            "revisions": {
854                "v6.0.0": True,
855                "v7.0.0": True,
856                "v6.0.5": True,
857                "v6.4.4": True,
858                "v6.4.0": True,
859                "v6.4.1": True,
860                "v6.2.0": True,
861                "v6.2.3": True,
862                "v6.2.5": True,
863                "v6.2.7": True,
864                "v6.0.11": True
865            }
866        },
867        "src": {
868            "type": "list",
869            "children": {
870                "subnet": {
871                    "type": "string",
872                    "revisions": {
873                        "v6.0.0": True,
874                        "v7.0.0": True,
875                        "v6.0.5": True,
876                        "v6.4.4": True,
877                        "v6.4.0": True,
878                        "v6.4.1": True,
879                        "v6.2.0": True,
880                        "v6.2.3": True,
881                        "v6.2.5": True,
882                        "v6.2.7": True,
883                        "v6.0.11": True
884                    }
885                }
886            },
887            "revisions": {
888                "v6.0.0": True,
889                "v7.0.0": True,
890                "v6.0.5": True,
891                "v6.4.4": True,
892                "v6.4.0": True,
893                "v6.4.1": True,
894                "v6.2.0": True,
895                "v6.2.3": True,
896                "v6.2.5": True,
897                "v6.2.7": True,
898                "v6.0.11": True
899            }
900        },
901        "seq_num": {
902            "type": "integer",
903            "revisions": {
904                "v6.0.0": True,
905                "v7.0.0": True,
906                "v6.0.5": True,
907                "v6.4.4": True,
908                "v6.4.0": True,
909                "v6.4.1": True,
910                "v6.2.0": True,
911                "v6.2.3": True,
912                "v6.2.5": True,
913                "v6.2.7": True,
914                "v6.0.11": True
915            }
916        },
917        "internet_service_id": {
918            "type": "list",
919            "children": {
920                "id": {
921                    "type": "integer",
922                    "revisions": {
923                        "v7.0.0": True,
924                        "v6.4.4": True,
925                        "v6.4.0": True,
926                        "v6.4.1": True,
927                        "v6.2.0": True,
928                        "v6.2.3": True,
929                        "v6.2.5": True,
930                        "v6.2.7": True
931                    }
932                }
933            },
934            "revisions": {
935                "v7.0.0": True,
936                "v6.4.4": True,
937                "v6.4.0": True,
938                "v6.4.1": True,
939                "v6.2.0": True,
940                "v6.2.3": True,
941                "v6.2.5": True,
942                "v6.2.7": True
943            }
944        },
945        "src_negate": {
946            "type": "string",
947            "options": [
948                {
949                    "value": "enable",
950                    "revisions": {
951                        "v6.0.0": True,
952                        "v7.0.0": True,
953                        "v6.0.5": True,
954                        "v6.4.4": True,
955                        "v6.4.0": True,
956                        "v6.4.1": True,
957                        "v6.2.0": True,
958                        "v6.2.3": True,
959                        "v6.2.5": True,
960                        "v6.2.7": True,
961                        "v6.0.11": True
962                    }
963                },
964                {
965                    "value": "disable",
966                    "revisions": {
967                        "v6.0.0": True,
968                        "v7.0.0": True,
969                        "v6.0.5": True,
970                        "v6.4.4": True,
971                        "v6.4.0": True,
972                        "v6.4.1": True,
973                        "v6.2.0": True,
974                        "v6.2.3": True,
975                        "v6.2.5": True,
976                        "v6.2.7": True,
977                        "v6.0.11": True
978                    }
979                }
980            ],
981            "revisions": {
982                "v6.0.0": True,
983                "v7.0.0": True,
984                "v6.0.5": True,
985                "v6.4.4": True,
986                "v6.4.0": True,
987                "v6.4.1": True,
988                "v6.2.0": True,
989                "v6.2.3": True,
990                "v6.2.5": True,
991                "v6.2.7": True,
992                "v6.0.11": True
993            }
994        },
995        "action": {
996            "type": "string",
997            "options": [
998                {
999                    "value": "deny",
1000                    "revisions": {
1001                        "v6.0.0": True,
1002                        "v7.0.0": True,
1003                        "v6.0.5": True,
1004                        "v6.4.4": True,
1005                        "v6.4.0": True,
1006                        "v6.4.1": True,
1007                        "v6.2.0": True,
1008                        "v6.2.3": True,
1009                        "v6.2.5": True,
1010                        "v6.2.7": True,
1011                        "v6.0.11": True
1012                    }
1013                },
1014                {
1015                    "value": "permit",
1016                    "revisions": {
1017                        "v6.0.0": True,
1018                        "v7.0.0": True,
1019                        "v6.0.5": True,
1020                        "v6.4.4": True,
1021                        "v6.4.0": True,
1022                        "v6.4.1": True,
1023                        "v6.2.0": True,
1024                        "v6.2.3": True,
1025                        "v6.2.5": True,
1026                        "v6.2.7": True,
1027                        "v6.0.11": True
1028                    }
1029                }
1030            ],
1031            "revisions": {
1032                "v6.0.0": True,
1033                "v7.0.0": True,
1034                "v6.0.5": True,
1035                "v6.4.4": True,
1036                "v6.4.0": True,
1037                "v6.4.1": True,
1038                "v6.2.0": True,
1039                "v6.2.3": True,
1040                "v6.2.5": True,
1041                "v6.2.7": True,
1042                "v6.0.11": True
1043            }
1044        },
1045        "end_source_port": {
1046            "type": "integer",
1047            "revisions": {
1048                "v6.0.0": True,
1049                "v7.0.0": True,
1050                "v6.0.5": True,
1051                "v6.4.4": True,
1052                "v6.4.0": True,
1053                "v6.4.1": True,
1054                "v6.2.0": True,
1055                "v6.2.3": True,
1056                "v6.2.5": True,
1057                "v6.2.7": True,
1058                "v6.0.11": True
1059            }
1060        },
1061        "dstaddr": {
1062            "type": "list",
1063            "children": {
1064                "name": {
1065                    "type": "string",
1066                    "revisions": {
1067                        "v6.0.0": True,
1068                        "v7.0.0": True,
1069                        "v6.0.5": True,
1070                        "v6.4.4": True,
1071                        "v6.4.0": True,
1072                        "v6.4.1": True,
1073                        "v6.2.0": True,
1074                        "v6.2.3": True,
1075                        "v6.2.5": True,
1076                        "v6.2.7": True,
1077                        "v6.0.11": True
1078                    }
1079                }
1080            },
1081            "revisions": {
1082                "v6.0.0": True,
1083                "v7.0.0": True,
1084                "v6.0.5": True,
1085                "v6.4.4": True,
1086                "v6.4.0": True,
1087                "v6.4.1": True,
1088                "v6.2.0": True,
1089                "v6.2.3": True,
1090                "v6.2.5": True,
1091                "v6.2.7": True,
1092                "v6.0.11": True
1093            }
1094        },
1095        "output_device": {
1096            "type": "string",
1097            "revisions": {
1098                "v6.0.0": True,
1099                "v7.0.0": True,
1100                "v6.0.5": True,
1101                "v6.4.4": True,
1102                "v6.4.0": True,
1103                "v6.4.1": True,
1104                "v6.2.0": True,
1105                "v6.2.3": True,
1106                "v6.2.5": True,
1107                "v6.2.7": True,
1108                "v6.0.11": True
1109            }
1110        }
1111    },
1112    "revisions": {
1113        "v6.0.0": True,
1114        "v7.0.0": True,
1115        "v6.0.5": True,
1116        "v6.4.4": True,
1117        "v6.4.0": True,
1118        "v6.4.1": True,
1119        "v6.2.0": True,
1120        "v6.2.3": True,
1121        "v6.2.5": True,
1122        "v6.2.7": True,
1123        "v6.0.11": True
1124    }
1125}
1126
1127
1128def main():
1129    module_spec = schema_to_module_spec(versioned_schema)
1130    mkeyname = 'seq-num'
1131    fields = {
1132        "access_token": {"required": False, "type": "str", "no_log": True},
1133        "enable_log": {"required": False, "type": bool},
1134        "vdom": {"required": False, "type": "str", "default": "root"},
1135        "state": {"required": True, "type": "str",
1136                  "choices": ["present", "absent"]},
1137        "router_policy": {
1138            "required": False, "type": "dict", "default": None,
1139            "options": {
1140            }
1141        }
1142    }
1143    for attribute_name in module_spec['options']:
1144        fields["router_policy"]['options'][attribute_name] = module_spec['options'][attribute_name]
1145        if mkeyname and mkeyname == attribute_name:
1146            fields["router_policy"]['options'][attribute_name]['required'] = True
1147
1148    check_legacy_fortiosapi()
1149    module = AnsibleModule(argument_spec=fields,
1150                           supports_check_mode=True)
1151
1152    versions_check_result = None
1153    if module._socket_path:
1154        connection = Connection(module._socket_path)
1155        if 'access_token' in module.params:
1156            connection.set_option('access_token', module.params['access_token'])
1157
1158        if 'enable_log' in module.params:
1159            connection.set_option('enable_log', module.params['enable_log'])
1160        else:
1161            connection.set_option('enable_log', False)
1162        fos = FortiOSHandler(connection, module, mkeyname)
1163        versions_check_result = check_schema_versioning(fos, versioned_schema, "router_policy")
1164
1165        is_error, has_changed, result = fortios_router(module.params, fos, module.check_mode)
1166
1167    else:
1168        module.fail_json(**FAIL_SOCKET_MSG)
1169
1170    if versions_check_result and versions_check_result['matched'] is False:
1171        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")
1172
1173    if not is_error:
1174        if versions_check_result and versions_check_result['matched'] is False:
1175            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
1176        else:
1177            module.exit_json(changed=has_changed, meta=result)
1178    else:
1179        if versions_check_result and versions_check_result['matched'] is False:
1180            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
1181        else:
1182            module.fail_json(msg="Error in repo", meta=result)
1183
1184
1185if __name__ == '__main__':
1186    main()
1187