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