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_system_wccp
27short_description: Configure WCCP 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 system feature and wccp 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    system_wccp:
76        description:
77            - Configure WCCP.
78        default: null
79        type: dict
80        suboptions:
81            assignment_bucket_format:
82                description:
83                    - Assignment bucket format for the WCCP cache engine.
84                type: str
85                choices:
86                    - wccp-v2
87                    - cisco-implementation
88            assignment_dstaddr_mask:
89                description:
90                    - Assignment destination address mask.
91                type: str
92            assignment_method:
93                description:
94                    - Hash key assignment preference.
95                type: str
96                choices:
97                    - HASH
98                    - MASK
99                    - any
100            assignment_srcaddr_mask:
101                description:
102                    - Assignment source address mask.
103                type: str
104            assignment_weight:
105                description:
106                    - Assignment of hash weight/ratio for the WCCP cache engine.
107                type: int
108            authentication:
109                description:
110                    - Enable/disable MD5 authentication.
111                type: str
112                choices:
113                    - enable
114                    - disable
115            cache_engine_method:
116                description:
117                    - Method used to forward traffic to the routers or to return to the cache engine.
118                type: str
119                choices:
120                    - GRE
121                    - L2
122            cache_id:
123                description:
124                    - IP address known to all routers. If the addresses are the same, use the default 0.0.0.0.
125                type: str
126            forward_method:
127                description:
128                    - Method used to forward traffic to the cache servers.
129                type: str
130                choices:
131                    - GRE
132                    - L2
133                    - any
134            group_address:
135                description:
136                    - IP multicast address used by the cache routers. For the FortiGate to ignore multicast WCCP traffic, use the default 0.0.0.0.
137                type: str
138            password:
139                description:
140                    - Password for MD5 authentication.
141                type: str
142            ports:
143                description:
144                    - Service ports.
145                type: str
146            ports_defined:
147                description:
148                    - Match method.
149                type: str
150                choices:
151                    - source
152                    - destination
153            primary_hash:
154                description:
155                    - Hash method.
156                type: list
157                choices:
158                    - src-ip
159                    - dst-ip
160                    - src-port
161                    - dst-port
162            priority:
163                description:
164                    - Service priority.
165                type: int
166            protocol:
167                description:
168                    - Service protocol.
169                type: int
170            return_method:
171                description:
172                    -  Method used to decline a redirected packet and return it to the FortiGate.
173                type: str
174                choices:
175                    - GRE
176                    - L2
177                    - any
178            router_id:
179                description:
180                    - IP address known to all cache engines. If all cache engines connect to the same FortiGate interface, use the default 0.0.0.0.
181                type: str
182            router_list:
183                description:
184                    - IP addresses of one or more WCCP routers.
185                type: str
186            server_list:
187                description:
188                    - IP addresses and netmasks for up to four cache servers.
189                type: str
190            server_type:
191                description:
192                    - Cache server type.
193                type: str
194                choices:
195                    - forward
196                    - proxy
197            service_id:
198                description:
199                    - Service ID.
200                type: str
201            service_type:
202                description:
203                    - WCCP service type used by the cache server for logical interception and redirection of traffic.
204                type: str
205                choices:
206                    - auto
207                    - standard
208                    - dynamic
209'''
210
211EXAMPLES = '''
212- hosts: fortigates
213  collections:
214    - fortinet.fortios
215  connection: httpapi
216  vars:
217   vdom: "root"
218   ansible_httpapi_use_ssl: yes
219   ansible_httpapi_validate_certs: no
220   ansible_httpapi_port: 443
221  tasks:
222  - name: Configure WCCP.
223    fortios_system_wccp:
224      vdom:  "{{ vdom }}"
225      state: "present"
226      access_token: "<your_own_value>"
227      system_wccp:
228        assignment_bucket_format: "wccp-v2"
229        assignment_dstaddr_mask: "<your_own_value>"
230        assignment_method: "HASH"
231        assignment_srcaddr_mask: "<your_own_value>"
232        assignment_weight: "7"
233        authentication: "enable"
234        cache_engine_method: "GRE"
235        cache_id: "<your_own_value>"
236        forward_method: "GRE"
237        group_address: "<your_own_value>"
238        password: "<your_own_value>"
239        ports: "<your_own_value>"
240        ports_defined: "source"
241        primary_hash: "src-ip"
242        priority: "17"
243        protocol: "18"
244        return_method: "GRE"
245        router_id: "<your_own_value>"
246        router_list: "<your_own_value>"
247        server_list: "<your_own_value>"
248        server_type: "forward"
249        service_id: "<your_own_value>"
250        service_type: "auto"
251
252'''
253
254RETURN = '''
255build:
256  description: Build number of the fortigate image
257  returned: always
258  type: str
259  sample: '1547'
260http_method:
261  description: Last method used to provision the content into FortiGate
262  returned: always
263  type: str
264  sample: 'PUT'
265http_status:
266  description: Last result given by FortiGate on last operation applied
267  returned: always
268  type: str
269  sample: "200"
270mkey:
271  description: Master key (id) used in the last call to FortiGate
272  returned: success
273  type: str
274  sample: "id"
275name:
276  description: Name of the table used to fulfill the request
277  returned: always
278  type: str
279  sample: "urlfilter"
280path:
281  description: Path of the table used to fulfill the request
282  returned: always
283  type: str
284  sample: "webfilter"
285revision:
286  description: Internal revision number
287  returned: always
288  type: str
289  sample: "17.0.2.10658"
290serial:
291  description: Serial number of the unit
292  returned: always
293  type: str
294  sample: "FGVMEVYYQT3AB5352"
295status:
296  description: Indication of the operation's result
297  returned: always
298  type: str
299  sample: "success"
300vdom:
301  description: Virtual domain used
302  returned: always
303  type: str
304  sample: "root"
305version:
306  description: Version of the FortiGate
307  returned: always
308  type: str
309  sample: "v5.6.3"
310
311'''
312from ansible.module_utils.basic import AnsibleModule
313from ansible.module_utils.connection import Connection
314from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import FortiOSHandler
315from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_legacy_fortiosapi
316from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import schema_to_module_spec
317from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.fortios import check_schema_versioning
318from ansible_collections.fortinet.fortios.plugins.module_utils.fortimanager.common import FAIL_SOCKET_MSG
319from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import is_same_comparison
320from ansible_collections.fortinet.fortios.plugins.module_utils.fortios.comparison import serialize
321
322
323def filter_system_wccp_data(json):
324    option_list = ['assignment_bucket_format', 'assignment_dstaddr_mask', 'assignment_method',
325                   'assignment_srcaddr_mask', 'assignment_weight', 'authentication',
326                   'cache_engine_method', 'cache_id', 'forward_method',
327                   'group_address', 'password', 'ports',
328                   'ports_defined', 'primary_hash', 'priority',
329                   'protocol', 'return_method', 'router_id',
330                   'router_list', 'server_list', 'server_type',
331                   'service_id', 'service_type']
332    dictionary = {}
333
334    for attribute in option_list:
335        if attribute in json and json[attribute] is not None:
336            dictionary[attribute] = json[attribute]
337
338    return dictionary
339
340
341def flatten_single_path(data, path, index):
342    if not data or index == len(path) or path[index] not in data or not data[path[index]]:
343        return
344
345    if index == len(path) - 1:
346        data[path[index]] = ' '.join(str(elem) for elem in data[path[index]])
347    elif isinstance(data[path[index]], list):
348        for value in data[path[index]]:
349            flatten_single_path(value, path, index + 1)
350    else:
351        flatten_single_path(data[path[index]], path, index + 1)
352
353
354def flatten_multilists_attributes(data):
355    multilist_attrs = [[u'primary_hash']]
356
357    for attr in multilist_attrs:
358        flatten_single_path(data, attr, 0)
359
360    return data
361
362
363def underscore_to_hyphen(data):
364    if isinstance(data, list):
365        for i, elem in enumerate(data):
366            data[i] = underscore_to_hyphen(elem)
367    elif isinstance(data, dict):
368        new_data = {}
369        for k, v in data.items():
370            new_data[k.replace('_', '-')] = underscore_to_hyphen(v)
371        data = new_data
372
373    return data
374
375
376def system_wccp(data, fos, check_mode=False):
377
378    vdom = data['vdom']
379
380    state = data['state']
381
382    system_wccp_data = data['system_wccp']
383    system_wccp_data = flatten_multilists_attributes(system_wccp_data)
384    filtered_data = underscore_to_hyphen(filter_system_wccp_data(system_wccp_data))
385
386    # check_mode starts from here
387    if check_mode:
388        mkey = fos.get_mkey('system', 'interface', filtered_data, vdom=vdom)
389        current_data = fos.get('system', 'interface', vdom=vdom, mkey=mkey)
390        is_existed = current_data and current_data.get('http_status') == 200 \
391            and isinstance(current_data.get('results'), list) \
392            and len(current_data['results']) > 0
393
394        # 2. if it exists and the state is 'present' then compare current settings with desired
395        if state == 'present' or state is True:
396            if mkey is None:
397                return False, True, filtered_data
398
399            # if mkey exists then compare each other
400            # record exits and they're matched or not
401            if is_existed:
402                is_same = is_same_comparison(
403                    serialize(current_data['results'][0]), serialize(filtered_data))
404                return False, not is_same, filtered_data
405
406            # record does not exist
407            return False, True, filtered_data
408
409        if state == 'absent':
410            if mkey is None:
411                return False, False, filtered_data
412
413            if is_existed:
414                return False, True, filtered_data
415            return False, False, filtered_data
416
417        return True, False, {'reason: ': 'Must provide state parameter'}
418
419    if state == "present" or state is True:
420        return fos.set('system',
421                       'wccp',
422                       data=filtered_data,
423                       vdom=vdom)
424
425    elif state == "absent":
426        return fos.delete('system',
427                          'wccp',
428                          mkey=filtered_data['service-id'],
429                          vdom=vdom)
430    else:
431        fos._module.fail_json(msg='state must be present or absent!')
432
433
434def is_successful_status(status):
435    return status['status'] == "success" or \
436        status['http_method'] == "DELETE" and status['http_status'] == 404
437
438
439def fortios_system(data, fos, check_mode):
440
441    if data['system_wccp']:
442        resp = system_wccp(data, fos, check_mode)
443    else:
444        fos._module.fail_json(msg='missing task body: %s' % ('system_wccp'))
445    if check_mode:
446        return resp
447    return not is_successful_status(resp), \
448        resp['status'] == "success" and \
449        (resp['revision_changed'] if 'revision_changed' in resp else True), \
450        resp
451
452
453versioned_schema = {
454    "type": "list",
455    "children": {
456        "protocol": {
457            "type": "integer",
458            "revisions": {
459                "v6.0.0": True,
460                "v7.0.0": True,
461                "v6.0.5": True,
462                "v6.4.4": True,
463                "v6.4.0": True,
464                "v6.4.1": True,
465                "v6.2.0": True,
466                "v6.2.3": True,
467                "v6.2.5": True,
468                "v6.2.7": True,
469                "v6.0.11": True
470            }
471        },
472        "cache_id": {
473            "type": "string",
474            "revisions": {
475                "v6.0.0": True,
476                "v7.0.0": True,
477                "v6.0.5": True,
478                "v6.4.4": True,
479                "v6.4.0": True,
480                "v6.4.1": True,
481                "v6.2.0": True,
482                "v6.2.3": True,
483                "v6.2.5": True,
484                "v6.2.7": True,
485                "v6.0.11": True
486            }
487        },
488        "assignment_weight": {
489            "type": "integer",
490            "revisions": {
491                "v6.0.0": True,
492                "v7.0.0": True,
493                "v6.0.5": True,
494                "v6.4.4": True,
495                "v6.4.0": True,
496                "v6.4.1": True,
497                "v6.2.0": True,
498                "v6.2.3": True,
499                "v6.2.5": True,
500                "v6.2.7": True,
501                "v6.0.11": True
502            }
503        },
504        "assignment_srcaddr_mask": {
505            "type": "string",
506            "revisions": {
507                "v6.0.0": True,
508                "v7.0.0": True,
509                "v6.0.5": True,
510                "v6.4.4": True,
511                "v6.4.0": True,
512                "v6.4.1": True,
513                "v6.2.0": True,
514                "v6.2.3": True,
515                "v6.2.5": True,
516                "v6.2.7": True,
517                "v6.0.11": True
518            }
519        },
520        "priority": {
521            "type": "integer",
522            "revisions": {
523                "v6.0.0": True,
524                "v7.0.0": True,
525                "v6.0.5": True,
526                "v6.4.4": True,
527                "v6.4.0": True,
528                "v6.4.1": True,
529                "v6.2.0": True,
530                "v6.2.3": True,
531                "v6.2.5": True,
532                "v6.2.7": True,
533                "v6.0.11": True
534            }
535        },
536        "authentication": {
537            "type": "string",
538            "options": [
539                {
540                    "value": "enable",
541                    "revisions": {
542                        "v6.0.0": True,
543                        "v7.0.0": True,
544                        "v6.0.5": True,
545                        "v6.4.4": True,
546                        "v6.4.0": True,
547                        "v6.4.1": True,
548                        "v6.2.0": True,
549                        "v6.2.3": True,
550                        "v6.2.5": True,
551                        "v6.2.7": True,
552                        "v6.0.11": True
553                    }
554                },
555                {
556                    "value": "disable",
557                    "revisions": {
558                        "v6.0.0": True,
559                        "v7.0.0": True,
560                        "v6.0.5": True,
561                        "v6.4.4": True,
562                        "v6.4.0": True,
563                        "v6.4.1": True,
564                        "v6.2.0": True,
565                        "v6.2.3": True,
566                        "v6.2.5": True,
567                        "v6.2.7": True,
568                        "v6.0.11": True
569                    }
570                }
571            ],
572            "revisions": {
573                "v6.0.0": True,
574                "v7.0.0": True,
575                "v6.0.5": True,
576                "v6.4.4": True,
577                "v6.4.0": True,
578                "v6.4.1": True,
579                "v6.2.0": True,
580                "v6.2.3": True,
581                "v6.2.5": True,
582                "v6.2.7": True,
583                "v6.0.11": True
584            }
585        },
586        "return_method": {
587            "type": "string",
588            "options": [
589                {
590                    "value": "GRE",
591                    "revisions": {
592                        "v6.0.0": True,
593                        "v7.0.0": True,
594                        "v6.0.5": True,
595                        "v6.4.4": True,
596                        "v6.4.0": True,
597                        "v6.4.1": True,
598                        "v6.2.0": True,
599                        "v6.2.3": True,
600                        "v6.2.5": True,
601                        "v6.2.7": True,
602                        "v6.0.11": True
603                    }
604                },
605                {
606                    "value": "L2",
607                    "revisions": {
608                        "v6.0.0": True,
609                        "v7.0.0": True,
610                        "v6.0.5": True,
611                        "v6.4.4": True,
612                        "v6.4.0": True,
613                        "v6.4.1": True,
614                        "v6.2.0": True,
615                        "v6.2.3": True,
616                        "v6.2.5": True,
617                        "v6.2.7": True,
618                        "v6.0.11": True
619                    }
620                },
621                {
622                    "value": "any",
623                    "revisions": {
624                        "v6.0.0": True,
625                        "v7.0.0": True,
626                        "v6.0.5": True,
627                        "v6.4.4": True,
628                        "v6.4.0": True,
629                        "v6.4.1": True,
630                        "v6.2.0": True,
631                        "v6.2.3": True,
632                        "v6.2.5": True,
633                        "v6.2.7": True,
634                        "v6.0.11": True
635                    }
636                }
637            ],
638            "revisions": {
639                "v6.0.0": True,
640                "v7.0.0": True,
641                "v6.0.5": True,
642                "v6.4.4": True,
643                "v6.4.0": True,
644                "v6.4.1": True,
645                "v6.2.0": True,
646                "v6.2.3": True,
647                "v6.2.5": True,
648                "v6.2.7": True,
649                "v6.0.11": True
650            }
651        },
652        "assignment_dstaddr_mask": {
653            "type": "string",
654            "revisions": {
655                "v6.0.0": True,
656                "v7.0.0": True,
657                "v6.0.5": True,
658                "v6.4.4": True,
659                "v6.4.0": True,
660                "v6.4.1": True,
661                "v6.2.0": True,
662                "v6.2.3": True,
663                "v6.2.5": True,
664                "v6.2.7": True,
665                "v6.0.11": True
666            }
667        },
668        "service_type": {
669            "type": "string",
670            "options": [
671                {
672                    "value": "auto",
673                    "revisions": {
674                        "v6.0.0": True,
675                        "v7.0.0": True,
676                        "v6.0.5": True,
677                        "v6.4.4": True,
678                        "v6.4.0": True,
679                        "v6.4.1": True,
680                        "v6.2.0": True,
681                        "v6.2.3": True,
682                        "v6.2.5": True,
683                        "v6.2.7": True,
684                        "v6.0.11": True
685                    }
686                },
687                {
688                    "value": "standard",
689                    "revisions": {
690                        "v6.0.0": True,
691                        "v7.0.0": True,
692                        "v6.0.5": True,
693                        "v6.4.4": True,
694                        "v6.4.0": True,
695                        "v6.4.1": True,
696                        "v6.2.0": True,
697                        "v6.2.3": True,
698                        "v6.2.5": True,
699                        "v6.2.7": True,
700                        "v6.0.11": True
701                    }
702                },
703                {
704                    "value": "dynamic",
705                    "revisions": {
706                        "v6.0.0": True,
707                        "v7.0.0": True,
708                        "v6.0.5": True,
709                        "v6.4.4": True,
710                        "v6.4.0": True,
711                        "v6.4.1": True,
712                        "v6.2.0": True,
713                        "v6.2.3": True,
714                        "v6.2.5": True,
715                        "v6.2.7": True,
716                        "v6.0.11": True
717                    }
718                }
719            ],
720            "revisions": {
721                "v6.0.0": True,
722                "v7.0.0": True,
723                "v6.0.5": True,
724                "v6.4.4": True,
725                "v6.4.0": True,
726                "v6.4.1": True,
727                "v6.2.0": True,
728                "v6.2.3": True,
729                "v6.2.5": True,
730                "v6.2.7": True,
731                "v6.0.11": True
732            }
733        },
734        "router_list": {
735            "type": "string",
736            "revisions": {
737                "v6.0.0": True,
738                "v7.0.0": True,
739                "v6.0.5": True,
740                "v6.4.4": True,
741                "v6.4.0": True,
742                "v6.4.1": True,
743                "v6.2.0": True,
744                "v6.2.3": True,
745                "v6.2.5": True,
746                "v6.2.7": True,
747                "v6.0.11": True
748            }
749        },
750        "router_id": {
751            "type": "string",
752            "revisions": {
753                "v6.0.0": True,
754                "v7.0.0": True,
755                "v6.0.5": True,
756                "v6.4.4": True,
757                "v6.4.0": True,
758                "v6.4.1": True,
759                "v6.2.0": True,
760                "v6.2.3": True,
761                "v6.2.5": True,
762                "v6.2.7": True,
763                "v6.0.11": True
764            }
765        },
766        "group_address": {
767            "type": "string",
768            "revisions": {
769                "v6.0.0": True,
770                "v7.0.0": True,
771                "v6.0.5": True,
772                "v6.4.4": True,
773                "v6.4.0": True,
774                "v6.4.1": True,
775                "v6.2.0": True,
776                "v6.2.3": True,
777                "v6.2.5": True,
778                "v6.2.7": True,
779                "v6.0.11": True
780            }
781        },
782        "server_type": {
783            "type": "string",
784            "options": [
785                {
786                    "value": "forward",
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                {
802                    "value": "proxy",
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            ],
818            "revisions": {
819                "v6.0.0": True,
820                "v7.0.0": True,
821                "v6.0.5": True,
822                "v6.4.4": True,
823                "v6.4.0": True,
824                "v6.4.1": True,
825                "v6.2.0": True,
826                "v6.2.3": True,
827                "v6.2.5": True,
828                "v6.2.7": True,
829                "v6.0.11": True
830            }
831        },
832        "assignment_bucket_format": {
833            "type": "string",
834            "options": [
835                {
836                    "value": "wccp-v2",
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                {
852                    "value": "cisco-implementation",
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            ],
868            "revisions": {
869                "v6.0.0": True,
870                "v7.0.0": True,
871                "v6.0.5": True,
872                "v6.4.4": True,
873                "v6.4.0": True,
874                "v6.4.1": True,
875                "v6.2.0": True,
876                "v6.2.3": True,
877                "v6.2.5": True,
878                "v6.2.7": True,
879                "v6.0.11": True
880            }
881        },
882        "assignment_method": {
883            "type": "string",
884            "options": [
885                {
886                    "value": "HASH",
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                {
902                    "value": "MASK",
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                {
918                    "value": "any",
919                    "revisions": {
920                        "v6.0.0": True,
921                        "v7.0.0": True,
922                        "v6.0.5": True,
923                        "v6.4.4": True,
924                        "v6.4.0": True,
925                        "v6.4.1": True,
926                        "v6.2.0": True,
927                        "v6.2.3": True,
928                        "v6.2.5": True,
929                        "v6.2.7": True,
930                        "v6.0.11": True
931                    }
932                }
933            ],
934            "revisions": {
935                "v6.0.0": True,
936                "v7.0.0": True,
937                "v6.0.5": True,
938                "v6.4.4": True,
939                "v6.4.0": True,
940                "v6.4.1": True,
941                "v6.2.0": True,
942                "v6.2.3": True,
943                "v6.2.5": True,
944                "v6.2.7": True,
945                "v6.0.11": True
946            }
947        },
948        "password": {
949            "type": "string",
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        "primary_hash": {
965            "multiple_values": True,
966            "type": "list",
967            "options": [
968                {
969                    "value": "src-ip",
970                    "revisions": {
971                        "v6.0.0": True,
972                        "v7.0.0": True,
973                        "v6.0.5": True,
974                        "v6.4.4": True,
975                        "v6.4.0": True,
976                        "v6.4.1": True,
977                        "v6.2.0": True,
978                        "v6.2.3": True,
979                        "v6.2.5": True,
980                        "v6.2.7": True,
981                        "v6.0.11": True
982                    }
983                },
984                {
985                    "value": "dst-ip",
986                    "revisions": {
987                        "v6.0.0": True,
988                        "v7.0.0": True,
989                        "v6.0.5": True,
990                        "v6.4.4": True,
991                        "v6.4.0": True,
992                        "v6.4.1": True,
993                        "v6.2.0": True,
994                        "v6.2.3": True,
995                        "v6.2.5": True,
996                        "v6.2.7": True,
997                        "v6.0.11": True
998                    }
999                },
1000                {
1001                    "value": "src-port",
1002                    "revisions": {
1003                        "v6.0.0": True,
1004                        "v7.0.0": True,
1005                        "v6.0.5": True,
1006                        "v6.4.4": True,
1007                        "v6.4.0": True,
1008                        "v6.4.1": True,
1009                        "v6.2.0": True,
1010                        "v6.2.3": True,
1011                        "v6.2.5": True,
1012                        "v6.2.7": True,
1013                        "v6.0.11": True
1014                    }
1015                },
1016                {
1017                    "value": "dst-port",
1018                    "revisions": {
1019                        "v6.0.0": True,
1020                        "v7.0.0": True,
1021                        "v6.0.5": True,
1022                        "v6.4.4": True,
1023                        "v6.4.0": True,
1024                        "v6.4.1": True,
1025                        "v6.2.0": True,
1026                        "v6.2.3": True,
1027                        "v6.2.5": True,
1028                        "v6.2.7": True,
1029                        "v6.0.11": True
1030                    }
1031                }
1032            ],
1033            "revisions": {
1034                "v6.0.0": True,
1035                "v7.0.0": True,
1036                "v6.0.5": True,
1037                "v6.4.4": True,
1038                "v6.4.0": True,
1039                "v6.4.1": True,
1040                "v6.2.0": True,
1041                "v6.2.3": True,
1042                "v6.2.5": True,
1043                "v6.2.7": True,
1044                "v6.0.11": True
1045            }
1046        },
1047        "forward_method": {
1048            "type": "string",
1049            "options": [
1050                {
1051                    "value": "GRE",
1052                    "revisions": {
1053                        "v6.0.0": True,
1054                        "v7.0.0": True,
1055                        "v6.0.5": True,
1056                        "v6.4.4": True,
1057                        "v6.4.0": True,
1058                        "v6.4.1": True,
1059                        "v6.2.0": True,
1060                        "v6.2.3": True,
1061                        "v6.2.5": True,
1062                        "v6.2.7": True,
1063                        "v6.0.11": True
1064                    }
1065                },
1066                {
1067                    "value": "L2",
1068                    "revisions": {
1069                        "v6.0.0": True,
1070                        "v7.0.0": True,
1071                        "v6.0.5": True,
1072                        "v6.4.4": True,
1073                        "v6.4.0": True,
1074                        "v6.4.1": True,
1075                        "v6.2.0": True,
1076                        "v6.2.3": True,
1077                        "v6.2.5": True,
1078                        "v6.2.7": True,
1079                        "v6.0.11": True
1080                    }
1081                },
1082                {
1083                    "value": "any",
1084                    "revisions": {
1085                        "v6.0.0": True,
1086                        "v7.0.0": True,
1087                        "v6.0.5": True,
1088                        "v6.4.4": True,
1089                        "v6.4.0": True,
1090                        "v6.4.1": True,
1091                        "v6.2.0": True,
1092                        "v6.2.3": True,
1093                        "v6.2.5": True,
1094                        "v6.2.7": True,
1095                        "v6.0.11": True
1096                    }
1097                }
1098            ],
1099            "revisions": {
1100                "v6.0.0": True,
1101                "v7.0.0": True,
1102                "v6.0.5": True,
1103                "v6.4.4": True,
1104                "v6.4.0": True,
1105                "v6.4.1": True,
1106                "v6.2.0": True,
1107                "v6.2.3": True,
1108                "v6.2.5": True,
1109                "v6.2.7": True,
1110                "v6.0.11": True
1111            }
1112        },
1113        "ports_defined": {
1114            "type": "string",
1115            "options": [
1116                {
1117                    "value": "source",
1118                    "revisions": {
1119                        "v6.0.0": True,
1120                        "v7.0.0": True,
1121                        "v6.0.5": True,
1122                        "v6.4.4": True,
1123                        "v6.4.0": True,
1124                        "v6.4.1": True,
1125                        "v6.2.0": True,
1126                        "v6.2.3": True,
1127                        "v6.2.5": True,
1128                        "v6.2.7": True,
1129                        "v6.0.11": True
1130                    }
1131                },
1132                {
1133                    "value": "destination",
1134                    "revisions": {
1135                        "v6.0.0": True,
1136                        "v7.0.0": True,
1137                        "v6.0.5": True,
1138                        "v6.4.4": True,
1139                        "v6.4.0": True,
1140                        "v6.4.1": True,
1141                        "v6.2.0": True,
1142                        "v6.2.3": True,
1143                        "v6.2.5": True,
1144                        "v6.2.7": True,
1145                        "v6.0.11": True
1146                    }
1147                }
1148            ],
1149            "revisions": {
1150                "v6.0.0": True,
1151                "v7.0.0": True,
1152                "v6.0.5": True,
1153                "v6.4.4": True,
1154                "v6.4.0": True,
1155                "v6.4.1": True,
1156                "v6.2.0": True,
1157                "v6.2.3": True,
1158                "v6.2.5": True,
1159                "v6.2.7": True,
1160                "v6.0.11": True
1161            }
1162        },
1163        "cache_engine_method": {
1164            "type": "string",
1165            "options": [
1166                {
1167                    "value": "GRE",
1168                    "revisions": {
1169                        "v6.0.0": True,
1170                        "v7.0.0": True,
1171                        "v6.0.5": True,
1172                        "v6.4.4": True,
1173                        "v6.4.0": True,
1174                        "v6.4.1": True,
1175                        "v6.2.0": True,
1176                        "v6.2.3": True,
1177                        "v6.2.5": True,
1178                        "v6.2.7": True,
1179                        "v6.0.11": True
1180                    }
1181                },
1182                {
1183                    "value": "L2",
1184                    "revisions": {
1185                        "v6.0.0": True,
1186                        "v7.0.0": True,
1187                        "v6.0.5": True,
1188                        "v6.4.4": True,
1189                        "v6.4.0": True,
1190                        "v6.4.1": True,
1191                        "v6.2.0": True,
1192                        "v6.2.3": True,
1193                        "v6.2.5": True,
1194                        "v6.2.7": True,
1195                        "v6.0.11": True
1196                    }
1197                }
1198            ],
1199            "revisions": {
1200                "v6.0.0": True,
1201                "v7.0.0": True,
1202                "v6.0.5": True,
1203                "v6.4.4": True,
1204                "v6.4.0": True,
1205                "v6.4.1": True,
1206                "v6.2.0": True,
1207                "v6.2.3": True,
1208                "v6.2.5": True,
1209                "v6.2.7": True,
1210                "v6.0.11": True
1211            }
1212        },
1213        "server_list": {
1214            "type": "string",
1215            "revisions": {
1216                "v6.0.0": True,
1217                "v7.0.0": True,
1218                "v6.0.5": True,
1219                "v6.4.4": True,
1220                "v6.4.0": True,
1221                "v6.4.1": True,
1222                "v6.2.0": True,
1223                "v6.2.3": True,
1224                "v6.2.5": True,
1225                "v6.2.7": True,
1226                "v6.0.11": True
1227            }
1228        },
1229        "service_id": {
1230            "type": "string",
1231            "revisions": {
1232                "v6.0.0": True,
1233                "v7.0.0": True,
1234                "v6.0.5": True,
1235                "v6.4.4": True,
1236                "v6.4.0": True,
1237                "v6.4.1": True,
1238                "v6.2.0": True,
1239                "v6.2.3": True,
1240                "v6.2.5": True,
1241                "v6.2.7": True,
1242                "v6.0.11": True
1243            }
1244        },
1245        "ports": {
1246            "type": "string",
1247            "revisions": {
1248                "v6.0.0": True,
1249                "v7.0.0": True,
1250                "v6.0.5": True,
1251                "v6.4.4": True,
1252                "v6.4.0": True,
1253                "v6.4.1": True,
1254                "v6.2.0": True,
1255                "v6.2.3": True,
1256                "v6.2.5": True,
1257                "v6.2.7": True,
1258                "v6.0.11": True
1259            }
1260        }
1261    },
1262    "revisions": {
1263        "v6.0.0": True,
1264        "v7.0.0": True,
1265        "v6.0.5": True,
1266        "v6.4.4": True,
1267        "v6.4.0": True,
1268        "v6.4.1": True,
1269        "v6.2.0": True,
1270        "v6.2.3": True,
1271        "v6.2.5": True,
1272        "v6.2.7": True,
1273        "v6.0.11": True
1274    }
1275}
1276
1277
1278def main():
1279    module_spec = schema_to_module_spec(versioned_schema)
1280    mkeyname = 'service-id'
1281    fields = {
1282        "access_token": {"required": False, "type": "str", "no_log": True},
1283        "enable_log": {"required": False, "type": bool},
1284        "vdom": {"required": False, "type": "str", "default": "root"},
1285        "state": {"required": True, "type": "str",
1286                  "choices": ["present", "absent"]},
1287        "system_wccp": {
1288            "required": False, "type": "dict", "default": None,
1289            "options": {
1290            }
1291        }
1292    }
1293    for attribute_name in module_spec['options']:
1294        fields["system_wccp"]['options'][attribute_name] = module_spec['options'][attribute_name]
1295        if mkeyname and mkeyname == attribute_name:
1296            fields["system_wccp"]['options'][attribute_name]['required'] = True
1297
1298    check_legacy_fortiosapi()
1299    module = AnsibleModule(argument_spec=fields,
1300                           supports_check_mode=True)
1301
1302    versions_check_result = None
1303    if module._socket_path:
1304        connection = Connection(module._socket_path)
1305        if 'access_token' in module.params:
1306            connection.set_option('access_token', module.params['access_token'])
1307
1308        if 'enable_log' in module.params:
1309            connection.set_option('enable_log', module.params['enable_log'])
1310        else:
1311            connection.set_option('enable_log', False)
1312        fos = FortiOSHandler(connection, module, mkeyname)
1313        versions_check_result = check_schema_versioning(fos, versioned_schema, "system_wccp")
1314
1315        is_error, has_changed, result = fortios_system(module.params, fos, module.check_mode)
1316
1317    else:
1318        module.fail_json(**FAIL_SOCKET_MSG)
1319
1320    if versions_check_result and versions_check_result['matched'] is False:
1321        module.warn("Ansible has detected version mismatch between FortOS system and your playbook, see more details by specifying option -vvv")
1322
1323    if not is_error:
1324        if versions_check_result and versions_check_result['matched'] is False:
1325            module.exit_json(changed=has_changed, version_check_warning=versions_check_result, meta=result)
1326        else:
1327            module.exit_json(changed=has_changed, meta=result)
1328    else:
1329        if versions_check_result and versions_check_result['matched'] is False:
1330            module.fail_json(msg="Error in repo", version_check_warning=versions_check_result, meta=result)
1331        else:
1332            module.fail_json(msg="Error in repo", meta=result)
1333
1334
1335if __name__ == '__main__':
1336    main()
1337