#!/usr/bin/python
# -*- coding: utf-8 -*-
# Copyright 2021 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 junos_routing_instances
"""

from __future__ import absolute_import, division, print_function


__metaclass__ = type

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

DOCUMENTATION = """
---
module: junos_routing_instances
version_added: 2.1.0
short_description: Manage routing instances on Junos devices.
description: Manage routing instances on Junos network devices.
author: Rohit Thakur (@rohitthakur2590)
requirements:
  - ncclient (>=v0.6.4)
  - xmltodict (>=0.12.0)
notes:
  - This module requires the netconf system service be enabled on the device being managed.
  - This module works with connection C(netconf). See L(the Junos OS Platform Options,../network/user_guide/platform_junos.html).
  - Tested against JunOS v18.4R1
options:
  running_config:
    description:
      - This option is used only with state I(parsed).
      - The value of this option should be the output received from the Junos device
        by executing the command B(show routing-instances).
      - The state I(parsed) reads the configuration from C(running_config) option and
        transforms it into Ansible structured data as per the resource module's argspec
        and the value is then returned in the I(parsed) key within the result
    type: str
  config:
    description: The provided Routing instance configuration list.
    type: list
    elements: dict
    suboptions:
      name:
        description: Specify routing instance name.
        type: str
      connector_id_advertise:
        description: Advertise connector-id attribute.
        type: bool
      description:
        description: Specify text description of routing instance.
        type: str
      egress_protection:
        description: Egress instance protection dictionary.
        type: dict
        suboptions:
          context_identifier:
            description: Specify context identifier.
            type: str
          protector:
            description: Enable Edge Protector functionality for this VPN.
            type: bool
      instance_role:
        description: Primary role of L2Backhaul-vpn router.
        type: str
        choices: ['access', 'nni']
      type:
        description: Specify instance type.
        type: str
        choices:
          - evpn
          - evpn-vpws
          - forwarding
          - l2backhaul-vpn
          - l2vpn
          - layer2-control
          - mac-vrf
          - mpls-forwarding
          - mpls-internet-multicast
          - no-forwarding
          - virtual-router
          - vpls
          - vrf
      interfaces:
        description: Interface name for this routing instance.
        type: list
        elements: dict
        suboptions:
          name:
            description: Specify name of the interface.
            type: str
          protect_interface:
            description: Specify name of the protected interface.
            type: str
      l2vpn_id:
        description: Layer-2 vpn-id for this instance.
        type: str
      no_irb_layer_2_copy:
        description: Disable transmission of layer-2 copy of packets of irb routing-interface.
        type: bool
      no_normalization:
         description: Disable vlan id normalization for interfaces.
         type: bool
      no_local_switching:
        description: Disable vlan id normalization for interfaces.
        type: bool
      no_vrf_advertise:
        description: Disable vlan id normalization for interfaces.
        type: bool
      no_vrf_propagate_ttl:
        description: Disable TTL propagation from IP to MPLS (on push) and MPLS to IP (on pop).
        type: bool
      qualified_bum_pruning_mode:
        description: Enable BUM pruning for VPLS instance.
        type: bool
      route_distinguisher:
        description: Route distinguisher for this instance
        type: str
      routing_interface:
        description: Routing interface name for this routing-instance.
        type: list
        elements: str
      vrf_imports:
        description: Import policy for VRF instance RIBs.
        type: list
        elements: str
      vrf_exports:
        description: Export policy for VRF instance RIBs.
        type: list
        elements: str
  state:
    description:
      - The state the configuration should be left in.
    type: str
    choices:
    - merged
    - replaced
    - overridden
    - deleted
    - parsed
    - gathered
    - rendered
    default: merged
"""
EXAMPLES = """
# Using merged
#
# Before state
# ------------
#
# admin# show routing-instances
#
# [edit]
# vagrant@vsrx# show policy-options
# policy-statement test-policy {
#     term t1 {
#         then reject;
#     }
# }
# policy-statement test-policy-1 {
#     term t1 {
#         then reject;
#     }
# }

- name: Merge Junos BGP address family configuration
  junipernetworks.junos.junos_routing_instances:
    config:
      - name: "test"
        type: "vrf"
        route_distinguisher: "10.58.255.1:37"
        vrf_imports:
          - "test-policy"
        vrf_exports:
          - "test-policy"
          - "test-policy-1"
        interfaces:
          - name: "sp-0/0/0.0"
          - name: "gr-0/0/0.0"
        connector_id_advertise: true
      - name: "forwardinst"
        type: "forwarding"
        description: "Configured by Ansible Content Team"
    state: merged
#
# -------------------------
# Module Execution Result
# -------------------------
#
# After state
# -----------
#
# admin# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.58.255.1:37;
#     vrf-import test-policy;
#     vrf-export [ test-policy test-policy-1 ];
#     connector-id-advertise;
# }
#
# Using gathered
#
# Before state
# ------------
#
# admin# show routing-instances
#
# [edit]
# admin# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.58.255.1:37;
#     vrf-import test-policy;
#     vrf-export [ test-policy test-policy-1 ];
#     connector-id-advertise;
# }
- name: Gather Junos routing-instances
  junipernetworks.junos.junos_routing_instances:
    state: gathered
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
#    "gathered": [
#         {
#             "description": "Configured by Ansible Content Team",
#             "name": "forwardinst",
#             "type": "forwarding"
#         },
#         {
#             "connector_id_advertise": true,
#             "interfaces": [
#                 {
#                     "name": "gr-0/0/0.0"
#                 },
#                 {
#                     "name": "sp-0/0/0.0"
#                 }
#             ],
#             "name": "test",
#             "route_distinguisher": "10.58.255.1:37",
#             "type": "vrf",
#             "vrf_exports": [
#                 "test-policy",
#                 "test-policy-1"
#             ],
#             "vrf_imports": [
#                 "test-policy"
#             ]
#         }
#     ]
#
# Using replaced
#
# Before state
# ------------
#
# admin# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.58.255.1:37;
#     vrf-import test-policy;
#     vrf-export [ test-policy test-policy-1 ];
#     connector-id-advertise;
# }

- name: Replace existing Junos routing instance config with provided config
  junipernetworks.junos.junos_routing_instances:
    config:
      address_family:
        - name: "test"
          type: "vrf"
          route_distinguisher: "10.57.255.1:37"
          vrf_imports:
            - "test-policy"
          vrf_exports:
            - "test-policy"
          interfaces:
            - name: "sp-0/0/0.0"
            - name: "gr-0/0/0.0"
          connector_id_advertise: false
          description: "Configured by Ansible Content Team"
    state: replaced

# After state
# -----------
#
# admin@vsrx# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     description "Configured by Ansible Content Team";
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.57.255.1:37;
#     vrf-import test-policy;
#     vrf-export test-policy;
# }

# Using overridden
#
# Before state
# ------------
#
# admin@vsrx# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     description "Configured by Ansible Content Team";
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.57.255.1:37;
#     vrf-import test-policy;
#     vrf-export test-policy;
# }

- name: Override Junos routing-instances configuration
  junipernetworks.junos.junos_routing_instances:
    config:
      - name: "test"
        type: "vrf"
        route_distinguisher: "10.58.255.1:37"
        vrf_imports:
          - "test-policy"
        vrf_exports:
          - "test-policy"
          - "test-policy-1"
        interfaces:
          - name: "sp-0/0/0.0"
          - name: "gr-0/0/0.0"
        connector_id_advertise: true
      - name: "forwardinst"
        type: "forwarding"
        description: "Configured by Ansible Content Team"
      - name: "vtest1"
        type: "virtual-router"
    state: overridden

# After state
# -----------
#
# admin@vsrx# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.58.255.1:37;
#     vrf-import test-policy;
#     vrf-export [ test-policy test-policy-1 ];
#     connector-id-advertise;
# }
# vtest1 {
#     instance-type virtual-router;
# }


# Using deleted
#
# Before state
# ------------
#
# admin@vsrx# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.58.255.1:37;
#     vrf-import test-policy;
#     vrf-export [ test-policy test-policy-1 ];
#     connector-id-advertise;
# }

- name: Delete provided junos routing-instamce
  junipernetworks.junos.junos_routing_instances:
    config:
      - name: "test"
    state: deleted

# After state
# -----------
#
# admin@vsrx# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }

# Using deleted without config
#
# Before state
# ------------
#
# admin@vsrx# show routing-instances
# forwardinst {
#     description "Configured by Ansible Content Team";
#     instance-type forwarding;
# }
# test {
#     instance-type vrf;
#     interface gr-0/0/0.0; ## 'gr-0/0/0.0' is not defined
#     interface sp-0/0/0.0; ## 'sp-0/0/0.0' is not defined
#     route-distinguisher 10.58.255.1:37;
#     vrf-import test-policy;
#     vrf-export [ test-policy test-policy-1 ];
#     connector-id-advertise;
# }
# vtest1 {
#     instance-type virtual-router;
# }

- name: Delete complete Junos routing-instances config
  junipernetworks.junos.junos_routing_instances:
    config:
    state: deleted

# After state
# -----------
#
# admin@vsrx# show routing-instances
#
# [edit]

- name: Gather Junos BGP address family config
  junipernetworks.junos.junos_routing_instances:
    config:
    state: gathered
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
#    "gathered": {
#         "address_family": [
#             {
#                 "af_type": [
#                     {
#                         "accepted_prefix_limit": {
#                             "idle_timeout_value": 2001,
#                             "limit_threshold": 98,
#                             "maximum": 20
#                         },
#                         "damping": true,
#                         "defer_initial_multipath_build": {
#                             "maximum_delay": 2
#                         },
#                         "type": "signaling"
#                     }
#                 ],
#                 "afi": "evpn"
#             },
#             {
#                 "af_type": [
#                     {
#                         "accepted_prefix_limit": {
#                             "idle_timeout_value": 2000,
#                             "limit_threshold": 99,
#                             "maximum": 20
#                         },
#                         "damping": true,
#                         "defer_initial_multipath_build": {
#                             "maximum_delay": 2
#                         },
#                         "delay_route_advertisements": {
#                             "max_delay_route_age": 20,
#                             "max_delay_routing_uptime": 32000,
#                             "min_delay_inbound_convergence": 32000,
#                             "min_delay_routing_uptime": 23000
#                         },
#                         "graceful_restart_forwarding_state_bit": "from-fib",
#                         "type": "any"
#                     },
#                     {
#                         "legacy_redirect_ip_action": {
#                             "receive": true,
#                             "send": true
#                         },
#                         "loops": 4,
#                         "no_install": true,
#                         "output_queue_priority_expedited": true,
#                         "secondary_independent_resolution": true,
#                         "type": "flow"
#                     },
#                     {
#                         "entropy_label": {
#                             "no_next_hop_validation": true
#                         },
#                         "explicit_null": {
#                             "connected_only": true
#                         },
#                         "per_group_label": true,
#                         "per_prefix_label": true,
#                         "prefix_limit": {
#                             "forever": true,
#                             "limit_threshold": 99,
#                             "maximum": 20
#                         },
#                         "resolve_vpn": true,
#                         "rib": "inet.3",
#                         "route_refresh_priority_priority": 3,
#                         "type": "labeled-unicast"
#                     },
#                     {
#                         "extended_nexthop": true,
#                         "extended_nexthop_color": true,
#                         "local_ipv4_address": "9.9.9.9",
#                         "type": "unicast"
#                     }
#                 ],
#                 "afi": "inet"
#             }
#         ]
#     }
#
# Using parsed
# parsed.cfg
# ------------
# <?xml version="1.0" encoding="UTF-8"?>
# <rpc-reply message-id="urn:uuid:0cadb4e8-5bba-47f4-986e-72906227007f">
#     <configuration changed-seconds="1590139550" changed-localtime="2020-05-22 09:25:50 UTC">
#         <version>18.4R1-S2.4</version>
#         <routing-instances>
#             <instance>
#                 <name>forwardinst</name>
#                 <description>Configured by Ansible Content Team</description>
#                 <instance-type>forwarding</instance-type>
#             </instance>
#             <instance>
#                 <name>test</name>
#                 <instance-type>vrf</instance-type>
#                 <interface>
#                     <name>gr-0/0/0.0</name>
#                 </interface>
#                 <interface>
#                     <name>sp-0/0/0.0</name>
#                 </interface>
#                 <route-distinguisher>
#                     <rd-type>10.58.255.1:37</rd-type>
#                 </route-distinguisher>
#                 <vrf-import>test-policy</vrf-import>
#                 <vrf-export>test-policy</vrf-export>
#                 <vrf-export>test-policy-1</vrf-export>
#                 <connector-id-advertise/>
#             </instance>
#         </routing-instances>
#     </configuration>
# </rpc-reply>

- name: Parse routing instance running config
  junipernetworks.junos.junos_routing_instances:
    running_config: "{{ lookup('file', './parsed.cfg') }}"
    state: parsed
#
#
# -------------------------
# Module Execution Result
# -------------------------
#
#
# "parsed":  [
#         {
#             "description": "Configured by Ansible Content Team",
#             "name": "forwardinst",
#             "type": "forwarding"
#         },
#         {
#             "connector_id_advertise": true,
#             "interfaces": [
#                 {
#                     "name": "gr-0/0/0.0"
#                 },
#                 {
#                     "name": "sp-0/0/0.0"
#                 }
#             ],
#             "name": "test",
#             "route_distinguisher": "10.58.255.1:37",
#             "type": "vrf",
#             "vrf_exports": [
#                 "test-policy",
#                 "test-policy-1"
#             ],
#             "vrf_imports": [
#                 "test-policy"
#             ]
#         }
#     ]
#
#
# Using rendered
#
#
- name: Render the xml for provided  configuration
  junipernetworks.junos.junos_routing_instances:
    config:
      - name: "test"
        type: "vrf"
        route_distinguisher: "10.58.255.1:37"
        vrf_imports:
          - "test-policy"
        vrf_exports:
          - "test-policy"
          - "test-policy-1"
        interfaces:
          - name: "sp-0/0/0.0"
          - name: "gr-0/0/0.0"
        connector_id_advertise: true
      - name: "forwardinst"
        type: "forwarding"
        description: "Configured by Ansible Content Team"
    state: rendered

#
#
# -------------------------
# Module Execution Result
# -------------------------
#
#
# "rendered": "<nc:routing-instances xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">
# <nc:instance><nc:name>test</nc:name><nc:connector-id-advertise/><nc:instance-type>vrf</nc:instance-type>
# <nc:interface><nc:name>sp-0/0/0.0</nc:name></nc:interface><nc:interface><nc:name>gr-0/0/0.0</nc:name></nc:interface>
# <nc:route-distinguisher><nc:rd-type>10.58.255.1:37</nc:rd-type></nc:route-distinguisher>
# <nc:vrf-import>test-policy</nc:vrf-import><nc:vrf-export>test-policy</nc:vrf-export>
# <nc:vrf-export>test-policy-1</nc:vrf-export></nc:instance>
# <nc:instance><nc:name>forwardinst</nc:name><nc:description>Configured by Ansible Content Team</nc:description>
# <nc:instance-type>forwarding</nc:instance-type></nc:instance></nc:routing-instances>"
"""
RETURN = """
before:
  description: The configuration prior to the model invocation.
  returned: always
  sample: >
    The configuration returned will always be in the same format
     of the parameters above.
  type: list
after:
  description: The resulting configuration model invocation.
  returned: when changed
  sample: >
    The configuration returned will always be in the same format
     of the parameters above.
  type: list
commands:
  description: The set of commands pushed to the remote device.
  returned: always
  type: list
  sample: ['<nc:routing-instances
    xmlns:nc=\"urn:ietf:params:xml:ns:netconf:base:1.0\">
    <nc:instance>
        <nc:name>test</nc:name>
        <nc:connector-id-advertise/>
        <nc:instance-type>vrf</nc:instance-type>
        <nc:interface>
            <nc:name>sp-0/0/0.0</nc:name>
        </nc:interface>
        <nc:interface>
            <nc:name>gr-0/0/0.0</nc:name>
        </nc:interface>
        <nc:route-distinguisher>
            <nc:rd-type>10.58.255.1:37</nc:rd-type>
        </nc:route-distinguisher>
        <nc:vrf-import>test-policy</nc:vrf-import>
        <nc:vrf-export>test-policy</nc:vrf-export>
        <nc:vrf-export>test-policy-1</nc:vrf-export>
    </nc:instance>
    </routing-instances>
    </configuration>
    </rpc-reply>', 'xml2', 'xml 3']
"""


from ansible.module_utils.basic import AnsibleModule

from ansible_collections.junipernetworks.junos.plugins.module_utils.network.junos.argspec.routing_instances.routing_instances import (
    Routing_instancesArgs,
)
from ansible_collections.junipernetworks.junos.plugins.module_utils.network.junos.config.routing_instances.routing_instances import (
    Routing_instances,
)


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

    :returns: the result form module invocation
    """
    required_if = [
        ("state", "merged", ("config",)),
        ("state", "replaced", ("config",)),
        ("state", "rendered", ("config",)),
        ("state", "overridden", ("config",)),
        ("state", "parsed", ("running_config",)),
    ]
    module = AnsibleModule(
        argument_spec=Routing_instancesArgs.argument_spec,
        required_if=required_if,
        supports_check_mode=True,
    )
    result = Routing_instances(module).execute_module()
    module.exit_json(**result)


if __name__ == "__main__":
    main()
