#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2019 Red Hat
# GNU General Public License v3.0+
# (see COPYING or https://www.gnu.org/licenses/gpl-3.0.txt)

#############################################
#                WARNING                    #
#############################################
#
# This file is auto generated by the resource
#   module builder playbook.
#
# Do not edit this file manually.
#
# Changes to this file will be over written
#   by the resource module builder.
#
# Changes should be made in the model used to
#   generate this file or in the resource module
#   builder template.
#
#############################################

"""
The module file for iosxr_acls
"""

from __future__ import absolute_import, division, print_function
__metaclass__ = type

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

DOCUMENTATION = """
---
module: iosxr_acls
version_added: "2.10"
short_description: Manage Access Control Lists (ACLs) on devices running IOS-XR.
description:
  - This module manages Access Control Lists (ACLs) on devices running IOS-XR.
author: Nilashish Chakraborty (@NilashishC)
options:
  config:
    description: A list of dictionaries specifying ACL configurations.
    type: list
    elements: dict
    suboptions:
      afi:
        description:
          - The Address Family Indicator (AFI) for the Access Control Lists (ACL).
        type: str
        required: True
        choices: ['ipv4', 'ipv6']
      acls:
        description:
          - A list of Access Control Lists (ACLs).
        type: list
        elements: dict
        suboptions:
          name:
            description:
              - The name of the Access Control List (ACL).
            type: str
          aces:
            description:
              - List of Access Control Entries (ACEs) for this Access Control List (ACL).
            type: list
            elements: dict
            suboptions:
              sequence:
                description:
                  - Sequence number for the Access Control Entry (ACE).
                type: int
              grant:
                description:
                  - Forward or drop packets matching the Access Control Entry (ACE).
                type: str
                choices: ['permit', 'deny']
              remark:
                description:
                  - Comments or a description for the access list.
                type: str
              line:
                description:
                  - An ACE excluding the sequence number.
                  - This key is mutually exclusive with all the other attributes except 'sequence'.
                  - When used with other attributes, the value of this key will get precedence and the
                    other keys will be ignored.
                  - This should only be used when an attribute doesn't exist in the argspec but is valid for the device.
                  - For fact gathering, any ACE that is not fully parsed, will show up as a value of this attribute,
                    excluding the sequence number, which will be populated as value of the sequence key.
                type: str
                aliases: ['ace']
              source:
                description:
                  - Specifies the packet source.
                type: dict
                suboptions:
                  host:
                    description:
                      - The host IP address to match.
                    type: str
                  address:
                    description:
                      - The source IP address to match.
                    type: str
                  wildcard_bits:
                    description:
                      - The Wildcard bits to apply to source address.
                    type: str
                  any:
                    description:
                      - Match any source address.
                    type: bool
                  prefix:
                    description:
                      - Source network prefix.
                    type: str
                  port_protocol:
                    description:
                      - Specify the source port or protocol.
                    type: dict
                    suboptions:
                      eq:
                        description:
                          - Match only packets on a given port number.
                        type: str
                      gt:
                        description:
                          - Match only packets with a greater port number.
                        type: str
                      lt:
                        description:
                          - Match only packets with a lower port number.
                        type: str
                      neq:
                        description:
                          - Match only packets not on a given port number.
                        type: str
                      range:
                        description:
                          - Match only packets in the range of port numbers
                        type: dict
                        suboptions:
                          start:
                            description:
                              - Specify the start of the port range
                            type: str
                          end:
                            description:
                              - Specify the end of the port range
                            type: str
              destination:
                description:
                  - Specifies the packet destination.
                type: dict
                suboptions:
                  host:
                    description:
                      - The host IP address to match.
                    type: str
                  address:
                    description:
                      - The destination IP address to match.
                    type: str
                  wildcard_bits:
                    description:
                      - The Wildcard bits to apply to destination address.
                    type: str
                  any:
                    description:
                      - Match any destination address.
                    type: bool
                  prefix:
                    description:
                      - Destination network prefix.
                    type: str
                  port_protocol:
                    description:
                      - Specify the source port or protocol.
                    type: dict
                    suboptions:
                      eq:
                        description:
                          - Match only packets on a given port number.
                        type: str
                      gt:
                        description:
                          - Match only packets with a greater port number.
                        type: str
                      lt:
                        description:
                          - Match only packets with a lower port number.
                        type: str
                      neq:
                        description:
                          - Match only packets not on a given port number.
                        type: str
                      range:
                        description:
                          - Match only packets in the range of port numbers
                        type: dict
                        suboptions:
                          start:
                            description:
                              - Specify the start of the port range
                            type: str
                          end:
                            description:
                              - Specify the end of the port range
                            type: str
              protocol:
                description:
                  - Specify the protocol to match.
                  - Refer to vendor documentation for valid values.
                type: str
              protocol_options:
                description:
                  - Additional suboptions for the protocol.
                type: dict
                suboptions:
                  icmpv6:
                    description: Internet Control Message Protocol settings for IPv6.
                    type: dict
                    suboptions:
                      address_unreachable:
                        description: Address Unreachable
                        type: bool
                      administratively_prohibited:
                        description: Administratively Prohibited
                        type: bool
                      beyond_scope_of_source_address:
                        description: Administratively Prohibited
                        type: bool
                      destination_unreachable:
                        description: Destination Unreachable
                        type: bool
                      echo:
                        description: Echo
                        type: bool
                      echo_reply:
                        description: Echo Reply
                        type: bool
                      erroneous_header_field:
                        description: Erroneous Header Field
                        type: bool
                      group_membership_query:
                        description: Group Membership Query
                        type: bool
                      group_membership_report:
                        description: Group Membership Report
                        type: bool
                      group_membership_termination:
                        description: Group Membership Termination
                        type: bool
                      host_unreachable:
                        description: Host Unreachable
                        type: bool
                      nd_na:
                        description: Neighbor Discovery - Neighbor Advertisement
                        type: bool
                      nd_ns:
                        description: Neighbor Discovery - Neighbor Solicitation
                        type: bool
                      neighbor_redirect:
                        description: Neighbor Redirect
                        type: bool
                      no_route_to_destination:
                        description: No Route To Destination
                        type: bool
                      node_information_request_is_refused:
                        description: Node Information Request Is Refused
                        type: bool
                      node_information_successful_reply:
                        description: Node Information Successful Reply
                        type: bool
                      packet_too_big:
                        description: Packet Too Big
                        type: bool
                      parameter_problem:
                        description: Parameter Problem
                        type: bool
                      port_unreachable:
                        description: Port Unreachable
                        type: bool
                      query_subject_is_IPv4address:
                        description: Query Subject Is IPv4 address
                        type: bool
                      query_subject_is_IPv6address:
                        description: Query Subject Is IPv6 address
                        type: bool
                      query_subject_is_domainname:
                        description: Query Subject Is Domain name
                        type: bool
                      reassembly_timeout:
                        description: Reassembly Timeout
                        type: bool
                      redirect:
                        description: Redirect
                        type: bool
                      router_advertisement:
                        description: Router Advertisement
                        type: bool
                      router_renumbering:
                        description: Router Renumbering
                        type: bool
                      router_solicitation:
                        description: Router Solicitation
                        type: bool
                      rr_command:
                        description: RR Command
                        type: bool
                      rr_result:
                        description: RR Result
                        type: bool
                      rr_seqnum_reset:
                        description: RR Seqnum Reset
                        type: bool
                      time_exceeded:
                        description: Time Exceeded
                        type: bool
                      ttl_exceeded:
                        description: TTL Exceeded
                        type: bool
                      unknown_query_type:
                        description: Unknown Query Type
                        type: bool
                      unreachable:
                        description: Unreachable
                        type: bool
                      unrecognized_next_header:
                        description: Unrecognized Next Header
                        type: bool
                      unrecognized_option:
                        description: Unrecognized Option
                        type: bool
                      whoareyou_reply:
                        description: Whoareyou Reply
                        type: bool
                      whoareyou_request:
                        description: Whoareyou Request
                        type: bool
                  icmp:
                    description: Internet Control Message Protocol settings.
                    type: dict
                    suboptions:
                      administratively_prohibited:
                        description: Administratively prohibited
                        type: bool
                      alternate_address:
                        description: Alternate address
                        type: bool
                      conversion_error:
                        description: Datagram conversion
                        type: bool
                      dod_host_prohibited:
                        description: Host prohibited
                        type: bool
                      dod_net_prohibited:
                        description: Net prohibited
                        type: bool
                      echo:
                        description: Echo (ping)
                        type: bool
                      echo_reply:
                        description: Echo reply
                        type: bool
                      general_parameter_problem:
                        description: Parameter problem
                        type: bool
                      host_isolated:
                        description: Host isolated
                        type: bool
                      host_precedence_unreachable:
                        description: Host unreachable for precedence
                        type: bool
                      host_redirect:
                        description: Host redirect
                        type: bool
                      host_tos_redirect:
                        description: Host redirect for TOS
                        type: bool
                      host_tos_unreachable:
                        description: Host unreachable for TOS
                        type: bool
                      host_unknown:
                        description: Host unknown
                        type: bool
                      host_unreachable:
                        description: Host unreachable
                        type: bool
                      information_reply:
                        description: Information replies
                        type: bool
                      information_request:
                        description: Information requests
                        type: bool
                      mask_reply:
                        description: Mask replies
                        type: bool
                      mask_request:
                        description: Mask requests
                        type: bool
                      mobile_redirect:
                        description: Mobile host redirect
                        type: bool
                      net_redirect:
                        description: Network redirect
                        type: bool
                      net_tos_redirect:
                        description: Net redirect for TOS
                        type: bool
                      net_tos_unreachable:
                        description: Network unreachable for TOS
                        type: bool
                      net_unreachable:
                        description: Net unreachable
                        type: bool
                      network_unknown:
                        description: Network unknown
                        type: bool
                      no_room_for_option:
                        description: Parameter required but no room
                        type: bool
                      option_missing:
                        description: Parameter required but not present
                        type: bool
                      packet_too_big:
                        description: Fragmentation needed and DF set
                        type: bool
                      parameter_problem:
                        description: All parameter problems
                        type: bool
                      port_unreachable:
                        description: Port unreachable
                        type: bool
                      precedence_unreachable:
                        description: Precedence cutoff
                        type: bool
                      protocol_unreachable:
                        description: Protocol unreachable
                        type: bool
                      reassembly_timeout:
                        description: Reassembly timeout
                        type: bool
                      redirect:
                        description: All redirects
                        type: bool
                      router_advertisement:
                        description: Router discovery advertisements
                        type: bool
                      router_solicitation:
                        description: Router discovery solicitations
                        type: bool
                      source_quench:
                        description: Source quenches
                        type: bool
                      source_route_failed:
                        description: Source route failed
                        type: bool
                      time_exceeded:
                        description: All time exceededs
                        type: bool
                      timestamp_reply:
                        description: Timestamp replies
                        type: bool
                      timestamp_request:
                        description: Timestamp requests
                        type: bool
                      traceroute:
                        description: Traceroute
                        type: bool
                      ttl_exceeded:
                        description: TTL exceeded
                        type: bool
                      unreachable:
                        description: All unreachables
                        type: bool
                  tcp:
                    description: Match TCP packet flags
                    type: dict
                    suboptions:
                      ack:
                        description: Match on the ACK bit
                        type: bool
                      established:
                        description: Match established connections
                        type: bool
                      fin:
                        description: Match on the FIN bit
                        type: bool
                      psh:
                        description: Match on the PSH bit
                        type: bool
                      rst:
                        description: Match on the RST bit
                        type: bool
                      syn:
                        description: Match on the SYN bit
                        type: bool
                      urg:
                        description: Match on the URG bit
                        type: bool
                  igmp:
                    description: Internet Group Management Protocol (IGMP) settings.
                    type: dict
                    suboptions:
                      dvmrp:
                        description: Match Distance Vector Multicast Routing Protocol
                        type: bool
                      host_query:
                        description: Match Host Query
                        type: bool
                      host_report:
                        description: Match Host Report
                        type: bool
                      pim:
                        description: Match Protocol Independent Multicast
                        type: bool
                      trace:
                        description: Multicast trace
                        type: bool
                      mtrace:
                        description: Match mtrace
                        type: bool
                      mtrace_response:
                        description: Match mtrace response
                        type: bool
              dscp:
                description:
                  - Match packets with given DSCP value.
                type: dict
                suboptions:
                  eq:
                    description: Match only packets on a given dscp value
                    type: str
                  gt:
                    description: Match only packets with a greater dscp value
                    type: str
                  lt:
                    description: Match only packets with a lower dscp value
                    type: str
                  neq:
                    description: Match only packets not on a given dscp value
                    type: str
                  range:
                    description: Match only packets in the range of dscp values
                    type: dict
                    suboptions:
                      start:
                        description: Start of the dscp range
                        type: str
                      end:
                        description: End of the dscp range
                        type: str
              fragments:
                description:
                  - Check non-intial fragments.
                type: bool
              packet_length:
                description:
                  - Match packets given packet length.
                type: dict
                suboptions:
                  eq:
                    description: Match only packets on a given packet length
                    type: int
                  gt:
                    description: Match only packets with a greater packet length
                    type: int
                  lt:
                    description: Match only packets with a lower packet length
                    type: int
                  neq:
                    description: Match only packets not on a given packet length
                    type: int
                  range:
                    description: Match only packets in the range of packet lengths
                    type: dict
                    suboptions:
                      start:
                        description: Start of the packet length range
                        type: int
                      end:
                        description: End of the packet length range
                        type: int
              precedence:
                description: Match packets with given precedence value
                type: str
              ttl:
                description: Match against specified TTL value.
                type: dict
                suboptions:
                  eq:
                    description: Match only packets with exact TTL value.
                    type: int
                  gt:
                    description: Match only packets with a greater TTL value.
                    type: int
                  lt:
                    description: Match only packets with a lower TTL value.
                    type: int
                  neq:
                    description: Match only packets that won't have the given TTL value.
                    type: int
                  range:
                    description: Match only packets in the range of given TTL values.
                    type: dict
                    suboptions:
                      start:
                        description: Start of the TTL range.
                        type: int
                      end:
                        description: End of the TTL range.
                        type: int
              log:
                description:
                  - Enable/disable log matches against this entry.
                type: bool
              log_input:
                description:
                  - Enable/disable log matches against this entry, including input interface.
                type: bool
              icmp_off:
                description:
                  - Enable/disable the ICMP message for this entry.
                type: bool
              capture:
                description:
                  - Capture matched packet.
                type: bool
              destopts:
                description:
                  - Match if destination opts header is present.
                type: bool
              authen:
                description:
                  - Match if authentication header is present.
                type: bool
              routing:
                description:
                  - Match if routing header is present.
                type: bool
              hop_by_hop:
                description:
                  -  Match if hop-by-hop opts header is present.
                type: bool
  running_config:
    description:
      - The module, by default, will connect to the remote device and
        retrieve the current running-config to use as a base for comparing
        against the contents of source. There are times when it is not
        desirable to have the task get the current running-config for
        every task in a playbook.  The I(running_config) argument allows the
        implementer to pass in the configuration to use as the base
        config for comparison. This value of this option should be the
        output received from device by executing command
        B(show running-config router static).
    type: str
  state:
    description:
      - The state the configuration should be left in.
    type: str
    choices:
      - merged
      - replaced
      - overridden
      - deleted
      - gathered
      - rendered
      - parsed
    default: merged
"""
EXAMPLES = """
# Using merged to add new ACLs

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:07:45.767 UTC
# RP/0/RP0/CPU0:ios#

- name: Merge the provided configuration with the exisiting running configuration
  iosxr_acls:
    config:
      - afi: ipv6
        acls:
          - name: acl6_1
            aces:
              - sequence: 10
                grant: deny
                protocol: tcp
                source:
                  prefix: 2001:db8:1234::/48
                  port_protocol:
                    range:
                      start: ftp
                      end: telnet
                destination:
                  any: True
                protocol_options:
                  tcp:
                    syn: True
                ttl:
                  range:
                    start: 180
                    end: 250
                routing: True
                authen: True
                log: True

              - sequence: 20
                grant: permit
                protocol: icmpv6
                source:
                  any: True
                destination:
                  any: True
                protocol_options:
                  icmpv6:
                    router_advertisement: True
                precedence: network
                destopts: True

      - afi: ipv4
        acls:
          - name: acl_1
            aces:
              - sequence: 16
                remark: TEST_ACL_1_REMARK

              - sequence: 21
                grant: permit
                protocol: tcp
                source:
                  host: 192.0.2.10
                  port_protocol:
                    range:
                      start: pop3
                      end: 121
                destination:
                  address: 198.51.100.0
                  wildcard_bits: 0.0.0.15
                protocol_options:
                  tcp:
                    rst: True

              - sequence: 23
                grant: deny
                protocol: icmp
                source:
                  any: True
                destination:
                  prefix: 198.51.100.0/28
                protocol_options:
                  icmp:
                    reassembly_timeout: True
                dscp:
                  lt: af12

          - name: acl_2
            aces:
              - sequence: 10
                remark: TEST_ACL_2_REMARK
    state: merged

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

# Using merged to update existing ACLs

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Update existing ACEs
  iosxr_acls:
    config:
      - afi: ipv4
        acls:
          - name: acl_1
            aces:
              - sequence: 21
                source:
                  prefix: 198.51.100.32/28
                  port_protocol:
                    range:
                      start: pop3
                      end: 121
                protocol_options:
                  tcp:
                    syn: True

              - sequence: 23
                protocol_options:
                  icmp:
                    router_advertisement: True
                dscp:
                  eq: af23

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:47:18.711 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn
#  23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

# Using replaced to replace a whole ACL

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Replace device configurations of listed ACL with provided configurations
  iosxr_acls:
    config:
      - afi: ipv4
        acls:
          - name: acl_2
            aces:
              - sequence: 11
                grant: permit
                protocol: igmp
                source:
                  host: 198.51.100.130
                destination:
                  any: True
                ttl:
                  eq: 100

              - sequence: 12
                grant: deny
                source:
                  any: True
                destination:
                  any: True
                protocol: icmp
    state: replaced

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 06:19:51.496 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp 198.51.100.32 0.0.0.15 range pop3 121 198.51.100.0 0.0.0.15 syn
#  23 deny icmp any 198.51.100.0 0.0.0.15 router-advertisement dscp eq af23
# ipv4 access-list acl_2
#  11 permit igmp host 198.51.100.130 any ttl eq 100
#  12 deny icmp any any
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

# Using overridden to override all ACLs in the device

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Overridde all ACLs configuration with provided configuration
  iosxr_acls:
    config:
      - afi: ipv4
        acls:
          - name: acl_1
            aces:
              - sequence: 10
                grant: permit
                source:
                  any: True
                destination:
                  any: True
                protocol: tcp

          - name: acl_2
            aces:
              - sequence: 20
                grant: permit
                source:
                  any: True
                destination:
                  any: True
                protocol: igmp
    state: overridden

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 06:31:22.178 UTC
# ipv4 access-list acl_1
#  10 permit tcp any any
# ipv4 access-list acl_2
#  20 permit igmp any any

# Using deleted to delete a single ACE from an ACL

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Delete a single ACE
  iosxr_acls:
    config:
      - afi: ipv4
        acls:
          - name: acl_1
            aces:
              - sequence: 23
    state: deleted

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

# Using deleted to delete an entire ACL

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Delete a single ACL
  iosxr_acls:
    config:
      - afi: ipv6
        acls:
          - name: acl6_1
    state: deleted

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK

# Using deleted to delete all ACLs under one AFI

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Delete all ACLs under one AFI
  iosxr_acls:
    config:
      - afi: ipv4
    state: deleted

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

# Using deleted to delete all ACLs from the device

# Before state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:22:57.021 UTC
# ipv4 access-list acl_1
#  16 remark TEST_ACL_1_REMARK
#  21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
#  23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
# ipv4 access-list acl_2
#  10 remark TEST_ACL_2_REMARK
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network destopts

- name: Delete all ACLs from the device
  iosxr_acls:
    state: deleted

# After state:
# -------------

# RP/0/RP0/CPU0:ios#sh access-lists afi-all
# Thu Feb 20 05:07:45.767 UTC
# RP/0/RP0/CPU0:ios#

# Using gathered to gather ACL facts from the device

- name: Gather ACL interfaces facts using gathered state
  iosxr_acls:
    state: gathered

# Task Output (redacted)
# -----------------------
#

# "gathered": [
#    {
#        "acls": [
#            {
#                "aces": [
#                    {
#                        "remark": "TEST_ACL_1_REMARK",
#                        "sequence": 16
#                    },
#                    {
#                        "destination": {
#                            "address": "198.51.100.0",
#                            "wildcard_bits": "0.0.0.15"
#                        },
#                        "grant": "permit",
#                        "protocol": "tcp",
#                        "protocol_options": {
#                            "tcp": {
#                                "rst": true
#                            }
#                        },
#                        "sequence": 21,
#                        "source": {
#                            "host": "192.0.2.10",
#                            "port_protocol": {
#                                "range": {
#                                    "end": "121",
#                                    "start": "pop3"
#                                }
#                            }
#                        }
#                    },
#                    {
#                        "destination": {
#                            "address": "198.51.100.0",
#                            "wildcard_bits": "0.0.0.15"
#                        },
#                        "dscp": {
#                            "lt": "af12"
#                        },
#                        "grant": "deny",
#                        "protocol": "icmp",
#                        "protocol_options": {
#                            "icmp": {
#                                "reassembly_timeout": true
#                            }
#                        },
#                        "sequence": 23,
#                        "source": {
#                            "any": true
#                        }
#                    }
#                ],
#                "name": "acl_1"
#            },
#            {
#                "aces": [
#                    {
#                        "remark": "TEST_ACL_2_REMARK",
#                        "sequence": 10
#                    }
#                ],
#                "name": "acl_2"
#            }
#        ],
#        "afi": "ipv4"
#    },
#    {
#        "acls": [
#            {
#                "aces": [
#                    {
#                        "authen": true,
#                        "destination": {
#                            "any": true
#                        },
#                        "grant": "deny",
#                        "log": true,
#                        "protocol": "tcp",
#                        "protocol_options": {
#                            "tcp": {
#                                "syn": true
#                            }
#                        },
#                        "routing": true,
#                        "sequence": 10,
#                        "source": {
#                            "port_protocol": {
#                                "range": {
#                                   "end": "telnet",
#                                   "start": "ftp"
#                                }
#                            },
#                            "prefix": "2001:db8:1234::/48"
#                        },
#                        "ttl": {
#                            "range": {
#                                "end": 250,
#                                "start": 180
#                            }
#                        }
#                    },
#                    {
#                        "destination": {
#                            "any": true
#                        },
#                        "destopts": true,
#                        "grant": "permit",
#                        "precedence": "network",
#                        "protocol": "icmpv6",
#                        "protocol_options": {
#                            "icmpv6": {
#                                "router_advertisement": true
#                            }
#                        },
#                        "sequence": 20,
#                        "source": {
#                            "any": true
#                        }
#                    }
#                ],
#                "name": "acl6_1"
#            }
#        ],
#        "afi": "ipv6"
#    }
#  ]

# Using rendered

- name: Render platform specific commands (without connecting to the device)
  iosxr_acls:
    config:
      - afi: ipv4
        acls:
          - name: acl_2
            aces:
              - sequence: 11
                grant: permit
                protocol: igmp
                source:
                  host: 198.51.100.130
                destination:
                  any: True
                ttl:
                  eq: 100

              - sequence: 12
                grant: deny
                source:
                  any: True
                destination:
                  any: True
                protocol: icmp
    state: rendered

# Task Output (redacted)
# -----------------------

# "rendered": [
#    "ipv4 access-list acl_2",
#    "11 permit igmp host 198.51.100.130 any ttl eq 100",
#    "12 deny icmp any any"

# Using parsed

# parsed.cfg
# ------------
#
# ipv4 access-list acl_1
#  10 remark TEST_ACL_2_REMARK
# ipv4 access-list acl_2
#  11 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log
#  21 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts
# ipv6 access-list acl6_1
#  10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 routing authen log
#  20 permit icmpv6 any any router-advertisement precedence network packet-length eq 576 destopts

- name: Parse externally provided ACL config to agnostic model
  iosxr_acls:
    running_config: "{{ lookup('file', 'parsed.cfg') }}"
    state: parsed

# Task Output (redacted)
# -----------------------
#  "parsed": [
#        {
#            "acls": [
#                {
#                    "aces": [
#                      {
#                            "remark": "TEST_ACL_2_REMARK",
#                            "sequence": 10
#                        }
#                    ],
#                   "name": "acl_1"
#                },
#                {
#                    "aces": [
#                        {
#                            "authen": true,
#                            "destination": {
#                                "any": true
#                            },
#                            "grant": "deny",
#                            "log": true,
#                            "protocol": "tcp",
#                            "protocol_options": {
#                                "tcp": {
#                                    "syn": true
#                                }
#                            },
#                            "routing": true,
#                            "sequence": 11,
#                            "source": {
#                                "port_protocol": {
#                                    "range": {
#                                        "end": "telnet",
#                                        "start": "ftp"
#                                    }
#                                },
#                                "prefix": "2001:db8:1234::/48"
#                            },
#                            "ttl": {
#                                "range": {
#                                    "end": 250,
#                                    "start": 180
#                                }
#                            }
#                        },
#                        {
#                            "destination": {
#                                "any": true
#                            },
#                            "destopts": true,
#                            "grant": "permit",
#                            "packet_length": {
#                                "eq": 576
#                            },
#                            "precedence": "network",
#                            "protocol": "icmpv6",
#                            "protocol_options": {
#                                "icmpv6": {
#                                    "router_advertisement": true
#                                }
#                            },
#                            "sequence": 21,
#                            "source": {
#                                "any": true
#                            }
#                        }
#                    ],
#                    "name": "acl_2"
#                }
#            ],
#            "afi": "ipv4"
#        },
#        {
#            "acls": [
#                {
#                    "aces": [
#                        {
#                            "authen": true,
#                            "destination": {
#                                "any": true
#                            },
#                            "grant": "deny",
#                            "log": true,
#                            "protocol": "tcp",
#                            "protocol_options": {
#                                "tcp": {
#                                    "syn": true
#                                }
#                            },
#                            "routing": true,
#                            "sequence": 10,
#                            "source": {
#                                "port_protocol": {
#                                    "range": {
#                                        "end": "telnet",
#                                        "start": "ftp"
#                                    }
#                                },
#                                "prefix": "2001:db8:1234::/48"
#                            },
#                            "ttl": {
#                                "range": {
#                                    "end": 250,
#                                    "start": 180
#                                }
#                            }
#                        },
#                        {
#                            "destination": {
#                                "any": true
#                            },
#                            "destopts": true,
#                            "grant": "permit",
#                            "packet_length": {
#                                "eq": 576
#                            },
#                            "precedence": "network",
#                            "protocol": "icmpv6",
#                            "protocol_options": {
#                                "icmpv6": {
#                                    "router_advertisement": true
#                                }
#                            },
#                            "sequence": 20,
#                            "source": {
#                                "any": true
#                            }
#                        }
#                    ],
#                    "name": "acl6_1"
#                }
#            ],
#            "afi": "ipv6"
#        }
#    ]
"""
RETURN = """
before:
  description: The configuration prior to the model invocation.
  returned: always
  type: list
  sample: >
    The configuration returned will always be in the same format
     of the parameters above.
after:
  description: The resulting configuration model invocation.
  returned: when changed
  type: list
  sample: >
    The configuration returned will always be in the same format
     of the parameters above.
commands:
  description: The set of commands pushed to the remote device.
  returned: always
  type: list
  sample:
    - ipv6 access-list acl6_1
    - 10 deny tcp 2001:db8:1234::/48 range ftp telnet any syn ttl range 180 250 authen routing log
    - 20 permit icmpv6 any any router-advertisement precedence network destopts
    - ipv4 access-list acl_1
    - 16 remark TEST_ACL_1_REMARK
    - 21 permit tcp host 192.0.2.10 range pop3 121 198.51.100.0 0.0.0.15 rst
    - 23 deny icmp any 198.51.100.0 0.0.0.15 reassembly-timeout dscp lt af12
"""


from ansible.module_utils.basic import AnsibleModule
from ansible.module_utils.network.iosxr.argspec.acls.acls import AclsArgs
from ansible.module_utils.network.iosxr.config.acls.acls import Acls


def main():
    """
    Main entry point for module execution

    :returns: the result form module invocation
    """
    required_if = [('state', 'merged', ('config',)),
                   ('state', 'replaced', ('config',)),
                   ('state', 'overridden', ('config',)),
                   ('state', 'rendered', ('config',)),
                   ('state', 'parsed', ('running_config',))]

    module = AnsibleModule(argument_spec=AclsArgs.argument_spec, required_if=required_if,
                           supports_check_mode=True)

    result = Acls(module).execute_module()
    module.exit_json(**result)


if __name__ == '__main__':
    main()
