From 898c364805ccc0b28f8da162d335a196d1600b21 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Thu, 8 Jun 2023 17:21:10 -0500 Subject: [PATCH 01/30] [minor_change] add aci_vrf_leak_internal_subnet module --- .../modules/aci_vrf_leak_internal_subnet.py | 352 ++++++++++++++++++ .../aci_vrf_leak_internal_subnet/aliases | 0 .../tasks/main.yml | 58 +++ 3 files changed, 410 insertions(+) create mode 100644 plugins/modules/aci_vrf_leak_internal_subnet.py create mode 100644 tests/integration/targets/aci_vrf_leak_internal_subnet/aliases create mode 100644 tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py new file mode 100644 index 000000000..4505ef963 --- /dev/null +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -0,0 +1,352 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +# 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_vrf +short_description: Manage contexts or VRFs (fv:Ctx) +description: +- Manage contexts or VRFs on Cisco ACI fabrics. +- Each context is a private network associated to a tenant, i.e. VRF. +- Enable Preferred Groups for VRF +options: + tenant: + description: + - The name of the Tenant the VRF should belong to. + type: str + aliases: [ tenant_name ] + vrf: + description: + - The name of the VRF. + type: str + aliases: [ context, name, vrf_name ] + policy_control_direction: + description: + - Determines if the policy should be enforced by the fabric on ingress or egress. + type: str + choices: [ egress, ingress ] + policy_control_preference: + description: + - Determines if the fabric should enforce contract policies to allow routing and packet forwarding. + type: str + choices: [ enforced, unenforced ] + description: + description: + - The description for the VRF. + type: str + aliases: [ descr ] + ip_data_plane_learning: + description: + - Whether IP data plane learning is enabled or disabled. + - The APIC defaults to C(enabled) when unset during creation. + type: str + choices: [ enabled, disabled ] + aliases: [ ip_dataplane_learning ] + 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 + preferred_group: + description: + - Enables preferred groups for the VRF under vzAny + type: str + choices: [enabled, disabled] + match_type: + description: + - Configures match type for contracts under vzAny + type: str + choices: [ all, at_least_one, at_most_one, none] +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(fv:Ctx). + link: https://developer.cisco.com/docs/apic-mim-ref/ +author: +- Jacob McGill (@jmcgill298) +""" + +EXAMPLES = r""" +- name: Add a new VRF to a tenant + cisco.aci.aci_vrf: + host: apic + username: admin + password: SomeSecretPassword + vrf: vrf_lab + tenant: lab_tenant + descr: Lab VRF + policy_control_preference: enforced + policy_control_direction: ingress + state: present + delegate_to: localhost + +- name: Remove a VRF for a tenant + cisco.aci.aci_vrf: + host: apic + username: admin + password: SomeSecretPassword + vrf: vrf_lab + tenant: lab_tenant + state: absent + delegate_to: localhost + +- name: Query a VRF of a tenant + cisco.aci.aci_vrf: + host: apic + username: admin + password: SomeSecretPassword + vrf: vrf_lab + tenant: lab_tenant + state: query + delegate_to: localhost + register: query_result + +- name: Query all VRFs + cisco.aci.aci_vrf: + host: apic + username: admin + password: SomeSecretPassword + state: query + delegate_to: localhost + register: query_result +""" + +RETURN = r""" +current: + description: The existing configuration from the APIC after the module has finished + returned: success + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +error: + description: The error information as returned from the APIC + returned: failure + type: dict + sample: + { + "code": "122", + "text": "unknown managed object class foo" + } +raw: + description: The raw output returned by the APIC REST API (xml or json) + returned: parse error + type: str + sample: '' +sent: + description: The actual/minimal configuration pushed to the APIC + returned: info + type: list + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment" + } + } + } +previous: + description: The original configuration from the APIC before the module has started + returned: info + type: list + sample: + [ + { + "fvTenant": { + "attributes": { + "descr": "Production", + "dn": "uni/tn-production", + "name": "production", + "nameAlias": "", + "ownerKey": "", + "ownerTag": "" + } + } + } + ] +proposed: + description: The assembled configuration from the user-provided parameters + returned: info + type: dict + sample: + { + "fvTenant": { + "attributes": { + "descr": "Production environment", + "name": "production" + } + } + } +filter_string: + description: The filter string used for the request + returned: failure or debug + type: str + sample: ?rsp-prop-include=config-only +method: + description: The HTTP method used for the request to the APIC + returned: failure or debug + type: str + sample: POST +response: + description: The HTTP response from the APIC + returned: failure or debug + type: str + sample: OK (30 bytes) +status: + description: The HTTP status from the APIC + returned: failure or debug + type: int + sample: 200 +url: + description: The HTTP url used for the request to the APIC + returned: failure or debug + type: str + sample: https://10.11.12.13/api/mo/uni/tn-production.json +""" + +from ansible.module_utils.basic import AnsibleModule +from ansible_collections.cisco.aci.plugins.module_utils.aci import ACIModule, aci_argument_spec, aci_annotation_spec, aci_owner_spec + +MATCH_TYPE_MAPPING = dict( + all="All", + at_least_one="AtleastOne", + at_most_one="AtmostOne", + none="None", +) + + +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 + vrf=dict(type="str", aliases=["context", "name", "vrf_name"]), # Not required for querying all objects + leak_internal_subnet=dict(type="str", aliases=["leak_internal_subnet_name"]), + description=dict(type="str", aliases=["descr"]), + policy_control_direction=dict(type="str", choices=["egress", "ingress"]), + policy_control_preference=dict(type="str", choices=["enforced", "unenforced"]), + state=dict(type="str", default="present", choices=["absent", "present", "query"]), + preferred_group=dict(type="str", choices=["enabled", "disabled"]), + match_type=dict(type="str", choices=["all", "at_least_one", "at_most_one", "none"]), + name_alias=dict(type="str"), + scope=dict(type="str", default="private", choices=["public","private","shared"]), + ip=dict(type="str"), + ) + + module = AnsibleModule( + argument_spec=argument_spec, + supports_check_mode=True, + required_if=[ + ["state", "absent", ["tenant", "vrf","leak_internal_subnet"]], + ["state", "present", ["tenant", "vrf","leak_internal_subnet"]], + ], + ) + + description = module.params.get("description") + policy_control_direction = module.params.get("policy_control_direction") + policy_control_preference = module.params.get("policy_control_preference") + state = module.params.get("state") + tenant = module.params.get("tenant") + vrf = module.params.get("vrf") + leak_internal_subnet = module.params.get("leak_internal_subnet") + name_alias = module.params.get("name_alias") + #preferred_group = module.params.get("preferred_group") + match_type = module.params.get("match_type") + scope = module.params.get("scope") + ip = module.params.get("ip") + + if match_type is not None: + match_type = MATCH_TYPE_MAPPING[match_type] + + 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="fvCtx", + aci_rn="ctx-{0}".format(vrf), + module_object=vrf, + target_filter={"name": vrf}, + ), + subclass_2=dict( + aci_class="leakRoutes", + aci_rn="leakroutes", + module_object=True, + ), + subclass_3=dict( + aci_class="leakInternalSubnet", + aci_rn="leakintsubnet-[{0}]".format(ip), + module_object=ip, + ), + #child_classes=["leakTo"], + ) + + aci.get_existing() + + if state == "present": + #loop for child_config list of dict + child_configs = [] + """for key in leak_internal_subnet: + child_configs.append(leak_internal_subnet[key])""" + aci.payload( + aci_class="leakInternalSubnet", + class_config=dict( + descr=description, + ip=ip, + scope=scope, + nameAlias=name_alias, + ), + child_configs=child_configs, + ) + + aci.get_diff(aci_class="leakInternalSubnet") + + aci.post_config() + + elif state == "absent": + aci.delete_config() + + aci.exit_json() + + +if __name__ == "__main__": + main() diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases b/tests/integration/targets/aci_vrf_leak_internal_subnet/aliases new file mode 100644 index 000000000..e69de29bb diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml new file mode 100644 index 000000000..694b7b43a --- /dev/null +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -0,0 +1,58 @@ +# Test code for the ACI modules +# Copyright: (c) 2023, Abraham Mughal (@abmughal) + +# 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: ensure tenant exists for tests to kick off +# cisco.aci.aci_tenant: &aci_tenant_present +# 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 +# state: present +# tenant: ansible_test +# register: tenant_present + +# - name: create vrf - check mode works +# cisco.aci.aci_vrf: &aci_vrf_present +# <<: *aci_tenant_present +# vrf: anstest +# description: Ansible Test +# check_mode: true +# register: vrf_present_check_mode + +# - name: create vrf - creation works +# cisco.aci.aci_vrf: +# <<: *aci_vrf_present +# register: vrf_present + + +- name: create leakInternalSubnet + cisco.aci.aci_vrf_leak_internal_subnet: &aci_vrf_leakInternalSubnet + #<<: *aci_vrf_present + 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 + state: present + tenant: abmughal + vrf: test + leak_internal_subnet: leakintsubnet + description: Ansible Test + ip: 1.1.1.2 + check_mode: true + register: vrf_present_check_mode + +#uni/tn-abmughal/ctx-test/leakroutes/leakintsubnet-[1.1.1.1] +#uni/tn-ansible_test/ctx-anstest/leakroutes/leakintsubnet-1.1.1.1 From 1962f6b4fd7fcc66d24e9d002a7aaea8b5a4e42b Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Tue, 13 Jun 2023 13:22:47 -0500 Subject: [PATCH 02/30] added child configs --- .../modules/aci_vrf_leak_internal_subnet.py | 33 +++++++---- .../tasks/main.yml | 59 ++++++++++++++++--- 2 files changed, 73 insertions(+), 19 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 4505ef963..dd7364934 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -256,7 +256,13 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects vrf=dict(type="str", aliases=["context", "name", "vrf_name"]), # Not required for querying all objects - leak_internal_subnet=dict(type="str", aliases=["leak_internal_subnet_name"]), + leak_internal_subnet=dict( + type="list", + elements="dict", + options=dict( + ctxName=dict(type="str",aliases=["name"]), + ), + ), description=dict(type="str", aliases=["descr"]), policy_control_direction=dict(type="str", choices=["egress", "ingress"]), policy_control_preference=dict(type="str", choices=["enforced", "unenforced"]), @@ -278,14 +284,11 @@ def main(): ) description = module.params.get("description") - policy_control_direction = module.params.get("policy_control_direction") - policy_control_preference = module.params.get("policy_control_preference") state = module.params.get("state") tenant = module.params.get("tenant") vrf = module.params.get("vrf") leak_internal_subnet = module.params.get("leak_internal_subnet") name_alias = module.params.get("name_alias") - #preferred_group = module.params.get("preferred_group") match_type = module.params.get("match_type") scope = module.params.get("scope") ip = module.params.get("ip") @@ -317,16 +320,26 @@ def main(): aci_rn="leakintsubnet-[{0}]".format(ip), module_object=ip, ), - #child_classes=["leakTo"], + child_classes=["leakTo"], ) aci.get_existing() if state == "present": - #loop for child_config list of dict - child_configs = [] - """for key in leak_internal_subnet: - child_configs.append(leak_internal_subnet[key])""" + #loop for child_config list of dict + child_configs = [] + for subnet in leak_internal_subnet: + child_configs.append(dict(leakTo=dict( + attributes=dict( + ctxName=subnet.get("ctxName"), + rn="to-[{0}]-[{1}]".format(tenant,subnet.get("ctxName")), + scope=scope, + tenantName=tenant, + ) + ) + ) + ) + aci.payload( aci_class="leakInternalSubnet", class_config=dict( @@ -349,4 +362,4 @@ def main(): if __name__ == "__main__": - main() + main() \ No newline at end of file diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 694b7b43a..0f6a803d5 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -29,13 +29,34 @@ # check_mode: true # register: vrf_present_check_mode -# - name: create vrf - creation works -# cisco.aci.aci_vrf: -# <<: *aci_vrf_present -# register: vrf_present - +- name: create vrf - check mode works + cisco.aci.aci_vrf: &aci_vrf_present + 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 + state: present + tenant: abmughal + vrf: test2 + description: Ansible Test + check_mode: true + register: vrf_present_check_mode -- name: create leakInternalSubnet +- name: create vrf - creation works + cisco.aci.aci_vrf: + <<: *aci_vrf_present + register: vrf_present + +- name: create test3 - creation works + cisco.aci.aci_vrf: + <<: *aci_vrf_present + vrf: test3 + register: vrf_present + +- name: create leakInternalSubnet - check_mode cisco.aci.aci_vrf_leak_internal_subnet: &aci_vrf_leakInternalSubnet #<<: *aci_vrf_present host: "{{ aci_hostname }}" @@ -48,11 +69,31 @@ state: present tenant: abmughal vrf: test - leak_internal_subnet: leakintsubnet + leak_internal_subnet: + - ctxName: "test2" + - ctxName: "test3" description: Ansible Test ip: 1.1.1.2 check_mode: true register: vrf_present_check_mode -#uni/tn-abmughal/ctx-test/leakroutes/leakintsubnet-[1.1.1.1] -#uni/tn-ansible_test/ctx-anstest/leakroutes/leakintsubnet-1.1.1.1 +- name: create leakInternalSubnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_vrf_leakInternalSubnet + 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 + state: present + tenant: abmughal + vrf: test + leak_internal_subnet: + - ctxName: "test2" + - ctxName: "test3" + description: Ansible Test + ip: 1.1.1.2 + register: vrf_present + From dc74611a6bfffc13ba848a422499392214b14378 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 10:12:20 -0500 Subject: [PATCH 03/30] Added leakInternalSubnet module --- .../modules/aci_vrf_leak_internal_subnet.py | 99 +++++++++---------- .../tasks/main.yml | 96 +++++++++--------- 2 files changed, 94 insertions(+), 101 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index dd7364934..a18a3a3b3 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -11,12 +11,10 @@ DOCUMENTATION = r""" --- -module: aci_vrf -short_description: Manage contexts or VRFs (fv:Ctx) +module: aci_vrf_leak_internal_subnet +short_description: Manage contexts or VRFs (fv:leakInternalSubnet) description: -- Manage contexts or VRFs on Cisco ACI fabrics. -- Each context is a private network associated to a tenant, i.e. VRF. -- Enable Preferred Groups for VRF +- Manage leaking subnets under VRF. options: tenant: description: @@ -28,28 +26,11 @@ - The name of the VRF. type: str aliases: [ context, name, vrf_name ] - policy_control_direction: - description: - - Determines if the policy should be enforced by the fabric on ingress or egress. - type: str - choices: [ egress, ingress ] - policy_control_preference: - description: - - Determines if the fabric should enforce contract policies to allow routing and packet forwarding. - type: str - choices: [ enforced, unenforced ] description: description: - The description for the VRF. type: str aliases: [ descr ] - ip_data_plane_learning: - description: - - Whether IP data plane learning is enabled or disabled. - - The APIC defaults to C(enabled) when unset during creation. - type: str - choices: [ enabled, disabled ] - aliases: [ ip_dataplane_learning ] state: description: - Use C(present) or C(absent) for adding or removing. @@ -61,11 +42,6 @@ description: - The alias for the current object. This relates to the nameAlias field in ACI. type: str - preferred_group: - description: - - Enables preferred groups for the VRF under vzAny - type: str - choices: [enabled, disabled] match_type: description: - Configures match type for contracts under vzAny @@ -85,35 +61,40 @@ description: More information about the internal APIC class B(fv:Ctx). link: https://developer.cisco.com/docs/apic-mim-ref/ author: -- Jacob McGill (@jmcgill298) +- Abraham Mughal (@abmughal) """ EXAMPLES = r""" -- name: Add a new VRF to a tenant - cisco.aci.aci_vrf: +- name: Create leakInternalSubnet + cisco.aci.aci_vrf_leak_internal_subnet: host: apic username: admin password: SomeSecretPassword vrf: vrf_lab tenant: lab_tenant descr: Lab VRF - policy_control_preference: enforced - policy_control_direction: ingress state: present + leak_internal_subnet: + - ctxName: "test" + tenant: "lab_tenant" + description: Ansible Test + ip: 1.1.1.2 delegate_to: localhost -- name: Remove a VRF for a tenant - cisco.aci.aci_vrf: +- name: Remove a subnet from leaking + cisco.aci.aci_vrf_leak_internal_subnet: host: apic username: admin password: SomeSecretPassword vrf: vrf_lab tenant: lab_tenant - state: absent + leak_internal_subnet: "{{ fake_var | default(omit) }}" + description: Ansible Test + ip: 1.1.1.2 delegate_to: localhost -- name: Query a VRF of a tenant - cisco.aci.aci_vrf: +- name: Query leakInternalSubnet + cisco.aci.aci_vrf_leak_internal_subnet: host: apic username: admin password: SomeSecretPassword @@ -122,15 +103,6 @@ state: query delegate_to: localhost register: query_result - -- name: Query all VRFs - cisco.aci.aci_vrf: - host: apic - username: admin - password: SomeSecretPassword - state: query - delegate_to: localhost - register: query_result """ RETURN = r""" @@ -260,14 +232,12 @@ def main(): type="list", elements="dict", options=dict( - ctxName=dict(type="str",aliases=["name"]), + ctxName=dict(type="str"), + tenant=dict(type="str", aliases=["tenantName"]) ), ), description=dict(type="str", aliases=["descr"]), - policy_control_direction=dict(type="str", choices=["egress", "ingress"]), - policy_control_preference=dict(type="str", choices=["enforced", "unenforced"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), - preferred_group=dict(type="str", choices=["enabled", "disabled"]), match_type=dict(type="str", choices=["all", "at_least_one", "at_most_one", "none"]), name_alias=dict(type="str"), scope=dict(type="str", default="private", choices=["public","private","shared"]), @@ -325,20 +295,39 @@ def main(): aci.get_existing() - if state == "present": - #loop for child_config list of dict + if state == "present": child_configs = [] + + custom = [] + #for loop for customer configs, key is to-[tenant]-[ctxName] for subnet in leak_internal_subnet: + custom.append("to-[{0}]-[{1}]".format(subnet.get("tenant"),subnet.get("ctxName"))) child_configs.append(dict(leakTo=dict( attributes=dict( ctxName=subnet.get("ctxName"), - rn="to-[{0}]-[{1}]".format(tenant,subnet.get("ctxName")), + rn="to-[{0}]-[{1}]".format(subnet.get("tenant"),subnet.get("ctxName")), scope=scope, tenantName=tenant, + ) ) ) - ) - ) + ) + + #loop through existing and delete if it's found + if isinstance(aci.existing, list) and len(aci.existing) > 0: #if there are existing children + for child in aci.existing[0].get("leakInternalSubnet", {}).get("children", {}): + if child.get("leakTo") and "to-[{0}]-[{1}]".format(child.get("leakTo").get("attributes").get("tenantName"),child.get("leakTo").get("attributes").get("ctxName")) not in custom: + child_configs.append( + { + "leakTo": { + "attributes": { + "dn": "uni/tn-{0}/ctx-{1}/leakroutes/leakintsubnet-[{2}]/to-[{3}]-[{4}]".format(child.get("leakTo").get("attributes").get("tenantName"), vrf, ip,child.get("leakTo").get("attributes").get("tenantName"), + child.get("leakTo").get("attributes").get("ctxName")), + "status": "deleted" + } + } + } + ) aci.payload( aci_class="leakInternalSubnet", diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 0f6a803d5..705225d06 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -3,34 +3,13 @@ # 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: 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: ensure tenant exists for tests to kick off -# cisco.aci.aci_tenant: &aci_tenant_present -# 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 -# state: present -# tenant: ansible_test -# register: tenant_present - -# - name: create vrf - check mode works -# cisco.aci.aci_vrf: &aci_vrf_present -# <<: *aci_tenant_present -# vrf: anstest -# description: Ansible Test -# check_mode: true -# register: vrf_present_check_mode - -- name: create vrf - check mode works - cisco.aci.aci_vrf: &aci_vrf_present +- name: ensure tenant exists for tests to kick off + cisco.aci.aci_tenant: &aci_tenant_present host: "{{ aci_hostname }}" username: "{{ aci_username }}" password: "{{ aci_password }}" @@ -40,6 +19,11 @@ output_level: debug state: present tenant: abmughal + register: tenant_present + +- name: create vrf - check mode works + cisco.aci.aci_vrf: &aci_vrf_present + <<: *aci_tenant_present vrf: test2 description: Ansible Test check_mode: true @@ -50,15 +34,19 @@ <<: *aci_vrf_present register: vrf_present +- name: create vrf again - idempotency works + cisco.aci.aci_vrf: + <<: *aci_vrf_present + register: vrf_present_idempotent + - name: create test3 - creation works cisco.aci.aci_vrf: <<: *aci_vrf_present vrf: test3 register: vrf_present -- name: create leakInternalSubnet - check_mode - cisco.aci.aci_vrf_leak_internal_subnet: &aci_vrf_leakInternalSubnet - #<<: *aci_vrf_present +- name: create leakInternalSubnet + cisco.aci.aci_vrf_leak_internal_subnet: host: "{{ aci_hostname }}" username: "{{ aci_username }}" password: "{{ aci_password }}" @@ -71,29 +59,45 @@ vrf: test leak_internal_subnet: - ctxName: "test2" + tenant: "abmughal" - ctxName: "test3" + tenant: "abmughal" description: Ansible Test ip: 1.1.1.2 - check_mode: true - register: vrf_present_check_mode + register: vrf_leak -- name: create leakInternalSubnet +- name: test leak_internal_subnet delete cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_vrf_leakInternalSubnet - 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 - state: present - tenant: abmughal + <<: *aci_vrf_present vrf: test leak_internal_subnet: - ctxName: "test2" - - ctxName: "test3" - description: Ansible Test + tenant: "abmughal" ip: 1.1.1.2 - register: vrf_present + register: vrf_leak_delete + +- name: get vrf query + cisco.aci.aci_vrf_leak_internal_subnet: &aci_query + <<: *aci_tenant_present + state: query + vrf: test + register: query_all + +- name: delete tenant - cleanup before ending tests + cisco.aci.aci_tenant: + <<: *aci_tenant_present + state: absent + when: tenant_present is changed + +# - name: delete vrf again - idempotency works +# cisco.aci.aci_vrf_leak_internal_subnet: +# <<: *aci_vrf_absent +# register: vrf_absent_idempotent +# - name: delete vrf - cleanup +# cisco.aci.aci_vrf_leak_internal_subnet: +# <<: *aci_vrf_absent +# name: test2 +# #check for idempotency, mod, and delete +# #add and delete children +# #query \ No newline at end of file From b17f5ac24139ebb8a0cc5c5de2f21ca770468b96 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 11:01:36 -0500 Subject: [PATCH 04/30] Fixed documentation for leak_internal_subnet --- .../modules/aci_vrf_leak_internal_subnet.py | 99 ++++++++++++------- 1 file changed, 64 insertions(+), 35 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index a18a3a3b3..68bfce40e 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -47,6 +47,29 @@ - Configures match type for contracts under vzAny type: str choices: [ all, at_least_one, at_most_one, none] + scope: + description: + - Scope of the object + type: str + choices: [ public, private, shared ] + leak_internal_subnet: + description: + - The subnets being leaked to + type: list + suboptions: + tenant: + description: + - Name of the tenant + type: str + aliases: [ tenantName ] + ctxName: + description: + - Name of the VRF + type: str + ip: + description: + - The IP address + type: str extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation @@ -229,18 +252,15 @@ def main(): tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects vrf=dict(type="str", aliases=["context", "name", "vrf_name"]), # Not required for querying all objects leak_internal_subnet=dict( - type="list", - elements="dict", - options=dict( - ctxName=dict(type="str"), - tenant=dict(type="str", aliases=["tenantName"]) - ), + type="list", + elements="dict", + options=dict(ctxName=dict(type="str"), tenant=dict(type="str", aliases=["tenantName"])), ), description=dict(type="str", aliases=["descr"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), match_type=dict(type="str", choices=["all", "at_least_one", "at_most_one", "none"]), name_alias=dict(type="str"), - scope=dict(type="str", default="private", choices=["public","private","shared"]), + scope=dict(type="str", default="private", choices=["public", "private", "shared"]), ip=dict(type="str"), ) @@ -248,8 +268,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["tenant", "vrf","leak_internal_subnet"]], - ["state", "present", ["tenant", "vrf","leak_internal_subnet"]], + ["state", "absent", ["tenant", "vrf", "leak_internal_subnet"]], + ["state", "present", ["tenant", "vrf", "leak_internal_subnet"]], ], ) @@ -295,39 +315,48 @@ def main(): aci.get_existing() - if state == "present": - child_configs = [] + if state == "present": + child_configs = [] custom = [] - #for loop for customer configs, key is to-[tenant]-[ctxName] for subnet in leak_internal_subnet: - custom.append("to-[{0}]-[{1}]".format(subnet.get("tenant"),subnet.get("ctxName"))) - child_configs.append(dict(leakTo=dict( - attributes=dict( - ctxName=subnet.get("ctxName"), - rn="to-[{0}]-[{1}]".format(subnet.get("tenant"),subnet.get("ctxName")), - scope=scope, - tenantName=tenant, - ) + custom.append("to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("ctxName"))) + child_configs.append( + dict( + leakTo=dict( + attributes=dict( + ctxName=subnet.get("ctxName"), + rn="to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("ctxName")), + scope=scope, + tenantName=tenant, + ) + ) ) - ) - ) + ) - #loop through existing and delete if it's found - if isinstance(aci.existing, list) and len(aci.existing) > 0: #if there are existing children + if isinstance(aci.existing, list) and len(aci.existing) > 0: for child in aci.existing[0].get("leakInternalSubnet", {}).get("children", {}): - if child.get("leakTo") and "to-[{0}]-[{1}]".format(child.get("leakTo").get("attributes").get("tenantName"),child.get("leakTo").get("attributes").get("ctxName")) not in custom: + if ( + child.get("leakTo") + and "to-[{0}]-[{1}]".format(child.get("leakTo").get("attributes").get("tenantName"), child.get("leakTo").get("attributes").get("ctxName")) + not in custom + ): child_configs.append( - { - "leakTo": { - "attributes": { - "dn": "uni/tn-{0}/ctx-{1}/leakroutes/leakintsubnet-[{2}]/to-[{3}]-[{4}]".format(child.get("leakTo").get("attributes").get("tenantName"), vrf, ip,child.get("leakTo").get("attributes").get("tenantName"), - child.get("leakTo").get("attributes").get("ctxName")), - "status": "deleted" - } - } - } - ) + { + "leakTo": { + "attributes": { + "dn": "uni/tn-{0}/ctx-{1}/leakroutes/leakintsubnet-[{2}]/to-[{3}]-[{4}]".format( + child.get("leakTo").get("attributes").get("tenantName"), + vrf, + ip, + child.get("leakTo").get("attributes").get("tenantName"), + child.get("leakTo").get("attributes").get("ctxName"), + ), + "status": "deleted", + } + } + } + ) aci.payload( aci_class="leakInternalSubnet", From 87aa99c8181e4838c1555553c2bb15dacdf23a37 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 11:37:23 -0500 Subject: [PATCH 05/30] Fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 68bfce40e..55a0cd08f 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -52,6 +52,7 @@ - Scope of the object type: str choices: [ public, private, shared ] + default: private leak_internal_subnet: description: - The subnets being leaked to @@ -316,7 +317,7 @@ def main(): aci.get_existing() if state == "present": - child_configs = [] + child_configs = [] custom = [] for subnet in leak_internal_subnet: @@ -334,7 +335,7 @@ def main(): ) ) - if isinstance(aci.existing, list) and len(aci.existing) > 0: + if isinstance(aci.existing, list) and len(aci.existing) > 0: for child in aci.existing[0].get("leakInternalSubnet", {}).get("children", {}): if ( child.get("leakTo") @@ -353,7 +354,7 @@ def main(): child.get("leakTo").get("attributes").get("ctxName"), ), "status": "deleted", - } + } } } ) @@ -380,4 +381,4 @@ def main(): if __name__ == "__main__": - main() \ No newline at end of file + main() From 6685f42b03584d77c69a541997499ba390d5f5c4 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 11:38:47 -0500 Subject: [PATCH 06/30] Fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 55a0cd08f..1f0ec544b 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -354,6 +354,7 @@ def main(): child.get("leakTo").get("attributes").get("ctxName"), ), "status": "deleted", + } } } From 0eb78901274e043dd4d888bab5b79c1330e2e810 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 11:40:03 -0500 Subject: [PATCH 07/30] Fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 1f0ec544b..8bc59f8ee 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -353,9 +353,8 @@ def main(): child.get("leakTo").get("attributes").get("tenantName"), child.get("leakTo").get("attributes").get("ctxName"), ), - "status": "deleted", - - } + "status": "deleted", + } } } ) From b2bf0e518b89016c10a6bd11f0769d2ff4c24166 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 11:42:14 -0500 Subject: [PATCH 08/30] Fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 8bc59f8ee..4f8baf019 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -353,8 +353,8 @@ def main(): child.get("leakTo").get("attributes").get("tenantName"), child.get("leakTo").get("attributes").get("ctxName"), ), - "status": "deleted", - } + "status": "deleted", + } } } ) From 643f285136028903a92a395f8e75ec83c03706e5 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 11:51:56 -0500 Subject: [PATCH 09/30] Fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 1 + 1 file changed, 1 insertion(+) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 4f8baf019..bf0def1b5 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -57,6 +57,7 @@ description: - The subnets being leaked to type: list + elements: dict suboptions: tenant: description: From 786bc9925adc45b7da763a55a3d92c74d4730355 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 19 Jun 2023 12:05:05 -0500 Subject: [PATCH 10/30] Fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index bf0def1b5..7a11ec49f 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -54,19 +54,19 @@ choices: [ public, private, shared ] default: private leak_internal_subnet: - description: + description: - The subnets being leaked to type: list elements: dict suboptions: tenant: description: - - Name of the tenant + - Name of the tenant type: str aliases: [ tenantName ] - ctxName: + ctxName: description: - - Name of the VRF + - Name of the VRF type: str ip: description: @@ -99,7 +99,7 @@ tenant: lab_tenant descr: Lab VRF state: present - leak_internal_subnet: + leak_internal_subnet: - ctxName: "test" tenant: "lab_tenant" description: Ansible Test From be473e56d7a23caf217f3e291d18bf98bf7f82e4 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Thu, 22 Jun 2023 09:41:45 -0500 Subject: [PATCH 11/30] Added tests --- .../modules/aci_vrf_leak_internal_subnet.py | 42 +++++---- .../tasks/main.yml | 90 ++++++++++--------- 2 files changed, 72 insertions(+), 60 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 7a11ec49f..6edba9afc 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -1,6 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- +# Copyright: (c) 2023, <> (@abmughal) # 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 @@ -63,11 +64,12 @@ description: - Name of the tenant type: str - aliases: [ tenantName ] - ctxName: + aliases: [ tenant_name ] + vrf: description: - Name of the VRF type: str + aliases: [ vrf_name ] ip: description: - The IP address @@ -90,7 +92,7 @@ """ EXAMPLES = r""" -- name: Create leakInternalSubnet +- name: Create leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: host: apic username: admin @@ -100,7 +102,7 @@ descr: Lab VRF state: present leak_internal_subnet: - - ctxName: "test" + - vrf: "test" tenant: "lab_tenant" description: Ansible Test ip: 1.1.1.2 @@ -118,7 +120,7 @@ ip: 1.1.1.2 delegate_to: localhost -- name: Query leakInternalSubnet +- name: Query leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: host: apic username: admin @@ -256,7 +258,10 @@ def main(): leak_internal_subnet=dict( type="list", elements="dict", - options=dict(ctxName=dict(type="str"), tenant=dict(type="str", aliases=["tenantName"])), + options=dict( + vrf=dict(type="str", aliases=["vrf_name"]), + tenant=dict(type="str", aliases=["tenantName"]), + ), ), description=dict(type="str", aliases=["descr"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), @@ -285,8 +290,7 @@ def main(): scope = module.params.get("scope") ip = module.params.get("ip") - if match_type is not None: - match_type = MATCH_TYPE_MAPPING[match_type] + match_type = MATCH_TYPE_MAPPING.get(match_type) aci = ACIModule(module) aci.construct_url( @@ -310,7 +314,8 @@ def main(): subclass_3=dict( aci_class="leakInternalSubnet", aci_rn="leakintsubnet-[{0}]".format(ip), - module_object=ip, + module_object=ip, + target_filter={"ip": ip}, ), child_classes=["leakTo"], ) @@ -320,15 +325,15 @@ def main(): if state == "present": child_configs = [] - custom = [] + subnet_rn_list = [] for subnet in leak_internal_subnet: - custom.append("to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("ctxName"))) + subnet_rn_list.append("to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("vrf"))) child_configs.append( dict( leakTo=dict( attributes=dict( - ctxName=subnet.get("ctxName"), - rn="to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("ctxName")), + ctxName=subnet.get("vrf"), + rn="to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("vrf")), scope=scope, tenantName=tenant, ) @@ -338,21 +343,22 @@ def main(): if isinstance(aci.existing, list) and len(aci.existing) > 0: for child in aci.existing[0].get("leakInternalSubnet", {}).get("children", {}): + child_attributes = child.get("leakTo", {}).get("attributes", {}) if ( child.get("leakTo") - and "to-[{0}]-[{1}]".format(child.get("leakTo").get("attributes").get("tenantName"), child.get("leakTo").get("attributes").get("ctxName")) - not in custom + and "to-[{0}]-[{1}]".format(child_attributes.get("tenantName"), child_attributes.get("ctxName")) + not in subnet_rn_list ): child_configs.append( { "leakTo": { "attributes": { "dn": "uni/tn-{0}/ctx-{1}/leakroutes/leakintsubnet-[{2}]/to-[{3}]-[{4}]".format( - child.get("leakTo").get("attributes").get("tenantName"), + child_attributes.get("tenantName"), vrf, ip, - child.get("leakTo").get("attributes").get("tenantName"), - child.get("leakTo").get("attributes").get("ctxName"), + child_attributes.get("tenantName"), + child_attributes.get("ctxName"), ), "status": "deleted", } diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 705225d06..0d4846557 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -8,23 +8,35 @@ 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: '{{ aci_output_level | default("info") }}' + +# - name: delete existing tenant +# cisco.aci.aci_tenant: +# <<: *aci_info +# state: absent +# tenant: ansible_test3 +# register: tenant_present + - name: ensure tenant exists for tests to kick off cisco.aci.aci_tenant: &aci_tenant_present - 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 + <<: *aci_info state: present - tenant: abmughal + tenant: ansible_test3 register: tenant_present - name: create vrf - check mode works cisco.aci.aci_vrf: &aci_vrf_present <<: *aci_tenant_present - vrf: test2 + vrf: test description: Ansible Test check_mode: true register: vrf_present_check_mode @@ -34,10 +46,11 @@ <<: *aci_vrf_present register: vrf_present -- name: create vrf again - idempotency works +- name: create test - creation works cisco.aci.aci_vrf: <<: *aci_vrf_present - register: vrf_present_idempotent + vrf: test2 + register: vrf_present - name: create test3 - creation works cisco.aci.aci_vrf: @@ -45,37 +58,45 @@ vrf: test3 register: vrf_present -- name: create leakInternalSubnet +- name: create leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: - 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 + <<: *aci_info state: present - tenant: abmughal + tenant: ansible_test3 vrf: test + ip: 1.1.1.2 + leak_internal_subnet: + - vrf: "test2" + tenant: "ansible_test3" + - vrf: "test3" + tenant: "ansible_test3" + description: Ansible Test + register: vrf_present + +- name: create leak internal subnet 2 + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_info + tenant: ansible_test3 + vrf: test2 leak_internal_subnet: - - ctxName: "test2" - tenant: "abmughal" - - ctxName: "test3" - tenant: "abmughal" + - vrf: "test" + tenant: "ansible_test3" description: Ansible Test ip: 1.1.1.2 + state: absent register: vrf_leak -- name: test leak_internal_subnet delete +- name: Delete leak_internal_subnet cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_vrf_present vrf: test leak_internal_subnet: - - ctxName: "test2" - tenant: "abmughal" + - vrf: "test2" + tenant: "ansible_test3" ip: 1.1.1.2 register: vrf_leak_delete +#add delete again task - name: get vrf query cisco.aci.aci_vrf_leak_internal_subnet: &aci_query <<: *aci_tenant_present @@ -83,21 +104,6 @@ vrf: test register: query_all -- name: delete tenant - cleanup before ending tests - cisco.aci.aci_tenant: - <<: *aci_tenant_present - state: absent - when: tenant_present is changed - -# - name: delete vrf again - idempotency works -# cisco.aci.aci_vrf_leak_internal_subnet: -# <<: *aci_vrf_absent -# register: vrf_absent_idempotent - -# - name: delete vrf - cleanup -# cisco.aci.aci_vrf_leak_internal_subnet: -# <<: *aci_vrf_absent -# name: test2 # #check for idempotency, mod, and delete # #add and delete children # #query \ No newline at end of file From bdae6a49db4d74a7cc67afb1b9054cf8c895432a Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 23 Jun 2023 18:07:52 -0500 Subject: [PATCH 12/30] [ignore] fix creation when parent leakRoute object doesn't work in aci_vrf_leak_internal_subnet --- plugins/module_utils/aci.py | 11 ++++++++++- plugins/modules/aci_vrf_leak_internal_subnet.py | 7 +++++-- .../aci_vrf_leak_internal_subnet/tasks/main.yml | 17 ++++++++++------- 3 files changed, 25 insertions(+), 10 deletions(-) diff --git a/plugins/module_utils/aci.py b/plugins/module_utils/aci.py index a9e666ec3..b5516c965 100644 --- a/plugins/module_utils/aci.py +++ b/plugins/module_utils/aci.py @@ -320,6 +320,7 @@ def __init__(self, module): self.obj_filter = None self.method = None self.path = None + self.parent_path = None self.response = None self.status = None self.url = None @@ -921,6 +922,7 @@ def _construct_url_1(self, obj, config_only=True): if self.module.params.get("state") in ("absent", "present"): # State is absent or present self.path = "api/mo/uni/{0}.json".format(obj_rn) + self.parent_path = "api/mo/uni.json" if config_only: self.update_qs({"rsp-prop-include": "config-only"}) self.obj_filter = obj_filter @@ -947,6 +949,7 @@ def _construct_url_2(self, parent, obj, config_only=True): if self.module.params.get("state") in ("absent", "present"): # State is absent or present self.path = "api/mo/uni/{0}/{1}.json".format(parent_rn, obj_rn) + self.parent_path = "api/mo/uni/{0}.json".format(parent_rn) if config_only: self.update_qs({"rsp-prop-include": "config-only"}) self.obj_filter = obj_filter @@ -984,6 +987,7 @@ def _construct_url_3(self, root, parent, obj, config_only=True): if self.module.params.get("state") in ("absent", "present"): # State is absent or present self.path = "api/mo/uni/{0}/{1}/{2}.json".format(root_rn, parent_rn, obj_rn) + self.parent_path = "api/mo/uni/{0}/{1}.json".format(root_rn, parent_rn) if config_only: self.update_qs({"rsp-prop-include": "config-only"}) self.obj_filter = obj_filter @@ -1053,6 +1057,7 @@ def _construct_url_4(self, root, sec, parent, obj, config_only=True): if self.module.params.get("state") in ("absent", "present"): # State is absent or present self.path = "api/mo/uni/{0}/{1}/{2}/{3}.json".format(root_rn, sec_rn, parent_rn, obj_rn) + self.parent_path = "api/mo/uni/{0}/{1}/{2}.json".format(root_rn, sec_rn, parent_rn) if config_only: self.update_qs({"rsp-prop-include": "config-only"}) self.obj_filter = obj_filter @@ -1108,6 +1113,7 @@ def _construct_url_5(self, root, ter, sec, parent, obj, config_only=True): if self.module.params.get("state") in ("absent", "present"): # State is absent or present self.path = "api/mo/uni/{0}/{1}/{2}/{3}/{4}.json".format(root_rn, ter_rn, sec_rn, parent_rn, obj_rn) + self.parent_path = "api/mo/uni/{0}/{1}/{2}/{3}.json".format(root_rn, ter_rn, sec_rn, parent_rn) if config_only: self.update_qs({"rsp-prop-include": "config-only"}) self.obj_filter = obj_filter @@ -1517,7 +1523,7 @@ def payload(self, aci_class, class_config, child_configs=None): if children: self.proposed[aci_class].update(dict(children=children)) - def post_config(self): + def post_config(self, parent_class=None): """ This method is used to handle the logic when the modules state is equal to present. The method only pushes a change if the object has differences than what exists on the APIC, and if check_mode is False. A successful change will mark the @@ -1527,6 +1533,9 @@ def post_config(self): return elif not self.module.check_mode: # Sign and encode request as to APIC's wishes + if parent_class is not None: + self.url = "{protocol}://{host}/{path}".format(path=self.parent_path, **self.module.params) + self.config = {parent_class: {"attributes": {}, "children": [self.config]}} if self.params.get("private_key"): self.cert_auth(method="POST", payload=json.dumps(self.config)) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 6edba9afc..32d0df11a 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -335,7 +335,7 @@ def main(): ctxName=subnet.get("vrf"), rn="to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("vrf")), scope=scope, - tenantName=tenant, + tenantName=subnet.get("tenant"), ) ) ) @@ -379,7 +379,10 @@ def main(): aci.get_diff(aci_class="leakInternalSubnet") - aci.post_config() + if aci.existing: + aci.post_config() + else: + aci.post_config(parent_class="leakRoutes") elif state == "absent": aci.delete_config() diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 0d4846557..9a3279e50 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -17,14 +17,14 @@ validate_certs: '{{ aci_validate_certs | default(false) }}' use_ssl: '{{ aci_use_ssl | default(true) }}' use_proxy: '{{ aci_use_proxy | default(true) }}' - output_level: '{{ aci_output_level | default("info") }}' + output_level: '{{ aci_output_level | default("debug") }}' -# - name: delete existing tenant -# cisco.aci.aci_tenant: -# <<: *aci_info -# state: absent -# tenant: ansible_test3 -# register: tenant_present +- name: delete existing tenant + cisco.aci.aci_tenant: + <<: *aci_info + state: absent + tenant: ansible_test3 + register: tenant_present - name: ensure tenant exists for tests to kick off cisco.aci.aci_tenant: &aci_tenant_present @@ -73,6 +73,9 @@ description: Ansible Test register: vrf_present +# why isn't leakRoutes being created in this call +# have to instantiate leakRoutes beforehand? + - name: create leak internal subnet 2 cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_info From a560eec6ce3de3fad6a466232bf825cadce72ab9 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 23 Jun 2023 18:18:35 -0500 Subject: [PATCH 13/30] [ignore] made formatting consistent for leak_internal_subnet --- .../modules/aci_vrf_leak_internal_subnet.py | 26 +++++++------------ 1 file changed, 10 insertions(+), 16 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 32d0df11a..895f0c216 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -333,9 +333,8 @@ def main(): leakTo=dict( attributes=dict( ctxName=subnet.get("vrf"), - rn="to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("vrf")), - scope=scope, tenantName=subnet.get("tenant"), + scope=scope, ) ) ) @@ -350,20 +349,15 @@ def main(): not in subnet_rn_list ): child_configs.append( - { - "leakTo": { - "attributes": { - "dn": "uni/tn-{0}/ctx-{1}/leakroutes/leakintsubnet-[{2}]/to-[{3}]-[{4}]".format( - child_attributes.get("tenantName"), - vrf, - ip, - child_attributes.get("tenantName"), - child_attributes.get("ctxName"), - ), - "status": "deleted", - } - } - } + dict( + leakTo=dict( + attributes=dict( + ctxName=child_attributes.get("ctxName"), + tenantName=child_attributes.get("tenantName"), + status="deleted", + ) + ) + ) ) aci.payload( From 0ab893a36b1ef864736655b190b8d6b50a617735 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 26 Jun 2023 10:09:24 -0500 Subject: [PATCH 14/30] [ignore] Fixed trailing whitespace for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 895f0c216..576cc3f73 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -259,7 +259,7 @@ def main(): type="list", elements="dict", options=dict( - vrf=dict(type="str", aliases=["vrf_name"]), + vrf=dict(type="str", aliases=["vrf_name"]), tenant=dict(type="str", aliases=["tenantName"]), ), ), @@ -314,7 +314,7 @@ def main(): subclass_3=dict( aci_class="leakInternalSubnet", aci_rn="leakintsubnet-[{0}]".format(ip), - module_object=ip, + module_object=ip, target_filter={"ip": ip}, ), child_classes=["leakTo"], @@ -343,11 +343,7 @@ def main(): if isinstance(aci.existing, list) and len(aci.existing) > 0: for child in aci.existing[0].get("leakInternalSubnet", {}).get("children", {}): child_attributes = child.get("leakTo", {}).get("attributes", {}) - if ( - child.get("leakTo") - and "to-[{0}]-[{1}]".format(child_attributes.get("tenantName"), child_attributes.get("ctxName")) - not in subnet_rn_list - ): + if child.get("leakTo") and "to-[{0}]-[{1}]".format(child_attributes.get("tenantName"), child_attributes.get("ctxName")) not in subnet_rn_list: child_configs.append( dict( leakTo=dict( From e94d1534c7babac2033a7bddbeace3059cdab5cf Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Mon, 26 Jun 2023 14:59:09 -0500 Subject: [PATCH 15/30] [ignore] added tests for leak_internal_subnet --- .../modules/aci_vrf_leak_internal_subnet.py | 6 +- .../tasks/main.yml | 125 ++++++++++++++---- 2 files changed, 101 insertions(+), 30 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 576cc3f73..ab91c6575 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -64,7 +64,7 @@ description: - Name of the tenant type: str - aliases: [ tenant_name ] + aliases: [ tenantName ] vrf: description: - Name of the VRF @@ -334,7 +334,7 @@ def main(): attributes=dict( ctxName=subnet.get("vrf"), tenantName=subnet.get("tenant"), - scope=scope, + scope=scope, ) ) ) @@ -350,7 +350,7 @@ def main(): attributes=dict( ctxName=child_attributes.get("ctxName"), tenantName=child_attributes.get("tenantName"), - status="deleted", + status="deleted", ) ) ) diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 9a3279e50..e4555b6cc 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -33,32 +33,47 @@ tenant: ansible_test3 register: tenant_present -- name: create vrf - check mode works +- name: create vrf cisco.aci.aci_vrf: &aci_vrf_present <<: *aci_tenant_present vrf: test description: Ansible Test - check_mode: true - register: vrf_present_check_mode - -- name: create vrf - creation works - cisco.aci.aci_vrf: - <<: *aci_vrf_present register: vrf_present -- name: create test - creation works +- name: create second vrf - creation works cisco.aci.aci_vrf: <<: *aci_vrf_present vrf: test2 register: vrf_present -- name: create test3 - creation works +- name: create third vrf - creation works cisco.aci.aci_vrf: <<: *aci_vrf_present vrf: test3 register: vrf_present -- name: create leak internal subnet +- name: create leak internal subnet - check_mode + cisco.aci.aci_vrf_leak_internal_subnet: &aci_leak_internal_subnet + <<: *aci_info + state: present + tenant: ansible_test3 + vrf: test + ip: 1.1.1.2 + leak_internal_subnet: + - vrf: "test2" + tenant: "ansible_test3" + - vrf: "test3" + tenant: "ansible_test3" + description: Ansible Test + check_mode: true + register: leak_sub_check_mode + +- name: create leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_leak_internal_subnet + register: leak_sub_present + +- name: create leak internal subnet - idempotency check cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_info state: present @@ -71,12 +86,47 @@ - vrf: "test3" tenant: "ansible_test3" description: Ansible Test - register: vrf_present + register: leak_sub_idempotent + +- name: create second leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_info + tenant: ansible_test3 + vrf: test2 + leak_internal_subnet: + - vrf: "test" + tenant: "ansible_test3" + description: Ansible Test + ip: 1.1.1.2 + register: leak_sub_present_2 -# why isn't leakRoutes being created in this call -# have to instantiate leakRoutes beforehand? +- name: present asserts + assert: + that: + - vrf_present is changed + - leak_sub_check_mode is changed + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_idempotent is not changed + - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' + - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + +- name: query all + cisco.aci.aci_vrf_leak_internal_subnet: &aci_query + <<: *aci_tenant_present + state: query + register: query_all + +- name: query vrf + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_tenant_present + state: query + vrf: test + register: query -- name: create leak internal subnet 2 +- name: absent case cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_info tenant: ansible_test3 @@ -87,26 +137,47 @@ description: Ansible Test ip: 1.1.1.2 state: absent - register: vrf_leak + register: leak_sub_absent -- name: Delete leak_internal_subnet +- name: query asserts + assert: + that: + - query_all is not changed + - query is not changed + - query_all.current.0.fvTenant.children.0.fvCtx.children.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' + - query_all.current.0.fvTenant.children.0.fvCtx.children.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - query.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - query.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_absent.proposed == {} + +- name: delete leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_vrf_present vrf: test leak_internal_subnet: - - vrf: "test2" + - vrf: "test3" tenant: "ansible_test3" ip: 1.1.1.2 - register: vrf_leak_delete + register: leak_sub_delete -#add delete again task -- name: get vrf query - cisco.aci.aci_vrf_leak_internal_subnet: &aci_query - <<: *aci_tenant_present - state: query +- name: delete leak internal subnet again + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_vrf_present vrf: test - register: query_all + leak_internal_subnet: + - vrf: "test2" + tenant: "ansible_test3" + ip: 1.1.1.2 + register: leak_sub_delete_2 -# #check for idempotency, mod, and delete -# #add and delete children -# #query \ No newline at end of file +- name: delete asserts + assert: + that: + - leak_sub_delete is changed + - leak_sub_delete.previous != [] + - leak_sub_delete_2 is changed + - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.status == 'deleted' + - leak_sub_delete_2.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' + - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.status == 'deleted' \ No newline at end of file From dd256f9b8803d6fcb9545256ca365478b560567e Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Tue, 27 Jun 2023 10:32:41 -0500 Subject: [PATCH 16/30] [ignore] small fix for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index ab91c6575..9d115dc19 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -265,7 +265,7 @@ def main(): ), description=dict(type="str", aliases=["descr"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), - match_type=dict(type="str", choices=["all", "at_least_one", "at_most_one", "none"]), + match_type=dict(type="str", choices=list(MATCH_TYPE_MAPPING.keys())), name_alias=dict(type="str"), scope=dict(type="str", default="private", choices=["public", "private", "shared"]), ip=dict(type="str"), From 1de3d750add236e754017e79fed06afdffea73bc Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Thu, 29 Jun 2023 12:53:50 -0500 Subject: [PATCH 17/30] [ignore] fixed documentation and query test for leak_internal_subnet --- plugins/module_utils/constants.py | 2 + .../modules/aci_vrf_leak_internal_subnet.py | 35 +- .../tasks/main.yml | 360 +++++++++--------- 3 files changed, 212 insertions(+), 185 deletions(-) diff --git a/plugins/module_utils/constants.py b/plugins/module_utils/constants.py index 9b273a75d..069921fad 100644 --- a/plugins/module_utils/constants.py +++ b/plugins/module_utils/constants.py @@ -31,3 +31,5 @@ NODE_TYPE_MAPPING = {"tier_2": "tier-2-leaf", "remote": "remote-leaf-wan", "virtual": "virtual", "unspecified": "unspecified"} SPAN_DIRECTION_MAP = {"incoming": "in", "outgoing": "out", "both": "both"} + +MATCH_TYPE_MAPPING = {"all": "All", "at_least_one": "AtleastOne", "at_most_one": "AtmostOne", "none": "None"} \ No newline at end of file diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 9d115dc19..948e5555e 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -45,34 +45,34 @@ type: str match_type: description: - - Configures match type for contracts under vzAny + - Configures match type for contracts under vzAny. type: str choices: [ all, at_least_one, at_most_one, none] scope: description: - - Scope of the object + - Scope of the object. type: str choices: [ public, private, shared ] default: private leak_internal_subnet: description: - - The subnets being leaked to + - The subnets being leaked to. type: list elements: dict suboptions: tenant: description: - - Name of the tenant + - Name of the tenant. type: str - aliases: [ tenantName ] + aliases: [ tenant_name ] vrf: description: - - Name of the VRF + - Name of the VRF. type: str aliases: [ vrf_name ] ip: description: - - The IP address + - The IP address. type: str extends_documentation_fragment: - cisco.aci.aci @@ -80,12 +80,13 @@ - 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 C(vrf) used must exist before using this module in your playbook. + The M(cisco.aci.aci_tenant) and M(cisco.aci.aci_vrf) modules can be used for this. seealso: - module: cisco.aci.aci_tenant +- module: cisco.aci.aci_vrf - name: APIC Management Information Model reference - description: More information about the internal APIC class B(fv:Ctx). + description: More information about the internal APIC class B(leak:InternalSubnet). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Abraham Mughal (@abmughal) @@ -120,6 +121,16 @@ ip: 1.1.1.2 delegate_to: localhost +- name: Query all leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + host: apic + username: admin + password: SomeSecretPassword + state: query + ip: 1.1.1.2 + delegate_to: localhost + register: query_result + - name: Query leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: host: apic @@ -128,6 +139,7 @@ vrf: vrf_lab tenant: lab_tenant state: query + ip: 1.1.1.2 delegate_to: localhost register: query_result """ @@ -247,7 +259,6 @@ none="None", ) - def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) @@ -260,7 +271,7 @@ def main(): elements="dict", options=dict( vrf=dict(type="str", aliases=["vrf_name"]), - tenant=dict(type="str", aliases=["tenantName"]), + tenant=dict(type="str", aliases=["tenant_name"]), ), ), description=dict(type="str", aliases=["descr"]), diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index e4555b6cc..880899695 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -8,176 +8,190 @@ 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: '{{ aci_output_level | default("debug") }}' - -- name: delete existing tenant - cisco.aci.aci_tenant: - <<: *aci_info - state: absent - tenant: ansible_test3 - register: tenant_present - -- name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - <<: *aci_info - state: present - tenant: ansible_test3 - register: tenant_present - -- name: create vrf - cisco.aci.aci_vrf: &aci_vrf_present - <<: *aci_tenant_present - vrf: test - description: Ansible Test - register: vrf_present - -- name: create second vrf - creation works - cisco.aci.aci_vrf: - <<: *aci_vrf_present - vrf: test2 - register: vrf_present - -- name: create third vrf - creation works - cisco.aci.aci_vrf: - <<: *aci_vrf_present - vrf: test3 - register: vrf_present - -- name: create leak internal subnet - check_mode - cisco.aci.aci_vrf_leak_internal_subnet: &aci_leak_internal_subnet - <<: *aci_info - state: present - tenant: ansible_test3 - vrf: test - ip: 1.1.1.2 - leak_internal_subnet: - - vrf: "test2" - tenant: "ansible_test3" - - vrf: "test3" - tenant: "ansible_test3" - description: Ansible Test - check_mode: true - register: leak_sub_check_mode - -- name: create leak internal subnet - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_leak_internal_subnet - register: leak_sub_present - -- name: create leak internal subnet - idempotency check - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_info - state: present - tenant: ansible_test3 - vrf: test - ip: 1.1.1.2 - leak_internal_subnet: - - vrf: "test2" - tenant: "ansible_test3" - - vrf: "test3" - tenant: "ansible_test3" - description: Ansible Test - register: leak_sub_idempotent - -- name: create second leak internal subnet - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_info - tenant: ansible_test3 - vrf: test2 - leak_internal_subnet: - - vrf: "test" - tenant: "ansible_test3" - description: Ansible Test - ip: 1.1.1.2 - register: leak_sub_present_2 - -- name: present asserts - assert: - that: - - vrf_present is changed - - leak_sub_check_mode is changed - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_idempotent is not changed - - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' - - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - -- name: query all - cisco.aci.aci_vrf_leak_internal_subnet: &aci_query - <<: *aci_tenant_present - state: query - register: query_all - -- name: query vrf - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_tenant_present - state: query - vrf: test - register: query - -- name: absent case - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_info - tenant: ansible_test3 - vrf: test2 - leak_internal_subnet: - - vrf: "test" - tenant: "ansible_test3" - description: Ansible Test - ip: 1.1.1.2 - state: absent - register: leak_sub_absent - -- name: query asserts - assert: - that: - - query_all is not changed - - query is not changed - - query_all.current.0.fvTenant.children.0.fvCtx.children.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' - - query_all.current.0.fvTenant.children.0.fvCtx.children.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - query.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' - - query.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_absent.proposed == {} - -- name: delete leak internal subnet - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_vrf_present - vrf: test - leak_internal_subnet: - - vrf: "test3" - tenant: "ansible_test3" - ip: 1.1.1.2 - register: leak_sub_delete - -- name: delete leak internal subnet again - cisco.aci.aci_vrf_leak_internal_subnet: - <<: *aci_vrf_present - vrf: test - leak_internal_subnet: - - vrf: "test2" - tenant: "ansible_test3" - ip: 1.1.1.2 - register: leak_sub_delete_2 - -- name: delete asserts - assert: - that: - - leak_sub_delete is changed - - leak_sub_delete.previous != [] - - leak_sub_delete_2 is changed - - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.status == 'deleted' - - leak_sub_delete_2.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' - - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.status == 'deleted' \ No newline at end of file +- 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 + - version.current.0.topSystem.attributes.version is version('5', '>=') + block: # block specifies execution of tasks within, based on conditions + - 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: '{{ aci_output_level | default("debug") }}' + + - name: delete existing tenant + cisco.aci.aci_tenant: + <<: *aci_info + state: absent + tenant: ansible_test3 + register: tenant_present + + - name: ensure tenant exists for tests to kick off + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_info + state: present + tenant: ansible_test3 + register: tenant_present + + - name: create vrf + cisco.aci.aci_vrf: &aci_vrf_present + <<: *aci_tenant_present + vrf: test + description: Ansible Test + register: vrf_present + + - name: create second vrf - creation works + cisco.aci.aci_vrf: + <<: *aci_vrf_present + vrf: test2 + register: vrf_present + + - name: create third vrf - creation works + cisco.aci.aci_vrf: + <<: *aci_vrf_present + vrf: test3 + register: vrf_present + + - name: create leak internal subnet - check_mode + cisco.aci.aci_vrf_leak_internal_subnet: &aci_leak_internal_subnet + <<: *aci_info + state: present + tenant: ansible_test3 + vrf: test + ip: 1.1.1.2 + leak_internal_subnet: + - vrf: "test2" + tenant: "ansible_test3" + - vrf: "test3" + tenant: "ansible_test3" + description: Ansible Test + check_mode: true + register: leak_sub_check_mode + + - name: create leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_leak_internal_subnet + register: leak_sub_present + + - name: create leak internal subnet - idempotency check + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_info + state: present + tenant: ansible_test3 + vrf: test + ip: 1.1.1.2 + leak_internal_subnet: + - vrf: "test2" + tenant: "ansible_test3" + - vrf: "test3" + tenant: "ansible_test3" + description: Ansible Test + register: leak_sub_idempotent + + - name: create second leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_info + tenant: ansible_test3 + vrf: test2 + leak_internal_subnet: + - vrf: "test" + tenant: "ansible_test3" + description: Ansible Test + ip: 1.1.1.2 + register: leak_sub_present_2 + + - name: present asserts + assert: + that: + - vrf_present is changed + - leak_sub_check_mode is changed + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' + - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_idempotent is not changed + - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' + - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + + - name: query all + cisco.aci.aci_vrf_leak_internal_subnet: &aci_query + <<: *aci_info + state: query + ip: 1.1.1.2 + register: query_all + + - name: query one leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_tenant_present + state: query + vrf: test + ip: 1.1.1.2 + register: query + + - name: absent case + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_info + tenant: ansible_test3 + vrf: test2 + leak_internal_subnet: + - vrf: "test" + tenant: "ansible_test3" + description: Ansible Test + ip: 1.1.1.2 + state: absent + register: leak_sub_absent + + - name: query asserts + assert: + that: + - query_all is not changed + - query is not changed + - query_all.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - query_all.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - query_all.current.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' + - query_all.current.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - query_all.current.1.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' + - query_all.current.1.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - query.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - query.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_absent.proposed == {} + + - name: delete leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_vrf_present + vrf: test + leak_internal_subnet: + - vrf: "test3" + tenant: "ansible_test3" + ip: 1.1.1.2 + register: leak_sub_delete + + - name: delete leak internal subnet again + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_vrf_present + vrf: test + leak_internal_subnet: + - vrf: "test2" + tenant: "ansible_test3" + ip: 1.1.1.2 + register: leak_sub_delete_2 + + - name: delete asserts + assert: + that: + - leak_sub_delete is changed + - leak_sub_delete.previous != [] + - leak_sub_delete_2 is changed + - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.status == 'deleted' + - leak_sub_delete_2.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' + - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.status == 'deleted' \ No newline at end of file From ebde3ae8470b06dfce7958d1200d922e268ac2bc Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 30 Jun 2023 10:34:54 -0500 Subject: [PATCH 18/30] [ignore] added test asserts for leak_internal_subnet --- .../tasks/main.yml | 33 ++++++++++++------- 1 file changed, 22 insertions(+), 11 deletions(-) diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 880899695..5fa6b046d 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -113,13 +113,20 @@ that: - vrf_present is changed - leak_sub_check_mode is changed - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' - - leak_sub_present.sent.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_check_mode.proposed.leakInternalSubnet.attributes.ip == '1.1.1.2' + - leak_sub_check_mode.proposed.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_check_mode.proposed.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_check_mode.proposed.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' + - leak_sub_check_mode.proposed.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.attributes.ip == '1.1.1.2' + - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' + - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' - leak_sub_idempotent is not changed - - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' - - leak_sub_present_2.sent.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present_2.current.0.leakRoutes.children.0.leakInternalSubnet.attributes.ip == '1.1.1.2' + - leak_sub_present_2.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' + - leak_sub_present_2.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - name: query all cisco.aci.aci_vrf_leak_internal_subnet: &aci_query @@ -154,10 +161,12 @@ that: - query_all is not changed - query is not changed + - query_all.current.0.leakInternalSubnet.attributes.ip == '1.1.1.2' - query_all.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' - query_all.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - query_all.current.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' - query_all.current.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - query_all.current.1.leakInternalSubnet.attributes.ip == '1.1.1.2' - query_all.current.1.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' - query_all.current.1.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - query.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' @@ -187,11 +196,13 @@ - name: delete asserts assert: that: + # change to current - leak_sub_delete is changed - leak_sub_delete.previous != [] + - leak_sub_delete.current.0.leakInternalSubnet.children | length == 1 + - leak_sub_delete.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - leak_sub_delete.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - leak_sub_delete_2 is changed - - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_delete.sent.leakInternalSubnet.children.0.leakTo.attributes.status == 'deleted' - - leak_sub_delete_2.sent.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' - - leak_sub_delete_2.sent.leakInternalSubnet.children.1.leakTo.attributes.status == 'deleted' \ No newline at end of file + - leak_sub_delete_2.current.0.leakInternalSubnet.children | length == 1 + - leak_sub_delete_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_delete_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' \ No newline at end of file From be1d841dc52153be7cb5ca2bdcf744bea6172e3e Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 30 Jun 2023 10:38:30 -0500 Subject: [PATCH 19/30] [ignore] formatting for leak_internal_subnet --- plugins/module_utils/constants.py | 2 +- plugins/modules/aci_vrf_leak_internal_subnet.py | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/module_utils/constants.py b/plugins/module_utils/constants.py index 069921fad..8788bd32a 100644 --- a/plugins/module_utils/constants.py +++ b/plugins/module_utils/constants.py @@ -32,4 +32,4 @@ SPAN_DIRECTION_MAP = {"incoming": "in", "outgoing": "out", "both": "both"} -MATCH_TYPE_MAPPING = {"all": "All", "at_least_one": "AtleastOne", "at_most_one": "AtmostOne", "none": "None"} \ No newline at end of file +MATCH_TYPE_MAPPING = {"all": "All", "at_least_one": "AtleastOne", "at_most_one": "AtmostOne", "none": "None"} diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 948e5555e..27c2bf918 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -259,6 +259,7 @@ none="None", ) + def main(): argument_spec = aci_argument_spec() argument_spec.update(aci_annotation_spec()) From 37658cebe9d8ab82bceac23711b486c348fc0569 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Wed, 5 Jul 2023 10:21:40 -0500 Subject: [PATCH 20/30] [ignore] added documentation for leak internal subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 27c2bf918..742ea8b86 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -121,6 +121,18 @@ ip: 1.1.1.2 delegate_to: localhost +- name: Delete leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + host: apic + username: admin + password: SomeSecretPassword + vrf: vrf_lab + tenant: lab_tenant + state: absent + description: Ansible Test + ip: 1.1.1.2 + delegate_to: localhost + - name: Query all leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: host: apic From 012b2c160a02e50fb53a56cba3538460578aa141 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Wed, 5 Jul 2023 10:27:42 -0500 Subject: [PATCH 21/30] [ignore] fixed trailing whitespace for leak internal subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 742ea8b86..3234c665c 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -132,7 +132,7 @@ description: Ansible Test ip: 1.1.1.2 delegate_to: localhost - + - name: Query all leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: host: apic From bace7909232a415bad6dbb15a79db276bff9facc Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Wed, 5 Jul 2023 11:28:20 -0500 Subject: [PATCH 22/30] [ignore] added documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 3234c665c..6a3cc592b 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -105,6 +105,8 @@ leak_internal_subnet: - vrf: "test" tenant: "lab_tenant" + - vrf: "test2" + tenant: "lab_tenant" description: Ansible Test ip: 1.1.1.2 delegate_to: localhost @@ -116,7 +118,9 @@ password: SomeSecretPassword vrf: vrf_lab tenant: lab_tenant - leak_internal_subnet: "{{ fake_var | default(omit) }}" + leak_internal_subnet: + - vrf: "test2" + tenant: "lab_tenant" description: Ansible Test ip: 1.1.1.2 delegate_to: localhost From 37fe7c27f8e94d6f7eb7e905c1c068cde8e44832 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Wed, 5 Jul 2023 11:37:00 -0500 Subject: [PATCH 23/30] [ignore] fixed documentation for leak_internal_subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 6a3cc592b..bb3b6f490 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -118,9 +118,10 @@ password: SomeSecretPassword vrf: vrf_lab tenant: lab_tenant + state: absent leak_internal_subnet: - vrf: "test2" - tenant: "lab_tenant" + tenant: "lab_tenant" description: Ansible Test ip: 1.1.1.2 delegate_to: localhost From 8047b6ec3f7ce31d79bda8e3d04d13683cb7fb18 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 7 Jul 2023 11:45:26 -0500 Subject: [PATCH 24/30] [ignore] fixed documentation for leak internal subnet --- plugins/module_utils/aci.py | 5 +- .../modules/aci_vrf_leak_internal_subnet.py | 50 +++++++++---------- .../tasks/main.yml | 16 +++--- 3 files changed, 36 insertions(+), 35 deletions(-) diff --git a/plugins/module_utils/aci.py b/plugins/module_utils/aci.py index b5516c965..7dc626763 100644 --- a/plugins/module_utils/aci.py +++ b/plugins/module_utils/aci.py @@ -1533,15 +1533,16 @@ def post_config(self, parent_class=None): return elif not self.module.check_mode: # Sign and encode request as to APIC's wishes + url = self.url if parent_class is not None: - self.url = "{protocol}://{host}/{path}".format(path=self.parent_path, **self.module.params) + url = "{protocol}://{host}/{path}".format(path=self.parent_path, **self.module.params) self.config = {parent_class: {"attributes": {}, "children": [self.config]}} if self.params.get("private_key"): self.cert_auth(method="POST", payload=json.dumps(self.config)) resp, info = fetch_url( self.module, - self.url, + url, data=json.dumps(self.config), headers=self.headers, method="POST", diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index bb3b6f490..50b26cc4d 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -13,13 +13,13 @@ DOCUMENTATION = r""" --- module: aci_vrf_leak_internal_subnet -short_description: Manage contexts or VRFs (fv:leakInternalSubnet) +short_description: Manage VRF leaking of subnets (fv:leakInternalSubnet) description: -- Manage leaking subnets under VRF. +- Manage the leaking of internal subnets under the VRF. options: tenant: description: - - The name of the Tenant the VRF should belong to. + - The name of the Tenant the VRF belongs to. type: str aliases: [ tenant_name ] vrf: @@ -29,23 +29,16 @@ aliases: [ context, name, vrf_name ] description: description: - - The description for the VRF. + - The description for the VRF Leak Internal Subnet. 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 match_type: description: - - Configures match type for contracts under vzAny. + - Configures how matches are performed. type: str choices: [ all, at_least_one, at_most_one, none] scope: @@ -54,9 +47,9 @@ type: str choices: [ public, private, shared ] default: private - leak_internal_subnet: + leak_to: description: - - The subnets being leaked to. + - The VRFs to leak the subnet routes into. type: list elements: dict suboptions: @@ -72,8 +65,15 @@ aliases: [ vrf_name ] ip: description: - - The IP address. + - The IP address / subnet used to match routes to be leaked. type: str + state: + description: + - Use C(present) or C(absent) for adding or removing. + - Use C(query) for listing an object or multiple objects. + type: str + choices: [ absent, present, query ] + default: present extends_documentation_fragment: - cisco.aci.aci - cisco.aci.annotation @@ -269,12 +269,12 @@ 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 -MATCH_TYPE_MAPPING = dict( - all="All", - at_least_one="AtleastOne", - at_most_one="AtmostOne", - none="None", -) +# MATCH_TYPE_MAPPING = dict( +# all="All", +# at_least_one="AtleastOne", +# at_most_one="AtmostOne", +# none="None", +# ) def main(): @@ -294,7 +294,7 @@ def main(): ), description=dict(type="str", aliases=["descr"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), - match_type=dict(type="str", choices=list(MATCH_TYPE_MAPPING.keys())), + #match_type=dict(type="str", choices=list(MATCH_TYPE_MAPPING.keys())), name_alias=dict(type="str"), scope=dict(type="str", default="private", choices=["public", "private", "shared"]), ip=dict(type="str"), @@ -315,11 +315,11 @@ def main(): vrf = module.params.get("vrf") leak_internal_subnet = module.params.get("leak_internal_subnet") name_alias = module.params.get("name_alias") - match_type = module.params.get("match_type") + #match_type = module.params.get("match_type") scope = module.params.get("scope") ip = module.params.get("ip") - match_type = MATCH_TYPE_MAPPING.get(match_type) + #match_type = MATCH_TYPE_MAPPING.get(match_type) aci = ACIModule(module) aci.construct_url( @@ -372,7 +372,7 @@ def main(): if isinstance(aci.existing, list) and len(aci.existing) > 0: for child in aci.existing[0].get("leakInternalSubnet", {}).get("children", {}): child_attributes = child.get("leakTo", {}).get("attributes", {}) - if child.get("leakTo") and "to-[{0}]-[{1}]".format(child_attributes.get("tenantName"), child_attributes.get("ctxName")) not in subnet_rn_list: + if child_attributes and "to-[{0}]-[{1}]".format(child_attributes.get("tenantName"), child_attributes.get("ctxName")) not in subnet_rn_list: child_configs.append( dict( leakTo=dict( diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 5fa6b046d..bd06b240f 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -118,15 +118,15 @@ - leak_sub_check_mode.proposed.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - leak_sub_check_mode.proposed.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' - leak_sub_check_mode.proposed.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.attributes.ip == '1.1.1.2' - - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' - - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' - - leak_sub_present.current.0.leakRoutes.children.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present.current.0.leakInternalSubnet.attributes.ip == '1.1.1.2' + - leak_sub_present.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - leak_sub_present.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present.current.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' + - leak_sub_present.current.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' - leak_sub_idempotent is not changed - - leak_sub_present_2.current.0.leakRoutes.children.0.leakInternalSubnet.attributes.ip == '1.1.1.2' - - leak_sub_present_2.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' - - leak_sub_present_2.current.0.leakRoutes.children.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_present_2.current.0.leakInternalSubnet.attributes.ip == '1.1.1.2' + - leak_sub_present_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' + - leak_sub_present_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - name: query all cisco.aci.aci_vrf_leak_internal_subnet: &aci_query From 687b5f0c00780c25e004b1f7bd46d4af145b0856 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 7 Jul 2023 11:57:46 -0500 Subject: [PATCH 25/30] [ignore] fixed documentation for leak internal subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 50b26cc4d..c50bd6ed0 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -36,18 +36,13 @@ description: - The alias for the current object. This relates to the nameAlias field in ACI. type: str - match_type: - description: - - Configures how matches are performed. - type: str - choices: [ all, at_least_one, at_most_one, none] scope: description: - Scope of the object. type: str choices: [ public, private, shared ] default: private - leak_to: + leak_internal_subnet: description: - The VRFs to leak the subnet routes into. type: list @@ -269,13 +264,6 @@ 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 -# MATCH_TYPE_MAPPING = dict( -# all="All", -# at_least_one="AtleastOne", -# at_most_one="AtmostOne", -# none="None", -# ) - def main(): argument_spec = aci_argument_spec() @@ -294,7 +282,6 @@ def main(): ), description=dict(type="str", aliases=["descr"]), state=dict(type="str", default="present", choices=["absent", "present", "query"]), - #match_type=dict(type="str", choices=list(MATCH_TYPE_MAPPING.keys())), name_alias=dict(type="str"), scope=dict(type="str", default="private", choices=["public", "private", "shared"]), ip=dict(type="str"), @@ -315,11 +302,9 @@ def main(): vrf = module.params.get("vrf") leak_internal_subnet = module.params.get("leak_internal_subnet") name_alias = module.params.get("name_alias") - #match_type = module.params.get("match_type") scope = module.params.get("scope") ip = module.params.get("ip") - #match_type = MATCH_TYPE_MAPPING.get(match_type) aci = ACIModule(module) aci.construct_url( From 5afb82115a10fc0d1aa3d66bdc56e7ce31320cb4 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 7 Jul 2023 11:59:09 -0500 Subject: [PATCH 26/30] [ignore] fixed documentation for leak internal subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 1 - 1 file changed, 1 deletion(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index c50bd6ed0..762c5f16f 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -305,7 +305,6 @@ def main(): scope = module.params.get("scope") ip = module.params.get("ip") - aci = ACIModule(module) aci.construct_url( root_class=dict( From a8d505933c7d85458b1b5777f667282cdea57bdd Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 7 Jul 2023 12:25:22 -0500 Subject: [PATCH 27/30] [ignore] fixed documentation for leak internal subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 16 ++++++++-------- .../aci_vrf_leak_internal_subnet/tasks/main.yml | 12 ++++++------ 2 files changed, 14 insertions(+), 14 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index 762c5f16f..a43bc6378 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -42,7 +42,7 @@ type: str choices: [ public, private, shared ] default: private - leak_internal_subnet: + leak_to: description: - The VRFs to leak the subnet routes into. type: list @@ -97,7 +97,7 @@ tenant: lab_tenant descr: Lab VRF state: present - leak_internal_subnet: + leak_to: - vrf: "test" tenant: "lab_tenant" - vrf: "test2" @@ -114,7 +114,7 @@ vrf: vrf_lab tenant: lab_tenant state: absent - leak_internal_subnet: + leak_to: - vrf: "test2" tenant: "lab_tenant" description: Ansible Test @@ -272,7 +272,7 @@ def main(): argument_spec.update( tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects vrf=dict(type="str", aliases=["context", "name", "vrf_name"]), # Not required for querying all objects - leak_internal_subnet=dict( + leak_to=dict( type="list", elements="dict", options=dict( @@ -291,8 +291,8 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["tenant", "vrf", "leak_internal_subnet"]], - ["state", "present", ["tenant", "vrf", "leak_internal_subnet"]], + ["state", "absent", ["tenant", "vrf", "leak_to"]], + ["state", "present", ["tenant", "vrf", "leak_to"]], ], ) @@ -300,7 +300,7 @@ def main(): state = module.params.get("state") tenant = module.params.get("tenant") vrf = module.params.get("vrf") - leak_internal_subnet = module.params.get("leak_internal_subnet") + leak_to = module.params.get("leak_to") name_alias = module.params.get("name_alias") scope = module.params.get("scope") ip = module.params.get("ip") @@ -339,7 +339,7 @@ def main(): child_configs = [] subnet_rn_list = [] - for subnet in leak_internal_subnet: + for subnet in leak_to: subnet_rn_list.append("to-[{0}]-[{1}]".format(subnet.get("tenant"), subnet.get("vrf"))) child_configs.append( dict( diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index bd06b240f..72f5daed7 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -67,7 +67,7 @@ tenant: ansible_test3 vrf: test ip: 1.1.1.2 - leak_internal_subnet: + leak_to: - vrf: "test2" tenant: "ansible_test3" - vrf: "test3" @@ -88,7 +88,7 @@ tenant: ansible_test3 vrf: test ip: 1.1.1.2 - leak_internal_subnet: + leak_to: - vrf: "test2" tenant: "ansible_test3" - vrf: "test3" @@ -101,7 +101,7 @@ <<: *aci_info tenant: ansible_test3 vrf: test2 - leak_internal_subnet: + leak_to: - vrf: "test" tenant: "ansible_test3" description: Ansible Test @@ -148,7 +148,7 @@ <<: *aci_info tenant: ansible_test3 vrf: test2 - leak_internal_subnet: + leak_to: - vrf: "test" tenant: "ansible_test3" description: Ansible Test @@ -177,7 +177,7 @@ cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_vrf_present vrf: test - leak_internal_subnet: + leak_to: - vrf: "test3" tenant: "ansible_test3" ip: 1.1.1.2 @@ -187,7 +187,7 @@ cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_vrf_present vrf: test - leak_internal_subnet: + leak_to: - vrf: "test2" tenant: "ansible_test3" ip: 1.1.1.2 From d011f40970ea7b3f7a4994d1e7372d2b2de9ea28 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 7 Jul 2023 20:19:57 -0500 Subject: [PATCH 28/30] [ignore] fixed tests for leak internal subnet --- plugins/module_utils/aci.py | 5 ++- .../tasks/main.yml | 33 ++++++++++++------- 2 files changed, 26 insertions(+), 12 deletions(-) diff --git a/plugins/module_utils/aci.py b/plugins/module_utils/aci.py index 7dc626763..f64ca6eed 100644 --- a/plugins/module_utils/aci.py +++ b/plugins/module_utils/aci.py @@ -1535,7 +1535,10 @@ def post_config(self, parent_class=None): # Sign and encode request as to APIC's wishes url = self.url if parent_class is not None: - url = "{protocol}://{host}/{path}".format(path=self.parent_path, **self.module.params) + if self.params.get("port") is not None: + url = "{protocol}://{host}:{port}/{path}".format(path=self.parent_path, **self.module.params) + else: + url = "{protocol}://{host}/{path}".format(path=self.parent_path, **self.module.params) self.config = {parent_class: {"attributes": {}, "children": [self.config]}} if self.params.get("private_key"): self.cert_auth(method="POST", payload=json.dumps(self.config)) diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index 72f5daed7..ee3c89f1e 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -108,6 +108,10 @@ ip: 1.1.1.2 register: leak_sub_present_2 + - name: Sort the list of leaked internal subnets for present + ansible.builtin.set_fact: + attributes_list_present: "{{ leak_sub_present.current.0.leakInternalSubnet.children | map(attribute='leakTo.attributes') | list | sort(attribute='ctxName') }}" + - name: present asserts assert: that: @@ -119,10 +123,10 @@ - leak_sub_check_mode.proposed.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test3' - leak_sub_check_mode.proposed.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' - leak_sub_present.current.0.leakInternalSubnet.attributes.ip == '1.1.1.2' - - leak_sub_present.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' - - leak_sub_present.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - leak_sub_present.current.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' - - leak_sub_present.current.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - attributes_list_present.0.tenantName == 'ansible_test3' + - attributes_list_present.0.ctxName == 'test2' + - attributes_list_present.1.tenantName == 'ansible_test3' + - attributes_list_present.1.ctxName == 'test3' - leak_sub_idempotent is not changed - leak_sub_present_2.current.0.leakInternalSubnet.attributes.ip == '1.1.1.2' - leak_sub_present_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' @@ -156,23 +160,30 @@ state: absent register: leak_sub_absent + - name: Sort the list of leaked internal subnets for query + ansible.builtin.set_fact: + attributes_list_query_all: "{{ query_all.current.0.leakInternalSubnet.children | map(attribute='leakTo.attributes') | list | sort(attribute='ctxName') }}" + attributes_list_query: "{{ query.current.0.leakInternalSubnet.children | map(attribute='leakTo.attributes') | list | sort(attribute='ctxName') }}" + - name: query asserts assert: that: - query_all is not changed - query is not changed - query_all.current.0.leakInternalSubnet.attributes.ip == '1.1.1.2' - - query_all.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' - - query_all.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - query_all.current.0.leakInternalSubnet.children.1.leakTo.attributes.ctxName == 'test2' - - query_all.current.0.leakInternalSubnet.children.1.leakTo.attributes.tenantName == 'ansible_test3' + - attributes_list_query_all.0.ctxName == 'test2' + - attributes_list_query_all.0.tenantName == 'ansible_test3' + - attributes_list_query_all.1.ctxName == 'test3' + - attributes_list_query_all.1.tenantName == 'ansible_test3' - query_all.current.1.leakInternalSubnet.attributes.ip == '1.1.1.2' - query_all.current.1.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test' - query_all.current.1.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - - query.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' - - query.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - attributes_list_query.0.ctxName == 'test2' + - attributes_list_query.0.tenantName == 'ansible_test3' + - attributes_list_query.1.ctxName == 'test3' + - attributes_list_query.1.tenantName == 'ansible_test3' - leak_sub_absent.proposed == {} - + - name: delete leak internal subnet cisco.aci.aci_vrf_leak_internal_subnet: <<: *aci_vrf_present From caa1511a06ed837116c64e68e8339b53ea43f3c2 Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Thu, 13 Jul 2023 11:12:22 -0500 Subject: [PATCH 29/30] [ignore] fixed documentation for leak internal subnet --- plugins/modules/aci_vrf_leak_internal_subnet.py | 4 ++-- .../targets/aci_vrf_leak_internal_subnet/tasks/main.yml | 1 - 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/plugins/modules/aci_vrf_leak_internal_subnet.py b/plugins/modules/aci_vrf_leak_internal_subnet.py index a43bc6378..67432de61 100644 --- a/plugins/modules/aci_vrf_leak_internal_subnet.py +++ b/plugins/modules/aci_vrf_leak_internal_subnet.py @@ -1,7 +1,7 @@ #!/usr/bin/python # -*- coding: utf-8 -*- -# Copyright: (c) 2023, <> (@abmughal) +# Copyright: (c) 2023, Abraham Mughal (@abmughal) abmughal@cisco.com # 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 @@ -291,7 +291,7 @@ def main(): argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["tenant", "vrf", "leak_to"]], + ["state", "absent", ["tenant", "vrf"]], ["state", "present", ["tenant", "vrf", "leak_to"]], ], ) diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index ee3c89f1e..a1a2d957e 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -207,7 +207,6 @@ - name: delete asserts assert: that: - # change to current - leak_sub_delete is changed - leak_sub_delete.previous != [] - leak_sub_delete.current.0.leakInternalSubnet.children | length == 1 From 3b44897b9f3163560be71cd76eceecb9661c43cf Mon Sep 17 00:00:00 2001 From: Abraham Mughal Date: Fri, 14 Jul 2023 11:45:43 -0500 Subject: [PATCH 30/30] [ignore] added test for leak internal subnet --- .../tasks/main.yml | 27 ++++++++++++++----- 1 file changed, 21 insertions(+), 6 deletions(-) diff --git a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml index a1a2d957e..2455f24e4 100644 --- a/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml +++ b/tests/integration/targets/aci_vrf_leak_internal_subnet/tasks/main.yml @@ -183,19 +183,24 @@ - attributes_list_query.1.ctxName == 'test3' - attributes_list_query.1.tenantName == 'ansible_test3' - leak_sub_absent.proposed == {} - - - name: delete leak internal subnet - cisco.aci.aci_vrf_leak_internal_subnet: + + - name: delete leak internal subnet - check_mode + cisco.aci.aci_vrf_leak_internal_subnet: &aci_delete <<: *aci_vrf_present vrf: test leak_to: - vrf: "test3" tenant: "ansible_test3" ip: 1.1.1.2 + register: leak_sub_delete_check_mode + + - name: delete leak internal subnet + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_delete register: leak_sub_delete - name: delete leak internal subnet again - cisco.aci.aci_vrf_leak_internal_subnet: + cisco.aci.aci_vrf_leak_internal_subnet: &aci_delete_again <<: *aci_vrf_present vrf: test leak_to: @@ -204,10 +209,17 @@ ip: 1.1.1.2 register: leak_sub_delete_2 + - name: delete leak internal subnet idempotency check + cisco.aci.aci_vrf_leak_internal_subnet: + <<: *aci_delete_again + register: leak_sub_delete_idempotency + - name: delete asserts assert: that: - - leak_sub_delete is changed + - leak_sub_delete_check_mode is changed + - leak_sub_delete_check_mode.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' + - leak_sub_delete_check_mode.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' - leak_sub_delete.previous != [] - leak_sub_delete.current.0.leakInternalSubnet.children | length == 1 - leak_sub_delete.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test3' @@ -215,4 +227,7 @@ - leak_sub_delete_2 is changed - leak_sub_delete_2.current.0.leakInternalSubnet.children | length == 1 - leak_sub_delete_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' - - leak_sub_delete_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' \ No newline at end of file + - leak_sub_delete_2.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' + - leak_sub_delete_idempotency is not changed + - leak_sub_delete_idempotency.current.0.leakInternalSubnet.children.0.leakTo.attributes.ctxName == 'test2' + - leak_sub_delete_idempotency.current.0.leakInternalSubnet.children.0.leakTo.attributes.tenantName == 'ansible_test3' \ No newline at end of file