From 1988036e0365102ade582a10287e5545dab3af34 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 14 Sep 2023 14:49:21 -0400 Subject: [PATCH 01/11] [minor_change] Add route control profile as a new module. --- plugins/modules/aci_route_control_profile.py | 276 +++++++++++++++++++ 1 file changed, 276 insertions(+) create mode 100644 plugins/modules/aci_route_control_profile.py diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py new file mode 100644 index 000000000..7fdeebe24 --- /dev/null +++ b/plugins/modules/aci_route_control_profile.py @@ -0,0 +1,276 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_route_control_profile +short_description: Manage route control profiles (rtcrtl:Profile) +description: +- Manage route auto_continue policies on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + l3out: + description: + - Name of an existing L3Out. + type: str + aliases: [ l3out_name ] + route_control_profile: + description: + - Name of the route control profile being created. + type: str + aliases: [ name, rtctrl_profile_name ] + description: + description: + - The description for the route control profile. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:Profile). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + route_control_profile = dict(type="str", aliases=["name", "rtctrl_profile_name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + auto_continue=dict(type="str", default="no", choices=["no", "yes"]), + policy_type=dict(type="str", default="combinable", choices=["combinable", "global"]), + name_alias=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["route_control_profile", "tenant"]], + ["state", "present", ["route_control_profile", "tenant"]], + ], + ) + + route_control_profile = module.params.get("route_control_profile") + description = module.params.get("description") + auto_continue = module.params.get("auto_continue") + policy_type = module.params.get("policy_type") + state = module.params.get("state") + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + name_alias = module.params.get("name_alias") + + aci = ACIModule(module) + + if l3out is not None: + 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="rtcrtlProfile", + aci_rn="prof-{0}".format(route_control_profile), + module_object=route_control_profile, + target_filter={"name": route_control_profile}, + ), + ) + else: + 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="rtcrtlProfile", + aci_rn="prof-{0}".format(route_control_profile), + module_object=route_control_profile, + target_filter={"name": route_control_profile}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlProfile", + class_config=dict( + name=route_control_profile, + descr=description, + autoContinue=auto_continue, + type=policy_type, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlProfile") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file From 4b8a6c4aa0e5fc0642501ac505c96da12cfcf259 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Wed, 20 Sep 2023 09:27:19 -0400 Subject: [PATCH 02/11] [ignore] Modify conditions to construct URL for aci_route_control_profile. --- plugins/modules/aci_route_control_profile.py | 38 +++++++++----------- 1 file changed, 16 insertions(+), 22 deletions(-) diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py index 7fdeebe24..6a519a7e0 100644 --- a/plugins/modules/aci_route_control_profile.py +++ b/plugins/modules/aci_route_control_profile.py @@ -211,41 +211,35 @@ def main(): aci = ACIModule(module) - if l3out is not None: - aci.construct_url( - root_class=dict( + tenant_url_config = dict( aci_class="fvTenant", aci_rn="tn-{0}".format(tenant), module_object=tenant, target_filter={"name": tenant}, - ), + ) + + route_control_profile_url_config = dict( + aci_class="rtcrtlProfile", + aci_rn="prof-{0}".format(route_control_profile), + module_object=route_control_profile, + target_filter={"name": route_control_profile}, + ) + + if l3out is not None: + aci.construct_url( + root_class=tenant_url_config, subclass_1=dict( aci_class="l3extOut", aci_rn="out-{0}".format(l3out), module_object=l3out, target_filter={"name": l3out}, ), - subclass_2=dict( - aci_class="rtcrtlProfile", - aci_rn="prof-{0}".format(route_control_profile), - module_object=route_control_profile, - target_filter={"name": route_control_profile}, - ), + subclass_2=route_control_profile_url_config, ) else: 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="rtcrtlProfile", - aci_rn="prof-{0}".format(route_control_profile), - module_object=route_control_profile, - target_filter={"name": route_control_profile}, - ), + root_class=tenant_url_config, + subclass_1=route_control_profile_url_config, ) aci.get_existing() From ec5510b62815fec2bef206020e37fe0e92f2d71f Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Wed, 20 Sep 2023 13:10:53 -0400 Subject: [PATCH 03/11] [ignore] add test case for aci_route_control_profile. --- plugins/modules/aci_route_control_profile.py | 3 +- .../targets/aci_route_control_profile/aliases | 2 + .../aci_route_control_profile/tasks/main.yml | 144 ++++++++++++++++++ 3 files changed, 148 insertions(+), 1 deletion(-) create mode 100644 tests/integration/targets/aci_route_control_profile/aliases create mode 100644 tests/integration/targets/aci_route_control_profile/tasks/main.yml diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py index 6a519a7e0..66911b13d 100644 --- a/plugins/modules/aci_route_control_profile.py +++ b/plugins/modules/aci_route_control_profile.py @@ -189,6 +189,7 @@ def main(): auto_continue=dict(type="str", default="no", choices=["no", "yes"]), policy_type=dict(type="str", default="combinable", choices=["combinable", "global"]), name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), ) module = AnsibleModule( @@ -219,7 +220,7 @@ def main(): ) route_control_profile_url_config = dict( - aci_class="rtcrtlProfile", + aci_class="rtctrlProfile", aci_rn="prof-{0}".format(route_control_profile), module_object=route_control_profile, target_filter={"name": route_control_profile}, diff --git a/tests/integration/targets/aci_route_control_profile/aliases b/tests/integration/targets/aci_route_control_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_route_control_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_route_control_profile/tasks/main.yml b/tests/integration/targets/aci_route_control_profile/tasks/main.yml new file mode 100644 index 000000000..a533cd229 --- /dev/null +++ b/tests/integration/targets/aci_route_control_profile/tasks/main.yml @@ -0,0 +1,144 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new L3Out + aci_l3out: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + description: L3Out for ansible_tenant tenant + domain: ansible_dom + vrf: ansible_vrf + state: present + + - name: Add route control profile for l3out (check_mode) + aci_route_control_profile: &aci_route_control_profile_present + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + route_control_profile: ansible_rtctrl_profile_l3out + description: Route Control Profile for ansible_l3out L3Out + auto_continue: no + policy_type: combinable + state: present + check_mode: true + register: cm_add_route_control_profile + + - name: Add route control profile for l3out (normal_mode) + aci_route_control_profile: + <<: *aci_route_control_profile_present + register: nm_add_route_control_profile + + - name: Add route control profile for l3out again - testing idempotency + aci_route_control_profile: + <<: *aci_route_control_profile_present + register: nm_add_route_control_profile_idempotency + + - name: Add route control profile for tenant (normal_mode) + aci_route_control_profile: + <<: *aci_info + tenant: ansible_tenant + route_control_profile: ansible_rtctrl_profile_tenant + description: Route Control Profile for ansible_tenant tenant + state: present + register: nm_add_route_control_profile_2 + + - name: Asserts for route control profiles creation tasks + assert: + that: + - cm_add_route_control_profile is changed + - cm_add_route_control_profile.previous == [] + - cm_add_route_control_profile.current == [] + - nm_add_route_control_profile is changed + - nm_add_route_control_profile_idempotency is not changed + - nm_add_route_control_profile_2 is changed + - nm_add_route_control_profile_2.previous == [] + + - name: Query all route control profiles + aci_route_control_profile: + <<: *aci_info + state: query + register: query_all_route_control_profile + + - name: Query ansible_rtctrl_profile_l3out + aci_route_control_profile: + <<: *aci_route_control_profile_present + state: query + register: query_ansible_rtctrl_profile_l3out + + - name: Asserts query tasks + assert: + that: + - query_all_route_control_profile is not changed + - query_all_route_control_profile.current|length >= 2 + + - name: Remove route control profile for l3out (check_mode) + aci_route_control_profile: &route_control_profile_absent + <<: *aci_route_control_profile_present + state: absent + check_mode: true + register: cm_remove_route_control_profile + + - name: Remove route control profile for l3out (normal_mode) + aci_route_control_profile: + <<: *route_control_profile_absent + register: nm_remove_route_control_profile + + - name: Remove route control profile for l3out - testing idempotency + aci_route_control_profile: + <<: *route_control_profile_absent + register: nm_remove_route_control_profile_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_route_control_profile is changed + - cm_remove_route_control_profile.proposed == {} + - nm_remove_route_control_profile is changed + - nm_remove_route_control_profile.previous != [] + - nm_remove_route_control_profile.method == "DELETE" + - nm_remove_route_control_profile_idempotency is not changed + - nm_remove_route_control_profile_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent From ddcc3c99625b6e0face15aee0f1d8c78465f1e1f Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Fri, 22 Sep 2023 13:35:33 -0400 Subject: [PATCH 04/11] [minor_change] Add aci_context_policy and aci_subject_profile as new modules. --- plugins/modules/aci_context_policy.py | 297 +++++++++++++++++++ plugins/modules/aci_route_control_profile.py | 4 +- plugins/modules/aci_subject_profile.py | 243 +++++++++++++++ 3 files changed, 542 insertions(+), 2 deletions(-) create mode 100644 plugins/modules/aci_context_policy.py create mode 100644 plugins/modules/aci_subject_profile.py diff --git a/plugins/modules/aci_context_policy.py b/plugins/modules/aci_context_policy.py new file mode 100644 index 000000000..78231212c --- /dev/null +++ b/plugins/modules/aci_context_policy.py @@ -0,0 +1,297 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_route_control_profile +short_description: Manage Context Policy (rtcrtl:CtxP) +description: +- Manage Context Policies for the Route Control Profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + l3out: + description: + - Name of an existing L3Out. + type: str + aliases: [ l3out_name ] + route_control_profile: + description: + - Name of an existing route control profile. + type: str + aliases: [ rtctrl_profile_name ] + context_policy: + description: + - Name of the context profile being created. + type: str + aliases: [ name, context_name ] + action: + description: + - The action required when the condition is met. + type: str + choices: [ deny, permit ] + order: + description: + - The order of the policy context. + - The value range from 0 to 9. + type: int + description: + description: + - The description for the context policy. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:CtxP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + route_control_profile=dict(type="str", aliases=["rtctrl_profile_name"]), # Not required for querying all objects + context_policy=dict(type="str", aliases=["name", "context_name"]), # Not required for querying all objects + action = dict(type="str", choices=["deny", "permit"]), + order=dict(type="int"), + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["context_policy", "tenant"]], + ["state", "present", ["context_policy", "tenant"]], + ], + ) + + context_policy = module.params.get("context_policy") + description = module.params.get("description") + action = module.params.get("action") + order = module.params.get("order") + state = module.params.get("state") + tenant = module.params.get("tenant") + l3out = module.params.get("l3out") + route_control_profile = module.params.get("route_control_profile") + name_alias = module.params.get("name_alias") + + aci = ACIModule(module) + + tenant_url_config = dict( + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ) + + route_control_profile_url_config = dict( + aci_class="rtctrlProfile", + aci_rn="prof-{0}".format(route_control_profile), + module_object=route_control_profile, + target_filter={"name": route_control_profile}, + ) + + context_policy_url_config = dict( + aci_class="rtctrlCtxP", + aci_rn="ctx-{0}".format(context_policy), + module_object=context_policy, + target_filter={"name": context_policy}, + ) + + if l3out is not None: + aci.construct_url( + root_class=tenant_url_config, + subclass_1=dict( + aci_class="l3extOut", + aci_rn="out-{0}".format(l3out), + module_object=l3out, + target_filter={"name": l3out}, + ), + subclass_2=route_control_profile_url_config, + subclass_3=context_policy_url_config, + ) + else: + aci.construct_url( + root_class=tenant_url_config, + subclass_1=route_control_profile_url_config, + subclass_2=context_policy_url_config, + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlCtxP", + class_config=dict( + name=route_control_profile, + descr=description, + action=action, + order=order, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlCtxP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py index 66911b13d..ee1b70d47 100644 --- a/plugins/modules/aci_route_control_profile.py +++ b/plugins/modules/aci_route_control_profile.py @@ -13,9 +13,9 @@ DOCUMENTATION = r""" --- module: aci_route_control_profile -short_description: Manage route control profiles (rtcrtl:Profile) +short_description: Manage Route Control Profile (rtcrtl:Profile) description: -- Manage route auto_continue policies on Cisco ACI fabrics. +- Manage Route Control Profiles on Cisco ACI fabrics. options: tenant: description: diff --git a/plugins/modules/aci_subject_profile.py b/plugins/modules/aci_subject_profile.py new file mode 100644 index 000000000..9139f6119 --- /dev/null +++ b/plugins/modules/aci_subject_profile.py @@ -0,0 +1,243 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_profile +short_description: Manage Subject Profile (rtcrtl:SubjP) +description: +- Manage Subject Profiles for the Context Policies on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + subject_profile: + description: + - Name of the subject profile being created. + type: str + aliases: [ name, subject_name ] + description: + description: + - The description for the Subject Profile. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:SubjP). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["name", "subject_name"]), # Not required for querying all objects + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["subject_profile", "tenant"]], + ["state", "present", ["subject_profile", "tenant"]], + ], + ) + + subject_profile = module.params.get("subject_profile") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + name_alias = module.params.get("name_alias") + + 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="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlSubjP", + class_config=dict( + name=subject_profile, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlSubjP") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file From 5a731dbfe79a79f2e790dbf56da9fcca6e927b8f Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Fri, 22 Sep 2023 13:37:40 -0400 Subject: [PATCH 05/11] [minor_change] Add Match Rules for aci_route_control_profile as new Modules. --- .../modules/aci _match_as_path_regex_term.py | 263 +++++++++++++++++ plugins/modules/aci_match_comm_regex_term.py | 271 +++++++++++++++++ plugins/modules/aci_match_community_term.py | 256 ++++++++++++++++ .../modules/aci_match_route_destination.py | 276 ++++++++++++++++++ 4 files changed, 1066 insertions(+) create mode 100644 plugins/modules/aci _match_as_path_regex_term.py create mode 100644 plugins/modules/aci_match_comm_regex_term.py create mode 100644 plugins/modules/aci_match_community_term.py create mode 100644 plugins/modules/aci_match_route_destination.py diff --git a/plugins/modules/aci _match_as_path_regex_term.py b/plugins/modules/aci _match_as_path_regex_term.py new file mode 100644 index 000000000..67fa766a3 --- /dev/null +++ b/plugins/modules/aci _match_as_path_regex_term.py @@ -0,0 +1,263 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_profile +short_description: Manage Match Regular Expression AS-Path Term (rtctrl:MatchAsPathRegexTerm) +description: +- Manage Match Rule Based on Route Regular Expression AS-Path for Subject Profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + subject_profile: + description: + - Name of an exising subject profile. + type: str + aliases: [ subject_name ] + match_as_path_regex_term: + description: + - Name of the Match Regular Expression AS-Path Term. + type: str + aliases: [ name, match_rule_name ] + regex: + description: + - The Regular Expression. + type: str + description: + description: + - The description for the Match Regular Expression AS-Path Term. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:MatchAsPathRegexTerm). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + match_as_path_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), + regex=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["match_as_path_regex_term", "tenant"]], + ["state", "present", ["match_as_path_regex_term", "tenant"]], + ], + ) + + match_as_path_regex_term = module.params.get("match_as_path_regex_term") + description = module.params.get("description") + regex = module.params.get("regex") + state = module.params.get("state") + tenant = module.params.get("tenant") + subject_profile = module.params.get("subject_profile") + name_alias = module.params.get("name_alias") + + 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="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), + subclass_2=dict( + aci_class="rtctrlMatchAsPathRegexTerm", + aci_rn="aspathrxtrm-{0}".format(match_as_path_regex_term), + module_object=match_as_path_regex_term, + target_filter={"name": match_as_path_regex_term}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlMatchAsPathRegexTerm", + class_config=dict( + name=match_as_path_regex_term, + regex=regex, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlMatchAsPathRegexTerm") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/plugins/modules/aci_match_comm_regex_term.py b/plugins/modules/aci_match_comm_regex_term.py new file mode 100644 index 000000000..8295aa5cf --- /dev/null +++ b/plugins/modules/aci_match_comm_regex_term.py @@ -0,0 +1,271 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_profile +short_description: Manage Match Regular Expression Community Term (rtctrl:MatchCommRegexTerm) +description: +- Manage Match Rule Based on Route Regular Expression Community for Subject Profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + subject_profile: + description: + - Name of an exising subject profile. + type: str + aliases: [ subject_name ] + match_community_regex_term: + description: + - Name of the Match Regular Expression Community Term. + type: str + aliases: [ name, match_rule_name ] + community_type: + description: + - The Community Type. + type: str + choices: [ extended, regular ] + regex: + description: + - The Regular Expression. + type: str + description: + description: + - The description for the Match Regular Expression Community Term. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:MatchCommRegexTerm). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + match_community_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), + community_type=dict(type="str", choices=["extended", "regular"]), + regex=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["match_community_regex_term", "tenant"]], + ["state", "present", ["match_community_regex_term", "tenant"]], + ], + ) + + match_community_regex_term = module.params.get("match_community_regex_term") + description = module.params.get("description") + community_type = module.params.get("community_type") + regex = module.params.get("regex") + state = module.params.get("state") + tenant = module.params.get("tenant") + subject_profile = module.params.get("subject_profile") + name_alias = module.params.get("name_alias") + + 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="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), + subclass_2=dict( + aci_class="rtctrlMatchCommRegexTerm", + aci_rn="commrxtrm-{0}".format(match_community_regex_term), + module_object=match_community_regex_term, + target_filter={"name": match_community_regex_term}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlMatchCommRegexTerm", + class_config=dict( + name=match_community_regex_term, + commType=community_type, + regex=regex, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlMatchCommRegexTerm") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/plugins/modules/aci_match_community_term.py b/plugins/modules/aci_match_community_term.py new file mode 100644 index 000000000..dc46ddba1 --- /dev/null +++ b/plugins/modules/aci_match_community_term.py @@ -0,0 +1,256 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_profile +short_description: Manage Match Community Term (rtctrl:MatchCommTerm) +description: +- Manage Match Rule Based on Community for Subject Profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + subject_profile: + description: + - Name of an exising subject profile. + type: str + aliases: [ subject_name ] + match_community_term: + description: + - Name of the Match Community Term. + type: str + aliases: [ name, match_rule_name ] + description: + description: + - The description for the Match Community Term. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:MatchCommTerm). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + match_community_term=dict(type="str", aliases=["name", "match_rule_name"]), + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["match_community_term", "tenant"]], + ["state", "present", ["match_community_term", "tenant"]], + ], + ) + + match_community_term = module.params.get("match_community_term") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + subject_profile = module.params.get("subject_profile") + name_alias = module.params.get("name_alias") + + 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="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), + subclass_2=dict( + aci_class="rtctrlMatchCommTerm", + aci_rn="commrxtrm-{0}".format(match_community_term), + module_object=match_community_term, + target_filter={"name": match_community_term}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlMatchCommTerm", + class_config=dict( + name=match_community_term, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlMatchCommTerm") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/plugins/modules/aci_match_route_destination.py b/plugins/modules/aci_match_route_destination.py new file mode 100644 index 000000000..b72e8c40c --- /dev/null +++ b/plugins/modules/aci_match_route_destination.py @@ -0,0 +1,276 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_profile +short_description: Manage Match action rule based on the Route Destination. (rtctrl:MatchRtDest) +description: +- Match action rule based on the Route Destination for Subject Profiles on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + subject_profile: + description: + - Name of an exising subject profile. + type: str + aliases: [ subject_name ] + ip: + description: + - The IP address of the route destination. + type: str + aggregate: + description: + - Option to enable/disable aggregated route. + type: str + choices: [ yes, no ] + from_prefix_lenght: + description: + - Start of the prefix lenght. + type: str + to_prefix_lenght: + description: + - End of the prefix lenght. + description: + description: + - The description for the Match Action Rule. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) module can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:MatchRtDest). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + ip=dict(type="str", aliases=["name", "match_rule_name"]), + aggregate=dict(type="str", choices=["extended", "regular"]), + from_prefix_lenght=dict(type="str"), + to_prefix_lenght=dict(type="str"), + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["ip", "tenant"]], + ["state", "present", ["ip", "tenant"]], + ], + ) + + ip = module.params.get("ip") + description = module.params.get("description") + aggregate = module.params.get("aggregate") + from_prefix_lenght = module.params.get("from_prefix_lenght") + to_prefix_lenght = module.params.get("to_prefix_lenght") + state = module.params.get("state") + tenant = module.params.get("tenant") + subject_profile = module.params.get("subject_profile") + name_alias = module.params.get("name_alias") + + 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="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), + subclass_2=dict( + aci_class="rtctrlMatchRtDest", + aci_rn="dest-[{0}]".format(ip), + module_object=ip, + target_filter={"ip": ip}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlMatchRtDest", + class_config=dict( + ip=ip, + aggregate=aggregate, + fromPfxLen=from_prefix_lenght, + toPfxLen=to_prefix_lenght, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlMatchRtDest") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file From da80422a09eb0c94b9781e8d3a43ff01354bbad6 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 28 Sep 2023 09:34:45 -0400 Subject: [PATCH 06/11] [minor_changes] Add aci_match_community_factor and all test cases for route control profile and Match rules related modules. --- plugins/modules/aci_context_policy.py | 26 +- ...erm.py => aci_match_as_path_regex_term.py} | 5 +- plugins/modules/aci_match_community_factor.py | 277 ++++++++++++++++++ ...m.py => aci_match_community_regex_term.py} | 20 +- plugins/modules/aci_match_community_term.py | 11 +- .../modules/aci_match_route_destination.py | 19 +- plugins/modules/aci_subject_profile.py | 1 - .../targets/aci_context_policy/aliases | 2 + .../targets/aci_context_policy/tasks/main.yml | 196 +++++++++++++ .../aci_match_as_path_regex_term/aliases | 2 + .../tasks/main.yml | 150 ++++++++++ .../aci_match_community_factor/aliases | 2 + .../aci_match_community_factor/tasks/main.yml | 157 ++++++++++ .../aci_match_community_regex_term/aliases | 2 + .../tasks/main.yml | 152 ++++++++++ .../targets/aci_match_community_term/aliases | 2 + .../aci_match_community_term/tasks/main.yml | 146 +++++++++ .../aci_match_route_destination/aliases | 2 + .../tasks/main.yml | 158 ++++++++++ .../targets/aci_subject_profile/aliases | 2 + .../aci_subject_profile/tasks/main.yml | 135 +++++++++ 21 files changed, 1435 insertions(+), 32 deletions(-) rename plugins/modules/{aci _match_as_path_regex_term.py => aci_match_as_path_regex_term.py} (97%) create mode 100644 plugins/modules/aci_match_community_factor.py rename plugins/modules/{aci_match_comm_regex_term.py => aci_match_community_regex_term.py} (89%) create mode 100644 tests/integration/targets/aci_context_policy/aliases create mode 100644 tests/integration/targets/aci_context_policy/tasks/main.yml create mode 100644 tests/integration/targets/aci_match_as_path_regex_term/aliases create mode 100644 tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml create mode 100644 tests/integration/targets/aci_match_community_factor/aliases create mode 100644 tests/integration/targets/aci_match_community_factor/tasks/main.yml create mode 100644 tests/integration/targets/aci_match_community_regex_term/aliases create mode 100644 tests/integration/targets/aci_match_community_regex_term/tasks/main.yml create mode 100644 tests/integration/targets/aci_match_community_term/aliases create mode 100644 tests/integration/targets/aci_match_community_term/tasks/main.yml create mode 100644 tests/integration/targets/aci_match_route_destination/aliases create mode 100644 tests/integration/targets/aci_match_route_destination/tasks/main.yml create mode 100644 tests/integration/targets/aci_subject_profile/aliases create mode 100644 tests/integration/targets/aci_subject_profile/tasks/main.yml diff --git a/plugins/modules/aci_context_policy.py b/plugins/modules/aci_context_policy.py index 78231212c..aa35081b8 100644 --- a/plugins/modules/aci_context_policy.py +++ b/plugins/modules/aci_context_policy.py @@ -69,8 +69,8 @@ - cisco.aci.owner notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) module can be used for this. +- The C(tenant) and the C(route_control_profile) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_route_control_profile) modules can be used for this. seealso: - module: cisco.aci.aci_tenant - name: APIC Management Information Model reference @@ -201,6 +201,8 @@ def main(): l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects route_control_profile=dict(type="str", aliases=["rtctrl_profile_name"]), # Not required for querying all objects context_policy=dict(type="str", aliases=["name", "context_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), + action_rule=dict(type="str", aliases=["action_rule_name"]), action = dict(type="str", choices=["deny", "permit"]), order=dict(type="int"), description=dict(type="str", aliases=["descr"]), @@ -225,10 +227,14 @@ def main(): tenant = module.params.get("tenant") l3out = module.params.get("l3out") route_control_profile = module.params.get("route_control_profile") + subject_profile = module.params.get("subject_profile") + action_rule = module.params.get("action_rule") name_alias = module.params.get("name_alias") aci = ACIModule(module) + child_classes = ["rtctrlRsCtxPToSubjP", "rtctrlScope"] + tenant_url_config = dict( aci_class="fvTenant", aci_rn="tn-{0}".format(tenant), @@ -261,26 +267,40 @@ def main(): ), subclass_2=route_control_profile_url_config, subclass_3=context_policy_url_config, + child_classes=child_classes, ) else: aci.construct_url( root_class=tenant_url_config, subclass_1=route_control_profile_url_config, subclass_2=context_policy_url_config, + child_classes=child_classes, ) aci.get_existing() if state == "present": + child_configs = [] + if subject_profile is not None: + child_configs.append({"rtctrlRsCtxPToSubjP": {"attributes": {"tnRtctrlSubjPName": subject_profile}}}) + if action_rule is not None: + child_configs.append( + {"rtctrlScope": {"attributes": {"descr": ""}, + "children": [{"rtctrlRsScopeToAttrP": {"attributes": {"tnRtctrlAttrPName": action_rule}}}], + } + } + ) + aci.payload( aci_class="rtctrlCtxP", class_config=dict( - name=route_control_profile, + name=context_policy, descr=description, action=action, order=order, nameAlias=name_alias, ), + child_configs=child_configs, ) aci.get_diff(aci_class="rtctrlCtxP") diff --git a/plugins/modules/aci _match_as_path_regex_term.py b/plugins/modules/aci_match_as_path_regex_term.py similarity index 97% rename from plugins/modules/aci _match_as_path_regex_term.py rename to plugins/modules/aci_match_as_path_regex_term.py index 67fa766a3..05ce7b25a 100644 --- a/plugins/modules/aci _match_as_path_regex_term.py +++ b/plugins/modules/aci_match_as_path_regex_term.py @@ -58,8 +58,8 @@ - cisco.aci.owner notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) module can be used for this. +- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. seealso: - module: cisco.aci.aci_tenant - name: APIC Management Information Model reference @@ -187,7 +187,6 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects match_as_path_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), regex=dict(type="str"), diff --git a/plugins/modules/aci_match_community_factor.py b/plugins/modules/aci_match_community_factor.py new file mode 100644 index 000000000..c8da456df --- /dev/null +++ b/plugins/modules/aci_match_community_factor.py @@ -0,0 +1,277 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# 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": "certified"} + +DOCUMENTATION = r""" +--- +module: aci_subject_profile +short_description: Manage Match Community Factor (rtctrl:MatchCommFactor) +description: +- Manage Match Community Factors for Match Rules Based on Community on Cisco ACI fabrics. +options: + tenant: + description: + - The name of an existing tenant. + type: str + aliases: [ tenant_name ] + subject_profile: + description: + - Name of an exising subject profile. + type: str + aliases: [ subject_name ] + match_community_term: + description: + - Name of an existing match community term. + type: str + aliases: [ match_rule_name ] + community: + description: + - The match community value. + type: str + scope: + description: + - The item scope. + - if the scope is transitive, this community may be passed between ASs. + - if the scope is Non transitive, this community should be carried only within the local AS. + type: str + choices: [ transitive, non-transitive ] + description: + description: + - The description for the Match Community Term. + type: str + aliases: [ descr ] + 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 + name_alias: + description: + - The alias for the current object. This relates to the nameAlias field in ACI. + type: str +extends_documentation_fragment: +- cisco.aci.aci +- cisco.aci.annotation +- cisco.aci.owner + +notes: +- The C(tenant), the C(subject_profile) and the C(match_community_term) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), the M(cisco.aci.subject_profile) and M(cisco.aci.match_community_term) modules can be used for this. +seealso: +- module: cisco.aci.aci_tenant +- name: APIC Management Information Model reference + description: More information about the internal APIC class B(rtctrl:MatchCommFactor). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Gaspard Micol (@gmicol) +""" + +EXAMPLES = r""" +""" + +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": "", + "ownerauto_continue": "" + } + } + } + ] +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": "", + "ownerauto_continue": "" + } + } + } + ] +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, aci_owner_spec + + +def main(): + argument_spec = aci_argument_spec() + argument_spec.update(aci_annotation_spec()) + argument_spec.update(aci_owner_spec()) + argument_spec.update( + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + match_community_term=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + community=dict(type="str"), + scope=dict(type="str", choices=["transitive", "non-transitive"]), + description=dict(type="str", aliases=["descr"]), + name_alias=dict(type="str"), + state=dict(type="str", default="present", choices=["present", "absent", "query"]), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["community", "tenant", "subject_profile", "match_community_term"]], + ["state", "present", ["community", "tenant", "subject_profile", "match_community_term"]], + ], + ) + + community = module.params.get("community") + scope = module.params.get("scope") + description = module.params.get("description") + state = module.params.get("state") + tenant = module.params.get("tenant") + subject_profile = module.params.get("subject_profile") + match_community_term = module.params.get("match_community_term") + name_alias = module.params.get("name_alias") + + 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="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), + subclass_2=dict( + aci_class="rtctrlMatchCommTerm", + aci_rn="commtrm-{0}".format(match_community_term), + module_object=match_community_term, + target_filter={"name": match_community_term}, + ), + subclass_3=dict( + aci_class="rtctrlMatchCommFactor", + aci_rn="commfct-{0}".format(community), + module_object=community, + target_filter={"community": community}, + ), + ) + + aci.get_existing() + + if state == "present": + aci.payload( + aci_class="rtctrlMatchCommFactor", + class_config=dict( + community=community, + scope=scope, + descr=description, + nameAlias=name_alias, + ), + ) + + aci.get_diff(aci_class="rtctrlMatchCommFactor") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() \ No newline at end of file diff --git a/plugins/modules/aci_match_comm_regex_term.py b/plugins/modules/aci_match_community_regex_term.py similarity index 89% rename from plugins/modules/aci_match_comm_regex_term.py rename to plugins/modules/aci_match_community_regex_term.py index 8295aa5cf..34bc52094 100644 --- a/plugins/modules/aci_match_comm_regex_term.py +++ b/plugins/modules/aci_match_community_regex_term.py @@ -63,8 +63,9 @@ - cisco.aci.owner notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) module can be used for this. +- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. +- Only two match community regex terms can exist at the same two, one of each C(community_type). seealso: - module: cisco.aci.aci_tenant - name: APIC Management Information Model reference @@ -191,11 +192,10 @@ def main(): argument_spec.update(aci_annotation_spec()) argument_spec.update(aci_owner_spec()) argument_spec.update( - tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects match_community_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), - community_type=dict(type="str", choices=["extended", "regular"]), + community_type=dict(type="str", default="regular", choices=["extended", "regular"]), regex=dict(type="str"), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), @@ -206,8 +206,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["match_community_regex_term", "tenant"]], - ["state", "present", ["match_community_regex_term", "tenant"]], + ["state", "absent", ["community_type", "tenant", "subject_profile"]], + ["state", "present", ["community_type", "tenant", "subject_profile"]], ], ) @@ -237,9 +237,9 @@ def main(): ), subclass_2=dict( aci_class="rtctrlMatchCommRegexTerm", - aci_rn="commrxtrm-{0}".format(match_community_regex_term), - module_object=match_community_regex_term, - target_filter={"name": match_community_regex_term}, + aci_rn="commrxtrm-{0}".format(community_type), + module_object=community_type, + target_filter={"commType": community_type}, ), ) diff --git a/plugins/modules/aci_match_community_term.py b/plugins/modules/aci_match_community_term.py index dc46ddba1..83fc50837 100644 --- a/plugins/modules/aci_match_community_term.py +++ b/plugins/modules/aci_match_community_term.py @@ -54,8 +54,8 @@ - cisco.aci.owner notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) module can be used for this. +- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. seealso: - module: cisco.aci.aci_tenant - name: APIC Management Information Model reference @@ -183,7 +183,6 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects match_community_term=dict(type="str", aliases=["name", "match_rule_name"]), description=dict(type="str", aliases=["descr"]), @@ -195,8 +194,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["match_community_term", "tenant"]], - ["state", "present", ["match_community_term", "tenant"]], + ["state", "absent", ["match_community_term", "tenant", "subject_profile"]], + ["state", "present", ["match_community_term", "tenant", "subject_profile"]], ], ) @@ -224,7 +223,7 @@ def main(): ), subclass_2=dict( aci_class="rtctrlMatchCommTerm", - aci_rn="commrxtrm-{0}".format(match_community_term), + aci_rn="commtrm-{0}".format(match_community_term), module_object=match_community_term, target_filter={"name": match_community_term}, ), diff --git a/plugins/modules/aci_match_route_destination.py b/plugins/modules/aci_match_route_destination.py index b72e8c40c..2c3faf7d4 100644 --- a/plugins/modules/aci_match_route_destination.py +++ b/plugins/modules/aci_match_route_destination.py @@ -39,10 +39,12 @@ from_prefix_lenght: description: - Start of the prefix lenght. + - It corresponds to the less equal Mask if the route is aggregated. type: str to_prefix_lenght: description: - End of the prefix lenght. + - It corresponds to greater equal Mask if the route is aggregated. description: description: - The description for the Match Action Rule. @@ -65,8 +67,8 @@ - cisco.aci.owner notes: -- The C(tenant) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) module can be used for this. +- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. seealso: - module: cisco.aci.aci_tenant - name: APIC Management Information Model reference @@ -194,12 +196,11 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects - ip=dict(type="str", aliases=["name", "match_rule_name"]), - aggregate=dict(type="str", choices=["extended", "regular"]), - from_prefix_lenght=dict(type="str"), - to_prefix_lenght=dict(type="str"), + ip=dict(type="str"), + aggregate=dict(type="str", choices=["no", "yes"]), + from_prefix_lenght=dict(type="int"), + to_prefix_lenght=dict(type="int"), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), state=dict(type="str", default="present", choices=["present", "absent", "query"]), @@ -209,8 +210,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["ip", "tenant"]], - ["state", "present", ["ip", "tenant"]], + ["state", "absent", ["ip", "tenant", "subject_profile"]], + ["state", "present", ["ip", "tenant", "subject_profile"]], ], ) diff --git a/plugins/modules/aci_subject_profile.py b/plugins/modules/aci_subject_profile.py index 9139f6119..4ee7f9d7f 100644 --- a/plugins/modules/aci_subject_profile.py +++ b/plugins/modules/aci_subject_profile.py @@ -178,7 +178,6 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects subject_profile=dict(type="str", aliases=["name", "subject_name"]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), diff --git a/tests/integration/targets/aci_context_policy/aliases b/tests/integration/targets/aci_context_policy/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_context_policy/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_context_policy/tasks/main.yml b/tests/integration/targets/aci_context_policy/tasks/main.yml new file mode 100644 index 000000000..fb06a562b --- /dev/null +++ b/tests/integration/targets/aci_context_policy/tasks/main.yml @@ -0,0 +1,196 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new action rule profile + aci_tenant_action_rule_profile: &aci_action_rule_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + description: Ansible action rule profile for ansible_tenant tenant + state: present + + - name: Add a new L3Out + aci_l3out: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + description: Ansible l3Out for ansible_tenant tenant + domain: ansible_dom + vrf: ansible_vrf + state: present + + - name: Add route control profile for l3out + aci_route_control_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + route_control_profile: ansible_rtctrl_profile_l3out + description: Ansible Route Control Profile for ansible_l3out l3Out + state: present + + - name: Add subject profile + aci_subject_profile: &aci_subject_profile_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: Ansible Subject Profile for ansible_tenant tenant + state: present + + - name: Add context policy for l3out (check_mode) + aci_context_policy: &aci_context_policy_present + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + route_control_profile: ansible_rtctrl_profile_l3out + context_policy: ansible_context_policy_l3out + description: Ansible Context Policy for ansible_rtctrl_profile_l3out route control profile + subject_profile: ansible_subject_profile + action_rule: ansible_action_rule + action: deny + order: 5 + state: present + check_mode: true + register: cm_add_context_policy_l3out + + - name: Add context policy again (normal_mode) + aci_context_policy: + <<: *aci_context_policy_present + register: nm_add_context_policy_l3out + + - name: Add context policy again - testing idempotency + aci_context_policy: + <<: *aci_context_policy_present + register: nm_add_context_policy_l3out_idempotency + + - name: Add route control profile for tenant + aci_route_control_profile: + <<: *aci_info + tenant: ansible_tenant + route_control_profile: ansible_rtctrl_profile_tenant + description: Route Control Profile for ansible_tenant tenant + state: present + + - name: Add context policy for tenant + aci_context_policy: + <<: *aci_info + tenant: ansible_tenant + route_control_profile: ansible_rtctrl_profile_tenant + context_policy: ansible_context_policy_tenant + description: Ansible Context Policy for ansible_rtctrl_profile_tenant route control profile + state: present + register: nm_add_context_policy_tenant + + - name: Asserts for route control profiles creation tasks + assert: + that: + - cm_add_context_policy_l3out is changed + - cm_add_context_policy_l3out.previous == [] + - cm_add_context_policy_l3out.current == [] + - nm_add_context_policy_l3out is changed + - nm_add_context_policy_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_context_policy_l3out" + - nm_add_context_policy_l3out.current.0.rtctrlCtxP.attributes.action == "deny" + - nm_add_context_policy_l3out.current.0.rtctrlCtxP.attributes.order == "5" + - nm_add_context_policy_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tnRtctrlAttrPName == "ansible_action_rule" + - nm_add_context_policy_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tnRtctrlSubjPName == "ansible_subject_profile" + - nm_add_context_policy_l3out_idempotency is not changed + - nm_add_context_policy_tenant is changed + - nm_add_context_policy_tenant.previous == [] + - nm_add_context_policy_tenant.current.0.rtctrlCtxP.attributes.name == "ansible_context_policy_tenant" + - nm_add_context_policy_tenant.current.0.rtctrlCtxP.attributes.action == "permit" + - nm_add_context_policy_tenant.current.0.rtctrlCtxP.attributes.order == "0" + + - name: Query all context policy + aci_context_policy: + <<: *aci_info + state: query + register: query_all_context_policy + + - name: Query ansible_context_policy_l3out context policy + aci_context_policy: + <<: *aci_info + context_policy: ansible_context_policy_l3out + state: query + register: query_context_policy_l3out + + - name: Asserts query tasks + assert: + that: + - query_all_context_policy is not changed + - query_all_context_policy.current|length >= 2 + - query_context_policy_l3out is not changed + - query_context_policy_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_context_policy_l3out" + - query_context_policy_l3out.current.0.rtctrlCtxP.attributes.action == "deny" + - query_context_policy_l3out.current.0.rtctrlCtxP.attributes.order == "5" + - query_context_policy_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tDn == "uni/tn-ansible_tenant/attr-ansible_action_rule" + - query_context_policy_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tDn == "uni/tn-ansible_tenant/subj-ansible_subject_profile" + + - name: Remove context policy for l3out (check_mode) + aci_context_policy: &aci_context_policy_absent + <<: *aci_context_policy_present + state: absent + check_mode: true + register: cm_remove_context_policy + + - name: Remove context policy for l3out (normal_mode) + aci_context_policy: + <<: *aci_context_policy_absent + register: nm_remove_remove_context_policy + + - name: Remove route control profile for l3out - testing idempotency + aci_context_policy: + <<: *aci_context_policy_absent + register: nm_remove_context_policy_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_context_policy is changed + - cm_remove_context_policy.proposed == {} + - nm_remove_remove_context_policy is changed + - nm_remove_remove_context_policy.previous != [] + - nm_remove_remove_context_policy.method == "DELETE" + - nm_remove_context_policy_idempotency is not changed + - nm_remove_context_policy_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/tests/integration/targets/aci_match_as_path_regex_term/aliases b/tests/integration/targets/aci_match_as_path_regex_term/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_match_as_path_regex_term/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml new file mode 100644 index 000000000..466fcd405 --- /dev/null +++ b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml @@ -0,0 +1,150 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a subject profile + aci_subject_profile: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: subject profile for ansible_tenant tenant + state: present + register: cm_add_subject_profile + + - name: Add a match regex AS-Path term (check_mode) + aci_match_as_path_regex_term: &aci_match_as_path_regex_term_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_as_path_regex_term: ansible_match_as_path_regex_term_1 + description: match regex AS-Path term 1 for ansible_subject_profile subject profile + regex: .* + state: present + check_mode: true + register: cm_add_match_as_path_regex_term + + - name: Add a match regex AS-Path term (normal_mode) + aci_match_as_path_regex_term: + <<: *aci_match_as_path_regex_term_present + register: nm_add_match_as_path_regex_term + + - name: Add the first match regex AS-Path term again - testing idempotency + aci_match_as_path_regex_term: + <<: *aci_match_as_path_regex_term_present + register: nm_add_match_as_path_regex_term_idempotency + + - name: Add a second match regex AS-Path term (normal_mode) + aci_match_as_path_regex_term: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_as_path_regex_term: ansible_match_as_path_regex_term_2 + description: match regex AS-Path term 2 for ansible_subject_profile subject profile + state: present + register: nm_add_match_as_path_regex_term_2 + + - name: Asserts for match regex AS-Path terms creation tasks + assert: + that: + - cm_add_match_as_path_regex_term is changed + - cm_add_match_as_path_regex_term.previous == [] + - cm_add_match_as_path_regex_term.current == [] + - nm_add_match_as_path_regex_term is changed + - nm_add_match_as_path_regex_term.current.0.rtctrlMatchAsPathRegexTerm.attributes.name == "ansible_match_as_path_regex_term_1" + - nm_add_match_as_path_regex_term.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == ".*" + - nm_add_match_as_path_regex_term_idempotency is not changed + - nm_add_match_as_path_regex_term_2 is changed + - nm_add_match_as_path_regex_term_2.previous == [] + - nm_add_match_as_path_regex_term_2.current.0.rtctrlMatchAsPathRegexTerm.attributes.name == "ansible_match_as_path_regex_term_2" + - nm_add_match_as_path_regex_term_2.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == "" + + - name: Query all match regex AS-Path terms + aci_match_as_path_regex_term: + <<: *aci_info + state: query + register: query_all_match_as_path_regex_term + + - name: Query ansible_match_as_path_regex_term_1 + aci_match_as_path_regex_term: + <<: *aci_match_as_path_regex_term_present + state: query + register: query_ansible_match_as_path_regex_term_1 + + - name: Asserts query tasks + assert: + that: + - query_all_match_as_path_regex_term is not changed + - query_all_match_as_path_regex_term.current|length >= 2 + - query_ansible_match_as_path_regex_term_1 is not changed + - query_ansible_match_as_path_regex_term_1.current.0.rtctrlMatchAsPathRegexTerm.attributes.name == "ansible_match_as_path_regex_term_1" + - query_ansible_match_as_path_regex_term_1.current.0.rtctrlMatchAsPathRegexTerm.attributes.regex == ".*" + + - name: Remove match regex AS-Path term for l3out (check_mode) + aci_match_as_path_regex_term: &match_as_path_regex_term_absent + <<: *aci_match_as_path_regex_term_present + state: absent + check_mode: true + register: cm_remove_match_as_path_regex_term + + - name: Remove match regex AS-Path term for l3out (normal_mode) + aci_match_as_path_regex_term: + <<: *match_as_path_regex_term_absent + register: nm_remove_match_as_path_regex_term + + - name: Remove match regex AS-Path term for l3out - testing idempotency + aci_match_as_path_regex_term: + <<: *match_as_path_regex_term_absent + register: nm_remove_match_as_path_regex_term_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_match_as_path_regex_term is changed + - cm_remove_match_as_path_regex_term.proposed == {} + - nm_remove_match_as_path_regex_term is changed + - nm_remove_match_as_path_regex_term.previous != [] + - nm_remove_match_as_path_regex_term.method == "DELETE" + - nm_remove_match_as_path_regex_term_idempotency is not changed + - nm_remove_match_as_path_regex_term_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/tests/integration/targets/aci_match_community_factor/aliases b/tests/integration/targets/aci_match_community_factor/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_match_community_factor/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_match_community_factor/tasks/main.yml b/tests/integration/targets/aci_match_community_factor/tasks/main.yml new file mode 100644 index 000000000..28f2c68aa --- /dev/null +++ b/tests/integration/targets/aci_match_community_factor/tasks/main.yml @@ -0,0 +1,157 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a subject profile + aci_subject_profile: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: subject profile for ansible_tenant tenant + state: present + + - name: Add a match community term + aci_match_community_term: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_community_term: ansible_match_community_term + description: match community term for ansible_subject_profile subject profile + state: present + + - name: Add a match community factor (check_mode) + aci_match_community_factor: &aci_match_community_factor_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_community_term: ansible_match_community_term + community: regular:as2-nn2:4:15 + scope: non-transitive + description: match community factor 1 for ansible_match_community_term + state: present + check_mode: true + register: cm_add_match_community_factor + + - name: Add a match community factor (normal_mode) + aci_match_community_factor: + <<: *aci_match_community_factor_present + register: nm_add_match_community_factor + + - name: Add the first match community factor again - testing idempotency + aci_match_community_factor: + <<: *aci_match_community_factor_present + register: nm_add_match_community_factor_idempotency + + - name: Add a second match community factor (normal_mode) + aci_match_community_factor: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_community_term: ansible_match_community_term + community: regular:as2-nn2:4:16 + description: match community factor 2 for ansible_match_community_term + state: present + register: nm_add_match_community_factor_2 + + - name: Asserts for match community factors creation tasks + assert: + that: + - cm_add_match_community_factor is changed + - cm_add_match_community_factor.previous == [] + - cm_add_match_community_factor.current == [] + - nm_add_match_community_factor is changed + - nm_add_match_community_factor.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:15" + - nm_add_match_community_factor_idempotency is not changed + - nm_add_match_community_factor_2 is changed + - nm_add_match_community_factor_2.previous == [] + - nm_add_match_community_factor_2.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:16" + + - name: Query all match community factors + aci_match_community_factor: + <<: *aci_info + state: query + register: query_all_match_community_factor + + - name: Query a specific match community factor + aci_match_community_factor: + <<: *aci_match_community_factor_present + state: query + register: query_ansible_match_community_factor_1 + + - name: Asserts query tasks + assert: + that: + - query_all_match_community_factor is not changed + - query_all_match_community_factor.current|length >= 2 + - query_ansible_match_community_factor_1 is not changed + - query_ansible_match_community_factor_1.current.0.rtctrlMatchCommFactor.attributes.community == "regular:as2-nn2:4:15" + + - name: Remove match community factor (check_mode) + aci_match_community_factor: &match_community_term_absent + <<: *aci_match_community_factor_present + state: absent + check_mode: true + register: cm_remove_match_community_factor + + - name: Remove match community factor (normal_mode) + aci_match_community_factor: + <<: *match_community_term_absent + register: nm_remove_match_community_factor + + - name: Remove match community factor - testing idempotency + aci_match_community_factor: + <<: *match_community_term_absent + register: nm_remove_match_community_factor_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_match_community_factor is changed + - cm_remove_match_community_factor.proposed == {} + - nm_remove_match_community_factor is changed + - nm_remove_match_community_factor.previous != [] + - nm_remove_match_community_factor.method == "DELETE" + - nm_remove_match_community_factor_idempotency is not changed + - nm_remove_match_community_factor_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/tests/integration/targets/aci_match_community_regex_term/aliases b/tests/integration/targets/aci_match_community_regex_term/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_match_community_regex_term/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml new file mode 100644 index 000000000..9e9bf654f --- /dev/null +++ b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml @@ -0,0 +1,152 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a subject profile + aci_subject_profile: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: subject profile for ansible_tenant tenant + state: present + register: cm_add_subject_profile + + - name: Add a match community regex term (check_mode) + aci_match_community_regex_term: &aci_match_community_regex_term_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + name: ansible_community_regex_extended + description: match extended community regex term for ansible_subject_profile subject profile + community_type: extended + regex: .* + state: present + check_mode: true + register: cm_add_match_community_regex_term + + - name: Add a match community regex term (normal_mode) + aci_match_community_regex_term: + <<: *aci_match_community_regex_term_present + register: nm_add_match_community_regex_term + + - name: Add the first match community regex term again - testing idempotency + aci_match_community_regex_term: + <<: *aci_match_community_regex_term_present + register: nm_add_match_community_regex_term_idempotency + + - name: Add a second match community regex term (normal_mode) + aci_match_community_regex_term: &aci_match_community_regex_term_2_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: match regular community regex term for ansible_subject_profile subject profile + state: present + register: nm_add_match_community_regex_term_2 + + - name: Asserts for match community regex terms creation tasks + assert: + that: + - cm_add_match_community_regex_term is changed + - cm_add_match_community_regex_term.previous == [] + - cm_add_match_community_regex_term.current == [] + - nm_add_match_community_regex_term is changed + - nm_add_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.regex == ".*" + - nm_add_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.name == "ansible_community_regex_extended" + - nm_add_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "extended" + - nm_add_match_community_regex_term_idempotency is not changed + - nm_add_match_community_regex_term_2 is changed + - nm_add_match_community_regex_term_2.previous == [] + - nm_add_match_community_regex_term_2.current.0.rtctrlMatchCommRegexTerm.attributes.regex == "" + - nm_add_match_community_regex_term_2.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "regular" + + - name: Query all match community regex terms + aci_match_community_regex_term: + <<: *aci_info + state: query + community_type: extended + register: query_all_match_community_regex_term + + - name: Query ansible_match_community_regex_term_regular + aci_match_community_regex_term: + <<: *aci_match_community_regex_term_2_present + state: query + register: query_ansible_match_community_regex_term_regular + + - name: Asserts query tasks + assert: + that: + - query_all_match_community_regex_term is not changed + - query_all_match_community_regex_term.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "extended" + - query_ansible_match_community_regex_term_regular is not changed + - query_ansible_match_community_regex_term_regular.current.0.rtctrlMatchCommRegexTerm.attributes.regex == "" + - query_ansible_match_community_regex_term_regular.current.0.rtctrlMatchCommRegexTerm.attributes.commType == "regular" + + - name: Remove match community regex term (check_mode) + aci_match_community_regex_term: &match_community_regex_term_absent + <<: *aci_match_community_regex_term_present + state: absent + check_mode: true + register: cm_remove_match_community_regex_term + + - name: Remove match community regex term (normal_mode) + aci_match_community_regex_term: + <<: *match_community_regex_term_absent + register: nm_remove_match_community_regex_term + + - name: Remove match community regex term - testing idempotency + aci_match_community_regex_term: + <<: *match_community_regex_term_absent + register: nm_remove_match_community_regex_term_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_match_community_regex_term is changed + - cm_remove_match_community_regex_term.proposed == {} + - nm_remove_match_community_regex_term is changed + - nm_remove_match_community_regex_term.previous != [] + - nm_remove_match_community_regex_term.method == "DELETE" + - nm_remove_match_community_regex_term_idempotency is not changed + - nm_remove_match_community_regex_term_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent \ No newline at end of file diff --git a/tests/integration/targets/aci_match_community_term/aliases b/tests/integration/targets/aci_match_community_term/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_match_community_term/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_match_community_term/tasks/main.yml b/tests/integration/targets/aci_match_community_term/tasks/main.yml new file mode 100644 index 000000000..7e619206e --- /dev/null +++ b/tests/integration/targets/aci_match_community_term/tasks/main.yml @@ -0,0 +1,146 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a subject profile + aci_subject_profile: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: subject profile for ansible_tenant tenant + state: present + register: cm_add_subject_profile + + - name: Add a match community term (check_mode) + aci_match_community_term: &aci_match_community_term_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_community_term: ansible_match_community_term_1 + description: match community term 1 for ansible_subject_profile subject profile + state: present + check_mode: true + register: cm_add_match_community_term + + - name: Add a match community term (normal_mode) + aci_match_community_term: + <<: *aci_match_community_term_present + register: nm_add_match_community_term + + - name: Add the first match community term again - testing idempotency + aci_match_community_term: + <<: *aci_match_community_term_present + register: nm_add_match_community_term_idempotency + + - name: Add a second match community term (normal_mode) + aci_match_community_term: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + match_community_term: ansible_match_community_term_2 + description: match community term 2 for ansible_subject_profile subject profile + state: present + register: nm_add_match_community_term_2 + + - name: Asserts for match community terms creation tasks + assert: + that: + - cm_add_match_community_term is changed + - cm_add_match_community_term.previous == [] + - cm_add_match_community_term.current == [] + - nm_add_match_community_term is changed + - nm_add_match_community_term.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_1" + - nm_add_match_community_term_idempotency is not changed + - nm_add_match_community_term_2 is changed + - nm_add_match_community_term_2.previous == [] + - nm_add_match_community_term_2.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_2" + + - name: Query all match community terms + aci_match_community_term: + <<: *aci_info + state: query + register: query_all_match_community_term + + - name: Query ansible_match_community_term_1 + aci_match_community_term: + <<: *aci_match_community_term_present + state: query + register: query_ansible_match_community_term_1 + + - name: Asserts query tasks + assert: + that: + - query_all_match_community_term is not changed + - query_all_match_community_term.current|length >= 2 + - query_ansible_match_community_term_1 is not changed + - query_ansible_match_community_term_1.current.0.rtctrlMatchCommTerm.attributes.name == "ansible_match_community_term_1" + + - name: Remove match community term (check_mode) + aci_match_community_term: &match_community_term_absent + <<: *aci_match_community_term_present + state: absent + check_mode: true + register: cm_remove_match_community_term + + - name: Remove match community term (normal_mode) + aci_match_community_term: + <<: *match_community_term_absent + register: nm_remove_match_community_term + + - name: Remove match community term - testing idempotency + aci_match_community_term: + <<: *match_community_term_absent + register: nm_remove_match_community_term_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_match_community_term is changed + - cm_remove_match_community_term.proposed == {} + - nm_remove_match_community_term is changed + - nm_remove_match_community_term.previous != [] + - nm_remove_match_community_term.method == "DELETE" + - nm_remove_match_community_term_idempotency is not changed + - nm_remove_match_community_term_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/tests/integration/targets/aci_match_route_destination/aliases b/tests/integration/targets/aci_match_route_destination/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_match_route_destination/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/tests/integration/targets/aci_match_route_destination/tasks/main.yml new file mode 100644 index 000000000..3a57570a8 --- /dev/null +++ b/tests/integration/targets/aci_match_route_destination/tasks/main.yml @@ -0,0 +1,158 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a subject profile + aci_subject_profile: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: subject profile for ansible_tenant tenant + state: present + register: cm_add_subject_profile + + - name: Add a match route destination rule (check_mode) + aci_match_route_destination: &aci_match_route_destination_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: match route destination rule 1 for ansible_subject_profile subject profile + ip: 11.11.11.11/24 + aggregate: yes + from_prefix_lenght: 0 + to_prefix_lenght: 32 + state: present + check_mode: true + register: cm_add_match_route_destination + + - name: Add a match route destination rule (normal_mode) + aci_match_route_destination: + <<: *aci_match_route_destination_present + register: nm_add_match_route_destination + + - name: Add the first match route destination rule again - testing idempotency + aci_match_route_destination: + <<: *aci_match_route_destination_present + register: nm_add_match_route_destination_idempotency + + - name: Add a second match route destination rule (normal_mode) + aci_match_route_destination: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile + description: match route destination rule 2 for ansible_subject_profile subject profile + ip: 11.11.11.12/24 + state: present + register: nm_add_match_route_destination_2 + + - name: Asserts for match route destination rule creation tasks + assert: + that: + - cm_add_match_route_destination is changed + - cm_add_match_route_destination.previous == [] + - cm_add_match_route_destination.current == [] + - nm_add_match_route_destination is changed + - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.ip == "11.11.11.11/24" + - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.aggregate == "yes" + - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.fromPfxLen == "0" + - nm_add_match_route_destination.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "32" + - nm_add_match_route_destination_idempotency is not changed + - nm_add_match_route_destination_2 is changed + - nm_add_match_route_destination_2.previous == [] + - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.ip == "11.11.11.12/24" + - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.aggregate == "no" + - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.fromPfxLen == "0" + - nm_add_match_route_destination_2.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "0" + + - name: Query all match regex AS-Path terms + aci_match_route_destination: + <<: *aci_info + state: query + register: query_all_match_route_destination + + - name: Query ansible_match_route_destination_1 + aci_match_route_destination: + <<: *aci_match_route_destination_present + state: query + register: query_ansible_match_route_destination_1 + + - name: Asserts query tasks + assert: + that: + - query_all_match_route_destination is not changed + - query_all_match_route_destination.current|length >= 2 + - query_ansible_match_route_destination_1 is not changed + - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.ip == "11.11.11.11/24" + - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.aggregate == "yes" + - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.fromPfxLen == "0" + - query_ansible_match_route_destination_1.current.0.rtctrlMatchRtDest.attributes.toPfxLen == "32" + + - name: Remove match route destination rule (check_mode) + aci_match_route_destination: &match_route_destination_absent + <<: *aci_match_route_destination_present + state: absent + check_mode: true + register: cm_remove_match_route_destination + + - name: Remove match route destination rule (normal_mode) + aci_match_route_destination: + <<: *match_route_destination_absent + register: nm_remove_match_route_destination + + - name: Remove match route destination rule - testing idempotency + aci_match_route_destination: + <<: *match_route_destination_absent + register: nm_remove_match_route_destination_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_match_route_destination is changed + - cm_remove_match_route_destination.proposed == {} + - nm_remove_match_route_destination is changed + - nm_remove_match_route_destination.previous != [] + - nm_remove_match_route_destination.method == "DELETE" + - nm_remove_match_route_destination_idempotency is not changed + - nm_remove_match_route_destination_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent \ No newline at end of file diff --git a/tests/integration/targets/aci_subject_profile/aliases b/tests/integration/targets/aci_subject_profile/aliases new file mode 100644 index 000000000..209b793f9 --- /dev/null +++ b/tests/integration/targets/aci_subject_profile/aliases @@ -0,0 +1,2 @@ +# No ACI simulator yet, so not enabled +# unsupported diff --git a/tests/integration/targets/aci_subject_profile/tasks/main.yml b/tests/integration/targets/aci_subject_profile/tasks/main.yml new file mode 100644 index 000000000..51c1f423b --- /dev/null +++ b/tests/integration/targets/aci_subject_profile/tasks/main.yml @@ -0,0 +1,135 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a subject profile (check_mode) + aci_subject_profile: &aci_subject_profile_present + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile_1 + description: subject profile 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_subject_profile + + - name: Add a subject profile (normal_mode) + aci_subject_profile: + <<: *aci_subject_profile_present + register: nm_add_subject_profile + + - name: Add the first subject profile again - testing idempotency + aci_subject_profile: + <<: *aci_subject_profile_present + register: nm_add_subject_profile_idempotency + + - name: Add a second subject profile (normal_mode) + aci_subject_profile: + <<: *aci_info + tenant: ansible_tenant + subject_profile: ansible_subject_profile_2 + description: subject profile 2 for ansible_tenant tenant + state: present + register: nm_add_subject_profile_2 + + - name: Asserts for subject profiles creation tasks + assert: + that: + - cm_add_subject_profile is changed + - cm_add_subject_profile.previous == [] + - cm_add_subject_profile.current == [] + - nm_add_subject_profile is changed + - nm_add_subject_profile.current.0.rtctrlSubjP.attributes.name == "ansible_subject_profile_1" + - nm_add_subject_profile_idempotency is not changed + - nm_add_subject_profile_2 is changed + - nm_add_subject_profile_2.previous == [] + - nm_add_subject_profile_2.current.0.rtctrlSubjP.attributes.name == "ansible_subject_profile_2" + + - name: Query all subject profiles + aci_subject_profile: + <<: *aci_info + state: query + register: query_all_subject_profile + + - name: Query ansible_subject_profile_1 + aci_subject_profile: + <<: *aci_subject_profile_present + state: query + register: query_ansible_subject_profile_1 + + - name: Asserts query tasks + assert: + that: + - query_all_subject_profile is not changed + - query_all_subject_profile.current|length >= 2 + - query_ansible_subject_profile_1 is not changed + - query_ansible_subject_profile_1.current.0.rtctrlSubjP.attributes.name == "ansible_subject_profile_1" + + - name: Remove subject profile for l3out (check_mode) + aci_subject_profile: &subject_profile_absent + <<: *aci_subject_profile_present + state: absent + check_mode: true + register: cm_remove_subject_profile + + - name: Remove subject profile for l3out (normal_mode) + aci_subject_profile: + <<: *subject_profile_absent + register: nm_remove_subject_profile + + - name: Remove subject profile for l3out - testing idempotency + aci_subject_profile: + <<: *subject_profile_absent + register: nm_remove_subject_profile_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_subject_profile is changed + - cm_remove_subject_profile.proposed == {} + - nm_remove_subject_profile is changed + - nm_remove_subject_profile.previous != [] + - nm_remove_subject_profile.method == "DELETE" + - nm_remove_subject_profile_idempotency is not changed + - nm_remove_subject_profile_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent From 0dcf72cdf86875ec818e1790797274175d2786aa Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 28 Sep 2023 12:54:54 -0400 Subject: [PATCH 07/11] [ignore] Modify documentations and check sanity tests for all modules related to aci_route_control_profile. --- plugins/modules/aci_context_policy.py | 72 +++++++++++-------- .../modules/aci_match_as_path_regex_term.py | 36 +++++----- plugins/modules/aci_match_community_factor.py | 48 ++++++------- .../modules/aci_match_community_regex_term.py | 39 +++++----- plugins/modules/aci_match_community_term.py | 36 +++++----- .../modules/aci_match_route_destination.py | 41 +++++------ plugins/modules/aci_route_control_profile.py | 40 +++++++---- plugins/modules/aci_subject_profile.py | 24 +++---- 8 files changed, 183 insertions(+), 153 deletions(-) diff --git a/plugins/modules/aci_context_policy.py b/plugins/modules/aci_context_policy.py index aa35081b8..5c7c71513 100644 --- a/plugins/modules/aci_context_policy.py +++ b/plugins/modules/aci_context_policy.py @@ -12,10 +12,10 @@ DOCUMENTATION = r""" --- -module: aci_route_control_profile -short_description: Manage Context Policy (rtcrtl:CtxP) +module: aci_context_policy +short_description: Manage Route Context Policy (rtcrtl:CtxP) description: -- Manage Context Policies for the Route Control Profiles on Cisco ACI fabrics. +- Manage Route Context Policies for the Route Control Profiles on Cisco ACI fabrics. options: tenant: description: @@ -42,6 +42,20 @@ - The action required when the condition is met. type: str choices: [ deny, permit ] + action_rule: + description: + - Name of the action rule profile to be associated with this route context policy. + - Set the rules for a Route Map. + - See module M(cisco.aci.aci_tenant_action_rule_profile). + type: str + aliases: [ action_rule_name ] + subject_profile: + description: + - Name of the subject profile to be associated with this route context policy. + - Set the associated Matched rules. + - See module M(cisco.aci.aci_subject_profile). + type: str + aliases: [ subject_name ] order: description: - The order of the policy context. @@ -199,11 +213,11 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects - route_control_profile=dict(type="str", aliases=["rtctrl_profile_name"]), # Not required for querying all objects - context_policy=dict(type="str", aliases=["name", "context_name"]), # Not required for querying all objects + route_control_profile=dict(type="str", aliases=["rtctrl_profile_name"]), # Not required for querying all objects + context_policy=dict(type="str", aliases=["name", "context_name"]), # Not required for querying all objects subject_profile=dict(type="str", aliases=["subject_name"]), action_rule=dict(type="str", aliases=["action_rule_name"]), - action = dict(type="str", choices=["deny", "permit"]), + action=dict(type="str", choices=["deny", "permit"]), order=dict(type="int"), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), @@ -236,26 +250,26 @@ def main(): child_classes = ["rtctrlRsCtxPToSubjP", "rtctrlScope"] tenant_url_config = dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ) - + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ) + route_control_profile_url_config = dict( - aci_class="rtctrlProfile", - aci_rn="prof-{0}".format(route_control_profile), - module_object=route_control_profile, - target_filter={"name": route_control_profile}, - ) - + aci_class="rtctrlProfile", + aci_rn="prof-{0}".format(route_control_profile), + module_object=route_control_profile, + target_filter={"name": route_control_profile}, + ) + context_policy_url_config = dict( - aci_class="rtctrlCtxP", - aci_rn="ctx-{0}".format(context_policy), - module_object=context_policy, - target_filter={"name": context_policy}, - ) - + aci_class="rtctrlCtxP", + aci_rn="ctx-{0}".format(context_policy), + module_object=context_policy, + target_filter={"name": context_policy}, + ) + if l3out is not None: aci.construct_url( root_class=tenant_url_config, @@ -285,9 +299,11 @@ def main(): child_configs.append({"rtctrlRsCtxPToSubjP": {"attributes": {"tnRtctrlSubjPName": subject_profile}}}) if action_rule is not None: child_configs.append( - {"rtctrlScope": {"attributes": {"descr": ""}, - "children": [{"rtctrlRsScopeToAttrP": {"attributes": {"tnRtctrlAttrPName": action_rule}}}], - } + { + "rtctrlScope": { + "attributes": {"descr": ""}, + "children": [{"rtctrlRsScopeToAttrP": {"attributes": {"tnRtctrlAttrPName": action_rule}}}], + } } ) @@ -314,4 +330,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_match_as_path_regex_term.py b/plugins/modules/aci_match_as_path_regex_term.py index 05ce7b25a..181ea4d2b 100644 --- a/plugins/modules/aci_match_as_path_regex_term.py +++ b/plugins/modules/aci_match_as_path_regex_term.py @@ -12,7 +12,7 @@ DOCUMENTATION = r""" --- -module: aci_subject_profile +module: aci_match_as_path_regex_term short_description: Manage Match Regular Expression AS-Path Term (rtctrl:MatchAsPathRegexTerm) description: - Manage Match Rule Based on Route Regular Expression AS-Path for Subject Profiles on Cisco ACI fabrics. @@ -187,7 +187,7 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects match_as_path_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), regex=dict(type="str"), description=dict(type="str", aliases=["descr"]), @@ -216,23 +216,23 @@ def main(): aci.construct_url( root_class=dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ), + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), subclass_1=dict( - aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, - ), + aci_class="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), subclass_2=dict( - aci_class="rtctrlMatchAsPathRegexTerm", - aci_rn="aspathrxtrm-{0}".format(match_as_path_regex_term), - module_object=match_as_path_regex_term, - target_filter={"name": match_as_path_regex_term}, - ), + aci_class="rtctrlMatchAsPathRegexTerm", + aci_rn="aspathrxtrm-{0}".format(match_as_path_regex_term), + module_object=match_as_path_regex_term, + target_filter={"name": match_as_path_regex_term}, + ), ) aci.get_existing() @@ -259,4 +259,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_match_community_factor.py b/plugins/modules/aci_match_community_factor.py index c8da456df..70f94bbd6 100644 --- a/plugins/modules/aci_match_community_factor.py +++ b/plugins/modules/aci_match_community_factor.py @@ -12,7 +12,7 @@ DOCUMENTATION = r""" --- -module: aci_subject_profile +module: aci_match_community_factor short_description: Manage Match Community Factor (rtctrl:MatchCommFactor) description: - Manage Match Community Factors for Match Rules Based on Community on Cisco ACI fabrics. @@ -194,8 +194,8 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects - match_community_term=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + match_community_term=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects community=dict(type="str"), scope=dict(type="str", choices=["transitive", "non-transitive"]), description=dict(type="str", aliases=["descr"]), @@ -225,29 +225,29 @@ def main(): aci.construct_url( root_class=dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ), + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), subclass_1=dict( - aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, - ), + aci_class="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), subclass_2=dict( - aci_class="rtctrlMatchCommTerm", - aci_rn="commtrm-{0}".format(match_community_term), - module_object=match_community_term, - target_filter={"name": match_community_term}, - ), + aci_class="rtctrlMatchCommTerm", + aci_rn="commtrm-{0}".format(match_community_term), + module_object=match_community_term, + target_filter={"name": match_community_term}, + ), subclass_3=dict( - aci_class="rtctrlMatchCommFactor", - aci_rn="commfct-{0}".format(community), - module_object=community, - target_filter={"community": community}, - ), + aci_class="rtctrlMatchCommFactor", + aci_rn="commfct-{0}".format(community), + module_object=community, + target_filter={"community": community}, + ), ) aci.get_existing() @@ -274,4 +274,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_match_community_regex_term.py b/plugins/modules/aci_match_community_regex_term.py index 34bc52094..c64066d96 100644 --- a/plugins/modules/aci_match_community_regex_term.py +++ b/plugins/modules/aci_match_community_regex_term.py @@ -12,7 +12,7 @@ DOCUMENTATION = r""" --- -module: aci_subject_profile +module: aci_match_community_regex_term short_description: Manage Match Regular Expression Community Term (rtctrl:MatchCommRegexTerm) description: - Manage Match Rule Based on Route Regular Expression Community for Subject Profiles on Cisco ACI fabrics. @@ -37,6 +37,7 @@ - The Community Type. type: str choices: [ extended, regular ] + default: regular regex: description: - The Regular Expression. @@ -192,8 +193,8 @@ def main(): argument_spec.update(aci_annotation_spec()) argument_spec.update(aci_owner_spec()) argument_spec.update( - tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects match_community_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), community_type=dict(type="str", default="regular", choices=["extended", "regular"]), regex=dict(type="str"), @@ -224,23 +225,23 @@ def main(): aci.construct_url( root_class=dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ), + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), subclass_1=dict( - aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, - ), + aci_class="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), subclass_2=dict( - aci_class="rtctrlMatchCommRegexTerm", - aci_rn="commrxtrm-{0}".format(community_type), - module_object=community_type, - target_filter={"commType": community_type}, - ), + aci_class="rtctrlMatchCommRegexTerm", + aci_rn="commrxtrm-{0}".format(community_type), + module_object=community_type, + target_filter={"commType": community_type}, + ), ) aci.get_existing() @@ -268,4 +269,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_match_community_term.py b/plugins/modules/aci_match_community_term.py index 83fc50837..644bfead7 100644 --- a/plugins/modules/aci_match_community_term.py +++ b/plugins/modules/aci_match_community_term.py @@ -12,7 +12,7 @@ DOCUMENTATION = r""" --- -module: aci_subject_profile +module: aci_match_community_term short_description: Manage Match Community Term (rtctrl:MatchCommTerm) description: - Manage Match Rule Based on Community for Subject Profiles on Cisco ACI fabrics. @@ -183,7 +183,7 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects match_community_term=dict(type="str", aliases=["name", "match_rule_name"]), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), @@ -210,23 +210,23 @@ def main(): aci.construct_url( root_class=dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ), + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), subclass_1=dict( - aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, - ), + aci_class="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), subclass_2=dict( - aci_class="rtctrlMatchCommTerm", - aci_rn="commtrm-{0}".format(match_community_term), - module_object=match_community_term, - target_filter={"name": match_community_term}, - ), + aci_class="rtctrlMatchCommTerm", + aci_rn="commtrm-{0}".format(match_community_term), + module_object=match_community_term, + target_filter={"name": match_community_term}, + ), ) aci.get_existing() @@ -252,4 +252,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_match_route_destination.py b/plugins/modules/aci_match_route_destination.py index 2c3faf7d4..f068d1c02 100644 --- a/plugins/modules/aci_match_route_destination.py +++ b/plugins/modules/aci_match_route_destination.py @@ -12,7 +12,7 @@ DOCUMENTATION = r""" --- -module: aci_subject_profile +module: aci_match_route_destination short_description: Manage Match action rule based on the Route Destination. (rtctrl:MatchRtDest) description: - Match action rule based on the Route Destination for Subject Profiles on Cisco ACI fabrics. @@ -35,16 +35,17 @@ description: - Option to enable/disable aggregated route. type: str - choices: [ yes, no ] + choices: [ "no", "yes" ] from_prefix_lenght: description: - Start of the prefix lenght. - It corresponds to the less equal Mask if the route is aggregated. - type: str + type: int to_prefix_lenght: description: - End of the prefix lenght. - It corresponds to greater equal Mask if the route is aggregated. + type: int description: description: - The description for the Match Action Rule. @@ -196,7 +197,7 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects ip=dict(type="str"), aggregate=dict(type="str", choices=["no", "yes"]), from_prefix_lenght=dict(type="int"), @@ -229,23 +230,23 @@ def main(): aci.construct_url( root_class=dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ), + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), subclass_1=dict( - aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, - ), + aci_class="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), subclass_2=dict( - aci_class="rtctrlMatchRtDest", - aci_rn="dest-[{0}]".format(ip), - module_object=ip, - target_filter={"ip": ip}, - ), + aci_class="rtctrlMatchRtDest", + aci_rn="dest-[{0}]".format(ip), + module_object=ip, + target_filter={"ip": ip}, + ), ) aci.get_existing() @@ -274,4 +275,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py index ee1b70d47..18e9d2a84 100644 --- a/plugins/modules/aci_route_control_profile.py +++ b/plugins/modules/aci_route_control_profile.py @@ -32,6 +32,18 @@ - Name of the route control profile being created. type: str aliases: [ name, rtctrl_profile_name ] + auto_continue: + description: + - Option to enable/disable auto-continue. + type: str + choices: [ "no", "yes" ] + default: "no" + policy_type: + description: + - Set the policy type to combinable or global. + type: str + choices: [ combinable, global ] + default: combinable description: description: - The description for the route control profile. @@ -184,7 +196,7 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects - route_control_profile = dict(type="str", aliases=["name", "rtctrl_profile_name"]), # Not required for querying all objects + route_control_profile=dict(type="str", aliases=["name", "rtctrl_profile_name"]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), auto_continue=dict(type="str", default="no", choices=["no", "yes"]), policy_type=dict(type="str", default="combinable", choices=["combinable", "global"]), @@ -213,19 +225,19 @@ def main(): aci = ACIModule(module) tenant_url_config = dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ) - + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ) + route_control_profile_url_config = dict( - aci_class="rtctrlProfile", - aci_rn="prof-{0}".format(route_control_profile), - module_object=route_control_profile, - target_filter={"name": route_control_profile}, - ) - + aci_class="rtctrlProfile", + aci_rn="prof-{0}".format(route_control_profile), + module_object=route_control_profile, + target_filter={"name": route_control_profile}, + ) + if l3out is not None: aci.construct_url( root_class=tenant_url_config, @@ -268,4 +280,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() diff --git a/plugins/modules/aci_subject_profile.py b/plugins/modules/aci_subject_profile.py index 4ee7f9d7f..9d40d6b18 100644 --- a/plugins/modules/aci_subject_profile.py +++ b/plugins/modules/aci_subject_profile.py @@ -178,7 +178,7 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["name", "subject_name"]), # Not required for querying all objects + subject_profile=dict(type="str", aliases=["name", "subject_name"]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), state=dict(type="str", default="present", choices=["present", "absent", "query"]), @@ -203,17 +203,17 @@ def main(): aci.construct_url( root_class=dict( - aci_class="fvTenant", - aci_rn="tn-{0}".format(tenant), - module_object=tenant, - target_filter={"name": tenant}, - ), + aci_class="fvTenant", + aci_rn="tn-{0}".format(tenant), + module_object=tenant, + target_filter={"name": tenant}, + ), subclass_1=dict( - aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, - ), + aci_class="rtctrlSubjP", + aci_rn="subj-{0}".format(subject_profile), + module_object=subject_profile, + target_filter={"name": subject_profile}, + ), ) aci.get_existing() @@ -239,4 +239,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From 5d7acdbe169556d87860976c6ead04b0e391fd16 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 5 Oct 2023 10:06:01 -0400 Subject: [PATCH 08/11] [minor_change] Rename module aci_context_policy and aci_subject_profile to aci_route_control_context and aci_match_rule. Applied changes to all Documentations and Modules. --- .../modules/aci_match_as_path_regex_term.py | 74 +++++-- plugins/modules/aci_match_community_factor.py | 86 ++++++-- .../modules/aci_match_community_regex_term.py | 85 ++++++-- plugins/modules/aci_match_community_term.py | 75 +++++-- .../modules/aci_match_route_destination.py | 99 ++++++--- ...i_subject_profile.py => aci_match_rule.py} | 69 ++++-- ...policy.py => aci_route_control_context.py} | 124 ++++++++--- plugins/modules/aci_route_control_profile.py | 58 +++++- .../targets/aci_context_policy/tasks/main.yml | 196 ------------------ .../tasks/main.yml | 18 +- .../aci_match_community_factor/tasks/main.yml | 16 +- .../tasks/main.yml | 18 +- .../aci_match_community_term/tasks/main.yml | 18 +- .../tasks/main.yml | 16 +- .../aliases | 0 .../targets/aci_match_rule/tasks/main.yml | 135 ++++++++++++ .../aliases | 0 .../aci_route_control_context/tasks/main.yml | 196 ++++++++++++++++++ .../aci_subject_profile/tasks/main.yml | 135 ------------ 19 files changed, 894 insertions(+), 524 deletions(-) rename plugins/modules/{aci_subject_profile.py => aci_match_rule.py} (78%) rename plugins/modules/{aci_context_policy.py => aci_route_control_context.py} (68%) delete mode 100644 tests/integration/targets/aci_context_policy/tasks/main.yml rename tests/integration/targets/{aci_context_policy => aci_match_rule}/aliases (100%) create mode 100644 tests/integration/targets/aci_match_rule/tasks/main.yml rename tests/integration/targets/{aci_subject_profile => aci_route_control_context}/aliases (100%) create mode 100644 tests/integration/targets/aci_route_control_context/tasks/main.yml delete mode 100644 tests/integration/targets/aci_subject_profile/tasks/main.yml diff --git a/plugins/modules/aci_match_as_path_regex_term.py b/plugins/modules/aci_match_as_path_regex_term.py index 181ea4d2b..98d9cee02 100644 --- a/plugins/modules/aci_match_as_path_regex_term.py +++ b/plugins/modules/aci_match_as_path_regex_term.py @@ -15,30 +15,30 @@ module: aci_match_as_path_regex_term short_description: Manage Match Regular Expression AS-Path Term (rtctrl:MatchAsPathRegexTerm) description: -- Manage Match Rule Based on Route Regular Expression AS-Path for Subject Profiles on Cisco ACI fabrics. +- Manage Match Term Based on Route Regular Expression AS-Path for Match Rule Profiles on Cisco ACI fabrics. options: tenant: description: - The name of an existing tenant. type: str aliases: [ tenant_name ] - subject_profile: + match_rule: description: - - Name of an exising subject profile. + - The name of an exising match rule profile. type: str - aliases: [ subject_name ] + aliases: [ match_rule_name ] match_as_path_regex_term: description: - - Name of the Match Regular Expression AS-Path Term. + - The name of the match regex AS-Path term. type: str - aliases: [ name, match_rule_name ] + aliases: [ name, match_as_path_regex_term_name ] regex: description: - The Regular Expression. type: str description: description: - - The description for the Match Regular Expression AS-Path Term. + - The description for the match regex AS-Path term. type: str aliases: [ descr ] state: @@ -58,10 +58,11 @@ - cisco.aci.owner notes: -- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. +- The C(tenant) and the C(match_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_match_rule) modules can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_match_rule - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:MatchAsPathRegexTerm). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -70,6 +71,49 @@ """ EXAMPLES = r""" +- name: Create a match match AS-path regex term + cisco.aci.match_as_path_regex_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + match_as_path_regex_term: prod_match_as_path_regex_term + regex: .* + tenant: production + state: present + delegate_to: localhost + +- name: Delete a match match AS-path regex term + cisco.aci.match_as_path_regex_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + match_as_path_regex_term: prod_match_as_path_regex_term + state: absent + delegate_to: localhost + +- name: Query all match AS-path regex terms + cisco.aci.match_as_path_regex_term: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific match match AS-path regex term + cisco.aci.match_as_path_regex_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + match_as_path_regex_term: prod_match_as_path_regex_term + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -187,8 +231,8 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects - match_as_path_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), + match_rule=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + match_as_path_regex_term=dict(type="str", aliases=["name", "match_as_path_regex_term_name"]), regex=dict(type="str"), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), @@ -209,7 +253,7 @@ def main(): regex = module.params.get("regex") state = module.params.get("state") tenant = module.params.get("tenant") - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") name_alias = module.params.get("name_alias") aci = ACIModule(module) @@ -223,9 +267,9 @@ def main(): ), subclass_1=dict( aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, + aci_rn="subj-{0}".format(match_rule), + module_object=match_rule, + target_filter={"name": match_rule}, ), subclass_2=dict( aci_class="rtctrlMatchAsPathRegexTerm", diff --git a/plugins/modules/aci_match_community_factor.py b/plugins/modules/aci_match_community_factor.py index 70f94bbd6..853cbc3e7 100644 --- a/plugins/modules/aci_match_community_factor.py +++ b/plugins/modules/aci_match_community_factor.py @@ -15,23 +15,23 @@ module: aci_match_community_factor short_description: Manage Match Community Factor (rtctrl:MatchCommFactor) description: -- Manage Match Community Factors for Match Rules Based on Community on Cisco ACI fabrics. +- Manage Match Community Factors for Match Terms Based on Community on Cisco ACI fabrics. options: tenant: description: - The name of an existing tenant. type: str aliases: [ tenant_name ] - subject_profile: + match_rule: description: - - Name of an exising subject profile. + - The name of an exising match rule profile. type: str - aliases: [ subject_name ] + aliases: [ match_rule_name ] match_community_term: description: - - Name of an existing match community term. + - The name of an existing match community term. type: str - aliases: [ match_rule_name ] + aliases: [ match_community_term_name ] community: description: - The match community value. @@ -39,13 +39,13 @@ scope: description: - The item scope. - - if the scope is transitive, this community may be passed between ASs. - - if the scope is Non transitive, this community should be carried only within the local AS. + - If the scope is transitive, this community may be passed between ASs. + - If the scope is Non transitive, this community should be carried only within the local AS. type: str choices: [ transitive, non-transitive ] description: description: - - The description for the Match Community Term. + - The description for the match community factor. type: str aliases: [ descr ] state: @@ -65,10 +65,12 @@ - cisco.aci.owner notes: -- The C(tenant), the C(subject_profile) and the C(match_community_term) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant), the M(cisco.aci.subject_profile) and M(cisco.aci.match_community_term) modules can be used for this. +- The C(tenant), the C(match_rule) and the C(match_community_term) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant), the M(cisco.aci.aci_match_rule) and M(cisco.aci.aci_match_community_term) modules can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_match_rule +- module: cisco.aci.aci_match_community_term - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:MatchCommFactor). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -77,6 +79,52 @@ """ EXAMPLES = r""" +- name: Create a match match AS-path regex term + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + match_community_term: prod_match_community_term + community: regular:as2-nn2:4:15 + scope: transitive + tenant: production + state: present + delegate_to: localhost + +- name: Delete a match match AS-path regex term + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + match_community_term: prod_match_community_term + community: regular:as2-nn2:4:15 + state: absent + delegate_to: localhost + +- name: Query all match AS-path regex terms + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific match match AS-path regex term + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + match_community_term: prod_match_community_term + community: regular:as2-nn2:4:15 + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -194,8 +242,8 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects - match_community_term=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + match_rule=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + match_community_term=dict(type="str", aliases=["match_community_term_name"]), # Not required for querying all objects community=dict(type="str"), scope=dict(type="str", choices=["transitive", "non-transitive"]), description=dict(type="str", aliases=["descr"]), @@ -207,8 +255,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["community", "tenant", "subject_profile", "match_community_term"]], - ["state", "present", ["community", "tenant", "subject_profile", "match_community_term"]], + ["state", "absent", ["community", "tenant", "match_rule", "match_community_term"]], + ["state", "present", ["community", "tenant", "match_rule", "match_community_term"]], ], ) @@ -217,7 +265,7 @@ def main(): description = module.params.get("description") state = module.params.get("state") tenant = module.params.get("tenant") - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") match_community_term = module.params.get("match_community_term") name_alias = module.params.get("name_alias") @@ -232,9 +280,9 @@ def main(): ), subclass_1=dict( aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, + aci_rn="subj-{0}".format(match_rule), + module_object=match_rule, + target_filter={"name": match_rule}, ), subclass_2=dict( aci_class="rtctrlMatchCommTerm", diff --git a/plugins/modules/aci_match_community_regex_term.py b/plugins/modules/aci_match_community_regex_term.py index c64066d96..c76cd0cd9 100644 --- a/plugins/modules/aci_match_community_regex_term.py +++ b/plugins/modules/aci_match_community_regex_term.py @@ -15,36 +15,36 @@ module: aci_match_community_regex_term short_description: Manage Match Regular Expression Community Term (rtctrl:MatchCommRegexTerm) description: -- Manage Match Rule Based on Route Regular Expression Community for Subject Profiles on Cisco ACI fabrics. +- Manage Match Terms Based on Route Regular Expression Community for Match Rule Profiles on Cisco ACI fabrics. options: tenant: description: - The name of an existing tenant. type: str aliases: [ tenant_name ] - subject_profile: + match_rule: description: - - Name of an exising subject profile. + - The name of an exising math rule profile. type: str - aliases: [ subject_name ] + aliases: [ match_rule_name ] match_community_regex_term: description: - - Name of the Match Regular Expression Community Term. + - The name of the match regex community term. type: str - aliases: [ name, match_rule_name ] + aliases: [ name, match_community_regex_term_name ] community_type: description: - - The Community Type. + - The community type. type: str choices: [ extended, regular ] default: regular regex: description: - - The Regular Expression. + - The regular expression. type: str description: description: - - The description for the Match Regular Expression Community Term. + - The description for the match regex community term. type: str aliases: [ descr ] state: @@ -64,11 +64,12 @@ - cisco.aci.owner notes: -- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. -- Only two match community regex terms can exist at the same two, one of each C(community_type). +- The C(tenant) and the C(match_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_match_rule) modules can be used for this. +- Only two match community regex terms can exist at the same time, one of each C(community_type). seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_match_rule - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:MatchCommRegexTerm). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -77,6 +78,50 @@ """ EXAMPLES = r""" +- name: Create a match comunity regex term + cisco.aci.match_community_regex_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + match_community_regex_term: prod_match_community_regex_term + community_type: regular + regex: .* + tenant: production + state: present + delegate_to: localhost + +- name: Delete a match comunity regex term + cisco.aci.match_community_regex_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + community_type: regular + state: absent + delegate_to: localhost + +- name: Query all match rule commmuntiy regex terms + cisco.aci.match_community_regex_term: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific match comunity regex term + cisco.aci.match_community_regex_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + community_type: regular + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -194,8 +239,8 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects - match_community_regex_term=dict(type="str", aliases=["name", "match_rule_name"]), + match_rule=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + match_community_regex_term=dict(type="str", aliases=["name", "match_community_regex_term_name"]), community_type=dict(type="str", default="regular", choices=["extended", "regular"]), regex=dict(type="str"), description=dict(type="str", aliases=["descr"]), @@ -207,8 +252,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["community_type", "tenant", "subject_profile"]], - ["state", "present", ["community_type", "tenant", "subject_profile"]], + ["state", "absent", ["community_type", "tenant", "match_rule"]], + ["state", "present", ["community_type", "tenant", "match_rule"]], ], ) @@ -218,7 +263,7 @@ def main(): regex = module.params.get("regex") state = module.params.get("state") tenant = module.params.get("tenant") - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") name_alias = module.params.get("name_alias") aci = ACIModule(module) @@ -232,9 +277,9 @@ def main(): ), subclass_1=dict( aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, + aci_rn="subj-{0}".format(match_rule), + module_object=match_rule, + target_filter={"name": match_rule}, ), subclass_2=dict( aci_class="rtctrlMatchCommRegexTerm", diff --git a/plugins/modules/aci_match_community_term.py b/plugins/modules/aci_match_community_term.py index 644bfead7..eb2004e8f 100644 --- a/plugins/modules/aci_match_community_term.py +++ b/plugins/modules/aci_match_community_term.py @@ -15,23 +15,23 @@ module: aci_match_community_term short_description: Manage Match Community Term (rtctrl:MatchCommTerm) description: -- Manage Match Rule Based on Community for Subject Profiles on Cisco ACI fabrics. +- Manage Match Term Based on Community for Match Rule Profiles on Cisco ACI fabrics. options: tenant: description: - The name of an existing tenant. type: str aliases: [ tenant_name ] - subject_profile: + match_rule: description: - - Name of an exising subject profile. + - the name of an exising match rule profile. type: str - aliases: [ subject_name ] + aliases: [ match_rule_name ] match_community_term: description: - - Name of the Match Community Term. + - the name of the Match Community Term. type: str - aliases: [ name, match_rule_name ] + aliases: [ name, match_community_term_name ] description: description: - The description for the Match Community Term. @@ -54,10 +54,11 @@ - cisco.aci.owner notes: -- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. +- The C(tenant) and the C(match_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_match_rule) modules can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_match_rule - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:MatchCommTerm). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -66,6 +67,48 @@ """ EXAMPLES = r""" +- name: Create a match match AS-path regex term + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + match_community_term: prod_match_community_term + tenant: production + state: present + delegate_to: localhost + +- name: Delete a match match AS-path regex term + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + match_community_term: prod_match_community_term + state: absent + delegate_to: localhost + +- name: Query all match AS-path regex terms + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific match match AS-path regex term + cisco.aci.match_community_term: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + match_community_term: prod_match_community_term + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -183,8 +226,8 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects - match_community_term=dict(type="str", aliases=["name", "match_rule_name"]), + match_rule=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects + match_community_term=dict(type="str", aliases=["name", "match_community_term_name"]), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), state=dict(type="str", default="present", choices=["present", "absent", "query"]), @@ -194,8 +237,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["match_community_term", "tenant", "subject_profile"]], - ["state", "present", ["match_community_term", "tenant", "subject_profile"]], + ["state", "absent", ["match_community_term", "tenant", "match_rule"]], + ["state", "present", ["match_community_term", "tenant", "match_rule"]], ], ) @@ -203,7 +246,7 @@ def main(): description = module.params.get("description") state = module.params.get("state") tenant = module.params.get("tenant") - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") name_alias = module.params.get("name_alias") aci = ACIModule(module) @@ -217,9 +260,9 @@ def main(): ), subclass_1=dict( aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, + aci_rn="subj-{0}".format(match_rule), + module_object=match_rule, + target_filter={"name": match_rule}, ), subclass_2=dict( aci_class="rtctrlMatchCommTerm", diff --git a/plugins/modules/aci_match_route_destination.py b/plugins/modules/aci_match_route_destination.py index f068d1c02..da6e73c5a 100644 --- a/plugins/modules/aci_match_route_destination.py +++ b/plugins/modules/aci_match_route_destination.py @@ -13,20 +13,20 @@ DOCUMENTATION = r""" --- module: aci_match_route_destination -short_description: Manage Match action rule based on the Route Destination. (rtctrl:MatchRtDest) +short_description: Manage Match action rule term based on the Route Destination. (rtctrl:MatchRtDest) description: -- Match action rule based on the Route Destination for Subject Profiles on Cisco ACI fabrics. +- Match action rule terms based on the Route Destination for Subject Profiles on Cisco ACI fabrics. options: tenant: description: - The name of an existing tenant. type: str aliases: [ tenant_name ] - subject_profile: + match_rule: description: - - Name of an exising subject profile. + - The name of an exising match rule profile. type: str - aliases: [ subject_name ] + aliases: [ match_rule_name ] ip: description: - The IP address of the route destination. @@ -36,19 +36,19 @@ - Option to enable/disable aggregated route. type: str choices: [ "no", "yes" ] - from_prefix_lenght: + from_prefix_length: description: - - Start of the prefix lenght. - - It corresponds to the less equal Mask if the route is aggregated. + - The start of the prefix length. + - It corresponds to the lesser Mask if the route is aggregated. type: int - to_prefix_lenght: + to_prefix_length: description: - - End of the prefix lenght. - - It corresponds to greater equal Mask if the route is aggregated. + - The end of the prefix length. + - It corresponds to greater Mask if the route is aggregated. type: int description: description: - - The description for the Match Action Rule. + - The description for the match action rule term. type: str aliases: [ descr ] state: @@ -68,10 +68,11 @@ - cisco.aci.owner notes: -- The C(tenant) and the C(subject_profile) used must exist before using this module in your playbook. - The M(cisco.aci.aci_tenant) and the M(cisco.aci.subject_profile) modules can be used for this. +- The C(tenant) and the C(match_rule) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_match_rule) modules can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_match_rule - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:MatchRtDest). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -80,6 +81,50 @@ """ EXAMPLES = r""" +- name: Create a match rule destination + cisco.aci.aci_match_rule_destination: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + ip: 11.11.11.11/24 + aggregate: "yes" + from_prefix_length: 0 + to_prefix_length: 32 + state: present + delegate_to: localhost + +- name: Delete a match rule destination + cisco.aci.aci_match_rule_destination: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + state: absent + delegate_to: localhost + +- name: Query all match rules destination + cisco.aci.aci_match_rule_destination: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific match rule destination + cisco.aci.aci_match_rule_destination: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + ip: 11.11.11.11/24 + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -197,11 +242,11 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), # Not required for querying all objects + match_rule=dict(type="str", aliases=["match_rule_name"]), # Not required for querying all objects ip=dict(type="str"), aggregate=dict(type="str", choices=["no", "yes"]), - from_prefix_lenght=dict(type="int"), - to_prefix_lenght=dict(type="int"), + from_prefix_length=dict(type="int"), + to_prefix_length=dict(type="int"), description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), state=dict(type="str", default="present", choices=["present", "absent", "query"]), @@ -211,19 +256,19 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["ip", "tenant", "subject_profile"]], - ["state", "present", ["ip", "tenant", "subject_profile"]], + ["state", "absent", ["ip", "tenant", "match_rule"]], + ["state", "present", ["ip", "tenant", "match_rule"]], ], ) ip = module.params.get("ip") description = module.params.get("description") aggregate = module.params.get("aggregate") - from_prefix_lenght = module.params.get("from_prefix_lenght") - to_prefix_lenght = module.params.get("to_prefix_lenght") + from_prefix_length = module.params.get("from_prefix_length") + to_prefix_length = module.params.get("to_prefix_length") state = module.params.get("state") tenant = module.params.get("tenant") - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") name_alias = module.params.get("name_alias") aci = ACIModule(module) @@ -237,9 +282,9 @@ def main(): ), subclass_1=dict( aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, + aci_rn="subj-{0}".format(match_rule), + module_object=match_rule, + target_filter={"name": match_rule}, ), subclass_2=dict( aci_class="rtctrlMatchRtDest", @@ -257,8 +302,8 @@ def main(): class_config=dict( ip=ip, aggregate=aggregate, - fromPfxLen=from_prefix_lenght, - toPfxLen=to_prefix_lenght, + fromPfxLen=from_prefix_length, + toPfxLen=to_prefix_length, descr=description, nameAlias=name_alias, ), diff --git a/plugins/modules/aci_subject_profile.py b/plugins/modules/aci_match_rule.py similarity index 78% rename from plugins/modules/aci_subject_profile.py rename to plugins/modules/aci_match_rule.py index 9d40d6b18..0285c3a81 100644 --- a/plugins/modules/aci_subject_profile.py +++ b/plugins/modules/aci_match_rule.py @@ -12,24 +12,24 @@ DOCUMENTATION = r""" --- -module: aci_subject_profile -short_description: Manage Subject Profile (rtcrtl:SubjP) +module: aci_match_rule +short_description: Manage Match Rule (rtcrtl:SubjP) description: -- Manage Subject Profiles for the Context Policies on Cisco ACI fabrics. +- Manage Match Rule Profiles for the Tenants on Cisco ACI fabrics. options: tenant: description: - The name of an existing tenant. type: str aliases: [ tenant_name ] - subject_profile: + match_rule: description: - - Name of the subject profile being created. + - The name of the match rule profile being created. type: str - aliases: [ name, subject_name ] + aliases: [ name, match_rule_name ] description: description: - - The description for the Subject Profile. + - The description for the match rule profile. type: str aliases: [ descr ] state: @@ -61,6 +61,45 @@ """ EXAMPLES = r""" +- name: Create a match rule + cisco.aci.aci_match_rule: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + state: present + delegate_to: localhost + +- name: Delete a match rule + cisco.aci.aci_match_rule: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + state: absent + delegate_to: localhost + +- name: Query all match rules + cisco.aci.aci_match_rule: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific match rule + cisco.aci.aci_match_rule: + host: apic + username: admin + password: SomeSecretPassword + match_rule: prod_match_rule + tenant: production + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -178,7 +217,7 @@ def main(): argument_spec.update(aci_owner_spec()) argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["name", "subject_name"]), # Not required for querying all objects + match_rule=dict(type="str", aliases=["name", "match_rule_name"]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), name_alias=dict(type="str"), state=dict(type="str", default="present", choices=["present", "absent", "query"]), @@ -188,12 +227,12 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["subject_profile", "tenant"]], - ["state", "present", ["subject_profile", "tenant"]], + ["state", "absent", ["match_rule", "tenant"]], + ["state", "present", ["match_rule", "tenant"]], ], ) - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") description = module.params.get("description") state = module.params.get("state") tenant = module.params.get("tenant") @@ -210,9 +249,9 @@ def main(): ), subclass_1=dict( aci_class="rtctrlSubjP", - aci_rn="subj-{0}".format(subject_profile), - module_object=subject_profile, - target_filter={"name": subject_profile}, + aci_rn="subj-{0}".format(match_rule), + module_object=match_rule, + target_filter={"name": match_rule}, ), ) @@ -222,7 +261,7 @@ def main(): aci.payload( aci_class="rtctrlSubjP", class_config=dict( - name=subject_profile, + name=match_rule, descr=description, nameAlias=name_alias, ), diff --git a/plugins/modules/aci_context_policy.py b/plugins/modules/aci_route_control_context.py similarity index 68% rename from plugins/modules/aci_context_policy.py rename to plugins/modules/aci_route_control_context.py index 5c7c71513..30ccac990 100644 --- a/plugins/modules/aci_context_policy.py +++ b/plugins/modules/aci_route_control_context.py @@ -12,10 +12,10 @@ DOCUMENTATION = r""" --- -module: aci_context_policy -short_description: Manage Route Context Policy (rtcrtl:CtxP) +module: aci_route_control_context +short_description: Manage Route Control Context (rtcrtl:CtxP) description: -- Manage Route Context Policies for the Route Control Profiles on Cisco ACI fabrics. +- Manage Route Control Context Policies for the Route Control Profiles on Cisco ACI fabrics. options: tenant: description: @@ -24,19 +24,20 @@ aliases: [ tenant_name ] l3out: description: - - Name of an existing L3Out. + - The name of an existing L3Out. + - To use only if the route control profile is linked to an existing L3Out. type: str aliases: [ l3out_name ] route_control_profile: description: - - Name of an existing route control profile. + - The name of an existing route control profile. type: str - aliases: [ rtctrl_profile_name ] - context_policy: + aliases: [ route_control_profile_name ] + route_control_context: description: - - Name of the context profile being created. + - The name of the route control context being created. type: str - aliases: [ name, context_name ] + aliases: [ name, route_control_context_name, context ] action: description: - The action required when the condition is met. @@ -44,26 +45,24 @@ choices: [ deny, permit ] action_rule: description: - - Name of the action rule profile to be associated with this route context policy. + - The name of the action rule profile to be associated with this route control context. - Set the rules for a Route Map. - - See module M(cisco.aci.aci_tenant_action_rule_profile). type: str aliases: [ action_rule_name ] - subject_profile: + match_rule: description: - - Name of the subject profile to be associated with this route context policy. + - The name of the match rule profile to be associated with this route control context. - Set the associated Matched rules. - - See module M(cisco.aci.aci_subject_profile). type: str - aliases: [ subject_name ] + aliases: [ match_rule_name ] order: description: - - The order of the policy context. + - The order of the route control context. - The value range from 0 to 9. type: int description: description: - - The description for the context policy. + - The description for the route control context. type: str aliases: [ descr ] state: @@ -85,8 +84,18 @@ notes: - The C(tenant) and the C(route_control_profile) used must exist before using this module in your playbook. The M(cisco.aci.aci_tenant) and the M(cisco.aci.aci_route_control_profile) modules can be used for this. +- If C(l3out) is used, the C(l3out) used must exist before using this module in your playbook. + The M(cisco.aci.aci_l3out) module can be used for this. +- if C(action_rule) is used, the C(action_rule) used must exist before using this module in your plabook. + The module M(cisco.aci.aci_tenant_action_rule_profile) can be used for this. +- if C(match_rule) is used, the C(match_rule) used must exist before using this module in your plabook. + The module M(cisco.aci.aci_match_rule) can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_route_control_profile +- module: cisco.aci.aci_l3out +- module: cisco.aci.aci_tenant_action_rule_profile +- module: cisco.aci.aci_match_rule - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:CtxP). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -95,6 +104,55 @@ """ EXAMPLES = r""" +- name: Create a route context policy + cisco.aci.aci_route_control_context: + host: apic + username: admin + password: SomeSecretPassword + route_control_context: prod_route_control_context + route_control_profile: prod_route_control_profile + tenant: production + l3out: prod_l3out + action: permit + order: 0 + action_rule: prod_action_rule_profile + match_rule: prod_match_rule + state: present + delegate_to: localhost + +- name: Delete a route context policy + cisco.aci.aci_route_control_context: + host: apic + username: admin + password: SomeSecretPassword + route_control_context: prod_route_control_context + route_control_profile: prod_route_control_profile + tenant: production + l3out: prod_l3out + state: absent + delegate_to: localhost + +- name: Query all route context policy + cisco.aci.aci_route_control_context: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific route context policy + cisco.aci.aci_route_control_profile: + host: apic + username: admin + password: SomeSecretPassword + route_control_context: prod_route_control_context + route_control_profile: prod_route_control_profile + tenant: production + l3out: prod_l3out + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -213,9 +271,9 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects - route_control_profile=dict(type="str", aliases=["rtctrl_profile_name"]), # Not required for querying all objects - context_policy=dict(type="str", aliases=["name", "context_name"]), # Not required for querying all objects - subject_profile=dict(type="str", aliases=["subject_name"]), + route_control_profile=dict(type="str", aliases=["route_control_profile_name"]), # Not required for querying all objects + route_control_context=dict(type="str", aliases=["name", "route_control_context_name", "context"]), # Not required for querying all objects + match_rule=dict(type="str", aliases=["match_rule_name"]), action_rule=dict(type="str", aliases=["action_rule_name"]), action=dict(type="str", choices=["deny", "permit"]), order=dict(type="int"), @@ -228,12 +286,12 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["context_policy", "tenant"]], - ["state", "present", ["context_policy", "tenant"]], + ["state", "absent", ["route_control_context", "tenant"]], + ["state", "present", ["route_control_context", "tenant"]], ], ) - context_policy = module.params.get("context_policy") + route_control_context = module.params.get("route_control_context") description = module.params.get("description") action = module.params.get("action") order = module.params.get("order") @@ -241,7 +299,7 @@ def main(): tenant = module.params.get("tenant") l3out = module.params.get("l3out") route_control_profile = module.params.get("route_control_profile") - subject_profile = module.params.get("subject_profile") + match_rule = module.params.get("match_rule") action_rule = module.params.get("action_rule") name_alias = module.params.get("name_alias") @@ -263,11 +321,11 @@ def main(): target_filter={"name": route_control_profile}, ) - context_policy_url_config = dict( + route_control_context_url_config = dict( aci_class="rtctrlCtxP", - aci_rn="ctx-{0}".format(context_policy), - module_object=context_policy, - target_filter={"name": context_policy}, + aci_rn="ctx-{0}".format(route_control_context), + module_object=route_control_context, + target_filter={"name": route_control_context}, ) if l3out is not None: @@ -280,14 +338,14 @@ def main(): target_filter={"name": l3out}, ), subclass_2=route_control_profile_url_config, - subclass_3=context_policy_url_config, + subclass_3=route_control_context_url_config, child_classes=child_classes, ) else: aci.construct_url( root_class=tenant_url_config, subclass_1=route_control_profile_url_config, - subclass_2=context_policy_url_config, + subclass_2=route_control_context_url_config, child_classes=child_classes, ) @@ -295,8 +353,8 @@ def main(): if state == "present": child_configs = [] - if subject_profile is not None: - child_configs.append({"rtctrlRsCtxPToSubjP": {"attributes": {"tnRtctrlSubjPName": subject_profile}}}) + if match_rule is not None: + child_configs.append({"rtctrlRsCtxPToSubjP": {"attributes": {"tnRtctrlSubjPName": match_rule}}}) if action_rule is not None: child_configs.append( { @@ -310,7 +368,7 @@ def main(): aci.payload( aci_class="rtctrlCtxP", class_config=dict( - name=context_policy, + name=route_control_context, descr=description, action=action, order=order, diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py index 18e9d2a84..c89095ec3 100644 --- a/plugins/modules/aci_route_control_profile.py +++ b/plugins/modules/aci_route_control_profile.py @@ -24,17 +24,18 @@ aliases: [ tenant_name ] l3out: description: - - Name of an existing L3Out. + - The name of an existing L3Out. + - This will link the created route control profile to the existing L3Out. type: str aliases: [ l3out_name ] route_control_profile: description: - - Name of the route control profile being created. + - The name of the route control profile being created. type: str - aliases: [ name, rtctrl_profile_name ] + aliases: [ name, route_control_profile_name ] auto_continue: description: - - Option to enable/disable auto-continue. + - The option to enable/disable auto-continue. type: str choices: [ "no", "yes" ] default: "no" @@ -68,8 +69,11 @@ notes: - The C(tenant) used must exist before using this module in your playbook. The M(cisco.aci.aci_tenant) module can be used for this. +- If C(l3out) is used, the C(l3out) used must exist before using this module in your playbook. + The M(cisco.aci.aci_l3out) module can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_l3out - name: APIC Management Information Model reference description: More information about the internal APIC class B(rtctrl:Profile). link: https://developer.cisco.com/docs/apic-mim-ref/ @@ -78,6 +82,50 @@ """ EXAMPLES = r""" +- name: Create a route control profile + cisco.aci.aci_route_control_profile: + host: apic + username: admin + password: SomeSecretPassword + route_control_profile: prod_route_control_profile + tenant: production + l3out: prod_l3out + auto_continue: "no" + policy_type: combinable + state: present + delegate_to: localhost + +- name: Delete a route control profile + cisco.aci.aci_route_control_profile: + host: apic + username: admin + password: SomeSecretPassword + route_control_profile: prod_route_control_profile + tenant: production + l3out: prod_l3out + state: absent + delegate_to: localhost + +- name: Query all route control profiles + cisco.aci.aci_route_control_profile: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result + +- name: Query a specific route control profile + cisco.aci.aci_route_control_profile: + host: apic + username: admin + password: SomeSecretPassword + route_control_profile: prod_route_control_profile + tenant: production + l3out: prod_l3out + state: query + delegate_to: localhost + register: query_result """ RETURN = r""" @@ -196,7 +244,7 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects l3out=dict(type="str", aliases=["l3out_name"]), # Not required for querying all objects - route_control_profile=dict(type="str", aliases=["name", "rtctrl_profile_name"]), # Not required for querying all objects + route_control_profile=dict(type="str", aliases=["name", "route_control_profile_name"]), # Not required for querying all objects description=dict(type="str", aliases=["descr"]), auto_continue=dict(type="str", default="no", choices=["no", "yes"]), policy_type=dict(type="str", default="combinable", choices=["combinable", "global"]), diff --git a/tests/integration/targets/aci_context_policy/tasks/main.yml b/tests/integration/targets/aci_context_policy/tasks/main.yml deleted file mode 100644 index fb06a562b..000000000 --- a/tests/integration/targets/aci_context_policy/tasks/main.yml +++ /dev/null @@ -1,196 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) - -# 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 - 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 - -# CLEAN ENVIRONMENT -- name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent - <<: *aci_info - tenant: ansible_tenant - state: absent - -- 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 - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: Add a new tenant - aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_tenant - description: Ansible tenant - state: present - - - name: Add a new action rule profile - aci_tenant_action_rule_profile: &aci_action_rule_present - <<: *aci_info - tenant: ansible_tenant - action_rule: ansible_action_rule - description: Ansible action rule profile for ansible_tenant tenant - state: present - - - name: Add a new L3Out - aci_l3out: - <<: *aci_info - tenant: ansible_tenant - l3out: ansible_l3out - description: Ansible l3Out for ansible_tenant tenant - domain: ansible_dom - vrf: ansible_vrf - state: present - - - name: Add route control profile for l3out - aci_route_control_profile: - <<: *aci_info - tenant: ansible_tenant - l3out: ansible_l3out - route_control_profile: ansible_rtctrl_profile_l3out - description: Ansible Route Control Profile for ansible_l3out l3Out - state: present - - - name: Add subject profile - aci_subject_profile: &aci_subject_profile_present - <<: *aci_info - tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: Ansible Subject Profile for ansible_tenant tenant - state: present - - - name: Add context policy for l3out (check_mode) - aci_context_policy: &aci_context_policy_present - <<: *aci_info - tenant: ansible_tenant - l3out: ansible_l3out - route_control_profile: ansible_rtctrl_profile_l3out - context_policy: ansible_context_policy_l3out - description: Ansible Context Policy for ansible_rtctrl_profile_l3out route control profile - subject_profile: ansible_subject_profile - action_rule: ansible_action_rule - action: deny - order: 5 - state: present - check_mode: true - register: cm_add_context_policy_l3out - - - name: Add context policy again (normal_mode) - aci_context_policy: - <<: *aci_context_policy_present - register: nm_add_context_policy_l3out - - - name: Add context policy again - testing idempotency - aci_context_policy: - <<: *aci_context_policy_present - register: nm_add_context_policy_l3out_idempotency - - - name: Add route control profile for tenant - aci_route_control_profile: - <<: *aci_info - tenant: ansible_tenant - route_control_profile: ansible_rtctrl_profile_tenant - description: Route Control Profile for ansible_tenant tenant - state: present - - - name: Add context policy for tenant - aci_context_policy: - <<: *aci_info - tenant: ansible_tenant - route_control_profile: ansible_rtctrl_profile_tenant - context_policy: ansible_context_policy_tenant - description: Ansible Context Policy for ansible_rtctrl_profile_tenant route control profile - state: present - register: nm_add_context_policy_tenant - - - name: Asserts for route control profiles creation tasks - assert: - that: - - cm_add_context_policy_l3out is changed - - cm_add_context_policy_l3out.previous == [] - - cm_add_context_policy_l3out.current == [] - - nm_add_context_policy_l3out is changed - - nm_add_context_policy_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_context_policy_l3out" - - nm_add_context_policy_l3out.current.0.rtctrlCtxP.attributes.action == "deny" - - nm_add_context_policy_l3out.current.0.rtctrlCtxP.attributes.order == "5" - - nm_add_context_policy_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tnRtctrlAttrPName == "ansible_action_rule" - - nm_add_context_policy_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tnRtctrlSubjPName == "ansible_subject_profile" - - nm_add_context_policy_l3out_idempotency is not changed - - nm_add_context_policy_tenant is changed - - nm_add_context_policy_tenant.previous == [] - - nm_add_context_policy_tenant.current.0.rtctrlCtxP.attributes.name == "ansible_context_policy_tenant" - - nm_add_context_policy_tenant.current.0.rtctrlCtxP.attributes.action == "permit" - - nm_add_context_policy_tenant.current.0.rtctrlCtxP.attributes.order == "0" - - - name: Query all context policy - aci_context_policy: - <<: *aci_info - state: query - register: query_all_context_policy - - - name: Query ansible_context_policy_l3out context policy - aci_context_policy: - <<: *aci_info - context_policy: ansible_context_policy_l3out - state: query - register: query_context_policy_l3out - - - name: Asserts query tasks - assert: - that: - - query_all_context_policy is not changed - - query_all_context_policy.current|length >= 2 - - query_context_policy_l3out is not changed - - query_context_policy_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_context_policy_l3out" - - query_context_policy_l3out.current.0.rtctrlCtxP.attributes.action == "deny" - - query_context_policy_l3out.current.0.rtctrlCtxP.attributes.order == "5" - - query_context_policy_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tDn == "uni/tn-ansible_tenant/attr-ansible_action_rule" - - query_context_policy_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tDn == "uni/tn-ansible_tenant/subj-ansible_subject_profile" - - - name: Remove context policy for l3out (check_mode) - aci_context_policy: &aci_context_policy_absent - <<: *aci_context_policy_present - state: absent - check_mode: true - register: cm_remove_context_policy - - - name: Remove context policy for l3out (normal_mode) - aci_context_policy: - <<: *aci_context_policy_absent - register: nm_remove_remove_context_policy - - - name: Remove route control profile for l3out - testing idempotency - aci_context_policy: - <<: *aci_context_policy_absent - register: nm_remove_context_policy_idempotency - - - name: Asserts deletion tasks - assert: - that: - - cm_remove_context_policy is changed - - cm_remove_context_policy.proposed == {} - - nm_remove_remove_context_policy is changed - - nm_remove_remove_context_policy.previous != [] - - nm_remove_remove_context_policy.method == "DELETE" - - nm_remove_context_policy_idempotency is not changed - - nm_remove_context_policy_idempotency.previous == [] - - - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: - <<: *aci_tenant_present - state: absent diff --git a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml index 466fcd405..c513a05da 100644 --- a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml @@ -39,22 +39,22 @@ description: Ansible tenant state: present - - name: Add a subject profile - aci_subject_profile: + - name: Add a match rule profile + aci_match_rule: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: subject profile for ansible_tenant tenant + match_rule: ansible_match_rule + description: match rule profile for ansible_tenant tenant state: present - register: cm_add_subject_profile + register: cm_add_match_rule - name: Add a match regex AS-Path term (check_mode) aci_match_as_path_regex_term: &aci_match_as_path_regex_term_present <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_as_path_regex_term: ansible_match_as_path_regex_term_1 - description: match regex AS-Path term 1 for ansible_subject_profile subject profile + description: match regex AS-Path term 1 for ansible_match_rule match rule profile regex: .* state: present check_mode: true @@ -74,9 +74,9 @@ aci_match_as_path_regex_term: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_as_path_regex_term: ansible_match_as_path_regex_term_2 - description: match regex AS-Path term 2 for ansible_subject_profile subject profile + description: match regex AS-Path term 2 for ansible_match_rule match rule profile state: present register: nm_add_match_as_path_regex_term_2 diff --git a/tests/integration/targets/aci_match_community_factor/tasks/main.yml b/tests/integration/targets/aci_match_community_factor/tasks/main.yml index 28f2c68aa..be13ce733 100644 --- a/tests/integration/targets/aci_match_community_factor/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_factor/tasks/main.yml @@ -39,28 +39,28 @@ description: Ansible tenant state: present - - name: Add a subject profile - aci_subject_profile: + - name: Add a match rule profile + aci_match_rule: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: subject profile for ansible_tenant tenant + match_rule: ansible_match_rule + description: match rule profile for ansible_tenant tenant state: present - name: Add a match community term aci_match_community_term: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_community_term: ansible_match_community_term - description: match community term for ansible_subject_profile subject profile + description: match community term for ansible_match_rule match rule profile state: present - name: Add a match community factor (check_mode) aci_match_community_factor: &aci_match_community_factor_present <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_community_term: ansible_match_community_term community: regular:as2-nn2:4:15 scope: non-transitive @@ -83,7 +83,7 @@ aci_match_community_factor: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_community_term: ansible_match_community_term community: regular:as2-nn2:4:16 description: match community factor 2 for ansible_match_community_term diff --git a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml index 9e9bf654f..9c08c39ff 100644 --- a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml @@ -39,22 +39,22 @@ description: Ansible tenant state: present - - name: Add a subject profile - aci_subject_profile: + - name: Add a match rule profile + aci_match_rule: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: subject profile for ansible_tenant tenant + match_rule: ansible_match_rule + description: match rule profile for ansible_tenant tenant state: present - register: cm_add_subject_profile + register: cm_add_match_rule - name: Add a match community regex term (check_mode) aci_match_community_regex_term: &aci_match_community_regex_term_present <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule name: ansible_community_regex_extended - description: match extended community regex term for ansible_subject_profile subject profile + description: match extended community regex term for ansible_match_rule match rule profile community_type: extended regex: .* state: present @@ -75,8 +75,8 @@ aci_match_community_regex_term: &aci_match_community_regex_term_2_present <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: match regular community regex term for ansible_subject_profile subject profile + match_rule: ansible_match_rule + description: match regular community regex term for ansible_match_rule match rule profile state: present register: nm_add_match_community_regex_term_2 diff --git a/tests/integration/targets/aci_match_community_term/tasks/main.yml b/tests/integration/targets/aci_match_community_term/tasks/main.yml index 7e619206e..072b8a16e 100644 --- a/tests/integration/targets/aci_match_community_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_term/tasks/main.yml @@ -39,22 +39,22 @@ description: Ansible tenant state: present - - name: Add a subject profile - aci_subject_profile: + - name: Add a match rule profile + aci_match_rule: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: subject profile for ansible_tenant tenant + match_rule: ansible_match_rule + description: match rule profile for ansible_tenant tenant state: present - register: cm_add_subject_profile + register: cm_add_match_rule - name: Add a match community term (check_mode) aci_match_community_term: &aci_match_community_term_present <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_community_term: ansible_match_community_term_1 - description: match community term 1 for ansible_subject_profile subject profile + description: match community term 1 for ansible_match_rule match rule profile state: present check_mode: true register: cm_add_match_community_term @@ -73,9 +73,9 @@ aci_match_community_term: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule match_community_term: ansible_match_community_term_2 - description: match community term 2 for ansible_subject_profile subject profile + description: match community term 2 for ansible_match_rule match rule profile state: present register: nm_add_match_community_term_2 diff --git a/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/tests/integration/targets/aci_match_route_destination/tasks/main.yml index 3a57570a8..37b69f135 100644 --- a/tests/integration/targets/aci_match_route_destination/tasks/main.yml +++ b/tests/integration/targets/aci_match_route_destination/tasks/main.yml @@ -39,21 +39,21 @@ description: Ansible tenant state: present - - name: Add a subject profile - aci_subject_profile: + - name: Add a match rule profile + aci_match_rule: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile + match_rule: ansible_match_rule description: subject profile for ansible_tenant tenant state: present - register: cm_add_subject_profile + register: cm_add_match_rule - name: Add a match route destination rule (check_mode) aci_match_route_destination: &aci_match_route_destination_present <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: match route destination rule 1 for ansible_subject_profile subject profile + match_rule: ansible_match_rule + description: match route destination rule 1 for ansible_match_rule match rule profile ip: 11.11.11.11/24 aggregate: yes from_prefix_lenght: 0 @@ -76,8 +76,8 @@ aci_match_route_destination: <<: *aci_info tenant: ansible_tenant - subject_profile: ansible_subject_profile - description: match route destination rule 2 for ansible_subject_profile subject profile + match_rule: ansible_match_rule + description: match route destination rule 2 for ansible_match_rule match rule profile ip: 11.11.11.12/24 state: present register: nm_add_match_route_destination_2 diff --git a/tests/integration/targets/aci_context_policy/aliases b/tests/integration/targets/aci_match_rule/aliases similarity index 100% rename from tests/integration/targets/aci_context_policy/aliases rename to tests/integration/targets/aci_match_rule/aliases diff --git a/tests/integration/targets/aci_match_rule/tasks/main.yml b/tests/integration/targets/aci_match_rule/tasks/main.yml new file mode 100644 index 000000000..9c8f2974c --- /dev/null +++ b/tests/integration/targets/aci_match_rule/tasks/main.yml @@ -0,0 +1,135 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a match rule profile (check_mode) + aci_match_rule: &aci_match_rule_present + <<: *aci_info + tenant: ansible_tenant + match_rule: ansible_match_rule_1 + description: match rule profile 1 for ansible_tenant tenant + state: present + check_mode: true + register: cm_add_match_rule + + - name: Add a match rule profile (normal_mode) + aci_match_rule: + <<: *aci_match_rule_present + register: nm_add_match_rule + + - name: Add the first match rule profile again - testing idempotency + aci_match_rule: + <<: *aci_match_rule_present + register: nm_add_match_rule_idempotency + + - name: Add a second match rule profile (normal_mode) + aci_match_rule: + <<: *aci_info + tenant: ansible_tenant + match_rule: ansible_match_rule_2 + description: match rule profile 2 for ansible_tenant tenant + state: present + register: nm_add_match_rule_2 + + - name: Asserts for match rule profiles creation tasks + assert: + that: + - cm_add_match_rule is changed + - cm_add_match_rule.previous == [] + - cm_add_match_rule.current == [] + - nm_add_match_rule is changed + - nm_add_match_rule.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_1" + - nm_add_match_rule_idempotency is not changed + - nm_add_match_rule_2 is changed + - nm_add_match_rule_2.previous == [] + - nm_add_match_rule_2.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_2" + + - name: Query all match rule profiles + aci_match_rule: + <<: *aci_info + state: query + register: query_all_match_rule + + - name: Query ansible_match_rule_1 + aci_match_rule: + <<: *aci_match_rule_present + state: query + register: query_ansible_match_rule_1 + + - name: Asserts query tasks + assert: + that: + - query_all_match_rule is not changed + - query_all_match_rule.current|length >= 2 + - query_ansible_match_rule_1 is not changed + - query_ansible_match_rule_1.current.0.rtctrlSubjP.attributes.name == "ansible_match_rule_1" + + - name: Remove match rule profile for l3out (check_mode) + aci_match_rule: &match_rule_absent + <<: *aci_match_rule_present + state: absent + check_mode: true + register: cm_remove_match_rule + + - name: Remove match rule profile for l3out (normal_mode) + aci_match_rule: + <<: *match_rule_absent + register: nm_remove_match_rule + + - name: Remove match rule profile for l3out - testing idempotency + aci_match_rule: + <<: *match_rule_absent + register: nm_remove_match_rule_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_match_rule is changed + - cm_remove_match_rule.proposed == {} + - nm_remove_match_rule is changed + - nm_remove_match_rule.previous != [] + - nm_remove_match_rule.method == "DELETE" + - nm_remove_match_rule_idempotency is not changed + - nm_remove_match_rule_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/tests/integration/targets/aci_subject_profile/aliases b/tests/integration/targets/aci_route_control_context/aliases similarity index 100% rename from tests/integration/targets/aci_subject_profile/aliases rename to tests/integration/targets/aci_route_control_context/aliases diff --git a/tests/integration/targets/aci_route_control_context/tasks/main.yml b/tests/integration/targets/aci_route_control_context/tasks/main.yml new file mode 100644 index 000000000..eb31da780 --- /dev/null +++ b/tests/integration/targets/aci_route_control_context/tasks/main.yml @@ -0,0 +1,196 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Gaspard Micol (@gmicol) + +# 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 + 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 + +# CLEAN ENVIRONMENT +- name: Remove the ansible_tenant + aci_tenant: &aci_tenant_absent + <<: *aci_info + tenant: ansible_tenant + state: absent + +- 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 + when: query_cloud.current == [] # This condition will execute only non-cloud sites + block: # block specifies execution of tasks within, based on conditions + - name: Add a new tenant + aci_tenant: &aci_tenant_present + <<: *aci_info + tenant: ansible_tenant + description: Ansible tenant + state: present + + - name: Add a new action rule profile + aci_tenant_action_rule_profile: &aci_action_rule_present + <<: *aci_info + tenant: ansible_tenant + action_rule: ansible_action_rule + description: Ansible action rule profile for ansible_tenant tenant + state: present + + - name: Add a new L3Out + aci_l3out: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + description: Ansible l3Out for ansible_tenant tenant + domain: ansible_dom + vrf: ansible_vrf + state: present + + - name: Add a route control profile for l3out + aci_route_control_profile: + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + route_control_profile: ansible_rtctrl_profile_l3out + description: Ansible Route Control Profile for ansible_l3out l3Out + state: present + + - name: Add a subject profile + aci_match_rule: &aci_match_rule_present + <<: *aci_info + tenant: ansible_tenant + match_rule: ansible_match_rule + description: Ansible Subject Profile for ansible_tenant tenant + state: present + + - name: Add a route control context policy for l3out (check_mode) + aci_route_control_context: &aci_route_control_context_present + <<: *aci_info + tenant: ansible_tenant + l3out: ansible_l3out + route_control_profile: ansible_rtctrl_profile_l3out + route_control_context: ansible_route_control_context_l3out + description: Ansible route control Context Policy for ansible_rtctrl_profile_l3out route control profile + match_rule: ansible_match_rule + action_rule: ansible_action_rule + action: deny + order: 5 + state: present + check_mode: true + register: cm_add_route_control_context_l3out + + - name: Add a route control context policy again (normal_mode) + aci_route_control_context: + <<: *aci_route_control_context_present + register: nm_add_route_control_context_l3out + + - name: Add a route control context policy again - testing idempotency + aci_route_control_context: + <<: *aci_route_control_context_present + register: nm_add_route_control_context_l3out_idempotency + + - name: Add a route control profile for tenant + aci_route_control_profile: + <<: *aci_info + tenant: ansible_tenant + route_control_profile: ansible_rtctrl_profile_tenant + description: Route Control Profile for ansible_tenant tenant + state: present + + - name: Add a route control context policy for tenant + aci_route_control_context: + <<: *aci_info + tenant: ansible_tenant + route_control_profile: ansible_rtctrl_profile_tenant + route_control_context: ansible_route_control_context_tenant + description: Ansible route control Context Policy for ansible_rtctrl_profile_tenant route control profile + state: present + register: nm_add_route_control_context_tenant + + - name: Asserts for route control profiles creation tasks + assert: + that: + - cm_add_route_control_context_l3out is changed + - cm_add_route_control_context_l3out.previous == [] + - cm_add_route_control_context_l3out.current == [] + - nm_add_route_control_context_l3out is changed + - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_route_control_context_l3out" + - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.attributes.action == "deny" + - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.attributes.order == "5" + - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tnRtctrlAttrPName == "ansible_action_rule" + - nm_add_route_control_context_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tnRtctrlSubjPName == "ansible_match_rule" + - nm_add_route_control_context_l3out_idempotency is not changed + - nm_add_route_control_context_tenant is changed + - nm_add_route_control_context_tenant.previous == [] + - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.name == "ansible_route_control_context_tenant" + - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.action == "permit" + - nm_add_route_control_context_tenant.current.0.rtctrlCtxP.attributes.order == "0" + + - name: Query all route control context policies + aci_route_control_context: + <<: *aci_info + state: query + register: query_all_route_control_context + + - name: Query ansible_route_control_context_l3out route control context policy + aci_route_control_context: + <<: *aci_info + route_control_context: ansible_route_control_context_l3out + state: query + register: query_route_control_context_l3out + + - name: Asserts query tasks + assert: + that: + - query_all_route_control_context is not changed + - query_all_route_control_context.current|length >= 2 + - query_route_control_context_l3out is not changed + - query_route_control_context_l3out.current.0.rtctrlCtxP.attributes.name == "ansible_route_control_context_l3out" + - query_route_control_context_l3out.current.0.rtctrlCtxP.attributes.action == "deny" + - query_route_control_context_l3out.current.0.rtctrlCtxP.attributes.order == "5" + - query_route_control_context_l3out.current.0.rtctrlCtxP.children.0.rtctrlScope.children.0.rtctrlRsScopeToAttrP.attributes.tDn == "uni/tn-ansible_tenant/attr-ansible_action_rule" + - query_route_control_context_l3out.current.0.rtctrlCtxP.children.1.rtctrlRsCtxPToSubjP.attributes.tDn == "uni/tn-ansible_tenant/subj-ansible_match_rule" + + - name: Remove route control context policy for l3out (check_mode) + aci_route_control_context: &aci_route_control_context_absent + <<: *aci_route_control_context_present + state: absent + check_mode: true + register: cm_remove_route_control_context + + - name: Remove route control context policy for l3out (normal_mode) + aci_route_control_context: + <<: *aci_route_control_context_absent + register: nm_remove_remove_route_control_context + + - name: Remove route control profile for l3out - testing idempotency + aci_route_control_context: + <<: *aci_route_control_context_absent + register: nm_remove_route_control_context_idempotency + + - name: Asserts deletion tasks + assert: + that: + - cm_remove_route_control_context is changed + - cm_remove_route_control_context.proposed == {} + - nm_remove_remove_route_control_context is changed + - nm_remove_remove_route_control_context.previous != [] + - nm_remove_remove_route_control_context.method == "DELETE" + - nm_remove_route_control_context_idempotency is not changed + - nm_remove_route_control_context_idempotency.previous == [] + + - name: Remove the ansible_tenant - cleanup before ending tests + aci_tenant: + <<: *aci_tenant_present + state: absent diff --git a/tests/integration/targets/aci_subject_profile/tasks/main.yml b/tests/integration/targets/aci_subject_profile/tasks/main.yml deleted file mode 100644 index 51c1f423b..000000000 --- a/tests/integration/targets/aci_subject_profile/tasks/main.yml +++ /dev/null @@ -1,135 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) - -# 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 - 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 - -# CLEAN ENVIRONMENT -- name: Remove the ansible_tenant - aci_tenant: &aci_tenant_absent - <<: *aci_info - tenant: ansible_tenant - state: absent - -- 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 - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: Add a new tenant - aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_tenant - description: Ansible tenant - state: present - - - name: Add a subject profile (check_mode) - aci_subject_profile: &aci_subject_profile_present - <<: *aci_info - tenant: ansible_tenant - subject_profile: ansible_subject_profile_1 - description: subject profile 1 for ansible_tenant tenant - state: present - check_mode: true - register: cm_add_subject_profile - - - name: Add a subject profile (normal_mode) - aci_subject_profile: - <<: *aci_subject_profile_present - register: nm_add_subject_profile - - - name: Add the first subject profile again - testing idempotency - aci_subject_profile: - <<: *aci_subject_profile_present - register: nm_add_subject_profile_idempotency - - - name: Add a second subject profile (normal_mode) - aci_subject_profile: - <<: *aci_info - tenant: ansible_tenant - subject_profile: ansible_subject_profile_2 - description: subject profile 2 for ansible_tenant tenant - state: present - register: nm_add_subject_profile_2 - - - name: Asserts for subject profiles creation tasks - assert: - that: - - cm_add_subject_profile is changed - - cm_add_subject_profile.previous == [] - - cm_add_subject_profile.current == [] - - nm_add_subject_profile is changed - - nm_add_subject_profile.current.0.rtctrlSubjP.attributes.name == "ansible_subject_profile_1" - - nm_add_subject_profile_idempotency is not changed - - nm_add_subject_profile_2 is changed - - nm_add_subject_profile_2.previous == [] - - nm_add_subject_profile_2.current.0.rtctrlSubjP.attributes.name == "ansible_subject_profile_2" - - - name: Query all subject profiles - aci_subject_profile: - <<: *aci_info - state: query - register: query_all_subject_profile - - - name: Query ansible_subject_profile_1 - aci_subject_profile: - <<: *aci_subject_profile_present - state: query - register: query_ansible_subject_profile_1 - - - name: Asserts query tasks - assert: - that: - - query_all_subject_profile is not changed - - query_all_subject_profile.current|length >= 2 - - query_ansible_subject_profile_1 is not changed - - query_ansible_subject_profile_1.current.0.rtctrlSubjP.attributes.name == "ansible_subject_profile_1" - - - name: Remove subject profile for l3out (check_mode) - aci_subject_profile: &subject_profile_absent - <<: *aci_subject_profile_present - state: absent - check_mode: true - register: cm_remove_subject_profile - - - name: Remove subject profile for l3out (normal_mode) - aci_subject_profile: - <<: *subject_profile_absent - register: nm_remove_subject_profile - - - name: Remove subject profile for l3out - testing idempotency - aci_subject_profile: - <<: *subject_profile_absent - register: nm_remove_subject_profile_idempotency - - - name: Asserts deletion tasks - assert: - that: - - cm_remove_subject_profile is changed - - cm_remove_subject_profile.proposed == {} - - nm_remove_subject_profile is changed - - nm_remove_subject_profile.previous != [] - - nm_remove_subject_profile.method == "DELETE" - - nm_remove_subject_profile_idempotency is not changed - - nm_remove_subject_profile_idempotency.previous == [] - - - name: Remove the ansible_tenant - cleanup before ending tests - aci_tenant: - <<: *aci_tenant_present - state: absent From 585b59e0fa6cde6678872b563e470f94a6420c5e Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 5 Oct 2023 10:21:28 -0400 Subject: [PATCH 09/11] [ignore] Add Tim Cragg as author in the modules he worked on. --- plugins/modules/aci_match_route_destination.py | 2 ++ plugins/modules/aci_match_rule.py | 2 ++ plugins/modules/aci_route_control_context.py | 2 ++ plugins/modules/aci_route_control_profile.py | 2 ++ .../targets/aci_match_as_path_regex_term/tasks/main.yml | 2 +- .../targets/aci_match_community_factor/tasks/main.yml | 2 +- .../targets/aci_match_community_regex_term/tasks/main.yml | 2 +- .../targets/aci_match_community_term/tasks/main.yml | 2 +- .../targets/aci_match_route_destination/tasks/main.yml | 3 ++- tests/integration/targets/aci_match_rule/tasks/main.yml | 3 ++- .../targets/aci_route_control_context/tasks/main.yml | 3 ++- .../targets/aci_route_control_profile/tasks/main.yml | 3 ++- 12 files changed, 20 insertions(+), 8 deletions(-) diff --git a/plugins/modules/aci_match_route_destination.py b/plugins/modules/aci_match_route_destination.py index da6e73c5a..973d70561 100644 --- a/plugins/modules/aci_match_route_destination.py +++ b/plugins/modules/aci_match_route_destination.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # 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 @@ -78,6 +79,7 @@ link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Gaspard Micol (@gmicol) +- Tim Cragg (@timcragg) """ EXAMPLES = r""" diff --git a/plugins/modules/aci_match_rule.py b/plugins/modules/aci_match_rule.py index 0285c3a81..c412d2458 100644 --- a/plugins/modules/aci_match_rule.py +++ b/plugins/modules/aci_match_rule.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # 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 @@ -58,6 +59,7 @@ link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Gaspard Micol (@gmicol) +- Tim Cragg (@timcragg) """ EXAMPLES = r""" diff --git a/plugins/modules/aci_route_control_context.py b/plugins/modules/aci_route_control_context.py index 30ccac990..19993767a 100644 --- a/plugins/modules/aci_route_control_context.py +++ b/plugins/modules/aci_route_control_context.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # 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 @@ -101,6 +102,7 @@ link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Gaspard Micol (@gmicol) +- Tim Cragg (@timcragg) """ EXAMPLES = r""" diff --git a/plugins/modules/aci_route_control_profile.py b/plugins/modules/aci_route_control_profile.py index c89095ec3..496cce9b3 100644 --- a/plugins/modules/aci_route_control_profile.py +++ b/plugins/modules/aci_route_control_profile.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # 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 @@ -79,6 +80,7 @@ link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Gaspard Micol (@gmicol) +- Tim Cragg (@timcragg) """ EXAMPLES = r""" diff --git a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml index c513a05da..40fff6810 100644 --- a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_match_community_factor/tasks/main.yml b/tests/integration/targets/aci_match_community_factor/tasks/main.yml index be13ce733..ce377e73f 100644 --- a/tests/integration/targets/aci_match_community_factor/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_factor/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml index 9c08c39ff..3a64587b1 100644 --- a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_match_community_term/tasks/main.yml b/tests/integration/targets/aci_match_community_term/tasks/main.yml index 072b8a16e..5f21e960d 100644 --- a/tests/integration/targets/aci_match_community_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_term/tasks/main.yml @@ -1,5 +1,5 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/tests/integration/targets/aci_match_route_destination/tasks/main.yml index 37b69f135..c0e9a41d9 100644 --- a/tests/integration/targets/aci_match_route_destination/tasks/main.yml +++ b/tests/integration/targets/aci_match_route_destination/tasks/main.yml @@ -1,5 +1,6 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_match_rule/tasks/main.yml b/tests/integration/targets/aci_match_rule/tasks/main.yml index 9c8f2974c..ecef49ad7 100644 --- a/tests/integration/targets/aci_match_rule/tasks/main.yml +++ b/tests/integration/targets/aci_match_rule/tasks/main.yml @@ -1,5 +1,6 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_route_control_context/tasks/main.yml b/tests/integration/targets/aci_route_control_context/tasks/main.yml index eb31da780..9c1f496b3 100644 --- a/tests/integration/targets/aci_route_control_context/tasks/main.yml +++ b/tests/integration/targets/aci_route_control_context/tasks/main.yml @@ -1,5 +1,6 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) diff --git a/tests/integration/targets/aci_route_control_profile/tasks/main.yml b/tests/integration/targets/aci_route_control_profile/tasks/main.yml index a533cd229..c04c38efd 100644 --- a/tests/integration/targets/aci_route_control_profile/tasks/main.yml +++ b/tests/integration/targets/aci_route_control_profile/tasks/main.yml @@ -1,5 +1,6 @@ # Test code for the ACI modules -# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Gaspard Micol (@gmicol) +# Copyright: (c) 2023, Tim Cragg (@timcragg) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) From 3cb71c41e665e46ec03bd1e01fb55b23ab05c6b5 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Thu, 12 Oct 2023 12:53:52 -0400 Subject: [PATCH 10/11] [ignore] Modify documentation for march rule terms and test cases. --- plugins/modules/aci_match_as_path_regex_term.py | 8 ++++---- plugins/modules/aci_match_community_factor.py | 2 +- plugins/modules/aci_match_community_regex_term.py | 8 ++++---- plugins/modules/aci_match_community_term.py | 8 ++++---- .../targets/aci_match_as_path_regex_term/tasks/main.yml | 2 +- .../targets/aci_match_community_factor/tasks/main.yml | 2 +- .../targets/aci_match_community_regex_term/tasks/main.yml | 2 +- .../targets/aci_match_community_term/tasks/main.yml | 2 +- .../targets/aci_match_route_destination/tasks/main.yml | 2 +- tests/integration/targets/aci_match_rule/tasks/main.yml | 2 +- .../targets/aci_route_control_context/tasks/main.yml | 2 +- .../targets/aci_route_control_profile/tasks/main.yml | 2 +- 12 files changed, 21 insertions(+), 21 deletions(-) diff --git a/plugins/modules/aci_match_as_path_regex_term.py b/plugins/modules/aci_match_as_path_regex_term.py index 98d9cee02..a1779bb4d 100644 --- a/plugins/modules/aci_match_as_path_regex_term.py +++ b/plugins/modules/aci_match_as_path_regex_term.py @@ -71,7 +71,7 @@ """ EXAMPLES = r""" -- name: Create a match match AS-path regex term +- name: Create a match with AS-path regex term cisco.aci.match_as_path_regex_term: host: apic username: admin @@ -83,7 +83,7 @@ state: present delegate_to: localhost -- name: Delete a match match AS-path regex term +- name: Delete a match with AS-path regex term cisco.aci.match_as_path_regex_term: host: apic username: admin @@ -94,7 +94,7 @@ state: absent delegate_to: localhost -- name: Query all match AS-path regex terms +- name: Query all match with AS-path regex terms cisco.aci.match_as_path_regex_term: host: apic username: admin @@ -103,7 +103,7 @@ delegate_to: localhost register: query_result -- name: Query a specific match match AS-path regex term +- name: Query a specific match with AS-path regex term cisco.aci.match_as_path_regex_term: host: apic username: admin diff --git a/plugins/modules/aci_match_community_factor.py b/plugins/modules/aci_match_community_factor.py index 853cbc3e7..7be352159 100644 --- a/plugins/modules/aci_match_community_factor.py +++ b/plugins/modules/aci_match_community_factor.py @@ -40,7 +40,7 @@ description: - The item scope. - If the scope is transitive, this community may be passed between ASs. - - If the scope is Non transitive, this community should be carried only within the local AS. + - If the scope is non-transitive, this community should be carried only within the local AS. type: str choices: [ transitive, non-transitive ] description: diff --git a/plugins/modules/aci_match_community_regex_term.py b/plugins/modules/aci_match_community_regex_term.py index c76cd0cd9..2bbd89886 100644 --- a/plugins/modules/aci_match_community_regex_term.py +++ b/plugins/modules/aci_match_community_regex_term.py @@ -78,7 +78,7 @@ """ EXAMPLES = r""" -- name: Create a match comunity regex term +- name: Create a match with comunity regex term cisco.aci.match_community_regex_term: host: apic username: admin @@ -91,7 +91,7 @@ state: present delegate_to: localhost -- name: Delete a match comunity regex term +- name: Delete a match with comunity regex term cisco.aci.match_community_regex_term: host: apic username: admin @@ -102,7 +102,7 @@ state: absent delegate_to: localhost -- name: Query all match rule commmuntiy regex terms +- name: Query all match with commmuntiy regex terms cisco.aci.match_community_regex_term: host: apic username: admin @@ -111,7 +111,7 @@ delegate_to: localhost register: query_result -- name: Query a specific match comunity regex term +- name: Query a specific match with comunity regex term cisco.aci.match_community_regex_term: host: apic username: admin diff --git a/plugins/modules/aci_match_community_term.py b/plugins/modules/aci_match_community_term.py index eb2004e8f..f5357792e 100644 --- a/plugins/modules/aci_match_community_term.py +++ b/plugins/modules/aci_match_community_term.py @@ -67,7 +67,7 @@ """ EXAMPLES = r""" -- name: Create a match match AS-path regex term +- name: Create a match with community term cisco.aci.match_community_term: host: apic username: admin @@ -78,7 +78,7 @@ state: present delegate_to: localhost -- name: Delete a match match AS-path regex term +- name: Delete a match with community term cisco.aci.match_community_term: host: apic username: admin @@ -89,7 +89,7 @@ state: absent delegate_to: localhost -- name: Query all match AS-path regex terms +- name: Query all with community terms cisco.aci.match_community_term: host: apic username: admin @@ -98,7 +98,7 @@ delegate_to: localhost register: query_result -- name: Query a specific match match AS-path regex term +- name: Query a specific match with community term cisco.aci.match_community_term: host: apic username: admin diff --git a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml index 40fff6810..cdabd8b4e 100644 --- a/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_as_path_regex_term/tasks/main.yml @@ -128,7 +128,7 @@ <<: *match_as_path_regex_term_absent register: nm_remove_match_as_path_regex_term - - name: Remove match regex AS-Path term for l3out - testing idempotency + - name: Remove match regex AS-Path term for l3out again - testing previous Removal aci_match_as_path_regex_term: <<: *match_as_path_regex_term_absent register: nm_remove_match_as_path_regex_term_idempotency diff --git a/tests/integration/targets/aci_match_community_factor/tasks/main.yml b/tests/integration/targets/aci_match_community_factor/tasks/main.yml index ce377e73f..2cc1f3ac1 100644 --- a/tests/integration/targets/aci_match_community_factor/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_factor/tasks/main.yml @@ -135,7 +135,7 @@ <<: *match_community_term_absent register: nm_remove_match_community_factor - - name: Remove match community factor - testing idempotency + - name: Remove match community factor again - testing previous Removal aci_match_community_factor: <<: *match_community_term_absent register: nm_remove_match_community_factor_idempotency diff --git a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml index 3a64587b1..c0b12c78c 100644 --- a/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_regex_term/tasks/main.yml @@ -130,7 +130,7 @@ <<: *match_community_regex_term_absent register: nm_remove_match_community_regex_term - - name: Remove match community regex term - testing idempotency + - name: Remove match community regex term again - testing previous Removal aci_match_community_regex_term: <<: *match_community_regex_term_absent register: nm_remove_match_community_regex_term_idempotency diff --git a/tests/integration/targets/aci_match_community_term/tasks/main.yml b/tests/integration/targets/aci_match_community_term/tasks/main.yml index 5f21e960d..aecf89096 100644 --- a/tests/integration/targets/aci_match_community_term/tasks/main.yml +++ b/tests/integration/targets/aci_match_community_term/tasks/main.yml @@ -124,7 +124,7 @@ <<: *match_community_term_absent register: nm_remove_match_community_term - - name: Remove match community term - testing idempotency + - name: Remove match community term again - testing previous Removal aci_match_community_term: <<: *match_community_term_absent register: nm_remove_match_community_term_idempotency diff --git a/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/tests/integration/targets/aci_match_route_destination/tasks/main.yml index c0e9a41d9..bea0ce0dd 100644 --- a/tests/integration/targets/aci_match_route_destination/tasks/main.yml +++ b/tests/integration/targets/aci_match_route_destination/tasks/main.yml @@ -137,7 +137,7 @@ <<: *match_route_destination_absent register: nm_remove_match_route_destination - - name: Remove match route destination rule - testing idempotency + - name: Remove match route destination rule again - testing previous Removal aci_match_route_destination: <<: *match_route_destination_absent register: nm_remove_match_route_destination_idempotency diff --git a/tests/integration/targets/aci_match_rule/tasks/main.yml b/tests/integration/targets/aci_match_rule/tasks/main.yml index ecef49ad7..23509494c 100644 --- a/tests/integration/targets/aci_match_rule/tasks/main.yml +++ b/tests/integration/targets/aci_match_rule/tasks/main.yml @@ -114,7 +114,7 @@ <<: *match_rule_absent register: nm_remove_match_rule - - name: Remove match rule profile for l3out - testing idempotency + - name: Remove match rule profile for l3out again - testing previous Removal aci_match_rule: <<: *match_rule_absent register: nm_remove_match_rule_idempotency diff --git a/tests/integration/targets/aci_route_control_context/tasks/main.yml b/tests/integration/targets/aci_route_control_context/tasks/main.yml index 9c1f496b3..83f46e4b8 100644 --- a/tests/integration/targets/aci_route_control_context/tasks/main.yml +++ b/tests/integration/targets/aci_route_control_context/tasks/main.yml @@ -175,7 +175,7 @@ <<: *aci_route_control_context_absent register: nm_remove_remove_route_control_context - - name: Remove route control profile for l3out - testing idempotency + - name: Remove route control profile for l3out again - testing previous Removal aci_route_control_context: <<: *aci_route_control_context_absent register: nm_remove_route_control_context_idempotency diff --git a/tests/integration/targets/aci_route_control_profile/tasks/main.yml b/tests/integration/targets/aci_route_control_profile/tasks/main.yml index c04c38efd..db0022100 100644 --- a/tests/integration/targets/aci_route_control_profile/tasks/main.yml +++ b/tests/integration/targets/aci_route_control_profile/tasks/main.yml @@ -123,7 +123,7 @@ <<: *route_control_profile_absent register: nm_remove_route_control_profile - - name: Remove route control profile for l3out - testing idempotency + - name: Remove route control profile for l3out again - testing previous Removal aci_route_control_profile: <<: *route_control_profile_absent register: nm_remove_route_control_profile_idempotency From 04e8886be826259da841fc259661709d0ce575a8 Mon Sep 17 00:00:00 2001 From: Gaspard Micol Date: Tue, 24 Oct 2023 13:48:37 -0400 Subject: [PATCH 11/11] [ignore] Update the examples in match rules modules. --- plugins/modules/aci_match_as_path_regex_term.py | 8 ++++---- plugins/modules/aci_match_community_factor.py | 8 ++++---- plugins/modules/aci_match_community_regex_term.py | 8 ++++---- plugins/modules/aci_match_community_term.py | 8 ++++---- .../targets/aci_match_route_destination/tasks/main.yml | 4 ++-- 5 files changed, 18 insertions(+), 18 deletions(-) diff --git a/plugins/modules/aci_match_as_path_regex_term.py b/plugins/modules/aci_match_as_path_regex_term.py index a1779bb4d..bb87acaa5 100644 --- a/plugins/modules/aci_match_as_path_regex_term.py +++ b/plugins/modules/aci_match_as_path_regex_term.py @@ -72,7 +72,7 @@ EXAMPLES = r""" - name: Create a match with AS-path regex term - cisco.aci.match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: host: apic username: admin password: SomeSecretPassword @@ -84,7 +84,7 @@ delegate_to: localhost - name: Delete a match with AS-path regex term - cisco.aci.match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: host: apic username: admin password: SomeSecretPassword @@ -95,7 +95,7 @@ delegate_to: localhost - name: Query all match with AS-path regex terms - cisco.aci.match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: host: apic username: admin password: SomeSecretPassword @@ -104,7 +104,7 @@ register: query_result - name: Query a specific match with AS-path regex term - cisco.aci.match_as_path_regex_term: + cisco.aci.aci_match_as_path_regex_term: host: apic username: admin password: SomeSecretPassword diff --git a/plugins/modules/aci_match_community_factor.py b/plugins/modules/aci_match_community_factor.py index 7be352159..8db4e6e71 100644 --- a/plugins/modules/aci_match_community_factor.py +++ b/plugins/modules/aci_match_community_factor.py @@ -80,7 +80,7 @@ EXAMPLES = r""" - name: Create a match match AS-path regex term - cisco.aci.match_community_term: + cisco.aci.aci_match_community_factor: host: apic username: admin password: SomeSecretPassword @@ -93,7 +93,7 @@ delegate_to: localhost - name: Delete a match match AS-path regex term - cisco.aci.match_community_term: + cisco.aci.aci_match_community_factor: host: apic username: admin password: SomeSecretPassword @@ -105,7 +105,7 @@ delegate_to: localhost - name: Query all match AS-path regex terms - cisco.aci.match_community_term: + cisco.aci.aci_match_community_factor: host: apic username: admin password: SomeSecretPassword @@ -114,7 +114,7 @@ register: query_result - name: Query a specific match match AS-path regex term - cisco.aci.match_community_term: + cisco.aci.aci_match_community_factor: host: apic username: admin password: SomeSecretPassword diff --git a/plugins/modules/aci_match_community_regex_term.py b/plugins/modules/aci_match_community_regex_term.py index 2bbd89886..1b2d0007a 100644 --- a/plugins/modules/aci_match_community_regex_term.py +++ b/plugins/modules/aci_match_community_regex_term.py @@ -79,7 +79,7 @@ EXAMPLES = r""" - name: Create a match with comunity regex term - cisco.aci.match_community_regex_term: + cisco.aci.aci_match_community_regex_term: host: apic username: admin password: SomeSecretPassword @@ -92,7 +92,7 @@ delegate_to: localhost - name: Delete a match with comunity regex term - cisco.aci.match_community_regex_term: + cisco.aci.aci_match_community_regex_term: host: apic username: admin password: SomeSecretPassword @@ -103,7 +103,7 @@ delegate_to: localhost - name: Query all match with commmuntiy regex terms - cisco.aci.match_community_regex_term: + cisco.aci.aci_match_community_regex_term: host: apic username: admin password: SomeSecretPassword @@ -112,7 +112,7 @@ register: query_result - name: Query a specific match with comunity regex term - cisco.aci.match_community_regex_term: + cisco.aci.aci_match_community_regex_term: host: apic username: admin password: SomeSecretPassword diff --git a/plugins/modules/aci_match_community_term.py b/plugins/modules/aci_match_community_term.py index f5357792e..21a3f35db 100644 --- a/plugins/modules/aci_match_community_term.py +++ b/plugins/modules/aci_match_community_term.py @@ -68,7 +68,7 @@ EXAMPLES = r""" - name: Create a match with community term - cisco.aci.match_community_term: + cisco.aci.aci_match_community_term: host: apic username: admin password: SomeSecretPassword @@ -79,7 +79,7 @@ delegate_to: localhost - name: Delete a match with community term - cisco.aci.match_community_term: + cisco.aci.aci_match_community_term: host: apic username: admin password: SomeSecretPassword @@ -90,7 +90,7 @@ delegate_to: localhost - name: Query all with community terms - cisco.aci.match_community_term: + cisco.aci.aci_match_community_term: host: apic username: admin password: SomeSecretPassword @@ -99,7 +99,7 @@ register: query_result - name: Query a specific match with community term - cisco.aci.match_community_term: + cisco.aci.aci_match_community_term: host: apic username: admin password: SomeSecretPassword diff --git a/tests/integration/targets/aci_match_route_destination/tasks/main.yml b/tests/integration/targets/aci_match_route_destination/tasks/main.yml index bea0ce0dd..b4d49c2ff 100644 --- a/tests/integration/targets/aci_match_route_destination/tasks/main.yml +++ b/tests/integration/targets/aci_match_route_destination/tasks/main.yml @@ -57,8 +57,8 @@ description: match route destination rule 1 for ansible_match_rule match rule profile ip: 11.11.11.11/24 aggregate: yes - from_prefix_lenght: 0 - to_prefix_lenght: 32 + from_prefix_length: 0 + to_prefix_length: 32 state: present check_mode: true register: cm_add_match_route_destination