From 61b09044be1d562adca2ef1e8969e748ecf82d6d Mon Sep 17 00:00:00 2001 From: Anvitha-Jain Date: Wed, 20 Dec 2023 23:06:55 +0530 Subject: [PATCH] [minor_changes] Add aci_l3out_bfd_multihop_interface_profile, aci_l3out_bfd_interface_profile, aci_interface_policy_bfd_multihop, aci_interface_policy_bfd and aci_bfd_multihop_node_policy modules (#492) --- .../modules/aci_bfd_multihop_node_policy.py | 320 +++++++++++++++ plugins/modules/aci_interface_policy_bfd.py | 318 +++++++++++++++ .../aci_interface_policy_bfd_multihop.py | 318 +++++++++++++++ .../aci_l3out_bfd_interface_profile.py | 367 ++++++++++++++++++ ...ci_l3out_bfd_multihop_interface_profile.py | 366 +++++++++++++++++ .../aci_bfd_multihop_node_policy/aliases | 2 + .../tasks/main.yml | 245 ++++++++++++ .../targets/aci_interface_policy_bfd/aliases | 2 + .../aci_interface_policy_bfd/tasks/main.yml | 245 ++++++++++++ .../aci_interface_policy_bfd_multihop/aliases | 2 + .../tasks/main.yml | 245 ++++++++++++ .../aci_l3out_bfd_interface_profile/aliases | 2 + .../tasks/main.yml | 226 +++++++++++ .../aliases | 2 + .../tasks/main.yml | 233 +++++++++++ 15 files changed, 2893 insertions(+) create mode 100644 plugins/modules/aci_bfd_multihop_node_policy.py create mode 100644 plugins/modules/aci_interface_policy_bfd.py create mode 100644 plugins/modules/aci_interface_policy_bfd_multihop.py create mode 100644 plugins/modules/aci_l3out_bfd_interface_profile.py create mode 100644 plugins/modules/aci_l3out_bfd_multihop_interface_profile.py create mode 100644 tests/integration/targets/aci_bfd_multihop_node_policy/aliases create mode 100644 tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml create mode 100644 tests/integration/targets/aci_interface_policy_bfd/aliases create mode 100644 tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml create mode 100644 tests/integration/targets/aci_interface_policy_bfd_multihop/aliases create mode 100644 tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml create mode 100644 tests/integration/targets/aci_l3out_bfd_interface_profile/aliases create mode 100644 tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml create mode 100644 tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases create mode 100644 tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml diff --git a/plugins/modules/aci_bfd_multihop_node_policy.py b/plugins/modules/aci_bfd_multihop_node_policy.py new file mode 100644 index 000000000..b6d1f9172 --- /dev/null +++ b/plugins/modules/aci_bfd_multihop_node_policy.py @@ -0,0 +1,320 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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: aci_bfd_multihop_node_policy +short_description: Manage BFD Multihop Node policies +description: +- Manage BFD Multihop Node policy (bfd:MhNodePol) configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later +options: + tenant: + description: + - Name of an existing tenant + type: str + name: + description: + - Name of the BFD Multihop Node policy + type: str + aliases: [ bfd_multihop_node_policy ] + description: + description: + - Description of the BFD Multihop Node policy + type: str + admin_state: + description: + - Admin state of the BFD Multihop Node policy + - APIC sets the default value to enabled + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - Detection multiplier of the BFD Multihop Node policy + - APIC sets the default value to 3 + - Allowed range is 1-50 + type: int + min_transmit_interval: + description: + - Minimum transmit (Tx) interval of the BFD Multihop Node policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + type: int + min_receive_interval: + description: + - Minimum receive (Rx) interval of the BFD Multihop Node policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + type: int + state: + description: + - Use C(present) or C(absent) for adding or removing + - Use C(query) for listing an object or multiple objects + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant) must exist before using this module in your playbook + The M(cisco.aci.aci_tenant) modules can be used for this +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bfd:MhNodePol) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + description: Ansible BFD Multihop Node Policy + state: present + delegate_to: localhost + +- name: Remove a BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + delegate_to: localhost + +- name: Query a BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: my_dhcp_relay + state: query + delegate_to: localhost + register: query_result + +- name: Query all BFD Multihop Node policies in a specific tenant + cisco.aci.aci_bfd_multihop_node_policy: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + name=dict(type="str", aliases=["bfd_multihop_node_policy"]), + description=dict(type="str"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_transmit_interval=dict(type="int"), + min_receive_interval=dict(type="int"), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "tenant"]], + ["state", "present", ["name", "tenant"]], + ], + ) + + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + admin_state = module.params.get("admin_state") + detection_multiplier = module.params.get("detection_multiplier") + min_transmit_interval = module.params.get("min_transmit_interval") + min_receive_interval = module.params.get("min_receive_interval") + + aci = ACIModule(module) + aci.construct_url( + root_class=dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), + subclass_1=dict( + aci_class="bfdMhNodePol", + aci_rn="bfdMhNodePol-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + adminSt=admin_state, + ) + + if detection_multiplier and detection_multiplier not in range(1, 50): + aci.fail_json(msg='The "detection_multiplier" must be a value between 1 and 50') + else: + class_config["detectMult"] = detection_multiplier + if min_transmit_interval and min_transmit_interval not in range(250, 999): + aci.fail_json(msg='The "min_transmit_interval" must be a value between 250 and 999') + else: + class_config["minTxIntvl"] = min_transmit_interval + if min_receive_interval and min_receive_interval not in range(250, 999): + aci.fail_json(msg='The "min_receive_interval" must be a value between 250 and 999') + else: + class_config["minRxIntvl"] = min_receive_interval + + aci.payload( + aci_class="bfdMhNodePol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bfdMhNodePol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/aci_interface_policy_bfd.py b/plugins/modules/aci_interface_policy_bfd.py new file mode 100644 index 000000000..8a16c7bd7 --- /dev/null +++ b/plugins/modules/aci_interface_policy_bfd.py @@ -0,0 +1,318 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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: aci_interface_policy_bfd +short_description: Manage BFD Interface policies +description: +- Manage BFD Interface policy (bfd:IfPol) configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later +options: + tenant: + description: + - Name of an existing tenant + type: str + name: + description: + - Name of the BFD Interface policy + type: str + aliases: [ bfd_interface_policy ] + description: + description: + - Description of the BFD Interface policy + type: str + admin_state: + description: + - Admin state of the BFD Interface policy + - APIC sets the default value to enabled + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - Detection multiplier of the BFD Interface policy + - APIC sets the default value to 3 + - Allowed range is 1-50 + type: int + min_transmit_interval: + description: + - Minimum transmit (Tx) interval of the BFD Interface policy + - APIC sets the default value to 50 + - Allowed range is 250-999 + type: int + min_receive_interval: + description: + - Minimum receive (Rx) interval of the BFD Interface policy + - APIC sets the default value to 50 + - Allowed range is 250-999 + type: int + state: + description: + - Use C(present) or C(absent) for adding or removing + - Use C(query) for listing an object or multiple objects + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant) must exist before using this module in your playbook + The M(cisco.aci.aci_tenant) modules can be used for this +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bfd:IfPol) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_interface_policy + description: Ansible BFD Interface Policy + state: present + delegate_to: localhost + +- name: Remove a BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + delegate_to: localhost + +- name: Query a BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: query + delegate_to: localhost + +- name: Query all BFD Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + state: query + delegate_to: localhost +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + name=dict(type="str", aliases=["bfd_interface_policy"]), + description=dict(type="str"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_transmit_interval=dict(type="int"), + min_receive_interval=dict(type="int"), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "tenant"]], + ["state", "present", ["name", "tenant"]], + ], + ) + + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + admin_state = module.params.get("admin_state") + detection_multiplier = module.params.get("detection_multiplier") + min_transmit_interval = module.params.get("min_transmit_interval") + min_receive_interval = module.params.get("min_receive_interval") + + aci = ACIModule(module) + aci.construct_url( + root_class=dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), + subclass_1=dict( + aci_class="bfdIfPol", + aci_rn="bfdIfPol-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + adminSt=admin_state, + ) + + if detection_multiplier and detection_multiplier not in range(1, 50): + module.fail_json(msg='The "detection_multiplier" must be a value between 1 and 50') + else: + class_config["detectMult"] = detection_multiplier + if min_transmit_interval and min_transmit_interval not in range(50, 999): + module.fail_json(msg='The "min_transmit_interval" must be a value between 50 and 999') + else: + class_config["minTxIntvl"] = min_transmit_interval + if min_receive_interval and min_receive_interval not in range(50, 999): + module.fail_json(msg='The "min_receive_interval" must be a value between 50 and 999') + else: + class_config["minRxIntvl"] = min_receive_interval + + aci.payload( + aci_class="bfdIfPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bfdIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/aci_interface_policy_bfd_multihop.py b/plugins/modules/aci_interface_policy_bfd_multihop.py new file mode 100644 index 000000000..cf972c562 --- /dev/null +++ b/plugins/modules/aci_interface_policy_bfd_multihop.py @@ -0,0 +1,318 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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: aci_interface_policy_bfd_multihop +short_description: Manage BFD Multihop Interface policies +description: +- Manage BFD Multihop Interface policy (bfd:MhIfPol) configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later +options: + tenant: + description: + - Name of an existing tenant + type: str + name: + description: + - Name of the BFD Multihop Interface policy + type: str + aliases: [ bfd_multihop_interface_policy ] + description: + description: + - Description of the BFD Multihop Interface policy + type: str + admin_state: + description: + - Admin state of the BFD Multihop Interface policy + - APIC sets the default value to enabled. + type: str + choices: [ enabled, disabled ] + detection_multiplier: + description: + - Detection multiplier of the BFD Multihop Interface policy + - APIC sets the default value to 3. + - Allowed range is 1-50. + type: int + min_transmit_interval: + description: + - Minimum transmit (Tx) interval of the BFD Multihop Interface policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + type: int + min_receive_interval: + description: + - Minimum receive (Rx) interval of the BFD Multihop Interface policy + - APIC sets the default value to 250 + - Allowed range is 250-999 + type: int + state: + description: + - Use C(present) or C(absent) for adding or removing + - Use C(query) for listing an object or multiple objects + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant) must exist before using this module in your playbook + The M(cisco.aci.aci_tenant) modules can be used for this +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bfd:MhIfPol) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + description: Ansible BFD Multihop Interface Policy + state: present + delegate_to: localhost + +- name: Remove a BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + delegate_to: localhost + +- name: Query a BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: query + delegate_to: localhost + +- name: Query all BFD Multihop Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd_multihop: + host: apic + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + state: query + delegate_to: localhost +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + name=dict(type="str", aliases=["bfd_multihop_interface_policy"]), + description=dict(type="str"), + admin_state=dict(type="str", choices=["enabled", "disabled"]), + detection_multiplier=dict(type="int"), + min_transmit_interval=dict(type="int"), + min_receive_interval=dict(type="int"), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + tenant=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["name", "tenant"]], + ["state", "present", ["name", "tenant"]], + ], + ) + + name = module.params.get("name") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + admin_state = module.params.get("admin_state") + detection_multiplier = module.params.get("detection_multiplier") + min_transmit_interval = module.params.get("min_transmit_interval") + min_receive_interval = module.params.get("min_receive_interval") + + aci = ACIModule(module) + aci.construct_url( + root_class=dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), + subclass_1=dict( + aci_class="bfdMhIfPol", + aci_rn="bfdMhIfPol-{0}".format(name), + module_object=name, + target_filter={"name": name}, + ), + ) + + aci.get_existing() + + if state == "present": + class_config = dict( + name=name, + descr=description, + adminSt=admin_state, + ) + + if detection_multiplier and detection_multiplier not in range(1, 50): + module.fail_json(msg='The "detection_multiplier" must be a value between 1 and 50') + else: + class_config["detectMult"] = detection_multiplier + if min_transmit_interval and min_transmit_interval not in range(250, 999): + module.fail_json(msg='The "min_transmit_interval" must be a value between 250 and 999') + else: + class_config["minTxIntvl"] = min_transmit_interval + if min_receive_interval and min_receive_interval not in range(250, 999): + module.fail_json(msg='The "min_receive_interval" must be a value between 250 and 999') + else: + class_config["minRxIntvl"] = min_receive_interval + + aci.payload( + aci_class="bfdMhIfPol", + class_config=class_config, + ) + + aci.get_diff(aci_class="bfdMhIfPol") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/aci_l3out_bfd_interface_profile.py b/plugins/modules/aci_l3out_bfd_interface_profile.py new file mode 100644 index 000000000..703b48c8e --- /dev/null +++ b/plugins/modules/aci_l3out_bfd_interface_profile.py @@ -0,0 +1,367 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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: aci_l3out_bfd_interface_profile +short_description: Manage L3Out BFD Interface profiles +description: +- Manage L3Out BFD Interface profile (bfd:IfP) configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later and for non-cloud APICs +options: + tenant: + description: + - Name of an existing tenant + type: str + aliases: [ tenant_name ] + l3out: + description: + - Name of an existing L3Out + type: str + aliases: [ l3out_name ] + l3out_logical_node_profile: + description: + - Name of an existing L3Out Logical Node profile + type: str + aliases: [ logical_node_profile, logical_node_profile_name ] + l3out_logical_interface_profile: + description: + - Name of an existing L3Out Logical Interface profile + type: str + aliases: [ logical_interface_profile, logical_interface_profile_name ] + name: + description: + - Name of the L3Out BFD Interface profile object + type: str + aliases: [ bfd_multihop_interface_profile ] + name_alias: + description: + - Name Alias of the L3Out BFD Interface profile object + type: str + description: + description: + - Description of the L3Out BFD Interface profile object + type: str + aliases: [ descr ] + authentication_type: + description: + - Authentication Type of the L3Out BFD Interface profile object + - APIC sets the default value to none + type: str + choices: [ none, sha1 ] + key: + description: + - Authentication Key of the L3Out BFD Interface profile object + type: str + key_id: + description: + - Authentication Key ID of the L3Out BFD Interface profile object + - APIC sets the default value to 3 + - Allowed range is 1-255 + type: int + bfd_interface_policy: + description: + - The name of the Interface policy + type: str + aliases: [ interface_policy, interface_policy_name ] + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant), c(l3out), C(l3out_logical_node_profile) and C(l3out_logical_interface_profile) must exist before using this module in your playbook + The M(cisco.aci.aci_tenant) modules can be used for this +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bfd:IfP) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_interface_policy_bfd +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: present + delegate_to: localhost + +- name: Query a new L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: query + delegate_to: localhost + +- name: Query all L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: absent + delegate_to: localhost +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + l3out_logical_node_profile=dict(type="str", aliases=["logical_node_profile_name", "logical_node_profile"]), + l3out_logical_interface_profile=dict(type="str", aliases=["logical_interface_profile_name", "logical_interface_profile"]), + name=dict(type="str", aliases=["bfd_multihop_interface_profile"]), + name_alias=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + authentication_type=dict(type="str", choices=["none", "sha1"]), + key=dict(type="str", no_log=True), + key_id=dict(type="int"), + bfd_interface_policy=dict(type="str", aliases=["interface_policy", "interface_policy_name"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile"]], + ["state", "present", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile", "bfd_interface_policy"]], + ["authentication_type", "sha1", ["key"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + l3out_logical_node_profile = module.params.get("l3out_logical_node_profile") + l3out_logical_interface_profile = module.params.get("l3out_logical_interface_profile") + name = module.params.get("name") + name_alias = module.params.get("name_alias") + description = module.params.get("description") + authentication_type = module.params.get("authentication_type") + key = module.params.get("key") + key_id = module.params.get("key_id") + bfd_interface_policy = module.params.get("bfd_interface_policy") + state = module.params.get("state") + + aci = ACIModule(module) + aci.construct_url( + root_class=dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), + subclass_1=dict( + aci_class="l3extOut", + aci_rn="out-{0}".format(l3out), + module_object=l3out, + target_filter={"name": l3out}, + ), + subclass_2=dict( + aci_class="l3extLNodeP", + aci_rn="lnodep-{0}".format(l3out_logical_node_profile), + module_object=l3out_logical_node_profile, + target_filter={"name": l3out_logical_node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(l3out_logical_interface_profile), + module_object=l3out_logical_interface_profile, + target_filter={"name": l3out_logical_interface_profile}, + ), + subclass_4=dict( + aci_class="bfdIfP", + aci_rn="bfdIfP", + module_object="bfdIfP", + target_filter={"name": name}, + ), + child_classes=["bfdRsIfPol"], + ) + + aci.get_existing() + + if state == "present": + child_configs = [] + class_config = dict( + name=name, + nameAlias=name_alias, + descr=description, + key=key, + type=authentication_type, + ) + + if key_id and key_id not in range(1, 255): + module.fail_json(msg='The "key_id" must be a value between 1 and 255') + else: + class_config["keyId"] = key_id + + if bfd_interface_policy is not None: + child_configs.append(dict(bfdRsIfPol=dict(attributes=dict(tnBfdIfPolName=bfd_interface_policy)))) + + aci.payload( + aci_class="bfdIfP", + class_config=class_config, + child_configs=child_configs, + ) + + aci.get_diff(aci_class="bfdIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py b/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py new file mode 100644 index 000000000..fe6d94bab --- /dev/null +++ b/plugins/modules/aci_l3out_bfd_multihop_interface_profile.py @@ -0,0 +1,366 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Anvitha Jain (@anvjain) +# 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: aci_l3out_bfd_multihop_interface_profile +short_description: Manage BFD Multihop Interface profiles +description: +- Manage BFD Multihop Interface profile (bfd:MhIfP) configuration on Cisco ACI fabrics +- Only available in APIC version 5.2 or later and for non-cloud APICs +options: + tenant: + description: + - Name of an existing tenant + type: str + aliases: [ tenant_name ] + l3out: + description: + - Name of an existing L3Out + type: str + aliases: [ l3out_name ] + l3out_logical_node_profile: + description: + - Name of an existing L3Out Logical Node profile + type: str + aliases: [ logical_node_profile, logical_node_profile_name ] + l3out_logical_interface_profile: + description: + - Name of an existing L3Out Logical Interface profile + type: str + aliases: [ logical_interface_profile, logical_interface_profile_name ] + name: + description: + - Name of the BFD Multihop Interface Profile object + type: str + aliases: [ bfd_multihop_interface_profile ] + name_alias: + description: + - Name Alias of the BFD Multihop Interface Profile object + type: str + description: + description: + - Description of the BFD Multihop Interface Profile object + type: str + aliases: [ descr ] + authentication_type: + description: + - Authentication Type of the BFD Multihop Interface Profile object + - APIC sets the default value to none. + type: str + choices: [ none, sha1 ] + key: + description: + - Authentication Key of the BFD Multihop Interface Profile object + type: str + key_id: + description: + - Authentication Key ID of the BFD Multihop Interface Profile object + - APIC sets the default value to 3 + - Allowed range is 1-255 + type: int + bfd_multihop_interface_policy: + description: + - The name of the BFD Multihop Interface policy + type: str + aliases: [ multihop_interface_policy, multihop_interface_policy_name ] + state: + description: + - Use C(present) or C(absent) for adding or removing + - Use C(query) for listing an object or multiple objects + type: str + choices: [ absent, present, query ] + default: present +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation + +notes: +- The C(tenant), c(l3out), C(l3out_logical_node_profile) and C(l3out_logical_interface_profile) must exist before using this module in your playbook + The M(cisco.aci.aci_tenant) modules can be used for this +seealso: +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(bfd:MhIfP) + link: https://developer.cisco.com/docs/apic-mim-ref/ +- module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_l3out_logical_node_profile +- module: cisco.aci.aci_l3out_logical_interface_profile +- module: cisco.aci.aci_interface_policy_bfd_multihop +author: +- Anvitha Jain (@anvjain) +""" + +EXAMPLES = r""" +- name: Add a new L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: present + delegate_to: localhost + +- name: Query a new L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: query + delegate_to: localhost + +- name: Query all L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + +- name: Delete L3Out BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + username: admin + password: SomeSecretPassword + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + state: absent + delegate_to: localhost +""" + +RETURN = r""" + current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } + raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' + sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } + previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] + proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } + filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only + method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST + response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) + status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 + url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json + """ + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), + l3out=dict(type="str", aliases=["l3out_name"]), + l3out_logical_node_profile=dict(type="str", aliases=["logical_node_profile_name", "logical_node_profile"]), + l3out_logical_interface_profile=dict(type="str", aliases=["logical_interface_profile_name", "logical_interface_profile"]), + name=dict(type="str", aliases=["bfd_multihop_interface_profile"]), + name_alias=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + authentication_type=dict(type="str", choices=["none", "sha1"]), + key=dict(type="str", no_log=True), + key_id=dict(type="int"), + bfd_multihop_interface_policy=dict(type="str", aliases=["multihop_interface_policy", "multihop_interface_policy_name"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile"]], + ["state", "present", ["tenant", "l3out", "l3out_logical_node_profile", "l3out_logical_interface_profile", "bfd_multihop_interface_policy"]], + ], + ) + + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + l3out_logical_node_profile = module.params.get("l3out_logical_node_profile") + l3out_logical_interface_profile = module.params.get("l3out_logical_interface_profile") + name = module.params.get("name") + name_alias = module.params.get("name_alias") + description = module.params.get("description") + authentication_type = module.params.get("authentication_type") + key = module.params.get("key") + key_id = module.params.get("key_id") + bfd_multihop_interface_policy = module.params.get("bfd_multihop_interface_policy") + state = module.params.get("state") + + aci = ACIModule(module) + aci.construct_url( + root_class=dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), + subclass_1=dict( + aci_class="l3extOut", + aci_rn="out-{0}".format(l3out), + module_object=l3out, + target_filter={"name": l3out}, + ), + subclass_2=dict( + aci_class="l3extLNodeP", + aci_rn="lnodep-{0}".format(l3out_logical_node_profile), + module_object=l3out_logical_node_profile, + target_filter={"name": l3out_logical_node_profile}, + ), + subclass_3=dict( + aci_class="l3extLIfP", + aci_rn="lifp-{0}".format(l3out_logical_interface_profile), + module_object=l3out_logical_interface_profile, + target_filter={"name": l3out_logical_interface_profile}, + ), + subclass_4=dict( + aci_class="bfdMhIfP", + aci_rn="bfdMhIfP", + module_object="bfdMhIfP", + target_filter={"name": name}, + ), + child_classes=["bfdRsMhIfPol"], + ) + + aci.get_existing() + aci.stdout = str(aci.get_existing()) + if state == "present": + child_configs = [] + class_config = dict( + name=name, + nameAlias=name_alias, + descr=description, + type=authentication_type, + key=key, + ) + + if key_id and key_id not in range(1, 255): + module.fail_json(msg='The "key_id" must be a value between 1 and 255') + else: + class_config["keyId"] = key_id + + if bfd_multihop_interface_policy is not None: + child_configs.append(dict(bfdRsMhIfPol=dict(attributes=dict(tnBfdMhIfPolName=bfd_multihop_interface_policy)))) + + aci.payload( + aci_class="bfdMhIfP", + class_config=class_config, + child_configs=child_configs, + ) + + aci.get_diff(aci_class="bfdMhIfP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/aci_bfd_multihop_node_policy/aliases b/tests/integration/targets/aci_bfd_multihop_node_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_bfd_multihop_node_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml b/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml new file mode 100644 index 000000000..99f853680 --- /dev/null +++ b/tests/integration/targets/aci_bfd_multihop_node_policy/tasks/main.yml @@ -0,0 +1,245 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# 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 APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') # This condition will execute only when APIC version >= 5.2 + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + - name: Add a new tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE BFD Multihop Node policy + - name: Add a new BFD Multihop Node policy - check mode + cisco.aci.aci_bfd_multihop_node_policy: &add_bfd_multihop_node_pol + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + description: Ansible BFD Multihop Node Policy + state: present + check_mode: true + register: cm_add_bfd_multihop_node_pol + + - name: Add a new BFD Multihop Node policy - normal mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + state: present + register: nm_add_bfd_multihop_node_pol + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - cm_add_bfd_multihop_node_pol is changed + - nm_add_bfd_multihop_node_pol is changed + - cm_add_bfd_multihop_node_pol.previous == nm_add_bfd_multihop_node_pol.previous == [] + - cm_add_bfd_multihop_node_pol.proposed.bfdMhNodePol.attributes.dn == nm_add_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy" + - cm_add_bfd_multihop_node_pol.proposed.bfdMhNodePol.attributes.name == nm_add_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + - cm_add_bfd_multihop_node_pol.proposed.bfdMhNodePol.attributes.descr == nm_add_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.descr == "Ansible BFD Multihop Node Policy" + + - name: Add a new BFD Multihop Node policy again - idempotency + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + state: present + register: add_bfd_multihop_node_pol_again + + - name: Verify BFD Multihop Node Policy creation again - idempotency + assert: + that: + - add_bfd_multihop_node_pol_again is not changed + - add_bfd_multihop_node_pol_again.previous != [] + - add_bfd_multihop_node_pol_again.current | length == 1 + - add_bfd_multihop_node_pol_again.previous | length == 1 + + - name: Modify a BFD Multihop Node policy + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + admin_state: disabled + detection_multiplier: 5 + min_transmit_interval: 270 + min_receive_interval: 500 + state: present + register: update_bfd_multihop_node_pol + + - name: Verify modifying BFD Multihop Node Policy + assert: + that: + - update_bfd_multihop_node_pol is changed + - update_bfd_multihop_node_pol.previous != update_bfd_multihop_node_pol.current + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.descr == "Ansible BFD Multihop Node Policy" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.adminSt == "disabled" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.detectMult == "5" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.minRxIntvl == "500" + - update_bfd_multihop_node_pol.current.0.bfdMhNodePol.attributes.minTxIntvl == "270" + + # Added another BFD Multihop Node policy + - name: Add a new BFD Multihop Node policy - normal mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_2 + state: present + register: add_bfd_multihop_node_pol_2 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_2 is changed + - add_bfd_multihop_node_pol_2.previous == [] + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy_2" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy_2" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.descr == "Ansible BFD Multihop Node Policy" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.adminSt == "enabled" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.detectMult == "3" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.minRxIntvl == "250" + - add_bfd_multihop_node_pol_2.current.0.bfdMhNodePol.attributes.minTxIntvl == "250" + + - name: Query all BFD Multihop Node policies in a specific tenant + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + state: query + register: query_all_result + + - name: Verify querying all BFD Multihop Node Policies + assert: + that: + - query_all_result is not changed + - query_all_result.current.0.fvTenant.children | length == 2 + - query_all_result.current.0.fvTenant.children[0].bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy_2" + - query_all_result.current.0.fvTenant.children[1].bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + + - name: Query 'ansible_bfd_multihop_node_policy' BFD Multihop Node policies in a specific tenant + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: query + register: query_result + + - name: Verify querying'ansible_bfd_multihop_node_policy BFD' Multihop Node Policy + assert: + that: + - query_result is not changed + - query_result.current.0.bfdMhNodePol.attributes.dn == "uni/tn-ansible_tenant/bfdMhNodePol-ansible_bfd_multihop_node_policy" + - query_result.current.0.bfdMhNodePol.attributes.name == "ansible_bfd_multihop_node_policy" + + - name: Remove a BFD Multihop Node policy - check mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + check_mode: true + register: cm_remove_bfd_multihop_node_pol + + - name: Remove a BFD Multihop Node policy - normal mode + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + register: nm_remove_bfd_multihop_node_pol + + - name: Remove a BFD Multihop Node policy again + cisco.aci.aci_bfd_multihop_node_policy: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_node_policy + state: absent + register: remove_bfd_multihop_node_pol_again + + - name: Verify removing BFD Multihop Node Policies + assert: + that: + - nm_remove_bfd_multihop_node_pol is changed + - cm_remove_bfd_multihop_node_pol is changed + - cm_remove_bfd_multihop_node_pol.proposed == {} + - nm_remove_bfd_multihop_node_pol.previous != [] + - remove_bfd_multihop_node_pol_again is not changed + - remove_bfd_multihop_node_pol_again.current == nm_remove_bfd_multihop_node_pol.current == [] + +# Validating out of rage parameters. + +# Added BFD Multihop Node policy with out of the range detection_multiplier + - name: Add a new BFD Multihop Node policy - out of the range detection_multiplier + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_3 + detection_multiplier: 256 + state: present + ignore_errors: true + register: add_bfd_multihop_node_pol_3 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_3 is not changed + - add_bfd_multihop_node_pol_3.msg == "The \"detection_multiplier\" must be a value between 1 and 50" + +# Added BFD Multihop Node policy with out of the range min_transmit_interval + - name: Add a new BFD Multihop Node policy - out of the range min_transmit_interval + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_3 + min_transmit_interval: 50 + state: present + ignore_errors: true + register: add_bfd_multihop_node_pol_3 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_3 is not changed + - add_bfd_multihop_node_pol_3.msg == "The \"min_transmit_interval\" must be a value between 250 and 999" + +# Added BFD Multihop Node policy with out of the range min_receive_interval + - name: Add a new BFD Multihop Node policy - out of the range min_receive_interval + cisco.aci.aci_bfd_multihop_node_policy: + <<: *add_bfd_multihop_node_pol + name: ansible_bfd_multihop_node_policy_3 + min_receive_interval: 1000 + state: present + ignore_errors: true + register: add_bfd_multihop_node_pol_3 + + - name: Verify BFD Multihop Node Policy creation + assert: + that: + - add_bfd_multihop_node_pol_3 is not changed + - add_bfd_multihop_node_pol_3.msg == "The \"min_receive_interval\" must be a value between 250 and 999" diff --git a/tests/integration/targets/aci_interface_policy_bfd/aliases b/tests/integration/targets/aci_interface_policy_bfd/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_interface_policy_bfd/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml b/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml new file mode 100644 index 000000000..2d688f2c6 --- /dev/null +++ b/tests/integration/targets/aci_interface_policy_bfd/tasks/main.yml @@ -0,0 +1,245 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# 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 APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') # This condition will execute only when APIC version >= 5.2 + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + - name: Add a new tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE BFD Interface policy + - name: Add a new BFD Interface policy - check mode + cisco.aci.aci_interface_policy_bfd: &add_bfd_interface_pol + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + description: Ansible BFD Interface Policy + state: present + check_mode: true + register: cm_add_bfd_interface_pol + + - name: Add a new BFD Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + state: present + register: nm_add_bfd_interface_pol + + - name: Verify BFD Interface Policy creation + assert: + that: + - cm_add_bfd_interface_pol is changed + - nm_add_bfd_interface_pol is changed + - cm_add_bfd_interface_pol.previous == nm_add_bfd_interface_pol.previous == [] + - cm_add_bfd_interface_pol.proposed.bfdIfPol.attributes.dn == nm_add_bfd_interface_pol.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy" + - cm_add_bfd_interface_pol.proposed.bfdIfPol.attributes.name == nm_add_bfd_interface_pol.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + - cm_add_bfd_interface_pol.proposed.bfdIfPol.attributes.descr == nm_add_bfd_interface_pol.current.0.bfdIfPol.attributes.descr == "Ansible BFD Interface Policy" + + - name: Add a new BFD Interface policy again - idempotency + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + state: present + register: add_bfd_interface_pol_again + + - name: Verify BFD Interface Policy creation again - idempotency + assert: + that: + - add_bfd_interface_pol_again is not changed + - add_bfd_interface_pol_again.previous != [] + - add_bfd_interface_pol_again.current | length == 1 + - add_bfd_interface_pol_again.previous | length == 1 + + - name: Modify a BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + admin_state: disabled + detection_multiplier: 5 + min_transmit_interval: 270 + min_receive_interval: 500 + state: present + register: update_bfd_interface_pol + + - name: Verify modifying BFD Interface Policy + assert: + that: + - update_bfd_interface_pol is changed + - update_bfd_interface_pol.previous != update_bfd_interface_pol.current + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.descr == "Ansible BFD Interface Policy" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.adminSt == "disabled" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.detectMult == "5" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.minRxIntvl == "500" + - update_bfd_interface_pol.current.0.bfdIfPol.attributes.minTxIntvl == "270" + + # Added another BFD Interface policy + - name: Add a new BFD Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_2 + state: present + register: add_bfd_interface_pol_2 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_2 is changed + - add_bfd_interface_pol_2.previous == [] + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy_2" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy_2" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.descr == "Ansible BFD Interface Policy" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.adminSt == "enabled" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.detectMult == "3" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.minRxIntvl == "50" + - add_bfd_interface_pol_2.current.0.bfdIfPol.attributes.minTxIntvl == "50" + + - name: Query all BFD Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + state: query + register: query_all_result + + - name: Verify querying all BFD Interface Policies + assert: + that: + - query_all_result is not changed + - query_all_result.current.0.fvTenant.children | length == 2 + - query_all_result.current.0.fvTenant.children[0].bfdIfPol.attributes.name == "ansible_bfd_interface_policy_2" + - query_all_result.current.0.fvTenant.children[1].bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + + - name: Query 'ansible_bfd_interface_policy' BFD Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: query + register: query_result + + - name: Verify querying'ansible_bfd_interface_policy BFD' Multihop Interface Policy + assert: + that: + - query_result is not changed + - query_result.current.0.bfdIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdIfPol-ansible_bfd_interface_policy" + - query_result.current.0.bfdIfPol.attributes.name == "ansible_bfd_interface_policy" + + - name: Remove a BFD Interface policy - check mode + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + check_mode: true + register: cm_remove_bfd_interface_pol + + - name: Remove a BFD Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + register: nm_remove_bfd_interface_pol + + - name: Remove a BFD Interface policy again + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_interface_policy + state: absent + register: remove_bfd_interface_pol_again + + - name: Verify removing BFD Interface Policies + assert: + that: + - nm_remove_bfd_interface_pol is changed + - cm_remove_bfd_interface_pol is changed + - cm_remove_bfd_interface_pol.proposed == {} + - nm_remove_bfd_interface_pol.previous != [] + - remove_bfd_interface_pol_again is not changed + - nm_remove_bfd_interface_pol.current == remove_bfd_interface_pol_again.current == [] + +# Validating out of range parameters. + +# Added BFD Interface policy with out of the range detection_multiplier + - name: Add a new BFD Interface policy - out of the range detection_multiplier + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_3 + detection_multiplier: 256 + state: present + ignore_errors: true + register: add_bfd_interface_pol_3 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_3 is not changed + - add_bfd_interface_pol_3.msg == "The \"detection_multiplier\" must be a value between 1 and 50" + +# Added BFD Interface policy with out of the range min_transmit_interval + - name: Add a new BFD Interface policy - out of the range min_transmit_interval + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_3 + min_transmit_interval: 10 + state: present + ignore_errors: true + register: add_bfd_interface_pol_3 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_3 is not changed + - add_bfd_interface_pol_3.msg == "The \"min_transmit_interval\" must be a value between 50 and 999" + +# Added BFD Interface policy with out of the range min_receive_interval + - name: Add a new BFD Interface policy - out of the range min_receive_interval + cisco.aci.aci_interface_policy_bfd: + <<: *add_bfd_interface_pol + name: ansible_bfd_interface_policy_3 + min_receive_interval: 1000 + state: present + ignore_errors: true + register: add_bfd_interface_pol_3 + + - name: Verify BFD Interface Policy creation + assert: + that: + - add_bfd_interface_pol_3 is not changed + - add_bfd_interface_pol_3.msg == "The \"min_receive_interval\" must be a value between 50 and 999" \ No newline at end of file diff --git a/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases b/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_interface_policy_bfd_multihop/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml b/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml new file mode 100644 index 000000000..8454803ec --- /dev/null +++ b/tests/integration/targets/aci_interface_policy_bfd_multihop/tasks/main.yml @@ -0,0 +1,245 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# 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 APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Execute tasks only for non-cloud sites + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') # This condition will execute only when APIC version >= 5.2 + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + - name: Add a new tenant + aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # CREATE BFD Multihop Interface policy + - name: Add a new BFD Multihop Interface policy - check mode + cisco.aci.aci_interface_policy_bfd_multihop: &add_bfd_multihop_interface_pol + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + description: Ansible BFD Multihop Interface Policy + state: present + check_mode: true + register: cm_add_bfd_multihop_interface_pol + + - name: Add a new BFD Multihop Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + state: present + register: nm_add_bfd_multihop_interface_pol + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - cm_add_bfd_multihop_interface_pol is changed + - nm_add_bfd_multihop_interface_pol is changed + - cm_add_bfd_multihop_interface_pol.previous == nm_add_bfd_multihop_interface_pol.previous == [] + - cm_add_bfd_multihop_interface_pol.proposed.bfdMhIfPol.attributes.dn == nm_add_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy" + - cm_add_bfd_multihop_interface_pol.proposed.bfdMhIfPol.attributes.name == nm_add_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + - cm_add_bfd_multihop_interface_pol.proposed.bfdMhIfPol.attributes.descr == nm_add_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.descr == "Ansible BFD Multihop Interface Policy" + + - name: Add a new BFD Multihop Interface policy again - idempotency + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + state: present + register: add_bfd_multihop_interface_pol_again + + - name: Verify BFD Multihop Interface Policy creation again - idempotency + assert: + that: + - add_bfd_multihop_interface_pol_again is not changed + - add_bfd_multihop_interface_pol_again.previous != [] + - add_bfd_multihop_interface_pol_again.current | length == 1 + - add_bfd_multihop_interface_pol_again.previous | length == 1 + + - name: Modify a BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + admin_state: disabled + detection_multiplier: 5 + min_transmit_interval: 270 + min_receive_interval: 500 + state: present + register: update_bfd_multihop_interface_pol + + - name: Verify modifying BFD Multihop Interface Policy + assert: + that: + - update_bfd_multihop_interface_pol is changed + - update_bfd_multihop_interface_pol.previous != update_bfd_multihop_interface_pol.current + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.descr == "Ansible BFD Multihop Interface Policy" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.adminSt == "disabled" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.detectMult == "5" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.minRxIntvl == "500" + - update_bfd_multihop_interface_pol.current.0.bfdMhIfPol.attributes.minTxIntvl == "270" + + # Added another BFD Multihop Interface policy + - name: Add a new BFD Multihop Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_2 + state: present + register: add_bfd_multihop_interface_pol_2 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_2 is changed + - add_bfd_multihop_interface_pol_2.previous == [] + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy_2" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy_2" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.descr == "Ansible BFD Multihop Interface Policy" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.adminSt == "enabled" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.detectMult == "3" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.minRxIntvl == "250" + - add_bfd_multihop_interface_pol_2.current.0.bfdMhIfPol.attributes.minTxIntvl == "250" + + - name: Query all BFD Multihop Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + state: query + register: query_all_result + + - name: Verify querying all BFD Multihop Interface Policies + assert: + that: + - query_all_result is not changed + - query_all_result.current.0.fvTenant.children | length == 2 + - query_all_result.current.0.fvTenant.children[0].bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy_2" + - query_all_result.current.0.fvTenant.children[1].bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + + - name: Query 'ansible_bfd_multihop_interface_policy' BFD Multihop Interface policies in a specific tenant + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: query + register: query_result + + - name: Verify querying'ansible_bfd_multihop_interface_policy BFD' Multihop Interface Policy + assert: + that: + - query_result is not changed + - query_result.current.0.bfdMhIfPol.attributes.dn == "uni/tn-ansible_tenant/bfdMhIfPol-ansible_bfd_multihop_interface_policy" + - query_result.current.0.bfdMhIfPol.attributes.name == "ansible_bfd_multihop_interface_policy" + + - name: Remove a BFD Multihop Interface policy - check mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + check_mode: true + register: cm_remove_bfd_multihop_interface_pol + + - name: Remove a BFD Multihop Interface policy - normal mode + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + register: nm_remove_bfd_multihop_interface_pol + + - name: Remove a BFD Multihop Interface policy again - idempotency + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + state: absent + register: remove_bfd_multihop_interface_pol_again + + - name: Verify removing BFD Multihop Interface Policies + assert: + that: + - nm_remove_bfd_multihop_interface_pol is changed + - cm_remove_bfd_multihop_interface_pol is changed + - cm_remove_bfd_multihop_interface_pol.proposed == nm_remove_bfd_multihop_interface_pol.proposed == {} + - nm_remove_bfd_multihop_interface_pol.previous != [] + - remove_bfd_multihop_interface_pol_again is not changed + - nm_remove_bfd_multihop_interface_pol.current == remove_bfd_multihop_interface_pol_again.current == [] + +# Validating out of rage parameters. + +# Added BFD Multihop Interface policy with out of the range detection_multiplier + - name: Add a new BFD Multihop Interface policy - out of the range detection_multiplier + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_3 + detection_multiplier: 256 + state: present + ignore_errors: true + register: add_bfd_multihop_interface_pol_3 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_3 is not changed + - add_bfd_multihop_interface_pol_3.msg == "The \"detection_multiplier\" must be a value between 1 and 50" + +# Added BFD Multihop Interface policy with out of the range min_transmit_interval + - name: Add a new BFD Multihop Interface policy - out of the range min_transmit_interval + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_3 + min_transmit_interval: 50 + state: present + ignore_errors: true + register: add_bfd_multihop_interface_pol_3 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_3 is not changed + - add_bfd_multihop_interface_pol_3.msg == "The \"min_transmit_interval\" must be a value between 250 and 999" + +# Added BFD Multihop Interface policy with out of the range min_receive_interval + - name: Add a new BFD Multihop Interface policy - out of the range min_receive_interval + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *add_bfd_multihop_interface_pol + name: ansible_bfd_multihop_interface_policy_3 + min_receive_interval: 1000 + state: present + ignore_errors: true + register: add_bfd_multihop_interface_pol_3 + + - name: Verify BFD Multihop Interface Policy creation + assert: + that: + - add_bfd_multihop_interface_pol_3 is not changed + - add_bfd_multihop_interface_pol_3.msg == "The \"min_receive_interval\" must be a value between 250 and 999" \ No newline at end of file diff --git a/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases b/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_l3out_bfd_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml b/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml new file mode 100644 index 000000000..19c034eb8 --- /dev/null +++ b/tests/integration/targets/aci_l3out_bfd_interface_profile/tasks/main.yml @@ -0,0 +1,226 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# 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 APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + # This condition will execute only when APIC version >= 5.2 and for non-cloud APICs + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') and query_cloud.current == [] + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + # Add a tenant + - name: Add a new tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # Add VRF + - name: Add a new VRF + cisco.aci.aci_vrf: + <<: *aci_info + tenant: ansible_tenant + name: ansible_vrf + description: Ansible VRF + state: present + + # Add L3Out + - name: Add a new L3 Outside + cisco.aci.aci_l3out: + <<: *aci_info + tenant: ansible_tenant + name: ansible_l3out + description: Ansible L3 Outside + domain: ansible_dom + vrf: ansible_vrf + l3protocol: bgp + state: present + + # ADD l3out logical node profile + - name: l3out logical node profile + cisco.aci.aci_l3out_logical_node_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + state: present + + # ADD l3out logical interface profile + - name: l3out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + interface_profile: ansible_interface_profile + state: present + + # CREATE L3Out BFD Interface policy + - name: Add a new L3Out BFD Interface policy + cisco.aci.aci_interface_policy_bfd: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd__interface_policy + description: Ansible BFD Interface Policy + state: present + register: add_bfd_interface_pol + + # Add L3Out BFD Interface Profile + - name: Add a new L3Out BFD Interface Profile - check mode + cisco.aci.aci_l3out_bfd_interface_profile: &present_l3out_bfd_int_profile + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + bfd_interface_policy: ansible_bfd_interface_policy + state: present + check_mode: true + register: cm_add_l3out_bfd_int_prof + + - name: Add a new L3Out BFD Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: present + register: nm_add_l3out_bfd_int_prof + + - name: Verify adding L3Out BFD Interface Profile + assert: + that: + - cm_add_l3out_bfd_int_prof is changed + - nm_add_l3out_bfd_int_prof is changed + - cm_add_l3out_bfd_int_prof.previous == nm_add_l3out_bfd_int_prof.previous == [] + - cm_add_l3out_bfd_int_prof.proposed.bfdIfP.attributes.dn == nm_add_l3out_bfd_int_prof.proposed.bfdIfP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/bfdIfP" + - cm_add_l3out_bfd_int_prof.proposed.bfdIfP.children.0.bfdRsIfPol.attributes.tnBfdIfPolName == cm_add_l3out_bfd_int_prof.proposed.bfdIfP.children.0.bfdRsIfPol.attributes.tnBfdIfPolName == "ansible_bfd_interface_policy" + + - name: Add L3Out BFD Interface Profile again- idempotency + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: present + register: add_l3out_bfd_int_prof_again + + - name: Verify adding L3Out BFD Interface Profile again - idempotency + assert: + that: + - add_l3out_bfd_int_prof_again is not changed + + # Update L3Out BFD Interface Profile + - name: Update L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + authentication_type: sha1 + key: "abc*123" + key_id: 15 + state: present + register: update_l3out_bfd_int_prof + + - name: Verify updating L3Out BFD Interface Profile + assert: + that: + - update_l3out_bfd_int_prof is changed + - update_l3out_bfd_int_prof.sent.bfdIfP.attributes.keyId == "15" + - update_l3out_bfd_int_prof.sent.bfdIfP.attributes.key == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - update_l3out_bfd_int_prof.sent.bfdIfP.attributes.type == "sha1" + + # Remove children from L3Out BFD Interface Profile + - name: Remove children from L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + bfd_interface_policy: "" + register: remove_children_l3out_bfd_int_prof + + - name: Asserts for children removal tasks for the from L3Out BFD Interface Profile + ansible.builtin.assert: + that: + - remove_children_l3out_bfd_int_prof is changed + - remove_children_l3out_bfd_int_prof.sent.bfdIfP.children.0.bfdRsIfPol.attributes.tnBfdIfPolName == "" + + # Query L3Out BFD Interface Profile + - name: Query L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: query + register: query_l3out_bfd_int_prof + + - name: Query all L3Out BFD Interface Profile + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *aci_info + state: query + register: query_all_l3out_bfd_int_prof + + # Validating out of range parameters. + - name: Add out of range key_id + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + key_id: 256 + state: present + ignore_errors: true + register: out_of_range_key_id + + - name: Verify out of range key_id + assert: + that: + - out_of_range_key_id is not changed + - out_of_range_key_id.msg == "The \"key_id\" must be a value between 1 and 255" + + - name: Delete L3Out BFD Interface Profile - check mode + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: absent + check_mode: true + register: cm_remove_l3out_bfd_int_prof + + - name: Delete L3Out BFD Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: absent + register: nm_remove_l3out_bfd_int_prof + + - name: Delete L3Out BFD Interface Profile again - idempotency + cisco.aci.aci_l3out_bfd_interface_profile: + <<: *present_l3out_bfd_int_profile + state: absent + register: remove_l3out_bfd_int_prof_again + + - name: Verify removing L3Out BFD Interface Profile + assert: + that: + - cm_remove_l3out_bfd_int_prof is changed + - nm_remove_l3out_bfd_int_prof is changed + - cm_remove_l3out_bfd_int_prof.proposed == nm_remove_l3out_bfd_int_prof.proposed == {} + - remove_l3out_bfd_int_prof_again is not changed + - nm_remove_l3out_bfd_int_prof.current == remove_l3out_bfd_int_prof_again.current == [] \ No newline at end of file diff --git a/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases b/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml b/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml new file mode 100644 index 000000000..920453708 --- /dev/null +++ b/tests/integration/targets/aci_l3out_bfd_multihop_interface_profile/tasks/main.yml @@ -0,0 +1,233 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Anvitha Jain (@anvjain) + +# 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 APIC host, ACI username and ACI password + fail: + msg: 'Please define the following variables: aci_hostname, aci_username and aci_password.' + when: aci_hostname is not defined or aci_username is not defined or aci_password is not defined + +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: debug + +- name: Query system information + cisco.aci.aci_system: + <<: *aci_info + id: 1 + state: query + register: version + +- name: Verify Cloud and Non-Cloud Sites in use. + include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml + +- name: Execute tasks only for non-cloud sites + # This condition will execute only when APIC version >= 5.2 and for non-cloud APICs + when: version.current.0.topSystem.attributes.version is version('5.2', '>=') and query_cloud.current == [] + block: # block specifies execution of tasks within, based on conditions + + # CLEAN ENVIRONMENT + - name: Remove the ansible_tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + state: absent + + # Add a tenant + - name: Add a new tenant + cisco.aci.aci_tenant: + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + # Add VRF + - name: Add a new VRF + cisco.aci.aci_vrf: + <<: *aci_info + tenant: ansible_tenant + name: ansible_vrf + description: Ansible VRF + state: present + + # Add L3Out + - name: Add a new L3 Outside + cisco.aci.aci_l3out: + <<: *aci_info + tenant: ansible_tenant + name: ansible_l3out + description: Ansible L3 Outside + domain: ansible_dom + vrf: ansible_vrf + l3protocol: bgp + state: present + + # ADD l3out logical node profile + - name: l3out logical node profile + cisco.aci.aci_l3out_logical_node_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + state: present + + # ADD l3out logical interface profile + - name: l3out logical interface profile + cisco.aci.aci_l3out_logical_interface_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + node_profile: ansible_node_profile + interface_profile: ansible_interface_profile + state: present + + # CREATE BFD Multihop Interface policy + - name: Add a new BFD Multihop Interface policy + cisco.aci.aci_interface_policy_bfd_multihop: + <<: *aci_info + tenant: ansible_tenant + name: ansible_bfd_multihop_interface_policy + description: Ansible BFD Multihop Interface Policy + state: present + register: add_bfd_multihop_interface_pol + + # Add BFD Multihop Interface Profile + - name: Add a new BFD Multihop Interface Profile - check mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: &present_bfd_mh_int_profile + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + l3out_logical_node_profile: ansible_node_profile + l3out_logical_interface_profile: ansible_interface_profile + bfd_multihop_interface_policy: ansible_bfd_multihop_interface_policy + state: present + check_mode: true + register: cm_add_bfd_mh_int_prof + + - name: Add a new BFD Multihop Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: present + register: nm_add_bfd_mh_int_prof + + - name: Verify adding BFD Multihop Interface Profile + assert: + that: + - cm_add_bfd_mh_int_prof is changed + - nm_add_bfd_mh_int_prof is changed + - cm_add_bfd_mh_int_prof.previous == nm_add_bfd_mh_int_prof.previous == [] + - cm_add_bfd_mh_int_prof.proposed.bfdMhIfP.attributes.dn == nm_add_bfd_mh_int_prof.proposed.bfdMhIfP.attributes.dn == "uni/tn-ansible_tenant/out-ansible_l3out/lnodep-ansible_node_profile/lifp-ansible_interface_profile/bfdMhIfP" + - cm_add_bfd_mh_int_prof.proposed.bfdMhIfP.children.0.bfdRsMhIfPol.attributes.tnBfdMhIfPolName == nm_add_bfd_mh_int_prof.proposed.bfdMhIfP.children.0.bfdRsMhIfPol.attributes.tnBfdMhIfPolName == "ansible_bfd_multihop_interface_policy" + + # Query BFD Multihop Interface Profile + - name: Query BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: query + register: query_bfd_mh_int_prof + + - name: Add BFD Multihop Interface Profile again- idempotency + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: present + register: add_bfd_mh_int_prof_again + + - name: Verify adding BFD Multihop Interface Profile again - idempotency + assert: + that: + - add_bfd_mh_int_prof_again is not changed + + # Update BFD Multihop Interface Profile + - name: Update BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + authentication_type: sha1 + key: "abc*123" + key_id: 15 + state: present + register: update_bfd_mh_int_prof + + - name: Verify updating BFD Multihop Interface Profile + assert: + that: + - update_bfd_mh_int_prof is changed + - update_bfd_mh_int_prof.sent.bfdMhIfP.attributes.keyId == "15" + - update_bfd_mh_int_prof.sent.bfdMhIfP.attributes.key == "VALUE_SPECIFIED_IN_NO_LOG_PARAMETER" + - update_bfd_mh_int_prof.sent.bfdMhIfP.attributes.type == "sha1" + + # Remove children from L3Out BFD Interface Profile + - name: Remove children from BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + bfd_multihop_interface_policy: "" + register: remove_children_bfd_mh_int_prof + + - name: Asserts for children removal tasks for the from BFD Multihop Interface Profile + ansible.builtin.assert: + that: + - remove_children_bfd_mh_int_prof is changed + - remove_children_bfd_mh_int_prof.sent.bfdMhIfP.children.0.bfdRsMhIfPol.attributes.tnBfdMhIfPolName == "" + + # Query BFD Multihop Interface Profile + - name: Query BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: query + register: query_bfd_mh_int_prof + + - name: Query all BFD Multihop Interface Profile + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *aci_info + state: query + register: query_all_bfd_mh_int_prof + + # Validating out of range parameters. + - name: Add out of range key_id + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + key_id: 256 + state: present + ignore_errors: true + register: out_of_range_key_id + + - name: Verify out of range key_id + assert: + that: + - out_of_range_key_id is not changed + - out_of_range_key_id.msg == "The \"key_id\" must be a value between 1 and 255" + + - name: Delete BFD Multihop Interface Profile - check mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: absent + check_mode: true + register: cm_remove_bfd_mh_int_prof + + - name: Delete BFD Multihop Interface Profile - normal mode + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: absent + register: nm_remove_bfd_mh_int_prof + + - name: Delete BFD Multihop Interface Profile again - idempotency + cisco.aci.aci_l3out_bfd_multihop_interface_profile: + <<: *present_bfd_mh_int_profile + state: absent + register: remove_bfd_mh_int_prof_again + + - name: Verify removing BFD Multihop Interface Profile + assert: + that: + - cm_remove_bfd_mh_int_prof is changed + - nm_remove_bfd_mh_int_prof is changed + - cm_remove_bfd_mh_int_prof.proposed == nm_remove_bfd_mh_int_prof.proposed == {} + - remove_bfd_mh_int_prof_again is not changed + - nm_remove_bfd_mh_int_prof.current == remove_bfd_mh_int_prof_again.current == [] \ No newline at end of file