diff --git a/plugins/modules/ndo_l3out_template.py b/plugins/modules/ndo_l3out_template.py index a9f35636..770babb6 100644 --- a/plugins/modules/ndo_l3out_template.py +++ b/plugins/modules/ndo_l3out_template.py @@ -130,6 +130,7 @@ - Use C(enabled) to configure the BGP routing protocol. - Use C(disabled) to remove the BGP routing protocol. type: str + default: enabled choices: [enabled, disabled] inbound_route_map: description: @@ -165,14 +166,17 @@ - Use C(enabled) to configure the OSPF routing protocol. - Use C(disabled) to remove the OSPF routing protocol. type: str + default: enabled choices: [enabled, disabled] area_id: description: - The area id of the OSPF area. + - This option is required when the O(ospf.state=enabled). type: str area_type: description: - The area type of the OSPF area. + - This option is required when the O(ospf.state=enabled). type: str choices: [regular, stub, nssa] cost: @@ -288,13 +292,11 @@ template: "Template1" routing_protocols: ["bgp", "ospf"] bgp: - state: enabled inbound_route_map: "ans_route_map" outbound_route_map: "ans_route_map" route_dampening_ipv4: "ans_route_map" route_dampening_ipv6: "ans_route_map" ospf: - state: enabled area_id: "0.0.0.1" area_type: "regular" cost: 1 @@ -387,10 +389,10 @@ def get_routing_protocol(existing_protocol, ospf_state, bgp_state): protocols = set() - if bgp_state == "enabled" or (bgp_state is None and "bgp" in L3OUT_ROUTING_PROTOCOLS.get(existing_protocol)): + if bgp_state == "enabled" or (bgp_state == "ignore" and "bgp" in L3OUT_ROUTING_PROTOCOLS.get(existing_protocol)): protocols.add("bgp") - if ospf_state == "enabled" or (ospf_state is None and "ospf" in L3OUT_ROUTING_PROTOCOLS.get(existing_protocol)): + if ospf_state == "enabled" or (ospf_state == "ignore" and "ospf" in L3OUT_ROUTING_PROTOCOLS.get(existing_protocol)): protocols.add("ospf") return "".join(protocols) if len(protocols) < 2 else L3OUT_ROUTING_PROTOCOLS.get("".join(protocols)) @@ -421,7 +423,7 @@ def main(): ospf=dict( type="dict", options=dict( - state=dict(type="str", choices=["enabled", "disabled"]), + state=dict(type="str", choices=["enabled", "disabled"], default="enabled"), area_id=dict(type="str"), area_type=dict(type="str", choices=["regular", "stub", "nssa"]), cost=dict(type="int"), @@ -431,30 +433,19 @@ def main(): originate_default_route=dict(type="str", choices=list(ORIGINATE_DEFAULT_ROUTE)), originate_default_route_always=dict(type="bool", aliases=["always"]), ), - required_one_of=[ - ( - "state", - "area_id", - "area_type", - "cost", - "send_redistributed_lsas", - "originate_summary_lsa", - "suppress_forwarding_addr_translated_lsa", - "originate_default_route", - "originate_default_route_always", - ) + required_if=[ + ["state", "enabled", ["area_id", "area_type"]], ], ), bgp=dict( type="dict", options=dict( - state=dict(type="str", choices=["enabled", "disabled"]), + state=dict(type="str", choices=["enabled", "disabled"], default="enabled"), inbound_route_map=dict(type="str", aliases=["import_route", "inbound_route"]), outbound_route_map=dict(type="str", aliases=["export_route", "outbound_route"]), route_dampening_ipv4=dict(type="str", aliases=["dampening_ipv4"]), route_dampening_ipv6=dict(type="str", aliases=["dampening_ipv6"]), ), - required_one_of=[("state", "inbound_route_map", "outbound_route_map", "route_dampening_ipv4", "route_dampening_ipv6")], ), state=dict(type="str", default="query", choices=["absent", "query", "present"]), ) @@ -532,24 +523,8 @@ def main(): existing_routing_protocols = mso.existing.get("routingProtocol", None) - if existing_routing_protocols in [None, "none"]: - if ospf is not None and ospf.get("state") in [None, "enabled"]: - ospf_state = "enabled" - elif ospf is not None and ospf.get("state") == "disabled": - ospf_state = "disabled" - else: - ospf_state = False - - if bgp is not None and bgp.get("state") in [None, "enabled"]: - bgp_state = "enabled" - elif bgp is not None and bgp.get("state") == "disabled": - bgp_state = "disabled" - else: - bgp_state = False - else: - # Update the existing protocol status - ospf_state = ospf.get("state") if ospf else None - bgp_state = bgp.get("state") if bgp else None + ospf_state = ospf.get("state") if ospf else "ignore" + bgp_state = bgp.get("state") if bgp else "ignore" res_routing_protocols = get_routing_protocol(None if existing_routing_protocols == "none" else existing_routing_protocols, ospf_state, bgp_state) @@ -657,9 +632,6 @@ def main(): ).get("uuid", "") if ospf: - if not (ospf.get("area_id") and ospf.get("area_type")): - mso.fail_json(msg="The O(ospf) - area_id, area_type is required during the creation.") - payload["ospfAreaConfig"] = dict( cost=ospf.get("cost"), id=ospf.get("area_id"), diff --git a/tests/integration/targets/ndo_l3out_template/tasks/main.yml b/tests/integration/targets/ndo_l3out_template/tasks/main.yml index 939ba676..a544616f 100644 --- a/tests/integration/targets/ndo_l3out_template/tasks/main.yml +++ b/tests/integration/targets/ndo_l3out_template/tasks/main.yml @@ -935,6 +935,8 @@ name: l3out_1_updated ospf: # when you enable originate_default_route_always, originate_default_route set to "only" when it is not configured and specified in the config + area_id: "0.0.0.1" + area_type: "regular" originate_default_route_always: true state: present register: l3out_1_update_ospf_default_route_true @@ -991,6 +993,7 @@ l3out_template: '{{ ansible_l3out_template | default("ansible_test") }}' name: l3out_1_updated ospf: + area_id: "0.0.0.1" area_type: "stub" cost: 3 originate_default_route: "only" @@ -1053,6 +1056,7 @@ name: l3out_1_updated ospf: area_id: "0.0.0.2" + area_type: "stub" state: present register: l3out_1_update_ospf_id @@ -1423,30 +1427,30 @@ - nm_l3out_2_absent_again.current == {} - nm_l3out_2_absent_again.previous == {} - - name: Enable pim with L3 Multicast disabled vrf + # Negative test part begins + - name: Update l3out_3 object without ospf - id and type cisco.mso.ndo_l3out_template: <<: *mso_info l3out_template: '{{ ansible_l3out_template | default("ansible_test") }}' - name: "l3out_nt" + name: "l3out_3" l3_domain: ans_l3_domain vrf: name: "VRF1" schema: '{{ ansible_schema | default("ansible_test") }}' template: "Template1" - pim: true - state: present - register: enable_pim_with_invalid_vrf + ospf: + cost: 5 + state: "present" + register: update_l3out_3_ospf_nt ignore_errors: true - - name: Assertion check for enable pim with L3 Multicast disabled vrf + - name: Assertion check for update l3out_3 object without ospf - id and type ansible.builtin.assert: that: - - enable_pim_with_invalid_vrf is not changed - - enable_pim_with_invalid_vrf.current == {} - - enable_pim_with_invalid_vrf.msg == "Invalid configuration in L3Out 'l3out_nt', 'PIM' cannot be enabled while using the VRF 'VRF1' with L3 Multicast disabled" - - enable_pim_with_invalid_vrf.previous == {} + - update_l3out_3_ospf_nt is not changed + - update_l3out_3_ospf_nt.msg == "state is enabled but all of the following are missing{{':'}} area_id, area_type found in ospf" - - name: Create L3Out object without ospf area_id + - name: Enable pim with L3 Multicast disabled vrf cisco.mso.ndo_l3out_template: <<: *mso_info l3out_template: '{{ ansible_l3out_template | default("ansible_test") }}' @@ -1456,21 +1460,20 @@ name: "VRF1" schema: '{{ ansible_schema | default("ansible_test") }}' template: "Template1" - ospf: - area_type: "stub" + pim: true state: present - register: create_ospf_without_area_id + register: enable_pim_with_invalid_vrf ignore_errors: true - - name: Assertion check for create L3Out object without ospf area_id + - name: Assertion check for enable pim with L3 Multicast disabled vrf ansible.builtin.assert: that: - - create_ospf_without_area_id is not changed - - create_ospf_without_area_id.current == {} - - create_ospf_without_area_id.msg == "The O(ospf) - area_id, area_type is required during the creation." - - create_ospf_without_area_id.previous == {} + - enable_pim_with_invalid_vrf is not changed + - enable_pim_with_invalid_vrf.current == {} + - enable_pim_with_invalid_vrf.msg == "Invalid configuration in L3Out 'l3out_nt', 'PIM' cannot be enabled while using the VRF 'VRF1' with L3 Multicast disabled" + - enable_pim_with_invalid_vrf.previous == {} - - name: Create L3Out object without ospf area_type + - name: Create L3Out object without ospf area_id cisco.mso.ndo_l3out_template: <<: *mso_info l3out_template: '{{ ansible_l3out_template | default("ansible_test") }}' @@ -1481,18 +1484,16 @@ schema: '{{ ansible_schema | default("ansible_test") }}' template: "Template1" ospf: - area_id: "0.0.0.1" + area_type: "stub" state: present - register: create_ospf_without_area_type + register: create_ospf_without_area_id ignore_errors: true - - name: Assertion check for create L3Out object without ospf area_type + - name: Assertion check for create L3Out object without ospf area_id ansible.builtin.assert: that: - - create_ospf_without_area_type is not changed - - create_ospf_without_area_type.current == {} - - create_ospf_without_area_type.msg == "The O(ospf) - area_id, area_type is required during the creation." - - create_ospf_without_area_type.previous == {} + - create_ospf_without_area_id is not changed + - create_ospf_without_area_id.msg == "state is enabled but all of the following are missing{{':'}} area_id found in ospf" - name: Create L3Out object without vrf cisco.mso.ndo_l3out_template: @@ -1512,6 +1513,8 @@ - create_without_vrf.msg == "The O(vrf) is required during the creation." - create_without_vrf.previous == {} + # Negative test part ends + - name: Query all L3Out objects cisco.mso.ndo_l3out_template: <<: *mso_info