diff --git a/plugins/module_utils/constants.py b/plugins/module_utils/constants.py index 376e621ad..5425a9a5f 100644 --- a/plugins/module_utils/constants.py +++ b/plugins/module_utils/constants.py @@ -264,18 +264,21 @@ ) USEG_ATTRIBUTE_MAPPING = dict( - vm_name=dict(attr_type="vm-name", attr_class="fvVmAttr"), - vm_guest=dict(attr_type="guest-os", attr_class="fvVmAttr"), - vm_host=dict(attr_type="hv", attr_class="fvVmAttr"), - vm_id=dict(attr_type="vm", attr_class="fvVmAttr"), - vmm_domain=dict(attr_type="domain", attr_class="fvVmAttr"), - vm_datacenter=dict(attr_type="rootContName", attr_class="fvVmAttr"), - vm_custom_attr=dict(attr_type="custom-label", attr_class="fvVmAttr"), - vm_tag=dict(attr_type="tag", attr_class="fvVmAttr"), - vm_nic=dict(attr_type="vnic", attr_class="fvVmAttr"), - ip=dict(attr_type="ip", attr_class="fvIpAttr"), - mac=dict(attr_type="mac", attr_class="fvMacAttr"), + ip=dict(attribute_type="ip", attribute_class="fvIpAttr", rn_format="ipattr-{0}"), + mac=dict(attribute_type="mac", attribute_class="fvMacAttr", rn_format="macattr-{0}"), + dns=dict(attribute_type="dns", attribute_class="fvDnsAttr", rn_format="dnsattr-{0}"), + ad_group=dict(attribute_type="ad", attribute_class="fvIdGroupAttr", rn_format="idgattr-[{0}]"), + vm_custom_attr=dict(attribute_type="custom-label", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_vmm_domain=dict(attribute_type="domain", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_operating_system=dict(attribute_type="guest-os", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_hypervisor_id=dict(attribute_type="hv", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_datacenter=dict(attribute_type="rootContName", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_id=dict(attribute_type="vm", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_name=dict(attribute_type="vm-name", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_folder=dict(attribute_type="vm-folder", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_folder_path=dict(attribute_type="vmfolder-path", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_vnic=dict(attribute_type="vnic", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), + vm_tag=dict(attribute_type="tag", attribute_class="fvVmAttr", rn_format="vmattr-{0}"), ) -# useg attribute operator mapping OPERATOR_MAPPING = dict(equals="equals", contains="contains", starts_with="startsWith", ends_with="endsWith") diff --git a/plugins/modules/aci_epg.py b/plugins/modules/aci_epg.py index 47e3d3744..b9faec64e 100644 --- a/plugins/modules/aci_epg.py +++ b/plugins/modules/aci_epg.py @@ -138,26 +138,6 @@ state: present delegate_to: localhost -- Add two new EPG - cisco.aci.aci_epg: - host: apic - username: admin - password: SomeSecretPassword - tenant: production - ap: ticketing - epg: "{{ item.epg }}" - description: Ticketing EPG - bd: "{{ item.bd }}" - priority: unspecified - intra_epg_isolation: unenforced - state: present - delegate_to: localhost - with_items: - - epg: web - bd: web_bd - - epg: database - bd: database_bd - - name: Add a new uSeg EPG cisco.aci.aci_epg: host: apic @@ -174,7 +154,7 @@ state: present delegate_to: localhost -- name: Add a uSeg EPG with criterion match and precedence +- name: Add a uSeg EPG with block statement match and precedence cisco.aci.aci_epg: host: apic username: admin diff --git a/plugins/modules/aci_epg_useg_attribute_simple_statement.py b/plugins/modules/aci_epg_useg_attribute_simple_statement.py index 149c941da..8b2b76eda 100644 --- a/plugins/modules/aci_epg_useg_attribute_simple_statement.py +++ b/plugins/modules/aci_epg_useg_attribute_simple_statement.py @@ -2,6 +2,7 @@ # -*- coding: utf-8 -*- # Copyright: (c) 2023, Christian Kolrep +# Copyright: (c) 2024, Akini Ross # 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 @@ -12,12 +13,10 @@ DOCUMENTATION = r""" --- -module: aci_epg_useg_attribute -short_description: Manage EPG useg Attributes +module: aci_epg_useg_attribute_simple_statement +short_description: Manage EPG useg Attributes Simple Statements (fv:DnsAttr, fv:IdGroupAttr, fv:IpAttr, fv:MacAttr, and fv:VmAttr) description: -- Manage VM Attributes in a microsegment EPG (fv:VmAttr) -- Manage IP Attributes in a microsegment EPG (fv:IpAttr) -- Manage MAC Attributes in a microsegment EPG (fv:MacAttr) +- Manage EPG useg Attributes Simple Statements options: tenant: description: @@ -34,6 +33,16 @@ - The name of an existing end point group. type: str aliases: [ epg_name ] + parent_block_statements: + description: + - The list of parent block statements. + - The order of the provided list matters, assuming the list ["A", "B", "C"]. + - The block statement "A" will be the parent of "B" + - The block statement "A" will be a child of the default block statement. + - The maximum amount of parent block statements is 3. + type: list + elements: str + aliases: [ blocks, parent_blocks ] name: description: - The name of the EPG useg attribute. @@ -41,44 +50,44 @@ aliases: [ useg_attribute_name ] type: description: - - The type of the attribute + - The type of the EPG useg attribute type: str - choices: [ ip, mac, vm_name, vm_guest, vm_host, vm_id, vmm_domain, vm_datacenter, vm_custom_attr, vm_tag, vm_nic ] + required: true + choices: + - ip + - mac + - dns + - ad_group + - vm_custom_attr + - vm_vmm_domain + - vm_operating_system + - vm_hypervisor_id + - vm_datacenter + - vm_id + - vm_name + - vm_folder + - vm_folder_path + - vm_vnic + - vm_tag aliases: [ useg_attribute_type ] operator: description: - - The operator. - - Required for most vm related attribute types. + - The operator of the EPG useg attribute. type: str choices: [ equals, contains, starts_with, ends_with ] category: description: - - The name of the vmware tag category. - - Required for type vm_tag. - - The name of the vmware custom attribute. - - Required for type vm_custom_attr. + - The name of the vmware tag category or vmware custom attribute. type: str aliases: [ custom_attribute ] use_subnet: description: - - Use the EPG subnet definition for ip. - - Used for type ip. - - Mutualy exclusive with value - type: str - choices: [ 'yes', 'no' ] + - Whether to use the EPG subnet definition for ip. + type: bool value: description: - - The value of the useg attribute. + - The value of the EPG useg attribute. type: str - criterion: - description: - - List of existing sub criterions, representing the path to the sub criterion that will contain the useg attribute. - - The order of the provided list matters, assuming the list ["A", "B", "C"]. - - Sub criterion A is chield of the default criterion, B is sub criterion of A and C is sub criterion of B. - - default->A->B->C, the maximum depth of sub criterions is 3. - - Empty list or None uses the default criterion of the EPG. - type: list - elements: str state: description: - Use C(present) or C(absent) for adding or removing. @@ -98,14 +107,15 @@ - module: cisco.aci.aci_ap - module: cisco.aci.aci_epg - name: APIC Management Information Model reference - description: More information about the internal APIC class B(fv:IpAttr) B(fv:MacAttr) B(fv:VmAttr). + description: More information about the internal APIC class B(fv:DnsAttr), B(fv:IdGroupAttr), B(fv:IpAttr), B(fv:MacAttr), and B(fv:VmAttr). link: https://developer.cisco.com/docs/apic-mim-ref/ author: - Christian Kolrep (@Christian-Kolrep) +- Akini Ross (@akinross) """ EXAMPLES = r""" -- name: Add a new vmtag useg attribute for default criterion +- name: Add a new vmtag useg attribute in default block statement cisco.aci.aci_epg_useg_attribute: host: apic username: admin @@ -121,7 +131,7 @@ state: present delegate_to: localhost -- name: Remove an existing vmtag useg attribute from default criterion +- name: Add a new vmtag useg attribute in nested block statement cisco.aci.aci_epg_useg_attribute: host: apic username: admin @@ -130,11 +140,17 @@ ap: anstest epg: anstest name: vmtagprod + parent_block_statements: + - block_a + - block_b type: vmtag - state: absent + category: Environment + operator: equals + value: Production + state: present delegate_to: localhost -- name: Query a specific vmtag useg attribute in default criterion +- name: Query a specific vmtag useg attribute in default block statement cisco.aci.aci_epg_useg_attribute: host: apic username: admin @@ -148,7 +164,7 @@ delegate_to: localhost register: query_result -- name: Query all vmtag useg attributes in default criterion +- name: Query all vmtag useg attributes cisco.aci.aci_epg_useg_attribute: host: apic username: admin @@ -157,6 +173,19 @@ type: vmtag delegate_to: localhost register: query_result + +- name: Remove an existing vmtag useg attribute from default block statement + cisco.aci.aci_epg_useg_attribute: + host: apic + username: admin + password: SomeSecretPassword + tenant: anstest + ap: anstest + epg: anstest + name: vmtagprod + type: vmtag + state: absent + delegate_to: localhost """ RETURN = r""" @@ -277,21 +306,21 @@ def main(): epg=dict(type="str", aliases=["epg_name"]), # Not required for querying all objects state=dict(type="str", default="present", choices=["absent", "present", "query"]), tenant=dict(type="str", aliases=["tenant_name"]), # Not required for querying all objects - criterion=dict(type="list", elements="str"), # Criterion list + parent_block_statements=dict(type="list", elements="str", aliases=["parent_blocks", "blocks"]), name=dict(type="str", aliases=["useg_attribute_name"]), - type=dict(type="str", choices=list(USEG_ATTRIBUTE_MAPPING.keys()), aliases=["useg_attribute_type"]), + type=dict(type="str", required=True, choices=list(USEG_ATTRIBUTE_MAPPING.keys()), aliases=["useg_attribute_type"]), operator=dict(type="str", choices=list(OPERATOR_MAPPING.keys())), category=dict(type="str", aliases=["custom_attribute"]), value=dict(type="str"), - use_subnet=dict(type="str", choices=["yes", "no"]), + use_subnet=dict(type="bool"), ) module = AnsibleModule( argument_spec=argument_spec, supports_check_mode=True, required_if=[ - ["state", "absent", ["ap", "epg", "tenant", "name", "type"]], - ["state", "present", ["ap", "epg", "tenant", "name", "type"]], + ["state", "absent", ["ap", "epg", "tenant", "name"]], + ["state", "present", ["ap", "epg", "tenant", "name"]], ], ) @@ -301,57 +330,35 @@ def main(): epg = module.params.get("epg") state = module.params.get("state") tenant = module.params.get("tenant") - criterion = module.params.get("criterion") - useg_attr_name = module.params.get("name") - useg_attr_type = module.params.get("type") - useg_attr_value = module.params.get("value") - useg_attr_operator = module.params.get("operator") - useg_attr_category = module.params.get("category") - useg_attr_use_subnet = module.params.get("use_subnet") - - # useg attribute class and config - attr_class = USEG_ATTRIBUTE_MAPPING[useg_attr_type]["attr_class"] - attr_type = USEG_ATTRIBUTE_MAPPING[useg_attr_type]["attr_type"] - attr_config = dict(name=useg_attr_name) - - if attr_class == "fvVmAttr": - attr_rn = "vmattr-{0}".format(useg_attr_name) - attr_config.update(type=attr_type) - if useg_attr_value is not None: - attr_config.update(value=useg_attr_value) - if useg_attr_operator is not None: - attr_config.update(operator=OPERATOR_MAPPING[useg_attr_operator]) - - if useg_attr_type == "vm_custom_attr": - if useg_attr_category is not None: - attr_config.update(labelName=useg_attr_category) - elif useg_attr_type == "vm_tag": - if useg_attr_category is not None: - attr_config.update(category=useg_attr_category) - - elif attr_class == "fvIpAttr": - attr_rn = "ipattr-{0}".format(useg_attr_name) - if useg_attr_use_subnet == "yes": - attr_config.update(usefvSubnet=useg_attr_use_subnet) - else: - if useg_attr_value is not None: - attr_config.update(ip=useg_attr_value) - - elif attr_class == "fvMacAttr": - attr_rn = "macattr-{0}".format(useg_attr_name) - if useg_attr_value is not None: - attr_config.update(mac=useg_attr_value.upper()) - - # criterion class and building relative name - crtrn_rn = "crtrn" - crtrn_class = "fvCrtrn" - crtrn_name = "default" - if criterion: - if len(criterion) > 3: - module.fail_json(msg="Depth of sub criterion exceeds maximum limit 3.") - crtrn_name = criterion[-1] - crtrn_class = "fvSCrtrn" - crtrn_rn = "crtrn/crtrn-" + "/crtrn-".join(criterion) + blocks = module.params.get("parent_block_statements") + name = module.params.get("name") + attribute_type = module.params.get("type") + value = module.params.get("value") + operator = module.params.get("operator") + category = module.params.get("category") + use_subnet = aci.boolean(module.params.get("use_subnet")) + + # Excluding below classes from the module: + # fvProtoAttr: + # Was used in AVS, but it is not longer in use. + # fvUsegBDCont: + # Was part of a feature that allowed uSeg attributes to be applied at VRF (instead of BD) level. + # It has been since deprecated and we no longer allow setting the scope at fvCtrn to scope-vrf. + # This type of functionality has been replaced by the ESG feature. + attribute_class = USEG_ATTRIBUTE_MAPPING[attribute_type]["attribute_class"] + attribute_rn = USEG_ATTRIBUTE_MAPPING[attribute_type]["rn_format"].format(name) + attribute_type = USEG_ATTRIBUTE_MAPPING[attribute_type]["attribute_type"] + + if blocks: + if len(blocks) > 3: + module.fail_json(msg="{0} block statements are provided but the maximum amount of parent_block_statements is 3".format(len(blocks))) + parent_blocks_class = "fvSCrtrn" + parent_blocks_rn = "crtrn/crtrn-{0}".format("/crtrn-".join(blocks)) + parent_blocks_name = blocks[-1] + else: + parent_blocks_class = "fvCrtrn" + parent_blocks_rn = "crtrn" + parent_blocks_name = "default" aci.construct_url( root_class=dict( @@ -373,25 +380,49 @@ def main(): target_filter={"name": epg}, ), subclass_3=dict( - aci_class=crtrn_class, - aci_rn=crtrn_rn, - module_object=crtrn_name, - target_filter={"name": crtrn_name}, + aci_class=parent_blocks_class, + aci_rn=parent_blocks_rn, + module_object=parent_blocks_name, + target_filter={"name": parent_blocks_name}, ), subclass_4=dict( - aci_class=attr_class, - aci_rn=attr_rn, - module_object=useg_attr_name, - target_filter={"name": useg_attr_name}, + aci_class=attribute_class, + aci_rn=attribute_rn, + module_object=name, + target_filter={"name": name}, ), ) aci.get_existing() if state == "present": - aci.payload(aci_class=attr_class, class_config=attr_config) + class_config = dict(name=name) + + if attribute_class == "fvVmAttr": + class_config.update(type=attribute_type) + class_config.update(operator=OPERATOR_MAPPING.get(operator)) + class_config.update(value=value) + if attribute_type == "tag": + class_config.update(category=category) + elif attribute_type == "custom-label": + class_config.update(labelName=category) + + elif attribute_class == "fvIpAttr": + class_config.update(usefvSubnet=use_subnet) + class_config.update(ip=value) + + elif attribute_class == "fvMacAttr": + class_config.update(mac=value.upper()) + + elif attribute_class == "fvDnsAttr": + class_config.update(filter=value) + + elif attribute_class == "fvIdGroupAttr": + class_config.update(selector=value) + + aci.payload(aci_class=attribute_class, class_config=class_config) - aci.get_diff(aci_class=attr_class) + aci.get_diff(aci_class=attribute_class) aci.post_config() diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/ip_attr.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/ip_attr.yml deleted file mode 100644 index 260d38b22..000000000 --- a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/ip_attr.yml +++ /dev/null @@ -1,212 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) - -# 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 - -# CLEAN ENVIRONMENT -- 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: Query system information - aci_system: - <<: *aci_info - id: 1 - state: query - register: version - -- name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - -- name: Execute tasks only for non-cloud sites - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_test_useg - state: present - register: tenant_present - - - name: ensure ap exists for tests to kick off - cisco.aci.aci_ap: &aci_ap_present - <<: *aci_tenant_present - ap: anstest - register: ap_present - - - name: ensure bd exists for tests to kick off - cisco.aci.aci_bd: &aci_bd_present - <<: *aci_tenant_present - bd: anstest - register: bd_present - - - name: ensure useg epg exists for tests to kick off - cisco.aci.aci_epg: &aci_epg_present - <<: *aci_ap_present - epg: anstest - bd: anstest - useg: yes - register: epg_present - - - name: ensure useg attribute of type ip not exists for tests to kick off - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: ip - state: absent - - - name: Add a useg attribute of type ip ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_ip_present - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: ip - value: "1.1.1.1" - check_mode: true - register: ip_present_check_mode - - - name: Add a useg attribute of type ip - creation works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - register: ip_present - - - name: Add a 2nd useg attribute of type ip - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest2 - useg_attribute_type: ip - value: "10.10.10.10" - register: ip_present_2 - - - name: Add a useg attribute of type ip - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - register: ip_present_idempotent - - - name: Update a useg attribute of type ip - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - value: "2.2.2.2" - register: ip_update - - - name: Update a useg attribute of type ip to use subnet - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - ip: "{{ fake_var | default(omit) }}" - use_subnet: yes - register: ip_update_use_subnet - - - name: Add a useg attribute of type ip - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - epg: "{{ fake_var | default(omit) }}" - ignore_errors: true - register: ip_present_missing_params - - - name: Add a useg attribute of type ip - criterion limit - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - criterion: - - A - - B - - C - - D - ignore_errors: true - register: ip_present_criterion_limit - - - name: ip present assertions - assert: - that: - - ip_present_check_mode is changed - - ip_present is changed - - ip_present.previous == [] - - ip_present.sent.fvIpAttr.attributes.name == 'anstest' - - ip_present.sent.fvIpAttr.attributes.ip == '1.1.1.1' - - ip_present.current.0.fvIpAttr.attributes.annotation == 'orchestrator:ansible' - - ip_present_idempotent is not changed - - ip_present_idempotent.sent == {} - - ip_update is changed - - ip_update.sent.fvIpAttr.attributes.ip == '2.2.2.2' - - ip_update_use_subnet.sent.fvIpAttr.attributes.usefvSubnet == 'yes' - - ip_present_missing_params is failed - - 'ip_present_missing_params.msg == "state is present but all of the following are missing: epg"' - - ip_present_criterion_limit is failed - - 'ip_present_criterion_limit.msg == "Depth of sub criterion exceeds maximum limit 3."' - - - name: Query a useg attribute of type ip - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - state: query - register: ip_query - - - name: Query all useg attributes of type ip - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_present - useg_attribute_name: "{{ fake_var | default(omit) }}" - state: query - register: ip_query_all - - - name: ip query assertions - assert: - that: - - ip_query is not changed - - ip_query.current | length == 1 - - ip_query_all is not changed - - ip_query_all.current.0.fvCrtrn.children | length > 1 - - - name: Delete a useg attribute of type ip ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_ip_absent - <<: *aci_ip_present - state: absent - check_mode: true - register: ip_absent_check_mode - - - name: Delete a useg attribute of type ip - delete works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_absent - register: ip_absent - - - name: Delete a useg attribute of type ip - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_absent - register: ip_absent_idempotent - - - name: Delete a useg attribute of type ip - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ip_absent - epg: "{{ fake_var | default(omit) }}" - state: absent - ignore_errors: true - register: ip_absent_missing_params - - - name: ip absent assertions - assert: - that: - - ip_absent_check_mode is changed - - ip_absent_check_mode.previous != [] - - ip_absent is changed - - ip_absent.previous == ip_absent_check_mode.previous - - ip_absent_idempotent is not changed - - ip_absent_idempotent.previous == [] - - ip_absent_missing_params is failed - - 'ip_absent_missing_params.msg == "state is absent but all of the following are missing: epg"' - - - name: remove tenant - cleanup - cisco.aci.aci_tenant: - <<: *aci_tenant_present - state: absent - when: tenant_present is changed diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/mac_attr.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/mac_attr.yml deleted file mode 100644 index c3147bbb0..000000000 --- a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/mac_attr.yml +++ /dev/null @@ -1,191 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) - -# 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 - -# CLEAN ENVIRONMENT -- 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: Query system information - aci_system: - <<: *aci_info - id: 1 - state: query - register: version - -- name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - -- name: Execute tasks only for non-cloud sites - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_test_useg - state: present - register: tenant_present - - - name: ensure ap exists for tests to kick off - cisco.aci.aci_ap: &aci_ap_present - <<: *aci_tenant_present - ap: anstest - register: ap_present - - - name: ensure bd exists for tests to kick off - cisco.aci.aci_bd: &aci_bd_present - <<: *aci_tenant_present - bd: anstest - register: bd_present - - - name: ensure useg epg exists for tests to kick off - cisco.aci.aci_epg: &aci_epg_present - <<: *aci_ap_present - epg: anstest - bd: anstest - useg: yes - register: epg_present - - - name: ensure useg attribute of type mac not exists for tests to kick off - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: mac - state: absent - - - name: Add a useg attribute of type mac ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_mac_present - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: mac - value: "aa:bb:cc:dd:ee:ff" - check_mode: true - register: mac_present_check_mode - - - name: Add a useg attribute of type mac - creation works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_present - register: mac_present - - - name: Add a 2nd useg attribute of type mac - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest2 - useg_attribute_type: mac - value: "aa:bb:cc:dd:ee:00" - register: mac_present_2 - - - name: Add a useg attribute of type mac - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_present - register: mac_present_idempotent - - - name: Update a useg attribute of type mac - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_present - value: "aa:bb:cc:dd:ee:11" - register: mac_update - - - name: Add a useg attribute of type mac - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_present - epg: "{{ fake_var | default(omit) }}" - ignore_errors: true - register: mac_present_missing_params - - - name: mac present assertions - assert: - that: - - mac_present_check_mode is changed - - mac_present is changed - - mac_present.previous == [] - - mac_present.sent.fvMacAttr.attributes.name == 'anstest' - - mac_present.sent.fvMacAttr.attributes.mac == 'AA:BB:CC:DD:EE:FF' - - mac_present.current.0.fvMacAttr.attributes.annotation == 'orchestrator:ansible' - - mac_present_idempotent is not changed - - mac_present_idempotent.sent == {} - - mac_update is changed - - mac_update.sent.fvMacAttr.attributes.mac == 'AA:BB:CC:DD:EE:11' - - mac_present_missing_params is failed - - 'mac_present_missing_params.msg == "state is present but all of the following are missing: epg"' - - - name: Query a useg attribute of type mac - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_present - state: query - register: mac_query - - - name: Query all useg attributes of type mac - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_present - useg_attribute_name: "{{ fake_var | default(omit) }}" - state: query - register: mac_query_all - - - name: mac query assertions - assert: - that: - - mac_query is not changed - - mac_query.current | length == 1 - - mac_query_all is not changed - - mac_query_all.current.0.fvCrtrn.children | length > 1 - - - name: Delete a useg attribute of type mac ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_mac_absent - <<: *aci_mac_present - state: absent - check_mode: true - register: mac_absent_check_mode - - - name: Delete a useg attribute of type mac - delete works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_absent - register: mac_absent - - - name: Delete a useg attribute of type mac - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_absent - register: mac_absent_idempotent - - - name: Delete a useg attribute of type mac - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_mac_absent - epg: "{{ fake_var | default(omit) }}" - state: absent - ignore_errors: true - register: mac_absent_missing_params - - - name: mac absent assertions - assert: - that: - - mac_absent_check_mode is changed - - mac_absent_check_mode.previous != [] - - mac_absent is changed - - mac_absent.previous == mac_absent_check_mode.previous - - mac_absent_idempotent is not changed - - mac_absent_idempotent.previous == [] - - mac_absent_missing_params is failed - - 'mac_absent_missing_params.msg == "state is absent but all of the following are missing: epg"' - - - name: remove tenant - cleanup - cisco.aci.aci_tenant: - <<: *aci_tenant_present - state: absent - when: tenant_present is changed diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml index 4b4971824..20e9371a9 100644 --- a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml +++ b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/main.yml @@ -1,19 +1,265 @@ # Test code for the ACI modules # Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) +# Copyright: (c) 2024, Akini Ross (@akinross) # GNU General Public License v3.0+ (see LICENSE or https://www.gnu.org/licenses/gpl-3.0.txt) -- name: test fvIpAttr - include_tasks: ip_attr.yml +- name: Test that we have an ACI APIC host, ACI username and ACI password + ansible.builtin.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 fvMacAttr - include_tasks: mac_attr.yml +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' -- name: test fvVmAttr type vm_custom_attr - include_tasks: vm_custom_attr.yml +- name: Verify Cloud and Non-Cloud Sites in use. + ansible.builtin.include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml -- name: test fvVmAttr type vm_name - include_tasks: vm_name.yml +- name: Execute tasks only for non-cloud sites ( clean after ) + when: + - query_cloud.current == [] + block: -- name: test fvVmAttr type vm_tag - include_tasks: vm_tag.yml + # CLEAN TEST ENVIRONMENT + - name: Ensure tenant removed + cisco.aci.aci_tenant: &aci_tenant_absent + <<: *aci_info + state: absent + tenant: ansible_test + + # SETUP TEST ENVIRONMENT + - name: Create tenant + cisco.aci.aci_tenant: &aci_tenant_present + <<: *aci_tenant_absent + state: present + + - name: Create AP + cisco.aci.aci_ap: &aci_ap + <<: *aci_tenant_present + ap: ansible_test + + - name: Create uSeg EPG + cisco.aci.aci_epg: + <<: *aci_ap + epg: ansible_test_1 + bd: ansible_test + useg: yes + + - name: Create block statement block_a + cisco.aci.aci_epg_useg_attribute_block_statement: &block + <<: *aci_ap + epg: ansible_test_1 + name: block_a + + - name: Create block statement block_b + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block + name: block_b + parent_block_statements: + - block_a + + - name: Create block statement block_c + cisco.aci.aci_epg_useg_attribute_block_statement: + <<: *block + name: block_c + parent_block_statements: + - block_a + - block_b + + # TEST THAT ALL LEVELS OF BLOCK STATEMENTS WORK WITH THE VM_NAME SIMPLE STATEMENT TYPE + - name: Execute tests for each block statement + ansible.builtin.include_tasks: simple_block_levels.yml + loop: + - [] + - [block_a] + - [block_a, block_b] + - [block_a, block_b, block_c] + loop_control: + loop_var: parent_block_statements + + # INPUT TEST FOR OPERATOR INPUT + - name: Create simple statement with all operator input options + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_ap + epg: ansible_test_1 + name: ansible_test_vm_name + type: vm_name + operator: "{{ item }}" + value: ansible_test_vm_name_value + register: nm_operators + loop: + - contains + - equals + - starts_with + - ends_with + + - name: Assert simple statement with all operator input options + ansible.builtin.assert: + that: + - nm_operators.results | length == 4 + - nm_operators.results.0.changed == true + - nm_operators.results.0.current.0.fvVmAttr.attributes.operator == "contains" + - nm_operators.results.1.changed == true + - nm_operators.results.1.current.0.fvVmAttr.attributes.operator == "equals" + - nm_operators.results.2.changed == true + - nm_operators.results.2.current.0.fvVmAttr.attributes.operator == "startsWith" + - nm_operators.results.3.changed == true + - nm_operators.results.3.current.0.fvVmAttr.attributes.operator == "endsWith" + + # INPUT TESTS FOR TYPES + - name: Create simple statement with all type input options + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_ap + epg: ansible_test_1 + name: "{{ item.name }}" + type: "{{ item.type }}" + operator: "{{ item.operator }}" + category: "{{ item.category }}" + value: "{{ item.value }}" + use_subnet: "{{ item.use_subnet | default(omit) }}" + register: nm_types + loop: + - { name: ansible_test_ip_1, type: ip, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: 10.0.0.1 } + - { name: ansible_test_ip_2, type: ip, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: true, value: "{{ fake_var | default(omit) }}" } + - { name: ansible_test_mac, type: mac, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "aa:bb:cc:dd:ee:ff" } + - { name: ansible_test_dns, type: dns, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "dns_filter" } + - { name: ansible_test_ad_group, type: ad_group, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "ad_group_selector" } + - { name: ansible_test_vm_custom_attr, type: vm_custom_attr, operator: "contains", category: "custom_attribute", use_subnet: "{{ fake_var | default(omit) }}", value: "custom_attribute_value" } + - { name: ansible_test_vm_vmm_domain, type: vm_vmm_domain, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_vmm_domain_value" } + - { name: ansible_test_vm_operating_system, type: vm_operating_system, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_operating_system_value" } + - { name: ansible_test_vm_hypervisor_id, type: vm_hypervisor_id, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_hypervisor_id_value" } + - { name: ansible_test_vm_datacenter, type: vm_datacenter, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_datacenter_value" } + - { name: ansible_test_vm_id, type: vm_id, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_id_value" } + - { name: ansible_test_vm_name, type: vm_name, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_name_value" } + - { name: ansible_test_vm_folder, type: vm_folder, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_folder_value" } + - { name: ansible_test_vm_folder_path, type: vm_folder_path, operator: "{{ fake_var | default(omit) }}", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_folder_path_value" } + - { name: ansible_test_vm_vnic, type: vm_vnic, operator: "contains", category: "{{ fake_var | default(omit) }}", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_vnic_value" } + - { name: ansible_test_vm_tag, type: vm_tag, operator: "equals", category: "vm_attribute", use_subnet: "{{ fake_var | default(omit) }}", value: "vm_attribute_value" } + ignore_errors: true # ignore errors is set to handle the ad group configuration which is not configurable in the lab environment, so error message is expected to ensure payload is sent + + - name: Debug + ansible.builtin.debug: + msg: "{{ nm_types }}" + + - name: Assert create simple statement with all type input options + ansible.builtin.assert: + that: + - nm_types.results | length == 16 + - nm_types.results.0.changed == true + - nm_types.results.0.current.0.fvIpAttr.attributes.name == "ansible_test_ip_1" + - nm_types.results.0.current.0.fvIpAttr.attributes.ip == "10.0.0.1" + - nm_types.results.0.current.0.fvIpAttr.attributes.usefvSubnet == "no" + - nm_types.results.1.changed == true + - nm_types.results.1.current.0.fvIpAttr.attributes.name == "ansible_test_ip_2" + - nm_types.results.1.current.0.fvIpAttr.attributes.ip == "0.0.0.0" + - nm_types.results.1.current.0.fvIpAttr.attributes.usefvSubnet == "yes" + - nm_types.results.2.changed == true + - nm_types.results.2.current.0.fvMacAttr.attributes.name == "ansible_test_mac" + - nm_types.results.2.current.0.fvMacAttr.attributes.mac == "AA:BB:CC:DD:EE:FF" + - nm_types.results.3.changed == true + - nm_types.results.3.current.0.fvDnsAttr.attributes.name == "ansible_test_dns" + - nm_types.results.3.current.0.fvDnsAttr.attributes.filter == "dns_filter" + - nm_types.results.4.failed == true + - nm_types.results.4.msg == "APIC Error 400{{":"}} Invalid request. Can not contain child 'idgattr-[ad_group_selector]' under parent 'uni/tn-ansible_test/ap-ansible_test/epg-ansible_test_1/crtrn/idgattr-[ansible_test_ad_group]'" + - nm_types.results.5.changed == true + - nm_types.results.5.current.0.fvVmAttr.attributes.name == "ansible_test_vm_custom_attr" + - nm_types.results.5.current.0.fvVmAttr.attributes.labelName == "custom_attribute" + - nm_types.results.5.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.5.current.0.fvVmAttr.attributes.type == "custom-label" + - nm_types.results.5.current.0.fvVmAttr.attributes.value == "custom_attribute_value" + - nm_types.results.6.changed == true + - nm_types.results.6.current.0.fvVmAttr.attributes.name == "ansible_test_vm_vmm_domain" + - nm_types.results.6.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.6.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.6.current.0.fvVmAttr.attributes.type == "domain" + - nm_types.results.6.current.0.fvVmAttr.attributes.value == "vm_vmm_domain_value" + - nm_types.results.7.changed == true + - nm_types.results.7.current.0.fvVmAttr.attributes.name == "ansible_test_vm_operating_system" + - nm_types.results.7.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.7.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.7.current.0.fvVmAttr.attributes.type == "guest-os" + - nm_types.results.7.current.0.fvVmAttr.attributes.value == "vm_operating_system_value" + - nm_types.results.8.changed == true + - nm_types.results.8.current.0.fvVmAttr.attributes.name == "ansible_test_vm_hypervisor_id" + - nm_types.results.8.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.8.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.8.current.0.fvVmAttr.attributes.type == "hv" + - nm_types.results.8.current.0.fvVmAttr.attributes.value == "vm_hypervisor_id_value" + - nm_types.results.9.changed == true + - nm_types.results.9.current.0.fvVmAttr.attributes.name == "ansible_test_vm_datacenter" + - nm_types.results.9.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.9.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.9.current.0.fvVmAttr.attributes.type == "rootContName" + - nm_types.results.9.current.0.fvVmAttr.attributes.value == "vm_datacenter_value" + - nm_types.results.10.changed == true + - nm_types.results.10.current.0.fvVmAttr.attributes.name == "ansible_test_vm_id" + - nm_types.results.10.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.10.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.10.current.0.fvVmAttr.attributes.type == "vm" + - nm_types.results.10.current.0.fvVmAttr.attributes.value == "vm_id_value" + - nm_types.results.11.changed == true + - nm_types.results.11.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_types.results.11.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.11.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.11.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_types.results.11.current.0.fvVmAttr.attributes.value == "vm_name_value" + - nm_types.results.12.changed == true + - nm_types.results.12.current.0.fvVmAttr.attributes.name == "ansible_test_vm_folder" + - nm_types.results.12.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.12.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.12.current.0.fvVmAttr.attributes.type == "vm-folder" + - nm_types.results.12.current.0.fvVmAttr.attributes.value == "vm_folder_value" + - nm_types.results.13.changed == true + - nm_types.results.13.current.0.fvVmAttr.attributes.name == "ansible_test_vm_folder_path" + - nm_types.results.13.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.13.current.0.fvVmAttr.attributes.operator == "equals" + - nm_types.results.13.current.0.fvVmAttr.attributes.type == "vmfolder-path" + - nm_types.results.13.current.0.fvVmAttr.attributes.value == "vm_folder_path_value" + - nm_types.results.14.changed == true + - nm_types.results.14.current.0.fvVmAttr.attributes.name == "ansible_test_vm_vnic" + - nm_types.results.14.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.14.current.0.fvVmAttr.attributes.operator == "contains" + - nm_types.results.14.current.0.fvVmAttr.attributes.type == "vnic" + - nm_types.results.14.current.0.fvVmAttr.attributes.value == "vm_vnic_value" + - nm_types.results.15.changed == true + - nm_types.results.15.current.0.fvVmAttr.attributes.name == "ansible_test_vm_tag" + - nm_types.results.15.current.0.fvVmAttr.attributes.labelName == "" + - nm_types.results.15.current.0.fvVmAttr.attributes.operator == "equals" + - nm_types.results.15.current.0.fvVmAttr.attributes.type == "tag" + - nm_types.results.15.current.0.fvVmAttr.attributes.value == "vm_attribute_value" + + # ERROR TESTS + - name: Create simple statement with too many parents (error) + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_ap + epg: ansible_test_1 + parent_block_statements: + - block_a + - block_b + - block_c + - block_d + name: ansible_test_vm_name + type: vm_name + operator: contains + value: ansible_test_vm_name_value + register: err_too_many_blocks + ignore_errors: true + + - name: Assert create block statement in default block + ansible.builtin.assert: + that: + - err_too_many_blocks is failed + - err_too_many_blocks.msg == "4 block statements are provided but the maximum amount of parent_block_statements is 3" + + # CLEAN TEST ENVIRONMENT + - name: Remove tenant + cisco.aci.aci_tenant: + <<: *aci_tenant_absent diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml new file mode 100644 index 000000000..b37a5c7d5 --- /dev/null +++ b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/simple_block_levels.yml @@ -0,0 +1,156 @@ +- name: Set vars + ansible.builtin.set_fact: + aci_info: &aci_info + host: "{{ aci_hostname }}" + username: "{{ aci_username }}" + password: "{{ aci_password }}" + validate_certs: '{{ aci_validate_certs | default(false) }}' + use_ssl: '{{ aci_use_ssl | default(true) }}' + use_proxy: '{{ aci_use_proxy | default(true) }}' + output_level: '{{ aci_output_level | default("debug") }}' + aci_epg: &aci_epg + tenant: ansible_test + ap: ansible_test + epg: ansible_test_1 + +# CREATE AND UPDATE TESTS +- name: Create simple statement in block statement (check mode) + cisco.aci.aci_epg_useg_attribute_simple_statement: &simple_present + <<: *aci_info + <<: *aci_epg + parent_block_statements: "{{ parent_block_statements }}" + name: ansible_test_vm_name + type: vm_name + operator: contains + value: ansible_test_vm_name_value + check_mode: true + register: cm_create_simple + +- name: Create simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present + register: nm_create_simple + +- name: Create simple statement in block statement again + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present + register: nm_create_simple_again + +- name: Assert create simple statement in block statement + ansible.builtin.assert: + that: + - cm_create_simple is changed + - cm_create_simple.previous == [] + - cm_create_simple.current == [] + - cm_create_simple.proposed.fvVmAttr.attributes.name == "ansible_test_vm_name" + - cm_create_simple.proposed.fvVmAttr.attributes.type == "vm-name" + - cm_create_simple.proposed.fvVmAttr.attributes.operator == "contains" + - cm_create_simple.proposed.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_create_simple is changed + - nm_create_simple.previous == [] + - nm_create_simple.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_create_simple.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple.current.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_create_simple_again is not changed + - nm_create_simple_again.previous.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_create_simple_again.previous.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_again.previous.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple_again.previous.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_create_simple_again.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_create_simple_again.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_again.current.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple_again.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + +# QUERY TESTS +- name: Create another simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: &simple_present_update + <<: *simple_present + name: ansible_test_vm_name_2 + type: vm_name + operator: contains + value: ansible_test_vm_name_value_2 + register: nm_create_simple_2 + +- name: Create another simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present_update + operator: equals + value: ansible_test_vm_name_value_3 + register: nm_create_simple_2_update + +- name: Assert updates + ansible.builtin.assert: + that: + - nm_create_simple_2.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name_2" + - nm_create_simple_2.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_2.current.0.fvVmAttr.attributes.operator == "contains" + - nm_create_simple_2.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value_2" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name_2" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.type == "vm-name" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.operator == "equals" + - nm_create_simple_2_update.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value_3" + +- name: Query simple statement in block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_present + state: query + register: query_one + +- name: Query all simple statements of type vm_name + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *aci_info + type: vm_name + state: query + register: query_all + +- name: Assert queries + ansible.builtin.assert: + that: + - query_one.current | length == 1 + - query_one.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - query_one.current.0.fvVmAttr.attributes.type == "vm-name" + - query_one.current.0.fvVmAttr.attributes.operator == "contains" + - query_one.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - query_all.current | length >= 2 + +# REMOVE TESTS +- name: Remove simple statement from block statement (check mode) + cisco.aci.aci_epg_useg_attribute_simple_statement: &simple_absent + <<: *simple_present + state: absent + check_mode: true + register: cm_remove_simple + +- name: Remove simple statement from block statement + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_absent + register: nm_remove_simple + +- name: Remove simple statement from block statement again + cisco.aci.aci_epg_useg_attribute_simple_statement: + <<: *simple_absent + register: nm_remove_simple_again + +- name: Assert remove simple statement from block statement + ansible.builtin.assert: + that: + - cm_remove_simple is changed + - cm_remove_simple.previous.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - cm_remove_simple.previous.0.fvVmAttr.attributes.type == "vm-name" + - cm_remove_simple.previous.0.fvVmAttr.attributes.operator == "contains" + - cm_remove_simple.previous.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - cm_remove_simple.current.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - cm_remove_simple.current.0.fvVmAttr.attributes.type == "vm-name" + - cm_remove_simple.current.0.fvVmAttr.attributes.operator == "contains" + - cm_remove_simple.current.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - cm_remove_simple.proposed == {} + - nm_remove_simple is changed + - nm_remove_simple.previous.0.fvVmAttr.attributes.name == "ansible_test_vm_name" + - nm_remove_simple.previous.0.fvVmAttr.attributes.type == "vm-name" + - nm_remove_simple.previous.0.fvVmAttr.attributes.operator == "contains" + - nm_remove_simple.previous.0.fvVmAttr.attributes.value == "ansible_test_vm_name_value" + - nm_remove_simple.current == [] + - nm_remove_simple_again is not changed + - nm_remove_simple_again.previous == [] + - nm_remove_simple_again.current == [] diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_custom_attr.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_custom_attr.yml deleted file mode 100644 index f3391afc9..000000000 --- a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_custom_attr.yml +++ /dev/null @@ -1,204 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) - -# 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 - -# CLEAN ENVIRONMENT -- 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: Query system information - aci_system: - <<: *aci_info - id: 1 - state: query - register: version - -- name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - -- name: Execute tasks only for non-cloud sites - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_test_useg - state: present - register: tenant_present - - - name: ensure ap exists for tests to kick off - cisco.aci.aci_ap: &aci_ap_present - <<: *aci_tenant_present - ap: anstest - register: ap_present - - - name: ensure bd exists for tests to kick off - cisco.aci.aci_bd: &aci_bd_present - <<: *aci_tenant_present - bd: anstest - register: bd_present - - - name: ensure useg epg exists for tests to kick off - cisco.aci.aci_epg: &aci_epg_present - <<: *aci_ap_present - epg: anstest - bd: anstest - useg: yes - register: epg_present - - - name: ensure useg attribute of type vm_custom_attr not exists for tests to kick off - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: vm_custom_attr - state: absent - - - name: Add a useg attribute of type vm_custom_attr ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_vm_custom_attr_present - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: vm_custom_attr - operator: equals - custom_attribute: ENVIRONMENT - value: PROD - check_mode: true - register: vm_custom_attr_present_check_mode - - - name: Add a useg attribute of type vm_custom_attr - creation works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_present - register: vm_custom_attr_present - - - name: Add a 2nd useg attribute of type vm_custom_attr - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest2 - useg_attribute_type: vm_custom_attr - operator: equals - custom_attribute: TIER - value: GOLD - state: present - register: vm_custom_attr_present_2 - - - name: Add a useg attribute of type vm_custom_attr - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_present - register: vm_custom_attr_present_idempotent - - - name: Update a useg attribute of type vm_custom_attr - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_present - operator: contains - custom_attribute: OS - value: REDHAT - - register: vm_custom_attr_update - - - name: Add a useg attribute of type vm_custom_attr - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_present - epg: "{{ fake_var | default(omit) }}" - ignore_errors: true - register: vm_custom_attr_present_missing_params - - - name: vm_custom_attr present assertions - assert: - that: - - vm_custom_attr_present_check_mode is changed - - vm_custom_attr_present is changed - - vm_custom_attr_present.previous == [] - - vm_custom_attr_present.sent.fvVmAttr.attributes.name == 'anstest' - - vm_custom_attr_present.sent.fvVmAttr.attributes.labelName == 'ENVIRONMENT' - - vm_custom_attr_present.sent.fvVmAttr.attributes.value == 'PROD' - - vm_custom_attr_present.sent.fvVmAttr.attributes.type == 'custom-label' - - vm_custom_attr_present.sent.fvVmAttr.attributes.operator == 'equals' - - vm_custom_attr_present.current.0.fvVmAttr.attributes.annotation == 'orchestrator:ansible' - - vm_custom_attr_present_idempotent is not changed - - vm_custom_attr_present_idempotent.sent == {} - - vm_custom_attr_update is changed - - vm_custom_attr_update.sent.fvVmAttr.attributes.operator == 'contains' - - vm_custom_attr_update.sent.fvVmAttr.attributes.labelName == 'OS' - - vm_custom_attr_update.sent.fvVmAttr.attributes.value == 'REDHAT' - - vm_custom_attr_present_missing_params is failed - - 'vm_custom_attr_present_missing_params.msg == "state is present but all of the following are missing: epg"' - - - name: Query a useg attribute of type vm_custom_attr - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_present - state: query - register: vm_custom_attr_query - - - name: Query all useg attribute of type vm_custom_attr - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_present - useg_attribute_name: "{{ fake_var | default(omit) }}" - state: query - register: vm_custom_attr_query_all - - - name: vm_custom_attr query assertions - assert: - that: - - vm_custom_attr_query is not changed - - vm_custom_attr_query.current | length == 1 - - vm_custom_attr_query_all is not changed - - vm_custom_attr_query_all.current.0.fvCrtrn.children | length > 1 - - - name: Delete a useg attribute of type vm_custom_attr ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_vm_custom_attr_absent - <<: *aci_vm_custom_attr_present - state: absent - check_mode: true - register: vm_custom_attr_absent_check_mode - - - name: Delete a useg attribute of type vm_custom_attr - delete works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_absent - register: vm_custom_attr_absent - - - name: Delete a useg attribute of type vm_custom_attr - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_absent - register: vm_custom_attr_absent_idempotent - - - name: Delete a useg attribute of type vm_custom_attr - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_custom_attr_absent - epg: "{{ fake_var | default(omit) }}" - state: absent - ignore_errors: true - register: vm_custom_attr_absent_missing_params - - - name: vm_custom_attr absent assertions - assert: - that: - - vm_custom_attr_absent_check_mode is changed - - vm_custom_attr_absent_check_mode.previous != [] - - vm_custom_attr_absent is changed - - vm_custom_attr_absent.previous == vm_custom_attr_absent_check_mode.previous - - vm_custom_attr_absent_idempotent is not changed - - vm_custom_attr_absent_idempotent.previous == [] - - vm_custom_attr_absent_missing_params is failed - - 'vm_custom_attr_absent_missing_params.msg == "state is absent but all of the following are missing: epg"' - - - name: remove tenant - cleanup - cisco.aci.aci_tenant: - <<: *aci_tenant_present - state: absent - when: tenant_present is changed diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_name.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_name.yml deleted file mode 100644 index c73916da0..000000000 --- a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_name.yml +++ /dev/null @@ -1,198 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) - -# 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 - -# CLEAN ENVIRONMENT -- 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: Query system information - aci_system: - <<: *aci_info - id: 1 - state: query - register: version - -- name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - -- name: Execute tasks only for non-cloud sites - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_test_useg - state: present - register: tenant_present - - - name: ensure ap exists for tests to kick off - cisco.aci.aci_ap: &aci_ap_present - <<: *aci_tenant_present - ap: anstest - register: ap_present - - - name: ensure bd exists for tests to kick off - cisco.aci.aci_bd: &aci_bd_present - <<: *aci_tenant_present - bd: anstest - register: bd_present - - - name: ensure useg epg exists for tests to kick off - cisco.aci.aci_epg: &aci_epg_present - <<: *aci_ap_present - epg: anstest - bd: anstest - useg: yes - register: epg_present - - - name: ensure useg attribute of type vm_name not exists for tests to kick off - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: vm_name - state: absent - - - name: Add a useg attribute of type vm_name ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_vm_name_present - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: vm_name - operator: equals - value: ANSVM01 - check_mode: true - register: vm_name_present_check_mode - - - name: Add a useg attribute of type vm_name - creation works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_present - register: vm_name_present - - - name: Add a 2nd useg attribute of type vm_name - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest2 - useg_attribute_type: vm_name - operator: equals - value: ANSVM03 - register: vm_name_present_2 - - - name: Add a useg attribute of type vm_name - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_present - register: vm_name_present_idempotent - - - name: Update a useg attribute of type vm_name - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_present - operator: contains - value: ANSVM02 - - register: vm_name_update - - - name: Add a useg attribute of type vm_name - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_present - epg: "{{ fake_var | default(omit) }}" - ignore_errors: true - register: vm_name_present_missing_params - - - name: vm_name present assertions - assert: - that: - - vm_name_present_check_mode is changed - - vm_name_present is changed - - vm_name_present.previous == [] - - vm_name_present.sent.fvVmAttr.attributes.name == 'anstest' - - vm_name_present.sent.fvVmAttr.attributes.value == 'ANSVM01' - - vm_name_present.sent.fvVmAttr.attributes.type == 'vm-name' - - vm_name_present.sent.fvVmAttr.attributes.operator == 'equals' - - vm_name_present.current.0.fvVmAttr.attributes.annotation == 'orchestrator:ansible' - - vm_name_present_idempotent is not changed - - vm_name_present_idempotent.sent == {} - - vm_name_update is changed - - vm_name_update.sent.fvVmAttr.attributes.operator == 'contains' - - vm_name_update.sent.fvVmAttr.attributes.value == 'ANSVM02' - - vm_name_present_missing_params is failed - - 'vm_name_present_missing_params.msg == "state is present but all of the following are missing: epg"' - - - name: Query a useg attribute of type vm_name - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_present - state: query - register: vm_name_query - - - name: Query all useg attribute of type vm_name - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_present - useg_attribute_name: "{{ fake_var | default(omit) }}" - state: query - register: vm_name_query_all - - - name: vm_name query assertions - assert: - that: - - vm_name_query is not changed - - vm_name_query.current | length == 1 - - vm_name_query_all is not changed - - vm_name_query_all.current.0.fvCrtrn.children | length > 1 - - - name: Delete a useg attribute of type vm_name ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_vm_name_absent - <<: *aci_vm_name_present - state: absent - check_mode: true - register: vm_name_absent_check_mode - - - name: Delete a useg attribute of type vm_name - delete works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_absent - register: vm_name_absent - - - name: Delete a useg attribute of type vm_name - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_absent - register: vm_name_absent_idempotent - - - name: Delete a useg attribute of type vm_name - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_name_absent - epg: "{{ fake_var | default(omit) }}" - state: absent - ignore_errors: true - register: vm_name_absent_missing_params - - - name: vm_name absent assertions - assert: - that: - - vm_name_absent_check_mode is changed - - vm_name_absent_check_mode.previous != [] - - vm_name_absent is changed - - vm_name_absent.previous == vm_name_absent_check_mode.previous - - vm_name_absent_idempotent is not changed - - vm_name_absent_idempotent.previous == [] - - vm_name_absent_missing_params is failed - - 'vm_name_absent_missing_params.msg == "state is absent but all of the following are missing: epg"' - - - name: remove tenant - cleanup - cisco.aci.aci_tenant: - <<: *aci_tenant_present - state: absent - when: tenant_present is changed diff --git a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_tag.yml b/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_tag.yml deleted file mode 100644 index c9b958376..000000000 --- a/tests/integration/targets/aci_epg_useg_attribute_simple_statement/tasks/vm_tag.yml +++ /dev/null @@ -1,202 +0,0 @@ -# Test code for the ACI modules -# Copyright: (c) 2023, Christian Kolrep (@Christian-Kolrep) - -# 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 - -# CLEAN ENVIRONMENT -- 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: Query system information - aci_system: - <<: *aci_info - id: 1 - state: query - register: version - -- name: Verify Cloud and Non-Cloud Sites in use. - include_tasks: ../../../../../../integration/targets/aci_cloud_provider/tasks/main.yml - -- name: Execute tasks only for non-cloud sites - when: query_cloud.current == [] # This condition will execute only non-cloud sites - block: # block specifies execution of tasks within, based on conditions - - name: ensure tenant exists for tests to kick off - cisco.aci.aci_tenant: &aci_tenant_present - <<: *aci_info - tenant: ansible_test_useg - state: present - register: tenant_present - - - name: ensure ap exists for tests to kick off - cisco.aci.aci_ap: &aci_ap_present - <<: *aci_tenant_present - ap: anstest - register: ap_present - - - name: ensure bd exists for tests to kick off - cisco.aci.aci_bd: &aci_bd_present - <<: *aci_tenant_present - bd: anstest - register: bd_present - - - name: ensure useg epg exists for tests to kick off - cisco.aci.aci_epg: &aci_epg_present - <<: *aci_ap_present - epg: anstest - bd: anstest - useg: yes - register: epg_present - - - name: ensure useg attribute of type vm_tag not exists for tests to kick off - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: vm_tag - state: absent - - - name: Add a useg attribute of type vm_tag ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_vm_tag_present - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest - useg_attribute_type: vm_tag - operator: equals - category: ENVIRONMENT - value: PROD - check_mode: true - register: vm_tag_present_check_mode - - - name: Add a useg attribute of type vm_tag - creation works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_present - register: vm_tag_present - - - name: Add a 2nd useg attribute of type vm_tag - cisco.aci.aci_epg_useg_attribute: - <<: *aci_ap_present - epg: anstest - useg_attribute_name: anstest2 - useg_attribute_type: vm_tag - operator: equals - category: TIER - value: GOLD - register: vm_tag_present_2 - - - name: Add a useg attribute of type vm_tag - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_present - register: vm_tag_present_idempotent - - - name: Update a useg attribute of type vm_tag - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_present - operator: contains - category: OS - value: REDHAT - register: vm_tag_update - - - name: Add a useg attribute of type vm_tag - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_present - epg: "{{ fake_var | default(omit) }}" - ignore_errors: true - register: vm_tag_present_missing_params - - - name: vm_tag present assertions - assert: - that: - - vm_tag_present_check_mode is changed - - vm_tag_present is changed - - vm_tag_present.previous == [] - - vm_tag_present.sent.fvVmAttr.attributes.name == 'anstest' - - vm_tag_present.sent.fvVmAttr.attributes.category == 'ENVIRONMENT' - - vm_tag_present.sent.fvVmAttr.attributes.value == 'PROD' - - vm_tag_present.sent.fvVmAttr.attributes.type == 'tag' - - vm_tag_present.sent.fvVmAttr.attributes.operator == 'equals' - - vm_tag_present.current.0.fvVmAttr.attributes.annotation == 'orchestrator:ansible' - - vm_tag_present_idempotent is not changed - - vm_tag_present_idempotent.sent == {} - - vm_tag_update is changed - - vm_tag_update.sent.fvVmAttr.attributes.operator == 'contains' - - vm_tag_update.sent.fvVmAttr.attributes.category == 'OS' - - vm_tag_update.sent.fvVmAttr.attributes.value == 'REDHAT' - - vm_tag_present_missing_params is failed - - 'vm_tag_present_missing_params.msg == "state is present but all of the following are missing: epg"' - - - name: Query a useg attribute of type vm_tag - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_present - state: query - register: vm_tag_query - - - name: Query all useg attribute of type vm_tag - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_present - useg_attribute_name: "{{ fake_var | default(omit) }}" - state: query - register: vm_tag_query_all - - - name: vm_tag query assertions - assert: - that: - - vm_tag_query is not changed - - vm_tag_query.current | length == 1 - - vm_tag_query_all is not changed - - vm_tag_query_all.current.0.fvCrtrn.children | length > 1 - - - name: Delete a useg attribute of type vm_tag ( check mode ) - cisco.aci.aci_epg_useg_attribute: &aci_vm_tag_absent - <<: *aci_vm_tag_present - state: absent - check_mode: true - register: vm_tag_absent_check_mode - - - name: Delete a useg attribute of type vm_tag - delete works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_absent - register: vm_tag_absent - - - name: Delete a useg attribute of type vm_tag - idempotency works - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_absent - register: vm_tag_absent_idempotent - - - name: Delete a useg attribute of type vm_tag - missing params - cisco.aci.aci_epg_useg_attribute: - <<: *aci_vm_tag_absent - epg: "{{ fake_var | default(omit) }}" - state: absent - ignore_errors: true - register: vm_tag_absent_missing_params - - - name: vm_tag absent assertions - assert: - that: - - vm_tag_absent_check_mode is changed - - vm_tag_absent_check_mode.previous != [] - - vm_tag_absent is changed - - vm_tag_absent.previous == vm_tag_absent_check_mode.previous - - vm_tag_absent_idempotent is not changed - - vm_tag_absent_idempotent.previous == [] - - vm_tag_absent_missing_params is failed - - 'vm_tag_absent_missing_params.msg == "state is absent but all of the following are missing: epg"' - - - name: remove tenant - cleanup - cisco.aci.aci_tenant: - <<: *aci_tenant_present - state: absent - when: tenant_present is changed