diff --git a/plugins/module_utils/constants.py b/plugins/module_utils/constants.py index edcf5367..eb35a85c 100644 --- a/plugins/module_utils/constants.py +++ b/plugins/module_utils/constants.py @@ -170,3 +170,5 @@ ORIGINATE_DEFAULT_ROUTE = {"only": "only", "in_addition": "inAddition", "": ""} L3OUT_ROUTING_PROTOCOLS = {"bgp": ["bgp"], "ospf": ["ospf"], "bgpOspf": ["bgp", "ospf"], None: [None], "": None, "bgpospf": "bgpOspf", "ospfbgp": "bgpOspf"} + +ENABLED_DISABLED_BOOLEAN_MAP = {"enabled": True, "disabled": False, True: "enabled", False: "disabled"} diff --git a/plugins/module_utils/template.py b/plugins/module_utils/template.py index 55d235b4..1a450bd6 100644 --- a/plugins/module_utils/template.py +++ b/plugins/module_utils/template.py @@ -207,3 +207,25 @@ def get_l3out_node_routing_policy_object(self, uuid=None, name=None, fail_module "L3Out Node Routing Policy", existing_l3out_node_routing_policy, [KVPair("uuid", uuid) if uuid else KVPair("name", name)], fail_module ) return existing_l3out_node_routing_policy # Query all objects + + def get_l3out_interface_routing_policy_object(self, uuid=None, name=None, fail_module=False): + """ + Get the L3Out Interface Routing Policy by UUID or Name. + :param uuid: UUID of the L3Out Interface Routing Policy to search for -> Str + :param name: Name of the L3Out Interface Routing Policy to search for -> Str + :param fail_module: When match is not found fail the ansible module -> Bool + :return: Dict | None | List[Dict] | List[]: The processed result which could be: + When the UUID | Name is existing in the search list -> Dict + When the UUID | Name is not existing in the search list -> None + When both UUID and Name are None, and the search list is not empty -> List[Dict] + When both UUID and Name are None, and the search list is empty -> List[] + """ + existing_l3out_interface_routing_policy = self.template.get("tenantPolicyTemplate", {}).get("template", {}).get("l3OutIntfPolGroups", []) + if uuid or name: # Query a specific object + return self.get_object_by_key_value_pairs( + "L3Out Interface Routing Policy", + existing_l3out_interface_routing_policy, + [KVPair("uuid", uuid) if uuid else KVPair("name", name)], + fail_module, + ) + return existing_l3out_interface_routing_policy # Query all objects diff --git a/plugins/modules/ndo_l3out_interface_routing_policy.py b/plugins/modules/ndo_l3out_interface_routing_policy.py new file mode 100644 index 00000000..395ec58f --- /dev/null +++ b/plugins/modules/ndo_l3out_interface_routing_policy.py @@ -0,0 +1,856 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2024, Sabari Jaganathan (@sajagana) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +from __future__ import absolute_import, division, print_function + +__metaclass__ = type + +ANSIBLE_METADATA = {"metadata_version": "1.1", "status": ["preview"], "supported_by": "community"} + +DOCUMENTATION = r""" +--- +module: ndo_l3out_interface_routing_policy +short_description: Manage L3Out Interface Routing Policies on Cisco Nexus Dashboard Orchestrator (NDO). +description: +- Manage L3Out Interface Routing Policies on Cisco Nexus Dashboard Orchestrator (NDO). +author: +- Sabari Jaganathan (@sajagana) +options: + template: + description: + - The name of the template. + - The template must be a tenant template. + type: str + required: true + name: + description: + - The name of the L3Out Interface Routing Policy. + type: str + aliases: [ l3out_interface_routing_policy_name ] + uuid: + description: + - The UUID of the L3Out Interface Routing Policy. + - This parameter is required when the O(name) needs to be updated. + type: str + aliases: [ l3out_interface_routing_policy_uuid ] + description: + description: + - The description of the L3Out Interface Routing Policy. + type: str + bfd_multi_hop_settings: + description: + - The BFD MultiHop Settings configuration of the L3Out Interface Routing Policy. + type: dict + suboptions: + state: + description: + - Use C(enabled) to configure the BFD MultiHop Settings. + - Use C(disabled) to remove the BFD MultiHop Settings. + type: str + choices: [ enabled, disabled ] + admin_state: + description: + - The administrative state of the BFD MultiHop Settings. + - Defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - The detection multiplier of the BFD MultiHop Settings. + - Defaults to 3 when unset during creation. + - The value must be between 1 and 50. + type: int + min_receive_interval: + description: + - The minimum receive interval of the BFD MultiHop Settings. + - Defaults to 250 when unset during creation. + - The value must be between 250 and 999 microseconds. + type: int + min_transmit_interval: + description: + - The minimum transmit interval of the BFD MultiHop Settings. + - Defaults to 250 when unset during creation. + - The value must be between 250 and 999 microseconds. + type: int + bfd_settings: + description: + - The BFD Settings of the L3Out Interface Routing Policy. + type: dict + suboptions: + state: + description: + - Use C(enabled) to configure the BFD Settings. + - Use C(disabled) to remove the BFD Settings. + type: str + choices: [ enabled, disabled ] + admin_state: + description: + - The administrative state of the BFD Settings. + - Defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - The detection multiplier of the BFD Settings. + - Defaults to 3 when unset during creation. + - The value must be between 1 and 50. + type: int + min_receive_interval: + description: + - The minimum receive interval of the BFD Settings. + - Defaults to 50 when unset during creation. + - The value must be between 50 and 999 microseconds. + type: int + min_transmit_interval: + description: + - The minimum transmit interval of the BFD Settings. + - Defaults to 50 when unset during creation. + - The value must be between 50 and 999 microseconds. + type: int + echo_receive_interval: + description: + - The echo receive interval of the BFD Settings. + - Defaults to 50 when unset during creation. + - The value must be between 50 and 999. + type: int + echo_admin_state: + description: + - The echo administrative state of the BFD Settings. + - Defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + interface_control: + description: + - The interface control of the BFD Settings. + - Defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + ospf_interface_settings: + description: + - The OSPF Interface Settings of the L3Out Interface Routing Policy. + type: dict + suboptions: + state: + description: + - Use C(enabled) to configure the OSPF Interface Settings. + - Use C(disabled) to remove the OSPF Interface Settings. + type: str + choices: [ enabled, disabled ] + network_type: + description: + - The network type of the OSPF Interface Settings. + - Defaults to C(broadcast) when unset during creation. + type: str + choices: [ broadcast, point_to_point ] + priority: + description: + - The priority of the OSPF Interface Settings. + - Defaults to 1 when unset during creation. + - The value must be between 0 and 255. + type: int + cost_of_interface: + description: + - The cost of the OSPF Interface Settings. + - Defaults to 0 when unset during creation. + - The value must be between 0 and 65535. + type: int + hello_interval: + description: + - The hello interval of the OSPF Interface Settings. + - Defaults to 10 when unset during creation. + - The value must be between 1 and 65535 seconds. + type: int + dead_interval: + description: + - The dead interval of the OSPF Interface Settings. + - Defaults to 40 when unset during creation. + - The value must be between 1 and 65535 seconds. + type: int + retransmit_interval: + description: + - The retransmit interval of the OSPF Interface Settings. + - Defaults to 5 when unset during creation. + - The value must be between 1 and 65535 seconds. + type: int + transmit_delay: + description: + - The transmit delay of the OSPF Interface Settings. + - Defaults to 1 when unset during creation. + - The value must be between 1 and 450 seconds. + type: int + advertise_subnet: + description: + - The advertise subnet of the OSPF Interface Settings. + - Defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + bfd: + description: + - The Bidirectional Forwarding Detection (BFD) of the OSPF Interface Settings. + - Defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + mtu_ignore: + description: + - The Maximum Transmission Unit (MTU) of the OSPF Interface Settings. + - Defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + passive_participation: + description: + - The passive participation of the OSPF Interface Settings. + - Defaults to C(disabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + state: + description: + - Use C(absent) for removing. + - Use C(query) for listing an object or multiple objects. + - Use C(present) for creating or updating. + type: str + choices: [ absent, query, present ] + default: query +extends_documentation_fragment: cisco.mso.modules +""" + +EXAMPLES = r""" +- name: Create a new L3Out Interface Routing Policy with default values + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + name: irp_1 + bfd_settings: + state: enabled + bfd_multi_hop_settings: + state: enabled + state: present + register: irp_1_present + +- name: Update an existing L3Out Interface Routing Policy with UUID + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + uuid: "{{ irp_1_present.current.uuid }}" + name: irp_1_updated + bfd_multi_hop_settings: + admin_state: disabled + detection_multiplier: 10 + min_receive_interval: 255 + min_transmit_interval: 255 + bfd_settings: + admin_state: disabled + detection_multiplier: 10 + min_receive_interval: 266 + min_transmit_interval: 266 + echo_receive_interval: 60 + echo_admin_state: disabled + interface_control: enabled + ospf_interface_settings: + network_type: point_to_point + priority: 10 + cost_of_interface: 100 + advertise_subnet: enabled + bfd: enabled + mtu_ignore: enabled + passive_participation: enabled + hello_interval: 20 + dead_interval: 30 + retransmit_interval: 20 + transmit_delay: 10 + state: present + register: irp_1_present + +- name: Clear an existing L3Out Interface Routing Policy BFD and OSPF interface settings + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + uuid: "{{ irp_1_present.current.uuid }}" + bfd_settings: + state: disabled + ospf_interface_settings: + state: disabled + state: present + +- name: Query a L3Out Interface Routing Policies with name + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + name: irp_1_updated + state: query + register: query_with_name + +- name: Query a L3Out Interface Routing Policies with UUID + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + uuid: "{{ query_with_name.current.uuid }}" + state: query + register: query_with_uuid + +- name: Query all L3Out Interface Routing Policies + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + state: query + register: query_all + +- name: Delete a L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + name: irp_1_updated + state: absent + +- name: Delete a L3Out Interface Routing Policy using UUID + cisco.mso.ndo_l3out_interface_routing_policy: + host: mso_host + username: admin + password: SomeSecretPassword + template: ansible_tenant_template + uuid: "{{ query_with_name.current.uuid }}" + state: absent +""" + +RETURN = r""" +""" + +import copy +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.mso.plugins.module_utils.mso import MSOModule, mso_argument_spec +from ansible_collections.cisco.mso.plugins.module_utils.template import MSOTemplate +from ansible_collections.cisco.mso.plugins.module_utils.constants import ENABLED_DISABLED_BOOLEAN_MAP + + +def main(): + argument_spec = mso_argument_spec() + argument_spec.update( + template=dict(type="str", required=True), + uuid=dict(type="str", aliases=["l3out_interface_routing_policy_uuid"]), + name=dict(type="str", aliases=["l3out_interface_routing_policy_name"]), + description=dict(type="str"), + bfd_settings=dict( + type="dict", + options=dict( + state=dict(type="str", choices=["enabled", "disabled"]), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_receive_interval=dict(type="int"), + min_transmit_interval=dict(type="int"), + echo_receive_interval=dict(type="int"), + echo_admin_state=dict(type="str", choices=["enabled", "disabled"]), + interface_control=dict(type="str", choices=["enabled", "disabled"]), + ), + ), + bfd_multi_hop_settings=dict( + type="dict", + options=dict( + state=dict(type="str", choices=["enabled", "disabled"]), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_receive_interval=dict(type="int"), + min_transmit_interval=dict(type="int"), + ), + ), + ospf_interface_settings=dict( + type="dict", + options=dict( + state=dict(type="str", choices=["enabled", "disabled"]), + network_type=dict(type="str", choices=["broadcast", "point_to_point"]), + priority=dict(type="int"), + cost_of_interface=dict(type="int"), + advertise_subnet=dict(type="str", choices=["enabled", "disabled"]), + bfd=dict(type="str", choices=["enabled", "disabled"]), + mtu_ignore=dict(type="str", choices=["enabled", "disabled"]), + passive_participation=dict(type="str", choices=["enabled", "disabled"]), + hello_interval=dict(type="int"), + dead_interval=dict(type="int"), + retransmit_interval=dict(type="int"), + transmit_delay=dict(type="int"), + ), + ), + state=dict(type="str", default="query", choices=["absent", "query", "present"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "uuid"], True], + ["state", "present", ["name", "uuid"], True], + ], + ) + + mso = MSOModule(module) + + template = module.params.get("template") + name = module.params.get("name") + uuid = module.params.get("uuid") + description = module.params.get("description") + bfd_settings = module.params.get("bfd_settings") + bfd_multi_hop_settings = module.params.get("bfd_multi_hop_settings") + ospf_interface_settings = module.params.get("ospf_interface_settings") + state = module.params.get("state") + + mso_template = MSOTemplate(mso, "tenant", template) + mso_template.validate_template("tenantPolicy") + + l3out_interface_routing_policy = mso_template.get_l3out_interface_routing_policy_object(uuid, name) + + if (uuid or name) and l3out_interface_routing_policy: + mso.existing = mso.previous = copy.deepcopy(l3out_interface_routing_policy.details) # Query a specific object + elif l3out_interface_routing_policy: + mso.existing = l3out_interface_routing_policy # Query all objects + + if state != "query": + interface_routing_policy_path = "/tenantPolicyTemplate/template/l3OutIntfPolGroups/{0}".format( + l3out_interface_routing_policy.index if l3out_interface_routing_policy else "-" + ) + + ops = [] + if state == "present": + if mso.existing: + proposed_payload = copy.deepcopy(mso.existing) + + if name and proposed_payload.get("name") != name: + ops.append(dict(op="replace", path="{0}/name".format(interface_routing_policy_path), value=name)) + proposed_payload["name"] = name + + if description is not None and proposed_payload.get("description") != description: + ops.append(dict(op="replace", path="{0}/description".format(interface_routing_policy_path), value=description)) + proposed_payload["description"] = description + + # BFD MultiHop Settings + if bfd_multi_hop_settings is not None: + if bfd_multi_hop_settings.get("state") == "disabled" and proposed_payload.get("bfdMultiHopPol"): + proposed_payload.pop("bfdMultiHopPol", None) + ops.append(dict(op="remove", path="{0}/bfdMultiHopPol".format(interface_routing_policy_path))) + + elif bfd_multi_hop_settings.get("state") != "disabled": + if not proposed_payload.get("bfdMultiHopPol"): + proposed_payload["bfdMultiHopPol"] = dict() + ops.append(dict(op="replace", path="{0}/bfdMultiHopPol".format(interface_routing_policy_path), value=dict())) + + if bfd_multi_hop_settings.get("admin_state") is not None and proposed_payload.get("bfdMultiHopPol").get( + "adminState" + ) != bfd_multi_hop_settings.get("admin_state"): + proposed_payload["bfdMultiHopPol"]["adminState"] = bfd_multi_hop_settings.get("admin_state") + ops.append( + dict( + op="replace", + path="{0}/bfdMultiHopPol/adminState".format(interface_routing_policy_path), + value=bfd_multi_hop_settings.get("admin_state"), + ) + ) + + if bfd_multi_hop_settings.get("detection_multiplier") is not None and proposed_payload.get("bfdMultiHopPol").get( + "detectionMultiplier" + ) != bfd_multi_hop_settings.get("detection_multiplier"): + proposed_payload["bfdMultiHopPol"]["detectionMultiplier"] = bfd_multi_hop_settings.get("detection_multiplier") + ops.append( + dict( + op="replace", + path="{0}/bfdMultiHopPol/detectionMultiplier".format(interface_routing_policy_path), + value=bfd_multi_hop_settings.get("detection_multiplier"), + ) + ) + + if bfd_multi_hop_settings.get("min_receive_interval") is not None and proposed_payload.get("bfdMultiHopPol").get( + "minRxInterval" + ) != bfd_multi_hop_settings.get("min_receive_interval"): + proposed_payload["bfdMultiHopPol"]["minRxInterval"] = bfd_multi_hop_settings.get("min_receive_interval") + ops.append( + dict( + op="replace", + path="{0}/bfdMultiHopPol/minRxInterval".format(interface_routing_policy_path), + value=bfd_multi_hop_settings.get("min_receive_interval"), + ) + ) + + if bfd_multi_hop_settings.get("min_transmit_interval") is not None and proposed_payload.get("bfdMultiHopPol").get( + "minTxInterval" + ) != bfd_multi_hop_settings.get("min_transmit_interval"): + proposed_payload["bfdMultiHopPol"]["minTxInterval"] = bfd_multi_hop_settings.get("min_transmit_interval") + ops.append( + dict( + op="replace", + path="{0}/bfdMultiHopPol/minTxInterval".format(interface_routing_policy_path), + value=bfd_multi_hop_settings.get("min_transmit_interval"), + ) + ) + + # BFD Settings + if bfd_settings is not None: + if bfd_settings.get("state") == "disabled" and proposed_payload.get("bfdPol"): + proposed_payload.pop("bfdPol", None) + ops.append(dict(op="remove", path="{0}/bfdPol".format(interface_routing_policy_path))) + + elif bfd_settings.get("state") != "disabled": + if not proposed_payload.get("bfdPol"): + proposed_payload["bfdPol"] = dict() + ops.append(dict(op="replace", path="{0}/bfdPol".format(interface_routing_policy_path), value=dict())) + + if bfd_settings.get("admin_state") is not None and proposed_payload.get("bfdPol").get("adminState") != bfd_settings.get("admin_state"): + proposed_payload["bfdPol"]["adminState"] = bfd_settings.get("admin_state") + ops.append( + dict( + op="replace", + path="{0}/bfdPol/adminState".format(interface_routing_policy_path), + value=bfd_settings.get("admin_state"), + ) + ) + + if bfd_settings.get("detection_multiplier") is not None and proposed_payload.get("bfdPol").get("detectionMultiplier") != bfd_settings.get( + "detection_multiplier" + ): + proposed_payload["bfdPol"]["detectionMultiplier"] = bfd_settings.get("detection_multiplier") + ops.append( + dict( + op="replace", + path="{0}/bfdPol/detectionMultiplier".format(interface_routing_policy_path), + value=bfd_settings.get("detection_multiplier"), + ) + ) + + if bfd_settings.get("min_receive_interval") is not None and proposed_payload.get("bfdPol").get("minRxInterval") != bfd_settings.get( + "min_receive_interval" + ): + proposed_payload["bfdPol"]["minRxInterval"] = bfd_settings.get("min_receive_interval") + ops.append( + dict( + op="replace", + path="{0}/bfdPol/minRxInterval".format(interface_routing_policy_path), + value=bfd_settings.get("min_receive_interval"), + ) + ) + + if bfd_settings.get("min_transmit_interval") is not None and proposed_payload.get("bfdPol").get("minTxInterval") != bfd_settings.get( + "min_transmit_interval" + ): + proposed_payload["bfdPol"]["minTxInterval"] = bfd_settings.get("min_transmit_interval") + ops.append( + dict( + op="replace", + path="{0}/bfdPol/minTxInterval".format(interface_routing_policy_path), + value=bfd_settings.get("min_transmit_interval"), + ) + ) + + if bfd_settings.get("echo_receive_interval") is not None and proposed_payload.get("bfdPol").get("echoRxInterval") != bfd_settings.get( + "echo_receive_interval" + ): + proposed_payload["bfdPol"]["echoRxInterval"] = bfd_settings.get("echo_receive_interval") + ops.append( + dict( + op="replace", + path="{0}/bfdPol/echoRxInterval".format(interface_routing_policy_path), + value=bfd_settings.get("echo_receive_interval"), + ) + ) + + if bfd_settings.get("echo_admin_state") is not None and proposed_payload.get("bfdPol").get("echoAdminState") != bfd_settings.get( + "echo_admin_state" + ): + proposed_payload["bfdPol"]["echoAdminState"] = bfd_settings.get("echo_admin_state") + ops.append( + dict( + op="replace", + path="{0}/bfdPol/echoAdminState".format(interface_routing_policy_path), + value=bfd_settings.get("echo_admin_state"), + ) + ) + + interface_control_value = ENABLED_DISABLED_BOOLEAN_MAP.get(bfd_settings.get("interface_control")) + if interface_control_value is not None and proposed_payload.get("bfdPol").get("gracefulRestartHelper") is not interface_control_value: + proposed_payload["bfdPol"]["gracefulRestartHelper"] = interface_control_value + ops.append( + dict( + op="replace", + path="{0}/bfdPol/gracefulRestartHelper".format(interface_routing_policy_path), + value=interface_control_value, + ) + ) + + # OSPF Interface Settings + if ospf_interface_settings is not None: + if ospf_interface_settings.get("state") == "disabled" and proposed_payload.get("ospfIntfPol"): + proposed_payload.pop("ospfIntfPol", None) + ops.append(dict(op="remove", path="{0}/ospfIntfPol".format(interface_routing_policy_path))) + + elif ospf_interface_settings.get("state") != "disabled": + if not proposed_payload.get("ospfIntfPol"): + proposed_payload["ospfIntfPol"] = dict() + proposed_payload["ospfIntfPol"]["ifControl"] = dict() + ops.append(dict(op="replace", path="{0}/ospfIntfPol".format(interface_routing_policy_path), value=dict())) + ops.append(dict(op="replace", path="{0}/ospfIntfPol/ifControl".format(interface_routing_policy_path), value=dict())) + + network_type_value = get_ospf_network_type(ospf_interface_settings.get("network_type")) + if network_type_value is not None and proposed_payload.get("ospfIntfPol").get("networkType") != network_type_value: + proposed_payload["ospfIntfPol"]["networkType"] = network_type_value + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/networkType".format(interface_routing_policy_path), + value=network_type_value, + ) + ) + + if ospf_interface_settings.get("priority") is not None and proposed_payload.get("ospfIntfPol").get("prio") != ospf_interface_settings.get( + "priority" + ): + proposed_payload["ospfIntfPol"]["prio"] = ospf_interface_settings.get("priority") + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/prio".format(interface_routing_policy_path), + value=ospf_interface_settings.get("priority"), + ) + ) + + if ospf_interface_settings.get("cost_of_interface") is not None and proposed_payload.get("ospfIntfPol").get( + "cost" + ) != ospf_interface_settings.get("cost_of_interface"): + proposed_payload["ospfIntfPol"]["cost"] = ospf_interface_settings.get("cost_of_interface") + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/cost".format(interface_routing_policy_path), + value=ospf_interface_settings.get("cost_of_interface"), + ) + ) + + if ospf_interface_settings.get("hello_interval") is not None and proposed_payload.get("ospfIntfPol").get( + "helloInterval" + ) != ospf_interface_settings.get("hello_interval"): + proposed_payload["ospfIntfPol"]["helloInterval"] = ospf_interface_settings.get("hello_interval") + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/helloInterval".format(interface_routing_policy_path), + value=ospf_interface_settings.get("hello_interval"), + ) + ) + + if ospf_interface_settings.get("dead_interval") is not None and proposed_payload.get("ospfIntfPol").get( + "deadInterval" + ) != ospf_interface_settings.get("dead_interval"): + proposed_payload["ospfIntfPol"]["deadInterval"] = ospf_interface_settings.get("dead_interval") + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/deadInterval".format(interface_routing_policy_path), + value=ospf_interface_settings.get("dead_interval"), + ) + ) + + if ospf_interface_settings.get("retransmit_interval") is not None and proposed_payload.get("ospfIntfPol").get( + "retransmitInterval" + ) != ospf_interface_settings.get("retransmit_interval"): + proposed_payload["ospfIntfPol"]["retransmitInterval"] = ospf_interface_settings.get("retransmit_interval") + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/retransmitInterval".format(interface_routing_policy_path), + value=ospf_interface_settings.get("retransmit_interval"), + ) + ) + + if ospf_interface_settings.get("transmit_delay") is not None and proposed_payload.get("ospfIntfPol").get( + "transmitDelay" + ) != ospf_interface_settings.get("transmit_delay"): + proposed_payload["ospfIntfPol"]["transmitDelay"] = ospf_interface_settings.get("transmit_delay") + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/transmitDelay".format(interface_routing_policy_path), + value=ospf_interface_settings.get("transmit_delay"), + ) + ) + + advertise_subnet_value = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("advertise_subnet")) + if ( + advertise_subnet_value is not None + and proposed_payload.get("ospfIntfPol").get("ifControl").get("advertiseSubnet") is not advertise_subnet_value + ): + proposed_payload["ospfIntfPol"]["ifControl"]["advertiseSubnet"] = advertise_subnet_value + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/ifControl/advertiseSubnet".format(interface_routing_policy_path), + value=advertise_subnet_value, + ) + ) + + bfd_value = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("bfd")) + if bfd_value is not None and proposed_payload.get("ospfIntfPol").get("ifControl").get("bfd") is not bfd_value: + proposed_payload["ospfIntfPol"]["ifControl"]["bfd"] = bfd_value + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/ifControl/bfd".format(interface_routing_policy_path), + value=bfd_value, + ) + ) + + mtu_ignore_value = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("mtu_ignore")) + if mtu_ignore_value is not None and proposed_payload.get("ospfIntfPol").get("ifControl").get("ignoreMtu") is not mtu_ignore_value: + proposed_payload["ospfIntfPol"]["ifControl"]["ignoreMtu"] = mtu_ignore_value + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/ifControl/ignoreMtu".format(interface_routing_policy_path), + value=mtu_ignore_value, + ) + ) + + passive_participation_value = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("passive_participation")) + if ( + passive_participation_value is not None + and proposed_payload.get("ospfIntfPol").get("ifControl").get("passiveParticipation") is not passive_participation_value + ): + proposed_payload["ospfIntfPol"]["ifControl"]["passiveParticipation"] = passive_participation_value + ops.append( + dict( + op="replace", + path="{0}/ospfIntfPol/ifControl/passiveParticipation".format(interface_routing_policy_path), + value=passive_participation_value, + ) + ) + + mso.sanitize(proposed_payload) + else: + payload = dict(name=name, description=description) + + # OSPF Interface Settings + if ospf_interface_settings is not None: + ospf_interface_pol = dict() + interface_controls = dict() + + if ospf_interface_settings.get("advertise_subnet"): + interface_controls["advertiseSubnet"] = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("advertise_subnet")) + + if ospf_interface_settings.get("bfd"): + interface_controls["bfd"] = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("bfd")) + + if ospf_interface_settings.get("mtu_ignore"): + interface_controls["ignoreMtu"] = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("mtu_ignore")) + + if ospf_interface_settings.get("passive_participation"): + interface_controls["passiveParticipation"] = ENABLED_DISABLED_BOOLEAN_MAP.get(ospf_interface_settings.get("passive_participation")) + + if interface_controls: + ospf_interface_pol["ifControl"] = interface_controls + + if ospf_interface_settings.get("network_type"): + ospf_interface_pol["networkType"] = get_ospf_network_type(ospf_interface_settings.get("network_type")) + + if ospf_interface_settings.get("priority"): + ospf_interface_pol["prio"] = ospf_interface_settings.get("priority") + + if ospf_interface_settings.get("cost_of_interface"): + ospf_interface_pol["cost"] = ospf_interface_settings.get("cost_of_interface") + + if ospf_interface_settings.get("hello_interval"): + ospf_interface_pol["helloInterval"] = ospf_interface_settings.get("hello_interval") + + if ospf_interface_settings.get("dead_interval"): + ospf_interface_pol["deadInterval"] = ospf_interface_settings.get("dead_interval") + + if ospf_interface_settings.get("retransmit_interval"): + ospf_interface_pol["retransmitInterval"] = ospf_interface_settings.get("retransmit_interval") + + if ospf_interface_settings.get("transmit_delay"): + ospf_interface_pol["transmitDelay"] = ospf_interface_settings.get("transmit_delay") + + if ospf_interface_pol or ospf_interface_settings.get("state") == "enabled": + payload["ospfIntfPol"] = ospf_interface_pol + + # BFD MultiHop Settings + if bfd_multi_hop_settings is not None: + bfd_multi_hop_pol = dict() + if bfd_multi_hop_settings.get("admin_state"): + bfd_multi_hop_pol["adminState"] = bfd_multi_hop_settings.get("admin_state") + + if bfd_multi_hop_settings.get("detection_multiplier"): + bfd_multi_hop_pol["detectionMultiplier"] = bfd_multi_hop_settings.get("detection_multiplier") + + if bfd_multi_hop_settings.get("min_receive_interval"): + bfd_multi_hop_pol["minRxInterval"] = bfd_multi_hop_settings.get("min_receive_interval") + + if bfd_multi_hop_settings.get("min_transmit_interval"): + bfd_multi_hop_pol["minTxInterval"] = bfd_multi_hop_settings.get("min_transmit_interval") + + if bfd_multi_hop_pol or bfd_multi_hop_settings.get("state") == "enabled": + payload["bfdMultiHopPol"] = bfd_multi_hop_pol + + # BFD Settings + if bfd_settings is not None: + bfd_settings_map = dict() + + if bfd_settings.get("admin_state"): + bfd_settings_map["adminState"] = bfd_settings.get("admin_state") + + if bfd_settings.get("detection_multiplier"): + bfd_settings_map["detectionMultiplier"] = bfd_settings.get("detection_multiplier") + + if bfd_settings.get("min_receive_interval"): + bfd_settings_map["minRxInterval"] = bfd_settings.get("min_receive_interval") + + if bfd_settings.get("min_transmit_interval"): + bfd_settings_map["minTxInterval"] = bfd_settings.get("min_transmit_interval") + + if bfd_settings.get("echo_receive_interval"): + bfd_settings_map["echoRxInterval"] = bfd_settings.get("echo_receive_interval") + + if bfd_settings.get("echo_admin_state"): + bfd_settings_map["echoAdminState"] = bfd_settings.get("echo_admin_state") + + if bfd_settings.get("interface_control"): + bfd_settings_map["ifControl"] = ENABLED_DISABLED_BOOLEAN_MAP.get(bfd_settings.get("interface_control")) + + if bfd_settings_map or bfd_settings.get("state") == "enabled": + payload["bfdPol"] = bfd_settings_map + + ops.append(dict(op="add", path=interface_routing_policy_path, value=copy.deepcopy(payload))) + + mso.sanitize(payload) + elif state == "absent": + if mso.existing: + ops.append(dict(op="remove", path=interface_routing_policy_path)) + + if not module.check_mode and ops: + mso_template.template = mso.request(mso_template.template_path, method="PATCH", data=ops) + l3out_interface_routing_policy = mso_template.get_l3out_interface_routing_policy_object(uuid, name) + if l3out_interface_routing_policy: + mso.existing = l3out_interface_routing_policy.details # When the state is present + else: + mso.existing = {} # When the state is absent + elif module.check_mode and state != "query": # When the state is present/absent with check mode + mso.existing = mso.proposed if state == "present" else {} + + mso.exit_json() + + +def get_ospf_network_type(network_type): + return "pointToPoint" if network_type == "point_to_point" else network_type + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/ndo_l3out_interface_routing_policy/aliases b/tests/integration/targets/ndo_l3out_interface_routing_policy/aliases new file mode 100644 index 00000000..5042c9c0 --- /dev/null +++ b/tests/integration/targets/ndo_l3out_interface_routing_policy/aliases @@ -0,0 +1,2 @@ +# No ACI MultiSite infrastructure, so not enabled +# unsupported diff --git a/tests/integration/targets/ndo_l3out_interface_routing_policy/tasks/main.yml b/tests/integration/targets/ndo_l3out_interface_routing_policy/tasks/main.yml new file mode 100644 index 00000000..95d42fef --- /dev/null +++ b/tests/integration/targets/ndo_l3out_interface_routing_policy/tasks/main.yml @@ -0,0 +1,1084 @@ +# Test code for the MSO modules +# Copyright: (c) 2024, Sabari Jaganathan (@sajagana) + +# GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) + +- name: Test that we have an ACI MultiSite host, username and password + ansible.builtin.fail: + msg: "Please define the following variables: mso_hostname, mso_username and mso_password." + when: mso_hostname is not defined or mso_username is not defined or mso_password is not defined + +# CLEAN ENVIRONMENT +- name: Set vars + ansible.builtin.set_fact: + mso_info: &mso_info + host: "{{ mso_hostname }}" + username: "{{ mso_username }}" + password: "{{ mso_password }}" + validate_certs: "{{ mso_validate_certs | default(false) }}" + use_ssl: "{{ mso_use_ssl | default(true) }}" + use_proxy: "{{ mso_use_proxy | default(true) }}" + output_level: '{{ mso_output_level | default("info") }}' + +# QUERY VERSION +- name: Query MSO version + cisco.mso.mso_version: + <<: *mso_info + state: query + register: version + +- name: Execute tasks only for MSO version > 4.3 + when: version.current.version is version('4.3', '>=') + block: + - name: Ensure sites exists + cisco.mso.mso_site: + <<: *mso_info + site: "{{ item.site }}" + apic_username: "{{ apic_username }}" + apic_password: "{{ apic_password }}" + apic_site_id: "{{ item.apic_site_id }}" + urls: + - https://{{ apic_hostname }} + state: present + loop: + - { site: "ansible_test", apic_site_id: 101 } + - { site: "ansible_test_2", apic_site_id: 102 } + + - name: Ensure tenants exist + cisco.mso.mso_tenant: + <<: *mso_info + tenant: "{{ item }}" + users: + - "{{ mso_username }}" + sites: + - '{{ mso_site | default("ansible_test") }}' + - ansible_test_2 + state: present + loop: + - ansible_test + + - name: Ensure templates do not exist + cisco.mso.ndo_template: &template_absent + <<: *mso_info + name: '{{ ansible_tenant_template | default("ansible_test") }}' + template_type: tenant + tenant: ansible_test + state: absent + + - name: Ensure templates exist + cisco.mso.ndo_template: + <<: *template_absent + state: present + + # Test Part + - name: Query all L3Out Interface Routing Policy when it is empty + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + state: query + register: query_all_with_empty_template + + - name: Assertion check for query all L3Out Interface Routing Policy when it is empty + ansible.builtin.assert: + that: + - query_all_with_empty_template is not changed + - query_all_with_empty_template.current == {} + + - name: Create a new L3Out Interface Routing Policy with default values - check_mode + cisco.mso.ndo_l3out_interface_routing_policy: &cm_irp_1_present + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_1 + bfd_settings: + state: enabled + bfd_multi_hop_settings: + state: enabled + state: present + output_level: debug + check_mode: true + register: cm_irp_1_present + + - name: Assertion check for create a new L3Out Interface Routing Policy with default values - check_mode + ansible.builtin.assert: + that: + - cm_irp_1_present is changed + - cm_irp_1_present.current.bfdMultiHopPol == {} + - cm_irp_1_present.current.bfdPol == {} + - cm_irp_1_present.current.name == "irp_1" + - cm_irp_1_present.previous == {} + - cm_irp_1_present.proposed.bfdMultiHopPol == {} + - cm_irp_1_present.proposed.bfdPol == {} + - cm_irp_1_present.proposed.name == "irp_1" + + - name: Create a new L3Out Interface Routing Policy with default values - normal_mode + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_present + register: nm_irp_1_present + + - name: Assertion check for create a new L3Out Interface Routing Policy with default values - normal_mode + ansible.builtin.assert: + that: + - nm_irp_1_present is changed + - nm_irp_1_present.current.bfdMultiHopPol.adminState == "enabled" + - nm_irp_1_present.current.bfdMultiHopPol.detectionMultiplier == 3 + - nm_irp_1_present.current.bfdMultiHopPol.minRxInterval == 250 + - nm_irp_1_present.current.bfdMultiHopPol.minTxInterval == 250 + - nm_irp_1_present.current.bfdPol.adminState == "enabled" + - nm_irp_1_present.current.bfdPol.detectionMultiplier == 3 + - nm_irp_1_present.current.bfdPol.echoAdminState == "enabled" + - nm_irp_1_present.current.bfdPol.echoRxInterval == 50 + - nm_irp_1_present.current.bfdPol.ifControl == false + - nm_irp_1_present.current.bfdPol.minRxInterval == 50 + - nm_irp_1_present.current.bfdPol.minTxInterval == 50 + - nm_irp_1_present.current.name == "irp_1" + - nm_irp_1_present.current.uuid is defined + - nm_irp_1_present.previous == {} + + - name: Create a new L3Out Interface Routing Policy with default values - normal_mode again + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_present + register: nm_irp_1_present_again + + - name: Assertion check for create a new L3Out Interface Routing Policy with default values - normal_mode again + ansible.builtin.assert: + that: + - nm_irp_1_present_again is not changed + - nm_irp_1_present_again.current.bfdMultiHopPol.adminState == "enabled" + - nm_irp_1_present_again.current.bfdMultiHopPol.detectionMultiplier == 3 + - nm_irp_1_present_again.current.bfdMultiHopPol.minRxInterval == 250 + - nm_irp_1_present_again.current.bfdMultiHopPol.minTxInterval == 250 + - nm_irp_1_present_again.current.bfdPol.adminState == "enabled" + - nm_irp_1_present_again.current.bfdPol.detectionMultiplier == 3 + - nm_irp_1_present_again.current.bfdPol.echoAdminState == "enabled" + - nm_irp_1_present_again.current.bfdPol.echoRxInterval == 50 + - nm_irp_1_present_again.current.bfdPol.ifControl == false + - nm_irp_1_present_again.current.bfdPol.minRxInterval == 50 + - nm_irp_1_present_again.current.bfdPol.minTxInterval == 50 + - nm_irp_1_present_again.current.name == "irp_1" + - nm_irp_1_present_again.current.uuid is defined + - nm_irp_1_present_again.previous.bfdMultiHopPol.adminState == "enabled" + - nm_irp_1_present_again.previous.bfdMultiHopPol.detectionMultiplier == 3 + - nm_irp_1_present_again.previous.bfdMultiHopPol.minRxInterval == 250 + - nm_irp_1_present_again.previous.bfdMultiHopPol.minTxInterval == 250 + - nm_irp_1_present_again.previous.bfdPol.adminState == "enabled" + - nm_irp_1_present_again.previous.bfdPol.detectionMultiplier == 3 + - nm_irp_1_present_again.previous.bfdPol.echoAdminState == "enabled" + - nm_irp_1_present_again.previous.bfdPol.echoRxInterval == 50 + - nm_irp_1_present_again.previous.bfdPol.ifControl == false + - nm_irp_1_present_again.previous.bfdPol.minRxInterval == 50 + - nm_irp_1_present_again.previous.bfdPol.minTxInterval == 50 + - nm_irp_1_present_again.previous.name == "irp_1" + - nm_irp_1_present_again.previous.uuid is defined + + - name: Update irp_1 L3Out Interface Routing Policy - check_mode + cisco.mso.ndo_l3out_interface_routing_policy: &cm_irp_1_update + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + uuid: "{{ nm_irp_1_present_again.current.uuid }}" + name: irp_1_update + description: Updated + bfd_multi_hop_settings: + admin_state: disabled + detection_multiplier: 10 + min_receive_interval: 255 + min_transmit_interval: 255 + bfd_settings: + admin_state: disabled + detection_multiplier: 10 + min_receive_interval: 266 + min_transmit_interval: 266 + echo_receive_interval: 60 + echo_admin_state: disabled + interface_control: enabled + ospf_interface_settings: + network_type: point_to_point + priority: 10 + cost_of_interface: 100 + advertise_subnet: enabled + bfd: enabled + mtu_ignore: enabled + passive_participation: enabled + hello_interval: 20 + dead_interval: 30 + retransmit_interval: 20 + transmit_delay: 10 + state: present + output_level: debug + check_mode: true + register: cm_irp_1_update + + - name: Assertion check for update irp_1 L3Out Interface Routing Policy - check_mode + ansible.builtin.assert: + that: + - cm_irp_1_update is changed + - cm_irp_1_update.current.bfdMultiHopPol.adminState == "disabled" + - cm_irp_1_update.current.bfdMultiHopPol.detectionMultiplier == 10 + - cm_irp_1_update.current.bfdMultiHopPol.minRxInterval == 255 + - cm_irp_1_update.current.bfdMultiHopPol.minTxInterval == 255 + - cm_irp_1_update.current.bfdPol.adminState == "disabled" + - cm_irp_1_update.current.bfdPol.detectionMultiplier == 10 + - cm_irp_1_update.current.bfdPol.echoAdminState == "disabled" + - cm_irp_1_update.current.bfdPol.echoRxInterval == 60 + - cm_irp_1_update.current.bfdPol.gracefulRestartHelper == true + - cm_irp_1_update.current.bfdPol.ifControl == false + - cm_irp_1_update.current.bfdPol.minRxInterval == 266 + - cm_irp_1_update.current.bfdPol.minTxInterval == 266 + - cm_irp_1_update.current.description == "Updated" + - cm_irp_1_update.current.name == "irp_1_update" + - cm_irp_1_update.current.ospfIntfPol.cost == 100 + - cm_irp_1_update.current.ospfIntfPol.deadInterval == 30 + - cm_irp_1_update.current.ospfIntfPol.helloInterval == 20 + - cm_irp_1_update.current.ospfIntfPol.ifControl.advertiseSubnet == true + - cm_irp_1_update.current.ospfIntfPol.ifControl.bfd == true + - cm_irp_1_update.current.ospfIntfPol.ifControl.ignoreMtu == true + - cm_irp_1_update.current.ospfIntfPol.ifControl.passiveParticipation == true + - cm_irp_1_update.current.ospfIntfPol.networkType == "pointToPoint" + - cm_irp_1_update.current.ospfIntfPol.prio == 10 + - cm_irp_1_update.current.ospfIntfPol.retransmitInterval == 20 + - cm_irp_1_update.current.ospfIntfPol.transmitDelay == 10 + - cm_irp_1_update.current.uuid is defined + - cm_irp_1_update.previous.bfdMultiHopPol.adminState == "enabled" + - cm_irp_1_update.previous.bfdMultiHopPol.detectionMultiplier == 3 + - cm_irp_1_update.previous.bfdMultiHopPol.minRxInterval == 250 + - cm_irp_1_update.previous.bfdMultiHopPol.minTxInterval == 250 + - cm_irp_1_update.previous.bfdPol.adminState == "enabled" + - cm_irp_1_update.previous.bfdPol.detectionMultiplier == 3 + - cm_irp_1_update.previous.bfdPol.echoAdminState == "enabled" + - cm_irp_1_update.previous.bfdPol.echoRxInterval == 50 + - cm_irp_1_update.previous.bfdPol.ifControl == false + - cm_irp_1_update.previous.bfdPol.minRxInterval == 50 + - cm_irp_1_update.previous.bfdPol.minTxInterval == 50 + - cm_irp_1_update.previous.name == "irp_1" + - cm_irp_1_update.previous.uuid is defined + - cm_irp_1_update.proposed.bfdMultiHopPol.adminState == "disabled" + - cm_irp_1_update.proposed.bfdMultiHopPol.detectionMultiplier == 10 + - cm_irp_1_update.proposed.bfdMultiHopPol.minRxInterval == 255 + - cm_irp_1_update.proposed.bfdMultiHopPol.minTxInterval == 255 + - cm_irp_1_update.proposed.bfdPol.adminState == "disabled" + - cm_irp_1_update.proposed.bfdPol.detectionMultiplier == 10 + - cm_irp_1_update.proposed.bfdPol.echoAdminState == "disabled" + - cm_irp_1_update.proposed.bfdPol.echoRxInterval == 60 + - cm_irp_1_update.proposed.bfdPol.gracefulRestartHelper == true + - cm_irp_1_update.proposed.bfdPol.ifControl == false + - cm_irp_1_update.proposed.bfdPol.minRxInterval == 266 + - cm_irp_1_update.proposed.bfdPol.minTxInterval == 266 + - cm_irp_1_update.proposed.description == "Updated" + - cm_irp_1_update.proposed.name == "irp_1_update" + - cm_irp_1_update.proposed.ospfIntfPol.cost == 100 + - cm_irp_1_update.proposed.ospfIntfPol.deadInterval == 30 + - cm_irp_1_update.proposed.ospfIntfPol.helloInterval == 20 + - cm_irp_1_update.proposed.ospfIntfPol.ifControl.advertiseSubnet == true + - cm_irp_1_update.proposed.ospfIntfPol.ifControl.bfd == true + - cm_irp_1_update.proposed.ospfIntfPol.ifControl.ignoreMtu == true + - cm_irp_1_update.proposed.ospfIntfPol.ifControl.passiveParticipation == true + - cm_irp_1_update.proposed.ospfIntfPol.networkType == "pointToPoint" + - cm_irp_1_update.proposed.ospfIntfPol.prio == 10 + - cm_irp_1_update.proposed.ospfIntfPol.retransmitInterval == 20 + - cm_irp_1_update.proposed.ospfIntfPol.transmitDelay == 10 + - cm_irp_1_update.proposed.uuid is defined + + - name: Update irp_1 L3Out Interface Routing Policy - normal_mode + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_update + register: nm_irp_1_update + + - name: Assertion check for update irp_1 L3Out Interface Routing Policy - normal_mode + ansible.builtin.assert: + that: + - nm_irp_1_update is changed + - nm_irp_1_update.current.bfdMultiHopPol.adminState == "disabled" + - nm_irp_1_update.current.bfdMultiHopPol.detectionMultiplier == 10 + - nm_irp_1_update.current.bfdMultiHopPol.minRxInterval == 255 + - nm_irp_1_update.current.bfdMultiHopPol.minTxInterval == 255 + - nm_irp_1_update.current.bfdPol.adminState == "disabled" + - nm_irp_1_update.current.bfdPol.detectionMultiplier == 10 + - nm_irp_1_update.current.bfdPol.echoAdminState == "disabled" + - nm_irp_1_update.current.bfdPol.echoRxInterval == 60 + - nm_irp_1_update.current.bfdPol.ifControl == false + - nm_irp_1_update.current.bfdPol.minRxInterval == 266 + - nm_irp_1_update.current.bfdPol.minTxInterval == 266 + - nm_irp_1_update.current.description == "Updated" + - nm_irp_1_update.current.name == "irp_1_update" + - nm_irp_1_update.current.ospfIntfPol.cost == 100 + - nm_irp_1_update.current.ospfIntfPol.deadInterval == 30 + - nm_irp_1_update.current.ospfIntfPol.helloInterval == 20 + - nm_irp_1_update.current.ospfIntfPol.ifControl.advertiseSubnet == true + - nm_irp_1_update.current.ospfIntfPol.ifControl.bfd == true + - nm_irp_1_update.current.ospfIntfPol.ifControl.ignoreMtu == true + - nm_irp_1_update.current.ospfIntfPol.ifControl.passiveParticipation == true + - nm_irp_1_update.current.ospfIntfPol.networkType == "pointToPoint" + - nm_irp_1_update.current.ospfIntfPol.prio == 10 + - nm_irp_1_update.current.ospfIntfPol.retransmitInterval == 20 + - nm_irp_1_update.current.ospfIntfPol.transmitDelay == 10 + - nm_irp_1_update.current.uuid is defined + - nm_irp_1_update.previous.bfdMultiHopPol.adminState == "enabled" + - nm_irp_1_update.previous.bfdMultiHopPol.detectionMultiplier == 3 + - nm_irp_1_update.previous.bfdMultiHopPol.minRxInterval == 250 + - nm_irp_1_update.previous.bfdMultiHopPol.minTxInterval == 250 + - nm_irp_1_update.previous.bfdPol.adminState == "enabled" + - nm_irp_1_update.previous.bfdPol.detectionMultiplier == 3 + - nm_irp_1_update.previous.bfdPol.echoAdminState == "enabled" + - nm_irp_1_update.previous.bfdPol.echoRxInterval == 50 + - nm_irp_1_update.previous.bfdPol.ifControl == false + - nm_irp_1_update.previous.bfdPol.minRxInterval == 50 + - nm_irp_1_update.previous.bfdPol.minTxInterval == 50 + - nm_irp_1_update.previous.name == "irp_1" + - nm_irp_1_update.previous.uuid is defined + + - name: Update irp_1 L3Out Interface Routing Policy - normal_mode again + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_update + register: nm_irp_1_update_again + + - name: Assertion check for update irp_1 L3Out Interface Routing Policy - normal_mode again + ansible.builtin.assert: + that: + - nm_irp_1_update_again is not changed + - nm_irp_1_update_again.current.bfdMultiHopPol.adminState == "disabled" + - nm_irp_1_update_again.current.bfdMultiHopPol.detectionMultiplier == 10 + - nm_irp_1_update_again.current.bfdMultiHopPol.minRxInterval == 255 + - nm_irp_1_update_again.current.bfdPol.echoAdminState == "disabled" + - nm_irp_1_update_again.current.bfdPol.echoRxInterval == 60 + - nm_irp_1_update_again.current.bfdPol.ifControl == false + - nm_irp_1_update_again.current.bfdPol.minRxInterval == 266 + - nm_irp_1_update_again.current.bfdPol.minTxInterval == 266 + - nm_irp_1_update_again.current.description == "Updated" + - nm_irp_1_update_again.current.name == "irp_1_update" + - nm_irp_1_update_again.current.ospfIntfPol.cost == 100 + - nm_irp_1_update_again.current.ospfIntfPol.ifControl.ignoreMtu == true + - nm_irp_1_update_again.current.ospfIntfPol.ifControl.passiveParticipation == true + - nm_irp_1_update_again.current.ospfIntfPol.networkType == "pointToPoint" + - nm_irp_1_update_again.current.ospfIntfPol.prio == 10 + - nm_irp_1_update_again.current.ospfIntfPol.retransmitInterval == 20 + - nm_irp_1_update_again.current.ospfIntfPol.transmitDelay == 10 + - nm_irp_1_update_again.current.uuid is defined + - nm_irp_1_update_again.previous.bfdMultiHopPol.adminState == "disabled" + - nm_irp_1_update_again.previous.bfdPol.echoRxInterval == 60 + - nm_irp_1_update_again.previous.bfdPol.ifControl == false + - nm_irp_1_update_again.previous.bfdPol.minRxInterval == 266 + - nm_irp_1_update_again.previous.bfdPol.minTxInterval == 266 + - nm_irp_1_update_again.previous.description == "Updated" + - nm_irp_1_update_again.previous.name == "irp_1_update" + - nm_irp_1_update_again.previous.ospfIntfPol.cost == 100 + - nm_irp_1_update_again.previous.ospfIntfPol.deadInterval == 30 + - nm_irp_1_update_again.previous.ospfIntfPol.helloInterval == 20 + - nm_irp_1_update_again.previous.ospfIntfPol.networkType == "pointToPoint" + - nm_irp_1_update_again.previous.ospfIntfPol.prio == 10 + - nm_irp_1_update_again.previous.ospfIntfPol.retransmitInterval == 20 + - nm_irp_1_update_again.previous.ospfIntfPol.transmitDelay == 10 + - nm_irp_1_update_again.previous.uuid is defined + + - name: Clear bfd_multi_hop_settings from irp_1 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_update + bfd_multi_hop_settings: + state: disabled + state: present + register: irp_1_clear_bfd_multi_hop_settings + + - name: Assertion check for clear bfd_multi_hop_settings from irp_1 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_1_clear_bfd_multi_hop_settings is changed + - irp_1_clear_bfd_multi_hop_settings.current.bfdPol.adminState == "disabled" + - irp_1_clear_bfd_multi_hop_settings.current.bfdPol.detectionMultiplier == 10 + - irp_1_clear_bfd_multi_hop_settings.current.bfdPol.minRxInterval == 266 + - irp_1_clear_bfd_multi_hop_settings.current.bfdPol.minTxInterval == 266 + - irp_1_clear_bfd_multi_hop_settings.current.description == "Updated" + - irp_1_clear_bfd_multi_hop_settings.current.name == "irp_1_update" + - irp_1_clear_bfd_multi_hop_settings.current.ospfIntfPol.cost == 100 + - irp_1_clear_bfd_multi_hop_settings.current.ospfIntfPol.deadInterval == 30 + - irp_1_clear_bfd_multi_hop_settings.current.ospfIntfPol.networkType == "pointToPoint" + - irp_1_clear_bfd_multi_hop_settings.current.ospfIntfPol.prio == 10 + - irp_1_clear_bfd_multi_hop_settings.current.ospfIntfPol.retransmitInterval == 20 + - irp_1_clear_bfd_multi_hop_settings.current.ospfIntfPol.transmitDelay == 10 + - irp_1_clear_bfd_multi_hop_settings.current.uuid is defined + - irp_1_clear_bfd_multi_hop_settings.previous.bfdMultiHopPol.adminState == "disabled" + - irp_1_clear_bfd_multi_hop_settings.previous.bfdMultiHopPol.detectionMultiplier == 10 + - irp_1_clear_bfd_multi_hop_settings.previous.bfdMultiHopPol.minRxInterval == 255 + - irp_1_clear_bfd_multi_hop_settings.previous.bfdMultiHopPol.minTxInterval == 255 + - irp_1_clear_bfd_multi_hop_settings.previous.bfdPol.adminState == "disabled" + - irp_1_clear_bfd_multi_hop_settings.previous.bfdPol.minRxInterval == 266 + - irp_1_clear_bfd_multi_hop_settings.previous.bfdPol.minTxInterval == 266 + - irp_1_clear_bfd_multi_hop_settings.previous.description == "Updated" + - irp_1_clear_bfd_multi_hop_settings.previous.name == "irp_1_update" + - irp_1_clear_bfd_multi_hop_settings.previous.ospfIntfPol.cost == 100 + - irp_1_clear_bfd_multi_hop_settings.previous.ospfIntfPol.deadInterval == 30 + - irp_1_clear_bfd_multi_hop_settings.previous.ospfIntfPol.helloInterval == 20 + - irp_1_clear_bfd_multi_hop_settings.previous.ospfIntfPol.prio == 10 + - irp_1_clear_bfd_multi_hop_settings.previous.ospfIntfPol.retransmitInterval == 20 + - irp_1_clear_bfd_multi_hop_settings.previous.ospfIntfPol.transmitDelay == 10 + - irp_1_clear_bfd_multi_hop_settings.previous.uuid is defined + + - name: Clear bfd_settings from irp_1 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_update + bfd_settings: + state: disabled + state: present + register: irp_1_clear_bfd_settings + + - name: Assertion check for clear bfd_settings from irp_1 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_1_clear_bfd_settings is changed + - irp_1_clear_bfd_settings.current.bfdMultiHopPol.adminState == "disabled" + - irp_1_clear_bfd_settings.current.bfdMultiHopPol.detectionMultiplier == 10 + - irp_1_clear_bfd_settings.current.bfdMultiHopPol.minRxInterval == 255 + - irp_1_clear_bfd_settings.current.bfdMultiHopPol.minTxInterval == 255 + - irp_1_clear_bfd_settings.current.description == "Updated" + - irp_1_clear_bfd_settings.current.name == "irp_1_update" + - irp_1_clear_bfd_settings.current.ospfIntfPol.cost == 100 + - irp_1_clear_bfd_settings.current.ospfIntfPol.deadInterval == 30 + - irp_1_clear_bfd_settings.current.ospfIntfPol.networkType == "pointToPoint" + - irp_1_clear_bfd_settings.current.ospfIntfPol.prio == 10 + - irp_1_clear_bfd_settings.current.ospfIntfPol.retransmitInterval == 20 + - irp_1_clear_bfd_settings.current.ospfIntfPol.transmitDelay == 10 + - irp_1_clear_bfd_settings.current.uuid is defined + - irp_1_clear_bfd_settings.previous.bfdPol.adminState == "disabled" + - irp_1_clear_bfd_settings.previous.bfdPol.detectionMultiplier == 10 + - irp_1_clear_bfd_settings.previous.bfdPol.echoAdminState == "disabled" + - irp_1_clear_bfd_settings.previous.bfdPol.echoRxInterval == 60 + - irp_1_clear_bfd_settings.previous.bfdPol.ifControl == false + - irp_1_clear_bfd_settings.previous.bfdPol.minRxInterval == 266 + - irp_1_clear_bfd_settings.previous.bfdPol.minTxInterval == 266 + - irp_1_clear_bfd_settings.previous.description == "Updated" + - irp_1_clear_bfd_settings.previous.name == "irp_1_update" + - irp_1_clear_bfd_settings.previous.ospfIntfPol.cost == 100 + - irp_1_clear_bfd_settings.previous.ospfIntfPol.transmitDelay == 10 + - irp_1_clear_bfd_settings.previous.uuid is defined + + - name: Clear ospf_interface_settings from irp_1 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_update + ospf_interface_settings: + state: disabled + bfd_settings: {} + bfd_multi_hop_settings: {} + state: present + register: irp_1_clear_ospf + + - name: Assertion check for clear ospf_interface_settings from irp_1 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_1_clear_ospf is changed + - irp_1_clear_ospf.current.bfdMultiHopPol.adminState == "disabled" + - irp_1_clear_ospf.current.bfdMultiHopPol.detectionMultiplier == 10 + - irp_1_clear_ospf.current.bfdMultiHopPol.minRxInterval == 255 + - irp_1_clear_ospf.current.bfdPol.minRxInterval == 50 + - irp_1_clear_ospf.current.bfdPol.minTxInterval == 50 + - irp_1_clear_ospf.current.description == "Updated" + - irp_1_clear_ospf.current.name == "irp_1_update" + - irp_1_clear_ospf.current.uuid is defined + - irp_1_clear_ospf.previous.bfdMultiHopPol.adminState == "disabled" + - irp_1_clear_ospf.previous.description == "Updated" + - irp_1_clear_ospf.previous.name == "irp_1_update" + - irp_1_clear_ospf.previous.ospfIntfPol.cost == 100 + - irp_1_clear_ospf.previous.ospfIntfPol.deadInterval == 30 + - irp_1_clear_ospf.previous.ospfIntfPol.ifControl.passiveParticipation == true + - irp_1_clear_ospf.previous.ospfIntfPol.networkType == "pointToPoint" + - irp_1_clear_ospf.previous.ospfIntfPol.prio == 10 + - irp_1_clear_ospf.previous.ospfIntfPol.retransmitInterval == 20 + - irp_1_clear_ospf.previous.ospfIntfPol.transmitDelay == 10 + - irp_1_clear_ospf.previous.uuid is defined + + - name: Enable ospf_interface_settings to irp_1 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *cm_irp_1_update + ospf_interface_settings: + state: enabled + bfd_settings: {} + bfd_multi_hop_settings: {} + state: present + register: irp_1_enable_ospf + + - name: Assertion check for enable ospf_interface_settings to irp_1 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_1_enable_ospf is changed + - irp_1_enable_ospf.current.bfdMultiHopPol.adminState == "disabled" + - irp_1_enable_ospf.current.bfdMultiHopPol.detectionMultiplier == 10 + - irp_1_enable_ospf.current.bfdMultiHopPol.minRxInterval == 255 + - irp_1_enable_ospf.current.bfdMultiHopPol.minTxInterval == 255 + - irp_1_enable_ospf.current.bfdPol.adminState == "enabled" + - irp_1_enable_ospf.current.bfdPol.detectionMultiplier == 3 + - irp_1_enable_ospf.current.bfdPol.echoAdminState == "enabled" + - irp_1_enable_ospf.current.bfdPol.echoRxInterval == 50 + - irp_1_enable_ospf.current.bfdPol.ifControl == false + - irp_1_enable_ospf.current.bfdPol.minRxInterval == 50 + - irp_1_enable_ospf.current.bfdPol.minTxInterval == 50 + - irp_1_enable_ospf.current.description == "Updated" + - irp_1_enable_ospf.current.name == "irp_1_update" + - irp_1_enable_ospf.current.ospfIntfPol.cost == 0 + - irp_1_enable_ospf.current.ospfIntfPol.deadInterval == 40 + - irp_1_enable_ospf.current.ospfIntfPol.helloInterval == 10 + - irp_1_enable_ospf.current.ospfIntfPol.ifControl.advertiseSubnet == false + - irp_1_enable_ospf.current.ospfIntfPol.ifControl.bfd == false + - irp_1_enable_ospf.current.ospfIntfPol.ifControl.ignoreMtu == false + - irp_1_enable_ospf.current.ospfIntfPol.ifControl.passiveParticipation == false + - irp_1_enable_ospf.current.ospfIntfPol.networkType == "broadcast" + - irp_1_enable_ospf.current.ospfIntfPol.prio == 1 + - irp_1_enable_ospf.current.ospfIntfPol.retransmitInterval == 5 + - irp_1_enable_ospf.current.ospfIntfPol.transmitDelay == 1 + - irp_1_enable_ospf.current.uuid is defined + - irp_1_enable_ospf.previous.bfdMultiHopPol.adminState == "disabled" + - irp_1_enable_ospf.previous.bfdMultiHopPol.detectionMultiplier == 10 + - irp_1_enable_ospf.previous.bfdMultiHopPol.minRxInterval == 255 + - irp_1_enable_ospf.previous.bfdMultiHopPol.minTxInterval == 255 + - irp_1_enable_ospf.previous.bfdPol.adminState == "enabled" + - irp_1_enable_ospf.previous.bfdPol.detectionMultiplier == 3 + - irp_1_enable_ospf.previous.bfdPol.echoAdminState == "enabled" + - irp_1_enable_ospf.previous.bfdPol.echoRxInterval == 50 + - irp_1_enable_ospf.previous.bfdPol.ifControl == false + - irp_1_enable_ospf.previous.bfdPol.minRxInterval == 50 + - irp_1_enable_ospf.previous.bfdPol.minTxInterval == 50 + - irp_1_enable_ospf.previous.description == "Updated" + - irp_1_enable_ospf.previous.name == "irp_1_update" + - irp_1_enable_ospf.previous.uuid is defined + + - name: Create irp_2 L3Out Interface Routing Policy with full configuration + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_2 + description: Created + bfd_multi_hop_settings: + admin_state: enabled + detection_multiplier: 10 + min_receive_interval: 255 + min_transmit_interval: 255 + bfd_settings: + admin_state: enabled + detection_multiplier: 10 + min_receive_interval: 266 + min_transmit_interval: 266 + echo_receive_interval: 55 + echo_admin_state: disabled + interface_control: enabled + ospf_interface_settings: + network_type: broadcast + priority: 10 + cost_of_interface: 100 + advertise_subnet: enabled + bfd: enabled + mtu_ignore: enabled + passive_participation: enabled + hello_interval: 20 + dead_interval: 30 + retransmit_interval: 20 + transmit_delay: 10 + state: present + output_level: debug + register: irp_2_present + + - name: Assertion check for create irp_2 L3Out Interface Routing Policy with full configuration + ansible.builtin.assert: + that: + - irp_2_present is changed + - irp_2_present.current.bfdMultiHopPol.adminState == "enabled" + - irp_2_present.current.bfdMultiHopPol.detectionMultiplier == 10 + - irp_2_present.current.bfdMultiHopPol.minRxInterval == 255 + - irp_2_present.current.bfdMultiHopPol.minTxInterval == 255 + - irp_2_present.current.bfdPol.adminState == "enabled" + - irp_2_present.current.bfdPol.detectionMultiplier == 10 + - irp_2_present.current.bfdPol.echoAdminState == "disabled" + - irp_2_present.current.bfdPol.echoRxInterval == 55 + - irp_2_present.current.bfdPol.ifControl == true + - irp_2_present.current.bfdPol.minRxInterval == 266 + - irp_2_present.current.bfdPol.minTxInterval == 266 + - irp_2_present.current.description == "Created" + - irp_2_present.current.name == "irp_2" + - irp_2_present.current.ospfIntfPol.cost == 100 + - irp_2_present.current.ospfIntfPol.deadInterval == 30 + - irp_2_present.current.ospfIntfPol.helloInterval == 20 + - irp_2_present.current.ospfIntfPol.ifControl.advertiseSubnet == true + - irp_2_present.current.ospfIntfPol.ifControl.bfd == true + - irp_2_present.current.ospfIntfPol.ifControl.ignoreMtu == true + - irp_2_present.current.ospfIntfPol.ifControl.passiveParticipation == true + - irp_2_present.current.ospfIntfPol.networkType == "broadcast" + - irp_2_present.current.ospfIntfPol.prio == 10 + - irp_2_present.current.ospfIntfPol.retransmitInterval == 20 + - irp_2_present.current.ospfIntfPol.transmitDelay == 10 + - irp_2_present.current.uuid is defined + - irp_2_present.previous == {} + + - name: Create irp_3 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_3 + ospf_interface_settings: + state: enabled + state: present + register: irp_3_present + + - name: Assertion check for create irp_3 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_3_present is changed + - irp_3_present.current.name == "irp_3" + - irp_3_present.current.ospfIntfPol.cost == 0 + - irp_3_present.current.ospfIntfPol.deadInterval == 40 + - irp_3_present.current.ospfIntfPol.helloInterval == 10 + - irp_3_present.current.ospfIntfPol.ifControl.advertiseSubnet == false + - irp_3_present.current.ospfIntfPol.ifControl.bfd == false + - irp_3_present.current.ospfIntfPol.ifControl.ignoreMtu == false + - irp_3_present.current.ospfIntfPol.ifControl.passiveParticipation == false + - irp_3_present.current.ospfIntfPol.networkType == "broadcast" + - irp_3_present.current.ospfIntfPol.prio == 1 + - irp_3_present.current.ospfIntfPol.retransmitInterval == 5 + - irp_3_present.current.ospfIntfPol.transmitDelay == 1 + - irp_3_present.current.uuid is defined + - irp_3_present.previous == {} + + - name: Clear ospf_interface_settings from irp_3 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_3 + bfd_settings: {} + ospf_interface_settings: + state: disabled + state: present + register: irp_3_clear_ospf + + - name: Assertion check for clear ospf_interface_settings from irp_3 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_3_clear_ospf is changed + - irp_3_clear_ospf.current.bfdPol.adminState == "enabled" + - irp_3_clear_ospf.current.bfdPol.detectionMultiplier == 3 + - irp_3_clear_ospf.current.bfdPol.echoAdminState == "enabled" + - irp_3_clear_ospf.current.bfdPol.echoRxInterval == 50 + - irp_3_clear_ospf.current.bfdPol.ifControl == false + - irp_3_clear_ospf.current.bfdPol.minRxInterval == 50 + - irp_3_clear_ospf.current.bfdPol.minTxInterval == 50 + - irp_3_clear_ospf.current.name == "irp_3" + - irp_3_clear_ospf.current.uuid is defined + - irp_3_clear_ospf.previous.name == "irp_3" + - irp_3_clear_ospf.previous.ospfIntfPol.cost == 0 + - irp_3_clear_ospf.previous.ospfIntfPol.deadInterval == 40 + - irp_3_clear_ospf.previous.ospfIntfPol.helloInterval == 10 + - irp_3_clear_ospf.previous.ospfIntfPol.ifControl.advertiseSubnet == false + - irp_3_clear_ospf.previous.ospfIntfPol.ifControl.bfd == false + - irp_3_clear_ospf.previous.ospfIntfPol.ifControl.ignoreMtu == false + - irp_3_clear_ospf.previous.ospfIntfPol.ifControl.passiveParticipation == false + - irp_3_clear_ospf.previous.ospfIntfPol.networkType == "broadcast" + - irp_3_clear_ospf.previous.ospfIntfPol.prio == 1 + - irp_3_clear_ospf.previous.ospfIntfPol.retransmitInterval == 5 + - irp_3_clear_ospf.previous.ospfIntfPol.transmitDelay == 1 + - irp_3_clear_ospf.previous.uuid is defined + + - name: Create irp_4 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_4 + bfd_multi_hop_settings: {} + bfd_settings: {} + ospf_interface_settings: + state: enabled + state: present + register: irp_4_present + + - name: Assertion check for create irp_4 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_4_present is changed + - irp_4_present.current.name == "irp_4" + - irp_4_present.current.ospfIntfPol.cost == 0 + - irp_4_present.current.ospfIntfPol.deadInterval == 40 + - irp_4_present.current.ospfIntfPol.helloInterval == 10 + - irp_4_present.current.ospfIntfPol.ifControl.advertiseSubnet == false + - irp_4_present.current.ospfIntfPol.ifControl.bfd == false + - irp_4_present.current.ospfIntfPol.ifControl.ignoreMtu == false + - irp_4_present.current.ospfIntfPol.ifControl.passiveParticipation == false + - irp_4_present.current.ospfIntfPol.networkType == "broadcast" + - irp_4_present.current.ospfIntfPol.prio == 1 + - irp_4_present.current.ospfIntfPol.retransmitInterval == 5 + - irp_4_present.current.ospfIntfPol.transmitDelay == 1 + - irp_4_present.current.uuid is defined + + - name: Update irp_4 enable - bfd_multi_hop_settings and disable - ospf_interface_settings + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_4 + bfd_multi_hop_settings: + state: enabled + bfd_settings: + state: enabled + ospf_interface_settings: + state: disabled + state: present + register: irp_4_configs + + - name: Assertion check for update irp_4 enable - bfd_multi_hop_settings and disable - ospf_interface_settings + ansible.builtin.assert: + that: + - irp_4_configs is changed + - irp_4_configs.current.bfdMultiHopPol.adminState == "enabled" + - irp_4_configs.current.bfdMultiHopPol.detectionMultiplier == 3 + - irp_4_configs.current.bfdMultiHopPol.minRxInterval == 250 + - irp_4_configs.current.bfdMultiHopPol.minTxInterval == 250 + - irp_4_configs.current.bfdPol.adminState == "enabled" + - irp_4_configs.current.bfdPol.detectionMultiplier == 3 + - irp_4_configs.current.bfdPol.echoAdminState == "enabled" + - irp_4_configs.current.bfdPol.echoRxInterval == 50 + - irp_4_configs.current.bfdPol.ifControl == false + - irp_4_configs.current.bfdPol.minRxInterval == 50 + - irp_4_configs.current.bfdPol.minTxInterval == 50 + - irp_4_configs.current.name == "irp_4" + - irp_4_configs.current.uuid is defined + - irp_4_configs.previous.name == "irp_4" + - irp_4_configs.previous.ospfIntfPol.cost == 0 + - irp_4_configs.previous.ospfIntfPol.deadInterval == 40 + - irp_4_configs.previous.ospfIntfPol.helloInterval == 10 + - irp_4_configs.previous.ospfIntfPol.ifControl.advertiseSubnet == false + - irp_4_configs.previous.ospfIntfPol.ifControl.bfd == false + - irp_4_configs.previous.ospfIntfPol.ifControl.ignoreMtu == false + - irp_4_configs.previous.ospfIntfPol.ifControl.passiveParticipation == false + - irp_4_configs.previous.ospfIntfPol.networkType == "broadcast" + - irp_4_configs.previous.ospfIntfPol.prio == 1 + - irp_4_configs.previous.ospfIntfPol.retransmitInterval == 5 + - irp_4_configs.previous.ospfIntfPol.transmitDelay == 1 + - irp_4_configs.previous.uuid is defined + + - name: Create irp_5 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_5 + bfd_settings: + state: enabled + ospf_interface_settings: {} + state: present + register: irp_5_create + + - name: Assertion check for create irp_5 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_5_create is changed + - irp_5_create.current.bfdPol.adminState == "enabled" + - irp_5_create.current.bfdPol.detectionMultiplier == 3 + - irp_5_create.current.bfdPol.echoAdminState == "enabled" + - irp_5_create.current.bfdPol.echoRxInterval == 50 + - irp_5_create.current.bfdPol.ifControl == false + - irp_5_create.current.bfdPol.minRxInterval == 50 + - irp_5_create.current.bfdPol.minTxInterval == 50 + - irp_5_create.current.name == "irp_5" + - irp_5_create.current.uuid is defined + + - name: Update irp_5 L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_5 + bfd_multi_hop_settings: + state: enabled + state: present + register: irp_5_update + + - name: Assertion check for update irp_5 L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - irp_5_update is changed + - irp_5_update.current.bfdMultiHopPol.adminState == "enabled" + - irp_5_update.current.bfdMultiHopPol.detectionMultiplier == 3 + - irp_5_update.current.bfdMultiHopPol.minRxInterval == 250 + - irp_5_update.current.bfdMultiHopPol.minTxInterval == 250 + - irp_5_update.current.bfdPol.adminState == "enabled" + - irp_5_update.current.bfdPol.detectionMultiplier == 3 + - irp_5_update.current.bfdPol.echoAdminState == "enabled" + - irp_5_update.current.bfdPol.echoRxInterval == 50 + - irp_5_update.current.bfdPol.ifControl == false + - irp_5_update.current.bfdPol.minRxInterval == 50 + - irp_5_update.current.bfdPol.minTxInterval == 50 + - irp_5_update.current.name == "irp_5" + - irp_5_update.current.uuid is defined + - irp_5_update.previous.bfdPol.adminState == "enabled" + - irp_5_update.previous.bfdPol.detectionMultiplier == 3 + - irp_5_update.previous.bfdPol.echoAdminState == "enabled" + - irp_5_update.previous.bfdPol.echoRxInterval == 50 + - irp_5_update.previous.bfdPol.ifControl == false + - irp_5_update.previous.bfdPol.minRxInterval == 50 + - irp_5_update.previous.bfdPol.minTxInterval == 50 + - irp_5_update.previous.name == "irp_5" + - irp_5_update.previous.uuid is defined + + - name: Update irp_5 L3Out Interface Routing Policy with partial bfd, bfd multi-hop and ospf configuration using uuid + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + uuid: "{{ irp_5_update.current.uuid }}" + bfd_multi_hop_settings: + admin_state: disabled + detection_multiplier: 10 + min_receive_interval: 255 + bfd_settings: + admin_state: enabled + detection_multiplier: 10 + echo_receive_interval: 55 + echo_admin_state: enabled + interface_control: disabled + ospf_interface_settings: + network_type: broadcast + mtu_ignore: disabled + passive_participation: enabled + hello_interval: 20 + dead_interval: 30 + retransmit_interval: 20 + transmit_delay: 10 + state: present + register: irp_5_update_full_config + + - name: Assertion check for update irp_5 L3Out Interface Routing Policy with partial bfd, bfd multi-hop and ospf configuration using uuid + ansible.builtin.assert: + that: + - irp_5_update_full_config is changed + - irp_5_update_full_config.current.bfdMultiHopPol.adminState == "disabled" + - irp_5_update_full_config.current.bfdMultiHopPol.detectionMultiplier == 10 + - irp_5_update_full_config.current.bfdMultiHopPol.minRxInterval == 255 + - irp_5_update_full_config.current.bfdMultiHopPol.minTxInterval == 250 + - irp_5_update_full_config.current.bfdPol.adminState == "enabled" + - irp_5_update_full_config.current.bfdPol.detectionMultiplier == 10 + - irp_5_update_full_config.current.bfdPol.echoAdminState == "enabled" + - irp_5_update_full_config.current.bfdPol.echoRxInterval == 55 + - irp_5_update_full_config.current.bfdPol.ifControl == false + - irp_5_update_full_config.current.bfdPol.minRxInterval == 50 + - irp_5_update_full_config.current.bfdPol.minTxInterval == 50 + - irp_5_update_full_config.current.name == "irp_5" + - irp_5_update_full_config.current.ospfIntfPol.cost == 0 + - irp_5_update_full_config.current.ospfIntfPol.deadInterval == 30 + - irp_5_update_full_config.current.ospfIntfPol.helloInterval == 20 + - irp_5_update_full_config.current.ospfIntfPol.ifControl.advertiseSubnet == false + - irp_5_update_full_config.current.ospfIntfPol.ifControl.bfd == false + - irp_5_update_full_config.current.ospfIntfPol.ifControl.ignoreMtu == false + - irp_5_update_full_config.current.ospfIntfPol.ifControl.passiveParticipation == true + - irp_5_update_full_config.current.ospfIntfPol.networkType == "broadcast" + - irp_5_update_full_config.current.ospfIntfPol.prio == 1 + - irp_5_update_full_config.current.ospfIntfPol.retransmitInterval == 20 + - irp_5_update_full_config.current.ospfIntfPol.transmitDelay == 10 + - irp_5_update_full_config.current.uuid is defined + - irp_5_update_full_config.previous.bfdMultiHopPol.adminState == "enabled" + - irp_5_update_full_config.previous.bfdMultiHopPol.detectionMultiplier == 3 + - irp_5_update_full_config.previous.bfdMultiHopPol.minRxInterval == 250 + - irp_5_update_full_config.previous.bfdMultiHopPol.minTxInterval == 250 + - irp_5_update_full_config.previous.bfdPol.adminState == "enabled" + - irp_5_update_full_config.previous.bfdPol.detectionMultiplier == 3 + - irp_5_update_full_config.previous.bfdPol.echoAdminState == "enabled" + - irp_5_update_full_config.previous.bfdPol.echoRxInterval == 50 + - irp_5_update_full_config.previous.bfdPol.ifControl == false + - irp_5_update_full_config.previous.bfdPol.minRxInterval == 50 + - irp_5_update_full_config.previous.bfdPol.minTxInterval == 50 + - irp_5_update_full_config.previous.name == "irp_5" + - irp_5_update_full_config.previous.uuid is defined + + - name: Query all L3Out Interface Routing Policy + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + state: query + register: query_all + + - name: Assertion check for query all L3Out Interface Routing Policy + ansible.builtin.assert: + that: + - query_all is not changed + - query_all.current | length == 5 + - "'irp_1_update' in query_all.current | map(attribute='name') | list" + - "'irp_2' in query_all.current | map(attribute='name') | list" + - "'irp_3' in query_all.current | map(attribute='name') | list" + - "'irp_4' in query_all.current | map(attribute='name') | list" + - "'irp_5' in query_all.current | map(attribute='name') | list" + + - name: Query L3Out Interface Routing Policy with name + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_5 + state: query + register: query_irp_5_name + + - name: Assertion check for query L3Out Interface Routing Policy with name + ansible.builtin.assert: + that: + - query_irp_5_name is not changed + - query_irp_5_name.current.bfdMultiHopPol.adminState == "disabled" + - query_irp_5_name.current.bfdMultiHopPol.detectionMultiplier == 10 + - query_irp_5_name.current.bfdMultiHopPol.minRxInterval == 255 + - query_irp_5_name.current.bfdMultiHopPol.minTxInterval == 250 + - query_irp_5_name.current.bfdPol.adminState == "enabled" + - query_irp_5_name.current.bfdPol.detectionMultiplier == 10 + - query_irp_5_name.current.bfdPol.echoAdminState == "enabled" + - query_irp_5_name.current.bfdPol.echoRxInterval == 55 + - query_irp_5_name.current.bfdPol.ifControl == false + - query_irp_5_name.current.bfdPol.minRxInterval == 50 + - query_irp_5_name.current.bfdPol.minTxInterval == 50 + - query_irp_5_name.current.name == "irp_5" + - query_irp_5_name.current.ospfIntfPol.cost == 0 + - query_irp_5_name.current.ospfIntfPol.deadInterval == 30 + - query_irp_5_name.current.ospfIntfPol.helloInterval == 20 + - query_irp_5_name.current.ospfIntfPol.ifControl.advertiseSubnet == false + - query_irp_5_name.current.ospfIntfPol.ifControl.bfd == false + - query_irp_5_name.current.ospfIntfPol.ifControl.ignoreMtu == false + - query_irp_5_name.current.ospfIntfPol.ifControl.passiveParticipation == true + - query_irp_5_name.current.ospfIntfPol.networkType == "broadcast" + - query_irp_5_name.current.ospfIntfPol.prio == 1 + - query_irp_5_name.current.ospfIntfPol.retransmitInterval == 20 + - query_irp_5_name.current.ospfIntfPol.transmitDelay == 10 + - query_irp_5_name.current.uuid is defined + + - name: Query L3Out Interface Routing Policy with uuid + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + uuid: "{{ query_irp_5_name.current.uuid }}" + state: query + register: query_irp_5_uuid + + - name: Assertion check for query L3Out Interface Routing Policy with uuid + ansible.builtin.assert: + that: + - query_irp_5_uuid is not changed + - query_irp_5_uuid.current.bfdMultiHopPol.adminState == "disabled" + - query_irp_5_uuid.current.bfdMultiHopPol.detectionMultiplier == 10 + - query_irp_5_uuid.current.bfdMultiHopPol.minRxInterval == 255 + - query_irp_5_uuid.current.bfdMultiHopPol.minTxInterval == 250 + - query_irp_5_uuid.current.bfdPol.adminState == "enabled" + - query_irp_5_uuid.current.bfdPol.detectionMultiplier == 10 + - query_irp_5_uuid.current.bfdPol.echoAdminState == "enabled" + - query_irp_5_uuid.current.bfdPol.echoRxInterval == 55 + - query_irp_5_uuid.current.bfdPol.ifControl == false + - query_irp_5_uuid.current.bfdPol.minRxInterval == 50 + - query_irp_5_uuid.current.bfdPol.minTxInterval == 50 + - query_irp_5_uuid.current.name == "irp_5" + - query_irp_5_uuid.current.ospfIntfPol.cost == 0 + - query_irp_5_uuid.current.ospfIntfPol.deadInterval == 30 + - query_irp_5_uuid.current.ospfIntfPol.helloInterval == 20 + - query_irp_5_uuid.current.ospfIntfPol.ifControl.advertiseSubnet == false + - query_irp_5_uuid.current.ospfIntfPol.ifControl.bfd == false + - query_irp_5_uuid.current.ospfIntfPol.ifControl.ignoreMtu == false + - query_irp_5_uuid.current.ospfIntfPol.ifControl.passiveParticipation == true + - query_irp_5_uuid.current.ospfIntfPol.networkType == "broadcast" + - query_irp_5_uuid.current.ospfIntfPol.prio == 1 + - query_irp_5_uuid.current.ospfIntfPol.retransmitInterval == 20 + - query_irp_5_uuid.current.ospfIntfPol.transmitDelay == 10 + - query_irp_5_uuid.current.uuid is defined + + - name: Remove L3Out Interface Routing Policy with name - check_mode + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_1_update + state: absent + output_level: debug + check_mode: true + register: cm_rm_with_name + + - name: Assertion check for remove L3Out Interface Routing Policy with name - check_mode + ansible.builtin.assert: + that: + - cm_rm_with_name is changed + - cm_rm_with_name.current == {} + - cm_rm_with_name.previous.bfdMultiHopPol.adminState == "disabled" + - cm_rm_with_name.previous.bfdMultiHopPol.detectionMultiplier == 10 + - cm_rm_with_name.previous.bfdMultiHopPol.minRxInterval == 255 + - cm_rm_with_name.previous.bfdMultiHopPol.minTxInterval == 255 + - cm_rm_with_name.previous.bfdPol.adminState == "enabled" + - cm_rm_with_name.previous.bfdPol.detectionMultiplier == 3 + - cm_rm_with_name.previous.bfdPol.echoAdminState == "enabled" + - cm_rm_with_name.previous.bfdPol.echoRxInterval == 50 + - cm_rm_with_name.previous.bfdPol.ifControl == false + - cm_rm_with_name.previous.bfdPol.minRxInterval == 50 + - cm_rm_with_name.previous.bfdPol.minTxInterval == 50 + - cm_rm_with_name.previous.description == "Updated" + - cm_rm_with_name.previous.name == "irp_1_update" + - cm_rm_with_name.previous.ospfIntfPol.cost == 0 + - cm_rm_with_name.previous.ospfIntfPol.deadInterval == 40 + - cm_rm_with_name.previous.ospfIntfPol.helloInterval == 10 + - cm_rm_with_name.previous.ospfIntfPol.ifControl.advertiseSubnet == false + - cm_rm_with_name.previous.ospfIntfPol.ifControl.bfd == false + - cm_rm_with_name.previous.ospfIntfPol.ifControl.ignoreMtu == false + - cm_rm_with_name.previous.ospfIntfPol.ifControl.passiveParticipation == false + - cm_rm_with_name.previous.ospfIntfPol.networkType == "broadcast" + - cm_rm_with_name.previous.ospfIntfPol.prio == 1 + - cm_rm_with_name.previous.ospfIntfPol.retransmitInterval == 5 + - cm_rm_with_name.previous.ospfIntfPol.transmitDelay == 1 + - cm_rm_with_name.previous.uuid is defined + + - name: Remove L3Out Interface Routing Policy with name - normal_mode + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_1_update + state: absent + register: nm_rm_with_name + + - name: Assertion check for remove L3Out Interface Routing Policy with name - normal_mode + ansible.builtin.assert: + that: + - nm_rm_with_name is changed + - nm_rm_with_name.current == {} + - nm_rm_with_name.previous.bfdMultiHopPol.adminState == "disabled" + - nm_rm_with_name.previous.bfdMultiHopPol.minTxInterval == 255 + - nm_rm_with_name.previous.bfdPol.adminState == "enabled" + - nm_rm_with_name.previous.bfdPol.ifControl == false + - nm_rm_with_name.previous.bfdPol.minRxInterval == 50 + - nm_rm_with_name.previous.bfdPol.minTxInterval == 50 + - nm_rm_with_name.previous.description == "Updated" + - nm_rm_with_name.previous.name == "irp_1_update" + - nm_rm_with_name.previous.ospfIntfPol.cost == 0 + - nm_rm_with_name.previous.ospfIntfPol.deadInterval == 40 + - nm_rm_with_name.previous.ospfIntfPol.helloInterval == 10 + - nm_rm_with_name.previous.ospfIntfPol.ifControl.advertiseSubnet == false + - nm_rm_with_name.previous.ospfIntfPol.networkType == "broadcast" + - nm_rm_with_name.previous.ospfIntfPol.prio == 1 + - nm_rm_with_name.previous.uuid is defined + + - name: Remove L3Out Interface Routing Policy with name - normal_mode again + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + name: irp_1_update + state: absent + register: nm_rm_with_name_again + + - name: Assertion check for remove L3Out Interface Routing Policy with name - normal_mode again + ansible.builtin.assert: + that: + - nm_rm_with_name_again is not changed + - nm_rm_with_name_again.current == {} + - nm_rm_with_name_again.previous == {} + + - name: Remove L3Out Interface Routing Policy with uuid + cisco.mso.ndo_l3out_interface_routing_policy: + <<: *mso_info + template: '{{ ansible_tenant_template | default("ansible_test") }}' + uuid: "{{ query_irp_5_name.current.uuid }}" + state: absent + register: nm_rm_with_uuid + + - name: Assertion check for remove L3Out Interface Routing Policy with uuid + ansible.builtin.assert: + that: + - nm_rm_with_uuid is changed + - nm_rm_with_uuid.current == {} + - nm_rm_with_uuid.previous.bfdMultiHopPol.adminState == "disabled" + - nm_rm_with_uuid.previous.bfdMultiHopPol.minTxInterval == 250 + - nm_rm_with_uuid.previous.bfdPol.adminState == "enabled" + - nm_rm_with_uuid.previous.bfdPol.detectionMultiplier == 10 + - nm_rm_with_uuid.previous.bfdPol.minRxInterval == 50 + - nm_rm_with_uuid.previous.bfdPol.minTxInterval == 50 + - nm_rm_with_uuid.previous.name == "irp_5" + - nm_rm_with_uuid.previous.ospfIntfPol.cost == 0 + - nm_rm_with_uuid.previous.ospfIntfPol.ifControl.bfd == false + - nm_rm_with_uuid.previous.ospfIntfPol.ifControl.ignoreMtu == false + - nm_rm_with_uuid.previous.ospfIntfPol.ifControl.passiveParticipation == true + - nm_rm_with_uuid.previous.ospfIntfPol.networkType == "broadcast" + - nm_rm_with_uuid.previous.uuid is defined + + # Cleanup Part + - name: Ensure templates do not exist + cisco.mso.ndo_template: + <<: *template_absent