diff --git a/plugins/modules/ndo_route_map_policy_multicast.py b/plugins/modules/ndo_route_map_policy_multicast.py index 7e812e4c..981b417d 100644 --- a/plugins/modules/ndo_route_map_policy_multicast.py +++ b/plugins/modules/ndo_route_map_policy_multicast.py @@ -139,6 +139,7 @@ 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, KVPair +from ansible_collections.cisco.mso.plugins.module_utils.utils import append_update_ops_data def main(): @@ -188,56 +189,33 @@ def main(): mso_template.validate_template("tenantPolicy") path = "/tenantPolicyTemplate/template/mcastRouteMapPolicies" - existing_route_map_policies = mso_template.template.get("tenantPolicyTemplate", {}).get("template", {}).get("mcastRouteMapPolicies", []) - if route_map_policy: - object_description = "Multicast Route Map Policy" - if route_map_policy_uuid: - match = mso_template.get_object_by_uuid(object_description, existing_route_map_policies, route_map_policy_uuid) - else: - kv_list = [KVPair("name", route_map_policy)] - match = mso_template.get_object_by_key_value_pairs(object_description, existing_route_map_policies, kv_list) - if match: - match.details["entries"] = match.details.pop("mcastRtMapEntryList") - mso.existing = mso.previous = copy.deepcopy(match.details) - else: - mso.existing = mso.previous = existing_route_map_policies + match = get_multicast_route_map_policy(mso_template, route_map_policy_uuid, route_map_policy) - if state == "present": - - if match: + if route_map_policy_uuid or route_map_policy: + if match: # Query a specific object + mso.existing = copy.deepcopy(match.details) + mso.previous = copy.deepcopy(match.details) + elif match: + mso.existing = match # Query all objects - if module.params.get("entries") is not None and len(entries) == 0: - mso.fail_json(msg=err_message_min_entries) - - if route_map_policy and match.details.get("name") != route_map_policy: - ops.append(dict(op="replace", path="{0}/{1}/name".format(path, match.index), value=route_map_policy)) - match.details["name"] = route_map_policy - - if description is not None and match.details.get("description") != description: - ops.append(dict(op="replace", path="{0}/{1}/description".format(path, match.index), value=description)) - match.details["description"] = description + if state == "present": + if (module.params.get("entries") is not None and len(entries) == 0) or (not entries): + mso.fail_json(msg=err_message_min_entries) - if module.params.get("entries") is not None and match.details.get("entries") != entries: - ops.append(dict(op="replace", path="{0}/{1}/mcastRtMapEntryList".format(path, match.index), value=entries)) - match.details["entries"] = entries + mso_values = dict( + name=route_map_policy, + description=description, + mcastRtMapEntryList=entries, + ) - mso.sanitize(match.details) + if match: + update_path = "{0}/{1}".format(path, match.index) + append_update_ops_data(ops, match.details, update_path, mso_values) + mso.sanitize(match.details, collate=True) else: - - if not entries: - mso.fail_json(msg=err_message_min_entries) - - payload = {"name": route_map_policy, "mcastRtMapEntryList": entries} - if description: - payload["description"] = description - - ops.append(dict(op="add", path="{0}/-".format(path), value=copy.deepcopy(payload))) - - payload["entries"] = payload.pop("mcastRtMapEntryList") - mso.sanitize(payload) - - mso.existing = mso.proposed + mso.sanitize(mso_values) + ops.append(dict(op="add", path="{0}/-".format(path), value=mso.sent)) elif state == "absent": if match: @@ -245,7 +223,14 @@ def main(): mso.existing = {} if not module.check_mode and ops: - mso.request(mso_template.template_path, method="PATCH", data=ops) + mso_template.template = mso.request(mso_template.template_path, method="PATCH", data=ops) + match = get_multicast_route_map_policy(mso_template, route_map_policy_uuid, route_map_policy) + if match: + mso.existing = match.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() @@ -265,5 +250,25 @@ def get_entries_payload(entries): return payload +def get_multicast_route_map_policy(mso_template, uuid=None, name=None, fail_module=False): + """ + Get the Multicast Route Map Policy by UUID or Name. + :param uuid: UUID of the Multicast Route Map Policy to search for -> Str + :param name: Name of the Multicast Route Map 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[] + """ + match = mso_template.template.get("tenantPolicyTemplate", {}).get("template", {}).get("mcastRouteMapPolicies", []) + if uuid or name: # Query a specific object + return mso_template.get_object_by_key_value_pairs( + "Multicast Route Map Policy", match, [KVPair("uuid", uuid) if uuid else KVPair("name", name)], fail_module + ) + return match # Query all objects + + if __name__ == "__main__": main() diff --git a/tests/integration/targets/ndo_route_map_policy_multicast/tasks/main.yml b/tests/integration/targets/ndo_route_map_policy_multicast/tasks/main.yml index 1199fb3c..f36f1e3d 100644 --- a/tests/integration/targets/ndo_route_map_policy_multicast/tasks/main.yml +++ b/tests/integration/targets/ndo_route_map_policy_multicast/tasks/main.yml @@ -5,19 +5,19 @@ - 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.' + 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) }}' + 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 @@ -27,31 +27,29 @@ 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 }}' + 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} + - { site: "ansible_test", apic_site_id: 101 } + - { site: "ansible_test_2", apic_site_id: 102 } - name: Ensure tenants exist - cisco.mso.mso_tenant: + cisco.mso.mso_tenant: <<: *mso_info - tenant: '{{ item }}' + tenant: "{{ item }}" users: - - '{{ mso_username }}' + - "{{ mso_username }}" sites: - '{{ mso_site | default("ansible_test") }}' - ansible_test_2 @@ -75,7 +73,8 @@ # CREATE - name: Create a new route map policy multicast (check_mode) - cisco.mso.ndo_route_map_policy_multicast: &create_route_map_policy_multicast + cisco.mso.ndo_route_map_policy_multicast: + &create_route_map_policy_multicast <<: *mso_info template: ansible_tenant_template route_map_policy: ansible_test_route_map_policy @@ -104,37 +103,38 @@ - cm_create_new_route_map_policy_multicast is changed - cm_create_new_route_map_policy_multicast.previous == {} - cm_create_new_route_map_policy_multicast.current.name == "ansible_test_route_map_policy" - - cm_create_new_route_map_policy_multicast.current.entries.0.order == 1 - - cm_create_new_route_map_policy_multicast.current.entries.0.group == "226.2.2.0/24" - - cm_create_new_route_map_policy_multicast.current.entries.0.source == "1.1.1.1/24" - - cm_create_new_route_map_policy_multicast.current.entries.0.action == "permit" + - cm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.order == 1 + - cm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.group == "226.2.2.0/24" + - cm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.source == "1.1.1.1/24" + - cm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.action == "permit" - nm_create_new_route_map_policy_multicast is changed - nm_create_new_route_map_policy_multicast.previous == {} - nm_create_new_route_map_policy_multicast.current.name == "ansible_test_route_map_policy" - - nm_create_new_route_map_policy_multicast.current.entries.0.order == 1 - - nm_create_new_route_map_policy_multicast.current.entries.0.group == "226.2.2.0/24" - - nm_create_new_route_map_policy_multicast.current.entries.0.source == "1.1.1.1/24" - - nm_create_new_route_map_policy_multicast.current.entries.0.action == "permit" + - nm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.order == 1 + - nm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.group == "226.2.2.0/24" + - nm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.source == "1.1.1.1/24" + - nm_create_new_route_map_policy_multicast.current.mcastRtMapEntryList.0.action == "permit" - nm_create_new_route_map_policy_multicast_again is not changed - nm_create_new_route_map_policy_multicast_again.previous.name == "ansible_test_route_map_policy" - nm_create_new_route_map_policy_multicast_again.previous.description == "" - nm_create_new_route_map_policy_multicast_again.previous.uuid is defined - - nm_create_new_route_map_policy_multicast_again.previous.entries.0.order == 1 - - nm_create_new_route_map_policy_multicast_again.previous.entries.0.group == "226.2.2.0/24" - - nm_create_new_route_map_policy_multicast_again.previous.entries.0.source == "1.1.1.1/24" - - nm_create_new_route_map_policy_multicast_again.previous.entries.0.action == "permit" + - nm_create_new_route_map_policy_multicast_again.previous.mcastRtMapEntryList.0.order == 1 + - nm_create_new_route_map_policy_multicast_again.previous.mcastRtMapEntryList.0.group == "226.2.2.0/24" + - nm_create_new_route_map_policy_multicast_again.previous.mcastRtMapEntryList.0.source == "1.1.1.1/24" + - nm_create_new_route_map_policy_multicast_again.previous.mcastRtMapEntryList.0.action == "permit" - nm_create_new_route_map_policy_multicast_again.current.name == "ansible_test_route_map_policy" - nm_create_new_route_map_policy_multicast_again.current.description == "" - nm_create_new_route_map_policy_multicast_again.current.uuid is defined - - nm_create_new_route_map_policy_multicast_again.current.entries.0.order == 1 - - nm_create_new_route_map_policy_multicast_again.current.entries.0.group == "226.2.2.0/24" - - nm_create_new_route_map_policy_multicast_again.current.entries.0.source == "1.1.1.1/24" - - nm_create_new_route_map_policy_multicast_again.current.entries.0.action == "permit" + - nm_create_new_route_map_policy_multicast_again.current.mcastRtMapEntryList.0.order == 1 + - nm_create_new_route_map_policy_multicast_again.current.mcastRtMapEntryList.0.group == "226.2.2.0/24" + - nm_create_new_route_map_policy_multicast_again.current.mcastRtMapEntryList.0.source == "1.1.1.1/24" + - nm_create_new_route_map_policy_multicast_again.current.mcastRtMapEntryList.0.action == "permit" # UPDATE - name: Update a route map policy multicast description (check_mode) - cisco.mso.ndo_route_map_policy_multicast: &update_route_map_policy_multicast + cisco.mso.ndo_route_map_policy_multicast: + &update_route_map_policy_multicast <<: *create_route_map_policy_multicast description: changed_description check_mode: true @@ -164,9 +164,10 @@ - nm_update_route_map_policy_multicast_description_again.current.description == "changed_description" - name: Update a route map policy multicast name - cisco.mso.ndo_route_map_policy_multicast: &update_route_map_policy_multicast_name + cisco.mso.ndo_route_map_policy_multicast: + &update_route_map_policy_multicast_name <<: *update_route_map_policy_multicast - route_map_policy_uuid: '{{ nm_update_route_map_policy_multicast_description.current.uuid }}' + route_map_policy_uuid: "{{ nm_update_route_map_policy_multicast_description.current.uuid }}" route_map_policy: ansible_test_route_map_policy_changed register: nm_update_route_map_policy_multicast_name @@ -182,7 +183,8 @@ register: nm_update_route_map_policy_multicast_entries_change_input - name: Update a route map policy multicast entries to 4 - cisco.mso.ndo_route_map_policy_multicast: &update_route_map_policy_multicast_entries_4 + cisco.mso.ndo_route_map_policy_multicast: + &update_route_map_policy_multicast_entries_4 <<: *update_route_map_policy_multicast_name entries: - order: 1 @@ -266,27 +268,28 @@ - nm_update_route_map_policy_multicast_name.previous.name == "ansible_test_route_map_policy" - nm_update_route_map_policy_multicast_name.current.name == "ansible_test_route_map_policy_changed" - nm_update_route_map_policy_multicast_entries_change_input is changed - - nm_update_route_map_policy_multicast_entries_change_input.previous.entries | length == 1 - - nm_update_route_map_policy_multicast_entries_change_input.previous.entries.0.order == 1 - - nm_update_route_map_policy_multicast_entries_change_input.current.entries | length == 1 - - nm_update_route_map_policy_multicast_entries_change_input.current.entries.0.order == 2 + - nm_update_route_map_policy_multicast_entries_change_input.previous.mcastRtMapEntryList | length == 1 + - nm_update_route_map_policy_multicast_entries_change_input.previous.mcastRtMapEntryList.0.order == 1 + - nm_update_route_map_policy_multicast_entries_change_input.current.mcastRtMapEntryList | length == 1 + - nm_update_route_map_policy_multicast_entries_change_input.current.mcastRtMapEntryList.0.order == 2 - nm_update_route_map_policy_multicast_entries_4 is changed - - nm_update_route_map_policy_multicast_entries_4.previous.entries | length == 1 - - nm_update_route_map_policy_multicast_entries_4.current.entries | length == 4 + - nm_update_route_map_policy_multicast_entries_4.previous.mcastRtMapEntryList | length == 1 + - nm_update_route_map_policy_multicast_entries_4.current.mcastRtMapEntryList | length == 4 - nm_update_route_map_policy_multicast_entries_4_again is not changed - - nm_update_route_map_policy_multicast_entries_4_again.previous.entries | length == 4 - - nm_update_route_map_policy_multicast_entries_4_again.current.entries | length == 4 + - nm_update_route_map_policy_multicast_entries_4_again.previous.mcastRtMapEntryList | length == 4 + - nm_update_route_map_policy_multicast_entries_4_again.current.mcastRtMapEntryList | length == 4 - nm_update_route_map_policy_multicast_entries_4_order is changed - - nm_update_route_map_policy_multicast_entries_4_order.previous.entries | length == 4 - - nm_update_route_map_policy_multicast_entries_4_order.current.entries | length == 4 + - nm_update_route_map_policy_multicast_entries_4_order.previous.mcastRtMapEntryList | length == 4 + - nm_update_route_map_policy_multicast_entries_4_order.current.mcastRtMapEntryList | length == 4 - nm_delete_route_map_policy_multicast_entries_3 is changed - - nm_delete_route_map_policy_multicast_entries_3.previous.entries | length == 4 - - nm_delete_route_map_policy_multicast_entries_3.current.entries | length == 3 + - nm_delete_route_map_policy_multicast_entries_3.previous.mcastRtMapEntryList | length == 4 + - nm_delete_route_map_policy_multicast_entries_3.current.mcastRtMapEntryList | length == 3 # QUERY - name: Create another route map policy multicast - cisco.mso.ndo_route_map_policy_multicast: &create_route_map_policy_multicast_2 + cisco.mso.ndo_route_map_policy_multicast: + &create_route_map_policy_multicast_2 <<: *create_route_map_policy_multicast route_map_policy: ansible_test_route_map_policy_2 description: "This is a test route map policy multicast 2" @@ -315,10 +318,11 @@ # ERRORS - name: Error entries provided as null on create - cisco.mso.ndo_route_map_policy_multicast: &create_route_map_policy_multicast_null_entries + cisco.mso.ndo_route_map_policy_multicast: + &create_route_map_policy_multicast_null_entries <<: *create_route_map_policy_multicast route_map_policy: ansible_test_route_map_policy_3 - entries: '{{ fakevar | default(omit)}}' + entries: "{{ fakevar | default(omit)}}" register: err_entries_create_null ignore_errors: true @@ -349,7 +353,8 @@ # DELETE - name: Delete a route map policy multicast (check_mode) - cisco.mso.ndo_route_map_policy_multicast: &delete_route_map_policy_multicast + cisco.mso.ndo_route_map_policy_multicast: + &delete_route_map_policy_multicast <<: *update_route_map_policy_multicast_name state: absent check_mode: true @@ -370,11 +375,11 @@ that: - cm_delete_route_map_policy_multicast is changed - cm_delete_route_map_policy_multicast.previous.name == 'ansible_test_route_map_policy_changed' - - cm_delete_route_map_policy_multicast.previous.entries | length == 3 + - cm_delete_route_map_policy_multicast.previous.mcastRtMapEntryList | length == 3 - cm_delete_route_map_policy_multicast.current == {} - nm_delete_route_map_policy_multicast is changed - nm_delete_route_map_policy_multicast.previous.name == 'ansible_test_route_map_policy_changed' - - nm_delete_route_map_policy_multicast.previous.entries | length == 3 + - nm_delete_route_map_policy_multicast.previous.mcastRtMapEntryList | length == 3 - nm_delete_route_map_policy_multicast.current == {} - nm_delete_route_map_policy_multicast_again is not changed - nm_delete_route_map_policy_multicast_again.previous == {}